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.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: caveat
|
||||
summary: The wallet password is captured at the EVALUATION of src/shared/utils/sharedWallet.ts; a value set after that first import is never re-read — a missing one used to yield AccessGateScreen's error block, now it makes ensureIdentity() throw and the app render nothing at all, silently
|
||||
last_checked: 2026-08-10
|
||||
summary: The wallet password is captured at the EVALUATION of src/shared/utils/sharedWallet.ts — a value set after that first import is never re-read, and the fetch that sets it must never be gated on NODE_ENV (production serves from src/). Missing it: ensureIdentity() throws, AuthGate shows the reason.
|
||||
last_checked: 2026-08-16
|
||||
---
|
||||
|
||||
# Pitfall: set the wallet-password global BEFORE the module is first imported
|
||||
@@ -15,8 +15,8 @@ The contract requires a deployment to **serve a wallet file and pass its URL and
|
||||
## Impact — if I touch X, Y breaks
|
||||
|
||||
- **Static import = trap.** A static `import` reaching `ngSession.ts` (hence `sharedWallet.ts`) from an entry point that sets the global itself is **hoisted above the assignment** → empty password → the failure mode above, with no JS error at the import site to signal it. The remedy is a **dynamic import** (`await import(...)`) executed after setting the global.
|
||||
- **The real entry point that must get this right**: the frontend served from `src/` (`src/app/frontend.tsx` fetches `/festipod-config.json`, sets the global, then imports `App` dynamically — mechanics in `tech-stack` → [[knowledge_build-pipeline]]). A bundle produced by `build.ts` is **not** concerned: there the value is inlined by `define`.
|
||||
- **The real entry point that must get this right**: the frontend served from `src/` (`src/app/frontend.tsx` fetches `/festipod-config.json`, sets the global, then imports `App` dynamically — mechanics in `tech-stack` → [[knowledge_build-pipeline]]). That fetch may be skipped on **one** condition: the global is already set, which only a `build.ts` bundle's `define` does. **Never on an `NODE_ENV` test** — this project's production serves from `src/` exactly like dev, so gating the fetch on "production" is what removed the wallet from the deployed app and left it unable to sign anybody in.
|
||||
- **`@ui` reaches the module too, but harmlessly today.** `screens/index.ts` eagerly imports every screen including `SettingsScreen`, which imports `ngSession.ts` — so any `@ui` test already evaluates `sharedWallet.ts` with the global unset. This does not currently break anything because no `@ui` path calls `ensureIdentity()` (`renderScreen()` bypasses `AuthGate`/`NextGraphProvider` entirely); see `bdd-testing` → [[knowledge_ui-layer]] for the detail and for what would make it stop being harmless.
|
||||
- **Operations**: a server without `FESTIPOD_SHARED_WALLET_PASSWORD` now fails **silently** (blank page, console-only) rather than with a screen saying so — worth knowing when diagnosing "the app shows nothing."
|
||||
- **Operations**: a server without `FESTIPOD_SHARED_WALLET_PASSWORD` cannot sign anyone in, and it **says so** — `ensureIdentity()` rejects and `AuthGate` renders its named error panel carrying the reason. Verified live on a rejected sign-in: a refusal shows the reason, not a blank page (`bdd-testing` → [[cookbook_live-probe]]). The failure mode still worth fearing is the **silent** one: a promise that never settles either way renders nothing at all and logs nothing — `app-architecture` → [[caveat_boot-unverified-outside-broker]].
|
||||
|
||||
**Verified (2026-08-10)**: capture at evaluation time in `src/shared/utils/sharedWallet.ts`; the `sharedWallet: hasSharedWallet() ? {...} : undefined` branch in `ngSession.ts`'s `configure()` call; the `throw` in `ensureIdentity()` when no `sharedWallet` config is present; `AuthGate`'s `.catch(err => console.error(...))` with no fallback UI.
|
||||
|
||||
Reference in New Issue
Block a user