Attended-bucket lint rule; app-lifetime resources fix first-nav corruption
Test / test (push) Successful in 25s

validate_questions now rejects content where a record_as bucket is
read by nothing: every bucket must be listed by some Kv resource in
the same repo (a desk) or carry aggregates.yaml's new attended_by
annotation naming the automation that consumes it - no publicly
collected answer may land where nothing reads.

Separately, all server-fn resources (question/user/nav) move to a
PortalShell above the routes, created once and provided via context.
Per-page Resources broke on the first client-side navigation: the
remounted component's fresh Resource consumed a stale SSR hydration
buffer - the nav list [[id, name], ..] deserialized as a Page (serde
fills structs from sequences in field order), so uhhm.no's landing
question rendered chain-gated behind its own nav entry instead of
the /develop/proposal form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-08-25 15:36:07 +02:00
co-authored by Claude Fable 5
parent 0d6cdb8a00
commit a1fc333079
3 changed files with 141 additions and 11 deletions
+9
View File
@@ -30,6 +30,12 @@ pub struct AggregateSchema {
pub event_for_state: HashMap<String, String>,
pub state_for_event: HashMap<String, String>,
pub transitions: HashMap<String, Vec<String>>,
/// Names what consumes this bucket's answers when no page in the
/// content repo reads it (e.g. "n8n newsletter compose").
/// Free-text - it exists so `validate_questions`' attended-bucket
/// rule has an explicit, auditable opt-out instead of a silent
/// one, and so the next reader knows where the answers go.
pub attended_by: Option<String>,
}
impl AggregateSchema {
@@ -57,6 +63,8 @@ struct RawAggregateSchema {
states: HashMap<String, RawState>,
#[serde(default)]
transitions: HashMap<String, Vec<String>>,
#[serde(default)]
attended_by: Option<String>,
}
#[derive(Debug, serde::Deserialize)]
@@ -123,6 +131,7 @@ pub fn parse_aggregates_yaml(raw: &str) -> anyhow::Result<HashMap<String, Aggreg
event_for_state,
state_for_event,
transitions: raw_schema.transitions,
attended_by: raw_schema.attended_by,
},
);
}