A self-hosted boot converts free and empty plans to `self-hosted`, which has
no limits. Nothing recorded which kind of instance owned a database, so one
non-cloud boot of a Pad Cloud database (a missing PAD_MODE, a restore tested
locally, a debug boot) made every free user unlimited for good: a later
cloud boot fills only empty plans.
- Every cloud-mode boot marks its database cloud-owned
(platform_settings.instance_mode = cloud), sticky and before its backfill.
- A database with no marker counts as cloud-owned when any user carries
Pad Cloud billing state (a stripe plan source or a stripe customer id).
- The non-cloud boot's conversion (store.BackfillSelfHostedPlans) checks
ownership in its own transaction and converts nothing on a cloud-owned
database. The boot logs an error and continues: a debug or restore boot is
not an outage, and free users keep free-plan limits.
- `pad db release-cloud [--force]`, on the server host, is the deliberate way
to move a Cloud database to self-host. It refuses while billing state
remains unless forced; a later cloud boot marks the database again.
The plan step of `pad server start` moves into bootPlanBackfill so it can be
tested as the server runs it. docs/backup.md documents the behaviour.
Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS