docs(website): the public surface, and the flag that decides what reaches it (Phase 14a)

EVENTS.md gains what the phase settled -- a new §I section on the public
surface, the four API surface rows filled in, `listed` in §D, and the §J
rows for player profiles and mobile. EVENTS_PLAN.md records the 14a/14b
split and 14a as built. BACKEND_DESIGN.md points at the two tiers the
Phase 14a reads live on. MODULE_API.md records core's own capability list
beside a module's -- the same word, a separate list, and why.

Two things this phase corrected in the document rather than in code.

"Venue" was never a field. §I's screens table and the API surface table had
both described one since the first revision; there has never been a column,
a spec key, an input on Phase 13's form, or a string anywhere in either
repo. Rather than add a field on the way past to a public page, both
descriptions dropped it.

And the six public triggers' missing url variable, which this document has
carried as a promise since Phase 10, is now kept: `eventUrl`, carrying
`?run=`, arriving with the page it points at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
2026-09-08 06:18:55 -05:00
parent c17893a215
commit 9aee5920af
4 changed files with 172 additions and 27 deletions

View File

@@ -1422,6 +1422,17 @@ Four fields, in the loader's scan order (§4.2). What is *not* there is the desi
string. A client must treat an unknown capability as absent and must not infer a route from one — the
mount prefixes are `module.json`'s business (§2.3), not the capability list's.
**Core publishes a capability list of its own, and it is deliberately not this one.** Since events
Phase 14a, `GET /public/version` — and `GET /public/status`, which embeds the same block — carries a
`capabilities` array naming what CORE serves beyond the baseline every backend has. It is the same
idea and the same word so that a client feature-detects one way rather than two, and a **separate
list** because core is not a module: publishing core here as a pseudo-module would leave a client
unable to tell *"this backend has events"* from *"a module called core happens to be installed"*,
which is exactly the distinction this endpoint exists to make. The value in core's list is in what is
absent — a backend released before a capability existed omits the key entirely, which is how a client
tells an older site from one that simply has nothing to show. The same rule applies to both: an
unknown string is absent, and no route may be inferred from one.
The endpoint owns the `/modules` prefix on the public tier, which is *why* it is a router of its own
rather than a fifth singleton beside `/settings` and `/version`. The loader's collision probe reads
the live tier stack and skips root-mounted layers (a `use('/', …)` matches every path), so a route