Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
fbf8ee1
feat(polkavm): vendor Chat v2 host authority
replghost Sep 10, 2026
3e1b681
test(host): smoke published Chat product
replghost Sep 10, 2026
c3aaa9f
Merge verified partitioned JIT and clipboard runtime from PR185
replghost Sep 10, 2026
824581c
Merge PR185 cold guest activation fix into Chat runtime integration
replghost Sep 10, 2026
276e06a
Merge conflict-resolved PolkaVM integration into Chat host
replghost Sep 10, 2026
2e5df47
Merge concurrent Chat integration refresh
replghost Sep 10, 2026
fc96553
Merge remote-tracking branch 'origin/feat/pvm-wasm' into feat/chat-v2…
replghost Sep 10, 2026
fe98341
feat(polkavm): refresh Chat authority runtime
replghost Sep 10, 2026
0577a4d
feat(polkavm): provide secure guest randomness
replghost Sep 11, 2026
ce2a625
fix(truapi): forward Chat statement proofs over SSO
replghost Sep 11, 2026
45d47b3
Merge remote-tracking branch 'origin/feat/pvm-wasm' into feat/chat-v2…
replghost Sep 12, 2026
c371777
fix(polkavm): keep refreshed runtime assets atomic
replghost Sep 12, 2026
d02244c
style(ui): format camera controls
replghost Sep 12, 2026
412038f
fix(ui): satisfy strict camera control lint
replghost Sep 12, 2026
073e78b
Merge commit '5ae09546' into integrate/touch-controls-chat
replghost Sep 12, 2026
0dc0797
Merge remote-tracking branch 'origin/feat/pvm-wasm' into integrate/to…
replghost Sep 12, 2026
3c6dc70
chore(deploy): support approved Chat branch deployments without new PRs
replghost Sep 12, 2026
587c4b7
Restore PR226 Chat stack above the runtime-only PR185 branch
replghost Sep 12, 2026
61d6152
refactor(chat): isolate browser wallet above Chat integration
replghost Sep 12, 2026
8392087
Merge current runtime base while preserving Chat host package set
replghost Sep 12, 2026
c74dd39
Merge wallet-backed PolkaVM base into Chat integration
replghost Sep 13, 2026
a7f6f7e
Merge branch 'integrate/wallet-base-runtime' into integrate/wallet-ba…
replghost Sep 13, 2026
b5ef59b
merge: update PolkaVM runtime base
replghost Sep 13, 2026
722058b
merge: refresh PolkaVM runtime base
replghost Sep 13, 2026
e0ff693
Merge branch 'integration/pvm-wallet-prereqs-20260913' into integrati…
replghost Sep 14, 2026
6678e3f
Merge branch 'integration/pvm-wallet-prereqs-20260913' into integrati…
replghost Sep 14, 2026
e2c6e19
Merge branch 'integration/pvm-wallet-prereqs-20260913' into integrati…
replghost Sep 14, 2026
15de596
Merge branch 'integration/pvm-wallet-prereqs-20260913' into integrati…
replghost Sep 14, 2026
9bee3e9
Merge wallet identity proxy deployment through PolkaVM into Chat
replghost Sep 14, 2026
343ef55
Merge branch 'integration/pvm-wallet-prereqs-20260913' into integrati…
replghost Sep 14, 2026
47564aa
Merge branch 'integration/pvm-wallet-prereqs-20260913' into integrati…
replghost Sep 14, 2026
5c10464
test(chat): handle automatic sign-in in product smoke
replghost Sep 14, 2026
7e4d0c4
fix(chat): inherit activation-first wallet and confirmation UX
replghost Sep 15, 2026
a144ce7
fix(chat): inherit complete base SDK packaging
replghost Sep 15, 2026
b6c894e
Merge branch 'integrate/wallet-runtime-followup-20260914' into integr…
replghost Sep 15, 2026
5f942fb
Merge branch 'integrate/wallet-runtime-followup-20260914' into integr…
replghost Sep 15, 2026
b211222
Merge wallet reload display hydration through runtime into Chat
replghost Sep 15, 2026
ad2624d
fix: vendor rebuilt Chat authority runtime and matching client
replghost Sep 15, 2026
7a67a6e
Merge generic runtime fixes while preserving the matched Chat package…
replghost Sep 15, 2026
9dd37be
Merge branch 'integrate/wallet-runtime-followup-20260914' into integr…
replghost Sep 15, 2026
4eed300
Refresh Chat browser packages for SDK 0.16
replghost Sep 15, 2026
0c80f2c
Merge the SDK 0.16 browser migration into Chat
replghost Sep 15, 2026
995a871
Pin the verified SDK 0.16 Chat source
replghost Sep 15, 2026
8d0dfaa
Merge final SDK provenance and signing review presentation
replghost Sep 15, 2026
7530936
Merge remote-tracking branch 'origin/feat/chat-v2-host-runtime' into …
replghost Sep 15, 2026
7881826
Merge remote-tracking branch 'origin/feat/pvm-wasm' into fix/chat-aut…
replghost Sep 15, 2026
a409e66
Merge remote-tracking branch 'origin/feat/pvm-wasm' into fix/chat-aut…
replghost Sep 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Deploy

on:
workflow_dispatch:
pull_request:
types: [labeled, synchronize]
push:
Expand Down Expand Up @@ -34,6 +35,11 @@ jobs:
# Environments a PR label is allowed to target (development only).
ALLOWED='["paseoli.dev","paseo.fyi"]'
case "$EVENT_NAME" in
workflow_dispatch)
echo 'environments=["westendli.dev"]' >> "$GITHUB_OUTPUT"
echo 'smoke_environments=["westendli.dev"]' >> "$GITHUB_OUTPUT"
echo "ref=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
;;
release)
echo 'environments=["paseo.li"]' >> "$GITHUB_OUTPUT"
echo "ref=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
Expand Down
13 changes: 13 additions & 0 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,16 @@ It requires successful HTTP status and a JSON object containing a 32-byte hex
with status 200 fails. No authentication challenge, token, or username is
created by the smoke check. Unset `DEPLOY_NGINX` to return to dist-only CI;
this does not remove an already installed proxy.

## Deploy a retained feature branch

The deployment workflow can deploy a branch to `westendli.dev` without opening
or merging a pull request:

```sh
gh workflow run deploy.yml --ref feat/chat-v2-host-runtime
```

Manual dispatch deploys the selected branch commit only to `westendli.dev`.
It runs the same quality gate, protected-environment approval, production build,
and published-product smoke checks as a labeled PR deployment.
18 changes: 17 additions & 1 deletion apps/host/tests/smoke/polkavm-products.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ interface ProductSmoke {
interaction?:
| "gameplay-pointer-capture"
| "pointer-motion"
| "host-frame-handshake";
| "host-frame-handshake"
| "host-sign-in";
}

const products: readonly ProductSmoke[] = [
Expand All @@ -41,6 +42,14 @@ const products: readonly ProductSmoke[] = [
nonzeroAudio: true,
interaction: "gameplay-pointer-capture",
},
{
label: "egui-chat",
profile: "tri2d",
keys: [],
audio: false,
nonzeroAudio: false,
interaction: "host-sign-in",
},
{
label: "egui-app-lab",
profile: "tri2d",
Expand Down Expand Up @@ -176,6 +185,13 @@ async function smokeProduct(
await expect(canvas).toHaveAttribute("data-polkavm-gpu", "ready");
}

if (product.interaction === "host-sign-in") {
const signIn = page.locator("#auth-modal-backdrop");
await expect(signIn).toBeVisible({ timeout: 30_000 });
await signIn.getByRole("button", { name: "Cancel", exact: true }).click();
await expect(signIn).toBeHidden();
}

const framesBefore = await counter(canvas, "data-polkavm-frames");
const updatesBefore = await counter(canvas, "data-polkavm-updates");
const audioBefore = await counter(canvas, "data-polkavm-audio-samples");
Expand Down
22 changes: 22 additions & 0 deletions packages/ui/src/host-callbacks/UserConfirmation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
AccountAccessReview,
AccountAliasReview,
ChatAuthorityReview,
CreateProofReview,
CreateTransactionReview,
IdentityDisclosureReview,
Expand Down Expand Up @@ -186,6 +187,8 @@ function confirmationDisplay(
case "IdentityDisclosure":
case "ProductSubtree":
return { fields: createRequestingProductFields(review.value) };
case "ChatAuthority":
return { fields: createChatAuthorityFields(review.value) };
case "ResourceAllocation":
return { fields: createResourceAllocationFields(review.value) };
}
Expand Down Expand Up @@ -373,6 +376,19 @@ function createRequestingProductFields(
return [{ label: "Requesting product", value: review.productId }];
}

function createChatAuthorityFields(
review: ChatAuthorityReview,
): ConfirmationField[] {
return [
{ label: "Requesting product", value: review.productId },
{
label: "Permission",
value:
"Bind its device account to your wallet Chat identity and encrypt or decrypt Chat routing data",
},
];
}

function formatResource(resource: AllocatableResource): string {
return resource.tag === "SmartContractAllowance"
? `SmartContractAllowance / ${formatDerivationIndex(resource.value)}`
Expand Down Expand Up @@ -428,6 +444,12 @@ function confirmationCopy(review: ModalReview): ConfirmationCopy {
action: "Allow",
cancelAction: "Deny",
};
case "ChatAuthority":
return {
title: "Chat Identity Authority",
action: "Allow",
cancelAction: "Deny",
};
case "ProductSubtree":
return {
title: "Product Account",
Expand Down
9 changes: 8 additions & 1 deletion packages/ui/src/permission-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { blockingModalAbortError } from "./blocking-modal-queue";
// Shows a confirmation dialog when a product requests a permission the
// host can actually gate: the Permissions-Policy-backed device
// variants (Camera, Microphone, Location, Bluetooth, NFC, Clipboard,
// Biometrics, Notifications), identity disclosure,
// Biometrics, Notifications), Chat identity authority, identity disclosure,
// and the internal submitted gates (ChainSubmit, PreimageSubmit,
// StatementSubmit). `OpenUrl` is auto-granted at the container level and never
// reaches this modal.
Expand All @@ -34,6 +34,8 @@ export const PERMISSION_DESCRIPTIONS: Record<
NFC: "Read and write nearby NFC tags",
Clipboard: "Read text and data from your clipboard",
Biometrics: "Authenticate with a platform passkey or biometric prompt",
ChatAuthority:
"Bind this app's device account to your wallet Chat identity and encrypt or decrypt Chat routing data",
IdentityDisclosure: "Share your primary DotNS identity with this app",
ChainSubmit: "Sign and submit on-chain transactions on your behalf",
PreimageSubmit: "Store preimage data on-chain via the Bulletin network",
Expand Down Expand Up @@ -76,6 +78,11 @@ const PERMISSION_ICONS: Record<EnforceablePermissionName, string> = {
'<path d="M12 11a4 4 0 0 0-4 4v2a4 4 0 0 0 8 0v-2a4 4 0 0 0-4-4z"/>' +
'<path d="M6 11a6 6 0 0 1 12 0"/>' +
'<path d="M4 11a8 8 0 0 1 16 0"/></svg>',
ChatAuthority:
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
'<circle cx="8" cy="8" r="4"/>' +
'<path d="M2 21a6 6 0 0 1 12 0"/>' +
'<path d="M17 11l2 2 4-4"/><path d="M19 13v7"/></svg>',
IdentityDisclosure:
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
'<circle cx="12" cy="8" r="4"/>' +
Expand Down
5 changes: 5 additions & 0 deletions packages/ui/src/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type DevicePermissionName = HostDevicePermissionRequest;
export type PermissionName =
| DevicePermissionName
| "ChainSubmit"
| "ChatAuthority"
| "IdentityDisclosure"
| "PreimageSubmit"
| "StatementSubmit";
Expand Down Expand Up @@ -103,6 +104,7 @@ export const ALL_PERMISSIONS: readonly {
{ name: "NFC", label: "NFC" },
{ name: "Clipboard", label: "Clipboard" },
{ name: "Biometrics", label: "Biometrics" },
{ name: "ChatAuthority", label: "Chat Identity Authority" },
{ name: "IdentityDisclosure", label: "Identity Disclosure" },
{ name: "ChainSubmit", label: "Sign Transactions" },
{ name: "PreimageSubmit", label: "Submit Preimages" },
Expand Down Expand Up @@ -163,6 +165,9 @@ export function authorizationRequest(
value: { permission: { tag: permission } },
};
}
if (permission === "ChatAuthority") {
return { tag: "ChatAuthority" };
}
if (permission === "IdentityDisclosure") {
return { tag: "IdentityDisclosure" };
}
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/topbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,8 @@ const PERM_ICONS: Record<string, string> = {
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>',
Biometrics:
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 11a4 4 0 0 0-4 4v2a4 4 0 0 0 8 0v-2a4 4 0 0 0-4-4z"/><path d="M6 11a6 6 0 0 1 12 0"/><path d="M4 11a8 8 0 0 1 16 0"/></svg>',
ChatAuthority:
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="4"/><path d="M2 21a6 6 0 0 1 12 0"/><path d="M17 11l2 2 4-4"/><path d="M19 13v7"/></svg>',
IdentityDisclosure:
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/><path d="M19 3v4h4"/></svg>',
ChainSubmit:
Expand Down
16 changes: 8 additions & 8 deletions vendor/truapi-host.lock.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
{
"schemaVersion": 1,
"upstreamRepository": "https://github.com/paritytech/host-rust-core",
"upstreamBranch": "feat/pvm-app-runtime",
"upstreamRevision": "a3ede1f1d03690c59ac224d0fe258be1f71f5dc6",
"pullRequest": "https://github.com/paritytech/host-rust-core/pull/540",
"upstreamBranch": "feat/chat-v2-product-authority",
"upstreamRevision": "48810675e2258ea7de6c3539d000cbaa2ea83bca",
"pullRequest": "https://github.com/paritytech/host-rust-core/pull/709",
"packages": {
"vendor/truapi": {
"name": "@parity/truapi",
"version": "0.16.0",
"sourceArchiveSha256": "073ad922a1eb823df33bf313a8db69389a565efe84416c3782e120235cd998cc",
"clientSha256": "19a874466c16a39684b30c39d495a9e3b4e290cc86db51c99ec9ad1bb1c9e77f"
"sourceArchiveSha256": "488f54abb90af7398bd2c06660204a46a2b2976cf8d94b30f26401e11cb2a235",
"clientSha256": "85b4f91d4a08a68fa10a9dd5edf680606b0925e095f1dfdaaed3d95706dddd4e"
},
"vendor/truapi-host": {
"name": "@parity/truapi-host",
"version": "0.16.0",
"sourceArchiveSha256": "e1ae2470ae254aa44d3be4f124c48713af3b5aa82f9d05a7d707fd01ced3dac7",
"sourceArchiveSha256": "5cebe9948792c55527756af062efdfb6efb66ed566a4a3d2991acc3bad13920b",
"dependencyOverride": "@parity/truapi=file:../truapi",
"wasmSha256": "42438b6267a5cd0ff1c77fdb6956c5d64b16747e01012a5d82a82da9e03a949d"
"wasmSha256": "77449c559ec094be981a3805ca40edf64e611325c2478305f2ec01410c59f112"
}
},
"wasmUpstreamRevision": "a3ede1f1d03690c59ac224d0fe258be1f71f5dc6"
"wasmUpstreamRevision": "48810675e2258ea7de6c3539d000cbaa2ea83bca"
}
27 changes: 27 additions & 0 deletions vendor/truapi-host/dist/generated/host-callbacks.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ export type AuthState =
tag: "Authenticating";
value?: undefined;
};
/**
* Review shown before a product binds or uses wallet-held Chat identity authority.
*/
export interface ChatAuthorityReview {
/**
* Product requesting the Chat identity operation.
*/
productId: string;
}
/**
* Core-owned host-private storage slots. Products never address these slots;
* the host chooses the backing store for each slot.
Expand Down Expand Up @@ -342,6 +351,13 @@ export type PermissionAuthorizationRequest =
value: {
targetProductId: string;
};
}
/**
* Product-scoped permission to bind and use wallet-held Chat identity authority.
*/
| {
tag: "ChatAuthority";
value?: undefined;
};
/**
* Authorization status for a permission request.
Expand Down Expand Up @@ -613,6 +629,13 @@ export type UserConfirmationReview =
| {
tag: "ProductSubtree";
value: ProductSubtreeReview;
}
/**
* Allow a product to bind and use wallet-held Chat identity authority.
*/
| {
tag: "ChatAuthority";
value: ChatAuthorityReview;
};
/**
* Review shown before a product asks to access another product account.
Expand All @@ -628,6 +651,10 @@ export declare const AccountAliasReview: S.Codec<AccountAliasReview>;
* and never derive auth UI from any other signal.
*/
export declare const AuthState: S.Codec<AuthState>;
/**
* Review shown before a product binds or uses wallet-held Chat identity authority.
*/
export declare const ChatAuthorityReview: S.Codec<ChatAuthorityReview>;
/**
* Core-owned host-private storage slots. Products never address these slots;
* the host chooses the backing store for each slot.
Expand Down
8 changes: 6 additions & 2 deletions vendor/truapi-host/dist/generated/host-callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const AccountAliasReview = S.lazy(() => S.Struct({ callingProductId: S.st
* and never derive auth UI from any other signal.
*/
export const AuthState = S.lazy(() => S.TaggedUnion({ Disconnected: S._void, Pairing: S.Struct({ deeplink: S.str }), Connected: SessionUiInfo, LoginFailed: S.Struct({ kind: LoginFailureKind, reason: S.str }), Authenticating: S._void }));
/**
* Review shown before a product binds or uses wallet-held Chat identity authority.
*/
export const ChatAuthorityReview = S.lazy(() => S.Struct({ productId: S.str }));
/**
* Core-owned host-private storage slots. Products never address these slots;
* the host chooses the backing store for each slot.
Expand Down Expand Up @@ -66,7 +70,7 @@ export const LoginFailureKind = S.lazy(() => S.Status("NoFreeAllowanceSlots", "O
* Permission request whose authorization status can be inspected or updated
* by host administration UI.
*/
export const PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: HostDevicePermissionRequest, Remote: RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }) }));
export const PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: HostDevicePermissionRequest, Remote: RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void }));
/**
* Authorization status for a permission request.
*
Expand Down Expand Up @@ -135,4 +139,4 @@ export const StatementStoreProductSignReview = S.lazy(() => S.Struct({ account:
/**
* Review shown before a user-confirmed core action continues.
*/
export const UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview }));
export const UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview }));
12 changes: 6 additions & 6 deletions vendor/truapi-host/dist/wasm/web/truapi_server.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,12 @@ export interface InitOutput {
readonly wasmsigninghostruntime_sessionChatIdentityKey: (a: number, b: number) => void;
readonly wasmsigninghostruntime_setPermissionAuthorizationStatus: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => number;
readonly wireSchemaHash: (a: number) => void;
readonly __wasm_bindgen_func_elem_16888: (a: number, b: number, c: number, d: number) => void;
readonly __wasm_bindgen_func_elem_16891: (a: number, b: number, c: number, d: number) => void;
readonly __wasm_bindgen_func_elem_3497: (a: number, b: number, c: number) => void;
readonly __wasm_bindgen_func_elem_3494: (a: number, b: number, c: number) => void;
readonly __wasm_bindgen_func_elem_10918: (a: number, b: number) => void;
readonly __wasm_bindgen_func_elem_3496: (a: number, b: number) => void;
readonly __wasm_bindgen_func_elem_17072: (a: number, b: number, c: number, d: number) => void;
readonly __wasm_bindgen_func_elem_17075: (a: number, b: number, c: number, d: number) => void;
readonly __wasm_bindgen_func_elem_3545: (a: number, b: number, c: number) => void;
readonly __wasm_bindgen_func_elem_3542: (a: number, b: number, c: number) => void;
readonly __wasm_bindgen_func_elem_11090: (a: number, b: number) => void;
readonly __wasm_bindgen_func_elem_3544: (a: number, b: number) => void;
readonly __wbindgen_export: (a: number, b: number) => number;
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_export3: (a: number) => void;
Expand Down
Loading
Loading