32c2302c91902e6288f1fffd022e13ba2fdd10ec
21 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
32c2302c91 |
Deployed, and it signs people in
First deployment carrying the injected wallet and the external data layer. A user signs in and sees their own data. That settles the one link in the chain nothing here had ever exercised: a deployed origin CAN be embedded in the hosted broker's iframe. The identity flow runs the application inside that iframe, so data reaching a signed-in user is proof the embedding works for this origin. It is settled by the deployment, not by a test, and the doctrine now says so: no scenario covers it, so a change of origin, of proxy, or of the broker's embedding policy would be found by a person rather than by the suite. Worth stating plainly what this deployment is: the first one able to sign anybody in at all. The production bundle never asked for its runtime configuration under NODE_ENV=production, so it had neither password nor wallet to hand the data layer, and the failure was invisible from outside — the server answered, the page rendered, and nothing was wrong except that nobody could get in. |
||
|
|
95479ebe77 |
The image builds, serves the injected wallet, and asks for its configuration
Built and run for the first time in this shape. `pnpm install --frozen-lockfile` fetches the external data layer from Gitea inside the install stage and succeeds -- the step that refused an hour ago. Run with only the password and the base64 wallet set, and no path variable, the container serves 810 bytes at /shared-wallet.ngw with the same sha256 as the original file. The check that mattered most: the production bundle contains exactly one call to /festipod-config.json. That call being absent under NODE_ENV=production is what made the deployed application unable to sign anybody in, and its absence is invisible from outside -- the server answers, the page renders, the endpoint works, and nothing asks it anything. Two doctrine claims the build disproved, corrected rather than left standing: The `bun` peer shim the deployment notes describe as a live hazard does not appear at all in a built image -- `bun` is absent from node_modules/.bin and resolves to the base image's binary. The `onlyBuiltDependencies` approval is currently inert. Kept, since it costs nothing and the shape can return, but the paragraph now says dormant instead of describing a mechanism that is not running. Asset paths are emitted as `/../chunk-*.js`. Browsers normalise that at the root and the existing deployment already passes it through its proxy, so it works -- but a proxy that treats `..` segments differently would break asset loading, and the symptom would be a blank page with 404s on chunks, naming nothing. |
||
|
|
c3d64555d9 |
The data layer is a real external dependency, pinned to a commit
`package.json` named `#main`, where the renamed `packages/polyfill` does not exist, and `pnpm-lock.yaml` still named the package as it was called in July. `pnpm install --frozen-lockfile` -- the Dockerfile's install step -- refused on exactly that mismatch, so the image could not build at all. Both now name the commit the branch was pushed at, and the frozen install passes. The dependency is now genuinely external: installed from git into pnpm's store, with no local overlay anywhere in the resolution. The invariant that justified the overlay in the first place holds -- `@ng-org/web` resolves to the same realpath from the application and from the installed package, so one instance and one verifier. A git-installed package does not carry its own `@ng-org`, where a symlink to the checkout would have. `.project/contracts.yaml` names the same commit as the dependency, so the surface the app is coded against and the package it installs designate one state, and a drift between them becomes visible instead of silent. A tag will replace the commit once the provider settles a convention; the invariant is that the two agree, whatever the ref. Deployment doctrine now carries what a deployer needs and did not have: the pinning discipline, that the frozen install only verifies, the wallet arriving through the environment with its one-directional precedence and its loud failure on a malformed value, that neither the wallet nor its password is a secret, that tailwindcss is a devDependency the server needs at serve time, and that a deployed origin's embedding in the broker's iframe is covered by no test. Nothing has been deployed in this shape yet, and the doctrine says so. |
||
|
|
ac29735d20 |
A deployment can carry the wallet in its environment, not on a mounted disk
The contract requires the application to serve a wallet file and hand its URL and password to the data layer. Until now the only source was a filesystem path, which no container has: `*.ngw` is gitignored, `COPY . .` brings none, and nothing mounts one -- so a deployed instance served 404 where the contract expects bytes. `FESTIPOD_SHARED_WALLET_FILE_BASE64` carries the file itself. It is 810 bytes, and it is not a secret: by design the application hands it to every user who opens the app, so provisioning persistent storage would be guarding something public. One channel for both values, nothing to mount, and a new host needs only its variables. Precedence is deliberate and one-directional: the path always wins when set, and an unreadable path does NOT fall through to the base64 form. A deployment sets exactly one; both set is a leftover, not a fallback chain. Local development and the test harness only ever set the path, so they are untouched. A malformed value answers 500 and names the variable. Answering 404 would have made "configured wrong" indistinguishable from "not configured at all" -- the confusion this codebase has spent two days removing. Proven by serving the same wallet from each source in turn and comparing: identical size, identical sha256. The first attempt at that proof silently exercised the path branch, because Bun auto-loads `.env` and the variable was already there; the checksums matched for the wrong reason. Caught, cleared, and measured again. |
||
|
|
ff26f26e60 |
Close the fixed blocker, and record what withdrawal converging faster does NOT mean
Six variations against the real application, one thing varied at a time: the sign-up-breaks-the-next-connection defect is gone. New identity, immediate reload or delayed; an identity already used for several cycles; and the very identity poisoned by the pre-fix code, which now reconnects cleanly three times out of three. So nothing needed healing -- the fix does not merely stop writing the bad state, it makes what was already written harmless. The leaf is deleted rather than graduated: its reproduction method, the stale-server trap it led to, and "a provider gap is not worked around here" all live elsewhere already. The count defect stays open, with its shape now known: it does converge across connections, but takes one more than expected -- the first reconnect still shows zero, the second shows the value. And a correction worth keeping. The explanation offered for why withdrawal converges in a single connection -- that it writes straight to the owner's document instead of depositing -- is contradicted by the code: it deposits its own marker into the same inbox, drained by the same owner routine, "symmetric" by the code's own comment. The asymmetry is real and recorded as verified; its cause is recorded as unknown rather than filled with a plausible story. Same mechanism, same inbox, two connections against one, is a lead worth having honestly. The dev-server caveat is upgraded from inferred to verified, and it is worse than it read: an edit to application source triggers a genuine rebuild, new bundle hash and all, and that rebuild still carries the stale dependency. Only a restart works, and "touch a file to force a rebuild" is now explicitly ruled out as a substitute. |
||
|
|
ac55dc96a4 |
A refreshed data-layer package never reaches a running dev server
`link:polyfill` overlays the package into node_modules and keeps it current. That is all it does. A `bun run dev` already running goes on serving what it loaded at startup, however many times the overlay is rewritten underneath it: node_modules is excluded by file watchers, so the change lands in the one place nothing is looking. The script promised the opposite -- that `bun --hot` would reload the copied file live. That promise is now removed, and replaced by the instruction to restart. It cost about an hour. A defect had been fixed upstream, the overlay refreshed, and a probe on a freshly launched server confirmed the fix 3 runs out of 3. The same sequence by hand reproduced the defect at once. The two observations looked irreconcilable and the hunt went to the wallet, to prior state, to timing. The dev server had been up for six days. It predated the package rename and the whole migration; the browser was running a different application from the one under test. Nothing warned: a stale server looks exactly like a current one, and the script's own header ruled out the true cause for anyone who trusted it. The reflex is written down with the leaf: when a fix seems not to take, or when a hand-run and an automated run disagree, check how long the server has been up before anything else. One command, cheapest hypothesis first. |
||
|
|
4148df8fcb |
Record what running the flow proved, and fix the leaf that caused one defect
The create-and-participate flow was driven in a real browser for the first time. It had been called correct by construction -- typecheck, build, reading -- and the probe found three defects none of those could see. Two open bugs, both major, both filed rather than worked around: signing up to your own event makes the NEXT connection fail outright (`ensureIdentity()` rejects inside the data layer's own inbox processing, 3/3, reproduced on a fresh origin and identity), and the participant count does not converge in the same session (2/2, 120 s and 75 s). Whether it converges at the next connection is recorded as UNKNOWN and unmeasurable, because the first bug stops the app from getting there. The doctrine defect is the one worth the trouble. `knowledge_build-pipeline` said production builds into `dist/`; `knowledge_deployment` said the container runs `bun run start` from `src/`. Both were written down, they contradicted each other, and the code followed the wrong one -- which is how a deployed app that could sign nobody in was shipped. The three paths now live in one table whose discriminating column is what is actually served: dev `src/`, production `src/`, and `dist/` served by nothing at all. A build artefact nobody serves is a trap for the next reader who assumes otherwise. The probe method itself is written down: the suite cannot run, a targeted probe can, and the difference is worth knowing before concluding that nothing is measurable. Stated once where a reader meets it: honest steps do not add up to an honest flow. Every gesture in the sign-up reports correctly, and the user is still told they participate while the count never moves and the next connection fails. |
||
|
|
53c0e095cf |
Code against the polyfill's published contract, and nothing else
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. |
||
|
|
c1817607b4 |
Migrate Festipod onto the rebuilt @ng-eventually/client surface
The SDK was rebuilt: reading is possession instead of an ACL, `Nuri` and `ReadCap` are template literal types, the cross-account fan-out is gone, and so is the global discovery index. Repair the typecheck gate FIRST — it was checking nothing. Under TypeScript 6 the deprecated `baseUrl` is reported as an ERROR that aborts compilation, so `tsc --noEmit` exited 0 having verified nothing, behind a single line that reads like a harmless warning. Dropping `baseUrl` (paths resolve relative to the file since 4.4) makes the gate real again — and it immediately surfaced 33 errors, three of which had been dormant for a long time. Types: 18 sites fixed AT THE SOURCE — the functions that produce a NURI now return `Nuri` — with `isNuri` guards only at genuine boundaries (an `@id` read back from a document, an argument coming from a Cucumber step). No cast, no `@ts-ignore`: silencing the compiler here would have removed the very guarantee the new types provide. Capabilities: the ACL is gone. `grantRead`/`protectedDocsOf`/`canRead`/ `makePublic` give way to `capFor`/`shareCap`/`publishRepoLink`, and `open` loses its `owner` argument. `declareConnections` now shares the caps of its OWN protected documents to each neighbour's wallet inbox. Discovery is REMOVED, not postponed: there is no discovery in the target model, a reader reaches a document only by following a link it was given. The module and its call sites are gone; the scenario is suspended with a comment saying what will bring it back — a Festipod DIRECTORY document, whose link the app knows. Kept rather than deleted: the product need has not gone away. Verification, and a correction to how it was measured. The @data baseline (20/22) had been taken on a bloated test wallet: 93 MB against a threshold documented around 99 MB, with the run stretching from 18 to 23 minutes. Restarting from a fresh profile drops it to 9m37 and turns BOTH baseline failures green — including the cold-reconnection one, which confirms the SDK's claim that a fresh session reads its own documents back with nothing re-declared. So the reference itself was degraded, on both sides of the comparison. Real state: typecheck 0, @ui 7/7, @data 20/21. The single failure is understood and left standing: the protected-connections probe reads the protected STORE document as a stand-in for an entity. Sharing a store cap would hand over its entire contents, present and future — precisely the gesture the model refuses. The scenario's own title says "the protected ENTITY"; the probe is what took the shortcut, and it is what has to change. |
||
|
|
7459d49e83 |
docs+fix: recadrer le polyfill comme compensateur d'écart, corriger la doctrine périmée
RECADRAGE — la doctrine était trop étroite. rule_app-uses-sdk-surface-only disait « le polyfill existe pour le WALLET VIRTUEL » : juste sur le fond, mais à la lettre l'émulation des caps qu'on vient de livrer n'entrait pas dans son mandat. Nouvelle formulation, portée aussi dans AGENTS.md : @ng-eventually/client est un POLYFILL, et ce mot dit toute sa mission : compenser l'écart entre le SDK tel qu'il devrait être et ce que NextGraph fournit aujourd'hui. Le wallet virtuel en est la plus grosse pièce, pas la totalité. Avec la conséquence opérationnelle : quand quelque chose ne marche pas, la question n'est jamais « comment contourner dans l'app » mais « qu'est-ce que le polyfill doit compenser ». Un contournement côté app est une violation même quand il fonctionne — il grave un état temporaire de NextGraph dans du code qui doit lui survivre. Et l'ignorance de l'état d'implémentation est durcie : ENTIÈREMENT, pas « sauf quand ça mord ». NOUVEAU — data-layer/knowledge_sdk-surface : le contrat SDK cible, écrit dans CE repo pour qu'un agent n'ait jamais à ouvrir le repo du polyfill. Couvre lectures réactives, écritures, placement par scope, inbox, discovery, capabilities (capFor/shareCap/publishRepoLink, livrées avec P1a), identité, sûreté SPARQL — et les surfaces exportées mais interdites à l'app. DOCTRINE PÉRIMÉE corrigée, après vérification dans le code : - rule_document-per-entity décrivait la lecture via readEntities/readUnion/ registerDoc/bumpRead : ZÉRO site d'appel, readEntities.ts supprimé. Réécrite sur watchShape/useShapeQuery. Le fond (un document par entité) est intact. - brief_2026-07-06 §P3 réaffirmait une phrase que son propre encadré déclare fausse : rétractée explicitement. - knowledge_data-modes citait useShapeWithDefaults(), qui n'existe nulle part. - ConnectScreen : les fiches avaient raison mais étaient vagues — l'écran existe, est routé et monté, et est bien absent du registre. Précisé. FIX CODE — build:orm était CASSÉ : il pointait ./src/shapes/, qui n'existe pas (les shapes vivent sous src/shared/shapes/), et sortait en erreur. Donc la commande que la doctrine prescrit après tout changement de .shex ne marchait pas. Corrigé et vérifié : exit 0. La fiche avait raison, c'est le code qui était faux — le point 4 approuvé, simplement situé dans l'autre fichier. Régénération NON embarquée : lancer build:orm reformate les bindings et retire l'annotation `: Schema`. C'est une montée de version d'outil, pas une correction de contenu — elle mérite son propre changement validé, pas un passage clandestin. Noté dans la fiche. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
b6a6b14fad |
docs(concept): passer les 59 fiches de doctrine en anglais
Convention du projet pour la documentation projet. Traduction fidèle, sans changement de fond : mêmes fiches, mêmes sections, mêmes liens. Le lint est identique à la baseline (59 leaves, 0 nouveau lien cassé, wikilinks bit-à-bit inchangés) et aucun `.feature` n'a été touché. Le `summary:` du frontmatter est traduit lui aussi — c'est ce que le hook affiche dans l'index, il porte autant que le corps. RESTENT EN FRANÇAIS, délibérément : - les fichiers .feature (convention explicite du projet : Etant donné/Quand/Alors) et le bloc Gherkin cité dans brief_2026-07-06 ; - les libellés d'interface cités en prose (« Entrer », « ✓ Je participe », « Voir tous les participants », « participant inconnu »…) : ce sont des chaînes réelles de l'app, pas de la prose ; - les noms de scénarios BDD ; - les `triggers.keywords` des _overview : jetons de matching du hook, et la conversation reste en français — les traduire aurait cassé la livraison. EFFET SECONDAIRE UTILE : relire intégralement a fait remonter des contradictions et des péremptions que personne ne voyait section par section. Notées, non corrigées (hors périmètre de la traduction) : - rule_document-per-entity décrit la lecture via readEntities/readUnion/ registerDoc/bumpRead, que rule_app-uses-sdk-surface-only déclare SUPPRIMÉS au profit de watchShape/useShapeQuery. Une règle qui décrit des APIs retirées est activement trompeuse — à traiter en priorité. - brief_2026-07-06 §P3 réaffirme « prouvé par l'e2e D.2, sans reload » juste après l'encadré qui déclare cette phrase fausse et sur-cadrée. - knowledge_data-modes cite useShapeWithDefaults() là où useShapeQuery est documenté ailleurs. - knowledge_stack-and-commands : build:orm pointe ./src/shapes/* alors que les shapes vivent sous src/shared/shapes/. - knowledge_screens / knowledge_routing : ConnectScreen décrit comme absent du registre mais présent en route. - brief_2026-05-18 : « identifié si connecté » était ambigu en français (session ouverte vs est une connexion) ; l'anglais a forcé à trancher — rendu par « if a connection », à confirmer côté produit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
96e28a702f |
docs(concept): solder la doc-debt des 6 concepts
Dette accumulée depuis le 13/07 (27 marqueurs). Au-delà du vidage, trois
corrections de doctrine réellement fausse — c'est ce que le reconcile devait
attraper :
- app-security : `sharedWallet.ts` capture le mot de passe à l'ÉVALUATION du
module. Tant qu'un repli existait, un global posé trop tard ne faisait que
dégrader ; depuis que le wallet partagé est l'unique mode, il rend la barrière
INUTILISABLE (écran d'erreur, aucun champ). Conséquence non anticipée de la
décision shared-wallet-only → nouveau caveat.
- bdd-testing : la doctrine rendait des tests faux-verts. `ctx.newPage()` sur le
profil persistant relit l'IndexedDB local et ne prouve JAMAIS la durabilité
broker ; seul un contexte partagé neuf tranche. Un agent suivant la doctrine
écrivait un test qui passe sans rien vérifier → nouveau caveat.
- app-architecture : `knowledge_routing` décrivait encore une route `/login`
disparue, et `knowledge_screen-pattern` citait `LoginScreen` qui n'existe
plus. Nouveau caveat sur les deux espaces d'id vus depuis un écran.
Aussi : data-layer/knowledge_context-internals décrit la jointure
participation→profil et corrige un mécanisme de changement d'identité périmé ;
tech-stack raccroche la table des scripts au vrai point d'entrée cucumber ;
functional-domain note qu'« implémenté » ≠ « durable ».
Trois marqueurs soldés comme sans objet : ils visaient
`reconnexion-socket-mort.{feature,steps.ts}`, absents de l'arbre ET de tout
l'historique — expérience abandonnée avant tout commit. Ce qu'elle devait
établir est capturé ailleurs (caveat de durabilité, post-mortem polyfill, fiche
INBOX socket-death).
Liens morts vers une décision disparue avec le concept `nextgraph-platform`
réparés. Reste au lint : le brief 07-06 (superseded) porte des file:line et des
références aux internes NextGraph — laissé intact, il décrit l'Option-B encore
implémentée et se dissoudra à la graduation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg
|
||
|
|
7e65a83d42 |
fix(test): cucumber via l'entrée JS réelle (@cucumber/cucumber/bin) — pnpm casse le shim .bin
pnpm installe node_modules/.bin/cucumber-js comme shim shell (pas du JS) → 'node --import tsx/esm node_modules/.bin/cucumber-js' échoue. Pointer sur l'entrée JS réelle du paquet. Répare test:data et cucumber:run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
a21d9b0735 |
docs(concept): durabilité écriture↔déconnexion, décision wallet-partagé-unique, rule_bun-first (install pnpm)
caveat_write-durability-across-disconnect + decision_2026-07-20 (wallet partagé = seul mode ; identifiant ≠ username profil) + amendement bun-first. Marqueurs _debt.md inclus (voyagent avec la branche, à réconcilier avant push). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
f6fc3c262e |
chore: install via pnpm + polyfill depuis Gitea (git-https) + lien local réactif
Passe l'installation de bun à pnpm (runtime/build/test restent bun). Dépendance prod @ng-eventually/client résolue depuis le Gitea public en git+https (committée, reproductible via pnpm-lock.yaml). Script link:polyfill (S2 copie-overlay + watcher) pour un lien local réactif préservant l'instance @ng-org unique. bun (peer de bun-plugin-tailwind) approuvé au build (pnpm.onlyBuiltDependencies) pour que node_modules/.bin/bun soit un vrai binaire. Dockerfile: install pnpm avec git + node dans l'image, runtime bun inchangé. Doctrine tech-stack (deployment, stack-and-commands) mise à jour. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg |
||
|
|
0958d70132 |
docs(tech-stack): caveat Firefox 151+ LNA bloque l'iframe app du broker en dev
Piège coûteux : iframe blanche + zéro log app + aucune erreur = pas un bug Festipod, c'est Local Network Access de Firefox qui bloque le broker public d'embarquer l'app locale. Fix navigateur (network.lna.enabled=false). HTTPS n'y change rien ; le top-level charge quand même ; le smoke ne peut pas l'attraper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c0fd69344b |
feat(data): auto-seed opt-in (FESTIPOD_AUTO_SEED) + logs data lisibles; diag bug participantCount
Seed: l'auto-seed sur wallet vide est désormais OPT-IN, OFF par défaut — ne se déclenche que si FESTIPOD_AUTO_SEED=1 (livré en dev via /festipod-config.json + define build.ts, comme le shared-wallet). Le seed répété bloatait le wallet (lenteurs de lecture). Seed explicite (loadTestData, tests @data) inchangé. Logs: chaque useShapeQuery logge à la réception du set le nombre d'objets + le type + des compteurs globaux cumulés : [FestipodData] set reçu: 9 objets Event (public) en 1234ms [FestipodData] totaux — Event: 9, Participation: 3, UserProfile: 10 (5 sets) (polyfill docs.ts: "N rows" -> "N triple-rows" pour clarifier que ce sont des triplets RDF, pas des objets métier.) Diagnostic bug participantCount (NON corrigé, design-sensible): le propriétaire d'un événement reste à participantCount=0 quand un inscrit d'un AUTRE verifier dépose. Cause: le owner-materializer n'est re-déclenché que par ownedKey, jamais par un push d'inbox — doc_subscribe ne délivre aucun Patch cross-session. Le bloat de wallet MASQUAIT le bug (faux-vert). La théorie "StorageError" était fausse. Scénario réactif @wip = test ROUGE qui documente le bug. Doctrine: knowledge_context-internals (caveat BUG ACTIF + auto-seed opt-in), brief_2026-07-06 (claim D.2 "prouvé vert" REFUTÉ), build-pipeline (nouvelle var). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3dfd549af3 |
docs(tech-stack): correct the dev shared-wallet command (real e2e password + file)
A dummy FESTIPOD_SHARED_WALLET_PASSWORD=1 only makes the screen appear; the import fails because the displayed password must match the imported .ngw. Document the working invocation with the real e2e wallet (festipod-e2e-tests) + its file. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
25b1c033d9 |
fix(auth): show the shared-wallet flow in dev; hide re-import when already connected
The access barrier's shared-wallet steps are gated on hasSharedWallet(), which reads a global set only by build.ts's compile-time `define`. The src-served paths (bun run dev AND bun run start) bundle index.html via Bun's HTML import, which applies no define and inlines neither `process.env` nor `bun --define` (verified) — so FESTIPOD_SHARED_WALLET_PASSWORD passed to `bun run dev` never reached the frontend, and the barrier showed the identifier-only variant. Expose the config at runtime instead: src/index.ts serves /festipod-config.json (+ /shared-wallet.ngw), and the entry (frontend.tsx) fetches it, sets the global, then dynamically imports App so sharedWallet.ts reads it on eval. In a build.ts bundle the value is inlined via define, so the fetch is skipped (NODE_ENV). Verified in a headless browser: FESTIPOD_SHARED_WALLET_PASSWORD=1 bun run dev now renders the download + import steps AND the identifier field, no console errors. Also: only show the download/import steps when status !== 'connected' — after a faux-logout the wallet is still open, so re-import must not be offered (just the identifier). Documents the build-define-vs-runtime-config pitfall in tech-stack. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
db9eb1cf47 |
doctrine: Festipod treats @ng-eventually/client as a finished NextGraph SDK
Enforce the project boundary: Festipod is written as if NextGraph were a mature, finished SDK; @ng-eventually/client IS that SDK. NO current-NextGraph-state, simulation, polyfill, shim, mono-store, store-id or broker-internal knowledge remains in this repo — it now lives in the @ng-eventually/client repo. - Dissolved the `nextgraph-platform` concept entirely (12 leaves — all current-state/simulation, now in the lib's docs/). Rescued the genuine domain parts into functional-domain/knowledge_data-scopes-and-discovery.md (which entity → which scope; product-level discovery/notification intent), framed as SDK usage with no mechanism. - data-layer re-anchored to "how Festipod persists via the SDK": stripped mono-store/private_store_id/RepoNotFound/DataCloneError/FESTIPOD_MULTISTORE. Deleted the current-SDK compensation leaves (private-store-scope, multistore, the 2026-03-17 ADRs, conditional-ng-init). Kept/reworded the domain + app leaves; caveat_participation-deletion reduced to the domain contract. - app-security reworded (isolation delegated to the SDK; app trusts it). - AGENTS.md: dropped the nextgraph-platform row, reworded data-layer/ functional-domain/app-security, added the "Frontière SDK NextGraph" note. - Fixed dangling [[links]]; concept lint clean (43 leaves). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0294e3992f |
docs(concepts): migrate project docs into 7 concepts + code-grounded audit
Migrate .project/{knowledge,decisions,briefs} and the always-loaded
AGENTS.md/CLAUDE.md into the in-repo `concept` system (hook-delivered,
typed leaves). Then audit the actual code to verify the migrated doctrine
and capture knowledge that lived only in the source.
Concepts (53 leaves):
- functional-domain — produit : point de rencontre greffé, acteurs, déduplication
- app-architecture — modules, invariant d'imports, routing, écrans, styling-system,
screen-pattern, cookbook d'ajout d'écran
- tech-stack — Bun-first, APIs, build pipeline, deployment (Dockerfile), commandes
- data-layer — NextGraph mono-store, shapes, modes, règles + caveats (suppression,
champs non persistés, internals du contexte)
- bdd-testing — Cucumber multi-couches, contrat de couches, harness, cookbook
- app-security — posture actuelle (mono-store, confiance broker), auth wallet,
brief matrice d'autorisations cible
- nextgraph-platform — NextGraph système externe + briefs (multi-store, shim, fork)
Audit corrections:
- décision SPARQL-delete annulée (superseded) → caveat (le code utilise ngSet.delete,
persistance possiblement partielle)
- divergences relevées : routing path-based (pas hash), thème moderne sous components/sketchy,
ConnectScreen hors registre, build:orm au chemin périmé, champs d'event perdus en connecté
Strip migrated sources; AGENTS.md/CLAUDE.md réduits au cœur (but, invariants,
carte des concepts) + pointeurs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|