Fifteen findings, all verified before acting. The ones that mattered:
- Corrections added without updating what they corrected. §5's table still
said a cap-less NURI is one "without :k:", two hundred lines after §4
established the discriminant is `r:`. Same shape of defect in the P1a
report, which kept the sentence "it is the owner's keyring, upstream the
keyring is the wallet" — the exact sentence §4quater declares wrong, and the
one that produced a global in-memory keyring.
- A wrong source citation: RootCapRefresh/BranchCapRefresh live in
verifier/src/commits/mod.rs, not repo/src/commit.rs, and are no-op stubs.
- Documentation describing deleted code: isolation.ts, discovery.readIndex,
the global index, and an acceptance test that was dropped with discovery.
- The P1a implementation report had aged into being wrong in four places
(caps not persisted, inbox processing not started, plain string types, the
:k: segment). It is dated, so it now carries a header saying what later lots
overtook, rather than being rewritten.
- vision.md stated "a document's data is stored encrypted" in the present
tense. That is the target; here the cap value is the constant OK and nothing
is encrypted. Said plainly now.
- Prose left mangled by an earlier mechanical find-and-replace, in four places
I had claimed were repaired.
Also: reach.ts and connect.ts had no home in the permanent docs — the boundary
and the connection sequence are now described in simulation.md, not only in a
brief.
Two batches, verified against nextgraph-rs throughout.
P1a — the capability surface. Reading was an ACL (Map<doc, Set<principal>>),
the exact inversion of key possession. It is now possession: `capFor(nuri)` is
the only question, there is no principal parameter anywhere, and nothing turns
a bare reference into a cap. Sharing is `shareCap(cap, toInbox)`, a Link
deposit; receiving needs no operation. `Nuri` and `ReadCap` are template
literal types, so passing a bare reference where a cap belongs is a compile
error, with runtime guards behind it for JavaScript callers.
The virtual user boundary. Every access function is now confined to the
connected user, through two rules on one criterion (possession), implemented in
two places so a lapse in either is caught by the other: authorization at the
passage points, and "do not even attempt" at the callers. The polyfill's own
machinery moved to physical.ts — unguarded, never exported — which replaced an
exemption list: the machinery no longer gets waved through the guard, it calls
something the guard never saw.
Removed, as emulating capabilities the target does not have:
- discovery.ts and its global index. There is no discovery in NextGraph; you
follow links. It also pooled user data across wallets.
- the cross-account fan-out (listEntityDocs, resolveReadGraphs, allAccounts,
loadShim), which was cross-user enumeration by construction.
- resolveInboxAnchor, a single inbox common to every user.
Caps are now stored where NextGraph stores them, and read back rather than
recomputed: AddRepo on the store's Store branch for documents a user creates,
AddLink on its User branch for caps received. Inboxes belong to someone — the
user's own, plus one per document — and connecting a user drains them all;
that is the library's job, not the app's.
Corrections worth recording: a ReadCap is `r:`, not `:k:` (reported by
NextGraph's developer, verified in BlockRef::readcap_nuri); received caps DO
have a register (AddLink), contrary to what this repo's notes claimed; and
"wallet" upstream means keyring — what owns three stores is a user, so the
vocabulary follows.
The cap value is the constant OK: the only question the emulation answers is
whether a cap is held. P1b replaces that one constant with a real key.
After this the shape is right and the isolation is still fake. Nothing here may
be described as anonymous or private.