// /api/v1/player โ€” the player self-service surface, assembled from // per-capability routers. // // This file owns exactly two things: the gate every player route shares, and the // mount table. No route is declared here. Each capability router mounts at the // prefix it already owned inside the old monolithic player.routes.js. // // Self-service account security (`/player/account/*`) used to be mounted here. It // is gone: `/auth/me/account/*` is the single canonical self surface for every // role, and this group's copy was a strictly smaller duplicate of it. // // **Staff are a superset of players.** This group is open to any authenticated // account, not just role 'player': every read/write is self-scoped to req.user.id, // and a staff member has every player ability plus their staff tools on top. // Adding a requireRole('player') here would 403 an admin off their own characters // (it happened once โ€” see docs/website/BACKEND_DESIGN.md). Staff also reach the // identical self-scoped handlers under /admin/shard, which lives in module-uo now // โ€” that changes where they are defined and nothing about which URLs answer. // // See docs/website/API_V2_PLAN.md ยง Phase 2 for the split. const express = require('express') const { requireAuth } = require('../../../auth/session.middleware') const noindex = require('../../../middleware/noindex') const appealsRouter = require('./appeals.router') const teamsRouter = require('./teams.router') const teamForumRouter = require('./teamForum.router') const playerRouter = express.Router() // Group gate: authenticated only (no role restriction). Keep it out of search // indexes. requireAuth also enforces the account status check (a disabled/banned // account is rejected here with 403 before any handler runs). // // It lives here, ahead of every mount, so a capability router added later cannot // silently ship without it. playerRouter.use(noindex, requireAuth) playerRouter.use('/appeals', appealsRouter) playerRouter.use('/teams', teamsRouter) // Same prefix, second router. The forum and the leader-exercised grant flow are a // different capability from "the caller's own Teams", and splitting them keeps // each file about one thing; no path in the two collides. playerRouter.use('/teams', teamForumRouter) module.exports = playerRouter