-- §22 (multi-project deployments) — Slice M1: the project spine.
--
-- A deployment now hosts one or more *projects*, each a corpus with its own
-- content repo, slug/RFC-NNNN namespace, catalog, roster, and branding. The
-- pre-multi-project single-corpus deployment is the N=1 case: this migration
-- generates one 'default' project and stamps every existing RFC-scoped row
-- to it, so the app keeps running exactly as before with the spine
-- underneath (see docs/design/multi-project-spec.md §22.13).
--
-- STRATEGY — additive, no table rebuilds. Every slug-bearing table gets a
-- `project_id TEXT NOT NULL DEFAULT 'default'` column. The constant default
-- means every existing INSERT in the codebase that does not yet mention
-- project_id keeps working and lands rows in the default project; no query
-- breaks because, with a single project, slugs remain globally unique. The
-- column carries no inline REFERENCES clause: SQLite's ALTER TABLE ADD
-- COLUMN forbids a FK column with a non-NULL default. project_id referential
-- integrity is therefore enforced at the app layer for now; the FK lands
-- with the table rebuilds below.
--
-- ============================================================================
-- DEFERRED to the slice that activates project #2 (M3/M4). Until a second
-- project exists these are correct as-is; the moment two projects can share a
-- slug or a Gitea PR number they become cross-project collision bugs and MUST
-- be rebuilt (SQLite needs a create-copy-drop-rename per table) to fold
-- project_id into the key, and to add the project_id FK:
--   * cached_rfcs            PRIMARY KEY (slug)                  -> (project_id, slug)
--   * cached_branches        UNIQUE (rfc_slug, branch_name)      -> +project_id
--   * branch_visibility      UNIQUE (rfc_slug, branch_name)      -> +project_id
--   * branch_contribute_grants UNIQUE (rfc_slug, branch_name, grantee_user_id) -> +project_id
--   * stars                  UNIQUE (user_id, rfc_slug)          -> +project_id
--   * watches                UNIQUE (user_id, rfc_slug)          -> +project_id
--   * pr_seen                UNIQUE (user_id, rfc_slug, pr_number) -> +project_id
--   * branch_chat_seen       UNIQUE (user_id, rfc_slug, branch_name) -> +project_id
--   * funder_consents        PRIMARY KEY (user_id, rfc_slug)      -> +project_id
--   * rfc_collaborators      UNIQUE INDEX (rfc_slug, user_id)     -> +project_id
--   * contribution_requests  UNIQUE INDEX (rfc_slug, requester_user_id) WHERE pending -> +project_id
--   * proposed_use_cases     UNIQUE (scope, pr_number)           -> +project_id
--                            (PR numbers are per-content-repo = per-project)
-- cached_prs UNIQUE (repo, pr_number) is already globally unique (repo is the
-- full 'org/repo' string, distinct per project) and needs no rebuild.
-- ============================================================================

-- The project registry cache (mirrored from the git registry by the M3
-- reconciler; rows are never written from user actions). content_repo is
-- NULL until the mirror — or the M1 startup backfill (§22.13 step 1) — sets
-- it from the deployment's configured repo.
CREATE TABLE IF NOT EXISTS projects (
    id            TEXT PRIMARY KEY,
    name          TEXT NOT NULL,
    content_repo  TEXT,
    visibility    TEXT NOT NULL DEFAULT 'gated'
                      CHECK (visibility IN ('gated', 'public', 'unlisted')),
    config_json   TEXT,
    registry_sha  TEXT,
    created_at    TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at    TEXT NOT NULL DEFAULT (datetime('now'))
);

-- The default project. visibility='public' preserves the pre-multi-project
-- open-by-default posture (§22.5, §22.13). name is a placeholder the startup
-- backfill / registry overwrites with the deployment's display name.
INSERT OR IGNORE INTO projects (id, name, visibility)
    VALUES ('default', 'default', 'public');

-- Per-(user, project) membership and the §22.6 middle-tier role. This is the
-- new tier between the §6.1 deployment role (users.role, now deployment-scope
-- only) and the §6.3 per-RFC authority.
CREATE TABLE IF NOT EXISTS project_members (
    project_id  TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
    user_id     INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    role        TEXT NOT NULL DEFAULT 'project_viewer'
                    CHECK (role IN ('project_admin', 'project_contributor', 'project_viewer')),
    granted_by  INTEGER REFERENCES users(id) ON DELETE SET NULL,
    granted_at  TEXT NOT NULL DEFAULT (datetime('now')),
    PRIMARY KEY (project_id, user_id)
);

CREATE INDEX IF NOT EXISTS idx_project_members_user ON project_members(user_id);

-- The project_id spine across every slug-bearing table. Backfills existing
-- rows to 'default' via the constant column default.
ALTER TABLE cached_rfcs              ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE cached_branches          ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE cached_prs               ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE branch_visibility        ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE branch_contribute_grants ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE stars                    ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE threads                  ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE changes                  ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE pr_seen                  ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE branch_chat_seen         ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE watches                  ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE notifications            ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE actions                  ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE pr_resolution_branches   ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE funder_consents          ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE rfc_invitations          ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE rfc_collaborators        ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE proposed_use_cases       ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';
ALTER TABLE contribution_requests    ADD COLUMN project_id TEXT NOT NULL DEFAULT 'default';

-- The catalog/directory lookup the M3 surfaces will make (RFCs in a project).
-- The per-table composite-key rebuilds in the DEFERRED block above will add
-- their own (project_id, …) indexes when they land.
CREATE INDEX IF NOT EXISTS idx_cached_rfcs_project ON cached_rfcs(project_id);
