diff --git a/docs/briefs/2026-07-20-caps-emulation-alignment.md b/docs/briefs/2026-07-20-caps-emulation-alignment.md index 4ffe89c..47a465f 100644 --- a/docs/briefs/2026-07-20-caps-emulation-alignment.md +++ b/docs/briefs/2026-07-20-caps-emulation-alignment.md @@ -288,15 +288,29 @@ mais le chemin est `unimplemented!()` et le récepteur **jette** le cap reçu. L polyfill l'émule donc en attendant → fiche dans le bug-inbox, avec ce qu'il faudra en retirer le jour où l'amont l'implémente. -### 4. La durabilité — exposer l'obligation, pas la masquer +### 4. La rotation de clé — re-livraison automatique, pas perte d'accès -Un cap partagé est **rafraîchissable** : après un refresh, qui n'est pas resté -abonné **perd l'accès**. Le cap durable (`PermaCap`) n'existe pas encore. +**CORRIGÉ le 2026-07-27 (direction confirmée par le PO).** Une version antérieure +de cette section disait « qui n'est pas resté abonné perd l'accès » et demandait +d'exposer une obligation d'abonnement. **C'est faux comme cible.** Le commentaire +amont dont ça venait (« *if they don't subscribe, they will lose access after the +refresh* ») décrit **l'état courant**, pas l'intention — l'erreur de méthode que ce +brief met justement en garde de commettre. -La surface ne doit donc **pas** promettre la permanence — sinon le consommateur -n'implémente jamais « rester abonné ou perdre l'accès » et conserve silencieusement -des caps morts. À exposer explicitement : un cap peut **expirer**, et une -re-livraison arrive par le même canal que la livraison initiale. +La **direction** : quand une clé tourne, la nouvelle est **envoyée dans l'inbox** +des utilisateurs qui conservent le droit d'accès, et cette inbox est **traitée +automatiquement** dès qu'un client de l'utilisateur se connecte. + +Conséquences pour la surface : + +- **Aucune obligation d'abonnement à exposer.** Le consommateur n'a rien à + implémenter pour « garder » un accès. +- L'accès n'est pas perdu, il est **différé** jusqu'à la prochaine connexion — + cohérent avec le reste du modèle local-first. +- Une re-livraison emprunte **le même canal** que la livraison initiale : l'inbox. + Donc le mécanisme de §3 couvre les deux, sans cas particulier. +- La **révocation** reste ce qu'elle est : on cesse de re-livrer à qui ne doit plus + lire, et c'est non rétroactif. ### 5. Ce qui disparaît ou change de nom @@ -310,13 +324,23 @@ re-livraison arrive par le même canal que la livraison initiale. | `resetCaps()` au changement d'identité | **basculer** de trousseau, **pas effacer** | | `PrincipalId` dans la surface caps | **sort** — on adresse des inboxes | -### 6. L'exception publique, à ne pas raboter +### 6. Le public — lisible par l'URL, et NON récursif -Un lien de repo **public** n'a **pas** de read_cap : le cap se télécharge depuis -l'outer overlay. Pour du contenu public, la forme cible **est** donc bien -« référence nue → contenu ». L'invariant du §2 admet cette exception — elle n'est -pas une entorse, c'est un second mécanisme. *(Type sans consommateur en amont : -DIRECTION, pas mécanisme vérifié.)* +Principe cible (confirmé par le PO, 2026-07-27), à exposer tel quel : + +> **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 le contenu référencé. + +C'est un **second mécanisme** à côté de la possession de clé du §2, pas une +entorse à l'invariant. Et c'est la non-récursivité qui porte la valeur : elle +permet un objet public qui **pointe** vers de l'identité privée — le cas exact du +consommateur. + +*Détail d'implémentation à ignorer côté forme* : NextGraph s'oriente vers un +**non-chiffrement** du contenu du store public (les données restant signées). La +surface ne doit pas en dépendre. **Si le store public ne fonctionne pas** comme ce +principe le décrit, c'est **le polyfill** qui s'adapte — pas le consommateur. ### 7. Recette de P1a — vérifiable sans une ligne de crypto