// /api/v1/public — the anonymous public surface, assembled from per-capability // routers. // // This file owns the mount table and nothing else; no route is declared here. // Each capability router mounts at the prefix it already owned inside the old // monolithic public.routes.js, so the emitted URL set is byte-identical — proved // by a zero-line diff in server/routes.manifest.json (`npm run routes:manifest`). // // **There is deliberately no group gate.** Unlike /admin (staffOnly) and /player // (requireAuth), this group is unauthenticated by design and must stay that way: // the SPA renders logged-out, the Discord bot reads it anonymously, and the // Android app's ShardStreamClient consumes /public/shard/stream with no // Authorization header. Content visibility during maintenance is handled by the // per-route `siteMode` middleware, not by an auth gate. // // See docs/website/API_V2_PLAN.md § Phase 2 for the split. const express = require('express') const postsRouter = require('./posts.router') const wikiRouter = require('./wiki.router') const pagesRouter = require('./pages.router') const shardRouter = require('./shard.router') const siteRouter = require('./site.router') const publicRouter = express.Router() // Content. All three are site-mode gated per route (the /pages draft-preview // route is the one deliberate exception — see pages.router.js). publicRouter.use('/posts', postsRouter) publicRouter.use('/wiki', wikiRouter) publicRouter.use('/pages', pagesRouter) // Live shard data, never site-mode gated. publicRouter.use('/shard', shardRouter) // The four singletons that own no path segment of their own: /settings, /status, // /version and /contact. Mounted at the group root, last — safe only because // site.router.js declares no router-level middleware (a bare `use(gate)` in a // root-mounted router runs for every request passing through toward another // mount). Same arrangement as admin/dashboard.router.js. publicRouter.use('/', siteRouter) module.exports = publicRouter