fix: generated and promoted writes go through the brain root (#188, #158)
CI / Lint / Test / Vet (pull_request) Successful in 1m17s
CI / Mirror to GitHub (pull_request) Skipped

Writers that created or rewrote brain files by path followed symlinks:
- promote/reject: os.MkdirAll + os.WriteFile of the destination, then
  os.Remove of the raw source. Now PutRegular + brainfs.Remove; the source
  is kept when the write is refused.
- StampProvenanceFile (brain_edit's re-stamp): provenance.ApplyFile read
  and rewrote by path. Now ReadRegular + WriteRegular; ApplyFile, now
  unused, is removed.
- BuildWingIndex (_index.md) and wiki.RebuildIndex (wiki/index.md): now
  PutRegular.
- wiki.AppendLog (log.md) and AutoTunnel's fuzzy-candidate log
  (raw/tunnel-candidates-*.md): now AppendRegular; tunnel's fileExists,
  now unused, is removed.
- New brainfs.Remove: clean path, real parent, removes a final symlink
  itself, never its target.

brain_edit's own atomic rename was already refused behind a symlinked
directory by #187's read check; a guard test pins it.

Pipeline writes, BackfillRefs, the watcher's raw/ markers and the session
archive in cmd/server follow in a separate PR (#158).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 22:39:41 +02:00
co-authored by Claude Opus 5.5
parent 41b7105b31
commit 138d6e2545
12 changed files with 273 additions and 74 deletions
@@ -28,7 +28,6 @@ import (
"context"
"errors"
"fmt"
"os"
"regexp"
"strings"
@@ -102,24 +101,6 @@ func Apply(content string, s Stamp) (string, error) {
return out, nil
}
// ApplyFile applies the stamp to the note at absPath in place.
func ApplyFile(absPath string, s Stamp) error {
b, err := os.ReadFile(absPath)
if err != nil {
return fmt.Errorf("read for provenance: %w", err)
}
out, err := Apply(string(b), s)
if err != nil {
return err
}
if out == string(b) {
return nil
}
if err := os.WriteFile(absPath, []byte(out), 0o644); err != nil {
return fmt.Errorf("write provenance: %w", err)
}
return nil
}
// plainGroups keeps the provably plain key groups of a frontmatter block.
func plainGroups(block string) string {