docs(events): Phase 1 as built — schema, CRUD and the core action registry
The docs half of RunicGateway/website#<n>. Three files.
**BACKEND_DESIGN.md** gains the six event tables, column by column, and the
eleven admin routes. Written where the other table groups are, in the same
shape, because the argument for a column belongs beside the column.
**EVENTS.md** records four things the build settled that §D and §F had left
open:
- `event_definitions.spec`, the working copy. §D's column list does not name
one because §D describes what a PUBLISHED event is made of — but "editing a
draft is free; no version exists yet" means the draft has to live somewhere,
and it cannot be an `event_versions` row: that table is immutable and a run
pins one, so a mutable unpublished row in it would be exactly what
versioning exists to prevent.
- A param's `example` is REQUIRED, on optional params too, the same rule
`registerEventTriggers` makes of a variable's example and for the same
reason: it is the authoring form's placeholder, one word at declaration
time and unreconstructable afterwards.
- The authoring side of dormancy. §F said what happens at DISPATCH; the save
path draws the same line one step earlier, in the shape `engagement_rules`
established — a saved step may keep an unregistered action, a new step may
not add one, and a dormant step blocks the publish rather than the save.
- Publish re-validates against the registries as they stand at that moment,
not from the save that wrote the spec.
Plus two routes the § API surface table did not name — `GET /admin/events/:id`
(the list serves a summary; the editor needs the tree) and `GET
/admin/events/series` (a form cannot offer a value it cannot enumerate) — and a
note stating which of that table's rows Phase 1 deliberately did not build.
**EVENTS_PLAN.md** marks Phase 1 complete, names those four settlements, and
states the two deliberate absences so a reviewer does not read them as gaps:
the live run controls are not stubbed, and core's three `perform()` bodies
answer `{ ok: false }` rather than `{ ok: true }` — `ok: true` on an action
that did nothing is a recorded world change that did not occur.
`api-route-inventory.json` is NOT resynced here. It has been stale since
engagement Phase 2 and is 47 routes behind; catching it up in this PR would
bury a 13-route change under an unrelated 47.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,38 @@ document and should be written where they will be found:
|
||||
|
||||
### Phase 1 — Schema, CRUD and the core action registry (`website` + `docs`)
|
||||
|
||||
> **Complete.** `edge` in `website` and `docs`. Six tables, thirteen routes, the action registry with
|
||||
> core as its first registrant, and 44 tests. **Nothing dispatches** — a run row is created and stays
|
||||
> `scheduled`, which is this phase's correct answer and is rendered as such.
|
||||
>
|
||||
> **Four things the build settled that the plan had left open, each recorded in `EVENTS.md`:**
|
||||
>
|
||||
> - **`event_definitions` gained a `spec` column.** §D's column list does not name one, because §D
|
||||
> describes what a published event is made of. But "editing a draft is free; no version exists yet"
|
||||
> means the working copy has to live somewhere, and it cannot be an `event_versions` row: that table
|
||||
> is immutable and a run pins one. Publishing copies the column into a version and leaves it as the
|
||||
> next draft.
|
||||
> - **The spec validator must accept its own output**, and a test found it did not. `validate()` adds
|
||||
> `actionVersion` and `dormant`, then refused them as unknown keys on the next call — which would
|
||||
> have made the *second* save of any definition, and publish's own re-validation, impossible. Both
|
||||
> are now accepted and recomputed rather than trusted.
|
||||
> - **A param's `example` is required**, on optional params too, matching `registerEventTriggers`. It
|
||||
> is the authoring form's placeholder and there is no other source for one.
|
||||
> - **Two routes the §API-surface table did not name**: `GET /admin/events/:id` (the list serves a
|
||||
> summary; the editor needs the tree) and `GET /admin/events/series` (a form cannot offer a value it
|
||||
> cannot enumerate). Both are staff reads over data the list already exposes.
|
||||
>
|
||||
> **Two deliberate absences, both stated so a reviewer does not read them as gaps.** The live run
|
||||
> controls and `verify` are not stubbed — nothing is in flight until P2, and a control that answers
|
||||
> `200` and does nothing is worse than one that is not there. And core's three `perform()` bodies
|
||||
> answer `{ ok: false, retry: false }` rather than `{ ok: true }`: `ok: true` on an action that did
|
||||
> nothing is a recorded world change that did not occur, which is the exact mistake §F's failure
|
||||
> default exists to prevent.
|
||||
>
|
||||
> `registerEventActions` is on the staging area and reachable **only** by `registerCore()` — the
|
||||
> loader builds its own `api` facade and has no method that delegates to it, so no module can call it
|
||||
> yet and `MODULE_API_VERSION` is untouched. P7 adds that facade and makes the bump.
|
||||
|
||||
The six tables that do not depend on the module contract: `event_definitions`, `event_series`,
|
||||
`event_versions`, `event_runs`, `event_run_steps`, `event_run_log`. Admin CRUD, publish (which
|
||||
snapshots a version), archive. `router/v1/admin/events.router.js` + `events.controller.js`, models as
|
||||
|
||||
Reference in New Issue
Block a user