The three terminal states (deployed, failed, cancelled) and every refusal
POST /build-sessions can return. Each says what happened, whether anything was created, and
the one thing the user can do next. Refusals at submit keep the form's values.
(d1) Deployed — terminal; the app tile appears on Applications
Launching
Building
Deploying
Deployed
“Expense tracker” is live in Acme Corp
It's now on your Applications page and in the menu for members who can see it. You're
recorded as its creator; Acme Corp owns it.
(d7) 403 — not an active member of the org / no apps:register there (in place, never a sign-in redirect)
You can't build apps in Acme Corp
Building into an organization needs an active membership and permission to register apps
there. Ask an Acme Corp admin, or build in your personal workspace.
(d8) 409 no_personal_org — personal chosen, but the account has no personal workspace
You don't have a personal workspace
Choose an organization you belong to instead.
(d9) 429 — rate limited
Too many builds started
Wait a minute before starting another. Your form is kept.
(d10) 404 — unknown session, or one you aren't entitled to see (never 403)
(d11) Polling error — last known state kept, retrying (not a failed build)
Can't reach the server
Showing the last known status (Building, 2 min ago). Retrying…
Deployed. The tile comes from the normal GET /apps list — no special-casing; the flow
invalidates that query when the session turns deployed and links appSlug. Open app uses
the app's normal route. Failed vs refused:failed is a session that exists (from the agent
callback, or 502 launch_failed); a 503/403/409/429 at submit
created nothing. Copy never blames the user for a platform fault. Authz.403 is shown in place; only 401 re-authenticates. A session the caller can't
see is 404 by contract — the UI never distinguishes "forbidden" from "missing".
Test hooks: [data-frame='04-build-outcomes'] · [data-session-status='deployed'] ·
[data-app='expense-tracker'] · [data-action='open-app'] ·
[data-session-status='failed'] · [data-session-status='cancelled'] ·
[data-action='start-new-build'] · [data-error-code='launch_failed'] ·
[data-error-code='builder_unavailable'] · [data-error-code='feature_disabled'] ·
[data-error-code='FORBIDDEN'] · [data-error-code='no_personal_org'] ·
[data-http='429'] · [data-http='404'] · [data-state='stale'].