Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
186 commits
Select commit Hold shift + click to select a range
a302550
feat(truapi): add testing API and versioned wiring
pgherveou Jun 30, 2026
4b83619
feat(truapi-platform): add host capability traits
pgherveou Jun 30, 2026
b25162f
feat(truapi-server): add Rust host runtime
pgherveou Jun 30, 2026
1c8334a
feat(truapi-codegen): emit Rust dispatcher, wire table, and host call…
pgherveou Jun 30, 2026
b137a87
feat(host-wasm): add @parity/truapi-host-wasm runtime
pgherveou Jun 30, 2026
4c04a81
chore: docs, CI, tooling, and dotli integration for the Rust core
pgherveou Jun 30, 2026
8e0e71f
feat(truapi): add testing API and versioned wiring
pgherveou Jun 30, 2026
f898de6
fixup! feat: port Rust core runtime
pgherveou Jul 1, 2026
3faed7e
fixup! feat: port Rust core runtime
pgherveou Jul 1, 2026
dea080a
fixup! feat(truapi): add testing API and versioned wiring
pgherveou Jul 1, 2026
3409152
fixup! feat(truapi): add testing API and versioned wiring
pgherveou Jul 1, 2026
6b1a0fc
fixup! feat: port Rust core runtime
pgherveou Jul 2, 2026
0569aaf
fixup! feat(truapi): add testing API and versioned wiring
pgherveou Jul 2, 2026
8c93e99
feat(truapi-platform): add host capability traits
pgherveou Jun 30, 2026
f3f37e9
fixup! feat: port Rust core runtime
pgherveou Jul 2, 2026
97d0b79
fixup! feat(truapi-platform): add host capability traits
pgherveou Jul 2, 2026
52e64b8
fixup! feat: port Rust core runtime
pgherveou Jul 2, 2026
3e6c0a0
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
d2e3674
fixup! feat(truapi-platform): add host capability traits
pgherveou Jul 3, 2026
c6f888c
feat(truapi-codegen): emit Rust dispatcher, wire table, and host call…
pgherveou Jun 30, 2026
a37abae
fixup! feat(truapi-codegen): emit Rust dispatcher, wire table, and ho…
pgherveou Jul 2, 2026
99d1b7e
fixup! feat(truapi-codegen): emit Rust dispatcher, wire table, and ho…
pgherveou Jul 2, 2026
1c46353
fixup! feat(truapi-codegen): emit Rust dispatcher, wire table, and ho…
pgherveou Jul 2, 2026
16f10e9
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
2c52262
fixup! feat(truapi-codegen): emit Rust dispatcher, wire table, and ho…
pgherveou Jul 3, 2026
8a4bab1
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
f1a10bc
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
7bd57b8
fixup! feat(truapi-codegen): emit Rust dispatcher, wire table, and ho…
pgherveou Jul 3, 2026
6964df3
feat(truapi-server): add host logic primitives
pgherveou Jul 1, 2026
c8c4595
fixup! feat(truapi-server): add host logic primitives
pgherveou Jul 1, 2026
88cf1a9
fixup! feat(truapi-server): add host logic primitives
pgherveou Jul 2, 2026
2d88bdf
fixup! feat(truapi-server): add host logic primitives
pgherveou Jul 3, 2026
5e938f1
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
e1f6790
feat(truapi-server): add wire and chain infrastructure
pgherveou Jul 1, 2026
d959726
fixup! feat(truapi-server): add wire and chain infrastructure
pgherveou Jul 3, 2026
fa642c1
fixup! feat(truapi-server): add host logic primitives
pgherveou Jul 3, 2026
176c6b1
feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 1, 2026
6aa9887
fixup! feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 1, 2026
0f6e16c
fixup! feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 2, 2026
80ff2c7
fixup! feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 2, 2026
c6091f0
fixup! feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 3, 2026
e4d9a0d
fixup! feat(truapi-server): add wire and chain infrastructure
pgherveou Jul 3, 2026
302e84c
feat(host-wasm): add @parity/truapi-host-wasm runtime
pgherveou Jun 30, 2026
63f59f9
fixup! feat(host-wasm): add @parity/truapi-host-wasm runtime
pgherveou Jul 1, 2026
cda98b6
chore: docs, CI, tooling, and dotli integration for the Rust core
pgherveou Jun 30, 2026
232458b
fixup! feat(host-wasm): add @parity/truapi-host-wasm runtime
pgherveou Jul 2, 2026
375c395
fixup! chore: docs, CI, tooling, and dotli integration for the Rust core
pgherveou Jul 1, 2026
7ac562a
fixup! feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 3, 2026
e33df7c
fixup! feat(host-wasm): add @parity/truapi-host-wasm runtime
pgherveou Jul 3, 2026
518d270
fixup! chore: docs, CI, tooling, and dotli integration for the Rust core
pgherveou Jul 2, 2026
124b5b7
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
cc4c5e5
Merge origin/main into rust core umbrella
pgherveou Jul 3, 2026
dab5395
Merge origin/main into rust-core/04-codegen
pgherveou Jul 3, 2026
15e1594
Merge branch 'rust-core/04-codegen' into rust-core/04a-server-host-logic
pgherveou Jul 3, 2026
54f0b20
docs(host-logic): link host-spec sections
pgherveou Jul 3, 2026
2da3da5
Merge branch 'rust-core/04a-server-host-logic' into rust-core/04b-ser…
pgherveou Jul 3, 2026
f7b2424
Merge branch 'rust-core/04b-server-wire-chain' into rust-core/03-serv…
pgherveou Jul 3, 2026
ac7992f
docs(runtime): link host-spec sections
pgherveou Jul 3, 2026
cd15f9c
Merge branch 'rust-core/03-server-runtime' into rust-core/05-host-wasm
pgherveou Jul 3, 2026
67d763b
docs(server): fix wasm rustdoc reference
pgherveou Jul 3, 2026
351f6e7
Merge branch 'rust-core/05-host-wasm' into rust-core/06-docs-ci-tooling
pgherveou Jul 3, 2026
e058ba3
chore(dotli): update truapi integration sha
pgherveou Jul 3, 2026
d0eab2a
fixup! feat: port Rust core runtime
pgherveou Jul 3, 2026
cda27e1
fixup! feat(truapi-server): add wire and chain infrastructure
pgherveou Jul 3, 2026
227f47c
Merge branch 'rust-core/04b-server-wire-chain' into rust-core/03-serv…
pgherveou Jul 3, 2026
8bd9085
fixup! feat(truapi-server): add platform runtime and host bridge
pgherveou Jul 3, 2026
51f1e1c
Merge branch 'rust-core/03-server-runtime' into rust-core/05-host-wasm
pgherveou Jul 3, 2026
312be68
Merge branch 'rust-core/05-host-wasm' into rust-core/06-docs-ci-tooling
pgherveou Jul 3, 2026
ba2571a
Merge branch 'main' into rust-core/03-server-runtime
pgherveou Jul 3, 2026
0c2b0f7
firs batch
pgherveou Jul 4, 2026
88c6989
wip
pgherveou Jul 5, 2026
f4468fc
feat(truapi-host-cli): headless pairing + signing hosts for local e2e
pgherveou Jul 5, 2026
7e8eb40
refactor(codegen): derive wasm host callbacks
pgherveou Jul 5, 2026
1d919f0
fix(chain): stop_transaction example broadcasts then cancels by id
pgherveou Jul 5, 2026
8bfbcdc
Merge remote-tracking branch 'origin/worktree-issue-96-rust-core-port…
pgherveou Jul 6, 2026
b804d04
fix(server): enforce runtime permissions
pgherveou Jul 6, 2026
f22b4b5
feat(codegen): generate wasm bridge callbacks
pgherveou Jul 6, 2026
2cb1e97
Merge branch 'rust-core/04-wasm-bridge-codegen' into rust-core/05-hos…
pgherveou Jul 6, 2026
4c04dd3
refactor(host-wasm): use namespaced callbacks
pgherveou Jul 6, 2026
fa859e3
Merge branch 'rust-core/05-host-wasm' into rust-core/06-docs-ci-tooling
pgherveou Jul 6, 2026
23bb0b8
chore(dotli): update host integration
pgherveou Jul 6, 2026
5de806e
fix(server): include runtime crate in workspace
pgherveou Jul 6, 2026
460dc77
Merge branch 'rust-core/03-server-runtime' into rust-core/04-wasm-bri…
pgherveou Jul 6, 2026
e9888aa
Merge branch 'rust-core/04-wasm-bridge-codegen' into rust-core/05-hos…
pgherveou Jul 6, 2026
d820bb0
Merge branch 'rust-core/05-host-wasm' into rust-core/06-docs-ci-tooling
pgherveou Jul 6, 2026
0d304f8
docs(server): describe permission flow
pgherveou Jul 6, 2026
cddce3e
Merge branch 'rust-core/03-server-runtime' into rust-core/04-wasm-bri…
pgherveou Jul 6, 2026
b4ac06f
Merge branch 'rust-core/04-wasm-bridge-codegen' into rust-core/05-hos…
pgherveou Jul 6, 2026
307e08f
Merge branch 'rust-core/05-host-wasm' into rust-core/06-docs-ci-tooling
pgherveou Jul 6, 2026
a253874
fix(codegen): satisfy wasm bridge clippy
pgherveou Jul 6, 2026
a46e8fe
Merge remote-tracking branch 'origin/rust-core/04-wasm-bridge-codegen…
pgherveou Jul 6, 2026
23ebade
Merge remote-tracking branch 'origin/rust-core/05-host-wasm' into rus…
pgherveou Jul 6, 2026
9f62ed0
Merge remote-tracking branch 'origin/rust-core/06-docs-ci-tooling' in…
pgherveou Jul 6, 2026
1735b8a
test(server): wait for auth sync callback
pgherveou Jul 6, 2026
01ddadc
Merge remote-tracking branch 'origin/rust-core/03-server-runtime' int…
pgherveou Jul 6, 2026
487b2d7
Merge remote-tracking branch 'origin/rust-core/04-wasm-bridge-codegen…
pgherveou Jul 6, 2026
a5113fe
Merge remote-tracking branch 'origin/rust-core/05-host-wasm' into rus…
pgherveou Jul 6, 2026
008c375
Merge remote-tracking branch 'origin/rust-core/06-docs-ci-tooling' in…
pgherveou Jul 6, 2026
f421258
test(server): make pairing snapshot test deterministic
pgherveou Jul 6, 2026
2fc5be9
Merge remote-tracking branch 'origin/rust-core/03-server-runtime' int…
pgherveou Jul 6, 2026
c137fef
Merge remote-tracking branch 'origin/rust-core/04-wasm-bridge-codegen…
pgherveou Jul 6, 2026
980d597
Merge remote-tracking branch 'origin/rust-core/05-host-wasm' into rus…
pgherveou Jul 6, 2026
b89869b
Merge remote-tracking branch 'origin/rust-core/06-docs-ci-tooling' in…
pgherveou Jul 6, 2026
7190552
chore(stack): move wasm bridge out of runtime layer
pgherveou Jul 6, 2026
c3c243b
Merge remote-tracking branch 'origin/rust-core/03-server-runtime' int…
pgherveou Jul 6, 2026
71c910f
Merge remote-tracking branch 'origin/rust-core/04-wasm-bridge-codegen…
pgherveou Jul 6, 2026
2b766bb
Merge remote-tracking branch 'origin/rust-core/05-host-wasm' into rus…
pgherveou Jul 6, 2026
60e0491
Merge remote-tracking branch 'origin/rust-core/06-docs-ci-tooling' in…
pgherveou Jul 6, 2026
1889194
feat(truapi-host-cli): pair over the real People-chain statement store
pgherveou Jul 6, 2026
9559cec
fixup! feat: port Rust core runtime
pgherveou Jul 6, 2026
b32df3e
fixup! feat: port Rust core runtime
pgherveou Jul 6, 2026
ae62bc6
fixup! feat: port Rust core runtime
pgherveou Jul 6, 2026
d01d9f5
feat(truapi-host-cli): drive hosts with product scripts + CLI confirm…
pgherveou Jul 6, 2026
6f8d642
refactor(truapi-host-cli): slim the script API + finalize allowance
pgherveou Jul 6, 2026
0cf134c
fixup! feat: port Rust core runtime
pgherveou Jul 6, 2026
588bc09
fix(runtime): gate account access
pgherveou Jul 6, 2026
b059572
fix(runtime): route statement proof signing
pgherveou Jul 6, 2026
abf7cd8
fix(runtime): use opaque SSO ids
pgherveou Jul 6, 2026
8e5d1e0
fix(runtime): harden session and permission flows
pgherveou Jul 7, 2026
153393f
fixup! feat(codegen): generate wasm bridge callbacks
pgherveou Jul 7, 2026
55f9eeb
wip
pgherveou Jul 7, 2026
17181af
fix login
pgherveou Jul 7, 2026
a9402a3
fix(runtime): bridge bulletin allowance signing
pgherveou Jul 8, 2026
f597a84
refactor(platform): derive allowance Debug
pgherveou Jul 8, 2026
ec8b20b
fix(runtime): keep allowance signing in Rust
pgherveou Jul 8, 2026
27f420b
fix: harden login and preimage failures
pgherveou Jul 8, 2026
f6e4fc9
chore: update dotli error formatting
pgherveou Jul 8, 2026
c98684d
fix(runtime): simplify pairing statement outcome
pgherveou Jul 8, 2026
319e867
ci: refresh CI workflow config
pgherveou Jul 8, 2026
1656382
ci: enforce codegen parity checks
pgherveou Jul 8, 2026
d0ef238
ci: refresh workflow pins
pgherveou Jul 8, 2026
31dc8f1
refactor: rename truapi host package
pgherveou Jul 8, 2026
7303f22
Merge remote-tracking branch 'origin/main' into worktree-issue-96-rus…
pgherveou Jul 9, 2026
a7bf860
feat: tighten wasm size profile
pgherveou Jul 9, 2026
4391181
refactor: remove flat host callbacks
pgherveou Jul 9, 2026
920ba81
test(host): cover worker permission auth
pgherveou Jul 9, 2026
8d548ef
feat(server): build, sign, and submit Bulletin preimages in the core
pgherveou Jul 8, 2026
070d7d8
fix(server): harden bulletin inclusion watch (cycle guard + pin release)
pgherveou Jul 8, 2026
e25503b
fix(server): stabilize bulletin preimage submit
pgherveou Jul 9, 2026
e9cf920
feat(server): implement local create_transaction via the shared assem…
pgherveou Jul 9, 2026
8a98b5b
refactor(server): simplify bulletin preimage config
pgherveou Jul 9, 2026
60b43ea
update
pgherveou Jul 9, 2026
e731d5c
first pass
pgherveou Jul 10, 2026
28941c9
2nd pass
pgherveou Jul 11, 2026
f93ad40
chore: update dotli submodule
pgherveou Jul 11, 2026
046215c
Merge branch 'bulletin-preimage-in-core' into headless-host
pgherveou Jul 11, 2026
6441925
fix: allocate headless signer resources
pgherveou Jul 12, 2026
20667cf
chore: ignore local generated artifacts
pgherveou Jul 12, 2026
bf3c7a7
chore: add headless cli install target
pgherveou Jul 12, 2026
4e0df24
fix: tighten headless allowance flows
pgherveou Jul 12, 2026
be2b29c
fix: use release wasm for dotli e2e
pgherveou Jul 12, 2026
496ec18
fix: use subxt rpc for attestation poll
pgherveou Jul 12, 2026
44dd085
fix: address headless host CI checks
pgherveou Jul 12, 2026
0cd8753
update
pgherveou Jul 13, 2026
ddf0786
feat(core): implement ring-vrf signing
pgherveou Jul 17, 2026
d59fdb1
Merge branch 'main' into feat/signing-host-ring-vrf
pgherveou Jul 20, 2026
5911457
Merge branch 'main' into feat/signing-host-ring-vrf
pgherveou Jul 21, 2026
d7e76f6
feat(host): integrate signing-host ring VRF
pgherveou Jul 21, 2026
af0c281
feat(cli): trace inbound SSO requests
pgherveou Jul 21, 2026
c000e7a
feat(cli): add interactive whoami
pgherveou Jul 21, 2026
e18fe52
feat(cli): add signing-host terminal UI
pgherveou Jul 21, 2026
872c2b9
test(e2e): extend signer pairing timeout
pgherveou Jul 21, 2026
17c7b3c
Merge branch 'verify/pr264-with-pr288'
pgherveou Jul 21, 2026
7671621
fix(cli): expose identity and all commands
pgherveou Jul 21, 2026
ea2cad3
fix(cli): suppress rustls tracing
pgherveou Jul 21, 2026
e8f61eb
fix(cli): retain clipboard ownership
pgherveou Jul 21, 2026
dd3b336
fix(cli): suppress WebSocket protocol logs
pgherveou Jul 21, 2026
59299eb
feat(cli): add persistent host sessions
pgherveou Jul 21, 2026
cf16f3c
fix(cli): restore cached session identity
pgherveou Jul 21, 2026
6268b56
fix(cli): derive account prefix from session
pgherveou Jul 21, 2026
3c34939
feat(cli): edit scratch scripts in terminal
pgherveou Jul 21, 2026
307f0bf
feat(cli)!: remove whoami command
pgherveou Jul 21, 2026
c19c22a
feat(cli): show SSO response outcomes
pgherveou Jul 21, 2026
9285fd1
wip
pgherveou Jul 22, 2026
f428d2c
fix
pgherveou Jul 22, 2026
7ea2c0c
fixes
pgherveou Jul 22, 2026
e34807e
feat(server,cli): auto-renew statement-store allowances
pgherveou Jul 22, 2026
da5bca4
Merge remote-tracking branch 'origin/main' into pg/statement-allowanc…
pgherveou Aug 5, 2026
ea3665a
fix(codegen): restore the wasm_bridge golden to generated output
TarikGul Aug 11, 2026
74feb2a
fix(server): keep a renewal pass going past one bad ledger entry
TarikGul Aug 11, 2026
284876d
fix(server): scope raw renewal targets to the identity that promised …
TarikGul Aug 11, 2026
0ba9989
fix(server): classify slot exhaustion from the error, not its text
TarikGul Aug 11, 2026
c7d7793
fix(server): serialize read-modify-write cycles on the renewal ledger
TarikGul Aug 11, 2026
ce270f5
fix(server): keep the renewal tick out of the post-boundary margin
TarikGul Aug 11, 2026
4d44b98
Merge origin/main into pg/statement-allowance-renewal
TarikGul Aug 11, 2026
53eef7b
test(server): cover the two renewal fixes that had no reproduction
TarikGul Aug 11, 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
7 changes: 6 additions & 1 deletion rust/crates/truapi-codegen/tests/golden/host-callbacks.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

103 changes: 103 additions & 0 deletions rust/crates/truapi-host-cli/e2e/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# Headless end-to-end run: a pairing host drives a product script against a
# signing host, pairing over the real People-chain statement store.
#
# make headless # build once
# e2e/run.sh # generates pairing-host-cli.md (default)
# e2e/run.sh path/to/script.ts # runs a custom product script
#
# Env:
# PRODUCT_ID product id the pairing host serves (default truapi-playground.dot)
# HOST_CLI_SIGNER_MNEMONIC optional wallet mnemonic; when unset, signing-host auto-manages one
# TRUAPI_HOST_BASE_PATH optional root for generated accounts and host state
# TRUAPI_PAIRING_BASE_PATH optional pairing-host state root; defaults to a fresh temporary root
# TRUAPI_E2E_LOAD_ENV set to 0 to ignore the gitignored e2e/.env (default 1)
# FRAME frame-server address (default 127.0.0.1:9955)
set -euo pipefail

ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)"
BIN="$ROOT/target/debug/truapi-host"

# Load HOST_CLI_SIGNER_MNEMONIC / TRUAPI_HOST_BASE_PATH (and any other vars)
# from a gitignored e2e/.env if present.
ENV_FILE="$(dirname "$0")/.env"
if [ "${TRUAPI_E2E_LOAD_ENV:-1}" = 1 ] && [ -f "$ENV_FILE" ]; then
set -a
. "$ENV_FILE"
set +a
fi

SCRIPT="${1:-$ROOT/rust/crates/truapi-host-cli/js/scripts/battery.ts}"
PRODUCT_ID="${PRODUCT_ID:-truapi-playground.dot}"
FRAME="${FRAME:-127.0.0.1:9955}"

PAIRING_BASE_PATH_OWNED=0
if [ -n "${TRUAPI_PAIRING_BASE_PATH:-}" ]; then
PAIRING_BASE_PATH="$TRUAPI_PAIRING_BASE_PATH"
else
PAIRING_BASE_PATH="$(mktemp -d /tmp/truapi-e2e-pairing.XXXXXX)"
PAIRING_BASE_PATH_OWNED=1
fi

[ -x "$BIN" ] || { echo "missing $BIN — run: make headless" >&2; exit 2; }

LOG="$(mktemp)"
SIGNER_PID=""
PAIR_PID=""
stop_pairing_host() {
[ -n "$PAIR_PID" ] || return 0
pkill -TERM -P "$PAIR_PID" 2>/dev/null || true
kill -TERM "$PAIR_PID" 2>/dev/null || true
sleep 0.5
pkill -KILL -P "$PAIR_PID" 2>/dev/null || true
kill -KILL "$PAIR_PID" 2>/dev/null || true
}
cleanup() {
[ -n "$SIGNER_PID" ] && kill "$SIGNER_PID" 2>/dev/null || true
stop_pairing_host
rm -f "$LOG"
if [ "$PAIRING_BASE_PATH_OWNED" -eq 1 ]; then
rm -rf -- "$PAIRING_BASE_PATH"
fi
}
trap cleanup EXIT

# The pairing host runs the product script; the script's
# `truapi.account.requestLogin` makes the host emit a pairing deeplink, which we
# hand to a signing host. The pairing host exits with the script's status.
"$BIN" pairing-host --product-id "$PRODUCT_ID" --script "$SCRIPT" \
--frame-listen "$FRAME" --base-path "$PAIRING_BASE_PATH" \
--auto-accept > >(tee "$LOG") 2>&1 &
PAIR_PID=$!

deeplink=""
for _ in $(seq 1 600); do
deeplink="$(grep -m1 -oE 'polkadotapp://pair\?handshake=[[:xdigit:]]+' "$LOG" || true)"
[ -n "$deeplink" ] && break
kill -0 "$PAIR_PID" 2>/dev/null || break
sleep 0.5
done
[ -n "$deeplink" ] || { echo "pairing host did not emit a deeplink" >&2; exit 1; }

# The signing host reads HOST_CLI_SIGNER_MNEMONIC from the env when set.
# Otherwise it auto-selects or creates an attested account under its base path.
"$BIN" signing-host --auto-accept exec "/deeplink $deeplink" &
SIGNER_PID=$!

pid_running() {
local stat
stat="$(ps -p "$1" -o stat= 2>/dev/null || true)"
[ -n "$stat" ] && [ "${stat#Z}" = "$stat" ]
}

while :; do
if ! pid_running "$PAIR_PID"; then
wait "$PAIR_PID"
exit $?
fi
if ! pid_running "$SIGNER_PID"; then
stop_pairing_host
exit 1
fi
sleep 0.5
done
121 changes: 111 additions & 10 deletions rust/crates/truapi-host-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ use tracing_subscriber::util::SubscriberInitExt;
use truapi_platform::{HostInfo, PlatformInfo};
use truapi_server::statement_allowance as alloc;
use truapi_server::subscription::Spawner;
use truapi_server::{PairingHostConfig, PairingHostRuntime, SigningHostConfig, SigningHostRuntime};
use truapi_server::{
PairingHostConfig, PairingHostRuntime, SigningHostConfig, SigningHostRuntime,
StatementRenewalTarget,
};

use crate::accounts::{ResolveSignerConfig, ResolvedSigner};
use crate::network::{Network, NetworkConfig};
Expand Down Expand Up @@ -898,11 +901,9 @@ fn build_signing_runtime(
network.bulletin_genesis,
)
.context("invalid signing host config")?;
Ok(Arc::new(SigningHostRuntime::new(
platform,
config,
tokio_spawner(),
)))
let runtime = Arc::new(SigningHostRuntime::new(platform, config, tokio_spawner()));
runtime.start_statement_allowance_renewal();
Ok(runtime)
}

impl Drop for SigningHostSession {
Expand Down Expand Up @@ -1082,7 +1083,10 @@ async fn prepare_pairing_response(session: &mut SigningHostSession, deeplink: &s
)
};
match register_pairing_allowances(session.network.people_ws, &entropy, deeplink).await {
Ok(()) => return Ok(()),
Ok(device) => {
track_pairing_renewal_targets(session, device).await;
return Ok(());
}
Err(err) if auto_managed && is_statement_slot_exhaustion(&err) => {
attempts += 1;
if attempts > 8 {
Expand Down Expand Up @@ -1132,6 +1136,99 @@ fn is_statement_slot_exhaustion(err: &anyhow::Error) -> bool {
err.to_string().contains("no free StatementStore slot")
}

/// Best-effort: record the pairing allowance accounts in the renewal ledger so
/// the background renewer keeps them allowed across periods.
async fn track_pairing_renewal_targets(session: &SigningHostSession, device: [u8; 32]) {
let result = session
.runtime
.track_statement_renewal_targets(vec![
StatementRenewalTarget::WalletSso,
StatementRenewalTarget::Account {
account_id: device,
label: "device".to_string(),
},
])
.await;
if let Err(err) = result {
tracing::warn!(reason = %err.reason, "failed to record pairing renewal targets");
}
}

/// Renew tracked statement-store allowances now, reporting each target. On
/// slot exhaustion an auto-managed signer account is marked exhausted so the
/// next pairing rotates to a fresh one.
async fn run_renew(session: &mut SigningHostSession) -> Result<()> {
use truapi_server::statement_allowance::renewal::TargetRenewalStatus;

ensure_signer(session).await?;
let report = session
.runtime
.renew_statement_allowances()
.await
.map_err(|err| anyhow::anyhow!("allowance renewal failed: {}", err.reason))?;

let (mut renewed, mut fresh, mut failed, mut skipped) = (0usize, 0usize, 0usize, 0usize);
for (target, status) in &report.outcomes {
match status {
TargetRenewalStatus::Registered { seq, block_hash } => {
renewed += 1;
terminal_ui::output_event(SystemEvent::AllowanceReady {
target: target.clone(),
sequence: *seq,
block_hash: Some(block_hash.clone()),
already_allocated: false,
});
}
TargetRenewalStatus::AlreadyAllocated { seq } => {
fresh += 1;
terminal_ui::output_event(SystemEvent::AllowanceReady {
target: target.clone(),
sequence: *seq,
block_hash: None,
already_allocated: true,
});
}
TargetRenewalStatus::Failed { reason } => {
failed += 1;
terminal_ui::output_event(SystemEvent::AllowanceRenewalFailed {
target: target.clone(),
reason: reason.clone(),
});
}
TargetRenewalStatus::SkippedExhausted => skipped += 1,
}
}
terminal_ui::output_event(SystemEvent::AllowanceRenewalReport {
period: report.period,
renewed,
fresh,
failed,
skipped,
});

if report.slots_exhausted {
mark_current_account_exhausted(session)?;
}
Ok(())
}

fn mark_current_account_exhausted(session: &SigningHostSession) -> Result<()> {
let Some(signer) = session.signer.as_ref() else {
return Ok(());
};
if !signer.auto_managed {
return Ok(());
}
let Some(name) = signer.account_name.clone() else {
return Ok(());
};
let period = accounts::current_statement_period()?;
let account_base_path = current_account_base_path(session)?;
accounts::mark_account_exhausted(&account_base_path, session.network.id, &name, period)?;
terminal_ui::output_event(SystemEvent::SigningHostAccountExhausted { name, period });
Ok(())
}

async fn respond_to_deeplink(session: &mut SigningHostSession, deeplink: String) -> Result<()> {
prepare_pairing_response(session, &deeplink).await?;
let exit = session
Expand Down Expand Up @@ -1316,11 +1413,13 @@ async fn switch_session(session: &mut SigningHostSession, name: String) -> Resul
/// statements during pairing: the signing host's RFC-0022 `uid.dot` identity
/// account and the pairing host's per-pairing device key (from the deeplink).
/// Proves the signing account's LitePeople ring membership once and reuses it.
/// Returns the device statement account id so the caller can track it for
/// renewal.
async fn register_pairing_allowances(
statement_store_url: &str,
entropy: &[u8],
deeplink: &str,
) -> Result<()> {
) -> Result<[u8; 32]> {
use truapi_server::host_logic::product_account::{
derive_identity_keypair, derive_lite_person_ring_vrf_entropy,
};
Expand Down Expand Up @@ -1418,7 +1517,7 @@ async fn register_pairing_allowances(
}
}
}
Ok(())
Ok(device)
}

async fn pairing_interactive_loop(
Expand Down Expand Up @@ -1527,7 +1626,7 @@ async fn pairing_interactive_loop(
Err(error) => ui.error(error.to_string()),
}
}
ShellCommand::Pair(_) | ShellCommand::Session(_) => {
ShellCommand::Pair(_) | ShellCommand::Session(_) | ShellCommand::Renew => {
ui.error("command is only available on the signing host");
}
}
Expand Down Expand Up @@ -1777,6 +1876,7 @@ async fn execute_interactive_operation(
ShellCommand::Session(SessionCommand::Switch(name)) => {
switch_session(session, name).await?;
}
ShellCommand::Renew => run_renew(session).await?,
ShellCommand::Login => bail!("/login is only available on the pairing host"),
ShellCommand::Logout => bail!("/logout is only available on the pairing host"),
ShellCommand::Product(_) => bail!("command must be handled by the terminal UI"),
Expand Down Expand Up @@ -1858,6 +1958,7 @@ async fn execute_non_interactive_command(
ShellCommand::Session(SessionCommand::Switch(name)) => {
switch_session(session, name).await?;
}
ShellCommand::Renew => run_renew(session).await?,
}
Ok(())
}
Expand Down
7 changes: 7 additions & 0 deletions rust/crates/truapi-host-cli/src/signing_shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub enum ShellCommand {
Product(ProductCommand),
/// Inspect, list, or switch the active persistent session.
Session(SessionCommand),
/// Renew tracked statement-store allowances for the current period.
Renew,
/// Shut down the signing host.
Quit,
}
Expand Down Expand Up @@ -116,6 +118,7 @@ pub fn parse_command(input: &str) -> Result<ShellCommand, String> {
argument.to_string(),
)))
}
"/renew" => no_argument(name, argument, ShellCommand::Renew),
"/quit" => no_argument(name, argument, ShellCommand::Quit),
_ => Err(format!(
"unknown command `{name}`; use /help to list commands"
Expand Down Expand Up @@ -146,6 +149,7 @@ const SIGNING_COMMANDS: &[(&str, &str)] = &[
("/log", "set error, warn, info, debug, or trace"),
("/product", "show or switch the active product"),
("/session", "show or switch the active session"),
("/renew", "renew statement-store allowances now"),
("/help", "show commands and keyboard shortcuts"),
("/clear", "clear the visible transcript"),
("/copy", "copy the transcript to the clipboard"),
Expand Down Expand Up @@ -532,6 +536,7 @@ pub const HELP_TEXT: &str = "\
/session show the current session and path
/session <name> switch to or create a session
/session --list list sessions for this network
/renew renew statement-store allowances now
/help show this help
/clear clear the visible transcript
/copy copy the transcript to the clipboard
Expand Down Expand Up @@ -593,6 +598,7 @@ mod tests {
)))
);
assert_eq!(parse_command("/copy"), Ok(ShellCommand::Copy));
assert_eq!(parse_command("/renew"), Ok(ShellCommand::Renew));
assert_eq!(
parse_command("/session"),
Ok(ShellCommand::Session(SessionCommand::Current))
Expand All @@ -618,6 +624,7 @@ mod tests {
assert!(parse_command("/logout now").is_err());
assert!(parse_command("/pair https://example.com").is_err());
assert!(parse_command("/deeplink polkadotapp://pair?handshake=01").is_err());
assert!(parse_command("/renew now").is_err());
assert!(parse_command("/log noisy").is_err());
assert!(parse_command("/product example.com").is_err());
assert!(parse_command("/session ../escape").is_err());
Expand Down
Loading