Public: anyone can read this; the crew can change it.

A spawned child's own keys and address, FORGE_APP_SSH verbatim, and one sealed, capped API key #747

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Closes #576. **Stacked on #716 (#712), which is stacked on #704 (#575)**: merge those first. This pull's own commit is "A spawned child's own keys and address…".

shipped production is serving it for issue #576 — its issue is already done deploy d5b2fe2

opened this

Closes #576. Stacked on #716 (#712), which is stacked on #704 (#575): merge those first. This pull's own commit is "A spawned child's own keys and address…".

The child's own keys. Spawn makes the child's secret.key (32 bytes, 0600) and SSH host key in the child's own directory, so they exist before first boot. A test compares them with the parent's.

Nothing points into the parent. The child's config paths resolve inside its own directory. parent.json holds only upstream, name, org, url, keepAccess, with no paths and no secrets. A key sealed in the child cannot be opened with the parent's secret.key (tested).

Its domain. The child's address is <name>.<parent's host>, from the placement. It is recorded as url in parent.json and shown on the child's home as "Your forge: maria.forge.test".

FORGE_APP_SSH verbatim. A hosted forge gets appSsh from FORGE_APP_SSH (in main.ts, only when hosted). sshCommand returns it word for word for the forge's own terminal. The SSH keys page says "The terminal is off on this forge." when there is neither a listener nor a host command. terminalFor now reads the listener port itself, so a host command never hides that an app's terminal is off.

The owner's open decision, as designed here. The one credential a spawner may give a child is modelKey, an API-billed key (sk-ant-api…), with a required keyCapUsd daily cap from $1 to $1000.

  • A subscription token (sk-ant-oat…) is refused: "a person's own plan and never goes to a child". A key without a cap, or a cap without a key, is refused.
  • The key never enters the plan, the dry run (which says only "its own model key (API-billed, sealed, never shown again), capped at $5 a day per app"), the answer, the ledger or the idempotency table.
  • In the child it is sealed with the child's own key as the account starter, granted to its organisation's crew, and each app's daily ceiling is the cap.
  • The MCP spawn tool refuses modelKey: a secret never passes through an agent's conversation; the error points to the API and the child's Subscriptions page.
  • No key is a clean state: the child's pages say the crew has no model key yet (#712).
  • A whole-life starter budget, rather than a daily cap, is #601's. It would need a migration number, so I added none.

The path: the person claims the forge and lands on a home that shows "Your forge: maria.forge.test", their app, and (without a key) the line saying the crew cannot start yet. An admin can open SSH keys and read whether the terminal is on and how to reach it.

Removes: nothing. It adds one line on a spawned forge's home and one sentence on the keys page.

Tests: test/spawn-keys.test.ts (8, in the gate): the oauth token, a missing cap, a cap with no key and a zero cap are refused; MCP refuses a key; the dry run and the answer never show the key; no parent file, ledger or idempotency row holds it, nor any child file in clear text; the child's keys differ from the parent's; the key opens only with the child's key and is granted to the org with a $5 ceiling; the config stays inside the child; the address is recorded and shown; "terminal is off" appears, then FORGE_APP_SSH is printed verbatim. Spawn, first-boot, child-apps, studio, MCP and apps suites pass.

Full gate under the lock: the only failure that was mine, "claim" missing from the reserved names (the /claim route from #704), is fixed on #704 and carried up the stack. Still failing: reserved-names on llms.txt, which also fails on main (#705), and the crew.test "assignment" load flake.

Looks (a real spawned child, 390 and 1280 px): on the phone home, "Your forge: maria.forge.test" above the cost line, the key note, then Your apps. On the desktop SSH keys page, "The terminal is off on this forge." above the key list.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs