carlos / platform Public

control_plane is a console-DB row only: a direct-bucket TrashApp never consults it Idea open

Migrated from github.com/carlosframework/platform issue #293, opened 2026-08-25. GitHub issues are closed for this repo; see AGENTS.md, "Work is tracked on amadan, not GitHub".

Still outstanding: control_plane is a console-DB row only; a direct-bucket TrashApp never consults it.

---

Found during the console-as-an-app branch (Task 4 review). This is the control-plane flag's one real bypass, filed before the flag ships so it exists in the tracker rather than in an archived report.

The gap

The control_plane flag lives in the console's database. Seven console doors consult it (API trash, browser trash, rename, move, purge, store-destroy, account deletion), plus service refusals on promote/rollback/retention-apply.

Nothing box-side or bucket-side sees it. A release.TrashApp marker written straight to the bucket by a box or a pinfra script is turned into a trashed row by materialize.go, and the auto-purge sweep destroys the prefix 30 days later — the flag never consulted.

Reachability, checked

Through console doors the trashed-then-flagged state has no constructor: both trash doors refuse a flagged app; the set door goes through accountApp→HasAppIn, which filters deleted_at = 0; and carlos apps create -control-plane on a trashed name hits CreateAppIn's ON CONFLICT DO NOTHING → claimTaken before the stamp ever runs. So the sweep cannot reach a flagged app by any console-driven route.

What is genuinely open is the direct-bucket path.

Why this is filed rather than fixed

Anyone holding direct bucket access can already rm -rf apps/<sqid>/<app>/** without a marker, so the flag adds nothing they could bypass. The fix is a spec decision — mirror the flag into the bucket (e.g. an app.json fact) so release.TrashApp/PurgeApp refuse it themselves — not another console-side check.

🤖 Generated with Claude Code