§22 S1: release v0.40.0 — three-tier collection grain (breaking URL + migration 029)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-06-05 08:31:43 -07:00
parent 4f72aa31e0
commit aaf7b09bbe
3 changed files with 82 additions and 2 deletions
+80
View File
@@ -23,6 +23,86 @@ skip versions are the composition of each intervening adjacent
release's steps in order — no A-to-B path is pre-computed beyond
that.
## 0.40.0 — 2026-06-05
**Minor (breaking URL) — §22 three-tier refactor, slice S1: the *collection*
grain. A deployment now hosts N projects, each owning one content repo and
holding N RFC *collections*, each collection a typed corpus. S1 inserts the
collection grain beneath today's project as the invisible default: the
deployment runs exactly as before, now with a real collection layer and one
extra `/c/<collection>/` URL segment. Per-corpus configuration (`type`,
`initial_state`), entry keys, and membership move to the collection grain;
no operator action is required beyond deploying.**
See [`docs/design/2026-06-05-three-tier-projects-collections.md`](./docs/design/2026-06-05-three-tier-projects-collections.md)
(Part A model, Part E / §A.6 migration strategy). The structural model (Parts
AD) is unaffected; the SPEC.md merge itself rides slice S6.
Added:
- **Migration `029_collections.sql`** — (1) a `collections` table
`(id, project_id, type, subfolder, initial_state, visibility, name,
registry_sha)` beneath `projects`; (2) the per-corpus fields (`type`,
`initial_state`) move **down** off `projects` onto the collection; (3) one
**default collection** per project (`id='default'` for the standard
single-project deployment, `subfolder` = repo root), inheriting the project's
type / initial_state / visibility; (4) the 13 entry-corpus tables re-key
`(project_id, slug)``(collection_id, slug)` via the migration-028 rebuild
pattern, each row mapped to its project's default collection; (5)
`project_members` generalises into **`memberships(scope_type ∈ {project,
collection}, scope_id, user_id, role, …)`** with the role enum collapsed to
`{owner, contributor}` (M2's `project_admin``owner`,
`project_contributor``contributor`; `project_viewer` folded into
`contributor` this pass — the read-only tier is deferred).
- **`app/collections.py`** — collection resolution helpers
(`default_collection_id`, `collection_type`, `collection_initial_state`,
`project_of_collection`).
- **`/c/<collection>/` URL segment** — the canonical entry route is now
`/p/<project>/c/<collection>/e/<slug>`. The project landing
`/p/<project>/` redirects into the project's single (default) collection
(C3.7); the deployment root `/` continues to redirect into the sole project
(C3.8).
Changed:
- **The registry mirror** writes a project's grouping-tier fields (name,
content_repo, visibility, config) to `projects` and the per-corpus fields
(`type`, `initial_state`) to its default collection; §22.4a type-immutability
is now enforced on the collection.
- **Backend threading** — `auth.project_of_rfc` recovers a project by joining
`collections`; `auth.project_member_role` reads `memberships`;
`cache`/`api_*`/`funder` writers + readers key the 13 entry-corpus tables by
`collection_id` (the denormalised `project_id` tags on
`cached_prs`/`threads`/`changes`/`notifications`/`actions`/`pr_resolution_branches`
are unchanged). Serving stays project-scoped (collection = default); the
registry `.collection.yaml` reader and collection-aware serving land in S2.
Breaking:
- **`/p/<project>/e/<slug>` URLs gain a `/c/<collection>/` segment.** The
shipped v0.35.0 `/p/<project>/e/<slug>` form is preserved by a client-side
redirect into the default collection; the pre-multi-project `/rfc/<slug>` and
`/proposals/<n>` server 308s now target `/p/<default>/c/<default>/…`.
> ### Upgrade steps (0.39.0 → 0.40.0)
>
> - A deployment **MUST** deploy this version with its migrations applied (the
> standard startup path runs `029_collections.sql` automatically); the
> migration seeds the default collection and re-keys existing entries with no
> data loss. No configuration change is required.
> - Operators **SHOULD** be aware that the canonical entry URL is now
> `/p/<project>/c/default/e/<slug>`. Existing `/p/<project>/e/<slug>`,
> `/rfc/<slug>`, and `/proposals/<n>` links keep working (client redirect /
> server 308). External systems that hardcoded the old form **SHOULD** be
> updated to the collection-scoped form at their convenience.
> - Deployments that pin the framework version **MUST** bump their version pin
> to `0.40.0`.
Deferred (later slices): creating + navigating a second collection and the
registry `.collection.yaml` reader (S2); the four-layer scope-role resolver and
the `viewer` read tier (S3); invitation surfaces (S4); in-app create-project
(S5); per-type surfaces, membership lifecycle, and the SPEC.md merge (S6).
## 0.39.0 — 2026-06-04
**Minor — §22.13 step 1: the default-project-id re-stamp. A deployment can
+1 -1
View File
@@ -1 +1 @@
0.39.0
0.40.0
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "rfc-app-frontend",
"private": true,
"version": "0.39.0",
"version": "0.40.0",
"type": "module",
"scripts": {
"dev": "vite",