brain_edit_root was gated but unobserved: on success it emitted a slog.Warn and nothing else. That proves a rewrite was allowed, not that one happened — and brain-sync commits it within 15 minutes authored `brain-sync`, so git history cannot tell a CLAUDE.md rewrite apart from routine note traffic. A successful brain_edit_root now emits an ntfy notification and an AuditEntry through the same sink a capture already uses. notes.Result gains PrevContentHash so both ends of the change are identifiable. Path and hashes only in the notification body. Reserved at Internal, not Confidential, because Confidential makes DegradingSink refuse to record while loki is down rather than buffer. Observation is best-effort and never fails the call; a failure to observe logs at ERROR. Ordinary brain_edit on knowledge//wiki/ is deliberately not audited — git history already carries the same before/after bytes with a diff. Closes #97. Co-authored-by: Mathias <mthbqv@gmail.com>
This commit was merged in pull request #98.
This commit is contained in:
@@ -36,11 +36,15 @@ var pathLocks sync.Map // string -> *sync.Mutex
|
||||
|
||||
// Result is what a successful edit reports.
|
||||
type Result struct {
|
||||
Path string `json:"path"`
|
||||
ContentHash string `json:"content_hash"`
|
||||
BytesBefore int `json:"bytes_before"`
|
||||
BytesAfter int `json:"bytes_after"`
|
||||
ReindexError string `json:"reindex_error,omitempty"`
|
||||
Path string `json:"path"`
|
||||
// PrevContentHash is the sha256 of the file as it was before this edit.
|
||||
// Paired with ContentHash it identifies a rewrite in an audit trail or an
|
||||
// alert without carrying any of the bytes (hyperguild#97).
|
||||
PrevContentHash string `json:"prev_content_hash"`
|
||||
ContentHash string `json:"content_hash"`
|
||||
BytesBefore int `json:"bytes_before"`
|
||||
BytesAfter int `json:"bytes_after"`
|
||||
ReindexError string `json:"reindex_error,omitempty"`
|
||||
}
|
||||
|
||||
// Read returns a note's bytes verbatim.
|
||||
@@ -149,11 +153,13 @@ func Edit(brainDir, path, oldStr, newStr string, scope Scope) (Result, error) {
|
||||
}
|
||||
|
||||
sum := sha256.Sum256([]byte(after))
|
||||
prev := sha256.Sum256(before)
|
||||
return Result{
|
||||
Path: t.Rel,
|
||||
ContentHash: hex.EncodeToString(sum[:]),
|
||||
BytesBefore: len(before),
|
||||
BytesAfter: len(after),
|
||||
Path: t.Rel,
|
||||
PrevContentHash: hex.EncodeToString(prev[:]),
|
||||
ContentHash: hex.EncodeToString(sum[:]),
|
||||
BytesBefore: len(before),
|
||||
BytesAfter: len(after),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user