Files
rose-ash/plans/host-on-sx.md
giles ff537bfba2 plans: six subsystem outline plans for the SX rewrite (store, commerce, identity, content, events, host)
Gap analysis from the five-subsystem set (acl/feed/flow/mod/search):
- store-on-sx: event-sourcing foundation the others fake with in-memory lists (build first)
- commerce-on-sx: catalog/cart/pricing/orders on miniKanren (+ store + flow)
- identity-on-sx: OAuth2/sessions/membership on Erlang (the core acl assumes)
- content-on-sx: documents/blocks/CRDT on Smalltalk
- events-on-sx: calendar/ticketing on Datalog + flow-driven delivery
- host-on-sx: the web boundary — off Quart onto native server+SXTP now, dream-on-sx next

All DRAFT outlines; substrate choices proposed, not final.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:39:29 +00:00

5.1 KiB
Raw Blame History

host-on-sx: The SX web host — off Quart, onto the kernel (Dream-bound)

DRAFT outline. The integration boundary that turns the subsystem libraries into running services, and the strangler path off Python/Quart. This is the dependency hub — it imports every subsystem. Decision recorded below: native server + SXTP now, dream-on-sx framework layer next, Python only at the external-integration edges.

The subsystems (feed, search, acl, mod, flow, commerce, identity, content, events) are libraries. Something has to receive an HTTP request, route it, call the right subsystem, and serialize the response. Today that's Python/Quart — the one large non-SX component in the stack: separate runtime, deploy, and failure mode. The goal is to move the web/host/domain layer onto the SX substrate and retire Quart, incrementally (strangler-fig), never big-bang.

This is already underway: a native OCaml HTTP server is live in prod on sx.rose-ash.com (~3ms cached, ~323 req/s, ~2MB RSS), defhandler/defpage exist, and a partial SXTP protocol is specced. That is the unblocked near-term host — no ocaml-on-sx dependency.

Two layers, two timelines

  1. Now (unblocked): native server + SXTP adapter + SX handlers. Route rose-ash endpoints onto the SX host one at a time. Each migrated endpoint is an SX handler dispatching to a subsystem; Quart proxies the rest until cut over.
  2. Next: dream-on-sx as the framework layer. Dream gives Quart-grade ergonomics — typed routing, middleware stacks, sessions, CSRF. It is gated on ocaml-on-sx Phases 15 + minimal stdlib. This plan is the concrete target user that un-parks dream-on-sx (see plans/dream-on-sx.md): "the subsystems need an HTTP front door" is the real feature pulling Dream. Until then, do not block migration on Dream — the native server is sufficient.
  3. Always: Python only at the edges. External integrations — SumUp payments, Ghost CMS, ActivityPub crypto, IPFS/Kubo — ride Python libraries today. They stay as thin injected adapters (Python/FFI) behind subsystem interfaces until native replacements exist. "Drop Quart" ≠ "drop every line of Python."

Status (rolling)

bash lib/host/conformance.sh0/0 (not yet started)

Ground rules

  • Scope: lib/host/** and plans/host-on-sx.md. May import every subsystem
    • the kernel's server/SXTP surface. Do not edit spec/, hosts/, shared/, or subsystem internals — wire to their public APIs only. Host-primitive / server changes belong in hosts/ (out of scope) → Blockers.
  • Architecture: a route maps (method, path) → handler; a handler is an SX fn request -> response that calls subsystem APIs; middleware is composed handlers (auth via identity, permission via acl, mute via subsystem prefs). SXTP is the wire format between host and subsystem-as-service.
  • Migration discipline: each endpoint moved must be behavior-equivalent to its Quart original (golden-response test before flip). Keep a migration ledger.
  • Commits: one feature per commit. Progress log + tick boxes.

Architecture sketch

HTTP request                            HTTP response
        │                                       ▲
        ▼                                       │
native OCaml http server (prod)  ──────►  lib/host/router.sx
   (hosts/ — out of scope)                  — (method,path) → handler
        │                                       ▲
        ▼                                       │
lib/host/middleware.sx                  lib/host/handler.sx
  — auth(identity) ∘ acl ∘ mute ∘ ...     — request → subsystem call → response
        │                                       ▲
        ▼                                       │
lib/host/sxtp.sx                        subsystem APIs (feed/search/commerce/…)
  — wire format, host↔service             — called via public interfaces
        │
        └── external edges: SumUp / Ghost / AP / IPFS  → injected Python/FFI adapters

Phase 1 — Router + handler + one real endpoint

  • router.sx — route table, (method,path) match
  • handler.sx — request/response model, subsystem dispatch
  • migrate ONE read endpoint (e.g. a feed timeline) end-to-end, golden test
  • conformance.sh + scoreboard

Phase 2 — Middleware + SXTP

  • middleware.sx — composable auth/acl/mute/error layers
  • sxtp.sx — host↔subsystem wire format (align with existing spec)
  • migrate a write endpoint (auth + permission + action)

Phase 3 — Strangler migration ledger

  • enumerate Quart endpoints; track migrated vs proxied
  • golden-response harness vs the live Quart responses
  • cut over a whole domain (smallest: likes or relations) as proof

Phase 4 — Dream framework layer (gated)

  • gate: ocaml-on-sx Phases 15 + minimal stdlib green
  • adopt dream-on-sx routing/middleware/session ergonomics over the same handlers
  • re-home external adapters as native where replacements land

Progress log

(loop fills this in)

Blockers

(loop fills this in)