feat(brain): audit-log every tools/call; server-owned write provenance (#147)
Closes #144 (audit line per tools/call) and #145 (origin/written_by stamped on every model-reachable write, surfaced in brain_query/brain_get). Passed pr-gatekeeper after four rounds of adversarial review, verified by execution: #147 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Mathias <mthbqv@gmail.com>
This commit was merged in pull request #147.
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/graphsync"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/notes"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/pipeline"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/provenance"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/search"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/session"
|
||||
)
|
||||
@@ -255,11 +256,14 @@ func (s *Server) brainWrite(ctx context.Context, args json.RawMessage) (json.Raw
|
||||
// one implementation (capture uses the same store). The read-after-write
|
||||
// handle {id, path, content_hash} comes back from the store; path is kept
|
||||
// for backward compatibility.
|
||||
origin, writtenBy := provenanceFrom(ctx)
|
||||
ref, err := s.store.Write(ctx, capture.Note{
|
||||
Content: a.Content,
|
||||
Filename: a.Filename,
|
||||
Wing: a.Wing,
|
||||
Hall: a.Hall,
|
||||
Content: a.Content,
|
||||
Filename: a.Filename,
|
||||
Wing: a.Wing,
|
||||
Hall: a.Hall,
|
||||
Origin: origin,
|
||||
WrittenBy: writtenBy,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -304,11 +308,14 @@ func (s *Server) brainUpdate(ctx context.Context, args json.RawMessage) (json.Ra
|
||||
if a.Path != "" {
|
||||
slug = a.Path
|
||||
}
|
||||
origin, writtenBy := provenanceFrom(ctx)
|
||||
ref, err := s.store.Update(ctx, slug, capture.Note{
|
||||
Content: a.Content,
|
||||
Wing: a.Wing,
|
||||
Hall: a.Hall,
|
||||
Reason: a.Reason,
|
||||
Content: a.Content,
|
||||
Wing: a.Wing,
|
||||
Hall: a.Hall,
|
||||
Reason: a.Reason,
|
||||
Origin: origin,
|
||||
WrittenBy: writtenBy,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -387,8 +394,10 @@ func (s *Server) brainPromote(ctx context.Context, args json.RawMessage) (json.R
|
||||
if err := json.Unmarshal(args, &a); err != nil {
|
||||
return nil, fmt.Errorf("parse args: %w", err)
|
||||
}
|
||||
origin, writtenBy := provenanceFrom(ctx)
|
||||
relPath, err := api.PromoteNote(s.brainDir, api.PromoteOptions{
|
||||
Filename: a.Filename, Wing: a.Wing, Hall: a.Hall, Slug: a.Slug,
|
||||
Origin: origin, WrittenBy: writtenBy,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -491,7 +500,7 @@ func (s *Server) brainIngestRaw(ctx context.Context, args json.RawMessage) (json
|
||||
if len(a.Pages) == 0 {
|
||||
return nil, fmt.Errorf("pages must be non-empty")
|
||||
}
|
||||
result, err := pipeline.RunRaw(s.brainDir, a.Source, a.Pages, a.DryRun)
|
||||
result, err := pipeline.RunRaw(withCallerStamp(ctx), s.brainDir, a.Source, a.Pages, a.DryRun)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ingest: %w", err)
|
||||
}
|
||||
@@ -590,7 +599,7 @@ func (s *Server) sessionLog(ctx context.Context, args json.RawMessage) (json.Raw
|
||||
}
|
||||
|
||||
func (s *Server) runIngest(ctx context.Context, content, source string, dryRun bool) (json.RawMessage, error) {
|
||||
result, err := pipeline.Run(ctx, s.pipeline, s.brainDir, content, source, dryRun)
|
||||
result, err := pipeline.Run(withCallerStamp(ctx), s.pipeline, s.brainDir, content, source, dryRun)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ingest: %w", err)
|
||||
}
|
||||
@@ -609,3 +618,10 @@ func (s *Server) runIngest(ctx context.Context, content, source string, dryRun b
|
||||
}
|
||||
return json.Marshal(map[string]any{"pages": pages, "warnings": warnings})
|
||||
}
|
||||
|
||||
// withCallerStamp attaches the caller's provenance for the ingest pipeline,
|
||||
// which stamps every page it writes or merges into (hyperguild#145).
|
||||
func withCallerStamp(ctx context.Context) context.Context {
|
||||
origin, writtenBy := provenanceFrom(ctx)
|
||||
return provenance.WithStamp(ctx, provenance.Stamp{Origin: origin, WrittenBy: writtenBy})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user