PR 0 of the router domain split (docs/website/API_V2_PLAN.md § Phase 2). The
split promises that admin.routes.js can be carved into one router file per
business capability without moving a single URL. That promise has to be proved
by a diff, not asserted in review — this lands the tool that proves it, with no
router file moved.
scripts/routeManifest.js walks the live Express stack (runtime introspection,
not source parsing: route paths in admin.routes.js sit on the line *after*
`adminRouter.get(`, which defeats greps) and writes a sorted { method, path }
list to routes.manifest.json. It reproduces the frozen baseline in
docs/website/api-route-inventory.json byte-for-byte — 199 public routes plus 2
on the internal listener — so the freeze is confirmed accurate, not just
claimed.
Scope is /api/** and /.well-known/** plus the internal app. The SPA catch-all,
/uploads and /brand are filesystem-conditional static mounts, so including them
would make the output depend on whether CI had built the client. Static mounts
are not API contract.
Also emits routes.guards.json — a review aid, not a contract: per route, the
handler count and the *named* middleware on its mount chain. Router-level
`use(noindex, isLoggedIn, staffOnly)` gates never appear in an individual
route's own stack, so an extracted capability router that forgot to re-apply
one would otherwise publish authenticated endpoints silently. Names are a hint
only (requireRole(...) returns an anonymous arrow), but a vanished requireAuth
is unambiguous — and the test suite asserts every /admin/** and /player/**
route still carries it.
The plan's optional unauthenticated-status snapshot was tried and dropped, as
it allowed: against the dead-port mariadb pool the tests use, the sweep sits on
the pool's acquire timeout and had not finished after two minutes. A flaky
two-minute gate is worse than none; the requireAuth assertion covers the same
regression deterministically.
CI runs `npm run routes:manifest -- --check` on every PR, so a URL change can
only merge by deliberately committing the new manifest.
Co-Authored-By: Claude <noreply@anthropic.com>
48 lines
1.1 KiB
JSON
48 lines
1.1 KiB
JSON
{
|
|
"name": "runic-gateway-server",
|
|
"version": "1.0.0",
|
|
"description": "REST API for the Runic Gateway website and admin panel",
|
|
"main": "src/server.js",
|
|
"scripts": {
|
|
"start": "node src/server.js",
|
|
"dev": "nodemon src/server.js",
|
|
"seed": "node db/seed.js",
|
|
"swagger": "node swagger/swagger.js",
|
|
"routes:manifest": "node scripts/routeManifest.js",
|
|
"test": "node --test"
|
|
},
|
|
"keywords": [
|
|
"express",
|
|
"mariadb",
|
|
"jwt",
|
|
"bcrypt"
|
|
],
|
|
"author": "whitlocktech",
|
|
"license": "ISC",
|
|
"dependencies": {
|
|
"bcryptjs": "^2.4.3",
|
|
"cookie-parser": "^1.4.6",
|
|
"cors": "^2.8.5",
|
|
"dotenv": "^16.4.5",
|
|
"express": "^4.19.2",
|
|
"express-rate-limit": "^7.4.0",
|
|
"express-slow-down": "^3.1.0",
|
|
"express-validator": "^7.2.0",
|
|
"helmet": "^7.1.0",
|
|
"jsonwebtoken": "^9.0.2",
|
|
"mariadb": "^3.3.1",
|
|
"morgan": "^1.10.0",
|
|
"multer": "^2.0.1",
|
|
"nodemailer": "^9.0.1",
|
|
"qrcode": "^1.5.4",
|
|
"sanitize-html": "^2.17.5",
|
|
"speakeasy": "^2.0.0",
|
|
"swagger-ui-express": "^5.0.1",
|
|
"ws": "^8.21.0"
|
|
},
|
|
"devDependencies": {
|
|
"nodemon": "^3.1.4",
|
|
"swagger-autogen": "^2.23.7"
|
|
}
|
|
}
|