Storylines: the same site told several ways, one per visitor, counted
docs / deploy (push) Successful in 3s
Test / test (push) Successful in 1m1s

Any text a person reads may be a list, one entry per storyline, every
list the same length. A visitor is given one storyline for the whole
site and reads it on every page and in every mail about their case.
Records and events carry the storyline; GET /report gives counts per
bucket, storyline and state, and nothing else.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
This commit is contained in:
Bendik Aagaard Lynghaug
2026-09-30 15:11:27 +02:00
co-authored by Claude Fable 5.1
parent cc3107e502
commit f395ace556
24 changed files with 561 additions and 45 deletions
+4 -3
View File
@@ -1,6 +1,7 @@
#![cfg(feature = "ssr")]
pub mod oidc;
pub mod storyline;
use arc_swap::ArcSwap;
use axum::extract::FromRef;
@@ -21,18 +22,18 @@ pub struct AppState {
/// message (see `content::watch_for_reload`) - readers never hold
/// a lock, just an atomic pointer load, so a reload never blocks or
/// is blocked by an in-flight request.
pub questions: Arc<ArcSwap<HashMap<String, Question>>>,
pub questions: Arc<ArcSwap<crate::content::Storylines<HashMap<String, Question>>>>,
/// Every bucket's event-sourced state graph, loaded from
/// `aggregates.yaml` (see `content::load_aggregates_from_gitea`) and
/// hot-swapped alongside `questions` on the same reload. A bucket
/// with no entry here isn't event-sourced - plain KV mutate-in-place
/// still works (see `answers.rs`).
pub aggregates: Arc<ArcSwap<HashMap<String, crate::aggregates::AggregateSchema>>>,
pub aggregates: Arc<ArcSwap<crate::content::Storylines<HashMap<String, crate::aggregates::AggregateSchema>>>>,
/// Site branding from the content repo's optional `site.yaml`
/// (title, wordmark, hero kind) - hot-swapped with `questions`/
/// `aggregates` on the same reload. Default = the historical uhhm
/// look.
pub site: Arc<ArcSwap<crate::content::SiteConfig>>,
pub site: Arc<ArcSwap<crate::content::Storylines<crate::content::SiteConfig>>>,
/// The access policy compiled from the content above (see
/// `access.rs`), swapped with it on every reload. Every server entry
/// point decides through this and nothing else.