fix(api,watcher,server): reject moves non-markdown untouched; read caps; BOM; strict routing flag (review of #211, pass 2)
- brain_reject on a parked pdf/txt moves the bytes; it no longer prepends YAML - raw/ notes are read through a cap (readCapped); an endless reader test fails instead of exhausting memory - a byte-order mark no longer hides a note's wing: key - INGEST_WING_ROUTING is parsed strictly; a typo stops the server rather than leaving routing silently off - tests for the reserved-wing check in every disguise (Sources, sources., ...) Mutation-checked. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,10 @@ func OpenRawRoot(brainDir string) (*os.Root, string, error) {
|
||||
return r, p, nil
|
||||
}
|
||||
|
||||
// maxRawNoteBytes bounds what promote, reject and the pending listing read from
|
||||
// one raw/ entry. A variable so a test can lower it.
|
||||
var maxRawNoteBytes int64 = 64 << 20
|
||||
|
||||
// readRawNote reads one raw/ entry by basename through the root, refusing
|
||||
// anything that is not a regular file.
|
||||
//
|
||||
@@ -59,9 +63,22 @@ func readRawNote(r *os.Root, base string) ([]byte, os.FileInfo, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
b, err := io.ReadAll(f)
|
||||
b, err := readCapped(f, maxRawNoteBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, fmt.Errorf("%s: %w", base, err)
|
||||
}
|
||||
return b, fi, nil
|
||||
}
|
||||
|
||||
// readCapped reads r but never more than max+1 bytes, so an oversize or growing
|
||||
// file costs at most that much memory.
|
||||
func readCapped(r io.Reader, max int64) ([]byte, error) {
|
||||
b, err := io.ReadAll(io.LimitReader(r, max+1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if int64(len(b)) > max {
|
||||
return nil, fmt.Errorf("note exceeds %d bytes", max)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user