53c0e095cf
The data layer is now reached through one pulled, version-pinned engagement (`.project/concepts/data-layer/contract_polyfill-surface.md`, @1ecf511e9d). That copy is the only reference: the provider's sources are never opened, and what the contract does not answer is a gap raised with it, never worked around here. Surface - `@ng-eventually/sdk` -> `@ng-eventually/polyfill`, one entry point. - `configure` loses `getSession`, `normalizeId`, `currentUser`; the session belongs to the package and its own `init` captures it. - Placement is named by scope alone -- a session is one user, so the app no longer passes an identity it had no way to obtain. This removes a constant that made every user collide on one owner's document. - `init(...)` then `await ensureIdentity()`, in that order, as one sequence: React runs child effects first, so the two calls sat in the wrong order and the contract now makes that throw. - `sessionId` relayed as `string | number`, `materialize` -> `read`. A rejection means "unknown", never "absent" Four places treated a caught error as an empty result. The worst wrote a duplicate participation: an unknown count read as zero defeated the idempotence guard of `joinEvent`. Also fixed: a per-document count, a silently dropped notification shown optimistically anyway, and a failed listing that left the owned-event set empty and disabled the materializer for the whole session. Shared identity is not a Festipod notion A browser context is one user. The per-scenario identity plant is deleted at its source and its five sites; what stays is the deployment's wallet file, which the contract requires an application to serve. Documentation The doctrine no longer describes how the data layer works underneath: five leaves whose subject was internals are gone, a dozen more are re-founded on the contract's own words, and two frozen arbitrations about a deleted screen were removed rather than left to mislead a future session. Test harness It can sign in at last: cucumber runs under node, which does not load `.env`, so the harness never received the wallet material and every scenario silently fell back to an empty local mode. A failed sign-in is now loud on both sides. The suite also releases what it opens and exits on its own -- runs were still resident hours after reporting, holding a browser and two servers. Known red: `@data` cannot be measured. The served wallet accumulates and nothing resets it; moving the browser profile aside does not, since the data lives in the wallet file, not the profile.
41 lines
3.3 KiB
Markdown
41 lines
3.3 KiB
Markdown
# Festipod
|
|
|
|
Web app mobile-first où les utilisateurs créent des **points de rencontre** qui se *greffent* sur des **événements publics** existants, pour favoriser les rencontres. L'événement n'est qu'un prétexte/ancrage ; la valeur, c'est le point de rencontre — **on s'inscrit à un point de rencontre, pas à un événement**. Stack : Bun + React + NextGraph (P2P, local-first, chiffré).
|
|
|
|
## Invariants à toujours garder
|
|
|
|
- **Architecture feature-based** : le code est organisé par domaine métier, pas par couche technique.
|
|
```
|
|
src/modules/{event,user,home,auth,workshop,meeting,notification}/
|
|
src/shared/ # Composants, context, data — importable par tous les modules
|
|
src/app/ # App shell (router, providers, entrée)
|
|
src/screens/index.ts # Registre d'écrans (utilisé par Storybook)
|
|
```
|
|
- **Un module n'importe QUE depuis `shared/` — jamais d'un autre module.** C'est l'invariant qui rend l'archi réelle.
|
|
- **Bun-first** : `bun` / `bun install` / `bun test` / `bun build`, jamais node/npm/vite/jest. `bun run dev` (port 3000).
|
|
|
|
## Frontière SDK
|
|
|
|
Le SDK de données de Festipod est **`@ng-eventually/polyfill`**, injecté une seule fois via `ngSession.configure(...)`.
|
|
|
|
**L'engagement que le fournisseur publie est tiré dans ce repo et épinglé** : `data-layer`, fiche `contract_polyfill-surface`. **C'est la seule référence.** On n'ouvre jamais les sources du fournisseur ni sa copie dans `node_modules`, pas même pour vérifier une signature. Ce que le contrat ne dit pas, ce repo ne le sait pas : **un manque est remonté au fournisseur**, jamais contourné ici ni documenté ici. Vaut aussi pour les tests, qui valident **Festipod** et jamais le SDK (`bdd-testing`, `rule_tests-validate-festipod-not-the-sdk`).
|
|
|
|
Le contrat se re-tire à chaque montée de version : `python3 ~/projects/skills/concept/contracts.py pull` (dérive : `… check`). Sa surface **rétrécit** — un symbole retiré est du code que l'app supprime, pas une régression à amortir.
|
|
|
|
**Ne jamais décrire dans ce repo comment la couche de données est implémentée.** La doctrine Festipod décrit uniquement *le contrat* + *comment Festipod l'utilise* + le domaine + l'architecture + le contrat BDD.
|
|
|
|
## Doctrine du projet — concepts (livrée automatiquement)
|
|
|
|
La connaissance détaillée vit dans `.project/concepts/` (système *concept*) : fiches courtes, typées, **livrées par un hook quand tu touches leur territoire** — tu n'as pas à les charger d'avance. Les 6 concepts :
|
|
|
|
| Concept | Couvre |
|
|
|---|---|
|
|
| `functional-domain` | Modèle produit : point de rencontre, acteurs, concepts métier, périmètres public/protected/private par entité, découverte, défi déduplication |
|
|
| `app-architecture` | Modules, invariant d'imports, app shell, routing path-based, écrans |
|
|
| `tech-stack` | Bun-first, APIs Bun, build pipeline, commandes |
|
|
| `data-layer` | Persistance via le SDK `@ng-eventually/polyfill` : entités-documents par scope, shapes SHEX/ORM, modes connected/demo, pièges |
|
|
| `bdd-testing` | Cucumber multi-couches FR, contrat `@ui`/`@data`/`@e2e`, harness broker, cookbook |
|
|
| `app-security` | Isolation déléguée au SDK (pas de contrôle d'accès dans les écrans), auth wallet, matrice d'autorisations cible |
|
|
|
|
Pour **documenter** un fait projet : `/concept document <sujet>` (ne pas écrire en libre dans `.project/`).
|