docs(website): record the PR 3 admin router split (posts, uploads, wiki, pages)

Adds a "PR 3 — as landed" section to API_V2_PLAN.md and ticks the sequencing
list. 31 routes extracted, 33 left in admin.routes.js; all four zero-diff gates
came back clean and 434 server tests passed.

Findings carried forward:

- The residual 33 is exactly PR 4's list, so admin.routes.js is deleted by
  PR 4 rather than PR 5.
- First shared module in the split: the multer config, because POST
  /posts/upload and POST /uploads no longer live in the same file.
- POST /uploads keeps its Admin · Posts swagger tag — retagging is a real
  OpenAPI diff and does not belong in a route-move PR.
- The wiki router has load-bearing intra-file route order (/categories and
  /tags ahead of /:slug) that no gate can catch, because the manifest sorts
  its entries. Verified by introspecting the built router stack instead.

BACKEND_DESIGN.md §2 gets the four new routers plus imageUpload.js in the
folder tree, and §4 notes that the content capabilities add no gate beyond
staffOnly.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-27 19:24:58 -05:00
parent d034c6f673
commit d515d42b7c
2 changed files with 67 additions and 10 deletions

View File

@@ -34,10 +34,10 @@ Skeleton from the spec, with a small number of justified additions marked **(+)*
> every URL unchanged**. This section and §4 get updated as each split PR lands. See
> [API_V2_PLAN.md](./API_V2_PLAN.md) § Phase 2.
>
> **Landed so far:** admin `users`, `account`, `invites`, `auth/providers` (PR 1, 28 routes) and
> `moderation`, `bot-activity`, `activity` (PR 2, 18 routes) now live in their own routers under
> `admin/`, behind a new `admin/index.js`. The remaining 64 admin routes are still in
> `admin.routes.js`, and `public/` and `player/` are untouched.
> **Landed so far:** admin `users`, `account`, `invites`, `auth/providers` (PR 1, 28 routes),
> `moderation`, `bot-activity`, `activity` (PR 2, 18 routes) and `posts`, `uploads`, `wiki`, `pages`
> (PR 3, 31 routes) now live in their own routers under `admin/`, behind a new `admin/index.js`. The
> remaining 33 admin routes are still in `admin.routes.js`, and `public/` and `player/` are untouched.
>
> "Every URL unchanged" is enforced mechanically, not by review: `server/scripts/routeManifest.js`
> (`npm run routes:manifest`) walks the live Express stack and writes the sorted
@@ -74,7 +74,16 @@ server/
botActivity.router.js (2) /admin/bot-activity — adminOnly
activity.router.js (1) /admin/activity — staff-wide
audit log, no extra gate
admin.routes.js (64) everything not yet split, mounted
posts.router.js (9) /admin/posts — editor tier, no
gate beyond staffOnly
uploads.router.js (1) /admin/uploads — rich-text editor
image upload
wiki.router.js (14) /admin/wiki — pages, revisions,
categories, tags
pages.router.js (7) /admin/pages — CMS page builder
imageUpload.js shared multer config for the two
upload routes above (not a router)
admin.routes.js (33) everything not yet split, mounted
last at the group root; goes away
when the final split PR lands
admin.controller.js + the per-capability controllers
@@ -467,9 +476,11 @@ Public content GETs pass through the **siteMode** gate (§5).
`admin/index.js` applies the shared gate and mounts each capability router at the prefix it owns;
`users`, `invites`, `auth/providers` and `bot-activity` add `adminOnly` on top, and `moderation` adds
`modAccess` (admin + moderator, so editors are excluded). Routes not yet extracted still live
in `admin.routes.js`, mounted last at the group root. The URLs below are unaffected by which file a
route currently sits in — that is the property the route manifest freezes.
`modAccess` (admin + moderator, so editors are excluded). The content capabilities — `posts`,
`uploads`, `wiki`, `pages` — add nothing: managing content is the editor tier's job, so `staffOnly` is
the whole gate. Routes not yet extracted still live in `admin.routes.js`, mounted last at the group
root. The URLs below are unaffected by which file a route currently sits in — that is the property the
route manifest freezes.
| Method | Path | Purpose |
|---|---|---|
| GET | `/dashboard` | current mode, last change time + who, content counts, recent activity |