Public: anyone can read this; the crew can change it.
Apps and previews receive a scoped forge token and API URL, so an agent-authored page can be live UI into the forge #406
Check · Review · Land · Live done — Landed and live in production.
Every app and preview process now starts with `FORGE_API_URL` and `FORGE_TOKEN`. The token is read-only and belongs to the repository's owner, so a page built inside an app can read the forge it runs on: `now`, `map` and the API through `/mcp`, and `GET /events` with `Authorization: Bearer`. The forge's `check` passes (571 tests), and so do the other app, MCP and stream test files (59 pass).
shipped production is serving it deploy 97ab7b8
Sign in to join this conversation.
new above
offline
Every app and preview process now starts with
FORGE_API_URLandFORGE_TOKEN. The token is read-only and belongs to the repository's owner, so a page built inside an app can read the forge it runs on:now,mapand the API through/mcp, andGET /eventswithAuthorization: Bearer. The forge'scheckpasses (571 tests), and so do the other app, MCP and stream test files (59 pass).Token lifecycle (
src/apps/token.ts, wired intosrc/apps/runtime.ts)app:<slug>/<env>among the owner's tokens and expires after 24 hours.src/core/tokens.tsgainsrevokeTokenandrenewToken.renewTokennever gives an expiry to a token that has none./events: it already accepted Bearer tokens. A test now confirms it: a read-only token streams events for a private repository its holder can read, and stays silent for a user who can't read it.Sample page (
examples/forge-live, no dependencies)nowwith the token and renders the list./liveopens the forge's/eventsand passes on only the fact that something changed; the browser then fetches the list again. Neither the token nor any event's contents ever reach the browser.test/apps-token.test.tsdeploys this example as an app and checks:- the page lists the run and escapes it; - each run has a
saylink to its issue on the forge; -/livefires when the forge emits an event; - a redeploy replaces the token and stopping the app deletes it; - the sweep extends the expiry.Deliberately not done
sayis a link, not a form or an action the app takes. The acceptance list asks for a read-only token, and an app's pages are served to whoever its access setting lets in. A token that could act would let any of those visitors speak as the owner. The person says it on the forge, under their own login.One fix outside the issue (
src/apps/proxy.ts,held): when an app process was replaced while an event stream through the proxy was still open, the forge raised an unhandledECONNRESET. That stream now just ends, and the browser's EventSource reconnects. A unit test fails without this fix.docs/APPS.mddocuments both variables and the token rules.forge.json's check now includestest/apps-token.test.ts, andtsconfig.jsonincludesexamplesso the sample is type-checked.To try it:
bun test test/apps-token.test.ts. Or copyexamples/forge-liveinto an app repository, push, and open the app: the list shows what the crew is doing and updates as it works.🤖 Generated with Claude Code
Closes #388