docs(website): record split PR 1 — admin users, account, invites, auth providers

Documentation half of the first of five domain-split PRs (API_V2_PLAN.md § Phase 2).

BACKEND_DESIGN.md
- §2 folder structure: admin/ now shows index.js (shared gate + mount table) and
  the four capability routers with their route counts, prefixes and extra gates;
  admin.routes.js is labelled as the 82-route residual that goes away with PR 5.
- §4 /admin heading: was "admin.routes.js -> admin.controller.js", now points at
  admin/index.js and notes staffOnly, which the old heading omitted.
- The "planned change" note becomes "in progress" with what has landed.

API_V2_PLAN.md
- Status: planning -> in progress; PR 1 marked landed in the sequencing list.
- New "PR 1 — as landed" section: the route-count table (6+15+3+4+82 = 110) and
  three findings for PRs 2-5 — why the self-service /shard/* routes stay with the
  shard capability despite their Admin · Account tag, why a prefix mount must not
  be "simplified" to a pathless one (a bare use(gate) would then run for requests
  headed to later mounts), and that routes.guards.json came back zero-diff too.
- New section on the swagger path-normalization prerequisite and its consequence:
  with sorted path keys, a pure route move produces no spec diff, so the spec
  becomes a third zero-diff gate alongside the manifest and guards files.
- Correction to step 6: PROJECT_TREE.md is auto-generated by the sync-project-tree
  workflow since website#98 and must not be hand-edited in split PRs.

api-route-inventory.json is unchanged — verified still byte-identical to
server/routes.manifest.json (200 public + 2 internal), which is the point.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-27 15:55:37 -05:00
parent 31c91fb307
commit b7244a24b0
2 changed files with 87 additions and 7 deletions

View File

@@ -29,11 +29,15 @@ Public contact email: **UOMysticmoon@gmail.com**
Skeleton from the spec, with a small number of justified additions marked **(+)**.
> **Planned change:** the monolithic route files below (`admin.routes.js` especially, 1552 lines /
> 110 routes) are being split into one router file per business capability — **in place, with every
> URL unchanged**. This section and §4 get updated as each split PR lands. See
> **In progress:** the monolithic route files below (`admin.routes.js` especially, originally 1552
> lines / 110 routes) are being split into one router file per business capability — **in place, with
> 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` and `auth/providers` (28 routes) now live in
> their own routers under `admin/`, behind a new `admin/index.js`. The remaining 82 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
> `{ method, path }` freeze to `server/routes.manifest.json`, mirrored here as
@@ -56,7 +60,20 @@ server/
v1.router.js mounts /auth /public /admin
auth/ auth.routes.js + auth.controller.js
public/ public.routes.js + public.controller.js
admin/ admin.routes.js + admin.controller.js
admin/ index.js mounts the capability routers below at their
own prefixes; owns the shared
`noindex, isLoggedIn, staffOnly` gate and
declares no routes itself
account.router.js (6) /admin/account — self-service, no adminOnly
users.router.js (15) /admin/users — adminOnly
invites.router.js (3) /admin/invites — adminOnly
authProviders.router.js (4) /admin/auth — adminOnly
admin.routes.js (82) 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
(already domain-split; the split PRs re-wire
routes, not logic)
model/
users/ users.model.js + users.db.js
posts/ posts.model.js + posts.db.js (news/five-on-friday/newsletter/screenshots)
@@ -440,7 +457,12 @@ expiry (~5 min); `/exchange` is rate-limited per-IP. The bridge tables self-prun
Public content GETs pass through the **siteMode** gate (§5).
### /admin (admin.routes.js → admin.controller.js) — all behind `isLoggedIn` + `noindex`
### /admin (admin/index.js → the capability routers in §2) — all behind `isLoggedIn` + `noindex` + `staffOnly`
`admin/index.js` applies the shared gate and mounts each capability router at the prefix it owns;
`users`, `invites` and `auth/providers` add `adminOnly` on top. 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 |