The anonymous surface an event was always for: GET /public/events, /public/events/:slug and /public/events/series/:slug, plus GET /player/events/history, and the four screens over them. Four org-lead decisions taken up front: split Phase 14 into 14a (website) and 14b (the app); add a `listed` flag rather than letting `state` mean both schedulable and announced; put the `events` capability string in the version block rather than publishing core as a pseudo-module; and drop "venue" from the spec rather than adding a field nothing had ever built. `listed` is announcement, not permission. Publishing is what makes a definition runnable, so without a separate flag a surprise event would have to be advertised in order to be allowed to happen. It is a column, a switch in Phase 13's editor, and three SQL predicates -- never a filter applied after a read, which works exactly as well until the first caller that forgets. The public shapes are a projection, and the projection is the security boundary: nothing is spread, so a column added to event_runs next year does not ride out through it. The spec, health, cleanup, claims, errors and member_key are all absent by construction. The six public event triggers gained `eventUrl` (version 1 -> 2), carrying ?run= because the page lives at the definition's slug while every trigger is about one occurrence. notify.event-started gained the button, at seedVersion 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
40 lines
2.4 KiB
JavaScript
40 lines
2.4 KiB
JavaScript
// Player · Events — this account's participation history (EVENTS.md § API
|
||
// surface, Phase 14a). Mounted at /api/v1/player/events by player/index.js.
|
||
//
|
||
// The group gate is `requireAuth` and it is the whole gate: this is role-agnostic
|
||
// self-service, like the rest of /player. Staff are a superset of players (see
|
||
// player/index.js), and an admin reading their own attendance is exactly as
|
||
// ordinary as a player doing it.
|
||
//
|
||
// **No backtick in a `#swagger.parameters` annotation.** Unlike `#swagger.summary`
|
||
// and `#swagger.description`, which are plain strings, a parameters annotation is
|
||
// parsed as an object literal — a backtick inside its quoted `description` is
|
||
// rewritten as a quote, and swagger-autogen then DROPS the whole annotation with a
|
||
// syntax error rather than failing the build.
|
||
//
|
||
// **There is no id parameter, deliberately.** The history is `req.user.id`'s and
|
||
// nothing else's; a route that took a user id would be one middleware mistake
|
||
// away from publishing who attended what, which is a question about people
|
||
// rather than about events.
|
||
|
||
const express = require('express')
|
||
|
||
const ctrl = require('./events.controller')
|
||
|
||
const eventsRouter = express.Router()
|
||
|
||
eventsRouter.get(
|
||
'/history',
|
||
// #swagger.tags = ['Player · Events']
|
||
// #swagger.summary = 'This account’s event participation'
|
||
// #swagger.description = 'The events this account took part in, most recent first — the run, when it was, the score a module reported, and the rank once results were published. `rank` is null until then, which is a real state rather than an error. Rehearsals and unlisted events are absent, the same rule the public calendar follows. Keyset paging: pass the last entry’s `id` as `before`.'
|
||
// #swagger.parameters['limit'] = { in: 'query', required: false, schema: { type: 'integer' }, description: 'Page size, max 200 (default 50).' }
|
||
// #swagger.parameters['before'] = { in: 'query', required: false, schema: { type: 'integer' }, description: 'Cursor: the id of the last entry on the previous page.' }
|
||
// #swagger.security = [{ "cookieAuth": [] }, { "bearerAuth": [] }]
|
||
/* #swagger.responses[200] = { description: 'Participation history', content: { "application/json": { schema: { $ref: "#/components/schemas/PlayerEventHistory" } } } } */
|
||
/* #swagger.responses[401] = { description: 'Not signed in', content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } } */
|
||
ctrl.getHistory,
|
||
)
|
||
|
||
module.exports = eventsRouter
|