UNPKG

run402-mcp

Version:

MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.

79 lines • 3.67 kB
/** Node-only helpers to adopt the org your wallet's agent owns. */ import { readWallet } from "../../core-dist/wallet.js"; import { prepareSIWx } from "../../core-dist/wallet-auth.js"; import { personalMessageSignerFor, walletCanSign } from "./signers/index.js"; import { getApiBase } from "../../core-dist/config.js"; import { loadLiveControlPlaneSession } from "../../core-dist/control-plane-session.js"; import { LocalError } from "../errors.js"; /** * Build the `SIGN-IN-WITH-X` wallet proof for an org adopt: a fresh CAIP-122 * SIWX message carrying the challenge `nonce`, signed by the local wallet. * The gateway binds the action/wallet/org/expiry server-side via the nonce, so * there is no canonical statement to match (simpler than `signCiDelegation`). */ export async function signOrgAdopt(nonce, opts = {}) { if (!nonce || typeof nonce !== "string") { throw new LocalError("signOrgAdopt requires the challenge nonce", "signing org adopt"); } const localWallet = readWallet(opts.walletPath); if (!localWallet || !localWallet.address || !walletCanSign(localWallet)) { throw new LocalError("No local wallet configured. Run `run402 init` before adopting an org.", "signing org adopt"); } const apiBase = opts.apiBase ?? getApiBase(); const url = new URL("/orgs/v1/adopt", apiBase); const now = new Date(); const prepared = prepareSIWx({ address: localWallet.address, domain: url.hostname, uri: url.toString(), statement: "Adopt wallet-owned org", chainId: opts.chainId ?? "eip155:84532", nonce, issuedAt: opts.issuedAt ?? now.toISOString(), expirationTime: opts.expirationTime ?? new Date(now.getTime() + 5 * 60 * 1000).toISOString(), }); const sign = await personalMessageSignerFor(localWallet); return prepared.finish(await sign(prepared.message))["SIGN-IN-WITH-X"]; } /** * Run the full org adopt dance (Node): resolve the human's write-capable * control-plane session from the local cache, request a challenge, sign the * nonce with the active wallet, and submit both proofs. Returns the * discriminated {@link AdoptResult} — a `select_org` result is returned, not * thrown; re-invoke with `{ orgId }` to adopt a specific org (this re-runs a * fresh challenge + signature, which is fine: the nonce is adopt-scoped). * * Does NOT drive the WebAuthn step-up: a stale session surfaces * `StepUpRequiredError` for the caller (CLI) to handle. */ export async function adoptOrg(r, opts = {}) { let token = opts.token; if (!token) { const session = loadLiveControlPlaneSession(opts.controlPlaneSessionPath); if (!session) { throw new LocalError("No live sign-in session. Run `run402 login` (passkey-fresh) before adopting an org.", "adopting org"); } token = session.control_plane_session_token; } let wallet = opts.wallet; if (!wallet) { const localWallet = readWallet(opts.walletPath); if (!localWallet || !localWallet.address) { throw new LocalError("No wallet specified and no local wallet address found. Pass { wallet } or run `run402 init`.", "adopting org"); } wallet = localWallet.address; } const challenge = await r.orgs.adopt.challenge({ wallet, token }); const siwx = await signOrgAdopt(challenge.nonce, { apiBase: opts.apiBase, walletPath: opts.walletPath, chainId: opts.chainId, }); return r.orgs.adopt.submit({ token, siwx, orgId: opts.orgId, displayName: opts.displayName, }); } //# sourceMappingURL=org-adopt.js.map