"""@S1 acceptance — the collection grain exists (invisible default) and N=1 is unchanged. Part C scenarios C3.7 (single-collection project skips the directory) and C3.8 (single-project deployment skips the directory) are the client-side redirect contract asserted in the frontend; this module asserts the backend N=1 invariants behind the slice: every entry keys on a real collection_id, the shipped project-scoped serving still resolves through the default collection, and the legacy /rfc/ URL 308-redirects through /c//. Binding: docs/design/2026-06-05-three-tier-projects-collections.md §A.6 / Part E. """ from __future__ import annotations from fastapi.testclient import TestClient from test_propose_vertical import ( # noqa: F401 app_with_fake_gitea, tmp_env, provision_user_row, sign_in_as, ) def _seed_entry(slug, title, collection_id="default", state="active"): from app import db db.conn().execute( "INSERT INTO cached_rfcs (slug, title, state, collection_id) VALUES (?, ?, ?, ?)", (slug, title, state, collection_id), ) def test_s1_migration_seeds_one_default_collection_for_the_default_project(app_with_fake_gitea): from app import db app, _ = app_with_fake_gitea with TestClient(app): row = db.conn().execute( "SELECT id FROM collections WHERE project_id = 'default'" ).fetchall() assert len(row) == 1 assert row[0]["id"] == "default" def test_s1_entry_served_under_default_collection(app_with_fake_gitea): """N=1 unchanged: an entry is keyed by collection_id under the hood and the shipped project-scoped serving endpoint still resolves it.""" from app import db app, _ = app_with_fake_gitea with TestClient(app) as client: _seed_entry("human", "Human") # the row carries a real collection grain (the default collection) cid = db.conn().execute( "SELECT collection_id FROM cached_rfcs WHERE slug='human'" ).fetchone()["collection_id"] assert cid == "default" # project-scoped serving (collection = default) still returns it r = client.get("/api/projects/default/rfcs/human") assert r.status_code == 200, r.text assert r.json()["slug"] == "human" # and it appears in the project catalog slugs = [i["slug"] for i in client.get("/api/projects/default/rfcs").json()["items"]] assert "human" in slugs def test_s1_legacy_rfc_url_redirects_through_collection(app_with_fake_gitea): """The shipped /rfc/ now 308s through the default collection segment.""" app, _ = app_with_fake_gitea with TestClient(app) as client: r = client.get("/rfc/human", follow_redirects=False) assert r.status_code == 308 assert r.headers["location"] == "/p/default/c/default/e/human" def test_s1_deployment_reports_single_project(app_with_fake_gitea): """C3.8 precondition: the N=1 deployment reports exactly one visible project and its default id (the frontend uses this to skip the directory).""" app, _ = app_with_fake_gitea with TestClient(app) as client: body = client.get("/api/deployment").json() assert body["default_project_id"] == "default" assert [p["id"] for p in body["projects"]] == ["default"]