carlos / platform Public

Temporary static sites: self-expiring tmp- apps, trashed at expiry, purged 3 days later

Adds a "temporary" static app for LLM scratchpads and one-shot customer
pages: `carlos deploy --temporary [--ttl 3d] ./dir` creates an app named
tmp-<label> that moves to the Trash when its TTL runs out (default 7d,
1h..30d) and is purged 3 days after that instead of 30. `carlos apps
ttl|keep|list` move the expiry, make an app permanent, and show every
app with its expiry or purge date. Spec:
docs/superpowers/specs/2026-09-25-temporary-static-sites-design.md
(rev 9; rulings 1-8 are Paul's).

How it holds together:
- All lifecycle state lives in four new console `apps` columns
  (expires_at, restoring, purge_after, purge_for). Nothing new is written
  to the bucket and box code is unchanged, so bucket write access cannot
  make an app temporary and an old box keeps its 30-day behaviour.
- Every transition (expire, trash, restore, keep, ttl, purge) runs under a
  per-app mutex (account lock first where both are taken), settles the row
  against the trash marker, and re-checks before acting.
- A 5-minute console pass expires due apps through the ordinary trash path
  and early-purges through release.PurgeAppIfTrashedAt, which acts only if
  the marker's clock matches the row's purge_for. The empty-bucket
  tripwire (now ignoring trash markers) holds every absence-based action.
- The tmp- namespace is reserved at every door that can create a name
  (claims, rename, grants, backfill, carlos add), so an expiry can only
  drop routes a temporary app created. Temporary apps stay static and
  platform-hosted: domains (incl. the instance catch-all), binaries,
  stores, private storage, email, relay, sidecars, fleet placement,
  production and control plane are refused until `carlos apps keep`.
- Creation is off until CARLOS_TEMPORARY_APPS=1, and temporary creates
  have their own 50/day budget. Cap: 20 live temporary apps per account.
- Every displayed purge date (Trash page, trash API, CLI, delete
  confirmation) comes from one effectivePurgeAt.

Reviewed: spec through 9 Astra rounds, plan through 7, each of 12 tasks
by a separate reviewer (4 needed one fix round), a Fable whole-branch
review, and an Opus review of the origin/main merge resolution. All user-
facing copy (105 strings) approved by Paul in copy review. Gate: build,
vet, gofmt, go test ./..., darwin and windows builds.

Rollout (needs approval, not done here): roll every box first, scan box
registries and the console's apps/owners tables for tmp- names, then set
CARLOS_TEMPORARY_APPS=1 on the console.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev f0606ae19046a107c44f9102ebbe45846b10310c parent 2b2cc87
77 files changed, +13278 −183
  • apimode.go +160 −0
  • apps.go +83 −28
  • apps_test.go +74 −19
  • cli.go +15 −0
  • cli_test.go +36 −0
  • cmd/console/main.go +7 −0
  • deploy.go +32 −2
  • docs/site/cli.md +29 −4
  • docs/superpowers/plans/2026-09-26-temporary-static-sites-copy.md +113 −0
  • docs/superpowers/plans/2026-09-26-temporary-static-sites.md +6342 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R1.md +23 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R2.md +23 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R3.md +42 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R4.md +41 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R5.md +42 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R6.md +43 −0
  • docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R7.md +39 −0
  • docs/superpowers/plans/CODEX-REVIEW-BRIEF-TEMPORARY-SITES-PLAN.md +45 −0
  • docs/superpowers/specs/2026-09-25-temporary-static-sites-design.md +619 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R1.md +21 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R2.md +38 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R3.md +40 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R4.md +42 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R5.md +48 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R6.md +24 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R7.md +40 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R8.md +30 −0
  • docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R9.md +18 −0
  • docs/superpowers/specs/CODEX-REVIEW-BRIEF-TEMPORARY-SITES.md +60 −0
  • internal/console/apicli.go +119 −51
  • internal/console/apidomains.go +3 −0
  • internal/console/apiinstances.go +12 −0
  • internal/console/apimail.go +12 −0
  • internal/console/apipipeline.go +8 −0
  • internal/console/apirelay.go +3 −0
  • internal/console/apisidecars.go +6 −0
  • internal/console/apistore.go +6 −0
  • internal/console/apistore_provision.go +3 −0
  • internal/console/apitemporary.go +431 −0
  • internal/console/apitemporary_test.go +462 −0
  • internal/console/applocks.go +59 −0
  • internal/console/appsettings.go +48 −3
  • internal/console/authcli.go +25 −0
  • internal/console/controlplane.go +14 −0
  • internal/console/deletion_test.go +53 −0
  • internal/console/domainattach.go +3 −0
  • internal/console/domaincatchall.go +12 −0
  • internal/console/expirypass.go +253 −0
  • internal/console/expirypass_test.go +339 −0
  • internal/console/fleets.go +8 −0
  • internal/console/instanceprivatestore.go +3 −0
  • internal/console/materialize.go +22 −6
  • internal/console/ownership.go +44 −5
  • internal/console/restore.go +192 −0
  • internal/console/restore_test.go +445 −0
  • internal/console/server.go +78 −11
  • internal/console/settle.go +127 −0
  • internal/console/settle_test.go +245 −0
  • internal/console/store.go +151 −39
  • internal/console/svcprincipal.go +7 −0
  • internal/console/temphook_test.go +66 −0
  • internal/console/templates/app_settings.html +3 −2
  • internal/console/templates/appnav.html +7 −0
  • internal/console/templates/apps.html +2 −2
  • internal/console/templates/trash.html +11 −8
  • internal/console/tempnames_test.go +95 −0
  • internal/console/temprefusal.go +51 −0
  • internal/console/temprefusal_test.go +343 −0
  • internal/console/tempregion_test.go +68 −0
  • internal/console/tempstore.go +219 −0
  • internal/console/tempstore_test.go +233 −0
  • internal/console/view.go +4 −1
  • internal/release/temporary.go +51 −0
  • internal/release/temporary_test.go +86 −0
  • internal/release/trash.go +21 −2
  • temporary.go +306 −0
  • temporary_test.go +350 −0

CI passed — run details

apimode.go

Loading diff…

apps.go

Loading diff…

apps_test.go

Loading diff…

cli.go

Loading diff…

cli_test.go

Loading diff…

cmd/console/main.go

Loading diff…

deploy.go

Loading diff…

docs/site/cli.md

Loading diff…

docs/superpowers/plans/2026-09-26-temporary-static-sites-copy.md

Loading diff…

docs/superpowers/plans/2026-09-26-temporary-static-sites.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R1.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R2.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R3.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R4.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R5.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R6.md

Loading diff…

docs/superpowers/plans/CODEX-FINDINGS-TEMPORARY-SITES-PLAN-R7.md

Loading diff…

docs/superpowers/plans/CODEX-REVIEW-BRIEF-TEMPORARY-SITES-PLAN.md

Loading diff…

docs/superpowers/specs/2026-09-25-temporary-static-sites-design.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R1.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R2.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R3.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R4.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R5.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R6.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R7.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R8.md

Loading diff…

docs/superpowers/specs/CODEX-FINDINGS-TEMPORARY-SITES-R9.md

Loading diff…

docs/superpowers/specs/CODEX-REVIEW-BRIEF-TEMPORARY-SITES.md

Loading diff…

internal/console/apicli.go

Loading diff…

internal/console/apidomains.go

Loading diff…

internal/console/apiinstances.go

Loading diff…

internal/console/apimail.go

Loading diff…

internal/console/apipipeline.go

Loading diff…

internal/console/apirelay.go

Loading diff…

internal/console/apisidecars.go

Loading diff…

internal/console/apistore.go

Loading diff…

internal/console/apistore_provision.go

Loading diff…

internal/console/apitemporary.go

Loading diff…

internal/console/apitemporary_test.go

Loading diff…

internal/console/applocks.go

Loading diff…

internal/console/appsettings.go

Loading diff…

internal/console/authcli.go

Loading diff…

internal/console/controlplane.go

Loading diff…

internal/console/deletion_test.go

Loading diff…

internal/console/domainattach.go

Loading diff…

internal/console/domaincatchall.go

Loading diff…

internal/console/expirypass.go

Loading diff…

internal/console/expirypass_test.go

Loading diff…

internal/console/fleets.go

Loading diff…

internal/console/instanceprivatestore.go

Loading diff…

internal/console/materialize.go

Loading diff…

internal/console/ownership.go

Loading diff…

internal/console/restore.go

Loading diff…

internal/console/restore_test.go

Loading diff…

internal/console/server.go

Loading diff…

internal/console/settle.go

Loading diff…

internal/console/settle_test.go

Loading diff…

internal/console/store.go

Loading diff…

internal/console/svcprincipal.go

Loading diff…

internal/console/temphook_test.go

Loading diff…

internal/console/templates/app_settings.html

Loading diff…

internal/console/templates/appnav.html

Loading diff…

internal/console/templates/apps.html

Loading diff…

internal/console/templates/trash.html

Loading diff…

internal/console/tempnames_test.go

Loading diff…

internal/console/temprefusal.go

Loading diff…

internal/console/temprefusal_test.go

Loading diff…

internal/console/tempregion_test.go

Loading diff…

internal/console/tempstore.go

Loading diff…

internal/console/tempstore_test.go

Loading diff…

internal/console/view.go

Loading diff…

internal/release/temporary.go

Loading diff…

internal/release/temporary_test.go

Loading diff…

internal/release/trash.go

Loading diff…

temporary.go

Loading diff…

temporary_test.go

Loading diff…