diff --git a/AGENTS.md b/AGENTS.md index e3fff50a..990ca97d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -68,7 +68,7 @@ When adding a new tool/command, add it to the `SURFACE` array **and** `SDK_BY_CA ## Architecture ``` -@run402/sdk (typed TypeScript kernel — 22 namespaces, ~100 methods) +@run402/sdk (typed TypeScript kernel — 23 namespaces, ~100 methods) │ │ /index.ts (isomorphic: Node + sandbox) │ /node (Node-only: keystore + allowance + x402-wrapped fetch + fileSetFromDir) @@ -155,6 +155,7 @@ The `core/` module contains shared logic imported by all interfaces: - **`allowance.ts`** — `readAllowance()`, `saveAllowance()` with atomic writes (temp-file + rename, mode 0600). - **`allowance-auth.ts`** — EIP-191 signing with `@noble/curves`. `getAllowanceAuthHeaders()` returns headers or null. - **`keystore.ts`** — Unified project credential store. Object schema: `{projects: {id: {anon_key, service_key, tier, lease_expires_at}}}`. Auto-migrates legacy array format and `expires_at` → `lease_expires_at`. Functions: `loadKeyStore()`, `saveKeyStore()`, `getProject()`, `saveProject()`, `removeProject()`. +- **`operator-session.ts`** — Operator-session cache for the **human/email** principal (distinct from the per-wallet allowance/keystore). `readOperatorSession()`, `saveOperatorSession()`, `clearOperatorSession()`, `isOperatorSessionExpired()`, `loadLiveOperatorSession()`, `operatorSessionFromTokenResponse()` over `{base}/operator-session.json` (mode 0600, **base** config dir — email-scoped, so it is shared across named wallets, not per-profile). Backs `r.operator` and `run402 operator login/logout/overview/whoami`. Core functions return `null` or throw — they never call `process.exit()`. Each interface wraps with its own error behavior. diff --git a/README.md b/README.md index 65a09815..74b5a182 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,7 @@ const p = await r.project(project.project_id); await p.assets.put("hello.txt", { content: "hi" }); ``` -The SDK is organised as 22 namespaces: `projects`, `assets`, `cache`, `ci`, `sites`, `functions`, `jobs`, `secrets`, `subdomains`, `domains`, `email` (+ `webhooks`), `senderDomain`, `auth`, `apps`, `tier`, `billing`, `contracts`, `ai`, `allowance`, `service`, `admin`, plus the `r.project(id).apply` hero for atomic mixed writes (release slices + assets slice via `/apply/v1/*`). Every operation throws a typed `Run402Error` subclass on failure: `PaymentRequired`, `ProjectNotFound`, `Unauthorized`, `ApiError`, `NetworkError`, `LocalError`, `Run402DeployError`. `apply()` automatically re-plans safe current-base `BASE_RELEASE_CONFLICT` races and emits `apply.retry` progress events. See [`sdk/README.md`](./sdk/README.md). +The SDK is organised as 23 namespaces: `projects`, `assets`, `cache`, `ci`, `sites`, `functions`, `jobs`, `secrets`, `subdomains`, `domains`, `email` (+ `webhooks`), `senderDomain`, `auth`, `apps`, `tier`, `billing`, `contracts`, `ai`, `allowance`, `service`, `admin`, `operator` (the human/email operator session — browser-delegated `login` + `overview` across every wallet that verified your email), plus the `r.project(id).apply` hero for atomic mixed writes (release slices + assets slice via `/apply/v1/*`). Every operation throws a typed `Run402Error` subclass on failure: `PaymentRequired`, `ProjectNotFound`, `Unauthorized`, `ApiError`, `NetworkError`, `LocalError`, `Run402DeployError`. `apply()` automatically re-plans safe current-base `BASE_RELEASE_CONFLICT` races and emits `apply.retry` progress events. See [`sdk/README.md`](./sdk/README.md). **Astro SSR + ISR cache (v1.52+).** For Astro apps, use `@run402/astro` 1.0+ — `export default run402();` in `astro.config.mjs` returns an `AstroUserConfig` composing the SSR adapter (Lambda + SnapStart + ISR cache + AsyncLocalStorage request-context), image integration, and build-time detectors. Functions opt into the SSR class via `FunctionSpec.class: "ssr"` in `ReleaseSpec`; the gateway provisions SnapStart and caches HTML responses keyed by `(host, path, search, method, locale, release_id)`. Cache is bypass-by-default (no-store unless `Cache-Control` explicitly allows it AND no `Set-Cookie` AND no auth-taint flag from `auth.*` helpers / payment primitives). Invalidate from in-function code or out-of-band: `r.cache.invalidate(url)` / `r.cache.invalidatePrefix({ host, prefix })` / `r.cache.invalidateAll({ host })` (SDK), `run402 cache invalidate ` (CLI). Inspect cached state with `r.cache.inspect(url)` / `run402 cache inspect `. Agent DX helpers also in the CLI: `run402 doctor` (5 health checks), `run402 dev` (Astro dev with `.env.local`), `run402 logs --request-id req_...` (correlate across functions). Full reference at [`astro/README.md`](./astro/README.md) and [`cli/llms-cli.txt`](./cli/llms-cli.txt) (R402_* SSR Runtime Error Codes section). diff --git a/cli/README.md b/cli/README.md index c5483c2f..b711d2fc 100644 --- a/cli/README.md +++ b/cli/README.md @@ -212,6 +212,17 @@ Hold several wallets on one machine and select between them: The CLI handles all x402 payment signing automatically — never ask the human for a private key or set up payment libraries by hand. +### Operator (human / email session) + +The **operator** is YOU, the human, identified by email — distinct from the agent (your wallet). One browser login spans every wallet that verified your email, so the overview is a cross-wallet union. For a single wallet's account state, use `run402 status`. + +- `run402 operator login` — browser-delegated sign-in (device-authorization, RFC 8628, like `aws sso login`): magic-link or passkey in the browser, no WebAuthn in the CLI. Caches an email-scoped session at the base config dir (shared across named wallets). +- `run402 operator overview` — account view across ALL wallets controlling your email (requires login; never falls back to a single wallet). +- `run402 operator whoami` — show the cached session (email, wallets, expiry); local, no network. +- `run402 operator logout` — revoke the session server-side and clear the local cache. + +Not exposed as MCP tools by design — MCP authenticates as the agent (wallet), and the human session must not be handed to it. + ## Active project (sticky default) After `provision`, the new project becomes the active one. `run402 projects use ` switches it. Most commands that take `` default to the active project when omitted. diff --git a/documentation.md b/documentation.md index f47608a2..c700cda0 100644 --- a/documentation.md +++ b/documentation.md @@ -32,13 +32,13 @@ Status is a snapshot — refresh it whenever the underlying doc changes. | 🟢 | [`SKILL.test.ts`](SKILL.test.ts) | CI | Validates frontmatter + required CLI verbs / MCP tool names / banned regressions for **both** SKILL files | Whenever a "canonical" verb or tool name moves in/out of either skill | | 🟢 | [`cli/README.md`](cli/README.md) | Humans on GitHub + the [`run402` npm page](https://www.npmjs.com/package/run402) | 30-second start, common-command examples per category, GitHub Actions OIDC quickstart/workflow shape, state-on-disk note, **points at `llms-cli.txt` as authoritative** | Major CLI surface change; install flow change; new top-level command group | | 🟢 | [`llms.txt`](llms.txt) | AI agents fetching (entry point) | High-level wayfinder. Vision, what we offer, the four integration surfaces (SDK ⭐ recommended, CLI, MCP, raw HTTP), GitHub Actions OIDC pointer, pricing summary, 30-second start, links to each surface's deep reference. Served at run402.com/llms.txt via private-repo deploy pulling this file | Vision / what-we-offer / pricing changes; new integration pattern added; surface-recommendation order changes | -| 🟢 | [`cli/llms-cli.txt`](cli/llms-cli.txt) | AI agents fetching | Comprehensive CLI reference. Every subcommand, every flag, deploy release inventory/diff commands, `site.public_paths`, `run402 deploy diagnose`/`resolve`, GitHub Actions OIDC flow, generated workflow shape, troubleshooting. Served via private-repo deploy pulling this file | **Any** CLI subcommand or flag added/removed/renamed | -| 🟢 | [`sdk/llms-sdk.txt`](sdk/llms-sdk.txt) | AI agents fetching | Comprehensive SDK reference. Two entry points, all 21 namespaces with method signatures, CI/OIDC helpers and credential semantics, the modern patterns, full `Run402Error` hierarchy with `Run402DeployError` envelope, `ReleaseSpec` + `site.public_paths` + static route targets + release inventory/diff/resolve shapes, stability + lockstep notes. Served via private-repo deploy pulling this file | Any SDK method or namespace added/changed; `ReleaseSpec` shape changes; new error class lands | +| 🟢 | [`cli/llms-cli.txt`](cli/llms-cli.txt) | AI agents fetching | Comprehensive CLI reference. Every subcommand, every flag, deploy release inventory/diff commands, `site.public_paths`, `run402 deploy diagnose`/`resolve`, GitHub Actions OIDC flow, `run402 operator` (human/email session) commands, generated workflow shape, troubleshooting. Served via private-repo deploy pulling this file | **Any** CLI subcommand or flag added/removed/renamed | +| 🟢 | [`sdk/llms-sdk.txt`](sdk/llms-sdk.txt) | AI agents fetching | Comprehensive SDK reference. Two entry points, all 22 namespaces with method signatures (incl. `r.operator`, the human/email session), CI/OIDC helpers and credential semantics, the modern patterns, full `Run402Error` hierarchy with `Run402DeployError` envelope, `ReleaseSpec` + `site.public_paths` + static route targets + release inventory/diff/resolve shapes, stability + lockstep notes. Served via private-repo deploy pulling this file | Any SDK method or namespace added/changed; `ReleaseSpec` shape changes; new error class lands | | 🟢 | [`llms-mcp.txt`](llms-mcp.txt) | AI agents fetching | Comprehensive MCP reference. Every tool with parameters, deploy release inventory/diff/diagnose tools, `site.public_paths`, the four patterns, error-envelope branching, troubleshooting, install snippets per host. Served via private-repo deploy pulling this file | Any MCP tool added/removed/renamed; pattern changes; new install host needs documenting | -| 🟢 | [`sdk/README.md`](sdk/README.md) | TypeScript devs / agents using the SDK; the [`@run402/sdk` npm page](https://www.npmjs.com/package/@run402/sdk) | Two entry-point install matrix (Node vs isomorphic), full 21-namespace catalog table, paste-and-go AssetRef pattern, unified `r.deploy.apply` v1.34+ primitive (with three layers + `fileSetFromDir`) plus release inventory/diff reads, CI/OIDC helpers, full error hierarchy including `Run402DeployError`, stability + lockstep notes | New SDK namespace / method; new error class; entry-point changes | +| 🟢 | [`sdk/README.md`](sdk/README.md) | TypeScript devs / agents using the SDK; the [`@run402/sdk` npm page](https://www.npmjs.com/package/@run402/sdk) | Two entry-point install matrix (Node vs isomorphic), full 23-namespace catalog table, paste-and-go AssetRef pattern, unified `r.project(id).apply` primitive (with three layers + `fileSetFromDir`) plus release inventory/diff reads, CI/OIDC helpers, full error hierarchy including `Run402DeployError`, stability + lockstep notes | New SDK namespace / method; new error class; entry-point changes | | 🟢 | [`astro/README.md`](astro/README.md) | Astro devs / agents using `@run402/astro`; the [`@run402/astro` npm page](https://www.npmjs.com/package/@run402/astro) | **v1.0.0-alpha.1 SSR preset** + v0.2.x image integration. One-line `export default run402();` returns AstroUserConfig composing the SSR adapter (Lambda + SnapStart + ISR cache + ALS context) + image integration + build-time detectors (dynamic Image / server islands / sessions). `` runtime CMS image component. R402_* error-code reference (17 codes). v0.2.x named `run402` aliased to `run402Image` for backwards-compat. Independent release cadence via `/publish-astro` (OIDC Trusted Publisher). | New ``/`` prop or option; preset option added; SSR adapter hook changes; data-driven pattern guidance changes; new R402_* code; v1.50+ image-pipeline features need wiring | | 🟢 | [`astro/CHANGELOG.md`](astro/CHANGELOG.md) | Anyone reading the npm changelog or upgrading | Per-version notes for `@run402/astro`. v1.0.0-alpha.1 SSR preset, v0.3.0-alpha.1 additive SSR exports, v0.2.4 image integration milestones, migration notes between versions. | Every `@run402/astro` version bump | -| 🟢 | `@run402/functions` package docs | TypeScript devs / agents using `@run402/functions`; the [`@run402/functions` npm page](https://www.npmjs.com/package/@run402/functions) | In-function helper API — `db(req)` / `adminDb()` / `getUser()` / `getUserId()` / `getRole()` / `email` / `ai` / `assets` / routed-http with examples, fluent surface, `adminDb().sql()` parameterized SQL, SSG build-time use, deploy-time bundling note ("don't list in `--deps`"), v1.51+ "Function-level auth gates" section covering `FunctionSpec.requireAuth` / `requireRole` shape, header injection, deploy-time validation, and cache-staleness footnote. **Source lives in `kychee-com/run402-private` at `packages/functions/`** so it can co-evolve with the gateway that bundles it; the npm package on the registry is unchanged. | `db`/`adminDb`/`getUser`/`getUserId`/`getRole`/`email`/`ai`/`assets` surface changes; new in-function helper lands; bundling rules change — edit `packages/functions/README.md` in the private repo | +| 🟢 | `@run402/functions` package docs | TypeScript devs / agents using `@run402/functions`; the [`@run402/functions` npm page](https://www.npmjs.com/package/@run402/functions) | In-function helper API — `db(req)` / `adminDb()` / `auth.*` (`auth.user`, `auth.requireUser`, `auth.requireRole`, `auth.requireMembership`, `auth.fetch`, `auth.sessions.*`, `auth.identities.link`; v3.0 retired the bare `getUser`/`getUserId`/`getRole` exports — they throw `R402_AUTH_UNKNOWN_EXPORT`) / `email` / `ai` / `assets` / routed-http with examples, fluent surface, `adminDb().sql()` parameterized SQL, SSG build-time use, deploy-time bundling note ("don't list in `--deps`"), v1.51+ "Function-level auth gates" section covering `FunctionSpec.requireAuth` / `requireRole` shape, header injection, deploy-time validation, and cache-staleness footnote. **Source lives in `kychee-com/run402-private` at `packages/functions/`** so it can co-evolve with the gateway that bundles it; the npm package on the registry is unchanged. | `db`/`adminDb`/`auth.*`/`email`/`ai`/`assets` surface changes; new in-function helper lands; bundling rules change — edit `packages/functions/README.md` in the private repo | | 🟢 | [`openclaw/README.md`](openclaw/README.md) | Humans browsing the `openclaw/` folder on GitHub | Install instructions, the script-runtime mechanism (re-export from CLI), pointer at `openclaw/SKILL.md` for the full body, the SKILL.md (root) vs openclaw/SKILL.md split, modern patterns callout (paste-and-go / expose manifest / deploy-dir / `site.public_paths` / db(req)), OpenClaw-vs-MCP comparison | Major skill or install-flow change; SKILL split changes | | 🟢 | [`documentation.md`](documentation.md) (this file) | Anyone updating docs | The map | A new doc surface is added; a doc moves / is renamed; status changes | @@ -66,6 +66,7 @@ When you… | Update at minimum… **Add or change stable static asset identity / public URL diagnostics** | SDK deploy types + `Deploy.resolve` helpers + scoped wrapper, `site.public_paths`, `static_public_paths` / `reachability_authority` observability, stable-host fields such as `authorization_result`, `cas_object`, `response_variant`, `allow`, `route_pattern`, `target_type`, `target_name`, and `target_file`, static route target validation, Node manifest normalization, CLI `run402 deploy diagnose` / `run402 deploy resolve`, MCP `deploy_diagnose_url`, OpenClaw parity, `sync.test.ts` (`SURFACE`, `SDK_BY_CAPABILITY`, docs drift guards for literals such as `active_release_missing`, `unsupported_manifest_version`, `negative_cache_hit`, `route_function`, `route_static_alias`, and `route_method_miss`), [sdk/llms-sdk.txt](sdk/llms-sdk.txt), [sdk/README.md](sdk/README.md), [cli/llms-cli.txt](cli/llms-cli.txt), [cli/README.md](cli/README.md), [llms-mcp.txt](llms-mcp.txt), [SKILL.md](SKILL.md), [openclaw/SKILL.md](openclaw/SKILL.md), [openclaw/README.md](openclaw/README.md), [README.md](README.md), [AGENTS.md](AGENTS.md), plus private `site/openapi.json`, `site/llms-full.txt`, `site/updates.txt`, and `site/humans/changelog.md` **Add or change CI/OIDC federation** | `sdk/src/namespaces/ci.ts`, `sdk/src/ci-credentials.ts`, `sdk/src/node/ci.ts`, `cli/lib/ci.mjs`, [sdk/llms-sdk.txt](sdk/llms-sdk.txt), [sdk/README.md](sdk/README.md), [cli/llms-cli.txt](cli/llms-cli.txt), [cli/README.md](cli/README.md), [README.md](README.md), [llms.txt](llms.txt) if it remains a wayfinder-level pattern, [AGENTS.md](AGENTS.md), [openclaw/SKILL.md](openclaw/SKILL.md), plus private `site/llms-full.txt`, `site/openapi.json`, `site/updates.txt`, and `site/humans/changelog.md` **Add or change project transfer surface** (v1.59 two-party SIWX handoff: initiate / preview / accept / cancel / list, `TransferFreezeError`, `tier_status.incoming_transfers[]`, `projects[].secrets_rotation_advised`) | `sdk/src/namespaces/transfers.ts` (the `Transfers` class exposed at `r.admin.transfers`), `sdk/src/namespaces/admin.ts` (sub-namespace wiring), `sdk/src/namespaces/tier.ts` (TierStatusResult extensions), `sdk/src/errors.ts` (`TransferFreezeError` + `isTransferFreezeError`), `sdk/src/kernel.ts` (409 PROJECT_HAS_PENDING_TRANSFER detection), `sdk/src/index.ts` (re-exports), `src/tools/transfers.ts` (six MCP tools), `src/index.ts` (registration), `src/errors.ts` (PROJECT_HAS_PENDING_TRANSFER guidance), `cli/lib/transfer.mjs` (CLI), `cli/cli.mjs` (dispatch), `openclaw/scripts/transfer.mjs` (re-export), `sync.test.ts` (`SURFACE` capabilities + `SDK_BY_CAPABILITY` entries + module list in `parseCliCommands`/`parseOpenClawCommands`), [SKILL.md](SKILL.md) (Project transfer section), [openclaw/SKILL.md](openclaw/SKILL.md) (Project transfer section), plus [cli/llms-cli.txt](cli/llms-cli.txt), [sdk/llms-sdk.txt](sdk/llms-sdk.txt), [llms-mcp.txt](llms-mcp.txt) for the comprehensive surface references, and private `site/llms-full.txt`, `site/openapi.json`, `site/updates.txt`, `site/humans/changelog.md` for the HTTP API + changelog entries. +**Add or change the operator (human/email) session surface** (`r.operator` device-auth + `overview`; `run402 operator login/logout/overview/whoami`; `core/operator-session.ts` cache) | `core/src/operator-session.ts` (cache primitive + test), `sdk/src/namespaces/operator.ts` + `sdk/src/index.ts` (namespace wiring + `export type *`), `cli/lib/operator.mjs` + `cli/cli.mjs` (dispatch + top-level HELP), `openclaw/scripts/operator.mjs` (re-export), `sync.test.ts` (`SURFACE` rows with **`mcp: null`** + `SDK_BY_CAPABILITY` + the `parseCliCommands`/`parseOpenClawCommands` module list + `operator.devicePoll` in `SDK_ONLY_METHODS`), `cli-help.test.mjs` MATRIX, [cli/llms-cli.txt](cli/llms-cli.txt), [sdk/llms-sdk.txt](sdk/llms-sdk.txt) (namespace section + count), [sdk/README.md](sdk/README.md) (catalog row + count), [README.md](README.md) + [AGENTS.md](AGENTS.md) (namespace count; AGENTS Shared Core entry), [cli/README.md](cli/README.md), [openclaw/SKILL.md](openclaw/SKILL.md). **No MCP tool by design — skip [SKILL.md](SKILL.md) / [llms-mcp.txt](llms-mcp.txt).** Gateway device-auth bridge (RFC 8628 endpoints) lives in `run402-private`. **Change `@run402/functions` surface** | edit `packages/functions/src/` AND `packages/functions/README.md` in the **private** repo (`kychee-com/run402-private`), then in this public repo update [AGENTS.md](AGENTS.md) (Functions library section), [SKILL.md](SKILL.md), [llms-mcp.txt](llms-mcp.txt), [sdk/llms-sdk.txt](sdk/llms-sdk.txt), and [openclaw/SKILL.md](openclaw/SKILL.md) (in-function helpers section in each). Publish via `/publish-functions` in the private repo. **Change `@run402/astro` surface** (new `` prop, integration option, data-driven pattern guidance, runtime helper) | edit `astro/src/` and [astro/README.md](astro/README.md) and [astro/CHANGELOG.md](astro/CHANGELOG.md). If the change touches the AssetRef-persistence vs manifest pattern guidance, also reflect it in [AGENTS.md](AGENTS.md) (Astro integration section). Publish via `/publish-astro` (OIDC Trusted Publisher → `.github/workflows/publish-astro.yml`) — independent of the SDK/CLI/MCP lockstep. **Add SSR Runtime / cache layer surface** (run402 `cache` / `dev` / `doctor` / `init astro` / `logs --request-id`; `r.cache` SDK; SSR adapter hooks; R402_* error codes; cache hot-path debug headers) | edit `cli/lib/.mjs` (impl), `cli/cli.mjs` (dispatch), `openclaw/scripts/.mjs` (CLI parity re-export), [cli/llms-cli.txt](cli/llms-cli.txt) (R402_* codes table + new sections), `sdk/src/namespaces/cache.ts` + `sdk/src/index.ts` (type re-export) + [sdk/llms-sdk.txt](sdk/llms-sdk.txt) (`r.cache` namespace), `astro/src/` + [astro/README.md](astro/README.md) + [astro/CHANGELOG.md](astro/CHANGELOG.md) (preset + adapter + detectors + ``), [AGENTS.md](AGENTS.md) (namespace count + v1.52 architecture section), [README.md](README.md) (namespace count + SSR pitch), [SKILL.md](SKILL.md) + [openclaw/SKILL.md](openclaw/SKILL.md) (Astro SSR runtime + ISR cache pattern section), [llms.txt](llms.txt) (vision bullet), [sdk/README.md](sdk/README.md) (namespace catalog table — bump count + cache row), `sync.test.ts` (`SURFACE` capabilities + `SDK_BY_CAPABILITY` entries + module list in `parseCliCommands`/`parseOpenClawCommands` + `SDK_ONLY_METHODS` for flag-variant convenience methods). Cross-repo to `run402-private`: edit `packages/gateway/src/` (substrate + hot path + apply-v1 plumbing), `packages/functions/src/` (SDK ALS + `cache.*`), `openspec/changes/astro-ssr-runtime/`, `site/llms-full.txt` (new `/cache/v1/*` endpoints), `site/openapi.json` (cache endpoint schemas), `site/updates.txt` + `site/humans/changelog.md` (user-visible feature entry). diff --git a/openclaw/SKILL.md b/openclaw/SKILL.md index 107a748f..11579e51 100644 --- a/openclaw/SKILL.md +++ b/openclaw/SKILL.md @@ -1066,6 +1066,19 @@ Other allowance options: - Coinbase AgentKit — MPC wallet on Base with built-in x402. - AgentPayy — auto-bootstraps an MPC wallet on Base via Coinbase CDP. +## Operator session (human / email) + +The **operator** is the human, identified by email — distinct from the **agent** (your wallet). One browser login spans every wallet that verified your email, so `operator overview` returns the cross-wallet union. For a single wallet's state, use `run402 status` (there is no `operator status`). + +```bash +run402 operator login # browser device-auth (RFC 8628, like `aws sso login`): magic-link OR passkey +run402 operator overview # account view across ALL wallets controlling your email (requires login) +run402 operator whoami # cached session: email, wallets, expiry - local, no network +run402 operator logout # revoke server-side + clear the local cache +``` + +`login` prints a verification URL + short code (and opens the browser on a TTY); you approve in the browser, and the CLI brokers the resulting session token (cached at the base config dir, ~30m TTL, shared across named wallets). `overview` requires login and never falls back to a single wallet's slice. These are CLI-only (no MCP tool) by design — MCP authenticates as the agent, not the human. + ## Troubleshooting | You see | Likely cause / fix | diff --git a/sdk/README.md b/sdk/README.md index 7e3bc190..8e5c934e 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -54,7 +54,7 @@ const r = new Run402({ The `CredentialsProvider` interface has two required methods (`getAuth`, `getProject`) plus optional ones (`saveProject`, `removeProject`, `setActiveProject`, `readAllowance`, `saveAllowance`, …) for hosts that want full sticky-default behavior. -## Namespaces (22) +## Namespaces (23) | Namespace | Highlights | |---|---| @@ -81,6 +81,7 @@ The `CredentialsProvider` interface has two required methods (`getAuth`, `getPro | `allowance` | `status`, `create`, `export`, `faucet` | | `service` | `status`, `health` (no auth, no setup — works on a fresh install) | | `admin` | Operator/admin endpoints: messages/contact, per-project finance (`getProjectFinance`) | +| `operator` | **The human / email principal** — the *operator session*, distinct from the agent's per-wallet SIWX identity (and from platform-`admin`). `deviceStart`, `devicePoll`, `overview({ token })`, `revoke({ token })`: browser-delegated device-authorization (RFC 8628, the `aws sso login` model). `overview` returns the email-union across every wallet that verified the email; a single wallet's own view stays `run402 status`. Drives `run402 operator login/overview/whoami/logout`. No MCP tool by design — MCP authenticates as the agent, not the human. | CLI-style aliases are available for agent ergonomics: `r.image` aliases `r.ai`, and common command names such as `r.billing.balance`, `r.auth.magicLink`, diff --git a/sdk/llms-sdk.txt b/sdk/llms-sdk.txt index 0aacb557..01373f3d 100644 --- a/sdk/llms-sdk.txt +++ b/sdk/llms-sdk.txt @@ -591,7 +591,7 @@ The helper makes raw `fetch()` calls to the project's own gateway endpoints usin ## Namespaces — full surface -The `Run402` class exposes 21 namespaces. Click into the SDK source for full method signatures. +The `Run402` class exposes 22 namespaces. Click into the SDK source for full method signatures. > Reference tables below use plain fences, not `ts` fences. They document the > type surface in compact form — they are not runnable programs. Runnable example @@ -783,6 +783,37 @@ isCiSessionCredentials(credentials): boolean CI error-code unions include binding errors (`invalid_route_scopes`, `nonce_replay`, `delegation_statement_mismatch`, `signer_mismatch`, `duplicate`), token-exchange errors (`invalid_token`, `access_denied`, `event_not_allowed`, `repository_id_mismatch`, `ambiguous_binding`), and CI deploy errors (`payment_required`, `insufficient_scope`, `forbidden_spec_field`, `forbidden_plan`, `CI_ROUTE_SCOPE_DENIED`). Preserve unknown future strings as opaque gateway codes. +### `r.operator` + +The **human / email principal** — the *operator session* — distinct from the agent's per-wallet SIWX identity (and from the platform-`admin` "operator" endpoints, which are a different thing). A wallet signature can only ever return one wallet's slice; the operator session proves control of the *email* and returns the union across every wallet that verified it. + +Authentication is browser-delegated via an OAuth 2.0 device-authorization grant (RFC 8628, the `aws sso login` model): the SDK never performs WebAuthn — the browser does, via the existing magic-link or passkey web flow — and the SDK brokers the resulting operator-session token (a read-only `operator.read` bearer, ~30-min TTL, ~12h absolute cap, revocable). + +``` +operator.deviceStart({ clientName? }): Promise + // POST /agent/v1/operator/session/device (unauthenticated). Returns + // { device_code, user_code, verification_uri, verification_uri_complete?, expires_in, interval }. + +operator.devicePoll(deviceCode): Promise + // POST /agent/v1/operator/session/device/token. RFC 8628 states are returned as + // DATA, not thrown: { kind: "approved", session } | { kind: "authorization_pending" } + // | { kind: "slow_down" } | { kind: "access_denied" } | { kind: "expired_token" }. + // `session` is the OperatorSessionToken { operator_session_token, token_type, + // expires_in, absolute_expires_at, email, wallets[] }. + +operator.overview({ token? }): Promise + // GET /agent/v1/operator/overview. With `token` (the operator-session bearer) → + // the email-union (scope.kind "email"): rollup, billing_accounts[], wallets[] + // (each with projects + email_binding), advisories[]. Without `token` it falls + // back to the provider's default auth (SIWX) → that one wallet's slice. + +operator.revoke({ token }): Promise + // POST /agent/v1/operator/session/revoke (operator-session bearer). Idempotent, + // 204. Server-side revoke is instant (no positive-validity cache). +``` + +The session cache is Node-only and lives in `core` (`{base}/operator-session.json`, mode 0600, base config dir — email-scoped, so it is shared across local named wallets). The CLI (`run402 operator login/logout/overview/whoami`) brokers it; `whoami` is a pure local-cache read with no SDK method. No MCP tool by design — MCP authenticates as the agent, not the human. + ### `r.sites` `deployDir` is exposed only on the Node entry (`@run402/sdk/node`); the