test(@data): align us-7 inscription tests to Option B; fix authParticipationCount

The three us-7 count assertions encoded the OLD increment model (participantCount =
baseline ± 1 via a fictional 'au départ N' step). Under Option B the count is
owner-derived, not baseline±1 and not the joiner's to write, so those lines were
false. Drop them; keep the real @data contract (join persists + participant + in
list; leave is authoritative + gone). Move count convergence to a @data @wip
scenario with an inline rationale (single-session can't derive the absolute count —
shared-inbox accumulation + create-vs-read NURI-form; the @multibrowser reactive
scenario is the real validation).

Fix a harness bug: authParticipationCount enumerated protected docs via the
all-accounts listEntityDocs (returned 0 for a fresh per-scenario virtual account —
a false 0); use the bounded listMyEntityDocs(currentUser,'protected') (the same
read-by-need path the app's idempotence check uses), and poll to absorb index lag.

Full @data suite green: 18 scenarios / 89 steps. Désinscription contract untouched
(caveat_participation-deletion). Build + tsc clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Duchesne
2026-07-07 14:23:25 +02:00
parent 22487ed575
commit 767a18e98c
3 changed files with 80 additions and 37 deletions
+18 -1
View File
@@ -309,7 +309,24 @@ function ConnectedHarness() {
// store-root graph. This stays authoritative (bypasses the reactive set):
// it counts the (event,user) triples actually persisted in the broker.
const reg = await import('../utils/storeRegistry');
const protectedDocs = await reg.listEntityDocs('protected');
// Enumerate the CURRENT account's own protected docs — the read-by-need
// path the APP uses (registration.countUserParticipations →
// listMyEntityDocs), NOT the all-accounts `listEntityDocs` fan-out. Each
// @data scenario runs under a FRESH virtual account (freshScenarioUsername
// in localStorage), whose participation docs live ONLY in that account's
// protected scope index. The all-accounts fan-out (`allAccounts()`) does
// not surface the fresh account here (its registry record isn't in the
// enumerated set), so `listEntityDocs('protected')` returned 0 docs and the
// authoritative count was a false 0 for a participation that provably
// exists. `listMyEntityDocs(currentUser, 'protected')` reads exactly the
// current account's own docs — the same bounded path the app writes/reads
// and the sanctioned non-hanging enumeration. Falls back to the fan-out
// only when no login is present (dev/demo).
let currentUser = '';
try { currentUser = window.localStorage.getItem('festipod.account.username') || ''; } catch { /* opaque origin */ }
const protectedDocs = currentUser
? await reg.listMyEntityDocs(currentUser, 'protected')
: await reg.listEntityDocs('protected');
let total = 0;
for (const g of protectedDocs) {
// Anchored default-graph (no `GRAPH` clause): participations are