Expand description
Tracked, confined filesystem reads.
The only way a rule reaches a file other than the one it is checking. Two properties have to hold together, and neither is optional:
Confinement. A read resolves inside the project root or it fails. Traversal is
rejected lexically before the filesystem is touched, so ../../../etc/passwd produces a
message about escaping the root rather than a confusing “not found” — and the resolved
path is canonicalized and re-checked, so a symlink inside the root pointing outside it is
rejected too. A lexical check alone would see an innocent relative path and allow it.
Tracking. Every read is recorded as (path, content_hash), including reads that
found nothing. That record is what a cache entry needs to know when it has gone stale;
see crate::tracked.
§Reads are memoized within a run
Reading the same path twice returns the same bytes, even if something rewrote the file in between. A rule that saw a file change under it could report differently on two runs over identical input, which is the determinism invariant — and the cache would record one of the two hashes with no way to say which was used.
§Why this lives in lanekeep-core rather than in an engine crate
Every engine that runs a rule needs the same confinement and the same tracking — a read
lanekeep-wasm’s component runtime allows that lanekeep-js’s sandbox forbids, or
records differently, would make a cache entry mean something different depending on
which engine happened to produce it. Defining FileAccess once, below every engine
rather than inside one of them, is what keeps that question from being askable.
Structs§
- File
Access - Tracked, confined access to the project’s files.
Enums§
- Read
Error - Why a read was refused.
Functions§
- normalize
- Resolve
.and..lexically, without consulting the filesystem.