host: Phase 3 — relations WRITE cut-over (attach/detach-child), 132/132
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 17s

Migrate the container relations write actions onto lib/relations: POST
/internal/actions/attach-child + /detach-child dispatch to relations/relate
and relations/unrelate over the same "type:id" node model, behind the
auth+ACL pipeline (wrap-errors . require-auth . require-permission), mirroring
POST /feed. Closed-loop test: attach -> visible via get-children -> detach ->
gone; 401/403/400 guards. Ledger now models the full relations surface (7
endpoints): container reads+writes migrated, typed relate/unrelate/can-relate
proxied (registry+cardinality validation not in lib/relations). Off-Quart
coverage 45% -> 50%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 17:30:45 +00:00
parent 11aba081f4
commit bac80f6c0b
5 changed files with 200 additions and 25 deletions

View File

@@ -36,10 +36,10 @@ host — no `ocaml-on-sx` dependency.
## Status (rolling)
`bash lib/host/conformance.sh`**121/121** (7 suites: handler, middleware, sxtp,
`bash lib/host/conformance.sh`**132/132** (7 suites: handler, middleware, sxtp,
router, feed, relations, ledger). Phases 1 & 2 DONE; Phase 3 (strangler ledger)
underway — ledger module + `relations` READ cut-over landed (45% off Quart);
relations writes + golden harness next.
underway — ledger module + `relations` container cut-over landed (reads + guarded
writes, 50% off Quart). Golden-response harness vs live Quart next.
## Ground rules
@@ -116,13 +116,15 @@ lib/host/sxtp.sx subsystem APIs (feed/search/commerce/…
the live state: feed reads+writes migrated, `/health` native, the
internal-only `relations`/`likes` data+action endpoints proxied.
- [ ] golden-response harness vs the live Quart responses
- [~] cut over a whole domain (`relations`) as proof — READ side DONE
(`lib/host/relations.sx`): `GET /internal/data/get-children` + `/get-parents`
dispatch to `lib/relations` (`relations/children`/`parents`). Node model:
graph atom = symbol `"type:id"`, edge = relation-type; optional child/parent
`-type` param filters by `"type:"` prefix. Golden tests pin each endpoint to
`subsystem-call + envelope`. Ledger entries flipped to `:migrated`. WRITE side
(`relate`/`unrelate` actions, behind auth+ACL like POST /feed) next.
- [x] cut over a whole domain (`relations`) as proof — the CONTAINER relations are
fully on the host (`lib/host/relations.sx`): reads `GET .../get-children` +
`/get-parents` `relations/children`/`parents`; writes `POST
.../attach-child` + `/detach-child``relations/relate`/`unrelate`, behind
the auth+ACL pipeline (mirrors POST /feed). Node model: graph atom = symbol
`"type:id"`, edge = relation-type; `child`/`parent-type` params filter by
`"type:"` prefix. Closed-loop test: attach → visible via get-children →
detach → gone. The TYPED actions (`relate`/`unrelate`/`can-relate`) stay
proxied by design — registry + cardinality validation lib/relations lacks.
## Phase 4 — Dream framework layer (gated)
- [ ] gate: `ocaml-on-sx` Phases 15 + minimal stdlib green
@@ -196,6 +198,23 @@ lib/host/sxtp.sx subsystem APIs (feed/search/commerce/…
same as the feed reads. NEXT: relations WRITE actions (`relate`/`unrelate`)
behind the auth+ACL pipeline (mirroring POST /feed).
- **Phase 3 — relations WRITE cut-over (DONE, 132/132).** `lib/host/relations.sx`
gains `host/relations-attach`/`-detach` (`POST .../attach-child` + `/detach-child`)
and `host/relations-write-routes` — the write side of the container reads,
dispatching to `relations/relate`/`unrelate` over the same `"type:id"` node
model so an attach is immediately visible through `get-children`. Each runs
behind the host pipeline `wrap-errors ∘ require-auth ∘ require-permission`
(`"relate"`/`"unrelate"` on `"relations"`) — exactly the POST /feed stack. The
relations test suite proves the closed loop end-to-end: 401 unauth, 403 authed-
but-unpermitted (graph unchanged), 201 attach → child visible via the migrated
read → 200 detach → child gone; 400 on bad/short payloads. The ledger now models
the full relations surface (7 endpoints): container reads+writes `:migrated`,
typed `relate`/`unrelate`/`can-relate` `:proxied` (registry/cardinality
validation not in lib/relations). Off-Quart coverage 45% → **50%** (7/14).
`relations` is the first whole *coherent feature* (container relations) fully
off Quart. NEXT: golden-response harness vs live Quart, then survey the next
domain (blog/likes proxied — likes needs an SX subsystem first).
## Blockers
- **Live wiring to the native OCaml HTTP server** (Phase 3/4): the prod server in