88efe4fea4962944dd399d0777e8c28c47a90dd6
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9d3e2d2bfe |
Fix documentation defects found by an adversarial review
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. |
||
|
|
ae9c32e271 |
Align the cap emulation on NextGraph's model, and confine it to a virtual user
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. |
||
|
|
0d52c82ba9 |
docs: passer vision, readcap-and-nuri-model et l'incident en anglais
Le reste du dossier docs/ était déjà en anglais ; ces trois fichiers avaient été rédigés en français par erreur. Traduction fidèle, sans changement de fond : mêmes sections, mêmes tableaux, mêmes blocs de code. Le retour à la ligne dur à 78 colonnes est levé (une ligne par paragraphe, convention du projet). Marqueurs épistémiques préservés et rendus aussi visibles : VERIFIED / INFERRED / CORRECTED / DIRECTION / GAP. Les citations verbatim de commentaires amont restent intactes. Deux incohérences de FOND signalées par la traduction et corrigées ici — elles étaient invisibles tant qu'on lisait chaque section isolément : - readcap-and-nuri-model, section « Caveats / gaps » : elle listait encore le fetch keyless comme hypothèse INFÉRÉE à confirmer, alors que le bloc CORRIGÉ du §4bis la déclare fausse et non constructible. Contradiction interne née de ma correction partielle. Conservée barrée plutôt que supprimée : l'hypothèse est intuitive et se reformera sinon. - incident write-loss : l'intro affirmait en fait établi que « l'écriture n'atteint jamais durablement le broker », alors que la réserve épistémique plus bas dit explicitement que l'alternative (perte d'écriture vs réhydratation à froid) n'est pas tranchée. L'intro ne rapporte plus que le symptôme observé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
b2cb774124 |
docs: état courant NextGraph enrichi + modèle cible aligné + retrait du lot PW
MODÈLE CIBLE (readcap-and-nuri-model) — trois ajouts, deux corrections :
- Store public : lisible par l'URL, et NON récursif — un contenu public peut
référencer du contenu privé sans y donner accès. C'est la non-récursivité qui
porte la valeur (objet public pointant vers de l'identité privée).
- Le trousseau : la branche de store, où chaque création commite AddRepo{read_cap}
— avec l'avertissement explicite que ce n'est PAS le mécanisme de partage.
Confondre l'index privé et le geste de partage mène à « on partage le store »,
ce qui livrerait tout son contenu présent et futur.
- Rotation de clé : re-livraison par inbox, traitée automatiquement à la
connexion. Écrit comme DIRECTION, en signalant que le commentaire amont dont ça
partait décrit l'état courant.
- Levée de la confusion did/NURI en tête de la section grammaire : `did🆖` est
un préfixe de schéma présent partout, pas un marqueur de « sans cap ». C'est un
seul objet, avec ou sans la clé dedans.
- Livraison de cap par inbox signalée comme MANQUE (forme bonne, chemin absent).
ÉTAT COURANT (nextgraph-current-state) — 218 lignes ajoutées, structure intacte :
livraison de cap par inbox non implémentée ; vérification de signature d'auteur
jamais appelée au runtime (members map vide, //TODO) ; aucune sonde d'existence
au niveau SDK ; expose_outer codé en dur à false, absent du SDK ; protocole Ext
sans aucun contrôle. Plus trois constats d'exploitation : heal cold-start,
fork de compte sur provision concurrente, et l'abort du flush outbox sur
TopicNotFound. La mort du socket est seulement référencée (déjà couverte).
CORRECTION D'UN FAIT QUE J'AVAIS ÉNONCÉ FAUX : le digest d'auteur n'est PAS clé
sous le secret de lecture — il est clé par l'overlay outer, public. C'est le
CONTENU du commit qui est chiffré. La conclusion « vérifier suppose de pouvoir
lire » tient, le mécanisme diffère.
Lot PW (WriteCap = membership) RETIRÉ de la liste des phases : il restait planifié
alors que le brief déclare plus haut qu'il n'y a pas de membership. Il était en
outre justifié par un besoin de dédup par signature que le consommateur n'a pas —
sa dédup s'appuie sur l'overlay.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg
|
||
|
|
60a9fd3ede |
docs: réécrire P1a après double revue adverse, corriger le verdict Q1 sur-lu
Deux adversaires à mandats disjoints (alignement NextGraph / économie
conceptuelle). Résultat : P1a fond de 8 notions nouvelles à 2, et un fait que
j'avais consigné comme VÉRIFIÉ était sur-lu.
CORRECTION DE FOND — le fetch keyless n'est PAS constructible. Le spike P0
concluait « Q1 OUI partiel, seul garde : l'overlay ». Il s'arrêtait au contrôle
d'accès sans regarder l'ADRESSAGE : aucune commande d'existence au niveau SDK ;
la seule sonde est interne au crate, exige des BlockId ET un repo chargé, et vise
l'overlay inner dérivé du secret de lecture. Une référence cap-less porte un
RepoId et l'overlay outer — ni BlockId, ni le bon overlay. L'adressage
présuppose le cap. Note corrigée sur place (pas empilée), avec la leçon
transposable : vérifier qu'une garde laisse passer ne prouve pas qu'une
opération est atteignable — encore faut-il pouvoir NOMMER ce qu'on demande.
P1a réécrite :
- UN seul type nouveau, `ReadCap`, le nom de l'amont. `Nuri` reste ce qu'il est
déjà (~90 usages) : la forme cap-less. Les types de marque disparaissent — le
SDK réel prend `nuri: String` et enforce au RUNTIME par la crypto ; une
garantie de compilation est un concept que NextGraph n'a pas, et un
consommateur qui typerait tout devrait dé-typer plus tard.
- `capFor(nuri) → ReadCap | undefined` : le trousseau. Comble un trou fatal du
premier jet — `doc_create` renvoie un NURI cap-less, donc l'invariant « on ne
va jamais d'une référence nue à un cap » empêchait le créateur d'obtenir le cap
de son propre document. Le trousseau existe déjà : la branche de store, où
chaque création commite AddRepo{read_cap}. En amont c'est le wallet.
- `shareCap(cap, toInbox)` : on partage UN DOCUMENT, à une ou plusieurs inboxes.
Pas le store — donner un cap de store livrerait tout son contenu présent et
futur. Les caps reçus arrivent comme dépôts d'inbox, consommés par le
inbox.watch existant (ce qui règle le point 7 de la revue adverse).
- Durabilité : ne PAS la promettre. Verbatim amont, les caps sont « not durable »
et qui ne reste pas abonné perd l'accès ; PermaCap est un TODO. La surface doit
exposer l'obligation d'abonnement, sinon le consommateur retient des caps morts.
- `PrincipalId` sort de la surface caps : n'existe pas en amont, et le brief le
supprimait de canRead en le qualifiant d'inversion ACL avant de le réintroduire
dans sealCapTo. On adresse des inboxes, comme inbox.post le fait déjà.
- Section 0 conservant les erreurs du premier jet : elles sont instructives.
- Exception publique actée : un lien de repo public n'a PAS de read_cap (il se
télécharge depuis l'outer overlay) — pour du public, « référence nue → contenu »
est bien la forme cible.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg
|
||
|
|
ead5aececf |
docs: l'overlay est store-scopé ; retrait de la fausse piste "membership"
readcap-and-nuri-model — nouvelle section sur l'OVERLAY, le concept qui manquait à la référence. C'est l'espace réseau d'un STORE : deux formes (outer = BLAKE3 public du store_id, calculable par tous ; inner = BLAKE3 keyed par le ReadCapSecret, réservé aux détenteurs de la clé). Le `✌️` d'un NURI de DOCUMENT porte l'overlay de son store — VÉRIFIÉ de bout en bout, avec une contre-preuve mécanique : dans Store, get/put/del/has passent tous `&self.overlay_id`, donc tous les documents d'un store partagent le namespace de blocs et un overlay par-document est structurellement impossible. Conséquence documentée, qui contraint tout modèle de présence anonyme : le `✌️` est un pseudonyme stable et permanent de la personne, présent dans toute référence cap-less vers n'importe lequel de ses documents protected. Le même bit d'information sert à dédupliquer sans lire ET à tracer — indissociables. vision — correction d'une forme fausse. Le document affirmait « écriture = membership/permissions », en miroir de « lecture = possession de clé ». Faux : il n'y a pas de notion d'appartenance dans le modèle, uniquement des clés et des URLs. Toute forme en member/role/permission est une MAUVAISE forme. brief caps — la section « périmètre élargi : WriteCap = membership » est retirée, conservée barrée comme garde-fou, avec la leçon de méthode qui vaut plus qu'elle : lire l'état courant de nextgraph-rs pour en DÉDUIRE la forme cible est une erreur — le source contient de l'échafaudage inerte (AddMember, PermissionV0, verify_sig jamais appelé hors tests). Le source sert à vérifier un mécanisme, jamais à inférer une intention. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
1791c31f42 |
docs: vision du polyfill (shape-fidelity), modèle ReadCap/NURI réel, brief caps
vision.md — la charte : le polyfill n'est PAS une couche de sécurité (wallet
partagé + pas de crypto = insécurité ACCEPTÉE) ; seul objectif = exposer la
BONNE FORME des primitives futures pour que les consommateurs n'aient rien à
réécrire. Invariant tenu par une simulation crypto légère : un `did` nu (sans
ReadCap) ne permet PAS de lire ; un NURI avec ReadCap est suffisant et requis.
readcap-and-nuri-model.md — le vrai modèle, VÉRIFIÉ par lecture de
`nextgraph-rs` : ReadCap = ObjectRef {id BLAKE3, clé ChaCha20} = possession de
clé, PAS une ACL ; grant = sceller la clé à l'inbox du destinataire ;
révocation = re-key grossier et non-rétroactif ; grammaire NURI cap-less vs
cap-porteur (le segment `:k:` est le discriminant) ; table des divergences avec
l'émulation `caps.ts` (aujourd'hui une ACL — l'inversion exacte).
briefs/2026-07-20-caps-emulation-alignment.md — le chantier d'alignement :
spike P0 keyless-resolve (verdicts vérifiés : existence sans clé OUI,
détection de suppression sans clé NON, confidentialité OUI), puis P1 cap-less
vs cap-porteur, P2 possession, P3 re-key, P4 migration d'API. Inclut la revue
adverse (WriteCap = membership et non possession ; sans crypto la privacy de
lecture n'est pas applicable ; migration = re-architecture consommateur).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg
|