feat: le polyfill possède la session et la normalisation des identités

Pour démarrer, une application devait écrire une promesse autour du callback
d'init(), attraper l'événement loggedin, puis fournir un thunk getSession qui
dépiaute session_id et les trois identifiants de store dans notre forme. Plus un
normalizeId. C'est précisément la plomberie que ce paquet existe pour absorber :
chaque application la réécrirait à l'identique, et c'est elle qui a produit deux
défauts aujourd'hui — un blocage et un partage cassé en silence.

En amont, une session est RENDUE ; une application n'en assemble jamais une à
partir de champs bruts. Et les identités virtuelles sont une invention du
polyfill, donc leur normalisation lui appartient.

Le wrapper init() enveloppe désormais le callback de l'appelant : il capture
l'événement, en dérive la session, puis appelle le callback avec le même
événement. Le paquet n'appelle jamais init de sa propre initiative — il
l'enveloppe. Sans callback, il capture quand même.

getSession et normalizeId quittent la surface publiée. Le chemin d'injection
reste pour les harnais, mais inatteignable depuis l'entrée : vérifié par un
import à l'exécution et par un configure() refusé à la compilation.

Défaut trouvé et corrigé en route : le broker envoie session_id en NOMBRE, et le
convertir en chaîne faisait refuser tous les appels par le binding wasm. La
valeur ne fait que transiter, elle est relayée telle quelle. Reste que toute la
chaîne la type string — inexactitude antérieure à ce commit, à traiter à part.

Une application écrit maintenant : configure({ ng, useShape, init, sharedWallet }).
This commit is contained in:
Sylvain Duchesne
2026-08-12 17:39:12 +02:00
parent 7a4d9b492f
commit cc8a95d303
20 changed files with 501 additions and 141 deletions
+15 -5
View File
@@ -35,6 +35,7 @@ import * as registryInternals from "../src/shared-wallet/account-registry";
// the reason `setCurrentUser` / `configureStoreRegistry` are no longer published. It
// reaches them by their internal path, like the rest of its machinery.
import {
adoptCurrentUser,
configureStoreRegistry,
setCurrentUser,
getCaps,
@@ -116,14 +117,23 @@ configure({
* hand the page to the broker (`surface/lifecycle.ts`). A page with no identity would
* raise the barrier instead and never hand over, so the harness supplies one.
*
* Set BEFORE `configureStoreRegistry` deliberately: until the registry is wired,
* `setCurrentUser` fires no connection work (`bootstrap.ts`), so this costs the batch
* neither an account nor a broker round-trip. Every check that cares about identity sets
* its own anyway — this one is only what the page opened as.
* Recorded with `adoptCurrentUser`, which names the identity and stops there — the
* session-free half, the same one the access gate settles with (`bootstrap.ts`). Naming it
* through `setCurrentUser` would FIRE the connection work: it costs the batch an account
* lookup and a broker round-trip for a boot identity nothing reads, and it registers a
* connection in flight for a user that does not exist. It used to fire nothing here for an
* incidental reason — the registry was still unwired at this line — and `configure` wires
* it now, so the intent is stated by the call instead of by the ordering. Every check that
* cares about identity sets its own anyway; this one is only what the page opened as.
*/
const BOOT_IDENTITY = "e2e-harness";
setCurrentUser(BOOT_IDENTITY);
adoptCurrentUser(BOOT_IDENTITY);
// The harness keeps its OWN route to the session, substituted through the internal wiring
// path AFTER `configure` has pointed the registry at the package's. Not redundancy: the
// checks below tear a session down and start another (`session_stop` + `session_start`, the
// reconnection cold-start), and only this page knows about the second one — the package's
// holder is fed by `init()`'s callback, which the broker fires once per page.
configureStoreRegistry({
// The registry (+ subscribe/inbox/read-model) reach the session
// through this. It resolves once the broker connects.