Forward wallet session tokens in launcher API calls

This commit is contained in:
Joshua 2026-02-18 20:15:39 -08:00
parent b0c54660fb
commit 42bccf5ed2
3 changed files with 41 additions and 2 deletions

View File

@ -54,6 +54,7 @@ Wallet automation helpers remain available in advanced controls:
3. `Sign payer proof` signs distinct-payer ownership proof and fills `payerProof`.
4. `Send membership tx` submits the quote transaction via `eth_sendTransaction` and fills `confirmTxHash`.
5. Membership confirm can optionally attach on-ramp attestation fields (`identity_assurance_level`, `identity_attested_by`, `identity_attestation_id`) for provider-integrated flows.
6. Wallet verify returns a session token; launcher forwards it on marketplace/member/governance API calls via bearer + `X-Edut-Session`.
Policy behavior in launcher shell:

View File

@ -9,6 +9,8 @@ const state = {
lastCheckoutQuote: null,
lastStatus: null,
channelReady: false,
walletSessionToken: "",
walletSessionExpiresAt: "",
};
function nowISO() {
@ -133,9 +135,14 @@ function sleep(ms) {
}
async function request(method, path, body) {
const headers = { "Content-Type": "application/json" };
if (state.walletSessionToken) {
headers["X-Edut-Session"] = state.walletSessionToken;
headers.Authorization = `Bearer ${state.walletSessionToken}`;
}
const opts = {
method,
headers: { "Content-Type": "application/json" },
headers,
};
if (body !== undefined) {
opts.body = JSON.stringify(body);
@ -260,12 +267,22 @@ function buildIntentTypedData(intent, origin) {
}
async function onConnectWallet() {
const previousWallet = normalizedAddress($("walletAddress").value);
const provider = await requireProvider();
const accounts = await provider.request({ method: "eth_requestAccounts" });
if (!accounts || accounts.length === 0) {
throw new Error("wallet provider returned no accounts");
}
$("walletAddress").value = normalizedAddress(accounts[0]);
const nextWallet = normalizedAddress(accounts[0]);
$("walletAddress").value = nextWallet;
if (previousWallet && previousWallet !== nextWallet) {
state.walletSessionToken = "";
state.walletSessionExpiresAt = "";
logLine("wallet session reset", {
previous_wallet: previousWallet,
next_wallet: nextWallet,
});
}
const chainHex = await provider.request({ method: "eth_chainId" });
const providerChainID = Number.parseInt(chainHex, 16);
if (Number.isFinite(providerChainID) && providerChainID !== chainID()) {
@ -400,7 +417,15 @@ async function onVerify() {
if (out.designation_code) {
$("designationCode").value = out.designation_code;
}
state.walletSessionToken = String(out.session_token || "").trim();
state.walletSessionExpiresAt = String(out.session_expires_at || "").trim();
logLine("wallet verify", out);
if (state.walletSessionToken) {
logLine("wallet session active", {
wallet: requireWallet(),
session_expires_at: state.walletSessionExpiresAt || "unknown",
});
}
refreshOverview();
}

View File

@ -18,6 +18,19 @@ Launcher integrates with EDUT web/backend contracts as follows:
12. `GET /governance/install/status`
13. `GET /member/channel/events`
## Wallet Session Contract
1. `POST /secret/wallet/verify` returns `session_token` and `session_expires_at`.
2. Launcher must attach session token on wallet-scoped calls using:
- `Authorization: Bearer <session_token>` (preferred)
- `X-Edut-Session: <session_token>` (compatibility)
3. Wallet change must clear cached session token before further calls.
4. Endpoints that require membership/admin authority can fail with:
- `wallet_session_required`
- `wallet_session_invalid`
- `wallet_session_expired`
- `wallet_session_mismatch`
## Deterministic Requirements
1. No runtime activation without entitlement proof.