docs(events): the acceptance walk, and the three contracts it moved (Phase 16a)
Phase 16 is split into 16a (the walk), 16b (the cutover) and 16c (runicgateway.com + .profile), because the phase as written asked for a walk "against released artefacts" BEFORE the cutover and all three component repos release on push to `main`. The walk therefore runs against artefacts built from `edge` the way a release builds them, and 16b re-verifies against the real bundle. `EVENTS_PLAN.md` gains the 16a record: the rig, all three deliberate failures passing, the six defects, the one finding withdrawn, and what each fix was verified against. Three contracts move, each because the walk proved the built thing did not match the written one: **`link/v6.md` — a refusal does not spend its key.** Rule 2 had two cases, throw and return, and needed a third: a handler that ran to completion and deliberately refused did nothing, so freezing that refusal as the key's answer made a refusal that WAITING FIXES impossible to retry past. The section now carries the case `uo.world.save` found it with, and the rule the release rests on — do not answer `*.error` after changing the world. `[bridge status` gains `refused=`. **`website/MODULE_API.md` — `revert`'s `idempotencyKey` identifies a dispatch; it is not a key to send on the undo.** The paragraph explained what the key is FOR and never said what it is not, and `module-uo` read it the other way: every despawn went out under the key its spawn had used, so a store that keys on the key alone answered the undo with the DO's reply and teardown became a no-op that reported success. **`website/EVENTS.md` §I — the public calendar matches a run that OVERLAPS the window.** The row promised "upcoming, live and recent" and the built route served only the first, because it read the start instant and a live run has already started. The default window now reaches back so "recent" has somewhere to live, and projections are forecast from now rather than into that tail. Pairs with `website#`, `Module-uo#` and `servuo-plugins#`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
@@ -1847,7 +1847,7 @@ no URL moved.
|
||||
| `DELETE /admin/events/series/:seriesId` | admin, editor | delete it, detaching its definitions; answers with how many |
|
||||
| `GET /admin/events/calendar` | staff | the calendar for a window: materialised runs and projected occurrences (Phase 4) |
|
||||
| `GET/PUT /admin/events/actions` | admin | which actions are enabled on this deployment, and their per-run caps (Phase 6). `admin` on the read as well as the write; the PUT takes one action at a time |
|
||||
| `GET /public/events` | — | **the calendar** (Phase 14a): upcoming, live and recent, by series. Runs and projections interleaved and each saying which it is, ascending by instant. Instants are UTC and every entry carries the EVENT's own zone; the reader's zone places them. Rehearsals and unlisted events are absent. Defaults to now through 31 days out and the window may span at most 92 — the anonymous surface is the one with no login in front of it |
|
||||
| `GET /public/events` | — | **the calendar** (Phase 14a): upcoming, live and recent, by series. Runs and projections interleaved and each saying which it is, ascending by instant. Instants are UTC and every entry carries the EVENT's own zone; the reader's zone places them. Rehearsals and unlisted events are absent. A run is an INTERVAL, not an instant: an entry is in the window when the run OVERLAPS it, so one that began before the window and has not ended is still "what is on" (Phase 16a — reading the start instant alone made this route serve only the first of its three words, while the event's own page said `live`). Defaults to seven days back through 31 days out — the tail is where "recent" lives — and the window may span at most 92; the anonymous surface is the one with no login in front of it. Projections are forecast from NOW, never into the tail, since a slot the runner has already passed did not happen |
|
||||
| `GET /public/events/:slug` | — | **one event** (Phase 14a): storyline, arc, what is live, what is next, what happened recently, and a results table once one is published. Takes an optional `?run=`, which is what an announcement's link carries, so a mail about last Friday's occurrence does not open next Friday's; a run belonging to some other event is **ignored rather than refused**, because a stale link in a months-old mail should land on the event it was about. A draft, an archived definition and an unlisted one all answer 404 |
|
||||
| `GET /public/events/series/:slug` | — | **the arc** (Phase 14a). A series with no listed events is a 404, not an empty page: the arc is a label on its definitions, so a page for an empty one would publish the fact that an operator has named something they have not announced |
|
||||
| `GET /player/events/history` | auth | **this account's participation** (Phase 14a) — the run, when it was, the score a module reported, and the rank once results were published (null until then, which is a real state rather than an error). Self-scoped on the session with **no id parameter**, deliberately: a route that took one would be a middleware mistake away from publishing who attended what. Keyset-paged on the participation row's id. It obeys the calendar's two exclusions, so attending an unannounced event does not disclose that it exists |
|
||||
|
||||
Reference in New Issue
Block a user