Skip to content

refactor(truapi)!: account holders behind HostAccounts - #1303

Closed
pgherveou wants to merge 12 commits into
refactor/account-holder-walletfrom
refactor/account-holder-sso
Closed

pgherveou wants to merge 12 commits into
refactor/account-holder-walletfrom
refactor/account-holder-sso

Conversation

@pgherveou

@pgherveou pgherveou commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Product account operations go through HostAccounts<H> over an AccountHolder on both host roles. ProductAuthority is removed.

Before: each role object keeps its own grants, wallet access and prompts behind ProductAuthority.

                 ┌──────────────────────────────────────────┐
                 │ ProductRuntimeHost                       │
                 ├──────────────────────────────────────────┤
                 │ • validates and normalizes each request  │
                 │ • checks the product's permissions       │
                 │ • prompts the user before signing        │
                 └─────────────────────┬────────────────────┘
                                       │ dyn ProductAuthority
                   ┌───────────────────┴───────────────────┐
                   ▼                                       ▼
┌────────────────────────────────────┐  ┌────────────────────────────────────┐
│ PairingHost  (browser, CLI)        │  │ SigningHost  (iOS, Android, CLI)   │
├────────────────────────────────────┤  ├────────────────────────────────────┤
│ • caches grants over CoreStorage   │  │ • grants in memory only            │
│ • SSO client session to the phone  │  │ • reads root entropy directly      │
│ • prompts before forwarding        │  │ • prompts for its own products     │
│                                    │  │ • paired calls reuse its methods   │
└────────────────────────────────────┘  └────────────────────────────────────┘

After: one HostAccounts<H> implementation; each role picks its account holder H.

                ┌────────────────────────────────────────────┐
                │ ProductRuntimeHost<H>                      │
                ├────────────────────────────────────────────┤
                │ • ProductConnection: adapters, permissions │
                │ • HostSession: login, logout, identity     │
                └──────────────────────┬─────────────────────┘
                                       │ account operations
                ┌──────────────────────▼─────────────────────┐
                │ HostAccounts<H>                            │
                ├────────────────────────────────────────────┤
                │ • one implementation for both host roles   │
                │ • HostGrantStore: kept grants and keys     │
                │ • ProductConsent: account access, prompts  │
                │ • signs with kept keys                     │
                └──────────────────────┬─────────────────────┘
                                       │ AccountHolder
                   ┌───────────────────┴───────────────────┐
                   ▼                                       ▼
┌────────────────────────────────────┐  ┌────────────────────────────────────┐
│ RemoteAccountHolder                │  │ WalletAccountHolder                │
│ (browser, pairing CLI)             │  │ (phone, signing CLI)               │
├────────────────────────────────────┤  ├────────────────────────────────────┤
│ • forwards calls to the phone      │  │ • wallet keys behind with_keys     │
│ • the phone confirms each again    │  │ • issuance, renewal                │
└────────────────────────────────────┘  └────────────────────────────────────┘

Paired request: reaches the phone's wallet through its SSO services, without the phone's HostAccounts.

┌─ Browser: PairingHost ────────────┐      ┌─ Phone: SigningHost ──────────────┐
│ ┌───────────────────────────────┐ │      │ ┌───────────────────────────────┐ │
│ │ HostAccounts                  │ │      │ │ WalletAccountHolder           │ │
│ ├───────────────────────────────┤ │      │ ├───────────────────────────────┤ │
│ │ • confirms or uses kept keys  │ │      │ │ • signs inside with_keys      │ │
│ └───────────────┬───────────────┘ │      │ └───────────────▲───────────────┘ │
│ ┌───────────────▼───────────────┐ │      │ ┌───────────────┴───────────────┐ │
│ │ RemoteAccountHolder           │ │      │ │ SsoAccountHolderService       │ │
│ ├───────────────────────────────┤ │      │ ├───────────────────────────────┤ │
│ │ • wallet call to SSO request  │ │      │ │ • confirms, one per peer      │ │
│ └───────────────┬───────────────┘ │      │ └───────────────▲───────────────┘ │
│ ┌───────────────▼───────────────┐ │ SSO  │ ┌───────────────┴───────────────┐ │
│ │ SsoRequestService             ├────────▶┤ SsoResponderService           │ │
│ ├───────────────────────────────┤ │      │ ├───────────────────────────────┤ │
│ │ • paired session, transport   │ │      │ │ • handshake, drops duplicates │ │
│ └───────────────────────────────┘ │      │ └───────────────────────────────┘ │
└───────────────────────────────────┘      └───────────────────────────────────┘

Wallet and consent:

  • WalletAccountHolder owns the wallet state. Only its private with_keys reads the root entropy, checking the wallet activation under the same lock. Its PersonhoodSigner signs inside with_keys, so personhood entropy never leaves it.
  • ProductConsent decides account access and which reviews a product may skip, runs one permission prompt at a time, and keeps Allow once until restart, lock, wallet switch or a reset of that product.

One host implementation:

  • HostAccounts<H> replaces both ProductAuthority implementations: product access, confirmations, grant acquisition and retention, delegated signing and provider selection exist once. Its kept grants live in a private HostGrantStore.
  • ProductRuntimeHost<H> splits into a ProductConnection (adapters, permissions, channels) and a HostSession (login, logout, identity), and passes account work to HostAccounts. Product code passes its ProductContext and never builds a caller.
  • AutoSigning has one form on every host: the product's //product//{id} key, which the host keeps and signs with.
  • The account holder is the only writer of the ring-VRF registry, and contact-handle and allowance secrets stay behind their owners.
  • PairingHost and SigningHost become role roots. Native allowance keys last one wallet activation (GrantKeeping::Wallet); #1305 persists them.

SSO:

  • RemoteAccountHolder is the paired host's account holder: it turns each wallet call into an SSO request and prompts nothing itself.
  • SsoRequestService owns the paired session (login, selection, persistence, cross-tab sync, cleanup) and the outbound channel, and reports session changes to the HostAccounts that keeps the paired grants.
  • SsoResponderService owns the phone's side: pairing handshake, serve loop and duplicate detection on the Rust transport.
  • Each paired peer gets its own SsoAccountHolderService, bound to the wallet activation that accepted it, with its own cancel list. It confirms each signing, transaction, VRF and allocation request, then calls the wallet directly and never uses the phone's grants.
  • Native wallets open one service per peer with openSsoService; the host runtime no longer has handleSsoRequest. The iOS SSO coordinator is updated in this PR.

@pgherveou
pgherveou added this pull request to stack #1304 October 7, 2026 14:53
@github-actions github-actions Bot added documentation Improvements or additions to documentation rfc rust Pull requests that update rust code host-ios Touches the iOS host tree host-android Touches the Android host tree labels Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

This pull request touches an app, which is not built by default. Add a label for each build you want:

  • iOS simulator build, ios-simulator-build: builds the iOS app, runs its tests and attaches a build for the iOS Simulator on a Mac.
  • iOS device build, ios-device-build: attaches a signed build that installs on a registered iPhone or iPad.
  • Android build, android-device-build: attaches an APK that installs on an Android phone or an emulator.

Each starts as soon as it is added and follows the branch from then on.

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Bundle size report

Compared with main at 10a36af.

Raw Gzip Brotli
truapi-host 7.94 MiB (+76.2 KiB, +0.9%) 5.68 MiB (+27.1 KiB, +0.5%) 5.40 MiB (+18.9 KiB, +0.3%)
truapi-provider 4.03 MiB 1.27 MiB 960.2 KiB
truapi 6.29 MiB 890.4 KiB 729.2 KiB
Total 18.27 MiB (+76.2 KiB, +0.4%) 7.82 MiB (+27.1 KiB, +0.3%) 7.05 MiB (+18.9 KiB, +0.3%)

WebAssembly modules

Raw Gzip Brotli
truapi-host/wasm/web/truapi_server_bg.wasm 2.83 MiB (+76.2 KiB, +2.7%) 1010.6 KiB (+27.1 KiB, +2.8%) 759.9 KiB (+18.9 KiB, +2.6%)
truapi-host/wasm/web/truapi_verifiable_bg.wasm 4.89 MiB 4.64 MiB 4.61 MiB
truapi-provider/truapi_provider_bg.wasm 3.99 MiB 1.26 MiB 952.4 KiB
Changed files (1)
Raw Gzip Brotli
truapi-host/wasm/web/truapi_server_bg.wasm 2.83 MiB (+76.2 KiB, +2.7%) 1010.6 KiB (+27.1 KiB, +2.8%) 759.9 KiB (+18.9 KiB, +2.6%)

Commit: 6bd6245

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

CI Status: 24 required jobs green, 21 passed and 3 skipped by path filter.

All job results
job result
android-bindings success
bundle-size success
changes success
changeset-guard success
cli-package success
codegen success
e2e skipped
explorer success
headless-install success
host-android-bindings success
host-android-detekt success
host-wasm success
ios-bindings success
ios-swift success
licenses success
playground success
provider-android-bindings skipped
release-guard success
rust success
ts-client success
ts-debugger success
ts-host success
wasm-provider success
workflow-lint skipped

Signing credentials: failure as of 2026-10-13, a release may fail

Commit 6bd6245b · run log

@pgherveou
pgherveou force-pushed the refactor/account-holder-sso branch from 340cc4e to b2c9552 Compare October 12, 2026 10:25
@pgherveou pgherveou changed the title refactor(rust)!: bind SSO account holder adapters refactor(truapi)!: account holders behind HostAccounts Oct 12, 2026
@pgherveou
pgherveou force-pushed the refactor/account-holder-sso branch from b2c9552 to 6816dde Compare October 12, 2026 13:45
@pgherveou
pgherveou force-pushed the refactor/account-holder-sso branch from 6bd6245 to eaadd22 Compare October 14, 2026 10:37
@pgherveou

Copy link
Copy Markdown
Collaborator Author

Collapsed into #1302, which carries this work as separate commits. The branch stays as it is, and a backup is in backup/account-holder-*-2026-10-14-collapse.

@pgherveou pgherveou closed this Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation host-android Touches the Android host tree host-ios Touches the iOS host tree rfc rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant