Estimate: 60m · Depends on: 6.12.3
The backend foundation of the square: the cross-org directory read that lists EVERY public project and EXCLUDES every non-public one. This is the load-bearing correctness work the whole story rides — it must surface only the card-projection fields and never an internal project field.
access_level = 'public' (the 6.12.3 enum value) — the public-only filter lives in ONE repository read, so no non-public project can leak through any code path. A private / open / limited project NEVER appears, for any viewer; the 6.12.3 404-not-403 posture for non-public projects is untouched (a non-public project is simply absent from the set, never "forbidden"). Anonymous-readable: the directory read requires NO session (the page is fully public — model revision 2026-06-14); it must run on the server with no getSession() gate so crawlers / logged-out visitors get the full list.OFFSET-the-world, never load-all) with a bounded page size. The default ordering is a deterministic total order (a stable tiebreak on project id) so the cursor never skips/duplicates a row — 6.13.4 swaps in the trending/popular/recent sort keys over this same cursored read.Stay 4-layer: the route parses + calls ONE service method returning the card-projection page; the access_level = public filter + the projection live in the service/repository read layer so no future read can leak a non-public project or an internal field; no raw Prisma in the route.
getSession() gate); 4-layer respected (the filter + projection in the service/repository, no raw Prisma in the route).scripts/plan-seed/data/story-6.12.ts § 6.12.3 (the public ProjectAccessLevel value + the cross-org read exception) + § 6.12.6 (the upvote / activity signals the stats read from) + § 6.12.4 (the public projection posture to mirror).motir-core/lib/repositories/ + lib/services/ — the project read layer the directory threads into; projectAccessService (6.4 / 6.12.3) — the public level the filter keys off.motir-core/CLAUDE.md § 4-layer.