§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:
@@ -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
|
||||
A–D) 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,7 +1,7 @@
|
||||
{
|
||||
"name": "rfc-app-frontend",
|
||||
"private": true,
|
||||
"version": "0.39.0",
|
||||
"version": "0.40.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user