-- Phase 5 / M3 (v1.2 Hierarchies): multi-repo single-owner ownership (§7). -- -- A group node is authoritatively MANAGED by at most one project-root (the -- repo whose manifest declares it as something it applies, not merely -- references). `groups.owner_project` has carried this seam since 0047 as an -- inert, FK-less UUID. M3 makes it a real reference: a `projects` table keyed -- by a stable, gitignored project key the CLI mints in `.picloud/`, and a -- foreign key from `groups.owner_project` to it. -- -- Ownership is recorded at GROUP granularity; apps inherit their owning project -- from their group (apps are never claimed directly). A NULL `owner_project` -- means the node is UI/API-owned — no manifest fights it (§7.5). First apply -- claims; a second project's apply to an owned node is refused unless -- `--takeover` (group-admin gated). Ownership ⟂ RBAC: owning the manifest does -- NOT grant write — the actor still needs the usual group capabilities (§7.4). -- -- ON DELETE SET NULL: deleting a project row (not something the platform does -- today) reverts its nodes to UI-owned rather than cascading away real groups. CREATE TABLE projects ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Stable, opaque key minted by `pic init` and persisted (gitignored) in the -- repo's `.picloud/`. The CLI presents it on every tree apply; the server -- maps it to this row (upsert-by-key), so the same repo keeps the same -- project identity across clones/CI without committing any server id. key TEXT NOT NULL UNIQUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Promote the inert `groups.owner_project` (0047) to a real FK now that the -- referent exists. Existing rows are all NULL (no projects yet), so this adds -- no validation burden. ALTER TABLE groups ADD CONSTRAINT groups_owner_project_fkey FOREIGN KEY (owner_project) REFERENCES projects(id) ON DELETE SET NULL; -- The ownership reconcile reads "which groups does project P own?" (to find -- owned-but-undeclared nodes for structural prune) and "who owns group G?". CREATE INDEX groups_owner_project_idx ON groups (owner_project);