init() de @ng-org/web redirige vers le broker en première instruction, dès qu'on est en tête. L'application appelait donc init() au chargement du module, la page partait, et ensureIdentity() ne s'exécutait jamais : la barrière n'apparaissait pas, ?ng-id= restait absent de l'URL remise au broker, et un primo-arrivant se retrouvait devant la page de connexion sans portefeuille et sans moyen d'en obtenir un — sans la moindre erreur. Appeler ensureIdentity() avant init() ne marchait pas non plus : il attend la session, que seul le callback d'init() résout. Cycle vérifié empiriquement. La cause n'était ni l'ordre ni la redirection, mais une confusion dans ensureIdentity() entre deux actes de nature différente — régler qui est l'utilisateur (barrière, URL, stockage : aucune session) et se connecter (session requise). settleIdentity() porte le premier ; le wrapper init() du polyfill l'attend avant de déléguer. L'invariant d'ordre est ainsi porté par la composition, pas par une consigne d'ordre d'appel que personne ne lit. Piège trouvé et épinglé en écrivant les tests : init() et ensureIdentity() dans le même tick montaient deux barrières, l'utilisateur répondait à l'une et l'autre ne se résolvait jamais. Le règlement en vol est désormais partagé.
1.8 KiB
Doc-debt — app-contract
Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file. One block = one "big change":
why+files+verify(leaves to review).
The broker redirect is stated as the application's obligation, and it is not
why — contract_polyfill-surface.md lists, under ### Deployment requirements, that the application must "be opened through the broker redirect". No such obligation belongs to the caller: the redirect is a step of the shared-wallet sign-in, which lives in this package (access-gate.ts, "the whole shared-wallet sign-in, moved out of consumer applications"). An application carrying it would have to know there is a broker, an iframe, and a redirect — three things the target SDK will never show it, and three things it would have to delete at migration.
The clause was written from an absent implementation: nothing in src/ navigates to the redirect today, and that gap was recorded as a division of roles. rule_no-divergence-from-nextgraph forbids exactly that inference.
files — the clause is in the contract; the fix is in the package: ensureIdentity() triggers the redirect itself once the identity is settled and ?ng-id= is written into the URL, and does nothing when already inside the iframe.
verify — contract_polyfill-surface.md (### Deployment requirements keeps only the wallet file/password and the ensureIdentity() await), knowledge_what-an-app-deletes-at-migration.md (the redirect is one more thing that evaporates), _overview.md if the surface list changes.
- TOUCHED packages/polyfill/src/surface/lifecycle.ts @2026-08-11 (session f93872b5-293a-4916-a353-181409a96d42)
- TOUCHED examples/notebook/app.ts @2026-08-11 (session f93872b5-293a-4916-a353-181409a96d42)