Greenfield SX-native pivot (NOT a strangler): the host speaks SX/SXTP end to end;
JSON only at the future ActivityPub federation edge.
- OUTPUT: host/json-status -> host/sx-status — every host/ok/host/error response is
text/sx via the serialize primitive (NOT application/json). Flips feed, relations,
blog reads. Tests assert the SX envelope ({:ok true :data ...}).
- DELETE the blog JSON CRUD /posts (POST/PUT/DELETE) + bearer-based host/blog--protect:
a pure old-contract REST mirror. Create/edit go through the HTML editor forms;
programmatic writes speak SXTP. FOLLOW-UP: no browser delete route yet (was JSON-only,
no UI) — add POST /:slug/delete + cascade edge cleanup when the metamodel UI needs it.
- INPUT: host/sx-body (sxtp.sx) parses a text/sx request body to a string-keyed dict
(parse-safe + sxtp/-normalize). feed POST + relations attach/detach read it.
- UNIFIED field reader host/fields / host/field: text/sx body OR urlencoded form by
content-type. The blog form handlers (new/edit/relate/unrelate) + login read through
it — additive, urlencoded still works (no-engine / bootstrap fallback).
Conformance 290/290 (11 suites). Retires the strangler framing in the plan; adds the
'SX all the way out' wire table. The engine half (browser posts text/sx) follows.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
42 lines
1.9 KiB
Plaintext
42 lines
1.9 KiB
Plaintext
;; lib/host/handler.sx — Host handler layer: the bridge from a Dream request to a
|
|
;; subsystem call and back to a Dream response. A host handler IS a Dream handler
|
|
;; (request -> response); these helpers build the SX-native envelope every host
|
|
;; endpoint shares — text/sx, serialized SX wire format (NOT JSON): {:ok true
|
|
;; :data ...} on success, {:ok false :error ...} on failure. The platform speaks
|
|
;; SX end to end; JSON lives only at the ActivityPub federation edge (JSON-LD).
|
|
;; Depends on lib/dream/types.sx.
|
|
|
|
;; ── responses ──────────────────────────────────────────────────────
|
|
|
|
;; SX response at an arbitrary status: content-type text/sx, body = the value
|
|
;; serialized to SX wire format (the same `serialize` SXTP uses). The SX engine /
|
|
;; WASM kernel parses this directly — NO JSON on the internal wire.
|
|
(define host/sx-status
|
|
(fn (status value)
|
|
(dream-response status {:content-type "text/sx; charset=utf-8"}
|
|
(serialize value))))
|
|
|
|
;; Success envelope: 200 {:ok true :data <value>}.
|
|
(define host/ok
|
|
(fn (value)
|
|
(host/sx-status 200 {:ok true :data value})))
|
|
|
|
;; Success envelope at a chosen status (e.g. 201 for a created resource).
|
|
(define host/ok-status
|
|
(fn (status value)
|
|
(host/sx-status status {:ok true :data value})))
|
|
|
|
;; Error envelope: {:ok false :error <message>} at the given status.
|
|
(define host/error
|
|
(fn (status message)
|
|
(host/sx-status status {:ok false :error message})))
|
|
|
|
;; ── request reading ────────────────────────────────────────────────
|
|
|
|
;; Integer query param with a fallback (query params arrive as strings).
|
|
;; Absent param -> fallback; present -> parsed number.
|
|
(define host/query-int
|
|
(fn (req name fallback)
|
|
(let ((raw (dream-query-param req name)))
|
|
(if raw (string->number raw) fallback))))
|