Review round 1 on PR #165:
- ReadRegularMax checked the size on the opened handle, then read with an
unbounded io.ReadAll, so a file growing after the check returned past the
limit. The read now goes through io.LimitReader(max+1). A test seam grows
the file between the check and the read and counts bytes consumed.
- New: ReadScoped returns ErrTooLarge for a note over maxNoteBytes; red if
readContained drops the limit.
- notes.Target carries the brain root instead of deriving it by TrimSuffix.
- Rule 9: reader tests renamed to <Reader>RefusesSymlinksAndSurvivesSwapRaces;
ReadNote test has a positive control; brainfstest comment states what the
harness observes and what it does not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brain_read returns a note verbatim; brain_edit is str_replace with an
exactly-once match, operating on the tree brain-sync commits from.
An adversarial design review before implementation changed three things:
1. Governance files are not in the model-facing tool. Brain content is
ingested from the outside world and reaches a model's context, and that
model would hold the editor — one poisoned page could rewrite the
CLAUDE.md a .dispatch-allow agent later loads as instructions. And
brain-sync merges with --strategy-option=ours, so the live tree beats a
human's corrective push on the conflicting lines. CLAUDE.md now goes
through brain_edit_root: de-surfaced from tools/list and gated on the
local static principal. The scopes are disjoint — the privileged door
has the smaller reach.
2. Reads needed the same allowlist, and brain_get already lacked it: it
returned verbatim session transcripts under archive/ by path. A test
proved the exposure live before the fix.
3. Canonicalise before allowlisting — knowledge/../.git/hooks/post-commit
would otherwise reach a hook that brain-sync executes in a pod holding
the Gitea push credentials.
Plus overlapping match counting, UTF-8 validation both ways, refusal while
git is mid-operation, flock with the read inside the lock, atomic
same-dir rename, and reindex only when frontmatter is touched.
Refs brain#4.
Co-authored-by: Mathias <mthbqv@gmail.com>