Commit Graph
66 Commits
Author SHA1 Message Date
Bendik Aagaard LynghaugandClaude Sonnet 5 326f2d884a Temporary: demo Feature.color/icon and Alternative.image for a visual check
Lint and reload / lint-and-reload (push) Successful in 2s
Will be reverted right after confirming the render looks right.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 17:35:53 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 f0abf71d47 review.yaml: give Applicants/Projects a shared consequence button too
Lint and reload / lint-and-reload (push) Successful in 2s
Matches the pattern Subscribers already used (action: /review +
consequence). Portal's per-row Confirm button is going away in favor
of one shared, content-labeled button per alternative that confirms
every selected row at once - see the paired portal change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 14:31:59 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 4efa26585a Add aggregates.yaml: the full state graph for applicants/subscribers/projects/organizations
Lint and reload / lint-and-reload (push) Successful in 2s
Portal's aggregate state machines used to be compiled Rust, duplicated
across four files plus the bucket-name wiring that dispatched to them.
This is now the single source of truth for what states exist, what
event-type string represents each, and what transitions are legal -
portal loads and validates it at boot/reload (see the paired portal
change). Adding a new aggregate, or reshaping an existing one, is now
a content-only change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 21:42:57 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 bc18add801 Lint with portal's question_lint binary, not the hand-maintained yq/jq script
Lint and reload / lint-and-reload (push) Successful in 2s
lint.sh only ever checked shape (missing id/name, duplicate ids, bad
requirement types) - it never validated transition targets against the
real state machines. question_lint runs portal's actual validation
logic (content::validate_questions) with no portal build required in
this repo's CI, since portal's deploy job now publishes it to a stable
path on the same runner/host.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 21:16:54 +02:00
Bendik Aagaard Lynghaug e8f266e8f7 Drop the last "someone reads it" phrasing, match the "we" voice used elsewhere
Lint and reload / lint-and-reload (push) Successful in 3s
applied.yaml and index.yaml still described review in the passive
third person ("someone here will read this", "taken on by someone
who reads") after project.yaml and the rest of applied.yaml's own
features had already been reworked to a direct first-person "we"
voice centered on the visitor's value, not on the fact that a person
reads it.
2026-08-06 22:06:44 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 a9eaca6b78 Speak to the applicant's actual concern, not just the process
Lint and reload / lint-and-reload (push) Successful in 3s
"A person reads it" reassures about process (a human, not a bot) but
never answers what an applicant actually wants to know: does what I
specifically bring matter here? Rewrote to say that directly, and
named how it gets used once they're in - dialogue-centered
development, not a queue of pre-decided tasks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 12:57:21 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 1b709d2a67 Ask subscribers for their name too, not just email
Lint and reload / lint-and-reload (push) Successful in 3s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 11:59:11 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 2af9a46afb lint.sh: accept type: select as a valid requirement type
Lint and reload / lint-and-reload (push) Successful in 3s
Matches portal's new resource-backed multi/single-select requirement
kind.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 11:57:21 +02:00
Bendik Aagaard LynghaugandClaude Sonnet 5 a424c6d3c2 Rename buckets, fold inquiry into project, add showcase + org fields
Lint and reload / lint-and-reload (push) Successful in 2s
Bucket names describe content, not their relation to portal:
portal_applicants -> applicants, portal_subscribers -> subscribers,
portal_project_inquiries -> projects. ResourceSpec's `bucket:` field
becomes `source: {kind: kv, bucket: ...}` to match portal's new
generalized ResourceSource schema.

The project-inquiry alternative now also shows a live "what we've
built" showcase (a gitea_starred resource, jq-shaped) and asks who the
work is for (organization/contact fields) - b2b framing. Review desk's
"Inquiries" -> "Projects", transitions to accepted/declined instead of
a generic "handled".

Front page gets a `responsible` contact for the "report this question"
mechanism.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 08:53:01 +02:00
Bendik Aagaard Lynghaug 731f307ce1 Add self-service Unsubscribe alternative to /subscribed
Lint and reload / lint-and-reload (push) Successful in 3s
Only shows when reached via a ?chain=&email= link (see portal's
self_transition), matching the link the newsletter workflow now
appends to every send.
2026-08-05 18:48:25 +02:00
Bendik Aagaard Lynghaug 9910ce0ec4 Fold newsletter compose into Subscribers as a second feature, not its own alternative
Lint and reload / lint-and-reload (push) Successful in 2s
Per feedback: sending a newsletter is naturally part of "Subscribers",
not a separate review task. Also fixes a real bug - the standalone
Compose newsletter alternative had no `action`, so AlternativeCard
never rendered a submit button/form for it at all (has_action gates
the <form>, unconditionally). action: /review reloads the dashboard
after sending.
2026-08-05 14:23:38 +02:00
Bendik Aagaard Lynghaug 6ed0b65bc2 Add portal_project_inquiries/portal_subscribers durable storage, review dashboard alternatives, newsletter compose
Lint and reload / lint-and-reload (push) Successful in 3s
- index.yaml: record_as on "I want something built" and "Keep me
  posted" - those submissions previously only existed as a NATS
  event, nothing durable, despite promising a reply/subscription.
- review.yaml: consolidated into one dashboard question with four
  alternatives (Applicants, Inquiries, Subscribers, Compose
  newsletter) rather than separate pages per resource.
- Compose newsletter has no record_as/resource of its own - an
  automation (n8n) filters portal.answers.submitted directly for
  question_id == "/review" && alternative == "Compose newsletter",
  matching events.rs's own "gain a second subscriber" design.
- lint.sh: allow type: prosekit (the new rich-text requirement kind).
2026-08-05 13:46:17 +02:00
Bendik Aagaard Lynghaug 1f0d930768 Invoke lint.sh via bash - checkout didn't preserve the exec bit
Lint and reload / lint-and-reload (push) Successful in 3s
2026-08-05 07:20:18 +02:00
Bendik Aagaard Lynghaug fc4cd1b86e Add lint + reload-trigger workflow
Lint and reload / lint-and-reload (push) Failing after 2s
Validates YAML/required fields/duplicate ids/requirement types with
yq+jq against the exact shape content.rs parses (not a full schema
check - that would mean building portal just to lint content), then
publishes portal.content.reload over NATS so every running portal
instance picks up the change without a restart (portal's own
content::watch_for_reload, added alongside this).
2026-08-05 07:19:07 +02:00
Bendik Aagaard Lynghaug d8628dbd15 Rework copy voice, add /review, Kanidm-gated applicant review
English URLs throughout; review.yaml adds a qualifies-gated question
listing applicants via the generic NATS-KV resource mechanism, with
Invite/Decline transitions. Content pass: concrete/positive phrasing
(no negation constructions), warmer inclusive tone, light puns in the
encouragement lines.
2026-07-29 19:39:00 +02:00
Bendik Aagaard Lynghaug 5321f70540 Initial content: opener, project, subscribed, applied 2026-07-29 12:51:55 +02:00