diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 9189805..78dd16b 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -18,7 +18,7 @@ on: - .gitea/workflows/deploy.yml env: - PORTAL_RELEASE: v0.1.0 + PORTAL_RELEASE: v0.2.0 INSTANCE: uhhm-portal jobs: diff --git a/README.md b/README.md index 41c12c5..ceecd15 100644 --- a/README.md +++ b/README.md @@ -167,10 +167,14 @@ The rules every page here follows: The exact structs live in portal's `src/content.rs`; the shape: ``` -Question id (doubles as the URL path), name, description, - qualifies (Kanidm group gate), followup (nav-hidden - until the visitor carries a chain), - responsible {name, contact}, alternatives[] +Question id (derived from the file's path - see routing + below - declare only to override), name, + description, qualifies (Kanidm group gate), + requires_chain (question ref the visitor's ?chain= + lineage must end at), followup (nav-hidden until + the visitor carries a chain; inferred from the + tree when unset), responsible {name, contact}, + alternatives[] Alternative name, description, action, consequence[label], encouragements[], images[] (1 = banner, 2+ = card deck), record_as (bucket), self_transition {bucket, to, label}, @@ -208,9 +212,54 @@ review resource's transitions — fireable by whoever holds one specific record's `?chain=` link plus its matching email (the unsubscribe pattern). +## Routing: the tree is the router + +The `questions/` directory tree is the URL tree — `index.yaml` names +its directory, everything else appends its stem: + +``` +questions/ + index.yaml / + applied.yaml /applied + develop/ + index.yaml /develop + proposal.yaml /develop/proposal + proposed.yaml /develop/proposed + review/ + _section.yaml (not a page - defaults for the directory) + index.yaml /review + [record].yaml /review/ +``` + +- `id:` is derived from the path; declaring it still wins (legacy), + with a lint warning when it disagrees. +- `action:` and `requires_chain:` take relative refs — `proposed` + names a sibling, `../x` climbs, `/x` is absolute. A directory is a + self-contained flow: `git mv` renames every internal edge with it. +- Files nested in a subdirectory infer `followup: true` unless + they're the directory's `index.yaml` — declare `followup: false` + on a nested page that should stay in the nav. Top-level files keep + the flat-repo default (not a followup). +- `_section.yaml` applies `qualifies`, `requires_chain`, and + `responsible` to every page at or below its directory (nearest + ancestor wins; a page's own declaration always overrides). A URL + prefix is a trust boundary. +- Any other `_`-prefixed file is skipped entirely — drafts live in + the tree without being served. +- `[name].yaml` is a dynamic page: it serves every `/dir/`, + with the segment substituted into `{name}` placeholders in the + page's resource `key`s (`/review/` shows that one + record). One per directory; never in the nav; not a valid `action` + target. +- `requires_chain: ` gates a page on provenance instead of + identity: the visitor's `?chain=` lineage must verifiably end at an + answer to the referenced question, otherwise the page renders a + pointer there instead of its alternatives. + ## Adding a page -Drop a `questions/.yaml` with a unique `id`, reference that `id` -from some alternative's `action`, push. Lint runs, portal hot-reloads, -the page is live — no registration, no deploy. Or propose it through -`/develop-proposal` and let the loop do the pushing. +Drop a YAML file where its URL should live (`questions/foo.yaml` → +`/foo`, `questions/flow/step.yaml` → `/flow/step`), reference it from +some alternative's `action`, push. Lint runs, portal hot-reloads, the +page is live — no registration, no deploy. Or propose it through +`/develop/proposal` and let the loop do the pushing.