feat: session mode parsing, memory-only cookies, single-user mode

- COOKIE_SECURE env now accepts: 'true' (secure), 'false' (memory-only), 'single_user' (no cookie)
- config.parse_cookie_mode() returns (COOKIE_SECURE, SINGLE_USER) tuple for routing
- single_user_owner() returns oldest Owner for test/local deployments
- session cookie respects mode: Max-Age only in secure mode, dropped for memory-only
- base.html renders ephemeral-session and single-user banners per mode
- Tests: comprehensive coverage for all three modes with monkeypatch configs
- CLAUDE.md + README docs updated

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 09:21:18 +02:00
co-authored by Claude Haiku 4.5
parent a8bcf7cdeb
commit f70ba93e7a
9 changed files with 231 additions and 12 deletions
+11 -6
View File
@@ -1203,16 +1203,20 @@ div.error > p {
.error p, .notice p { margin: 0; }
/* Memory-only-session banner (COOKIE_SECURE=false): icon, message, and the
escape hatch on one line, stacking on narrow screens. */
.notice.session-ephemeral {
/* Session-mode banners — memory-only (COOKIE_SECURE=false) and single-user
(COOKIE_SECURE=single_user): icon, message, and the escape hatch on one
line, stacking on narrow screens. */
.notice.session-ephemeral,
.notice.session-single-user {
display: flex;
align-items: center;
gap: .6rem;
}
.notice.session-ephemeral p { flex: 1; min-width: 12rem; }
.notice.session-ephemeral .ico { flex: none; }
.notice.session-ephemeral p,
.notice.session-single-user p { flex: 1; min-width: 12rem; }
.notice.session-ephemeral .ico,
.notice.session-single-user .ico { flex: none; }
.notice.session-ephemeral .btn {
flex: none;
@@ -1226,7 +1230,8 @@ div.error > p {
}
@media (max-width: 640px) {
.notice.session-ephemeral { flex-wrap: wrap; }
.notice.session-ephemeral,
.notice.session-single-user { flex-wrap: wrap; }
}
.notice details { margin: .4rem 0 0; }