fix: align sync and async read contracts - #120
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed August 3, 2026, 4:30 AM ET / 08:30 UTC. ClawSweeper reviewWhat this changesThis PR adds the public Merge readiness⛔ Blocked until real behavior proof is added - 4 items remain This PR remains necessary: current main still exposes the reported sync/async read-contract divergences, and the proposed patch appears to preserve the package’s guarded-read boundary while normalizing public error outcomes. No discrete correctness defect was found in the reviewed patch, but merge should wait for inspectable after-fix runtime proof rather than the PR body’s unlinked claims alone. Priority: P2 Review scores
Verification
How this fits togetherfs-safe turns guarded filesystem reads for secrets, rooted stores, and temporary workspaces into bytes or typed public errors. Path traversal, link/type, pinned-descriptor, and identity checks run before the read outcome is normalized for callers. flowchart LR
Caller[Application caller] --> APIs[Secret, store, and workspace reads]
APIs --> Guard[Path, type, link, and identity guards]
Guard --> Pinned[Pinned file open]
Pinned --> Normalize[Normalize filesystem failures]
Normalize --> Result[Bytes or typed public error]
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Merge the documented parity migration after a redacted real-runtime transcript demonstrates both sync and async public outcomes, including Windows non-directory ancestry and a post-validation read failure retaining Do we have a high-confidence way to reproduce the issue? Yes, at source level. Current main visibly maps the relevant sync and async failures differently in FileStore, temporary-workspace, secret-file, and symlink-parent paths; the PR adds focused parity regressions, though this read-only review did not execute them. Is this the best way to solve the issue? Yes. Reusing existing guarded-open and typed AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 5f528c322461. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
Summary
read-failedcode and preserve underlying filesystem failures incausenot-filefrom bothassertNoSymlinkParents()variants on every platformThe sync/async audit in #118 found four public error-code divergences. This resolves them without weakening confinement or identity checks: genuine I/O failures are no longer labeled as invalid input or path substitution, stable directories are
not-file, andallowMissingsuppresses only a truly absent suffix.Windows reports raw
ENOENTforfile\\child, while POSIX reportsENOTDIR. The guard now detects that the existing non-finalfilecomponent is not a directory before probing its child, so both async and sync APIs return the semanticnot-filecode on every OS.The follow-up drift pass also found that stable hardlinks and symlinks were collapsed by synchronous FileStore/temp reads, missing temp leaves surfaced raw
ENOENT, and I/O errors varied by twin. The same typed validation path now preserveshardlink,symlink, andnot-found, while actual ambiguity remainspath-mismatch.Compatibility
Consumers matching synchronous secret
invalid-path, asynchronous secret or synchronous storepath-mismatch, or top-level Node I/O codes for read failures should matchread-failedand inspectcause.code. Consumers treating synchronous directory/link errors as missing or identity drift should matchnot-file,hardlink, orsymlinkas appropriate. Callers that relied on a non-directory ancestor being accepted underallowMissingshould handlenot-fileinstead.Verification
cbx_c7ef28949e23, runrun_a442f6cf53a1: raw async/syncENOENT, public async/syncnot-file; parity suite 7 passed, 2 POSIX skipspnpm check: 1,013 passed, 59 platform skipspnpm test:security: 70 passedgit diff --checkgpt-5.6-sol, high): clean, no accepted/actionable findings