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
This commit is contained in:
@@ -45,6 +45,12 @@ sa clé privée.
|
||||
Le « ciblage wallet » vit donc dans **l'enveloppe de scellage**, pas dans le cap :
|
||||
le cap reste `{id, clé}`, possession-based.
|
||||
|
||||
> **État courant (2026-07-27) — le chemin est un MANQUE, pas un désaccord.** Le
|
||||
> champ `ContactDetails.read_cap` existe, mais la construction du message est
|
||||
> `unimplemented!()` (son unique appelant passe « sans read_cap ») et le récepteur
|
||||
> **jette** le cap qu'il recevrait. La *forme* est donc la bonne ; l'implémentation
|
||||
> n'est pas là. Le polyfill l'émule en attendant — fiche dans le bug-inbox.
|
||||
|
||||
## 3. Révocation = re-key (grossier, non-rétroactif)
|
||||
|
||||
On ne « reprend » pas une clé livrée. Révoquer = **re-chiffrer** avec une nouvelle
|
||||
@@ -60,8 +66,32 @@ clé et ne la re-sceller qu'aux autorisés restants.
|
||||
**antérieures** au refresh).
|
||||
- Livraison **durable** d'un cap = `PermaCap` — encore **TODO** (`repo/types.rs:578`).
|
||||
|
||||
### DIRECTION — la rotation ne fait PAS perdre l'accès (confirmé PO, 2026-07-27)
|
||||
|
||||
**Ne pas lire le commentaire ci-dessus comme l'intention.** « *if they don't
|
||||
subscribe, they lose access after the refresh* » décrit **l'état courant**, pas la
|
||||
cible. Ce que NextGraph vise :
|
||||
|
||||
> Quand une clé tourne, la nouvelle est **envoyée dans l'inbox** des utilisateurs
|
||||
> qui conservent le droit d'accès. Cette inbox est **traitée automatiquement** dès
|
||||
> qu'un client de l'utilisateur se connecte.
|
||||
|
||||
Donc l'accès n'est **pas perdu**, il est **différé** jusqu'à la prochaine connexion
|
||||
— cohérent avec le local-first. Conséquences de forme : **aucune obligation
|
||||
d'abonnement** à exposer au consommateur ; une re-livraison emprunte **le même
|
||||
canal** que la livraison initiale, donc le mécanisme de partage couvre les deux
|
||||
sans cas particulier. La **révocation** reste « cesser de re-livrer », non
|
||||
rétroactive.
|
||||
|
||||
## 4. Grammaire NURI : cap-less vs cap-porteur (le segment `:k:`)
|
||||
|
||||
**Lever la confusion d'abord** : `did:ng:` n'est **pas** un marqueur de « sans
|
||||
cap », c'est le **préfixe de schéma d'URI** — présent partout (inbox `did:ng:d:…`,
|
||||
branche `did:ng:b:…`, overlay `did:ng:v:…`, document `did:ng:o:…`). Un NURI **est**
|
||||
un `did:ng:…`. Il n'y a donc pas « le did » d'un côté et « le NURI » de l'autre :
|
||||
c'est **un seul objet**, avec ou sans la clé dedans — un seul type en amont,
|
||||
`NuriV0 { target, access }`, où un NURI cap-less a simplement `access` vide.
|
||||
|
||||
Le discriminant est le segment **`:k:{clé}`** : présent = cap-porteur ; **absent =
|
||||
cap-less** (nomme/localise **sans** donner le droit de lire). C'est de **première
|
||||
classe** dans le type : `NuriV0.target` (des ids) et `access`/`objects` (le cap)
|
||||
@@ -156,6 +186,45 @@ Leçon transposable : vérifier qu'une garde d'accès **laisse passer** ne prouv
|
||||
qu'une opération est atteignable — encore faut-il pouvoir **nommer** ce qu'on
|
||||
demande.
|
||||
|
||||
## 4ter. Le store public : lisible par l'URL, et NON récursif
|
||||
|
||||
Principe cible (confirmé PO, 2026-07-27) :
|
||||
|
||||
> **Un élément du store public est public : qui a l'URL lit le contenu.**
|
||||
> Mais **pas récursivement** — un contenu public peut *référencer* du contenu
|
||||
> privé, et la référence ne donne **pas** accès au référencé.
|
||||
|
||||
C'est un **second mécanisme**, à côté de la possession de clé (§1) — pas une
|
||||
entorse. Et c'est la **non-récursivité** qui porte la valeur : elle autorise un
|
||||
objet public qui **pointe** vers de l'identité privée, sans la divulguer. C'est
|
||||
exactement le motif dont un modèle de présence anonyme a besoin.
|
||||
|
||||
*Détail d'implémentation, à ne PAS faire porter par la forme* : NextGraph s'oriente
|
||||
vers un **non-chiffrement** du contenu du store public (les données restant
|
||||
**signées**). Une surface ne doit pas en dépendre. Et si le store public ne se
|
||||
comporte pas comme ce principe le décrit, c'est **le polyfill** qui s'adapte, pas
|
||||
le consommateur.
|
||||
|
||||
## 4quater. Le trousseau : d'où le propriétaire tire les caps de SES documents
|
||||
|
||||
À chaque création de document, un `AddRepo { read_cap }` est commité sur une
|
||||
**branche du store** — le store étant lui-même un repo, doté de branches **typées**
|
||||
(le mot « branche » n'a rien de git : c'est un compartiment à rôle défini). Cette
|
||||
branche liste **les documents du store, chacun avec sa clé de lecture**.
|
||||
|
||||
Elle **est** donc le **trousseau du propriétaire** : le mécanisme par lequel il
|
||||
retrouve les caps de ses propres documents. En amont, le trousseau, c'est le
|
||||
**wallet**.
|
||||
|
||||
**Ce n'est PAS le mécanisme de partage.** Confusion facile et coûteuse : en déduire
|
||||
« on partage au niveau du store » est faux — livrer un cap de store donnerait accès
|
||||
à **tout** son contenu, présent et futur. **L'unité de partage est le document**
|
||||
(§2). Le trousseau est un index privé, pas un geste de partage.
|
||||
|
||||
*(VÉRIFIÉ pour le mécanisme `AddRepo { read_cap }` ; le **nom exact** des branches
|
||||
et l'énumération de leurs types n'ont pas été re-tracés — à confirmer si ce point
|
||||
devient porteur.)*
|
||||
|
||||
## 5. Ce que le polyfill émule (caps.ts) — et où ça diverge
|
||||
|
||||
`packages/client/src/caps.ts` modélise `readers: Map<Nuri, Set<PrincipalId>>` +
|
||||
|
||||
Reference in New Issue
Block a user