feat(projects): M1 — the multi-project schema spine (§22)
Lays the additive foundation for hosting N projects per deployment, with today's single corpus as the N=1 case. No behavior change: the app runs exactly as before, single project, with the spine underneath. - migration 025: `projects` + `project_members` tables; seed the `default` project (visibility=public, preserving open-by-default); thread `project_id NOT NULL DEFAULT 'default'` onto all 19 slug-bearing tables, backfilling existing rows. Additive — no table rebuilds; the slug-keyed uniqueness/PK rework is enumerated in the migration header and deferred to the slice that activates project #2. - app/projects.py: §22.13 startup backfill of the default project's content_repo from META_REPO (idempotent — never clobbers a value the future registry mirror sets). - config: REGISTRY_REPO wired (optional through M1; consumed by the M3 mirror), documented in .env.example as META_REPO's successor. - tests: 6 vertical assertions on the spine (seed, backfill, column shape, role CHECK, idempotency, config). Full suite 381 passed. - docs: align Part C M1/M3 boundaries with the landed code (registry mirror + redirect move to M3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -315,13 +315,17 @@ first, the surfaces that consume them after, hardening last. Each slice is
|
||||
shippable: a deployment can stop at any slice boundary and still run (the
|
||||
default project keeps the N=1 case whole throughout).
|
||||
|
||||
**M1 — The project spine (schema + registry + default-project migration).**
|
||||
The `projects` and `project_members` tables; the §4 registry mirror (webhook
|
||||
+ reconciler over the registry repo); `project_id` threaded through every §5
|
||||
table per the Part B list; the §22.13 migration that generates the default
|
||||
project, backfills `project_id`, and stands up the redirect. No UI yet — the
|
||||
app runs exactly as before, single project, with the spine underneath. This
|
||||
is the slice that must land atomically; everything after is additive.
|
||||
**M1 — The project spine (schema + default-project migration).** *(landed)*
|
||||
The `projects` and `project_members` tables; `project_id` threaded
|
||||
additively onto every slug-bearing §5 table (migration 025); the §22.13
|
||||
default project generated and every existing row backfilled to it; the
|
||||
startup backfill that fills the default project's `content_repo` from
|
||||
`META_REPO`; `REGISTRY_REPO` wired into config (consumed in M3). No UI, no
|
||||
routing change, no registry mirror yet — the app runs exactly as before,
|
||||
single project, with the spine underneath. Additive only: no table rebuilds
|
||||
(the slug-keyed uniqueness/PK rework is deferred to the slice that activates
|
||||
project #2, enumerated in migration 025's header). This is the foundation
|
||||
everything after builds on.
|
||||
|
||||
**M2 — Project-scoped authorization + the §22.7 resolver.** The three-tier
|
||||
composition: `project_members` roles, the most-permissive union with
|
||||
@@ -331,12 +335,16 @@ re-checked under the project axis. Still single visible project; this slice
|
||||
is verifiable by granting/revoking roles on the default project and asserting
|
||||
the gates.
|
||||
|
||||
**M3 — Routing + runtime branding.** The `/p/<project>/` route prefix, the
|
||||
308 redirects, `GET /api/deployment` and `GET /api/projects/:id`, the
|
||||
frontend cut from `VITE_APP_NAME` to runtime config, per-project `theme`
|
||||
token overlay. The deployment directory at `/` and the project switcher in
|
||||
deployment chrome. After M3 a deployment with two registry projects is fully
|
||||
navigable.
|
||||
**M3 — Registry mirror + routing + runtime branding.** The §4 registry
|
||||
mirror (webhook + reconciler over the `REGISTRY_REPO`, populating `projects`
|
||||
rows beyond `default`); the `/p/<project>/` route prefix and the 308
|
||||
redirects off the old corpus-root URLs; `GET /api/deployment` and `GET
|
||||
/api/projects/:id`; the frontend cut from `VITE_APP_NAME` to runtime config,
|
||||
per-project `theme` token overlay. The deployment directory at `/` and the
|
||||
project switcher in deployment chrome. After M3 a deployment with two
|
||||
registry projects is fully navigable — which makes this the slice that must
|
||||
also land the deferred slug-keyed uniqueness/PK rebuilds (migration 025
|
||||
header) before a second project can collide with the first.
|
||||
|
||||
**M4 — Per-project corpus surfaces.** The §7 catalog, §8 RFC view, §9/§10
|
||||
proposal/PR flows, §13 graduation, and §14 philosophy all confirmed working
|
||||
|
||||
Reference in New Issue
Block a user