Unblock the guarded blog write routes for browsers: a login form sets a
signed session cookie that the same routes accept (alongside Bearer), so
publishing works end-to-end on blog.rose-ash.com without Quart.
- kernel: http-listen emit serialises a response :set-cookies LIST as one
Set-Cookie header each (a headers dict can't hold more than one). Purely
additive — responses without :set-cookies are unchanged.
- server.sx: host/-dream->native forwards :set-cookies to the native resp.
- lib/host/session.sx: durable, signed sessions on the persist KV
(session/create|exists|get|set|clear), wired via dream-sessions-signed.
- lib/host/auth.sx: GET/POST /login + POST /logout; host/require-user accepts
a session principal OR a Bearer token.
- router.sx: host/make-app wraps the whole app in the session middleware and
auto-mounts /login + /logout — the front door always has sessions.
- blog.sx: write routes use host/require-user; serve.sh flips POST /new from
the experimental UNGUARDED route to the guarded write routes, with admin
creds + signing secret + ACL grant from the container env.
- session conformance suite (12): login->cookie->guarded write 201; no
cookie/forged/logged-out -> 401; Bearer fallback still works.
Verified live on blog.rose-ash.com: 401 unauthenticated, 303 login, 303
publish, anonymous read renders, post persists across container recreate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First migrated endpoint onto the SX host. lib/host is a thin wiring layer:
a host handler is a Dream handler (request->response) that calls a subsystem
public API and serialises via a shared JSON envelope.
- handler.sx: host/ok, host/ok-status, host/error, host/json-status (Dream's
dream-json is 200-only), host/query-int
- router.sx: host/make-app assembles per-domain route groups + /health probe
into one dream-router (reuses dr/flatten-routes)
- feed.sx: GET /feed reads feed/all + stream combinators, recent-first, with
?actor= filter and ?limit= cap
- 3 test suites incl. a golden test (body == subsystem recent stream + envelope)
- conformance.sh mirrors lib/dream's runner
Builds on dream-on-sx (merged, gate green 480/480) rather than a throwaway
native request model; collapses most of plan Phase 4 into Phase 1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>