Announced pages: event windows, header announcements, summary tasks

A question may carry event: {starts, duration, place}. While the
window is open the page is announced in a strip at the top of every
header (name, when, 'in 3 days'), soonest first, and kept out of the
footer nav; when it closes the page becomes a followup - only a
visitor carrying an answer chain still sees it.

announce.rs keeps one record per event page in the runtime-owned
portal_events bucket (built-in state graph: announced ->
awaiting_summary -> summarized, content may override) and, on a
one-minute idempotent sweep, moves ended windows to awaiting_summary,
publishing the transition on portal.answers.submitted as 'Summary
due' - the post-what-happened task a review desk picks up. Lint
warns when event pages exist but nothing reads portal_events.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-08-30 12:34:34 +02:00
co-authored by Claude Fable 5
parent 47d7f9d2c3
commit 0154f6c8c0
8 changed files with 558 additions and 4 deletions
+7
View File
@@ -39,6 +39,13 @@ stream.
`requires_chain` gates a page on verifiable answer provenance next
to `qualifies`' Kanidm-group identity gate (see
`docs/design/filesystem-routes.md`).
- **Announced pages** (`src/announce.rs`): a question with an
`event: {starts, duration, place}` window is announced in the
header (not the footer nav) while the window is open, becomes a
followup when it closes, and its record in the runtime-owned
`portal_events` bucket moves to `awaiting_summary` - a "post what
happened" task any review desk can read, published on NATS like a
decision. A one-minute sweeper keeps it all idempotent.
- **State machines as content** (`src/aggregates/`): `aggregates.yaml`
declares each bucket's states and legal transitions; the engine
replays a record's event history and refuses undeclared moves, with