doctrine(data-layer): rule — one document per entity (not store-level)

Festipod persists each entity as its own document (via the SDK), placed in its
scope. The document is the SDK's unit of sharing/permission, so per-document
isolation (private→owner, protected→owner+connections, public→all) is only
possible when each entity has its own document. Writing several entities into a
store-level document defeats per-scope isolation. Framed as SDK usage; the SDK
owns enforcement (app-security/knowledge_trust-model).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Duchesne
2026-07-04 10:21:07 +02:00
parent bc3d270bd4
commit 82c2cb5f27
2 changed files with 41 additions and 0 deletions
@@ -20,6 +20,10 @@ Comment Festipod **persiste ses données** via NextGraph (P2P, local-first, chif
- [[knowledge_seed-data]] — données de seed, `CURRENT_USER_ID`
- [[knowledge_context-internals]] — pièges de `FestipodDataContext` (currentUser, auto-seed dev, `participantCount` cache, no-op local)
## Règles d'écriture
- [[rule_document-per-entity]] — chaque entité = **son propre document** (par scope), jamais au niveau du store ; c'est ce qui rend l'isolation par-document du SDK possible
## Pièges (lire avant de toucher aux suppressions / aux champs d'event)
- [[caveat_participation-deletion]] — la désinscription doit être **autoritative** et ne pas réapparaître
@@ -0,0 +1,37 @@
---
type: rule
summary: Festipod persiste CHAQUE entité comme SON PROPRE document (via le SDK), placé dans son scope (public/protected/private) — jamais plusieurs entités écrites dans un document de niveau store. Le document est l'unité de partage et de droits : l'isolation du SDK est PAR-DOCUMENT, donc un document par entité est ce qui la rend possible.
---
# Règle : un document par entité (jamais au niveau du store)
Quand Festipod crée une entité (événement, point de rencontre, profil, participation,
notification), il l'écrit comme **son propre document**, via l'appel « créer un document » du
SDK de données ([[knowledge_nextgraph-stack]]), en indiquant son **scope**
(`public` / `protected` / `private`). L'entité est ensuite lue et écrite dans **ce** document.
**Ne jamais** écrire plusieurs entités dans un document partagé « de niveau store » (p. ex.
tout mettre dans un seul document racine). C'est un anti-pattern qui casse l'isolation.
## Pourquoi
Le **document est l'unité de partage et de droits** du SDK : l'isolation (qui peut lire quoi)
est appliquée **par document**. `private` → le propriétaire ; `protected` → le propriétaire +
ses connexions ; `public` → tout le monde. Cette discrimination n'est possible **que si chaque
entité a son propre document** : mettre plusieurs entités (voire plusieurs propriétaires) dans
un même document rend le partage tout-ou-rien et défait l'isolation par périmètre.
L'isolation elle-même est **entièrement assurée par le SDK** ([[knowledge_trust-model]] du
concept `app-security`) — l'app ne porte aucune logique d'accès ; elle déclare seulement son
identité (au login) et ses connexions (acte de partage), puis fait confiance à ce que le SDK
renvoie. La granularité « un document par entité » est la contrepartie côté écriture de cette
confiance.
## Comment l'appliquer
- À la création : demander au SDK **un document pour l'entité, dans son scope** ; y écrire
l'entité. Ne pas réutiliser un document d'un autre périmètre ni un document de niveau store.
- En lecture : passer par le SDK, **par scope** — pas de résolution de document/NURI côté app.
- Le mapping *entité → scope* (événement/PdR → public, profil réseau/participation → protected,
settings → private) est un fait produit (concept `functional-domain`,
[[knowledge_data-scopes-and-discovery]]).