Merge pull request 'docs(website): record the PR 3 admin router split (posts, uploads, wiki, pages)' (#56) from docs/admin-router-split-3 into main
Reviewed-on: #56
This commit is contained in:
@@ -376,6 +376,51 @@ Notes:
|
|||||||
- **`modAccess` stays in the residual file** — the `/shard/*` in-game staff operations still use it
|
- **`modAccess` stays in the residual file** — the `/shard/*` in-game staff operations still use it
|
||||||
and do not move until PR 4. Its comment there was retargeted rather than deleted.
|
and do not move until PR 4. Its comment there was retargeted rather than deleted.
|
||||||
|
|
||||||
|
### PR 3 — as landed
|
||||||
|
|
||||||
|
`posts`, `uploads`, `wiki` and `pages` — 31 routes, leaving 33 in the residual file. The content tier,
|
||||||
|
and the first split PR where no gate moved at all: all four capabilities are editor-tier, so the shared
|
||||||
|
`staffOnly` in `admin/index.js` is their whole gate.
|
||||||
|
|
||||||
|
| Router | Routes | Prefix | Extra gate |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `posts.router.js` | 9 | `/admin/posts` | none — editor tier |
|
||||||
|
| `uploads.router.js` | 1 | `/admin/uploads` | none — editor tier |
|
||||||
|
| `wiki.router.js` | 14 | `/admin/wiki` | none — editor tier |
|
||||||
|
| `pages.router.js` | 7 | `/admin/pages` | none — editor tier |
|
||||||
|
| `admin.routes.js` (residual) | 33 | group root, mounted last | unchanged |
|
||||||
|
|
||||||
|
All four gates zero-diff: `routes.manifest.json` (200 public + 2 internal), `routes.guards.json`,
|
||||||
|
`swagger-output.json` (198 operations), and `docs/website/api-route-inventory.json` was already in
|
||||||
|
sync. 434 server tests green.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- **The residual 33 is exactly PR 4's list** — `shard` 16, `email` 6, `uo-link` 5, `settings` 2,
|
||||||
|
`discord-bot` 2, `dashboard` 1, `site-mode` 1. So `admin.routes.js` is deleted by PR 4, one PR
|
||||||
|
earlier than the sequencing list implies, and PR 5 touches only `public/*`, `player/*` and `auth/*`.
|
||||||
|
- **A shared module was unavoidable here, and it is the first one in the split.** The multer config
|
||||||
|
(upload dir, mimetype→extension allowlist, 8 MB cap) was defined inline in `admin.routes.js` and used
|
||||||
|
by *two* routes that this PR puts in different files: `POST /posts/upload` (→ `{image_url}`) and
|
||||||
|
`POST /uploads` (→ `{url}`). It moved to `admin/imageUpload.js` rather than being duplicated —
|
||||||
|
duplicating a security allowlist is how the two copies drift. It stays in `admin/` deliberately:
|
||||||
|
`UPLOAD_DIR` is resolved `__dirname`-relative, so relocating the file would silently repoint the
|
||||||
|
upload directory. Guard freshness is unaffected — multer's middleware is named `multerMiddleware`
|
||||||
|
wherever it is constructed, so `routes.guards.json` did not move.
|
||||||
|
- **`POST /uploads` keeps its `Admin · Posts` swagger tag**, which now disagrees with its filename. The
|
||||||
|
acceptance criterion is a byte-identical spec, so retagging is a real OpenAPI diff and does not
|
||||||
|
belong in a route-move PR. Same call as PR 1's `/shard/*` tag mismatch: fix tags in a PR that is
|
||||||
|
*about* tags.
|
||||||
|
- **The wiki router is the first one with load-bearing intra-file route order.** `/categories` and
|
||||||
|
`/tags` are literal paths that must stay ahead of `/:slug`, or `GET /admin/wiki/categories` gets
|
||||||
|
dispatched as a page whose slug is "categories". **The manifest cannot catch this — it sorts its
|
||||||
|
entries, so a reordering is invisible in all three gates.** It was verified separately by
|
||||||
|
introspecting the built router stack and asserting the last literal layer precedes the first `/:slug`
|
||||||
|
layer. Any future PR moving `/:slug`-style routes needs the same explicit check.
|
||||||
|
- **`/admin/pages` (CMS page builder) and `/admin/shard/pages` (in-game help-page queue) are unrelated
|
||||||
|
capabilities that read alike** — the latter stays with `shard` in PR 4. Same trap as PR 2's
|
||||||
|
`activity` / `dashboard` / `bot-activity` trio.
|
||||||
|
|
||||||
### The swagger path-normalization prerequisite (landed before PR 1)
|
### The swagger path-normalization prerequisite (landed before PR 1)
|
||||||
|
|
||||||
swagger-autogen builds a path by string-concatenating the mount prefix with the route argument, so a
|
swagger-autogen builds a path by string-concatenating the mount prefix with the route argument, so a
|
||||||
@@ -485,9 +530,10 @@ deliberate `+1` in the manifest — which is exactly the mechanism working as de
|
|||||||
as a `report-to` group on the enforced policy.
|
as a `report-to` group on the enforced policy.
|
||||||
4. **PR 1 — admin:** `users`, `account`, `invites`, `auth` (providers). ✅ landed
|
4. **PR 1 — admin:** `users`, `account`, `invites`, `auth` (providers). ✅ landed
|
||||||
5. **PR 2 — admin:** `moderation`, `bot-activity`, `activity`. ✅ landed
|
5. **PR 2 — admin:** `moderation`, `bot-activity`, `activity`. ✅ landed
|
||||||
6. **PR 3 — admin (content):** `posts`, `pages`, `wiki`, `uploads`.
|
6. **PR 3 — admin (content):** `posts`, `pages`, `wiki`, `uploads`. ✅ landed
|
||||||
7. **PR 4 — admin (ops/config):** `shard`, `uo-link`, `email`, `discord-bot`, `settings`, `site-mode`,
|
7. **PR 4 — admin (ops/config):** `shard`, `uo-link`, `email`, `discord-bot`, `settings`, `site-mode`,
|
||||||
`dashboard`. (`activity` went with PR 2 — see § PR 2 — as landed.)
|
`dashboard`. (`activity` went with PR 2 — see § PR 2 — as landed.) **This is the whole residual
|
||||||
|
file** — `admin.routes.js` is deleted here, not by PR 5.
|
||||||
8. **PR 5 — `public/*` + `player/*`** (and the residual `auth/*` grouping).
|
8. **PR 5 — `public/*` + `player/*`** (and the residual `auth/*` grouping).
|
||||||
|
|
||||||
Each PR: **zero-line diff in `routes.manifest.json`**, server tests green
|
Each PR: **zero-line diff in `routes.manifest.json`**, server tests green
|
||||||
|
|||||||
@@ -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
|
> 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.
|
> [API_V2_PLAN.md](./API_V2_PLAN.md) § Phase 2.
|
||||||
>
|
>
|
||||||
> **Landed so far:** admin `users`, `account`, `invites`, `auth/providers` (PR 1, 28 routes) and
|
> **Landed so far:** admin `users`, `account`, `invites`, `auth/providers` (PR 1, 28 routes),
|
||||||
> `moderation`, `bot-activity`, `activity` (PR 2, 18 routes) now live in their own routers under
|
> `moderation`, `bot-activity`, `activity` (PR 2, 18 routes) and `posts`, `uploads`, `wiki`, `pages`
|
||||||
> `admin/`, behind a new `admin/index.js`. The remaining 64 admin routes are still in
|
> (PR 3, 31 routes) now live in their own routers under `admin/`, behind a new `admin/index.js`. The
|
||||||
> `admin.routes.js`, and `public/` and `player/` are untouched.
|
> 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`
|
> "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
|
> (`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
|
botActivity.router.js (2) /admin/bot-activity — adminOnly
|
||||||
activity.router.js (1) /admin/activity — staff-wide
|
activity.router.js (1) /admin/activity — staff-wide
|
||||||
audit log, no extra gate
|
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
|
last at the group root; goes away
|
||||||
when the final split PR lands
|
when the final split PR lands
|
||||||
admin.controller.js + the per-capability controllers
|
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;
|
`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
|
`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
|
`modAccess` (admin + moderator, so editors are excluded). The content capabilities — `posts`,
|
||||||
in `admin.routes.js`, mounted last at the group root. The URLs below are unaffected by which file a
|
`uploads`, `wiki`, `pages` — add nothing: managing content is the editor tier's job, so `staffOnly` is
|
||||||
route currently sits in — that is the property the route manifest freezes.
|
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 |
|
| Method | Path | Purpose |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| GET | `/dashboard` | current mode, last change time + who, content counts, recent activity |
|
| GET | `/dashboard` | current mode, last change time + who, content counts, recent activity |
|
||||||
|
|||||||
Reference in New Issue
Block a user