Ng eventually #1
@@ -2,7 +2,7 @@
|
||||
type: _overview
|
||||
summary: Sécurité & confidentialité de Festipod — l'isolation entre périmètres est assurée par le SDK de données, l'app lui fait confiance et ne porte aucune logique d'autorisation dans les écrans ; authentification par wallet ; matrice d'autorisations cible en incubation
|
||||
triggers:
|
||||
keywords: [sécurité, security, confidentialité, privacy, accès, "access control", contrôle d'accès, trust, confiance, authz, autorisation, permission, wallet, auth, authentification, anonyme, identité, login, scope, isolation]
|
||||
keywords: [sécurité, security, confidentialité, privacy, accès, "access control", contrôle d'accès, trust, confiance, authz, autorisation, permission, wallet, auth, authentification, anonyme, anonymat, pseudonyme, traçage, corrélation, overlay, cap-less, identité, login, scope, isolation]
|
||||
paths: ["src/modules/auth/**", "src/shared/context/NextGraphContext.tsx"]
|
||||
---
|
||||
|
||||
@@ -13,6 +13,10 @@ Le modèle de **sécurité, confidentialité et autorisations** de Festipod.
|
||||
- **Modèle appliqué** — l'**isolation entre périmètres** (public / protected / private) est **assurée par le SDK de données** (`@ng-eventually/client`), qui n'expose à chaque utilisateur que ce à quoi il a droit. L'app **fait confiance** au SDK : aucun écran ne porte de logique d'autorisation. Voir [[knowledge_trust-model]].
|
||||
- **Matrice d'autorisations cible** — le détail *qui peut faire quoi* par acteur × verbe (données personnelles = réseau, anonymat via inbox de notification) : [[brief_2026-05-18_authorization-matrix]]. **Incubation.** Graduera en `rule_`/`behavior_` à mesure que le produit se cale.
|
||||
|
||||
## Pièges (lire AVANT de concevoir quoi que ce soit d'« anonyme »)
|
||||
|
||||
- [[caveat_stable-overlay-pseudonym]] — une référence cap-less expose un **pseudonyme permanent** de la personne ; un seul recoupement dé-anonymise **rétroactivement** tout son historique, et aucune rotation n'est connue
|
||||
|
||||
## Liens
|
||||
|
||||
- [[knowledge_trust-model]] — l'app délègue l'isolation au SDK, pas de contrôle d'accès dans les écrans
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
type: caveat
|
||||
summary: Toute référence cap-less vers un document protected d'une personne expose le `:v:` de son store — un pseudonyme STABLE ET PERMANENT, identique partout et pour toujours. Ne dit pas qui, mais un seul recoupement dé-anonymise RÉTROACTIVEMENT toutes ses références passées et futures. C'est le même bit d'information qui permet la dédup anonyme. Aucune rotation connue.
|
||||
last_checked: 2026-07-27
|
||||
---
|
||||
|
||||
# Piège : le `:v:` d'une référence cap-less est un pseudonyme permanent
|
||||
|
||||
**À lire avant de concevoir quoi que ce soit qui fasse circuler des références cap-less** (inscriptions, invitations, mentions, index, notifications).
|
||||
|
||||
## Le fait
|
||||
|
||||
Un NURI s'écrit `did:ng:o:{document}:v:{overlay}`. Le segment `:v:` ne vient **pas du document** mais de **son store** — et une personne a **un seul** store *protected*. Donc :
|
||||
|
||||
> **Toutes** les références cap-less vers **n'importe lequel** des documents protected d'une personne portent le **même** `:v:`. Partout, et pour toujours.
|
||||
|
||||
VÉRIFIÉ dans `nextgraph-rs` (le détail et les pointeurs vivent côté polyfill, `docs/readcap-and-nuri-model.md`) : la valeur injectée à la création d'un document est l'overlay du store contenant ; un `Repo` ne porte aucun overlay propre, et les accès blocs d'un `Store` passent tous par **son** `overlay_id` — un overlay par-document est donc structurellement impossible, pas seulement absent.
|
||||
|
||||
## Pourquoi c'est un piège et pas juste une limite
|
||||
|
||||
Ce `:v:` **ne dit pas qui** — c'est un `BLAKE3` non inversible du store id. La tentation est donc de le traiter comme opaque, donc inoffensif. Il ne l'est pas : c'est un **handle constant**.
|
||||
|
||||
- **Corrélation** — quiconque collecte des références cap-less relie entre elles toutes celles d'une même personne, sans jamais l'identifier. Présence récurrente, appartenances, rythme.
|
||||
- **Dé-anonymisation rétroactive** — c'est le vrai danger. Il suffit d'**un seul** recoupement, **une seule fois** (une personne qui se nomme, un canal qui fuit, un croisement avec une donnée externe) pour que `:v:X` soit attaché à une identité. À cet instant, **tout** l'historique lié à ce `:v:` bascule d'un coup — y compris ce qui a été publié des années plus tôt en croyant à l'anonymat.
|
||||
- **Aucune porte de sortie** — VÉRIFIÉ, sur quatre axes : pas de rotation d'overlay (l'outer est un hash pur du store id, sans secret) ; le store id est généré une seule fois à la création de l'identité et jamais régénéré ; aucun chemin de migration de contenu vers un nouveau store ; et aucune forme de référence ne permet de localiser un document sans exposer l'overlay de son store. Le renouvellement de capabilities ne changerait que l'overlay *inner* — l'outer, seul présent dans les NURIs cap-less, y survivrait. **La seule sortie est d'abandonner l'identité entière**, ce qui n'emporte aucun contenu. Signalé en amont comme possible défaut de conception (`orm-tests/INBOX/2026-07-27-outer-overlay-permanent-pseudonym-no-rotation.md`, cf. [[rule_nextgraph-inbox]]).
|
||||
|
||||
## Le couplage à ne pas espérer défaire
|
||||
|
||||
Ce même `:v:` est ce qui permet de **dédupliquer sans lire** — deux références de même `:v:` viennent de la même personne, c'est la base du compteur de participants anonyme ([[brief_2026-07-20_attendance-set-model]] côté `data-layer`).
|
||||
|
||||
**C'est le même bit d'information.** Dédup anonyme et non-traçabilité ne sont pas deux exigences à concilier : ce sont deux lectures d'une seule et même donnée. On ne peut pas obtenir l'une en supprimant l'autre. Le seul curseur réel est le **découpage en stores** — qui déplace l'arbitrage sans le faire disparaître.
|
||||
|
||||
Et ce n'est **pas** un artefact du polyfill : la propriété survit au vrai NextGraph.
|
||||
|
||||
## Ce qu'il faut en faire
|
||||
|
||||
- **Ne jamais présenter à l'utilisateur** une action comme « anonyme » sans réserve si elle fait circuler une référence cap-less. Elle est **pseudonyme**, et le pseudonyme est permanent.
|
||||
- **Compter** les occurrences d'un `:v:` qu'on expose : chaque contexte supplémentaire où il apparaît augmente la surface de recoupement.
|
||||
- **Revérifier** ce caveat si NextGraph introduit une rotation d'overlay ou une forme de référence indirecte — il deviendrait alors caduc, ce qui serait une bonne nouvelle.
|
||||
|
||||
Liens : [[knowledge_trust-model]], [[brief_2026-05-18_authorization-matrix]], data-layer ([[brief_2026-07-20_attendance-set-model]], [[rule_capture-nextgraph-findings]], [[rule_nextgraph-inbox]]).
|
||||
@@ -33,13 +33,15 @@ Vérifiés par lecture de `nextgraph-rs`. Le détail et les pointeurs vivent cô
|
||||
|
||||
## La dédup : sur quoi exactement
|
||||
|
||||
**Hypothèse de travail — à confirmer par le PO.** Le mécanisme que j'identifie derrière « il a normalement assez d'informations pour dédupliquer » :
|
||||
**Validé par le PO (2026-07-27).** Le mécanisme derrière « il a normalement assez d'informations pour dédupliquer » :
|
||||
|
||||
Le segment `:v:` d'un NURI ne vient **pas du document** mais de **son store** (`ProtectedStore(id) → outer(id)`). Or une personne a **un seul** store protected. Donc **toutes ses Participations portent le même `:v:`**, quel que soit le nombre d'objets qu'elle crée. Le créateur déduplique là-dessus : deux références de même `:v:` dans le Set d'un même événement = la même personne. **Sans jamais savoir qui.**
|
||||
|
||||
Conséquence de conception : le Set est **indexé par `:v:`** — au plus une référence par `:v:`. `Set.size` = nombre de `:v:` distincts = nombre de personnes distinctes.
|
||||
|
||||
### La contrepartie, à connaître avant de la découvrir plus tard
|
||||
### La contrepartie — réserve durable, à ne pas perdre
|
||||
|
||||
> **Elle vit dans `app-security/caveat_stable-overlay-pseudonym`**, pas ici. Ce brief a vocation à être dissous à sa graduation ; la réserve, elle, doit survivre. Résumé ci-dessous, référence là-bas.
|
||||
|
||||
Ce `:v:` 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. Il ne dit pas *qui* (`BLAKE3(store_id)` n'est pas inversible), mais c'est un **handle constant**, le même partout et pour toujours.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user