host: SX-native wire — reads + write bodies are text/sx, JSON CRUD deleted
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>
This commit is contained in:
@@ -42,8 +42,8 @@
|
||||
(host-bl-test "home lists post"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/"))) "href=\"/hello/\"")
|
||||
true)
|
||||
(host-bl-test "json list shows post"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/posts"))) "\"slug\":\"hello\"")
|
||||
(host-bl-test "sx list shows post"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/posts"))) ":slug \"hello\"")
|
||||
true)
|
||||
(host-bl-test "GET /new shows form"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/new"))) "<form")
|
||||
@@ -53,7 +53,7 @@
|
||||
(host-bl-test "unknown slug 404" (dream-status (host-bl-app (host-bl-req "/nope/"))) 404)
|
||||
(feed/reset!)
|
||||
(host-bl-test "/feed not captured by :slug"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/feed"))) "\"ok\":true")
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/feed"))) ":ok true")
|
||||
true)
|
||||
|
||||
;; ── writes: editor form ingest + JSON CRUD (auth+ACL) ───────────────
|
||||
@@ -94,39 +94,8 @@
|
||||
(contains? (dream-resp-body (host-bl-wapp (host-bl-req "/my-first-post/"))) "<h1>My First Post</h1>")
|
||||
true)
|
||||
|
||||
;; -- JSON CRUD --
|
||||
(host-bl-test "json create -> 201"
|
||||
(dream-status (host-bl-wapp (host-bl-send "POST" "/posts" "Bearer good" "application/json"
|
||||
"{\"title\":\"Json Post\",\"sx_content\":\"(p \\\"jp\\\")\",\"status\":\"draft\"}")))
|
||||
201)
|
||||
(host-bl-test "json create unpermitted -> 403"
|
||||
(dream-status (host-bl-wapp (host-bl-send "POST" "/posts" "Bearer weak" "application/json"
|
||||
"{\"title\":\"Nope\"}")))
|
||||
403)
|
||||
(host-bl-test "json create duplicate -> 409"
|
||||
(dream-status (host-bl-wapp (host-bl-send "POST" "/posts" "Bearer good" "application/json"
|
||||
"{\"slug\":\"json-post\",\"title\":\"Json Post\"}")))
|
||||
409)
|
||||
(host-bl-test "json create no title -> 400"
|
||||
(dream-status (host-bl-wapp (host-bl-send "POST" "/posts" "Bearer good" "application/json" "{}")))
|
||||
400)
|
||||
(host-bl-test "update -> 200"
|
||||
(dream-status (host-bl-wapp (host-bl-send "PUT" "/posts/json-post" "Bearer good" "application/json"
|
||||
"{\"sx_content\":\"(p \\\"edited\\\")\"}")))
|
||||
200)
|
||||
(host-bl-test "update changed content"
|
||||
(contains? (dream-resp-body (host-bl-wapp (host-bl-req "/json-post/"))) "edited")
|
||||
true)
|
||||
(host-bl-test "update missing -> 404"
|
||||
(dream-status (host-bl-wapp (host-bl-send "PUT" "/posts/ghost" "Bearer good" "application/json" "{}")))
|
||||
404)
|
||||
(host-bl-test "delete -> 200"
|
||||
(dream-status (host-bl-wapp (host-bl-send "DELETE" "/posts/json-post" "Bearer good" "" "")))
|
||||
200)
|
||||
(host-bl-test "deleted -> 404" (dream-status (host-bl-wapp (host-bl-req "/json-post/"))) 404)
|
||||
(host-bl-test "delete missing -> 404"
|
||||
(dream-status (host-bl-wapp (host-bl-send "DELETE" "/posts/ghost" "Bearer good" "" "")))
|
||||
404)
|
||||
;; (JSON CRUD tests removed — the /posts JSON create/update/delete endpoints were
|
||||
;; deleted in the SX-native pivot; create + edit go through the form ingest above.)
|
||||
|
||||
;; -- write-time validation: malformed sx_content rejected, never stored --
|
||||
;; "%3Ch1+broken%29" decodes to "<h1 broken)" — a typo'd paren the parser rejects.
|
||||
@@ -138,20 +107,8 @@
|
||||
(host-bl-test "rejected form post was not stored"
|
||||
(dream-status (host-bl-wapp (host-bl-req "/bad-form/")))
|
||||
404)
|
||||
(host-bl-test "json create malformed sx_content -> 400"
|
||||
(dream-status (host-bl-wapp (host-bl-send "POST" "/posts" "Bearer good" "application/json"
|
||||
"{\"title\":\"Bad Json\",\"sx_content\":\"<h1 broken)\"}")))
|
||||
400)
|
||||
(host-bl-test "rejected json post was not stored"
|
||||
(dream-status (host-bl-wapp (host-bl-req "/bad-json/")))
|
||||
404)
|
||||
(host-bl-test "json update malformed sx_content -> 400"
|
||||
(dream-status (host-bl-wapp (host-bl-send "PUT" "/posts/my-first-post" "Bearer good"
|
||||
"application/json" "{\"sx_content\":\"<h1 broken)\"}")))
|
||||
400)
|
||||
(host-bl-test "rejected update left content intact"
|
||||
(contains? (dream-resp-body (host-bl-wapp (host-bl-req "/my-first-post/"))) "<h1>My First Post</h1>")
|
||||
true)
|
||||
;; (JSON malformed-content tests removed with the JSON CRUD endpoints; the form
|
||||
;; ingest malformed-content checks above still cover write-time validation.)
|
||||
|
||||
;; -- view source (public) --
|
||||
(host-bl-test "view source -> 200"
|
||||
@@ -246,13 +203,9 @@
|
||||
(list (contains? (host/blog-related "my-first-post") "another-one")
|
||||
(contains? (host/blog-related "another-one") "my-first-post")))
|
||||
(list false false))
|
||||
(host-bl-test "delete cleans up related edges"
|
||||
(begin
|
||||
(host-bl-wapp (host-bl-send "POST" "/my-first-post/relate" "Bearer good"
|
||||
"application/x-www-form-urlencoded" "other=another-one"))
|
||||
(host-bl-wapp (host-bl-send "DELETE" "/posts/another-one" "Bearer good" "" ""))
|
||||
(contains? (host/blog-related "my-first-post") "another-one"))
|
||||
false)
|
||||
;; (The "delete cleans up related edges" test was removed with the JSON DELETE
|
||||
;; /posts endpoint; cascade edge cleanup returns when a browser delete route is
|
||||
;; added — see the FOLLOW-UP note in lib/host/blog.sx.)
|
||||
|
||||
;; -- relate picker (filterable candidate endpoint + glue + hint) --
|
||||
(host/blog-put! "alpha-post" "Alpha Post" "(p \"a\")" "published")
|
||||
|
||||
Reference in New Issue
Block a user