Festipod now follows the correct SDK logic: each entity (event, participation,
profile, notification) is created as its OWN document in its scope
(rule_document-per-entity), via the SDK create call — the store-root write path
and the FESTIPOD_MULTISTORE flag are gone. Reads subscribe the per-entity docs
with instant visibility on create; seed/bootstrap rewritten per-entity.
Removed all app-side access logic: utils/isolation.ts (applyIsolation) deleted.
The app only declares its identity (login) and its own bilateral connections
(sharing act), reads via the SDK, and trusts it — no access filtering in the app.
This makes the SDK's per-document ReadCap the sole, real isolation.
Unit-proven in the lib (89 tests). @data/@e2e validation deferred: the NextGraph
broker is unreachable — to be re-run in T03.d. Follow-up: unify app connection
principals (user IRI) onto the username key used by the SDK's cap owner.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Enforce the boundary in code-comments and doctrine (adversarial-review cleanup):
- App comments in the data plane no longer narrate the SDK's internals: "emulated
curator"→"the inbox read", "fan-out"→"discovered", removed store-placement
reasoning and "polyfill/shim/mono-store" wording (FestipodDataContext,
registration, storeRegistry, ngSession, AccountContext, isolation, sharedWallet,
AccessGateScreen). Executable logic unchanged.
- Removed dangling references to the dissolved `nextgraph-platform` concept and
`brief_2026-06-15_shared-wallet-shim` from app code.
- knowledge_nextgraph-stack: dropped "mécanique d'émulation" from the boundary note.
- Settled and deleted all concept _debt.md (confirmatory; target leaves clean).
(Test-infra under workshop/ + generated features.ts still carry some simulation
vocabulary — parked as a separate below-SDK decision.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On creating a public event, Festipod submits it to the discovery index (an SDK
call); the discovery screen reads the index instead of enumerating accounts. The
app knows nothing of the index's owner, inbox, or materialization — it treats the
lib as a finished SDK whose discovery is a global index. No store ids.
Unit-validated in the lib (79 tests). @data broker validation deferred: the
NextGraph broker (nextgraph.net/eu) was unreachable at run time — to be re-run
in T03.d once the broker recovers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Festipod performs the domain acts that make isolation real: AccountContext
declares the current identity at login/change; FestipodDataContext declares its
connections (friendships) to the data SDK. Reads then discriminate by scope
through the SDK (private→owner, protected→owner+connections, public→all) — no
app-side filtering, no store ids, no awareness that isolation is emulated. New
@data scenario proves an unconnected account can't read another's protected
entity but can after connecting; public stays visible. @data 21/21.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Festipod now treats @ng-eventually/client as a finished NextGraph SDK: the app
decides only each entity's logical scope (events/PdR public, profiles/
participations protected, settings private) and calls the lib by scope. The old
mono-store default and the FESTIPOD_MULTISTORE path collapse into ONE scope path.
Removed every physical-store leak from the app data-plane (ngGraph, registration,
FestipodDataContext, NextGraphContext, useShapeWithDefaults): no more
did🆖${store_id} construction. The session is handed to the lib only at the
sanctioned injection point (ngSession/configureStoreRegistry). Product behavior
unchanged. @data 20/20; build + tsc clean.
(_debt.md included; the T03.e doctrine pass settles accumulated doc-debt.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
- data-layer/caveat_multistore-is-multi-document (new): the recurring store vs
document confusion. Two axes — (A) which native store, (B) documents within a
store. FESTIPOD_MULTISTORE toggles axis B (multi-document), not multi-store.
Isolation (ReadCap) is per-document. As of T02.h the default path writes
shareable entities to the real protected store (axis A, step 1).
- rule_private-store-scope: rewritten — shareable entities now scope/@graph the
protected store; private anchors the shim/inbox + settings; "never did:ng:i"
kept. decision_2026-03-17 marked partially superseded.
- knowledge_stores-permissions: ⚠️ store↔document callout.
- knowledge_entities: MeetingPoint/Notification now persisted (not local-only).
- nextgraph-platform: decision_2026-06-17 records the emulated inbox; fork-inbox
brief marked short-circuited; discovery-model divergence (shipped fan-out vs
global-index target) flagged for confirmation.
- functional-domain/knowledge_roadmap, bdd-testing leaves updated. All doc-debt
settled; lint clean (60 leaves).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Polyfill-enabled features (T02). All NextGraph I/O goes through
@ng-eventually/client (docs/inbox/storeRegistry); no direct @ng-org.
- Shapes: FpMeetingPoint + FpNotification are now real SHEX shapes with ORM
bindings (previously app-TS-only, unpersisted).
- Registration (registration.ts, new): joinEvent persists a Participation +
deposits to the host's inbox + creates a Notification (from = registrant if
connected, anonymous otherwise). leaveEvent deletes the Participation
authoritatively via SPARQL DELETE-WHERE (sweep by event+user AND by subject,
then re-query to confirm) — the désinscription CRDT-resurrection bug is fixed:
the reactive delete is applied only once the broker confirms 0 remaining.
- Public discovery: useNgData fans out over every account's public docs so a
user sees others' public events without a connection (dedup union).
- Cap attribution: createEntityDoc declares the ReadCap (open + makePublic/
grantRead per scope), activating the per-document read filter.
- Protected store (T02.h): the default path now reads/writes shareable domain
entities in the native protected store (did🆖${protected_store_id}) instead
of private — verified openable against the broker — matching the per-wallet
target. Private still anchors the shim/inbox + settings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record the completed T01 migration + validation in the two relevant leaves.
- decision_2026-06-17_eventually-library.md: new dated section "Shim migré
dans la lib — 2026-07-02" — the integration boundary moved from "doc_create
stays on the real ng / shim still in-app" to "everything in the lib; the app
touches @ng-org at runtime only via ngSession". TODO "primitive doc_create/
SPARQL via injected ng" checked done. Namespaces docs/storeRegistry/
isolation/accounts; isolation<->ReadCap = coexist (distinct axes).
- brief_2026-06-15_shared-wallet-shim.md: Status/summary/Direction "shim
in-app" -> "shim in the lib".
Validation captured: lib 36/36 + tsc rc=0; app build + harness bundle OK;
full BDD suite 78 passed / 0 failed / 71 skipped (baseline held).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consume the shim mechanics now living in the lib (docs/storeRegistry/
isolation/accounts) and remove the remaining direct @ng-org runtime imports.
- storeRegistry.ts keeps ONLY the Festipod EntityKind/entityScope mapping,
injects it via configureStoreRegistry({ getSession, normalizeUser }), and
re-exports the lib's storeRegistry.* (callers unchanged). Drops
`import { ng } from '@ng-org/web'`.
- harness-ng.tsx createSmokeDoc now uses docs.docCreate (real injected ng,
no DataCloneError) instead of ng.doc_create. Drops the @ng-org import.
- AccountContext.tsx thin React wrapper over accounts.AccountStore +
normalizeUsername; historical key `festipod.account.username` pinned →
zero behavior change. Context/Provider stay in the app.
- isolation.ts Festipod wrapper over the lib's pure isolation.applyIsolation.
Invariant reached: `grep "from '@ng-org'" src/ | grep -v 'import type'` lists
only ngSession (the configure injection point) + the two documented
test-harness exceptions (auth-setup.tsx, harness.tsx mock). No doc_create
goes through the lib's public proxy. App build + harness-ng bundle OK.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full-suite validation of the merge surfaced 4 failures, all multistore: routing
doc_create through the lib's `ng` proxy (685f6d3) breaks @ng-org/web's iframe
postMessage marshaling — DataCloneError "function could not be cloned" (a JS
Proxy over the iframe-RPC proxy = double proxy).
Fix: storeRegistry.ts and harness-ng.tsx (createSmokeDoc) call doc_create /
SPARQL on the real @ng-org/web `ng` directly again. useShape / init / login /
ReadCap still route through the lib. After the fix the 3 multistore scenarios
pass; full suite = 77 passed, 0 merge regressions.
Integration boundary documented in decision_2026-06-17: the in-app shim's
low-level NextGraph calls stay on the real SDK until storeRegistry moves INTO
the lib (where it would use the injected real ng, no double proxy). Lib TODO:
expose a doc_create/SPARQL primitive that uses the injected ng.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Post-merge audit of main's shared-wallet shim: storeRegistry.ts was the only
runtime path still importing `ng` from @ng-org/web directly, bypassing the lib.
Route it through @ng-eventually/client (the ng proxy forwards doc_create /
sparql_update / sparql_query). Now the only @ng-org runtime imports in the app
are the single injection point (ngSession) + documented exceptions (auth-setup,
mock harness) + generated ORM type-only bindings — the decision_2026-06-17
invariant holds again.
Still in-app, to move into the lib later: storeRegistry, AccountContext, the
isolation filter (distinct from the lib's ReadCap filter).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings 266e335 (staging shared wallet: file-assisted import + multi-browser
e2e) into the ng-eventually branch. Conflicts resolved so both lines of work
coexist and route through the lib where they overlap:
- harness-ng.tsx: combine ReadCap FilterProbe (ours) with main's SmokeProbe/
FanoutProbe; useShape + ng imported from @ng-eventually/client.
- ngSession.ts (auto): our single-injection-point configure() + main's hidden
logoutNg, which uses the lib's ng.
- useShapeWithDefaults.ts (auto): lib useShape + main's { graphs } multistore
scope.
- cucumber.json: single "tags": "not @wip" (both branches added it).
- brief_2026-06-15_shared-wallet-shim: keep main's implemented status; record
that the read filter now lives in the lib (decision_2026-06-17) while the
rest of the shim (storeRegistry/accounts/isolation) is still in-app, slated
to move into the lib.
Build OK; harness-ng bundles. TODO (next): verify all of main's NextGraph
surface routes through @ng-eventually/client (storeRegistry uses ng directly).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "Se désinscrire" e2e wasn't obsolete: verified against the broker that
join reflects in the UI but leave does NOT — the button stays "✓ Je participe"
(>10s). DeepSignalSet.delete() does fire reactivity (touchIterable), so the
real cause is downstream: the deletion doesn't propagate / the item resurrects
via broker sync (the documented CRDT limitation).
- cycle-de-vie-evenement.feature: rewrite the désinscription scenario to be
self-contained (join → leave → "J'y serai" in one session, no cross-scenario
/ persistence dependency), and tag it @wip with an accurate comment.
- cucumber.json: add tags "not @wip" so known-incomplete scenarios document an
expectation without failing the suite (default run: 146 scenarios).
- docs: caveat_participation-deletion records the e2e finding (leave doesn't
reflect in the UI; delete fires reactivity but the item resurrects via sync);
knowledge_cucumber-setup documents @wip = excluded from the default run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stopgap staging multi-user sur wallet partagé (cf. brief_2026-06-15_shared-wallet-shim).
Distribution / import du wallet :
- AccessGateScreen : barrière d'accès ON PAR DÉFAUT (désactivable via
globalThis.__FESTIPOD_ACCESS_GATE_DISABLED__ pour tests/dev). Fournit le FICHIER
.ngw + le mot de passe + un guide en 3 étapes (import assisté sur nextgraph.eu —
le broker hébergé n'autorise pas l'import inline pendant l'auth web-app).
- sharedWallet.ts + build.ts : fichier copié en /shared-wallet.ngw, mot de passe gravé.
- Ancien LoginScreen (/login) retiré ; atterrissage post-login -> /home.
- NextGraphContext : dé-piégeage de l'état "connecting" au retour (pageshow/bfcache).
Couche multistore stopgap : storeRegistry, isolation, AccountContext, FestipodDataContext.
Tests e2e multi-navigateur :
- browserPool + world.openBrowser : contextes frais isolés, 2 axes orthogonaux
(nb de navigateurs × modèle de wallet own/shared).
- @humain : parcours humain complet (télécharge -> importe le fichier sur
nextgraph.eu -> Entrer -> pseudo -> accueil).
- Bypass de la barrière pour @e2e via context.addInitScript.
- Convention @wip exclue via cucumber.json.
Docs (concepts) : nextgraph-platform (knowledge_broker-import-constraint,
decision_2026-06-17_assisted-wallet-import), bdd-testing (knowledge_multibrowser-harness).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Align Festipod's @data read-filter scenario and harness bridge with
ng-eventually's grant→ReadCap refactor: the access unit is the document
(an item's `@graph`), not the item.
- harness-ng.tsx: governDocument(reader, user)/setUser via getCaps()/resetCaps()
(replaces setupReadFilter/setGrantOf); FilterProbe exposes a lazy snapshot()
reflecting the current user without remount.
- read-filter.feature/steps: validate per-document ReadCap on the real
DeepSignalSet — govern the wallet document, grant the cap to another user
→ current user sees 0; current user gets the cap → sees all (all-or-nothing
in mono-store, the faithful behavior). 5/5 steps pass against the broker.
- doctrine: knowledge_stores-permissions records the verified store/document/
repo/ReadCap model (containment by reference, no read-cap inheritance);
decision_2026-06-17_eventually-library updates the access-rights + filter
status to the ReadCap model.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a @data scenario (workshop/read-filter) that enables the lib's read filter on the
real reactive ORM set (via a FilterProbe + setupReadFilter harness helper, granting each
participation to its own user) and asserts useShape returns only the target user's
participations. Validates the trickiest piece — filtering a live DeepSignalSet — against the
broker. @data 9/9. Doc: read filter marked implemented & validated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The app now takes its NextGraph runtime AND types from @ng-eventually/client; the
only place that imports the real @ng-org SDK is ngSession (the single injection point for
configure()). Lifecycle (init/initNg), data (useShape) and types (ShapeType, DeepSignalSet,
NG…) all go through the lib. Test infra (auth-setup, mock harness) and generated ORM
bindings keep a direct @ng-org import (documented). Validated: build, @ui 4/4, @data 8/8
against the real broker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The reactive ORM data-plane now goes through the @ng-eventually/client wrapper
instead of @ng-org/orm directly; ngSession injects the real SDK into the polyfill via
configure(). Currently a transparent passthrough (lib mechanisms still stubbed) →
behavior unchanged. Validated: build, @ui 4/4, @data 8/8 against the real broker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Captures the design worked out this session:
- decision: ng-eventually generic polyfill library (external repo) encapsulates all
multi-user compensation; @ng-eventually/client is SDK-identical, app depends only on it.
- decision: discovery via a single global index fed through its inbox (owned doc,
materialized) — no Group store; index owner = open question (singleton app, deferred).
- knowledge: NextGraph apps/services are mono-user with no global data (corrects the
earlier 'index service with its own wallet' model).
- reconciled shared-wallet-shim brief (per-entity docs, login flow, polyfill terminology),
authorization-matrix (no Group store), data-layer stack (ng-eventually indirection).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Couche compte/login + isolation livrées et vérifiées ; couche multi-document
(storeRegistry) livrée derrière FESTIPOD_MULTISTORE/FESTIPOD_STAGING (OFF par
défaut, mono-store reste le défaut), runtime NG à valider sur broker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Capture the multi-user design exploration as project knowledge + briefs:
- knowledge: NextGraph store types/permissions (+ inbox at protocol, SDK
exposure, local repo path); integration model (iframe, where the verifier
runs, generic JS plumbing, ngd stateful, build-time broker target)
- briefs: multi-store refactor; authorization matrix + query inventory +
derived store partitions; temporary fork to expose the inbox (3 layers:
SDK fork, Coolify self-hosting, Festipod integration; libs via build:ng)
- fix stale @ng-org versions (alpha.11 -> alpha.13) and a broken
decision-record link in data-layer.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The @ng-org/* SDK alpha versions are now published on npm. Switch the
package.json dependencies from .ng-tarballs/*.tgz paths to npm
versions, removing the need for a sibling nextgraph-rs build to
install the project. Makes containerized deploys (Coolify) trivial.
- @ng-org/alien-deepsignals: 0.1.2-alpha.11 (unchanged)
- @ng-org/orm: 0.1.2-alpha.15 → 0.1.2-alpha.18
- @ng-org/shex-orm: 0.1.2-alpha.7 → 0.1.2-alpha.8
- @ng-org/web: 0.1.2-alpha.11 → 0.1.2-alpha.13
scripts/build-ng-packages.sh and the .ng-tarballs/ workflow remain
available for local development against an unreleased nextgraph-rs
build (`.gitignore` keeps the directory ignored).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Port modern clean theme (DM Sans, orange accent, app-* CSS classes)
and screen redesigns from festipod-mockups; replace sketchy Ubuntu
theme. New shared components: BottomNav, EventCover, EventMeetingPoints,
Toast, AvatarStack, Tag, RelevanceIcon.
- Restructure from prototyping shell to real mobile web app:
path-based routing (History API), Gallery/DemoMode/PhoneFrame removed,
Storybook setup for screen/component browsing.
- ConnectScreen ported from mockup (QR-based user connection); routed
at /profile/connect, wired from FriendsListScreen.
- Dev-only auto-seed of NG wallet when empty
(gated on NODE_ENV !== 'production'); bootstrapWallet already
self-checks for non-empty ngSet so safe even in race conditions.
- Render-based @ui test infrastructure: happy-dom + LocalDataProvider +
RouterProvider via src/shared/test-harness/renderHelper.tsx, exposed
on the world as renderedDoc. world.hasText/hasField/hasElement prefer
the rendered DOM and fall back to source for backward compatibility.
- Migrate 25 brittle @ui assertions from regex-on-source to DOM
queries; delete implementation-detail tests (showDuplicateWarning,
importableEvents, importedFrom — anti-patterns per the new contract).
Update feature files where the UI changed: "Mes amis" → "Mon réseau",
"Mes événements à venir" → "À venir" on home, Thématique removed
from create-event wizard, etc.
- Path-based @e2e steps (pushState + popstate dispatch) replacing the
legacy "#/demo/…" hash routing tied to the deleted Gallery.
- Add .project/knowledge/test-layer-contracts.md defining the role of
each test layer (@ui = display with seed data + DOM, @data = mutations
through NG broker, @e2e = critical user journeys) with anti-patterns
and migration consequences.
Test status: 75 passed / 71 skipped (explicit "non implémenté")
/ 2 failed (pre-existing @wip on ngSet.delete() NG ORM limitation).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refactor FestipodDataContext to use only the useShape ORM API:
- Remove ng.sparql_update, sessionPromise, ensureGraphNuri imports
- Use privateNuri (useShape scope) directly as @graph for adds
- Create/join are now synchronous (no async wrapper needed)
- Leave uses ngSet.delete() — known limitation: doesn't persist (@wip)
Add event lifecycle e2e scenarios (cycle-de-vie-evenement.feature):
- Create event via form and verify on home screen
- Created event persists after reconnexion
- Consult event detail from home
- Join an event
- Modify event location and verify
- Leave + persistence tagged @wip (ngSet.delete doesn't persist)
Fix DemoMode external navigation: sync initialScreenId prop changes
to internal state via useEffect (was ignored after first mount).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ngSet.delete() updates the local reactive set but does not persist to the
broker. Use ng.sparql_update() with SPARQL DELETE WHERE to remove RDF triples
directly — the broker sends back a GraphOrmUpdate that reactively removes the
item from the ORM set. The two methods must not be combined as they conflict
in the CRDT.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Writes (doc_create, orm_frontend_update) failed with RepoNotFound because
useShape with did:ng:i scope doesn't open individual repos in the verifier's
cache. Switched to did🆖${session.private_store_id} as both scope and
@graph, matching the expense-tracker-rdf pattern. This opens the private
store repo via orm_start_graph, making it available for subsequent writes.
Also adds wallet login step to ensureAuth so the verifier bootstraps repos
from the remote broker into localStorage on first run.
Key changes:
- useShapeWithDefaults accepts storeNuri param (private store NURI)
- FestipodDataContext.useNgData() passes private store scope
- ensureGraphNuri() simplified: reuse existing @graph or private_store_id
- ngBootstrap uses ensureGraphNuri + flushAndWait between ORM adds
- harness-ng.tsx uses private store scope for test bridge shapes
- hooks.ts: wallet creation logs in to bootstrap verifier repos
- E2e steps for data loading and persistence verification
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add @e2e test layer: real app in broker iframe via Playwright
- Fix broker redirect: conditional auto-init only when inside iframe
- Fix seed data flash: empty data during 'connecting' phase
- Fix Gallery button in iframe: explicit navigate instead of history.back
- Add auth e2e feature scenarios and step definitions
- Update docs: bdd-testing, data-layer-testing, data-layer, AGENTS.md
- Add decision record for conditional NG init approach
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename steps/frontend/ to steps/ui/ across all modules and shared
- Add data-layer test harness (mock + real broker modes) with Playwright
- Add inscription data-layer steps (@data scenarios)
- Add test auth setup script and browser debug script
- Update docs (architecture, BDD testing, data-layer testing)
- Add ADR for headless wallet creation decision
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add NextGraph data layer with @ng-org/orm, SHEX shapes (Event, UserProfile,
Participation), session management, and FestipodDataContext with dual-mode
operation (connected via NextGraph or local seed data)
- Add BrokerBanner and NgStatus components showing connection status
- Refactor to feature-based architecture: organize code by business domain
(event, user, home, auth, workshop, meeting, notification) instead of
technical layer. Modules only import from shared/, never from each other
- Collocate BDD features and step definitions with their modules: event-specific
steps in event/steps/, user steps in user/steps/, shared generic steps remain
in shared/steps/
- Set up multi-layer BDD structure (frontend/backend/e2e steps per module)
- Add project documentation (AGENTS.md, .project/knowledge/)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- EventDetailScreen: person who shared the event is now "Relayé par"
- ProfileScreen/UserProfileScreen: remove role badges from event lists
- FriendsListScreen: Organisateur/Organisatrice → Relayeur/Relayeuse
- Update event data to transition-themed examples
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>