Skip to content

v0.13.0

Choose a tag to compare

@johnthecat johnthecat released this 20 Sep 07:08
· 15 commits to main since this release
561a954

A rewrite of everything below the public API. The host no longer speaks the @novasamatech/host-container protocol — it runs the TrUAPI core itself, truapi-server compiled to WebAssembly in a Web Worker. Both sides of the wire move together, so a product must be on @parity/truapi 0.17 and boot through @parity/truapi/sandbox. A product on the old protocol will not connect at all.

Still no network, no node, no Docker: the People chain is an in-page loopback statement store, and the host mints both halves of the SSO session at boot.

Upgrading

Grep your tests for these — most are silent if you miss them.

  • productAccounts is keyed by the bare product id. { 'myapp.dot/0': 'bob' }{ 'myapp.dot': 'bob' }. A per-index key is now rejected with an error naming the replacement, and one entry moves every indexed account of that product together.
  • Any test pinning a product-account address must re-read it. The core derives index n as a soft child of the product subtree, not the hard junction //Selected//dotnsId/n. Root dev accounts are unchanged — //Alice is still 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.
  • Signing is an SSO round trip, not a synchronous callback. Tests that await a signature already work; tests that read getSigningLog() immediately after triggering an action must now await the product's own promise first.
  • Chat requires executionKind: 'Worker'. The core denies every Chat entry point for App and Widget.
  • accounts[].uri accepts only hard junctions, and the roster's first entry is the one active signing identity. switchAccount now resolves names against the roster instead of synthesising //Name.
  • Removed controls: the statement-store, login and payment groups, plus setEnforcePermissions. Removed types: LoginBehavior, PaymentLogEntry, PaymentTopUpBehavior, StatementSubmissionLogEntry.
  • Renamed: clearChatState()clearChat().
  • injectChatAction is async and takes ChatActionInput.

Overriding host conditions

The headline addition: a test can now set what the host reports and how it decides, live or before the product's first frame.

Two families, named consistently — get<Thing> / set<Thing> / seed<Thing> / clear<Thing> for ambient data, and set<Thing>Behavior plus get<Thing>Log / clear<Thing>Log for decisions. Ambient data covers theme, locale, feature support, the supported chain set, product storage, chat rooms and bots, and device-permission status; decisions cover permissions, user confirmation, navigation and notifications. Passing undefined to a per-key setter restores what the host would otherwise report.

initialState and behaviors on createTestHostServer and the Playwright fixture apply the same overrides before the product loads, so a product that reads theme or locale during startup can be tested on that path. An unknown status or behaviour mode throws at boot, naming the value.

Two limitations, both documented: product-storage keys must be replayed exactly as getProductStorage() reports them (the core namespaces them per product), and the function form of a behavior works in-page only — the Playwright fixture's setters take 'approve-all' | 'reject-all', because a function cannot cross page.evaluate.

See Overriding host conditions for the full table.

Also added

  • executionKind ('App' | 'Widget' | 'Worker', default 'App') on the server and the fixture.
  • getChainStatus() alongside getConnectionStatus() — the host's own session, as distinct from the product's connection. Signing travels over the session, so a switch that leaves it 'disconnected' means no signature is coming.
  • NetworkConfig.chain — a network's protocol role, reported through supportedChains(). A network that omits it is left out rather than labelled by guesswork.

Fixed

Four of these blocked signing outright, and each was invisible from the test suite that passed over it:

  • statement_submit was rejected by the core, which blocked ALL signing. The loopback store replied with the bare string "new"; the core reads a field, so every SSO request died before a signing request ever reached the responder.
  • An indexed product account was reported under one key and signed for under another — a product's own signature did not verify against its own address. Now verified against schnorrkel's own pinned vector, not just against itself.
  • The AutoSigning capability was refused as an invalid subtree secret. @scure/sr25519 hands out the cofactor-multiplied encoding; schnorrkel's SecretKey::from_bytes takes only the canonical one.
  • Topic filters were parsed under the wrong key spelling, so a real filter matched every statement and matchAny was silently narrowed to matchAll.
  • featureSupported denied the one chain the host always serves — the in-page People loopback, which every signature travels over.
  • Switching to a custom account signed with the wrong key, silently ignoring the configured URI.