feat(kernel-platforms): compile fs config into a narrowing - #1058
Draft
ci-belphegor wants to merge 1 commit into
Draft
feat(kernel-platforms): compile fs config into a narrowing#1058ci-belphegor wants to merge 1 commit into
ci-belphegor wants to merge 1 commit into
Conversation
The capability factory builds the full fs exo and narrows it by a delta compiled from the config, so `root` and the method set are enforced by the same `narrow` a holder would use. A holder narrowing further flattens onto that base instead of stacking a second mechanism on it. `makeRootCaveat` and the hand-rolled method selection are gone; `narrowInterfaceGuard` already drops methods absent from the delta. `assertPlainSegments` stays and is load-bearing: `pathUnder` matches segment by segment and cannot see inside one, so `['srv', 'x/../../etc']` satisfies the config's pattern and is caught only by the base's well-formedness check, which the narrowing inherits by forwarding. `readFile` now requires an encoding. Without one Node resolves a `Buffer`, and no typed array is Passable even frozen, so the result could never cross the exo boundary — a limit only real lockdown reveals. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ci-belphegor
force-pushed
the
grypez/narrowing-10-fs-config
branch
from
September 11, 2026 11:42
7f6cde9 to
a871971
Compare
ci-belphegor
added this pull request to stack #1060
September 11, 2026 11:44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
The payoff. Per-vat platform config already expressed narrowings in an ad-hoc vocabulary —
promises: { readFile: true }restricted the method set,rootDirrestricted the argument. Now it says the same things in the same vocabulary the library uses, and the capability factory applies the very samenarrowit exports:compiles to
{ readFile: [pathUnder(['srv', 'data'])] }. So the config-time bound is provably the root of the narrowing tree rather than a parallel mechanism.makeRootCaveatand the hand-rolled method selection are deleted — dropping methods absent from the delta is whatnarrowInterfaceGuardalready does. The compile step is a separate named function so that the general JSON delta encoding on the roadmap can replace it without rewriting the capability.Retires the last three ratchet cases; no
it.failsremains.Notes for reviewers
readFilenow takes a required encoding and returns a string, and this was forced rather than chosen. No typed array can cross an exo boundary:@endo/pass-stylerejectsBufferandUint8Arrayalike as mutable, andhardendoes not help. The result check runsmustMatch, which requires Passability first, soreturns(M.any())as shipped in 9b could never have worked — a read came backCannot pass mutable typed arrays like {"data":[...],"type":"Buffer"}. A required encoding makes the limitation a call-site error rather than a rejection on the way back; a silentutf8default would have hidden it. Raw-byte reads are recoverable viaharden(buffer.transferToImmutable()), which is Passable asbyteArray— on the roadmap, deferred becausetransferToImmutableis not guaranteed at the declaredengines: >=22.assertPlainSegmentscannot be dropped now that the root check is a pattern, and there is a test proving it end to end through the narrowed capability. A call passes the narrowed exo'spathUnderguard first and only then reaches the base, so['srv','data','x/../../etc']satisfies the prefix pattern — the prefix positions match — and is caught downstream. The pattern alone confines nothing; that layering is deliberate, and there is a comment recording it.An empty
rootis a config error, rejected and tested.pathUnder([])stays total at the library layer, so this is the config layer's job.kernel-platformscan no longer construct the capability under its own test setup:narrowforwards overE(), which bindsglobalThis.HandledPromiseat load, andmock-endoifysets that to plainPromise. Rather than gut the suite,makeFsBaseis split out — module-internal only, since a holder of it holds the whole filesystem — and stays fully unit-tested in-package (guards, forwarding,toPath, symlinks, traversal, separator rejection). Only the narrow composition moved to@ocap/kernel-test.nodejs.tsexportstoPath/makeNoSymlinksCaveatandbrowser.tsexportsbrowserFsOptionsso those tests build the real base rather than a lookalike copy.Not breaking — 9b and 9c already settled the config shape; this changes the enforcement mechanism.
Stack
PR 12 of 12. Base: #1057.