Bounded deploy
Use this skill to initialize, verify, ship, configure, and share a Bounded app.
Policy authoring belongs in bounded-backend; client code and app-user auth
belong in bounded-frontend.
Default workflow
For a new project or a normal release, read
docs/quickstart.md. The expected path is:
bounded init
bounded verify
bounded deploy --create --name my-app
bounded init reuses a saved web session or opens hosted browser login. It
writes public bounded.json and policy.json; credentials never belong in
either file.
Task router
Read only the reference needed for the current task.
| Task |
Read |
| First setup, normal verify/deploy, publish a site, multiple app IDs from one project |
docs/quickstart.md |
| Normal web account login, session refresh, headless OTP, account switching |
docs/accounts.md |
| Hosted web frontend, preview, private/public access |
frontend-hosting.md |
| Multi-environment policies: per-env app id, constants, schedule cadence, function scoping |
docs/environments.md |
Build an app from a prompt, iterate with edit, watch/cancel/gate a run |
docs/cli-reference.md (Prompt-driven builds) |
Source sync, --with-source, clone, pull |
docs/source-sync.md |
| Port an existing app (Supabase, Firebase, Express, Next, a key-holding backend) onto Bounded; decide what becomes rules, functions, schedules, or a capability |
docs/porting-an-existing-app.md |
Third-party API discovery, readiness, and requests: bounded services search/describe/request/status |
docs/cli-reference.md (Capabilities) |
Open dry run and rehearsal for an oApp: bounded oapp preflight, bounded oapp rehearse |
docs/cli-reference.md (Open Apps) |
| Custom domains and vanity slugs |
docs/domains.md |
Share, access, owner mismatch, 401/403 |
docs/access-playbook.md |
| Delete an app permanently (browser-confirmed, owner only) |
docs/cli-reference.md (apps delete) |
| Uncommon command or exact flag lookup |
docs/cli-reference.md |
| Local signing keys, profiles, CI key auth, legacy key-owned apps |
docs/key-and-account-safety.md |
Do not load the local-key reference during normal onboarding. It is an advanced
alternative for users who explicitly request local signing, CI key auth, an
account profile, or recovery of an existing key-owned app.
Incident router
503 + proof_substrate_unavailable (retryable: true) from bounded verify: the prover lane is warming up or busy.
This response does not establish policy correctness.
Retry the same policy UNCHANGED using the bounded protocol below.
Wait 30 seconds, then rerun the same bounded verify; make at most 3 attempts total, meaning the initial attempt plus 2 retries.
If the third attempt still returns this error, stop and tell the user the proving service is degraded.
Include the correlationId when present.
Do not edit the policy, switch accounts, or create a new app.
This retry protocol applies only to bounded verify.
Never use it to retry bounded deploy.
In particular, never retry bounded deploy --create because it can create another app.
deploy_in_progress, operationId, or recoveryCommand: use only the exact
owner-visible recovery command with unchanged inputs, then let the CLI poll.
See deploy recovery.
- An error with
code/state but NO recoveryCommand is terminal for that
operation - 410 policy_operation_unrecoverable and the abandoned, superseded,
target-mismatch and manual-intervention states. Re-running the recovery can
never commit it; run a fresh bounded deploy (or escalate, when the message
says operator review). Never invent a recovery command for these.
onchain_creation_pending, onchain_creation_unreadable, or
onchain_creation_superseded (all 409): the app's mainnet creation never
finished - its on-chain owner is not proven at finalized yet, so nothing can
be deployed to it and nothing has been signed or spent.
Re-run the SAME bounded deploy for that app id: the platform resumes the
original creation and lifts the fence as soon as the account is finalized.
Never re-run --create, and never create a replacement app - the first app's
on-chain account is already paid for and a second one strands that rent.
onchain_creation_owner_conflict (409): the app's on-chain account is
finalized under a wallet the creation did not intend. That is an integrity
fault, not a state to retry; escalate for operator review.
- Unsure which applies, or unsure whether a fresh deploy is safe: run the
read-only
bounded deploy status --json first. It reports what holds the
deploy slot and a freshDeploySafe verdict, and it never mutates anything.
- Before a deploy, to know whether it will LAND (not just whether the slot is
free): run the read-only
bounded deploy preflight --json. Deploys are metered
against the app's credit balance - each leg charges its actual Cloudflare infra
cost (sub-cent; no per-tier deploy cap, no minimum), so an out-of-credit app is
refused. Preflight reports the credit balance + a would_likely_admit/refuse/ unknown verdict so you can tell the user "this will land" or "top up first"
before spending time on the deploy. It never mutates anything.
402 deploy_credit_insufficient on site deploy: billing, not identity. The
deploying account has no spendable credit for the deploy's infra cost. Run
bounded billing status, add credit with bounded billing topup --credits <n>,
then retry under the same identity. Switching accounts never helps here.
site_control_denied (a 403), wrong owner, or unexpected 401/403: run
bounded whoami and bounded access --app-id <id> before changing identity.
See access playbook.
project_limit_exceeded: inventory apps; never delete or repurpose one
automatically. If the user decides an app should go, bounded apps delete
exists but always requires the human to confirm in the browser. See
billing.
boundary_violation: changing accounts will not bypass an app boundary. Use
the boundary-lock section of the access playbook.
Release rules
- Read
bounded.json first in an existing app.
- Regenerate a generated
policy.json before both verify and deploy.
bounded verify is the fast proof loop; bounded deploy still fails closed
if the exact deployed policy does not pass its release gate.
- After a release-critical deploy, use
bounded apps inspect --app-id <id> --json to confirm the active policy and
runtime publication before measuring behavior.
- Resolve the hosted URL from the exact site receipt or
bounded domains list --app-id <id> --env <environment> --json. Do not invent
a hostname.
- Share control-plane access with
bounded share <email-or-wallet> --role admin|developer|viewer|billing.
- Do not commit credentials, web sessions, refresh tokens, or provider secrets.
1---2name: bounded-deploy3description: Ship and configure a Bounded app: CLI setup, browser-backed developer login, verify and deploy, hosted frontend publishing, environments, source sync, domains, bounded.json, collaborators, and release recovery. Part of the Bounded skill family.4---56# Bounded deploy78Use this skill to initialize, verify, ship, configure, and share a Bounded app.9Policy authoring belongs in **bounded-backend**; client code and app-user auth10belong in **bounded-frontend**.1112## Default workflow1314For a new project or a normal release, read15[docs/quickstart.md](docs/quickstart.md). The expected path is:1617```bash18bounded init19bounded verify20bounded deploy --create --name my-app21```2223`bounded init` reuses a saved web session or opens hosted browser login. It24writes public `bounded.json` and `policy.json`; credentials never belong in25either file.2627## Task router2829Read only the reference needed for the current task.3031| Task | Read |32|---|---|33| First setup, normal verify/deploy, publish a site, multiple app IDs from one project | [docs/quickstart.md](docs/quickstart.md) |34| Normal web account login, session refresh, headless OTP, account switching | [docs/accounts.md](docs/accounts.md) |35| Hosted web frontend, preview, private/public access | [frontend-hosting.md](../bounded-frontend/docs/frontend-hosting.md) |36| Multi-environment policies: per-env app id, constants, schedule cadence, function scoping | [docs/environments.md](docs/environments.md) |37| Build an app from a prompt, iterate with `edit`, watch/cancel/gate a run | [docs/cli-reference.md](docs/cli-reference.md) (Prompt-driven builds) |38| Source sync, `--with-source`, clone, pull | [docs/source-sync.md](docs/source-sync.md) |39| Port an existing app (Supabase, Firebase, Express, Next, a key-holding backend) onto Bounded; decide what becomes rules, functions, schedules, or a capability | [docs/porting-an-existing-app.md](docs/porting-an-existing-app.md) |40| Third-party API discovery, readiness, and requests: `bounded services search/describe/request/status` | [docs/cli-reference.md](docs/cli-reference.md) (Capabilities) |41| Open dry run and rehearsal for an oApp: `bounded oapp preflight`, `bounded oapp rehearse` | [docs/cli-reference.md](docs/cli-reference.md) (Open Apps) |42| Custom domains and vanity slugs | [docs/domains.md](docs/domains.md) |43| Share, access, owner mismatch, `401`/`403` | [docs/access-playbook.md](docs/access-playbook.md) |44| Delete an app permanently (browser-confirmed, owner only) | [docs/cli-reference.md](docs/cli-reference.md) (`apps delete`) |45| Uncommon command or exact flag lookup | [docs/cli-reference.md](docs/cli-reference.md) |46| Local signing keys, profiles, CI key auth, legacy key-owned apps | [docs/key-and-account-safety.md](docs/key-and-account-safety.md) |4748Do not load the local-key reference during normal onboarding. It is an advanced49alternative for users who explicitly request local signing, CI key auth, an50account profile, or recovery of an existing key-owned app.5152## Incident router5354- `503` + `proof_substrate_unavailable` (`retryable: true`) from `bounded verify`: the prover lane is warming up or busy.55 This response does not establish policy correctness.56 Retry the same policy UNCHANGED using the bounded protocol below.57 Wait 30 seconds, then rerun the same `bounded verify`; make at most 3 attempts total, meaning the initial attempt plus 2 retries.58 If the third attempt still returns this error, stop and tell the user the proving service is degraded.59 Include the `correlationId` when present.60 Do not edit the policy, switch accounts, or create a new app.61 This retry protocol applies only to `bounded verify`.62 Never use it to retry `bounded deploy`.63 In particular, never retry `bounded deploy --create` because it can create another app.64- `deploy_in_progress`, `operationId`, or `recoveryCommand`: use only the exact65 owner-visible recovery command with unchanged inputs, then let the CLI poll.66 See [deploy recovery](docs/cli-reference.md#recover-an-in-progress-policy-deploy).67- An error with `code`/`state` but NO `recoveryCommand` is terminal for that68 operation - `410 policy_operation_unrecoverable` and the abandoned, superseded,69 target-mismatch and manual-intervention states. Re-running the recovery can70 never commit it; run a fresh `bounded deploy` (or escalate, when the message71 says operator review). Never invent a recovery command for these.72- `onchain_creation_pending`, `onchain_creation_unreadable`, or73 `onchain_creation_superseded` (all `409`): the app's mainnet creation never74 finished - its on-chain owner is not proven at finalized yet, so nothing can75 be deployed to it and nothing has been signed or spent.76 Re-run the SAME `bounded deploy` for that app id: the platform resumes the77 original creation and lifts the fence as soon as the account is finalized.78 Never re-run `--create`, and never create a replacement app - the first app's79 on-chain account is already paid for and a second one strands that rent.80- `onchain_creation_owner_conflict` (`409`): the app's on-chain account is81 finalized under a wallet the creation did not intend. That is an integrity82 fault, not a state to retry; escalate for operator review.83- Unsure which applies, or unsure whether a fresh deploy is safe: run the84 read-only `bounded deploy status --json` first. It reports what holds the85 deploy slot and a `freshDeploySafe` verdict, and it never mutates anything.86- Before a deploy, to know whether it will LAND (not just whether the slot is87 free): run the read-only `bounded deploy preflight --json`. Deploys are metered88 against the app's credit balance - each leg charges its actual Cloudflare infra89 cost (sub-cent; no per-tier deploy cap, no minimum), so an out-of-credit app is90 refused. Preflight reports the credit balance + a `would_likely_admit/refuse/91 unknown` verdict so you can tell the user "this will land" or "top up first"92 before spending time on the deploy. It never mutates anything.93- `402 deploy_credit_insufficient` on `site deploy`: billing, not identity. The94 deploying account has no spendable credit for the deploy's infra cost. Run95 `bounded billing status`, add credit with `bounded billing topup --credits <n>`,96 then retry under the same identity. Switching accounts never helps here.97- `site_control_denied` (a `403`), wrong owner, or unexpected `401`/`403`: run98 `bounded whoami` and `bounded access --app-id <id>` before changing identity.99 See [access playbook](docs/access-playbook.md).100- `project_limit_exceeded`: inventory apps; never delete or repurpose one101 automatically. If the user decides an app should go, `bounded apps delete`102 exists but always requires the human to confirm in the browser. See103 [billing](../bounded/docs/billing.md).104- `boundary_violation`: changing accounts will not bypass an app boundary. Use105 the boundary-lock section of the access playbook.106107## Release rules108109- Read `bounded.json` first in an existing app.110- Regenerate a generated `policy.json` before both verify and deploy.111- `bounded verify` is the fast proof loop; `bounded deploy` still fails closed112 if the exact deployed policy does not pass its release gate.113- After a release-critical deploy, use114 `bounded apps inspect --app-id <id> --json` to confirm the active policy and115 runtime publication before measuring behavior.116- Resolve the hosted URL from the exact site receipt or117 `bounded domains list --app-id <id> --env <environment> --json`. Do not invent118 a hostname.119- Share control-plane access with120 `bounded share <email-or-wallet> --role admin|developer|viewer|billing`.121- Do not commit credentials, web sessions, refresh tokens, or provider secrets.