Portal v0.6.21 serves this repo's .well-known/ at the root of the site,
so security.txt is a file in this repo rather than something only a
reverse proxy could place. A path that is not here answers 404 now,
instead of the app shell answering 200 with HTML.
Caddy also hands /.well-known/caldav and /.well-known/carddav to
Stalwart, which answers each with a 307 to the collection. RFC 6764 has
a client look for these on the domain its address is in - and iOS uses
them, which matters because Apple Mail ignores both autoconfig and
Autodiscover for IMAP accounts and discovers nothing else by itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015GeH3y8fwTaTudaD88P57o
Attachments both ways, rate limiting, sessions that survive a deploy,
and an upload route that asks the policy like every other way in.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four releases on from v0.3.36: maps and `place:`, a reply to a case
mail becoming a note on its record, and the access policy's newer
rules. iris moves with it, since it is the lint for exactly this
portal.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A development-proposal PR previously got no check at all (the workflow
only fired on push to main) - so branch protection's required status
check, the thing that makes the automation's merge_when_checks_succeed
an actual lint gate, had nothing to require. Lint now runs on both
events; the content-reload NATS publish stays push-only.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
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).