;; sx-host: Universal Platform Primitives
;; Five irreducible IO operations beneath every host.
;; Everything above — HTTP, SQL, TLS, protocols — is SX.

(defcomp ()
  (~docs/page :title "sx-host: Universal Platform Primitives"

    (p (~tw :tokens "text-stone-500 text-sm italic mb-8")
      "Every SX host — browser, server, CLI, embedded — is the same five IO primitives. "
      "Everything above that floor is SX evaluating SX. HTTP is an SX library. "
      "SQL is an SX library. TLS is an SX library. The host only touches raw bytes.")

    ;; =====================================================================
    ;; The Five Primitives
    ;; =====================================================================

    (~docs/section :title "The Five Primitives" :id "primitives"

      (table (~tw :tokens "w-full mb-6 text-sm")
        (thead
          (tr (th (~tw :tokens "text-left p-2") "Primitive") (th (~tw :tokens "text-left p-2") "Signature") (th (~tw :tokens "text-left p-2") "What")))
        (tbody
          (tr (td (~tw :tokens "p-2 font-mono text-violet-700") "read") (td (~tw :tokens "p-2 font-mono text-xs") "(read channel) → bytes") (td (~tw :tokens "p-2") "Bytes in. From a socket, a file handle, stdin, a sensor."))
          (tr (td (~tw :tokens "p-2 font-mono text-violet-700") "write") (td (~tw :tokens "p-2 font-mono text-xs") "(write channel bytes) → n") (td (~tw :tokens "p-2") "Bytes out. To a socket, a file handle, stdout, an actuator."))
          (tr (td (~tw :tokens "p-2 font-mono text-violet-700") "store") (td (~tw :tokens "p-2 font-mono text-xs") "(store key bytes) → ok") (td (~tw :tokens "p-2") "Persist bytes by key. Filesystem, KV store, database row, IPFS block."))
          (tr (td (~tw :tokens "p-2 font-mono text-violet-700") "retrieve") (td (~tw :tokens "p-2 font-mono text-xs") "(retrieve key) → bytes | nil") (td (~tw :tokens "p-2") "Get bytes by key. Same backends."))
          (tr (td (~tw :tokens "p-2 font-mono text-violet-700") "hash") (td (~tw :tokens "p-2 font-mono text-xs") "(hash bytes) → digest") (td (~tw :tokens "p-2") "Content-address bytes. SHA-256. The trust anchor for everything."))))

      (p "These are irreducible. You cannot implement " (code "read") " in terms of the others. "
         "You cannot implement " (code "store") " without the host. You cannot implement "
         (code "hash") " without CPU instructions for the algorithm. Everything else — "
         "HTTP, SQL, TLS, SMTP, ActivityPub, the Postgres wire protocol — is bytes "
         "interpreted by SX logic built on these five.")

      (~docs/code :src (highlight
        ";; The platform interface — total\n(platform\n  (read    channel → bytes)\n  (write   channel bytes → n)\n  (store   key bytes → ok)\n  (retrieve key → bytes | nil)\n  (hash    bytes → digest))\n\n;; Plus channel management\n(open    address opts → channel)    ;; obtain a channel\n(close   channel → ok)             ;; release a channel\n(listen  address handler → server)  ;; accept incoming channels"
        "lisp"))

      (p (code "open") ", " (code "close") ", and " (code "listen") " manage channels — "
         "they're the lifecycle around " (code "read") "/" (code "write") ". "
         "Whether a channel is a TCP socket, a UDP port, a serial connection, "
         "or a pipe to a subprocess is determined by the address. "
         "The SX layer doesn't know or care."))

    ;; =====================================================================
    ;; Everything Above Is SX
    ;; =====================================================================

    (~docs/section :title "Everything Above Is SX" :id "layers"

      (p "Each protocol is an SX library that reads and writes bytes through channels.")

      (table (~tw :tokens "w-full mb-6 text-sm")
        (thead
          (tr (th (~tw :tokens "text-left p-2") "What") (th (~tw :tokens "text-left p-2") "Primitives Used") (th (~tw :tokens "text-left p-2") "SX Library")))
        (tbody
          (tr (td (~tw :tokens "p-2") "TCP connection") (td (~tw :tokens "p-2 font-mono text-xs") "open, read, write, close") (td (~tw :tokens "p-2 font-mono text-xs") "net/tcp.sx"))
          (tr (td (~tw :tokens "p-2") "TLS handshake") (td (~tw :tokens "p-2 font-mono text-xs") "read, write, hash") (td (~tw :tokens "p-2 font-mono text-xs") "net/tls.sx"))
          (tr (td (~tw :tokens "p-2") "HTTP server") (td (~tw :tokens "p-2 font-mono text-xs") "listen, read, write") (td (~tw :tokens "p-2 font-mono text-xs") "net/http.sx"))
          (tr (td (~tw :tokens "p-2") "HTTP client") (td (~tw :tokens "p-2 font-mono text-xs") "open, read, write") (td (~tw :tokens "p-2 font-mono text-xs") "net/http-client.sx"))
          (tr (td (~tw :tokens "p-2") "Postgres client") (td (~tw :tokens "p-2 font-mono text-xs") "open, read, write") (td (~tw :tokens "p-2 font-mono text-xs") "db/postgres.sx"))
          (tr (td (~tw :tokens "p-2") "Redis client") (td (~tw :tokens "p-2 font-mono text-xs") "open, read, write") (td (~tw :tokens "p-2 font-mono text-xs") "db/redis.sx"))
          (tr (td (~tw :tokens "p-2") "IPFS content store") (td (~tw :tokens "p-2 font-mono text-xs") "store, retrieve, hash") (td (~tw :tokens "p-2 font-mono text-xs") "net/ipfs.sx"))
          (tr (td (~tw :tokens "p-2") "File system") (td (~tw :tokens "p-2 font-mono text-xs") "store, retrieve") (td (~tw :tokens "p-2 font-mono text-xs") "io/fs.sx"))
          (tr (td (~tw :tokens "p-2") "DNS resolver") (td (~tw :tokens "p-2 font-mono text-xs") "open, read, write") (td (~tw :tokens "p-2 font-mono text-xs") "net/dns.sx"))
          (tr (td (~tw :tokens "p-2") "WebSocket") (td (~tw :tokens "p-2 font-mono text-xs") "read, write (over HTTP upgrade)") (td (~tw :tokens "p-2 font-mono text-xs") "net/websocket.sx"))
          (tr (td (~tw :tokens "p-2") "SMTP") (td (~tw :tokens "p-2 font-mono text-xs") "open, read, write") (td (~tw :tokens "p-2 font-mono text-xs") "net/smtp.sx"))
          (tr (td (~tw :tokens "p-2") "ActivityPub") (td (~tw :tokens "p-2 font-mono text-xs") "HTTP + hash (signatures)") (td (~tw :tokens "p-2 font-mono text-xs") "net/activitypub.sx"))
          (tr (td (~tw :tokens "p-2") "sx-sync protocol") (td (~tw :tokens "p-2 font-mono text-xs") "read, write (over WS/WebRTC)") (td (~tw :tokens "p-2 font-mono text-xs") "net/sx-sync.sx"))))

      (~docs/code :src (highlight
        ";; HTTP server — pure SX on the five primitives\n(define http-server\n  (fn (address handler)\n    (listen address (fn (channel)\n      (let ((request-bytes (read channel))\n            (request (http-parse-request request-bytes))\n            (response (handler request))\n            (response-bytes (http-serialize-response response)))\n        (write channel response-bytes)\n        (close channel))))))\n\n;; Your app — SX all the way down\n(http-server \":8080\" (fn (req)\n  (let ((page (route (get req :path))))\n    (http-response 200 (render-to-html page)))))"
        "lisp"))

      (p "The HTTP library parses request bytes into an SX dict, "
         "calls your handler (which is SX), serializes the response dict back to bytes. "
         "The host never sees HTTP. It sees " (code "listen") ", " (code "read") ", "
         (code "write") ", " (code "close") ". Raw bytes in, raw bytes out."))

    ;; =====================================================================
    ;; Host Implementations
    ;; =====================================================================

    (~docs/section :title "Host Implementations" :id "hosts"

      (p "Each host implements the same 5+3 primitives. The SX layer is identical across all of them.")

      (table (~tw :tokens "w-full mb-6 text-sm")
        (thead
          (tr (th (~tw :tokens "text-left p-2") "Host") (th (~tw :tokens "text-left p-2") "read/write") (th (~tw :tokens "text-left p-2") "store/retrieve") (th (~tw :tokens "text-left p-2") "hash") (th (~tw :tokens "text-left p-2") "Target")))
        (tbody
          (tr (td (~tw :tokens "p-2 font-medium") "OCaml native")
            (td (~tw :tokens "p-2 text-xs") "Unix.read/write")
            (td (~tw :tokens "p-2 text-xs") "file IO / mmap")
            (td (~tw :tokens "p-2 text-xs") "Digestif SHA256")
            (td (~tw :tokens "p-2 text-xs") "Production servers"))
          (tr (td (~tw :tokens "p-2 font-medium") "Rust native")
            (td (~tw :tokens "p-2 text-xs") "tokio async IO")
            (td (~tw :tokens "p-2 text-xs") "sled / filesystem")
            (td (~tw :tokens "p-2 text-xs") "ring SHA256")
            (td (~tw :tokens "p-2 text-xs") "Edge, embedded"))
          (tr (td (~tw :tokens "p-2 font-medium") "Node.js")
            (td (~tw :tokens "p-2 text-xs") "net.Socket")
            (td (~tw :tokens "p-2 text-xs") "fs / LevelDB")
            (td (~tw :tokens "p-2 text-xs") "crypto.createHash")
            (td (~tw :tokens "p-2 text-xs") "Quick deploy, Lambda"))
          (tr (td (~tw :tokens "p-2 font-medium") "Python/Quart")
            (td (~tw :tokens "p-2 text-xs") "asyncio streams")
            (td (~tw :tokens "p-2 text-xs") "aiofiles / SQLAlchemy")
            (td (~tw :tokens "p-2 text-xs") "hashlib")
            (td (~tw :tokens "p-2 text-xs") "Current, prototyping"))
          (tr (td (~tw :tokens "p-2 font-medium") "Browser")
            (td (~tw :tokens "p-2 text-xs") "WebSocket / WebRTC")
            (td (~tw :tokens "p-2 text-xs") "IndexedDB / Cache API")
            (td (~tw :tokens "p-2 text-xs") "SubtleCrypto")
            (td (~tw :tokens "p-2 text-xs") "Client nodes"))
          (tr (td (~tw :tokens "p-2 font-medium") "WASM")
            (td (~tw :tokens "p-2 text-xs") "imported from host")
            (td (~tw :tokens "p-2 text-xs") "imported from host")
            (td (~tw :tokens "p-2 text-xs") "compiled in")
            (td (~tw :tokens "p-2 text-xs") "Universal, portable"))
          (tr (td (~tw :tokens "p-2 font-medium") "Embedded (Rust)")
            (td (~tw :tokens "p-2 text-xs") "UART / SPI / I2C")
            (td (~tw :tokens "p-2 text-xs") "flash / EEPROM")
            (td (~tw :tokens "p-2 text-xs") "hardware SHA")
            (td (~tw :tokens "p-2 text-xs") "IoT, sensors"))))

      (p "An SX app published to sx-pub runs on any of these hosts unchanged. "
         "The CIDs are the same. The evaluation is deterministic. "
         "The host is an implementation detail."))

    ;; =====================================================================
    ;; The Layered Stack
    ;; =====================================================================

    (~docs/section :title "The Layered Stack" :id "stack"

      (~docs/code :src (highlight
        "┌─────────────────────────────────────────────┐\n│  Your App                                   │\n│  defpage, defhandler, defquery, defaction    │\n│  defcomp, defisland, defprotocol             │\n├─────────────────────────────────────────────┤\n│  Protocol Libraries (SX)                    │\n│  net/http.sx  db/postgres.sx  net/tls.sx    │\n│  net/websocket.sx  net/ipfs.sx  io/fs.sx    │\n├─────────────────────────────────────────────┤\n│  Core Libraries (SX)                        │\n│  signals.sx  evaluator.sx  render.sx        │\n│  parser.sx   router.sx     content.sx       │\n├─────────────────────────────────────────────┤\n│  Platform Primitives (5+3)                  │\n│  read  write  store  retrieve  hash         │\n│  open  close  listen                        │\n├─────────────────────────────────────────────┤\n│  Host (native code)                         │\n│  OCaml / Rust / Node / Python / Browser     │\n└─────────────────────────────────────────────┘"
        "text"))

      (p "Every layer above the platform primitives is SX, published to sx-pub, "
         "content-addressed by CID. The host is the only part that varies per deployment target. "
         "The host is also the only part that isn't SX — it's native code for the target platform.")

      (p "This is the same architecture the browser already has. "
         "The browser host provides DOM primitives (" (code "host-call, host-get, host-set!") " etc). "
         "Everything above — signals, rendering, islands, routing — is SX. "
         "The server host provides IO primitives (" (code "read, write, store, retrieve, hash") "). "
         "Everything above — HTTP, SQL, TLS, your app — is SX. Same pattern, different primitives."))

    ;; =====================================================================
    ;; Bootstrap From sx-pub
    ;; =====================================================================

    (~docs/section :title "Bootstrap From sx-pub" :id "bootstrap"

      (p "A new server starts with the host binary and a seed peer. Everything else comes from the network.")

      (~docs/code :src (highlight
        ";; Server bootstrap sequence\n;;\n;; 1. Host binary starts (OCaml/Rust/Node — compiled, ~5MB)\n;;    Provides: read, write, store, retrieve, hash, open, close, listen\n;;\n;; 2. Fetch spec CIDs from seed peer\n;;    (open \"tcp://seed.sx-web.org:4433\")\n;;    (write channel (serialize (want spec-manifest-cid)))\n;;    (read channel) → spec source files\n;;    (store spec-cid spec-bytes) for each spec\n;;\n;; 3. Bootstrap the evaluator\n;;    evaluator.sx + parser.sx + primitives.sx → working SX runtime\n;;    All verified by CID before evaluation\n;;\n;; 4. Fetch protocol libraries\n;;    net/http.sx, net/tls.sx, db/postgres.sx\n;;    Resolved from seed peer or IPFS\n;;\n;; 5. Fetch app definition\n;;    defpage, defhandler, defquery, defaction, defcomp\n;;    Your app is a set of CIDs\n;;\n;; 6. Start serving\n;;    (http-server \":443\" app-handler)\n;;    The host calls listen → SX handles everything above"
        "text"))

      (p "The host binary is the only thing installed locally. "
         "The evaluator, the protocol libraries, and the app all come from the network. "
         "All verified by CID. If the spec at that CID evaluates correctly, the system works. "
         "The bootstrap IS the proof."))

    ;; =====================================================================
    ;; Migration Path
    ;; =====================================================================

    (~docs/section :title "Migration Path" :id "migration"

      (p "The current architecture migrates incrementally. Each step is independently useful.")

      (~docs/subsection :title "Step 1: SX Page Helpers"
        (p "Move Python page helpers to SX. The IO bridge already supports "
           (code "(service ...)") " calls from SX. Page helpers are just compositions of service calls.")

        (~docs/code :src (highlight
          ";; Current Python:\n;; async def post_detail_data(slug):\n;;     post = await fetch_data(\"blog\", \"post-by-slug\", {\"slug\": slug})\n;;     related = await fetch_data(\"blog\", \"related-posts\", {\"id\": post[\"id\"]})\n;;     return {\"post\": post, \"related\": related}\n\n;; SX equivalent — works today via IO bridge:\n(defhelper post-detail-data (slug)\n  (let ((post (service \"blog\" \"post-by-slug\" :slug slug))\n        (related (service \"blog\" \"related-posts\" :id (get post \"id\"))))\n    (dict :post post :related related)))"
          "lisp"))

        (p "New form: " (code "defhelper") ". Registers an async data function callable from "
           (code "defpage :data") ". Implementation: evaluate SX via OCaml bridge, "
           "IO requests dispatched through existing bridge. ~50 LOC spec change."))

      (~docs/subsection :title "Step 2: SX Config"
        (p "Replace YAML config with SX. Loaded at startup, frozen after boot.")

        (~docs/code :src (highlight
          ";; app-config.sx — replaces app-config.yaml\n(defconfig app\n  {:domain \"rose-ash.com\"\n   :services {:blog {:port 8001 :url \"https://blog.rose-ash.com\"}\n              :cart {:port 8003 :url \"https://cart.rose-ash.com\"}}\n   :features {:ipfs true :anchoring true}\n   :secrets (env-get \"SECRET_KEY\")})"
          "lisp"))

        (p (code "env-get") " reads environment variables — secrets never stored in SX. "
           "Config is SX but secrets are platform."))

      (~docs/subsection :title "Step 3: Protocol Libraries"
        (p "Implement HTTP, Postgres wire protocol, Redis protocol as SX libraries "
           "on the five primitives. Replaces Python framework dependencies.")

        (p "This is the big step. Each protocol library is substantial:")
        (ul (~tw :tokens "list-disc pl-6 mb-4 space-y-1")
          (li (code "net/http.sx") " — request/response parsing, chunked encoding, keep-alive (~800 LOC)")
          (li (code "net/tls.sx") " — TLS 1.3 handshake, certificate verification (~1200 LOC)")
          (li (code "db/postgres.sx") " — wire protocol, query serialization, result parsing (~600 LOC)")
          (li (code "db/redis.sx") " — RESP protocol, command serialization (~200 LOC)"))

        (p "Each library is independently publishable to sx-pub. "
           "Any SX server can use them. They're shared infrastructure for the whole network."))

      (~docs/subsection :title "Step 4: Host Binary"
        (p "Minimal native binary: SX evaluator + 5+3 IO primitives. Nothing else.")

        (ul (~tw :tokens "list-disc pl-6 mb-4 space-y-1")
          (li "OCaml: CEK machine + Unix IO (~2000 LOC, single binary)")
          (li "Rust: compiled evaluator + tokio IO (~3000 LOC, single binary)")
          (li "Both: no Python, no Quart, no SQLAlchemy, no pip, no virtualenv"))

        (p "The host binary is the only thing you install. "
           "Everything above it — HTTP, TLS, SQL, your app — downloads from sx-pub on first boot."))

      (~docs/subsection :title "Step 5: Self-Hosting"
        (p "sx-pub itself runs on this stack. The federation infrastructure is SX. "
           "The IPFS client is SX. The anchoring is SX. "
           "A new node bootstraps from the network, then helps serve the network. "
           "Fully self-hosting, fully federated, fully content-addressed.")))

    ;; =====================================================================
    ;; Non-Web Hosts
    ;; =====================================================================

    (~docs/section :title "Non-Web Hosts" :id "non-web"

      (p "The five primitives are not web-specific. They're IO-specific. "
         "Any device that can read bytes, write bytes, and store bytes can host SX.")

      (table (~tw :tokens "w-full mb-6 text-sm")
        (thead
          (tr (th (~tw :tokens "text-left p-2") "Host") (th (~tw :tokens "text-left p-2") "Channels") (th (~tw :tokens "text-left p-2") "Storage") (th (~tw :tokens "text-left p-2") "Use Case")))
        (tbody
          (tr (td (~tw :tokens "p-2 font-medium") "CLI")
            (td (~tw :tokens "p-2 text-xs") "stdin/stdout/stderr, files, pipes")
            (td (~tw :tokens "p-2 text-xs") "filesystem")
            (td (~tw :tokens "p-2 text-xs") "Build tools, scripts, automation"))
          (tr (td (~tw :tokens "p-2 font-medium") "Desktop (Tauri)")
            (td (~tw :tokens "p-2 text-xs") "IPC to native windows, file dialogs")
            (td (~tw :tokens "p-2 text-xs") "app data dir")
            (td (~tw :tokens "p-2 text-xs") "Native apps with SX UI"))
          (tr (td (~tw :tokens "p-2 font-medium") "Mobile")
            (td (~tw :tokens "p-2 text-xs") "network + sensor APIs")
            (td (~tw :tokens "p-2 text-xs") "SQLite / app storage")
            (td (~tw :tokens "p-2 text-xs") "Apps, games, tools"))
          (tr (td (~tw :tokens "p-2 font-medium") "Serverless")
            (td (~tw :tokens "p-2 text-xs") "event payload in, response out")
            (td (~tw :tokens "p-2 text-xs") "KV store / S3")
            (td (~tw :tokens "p-2 text-xs") "Lambda, Cloudflare Workers"))
          (tr (td (~tw :tokens "p-2 font-medium") "Game engine")
            (td (~tw :tokens "p-2 text-xs") "GPU commands, audio buffers")
            (td (~tw :tokens "p-2 text-xs") "asset cache")
            (td (~tw :tokens "p-2 text-xs") "SX game logic + native rendering"))
          (tr (td (~tw :tokens "p-2 font-medium") "Embedded")
            (td (~tw :tokens "p-2 text-xs") "UART, SPI, I2C, GPIO")
            (td (~tw :tokens "p-2 text-xs") "flash / EEPROM")
            (td (~tw :tokens "p-2 text-xs") "IoT, sensors, controllers"))))

      (p "Same five primitives. Same SX spec. Same content-addressed components from sx-pub. "
         "A component that works in the browser works on a server works on a Raspberry Pi — "
         "as long as it only uses the five primitives and the SX standard library. "
         "The host provides the bytes. SX provides the meaning."))

    ;; =====================================================================
    ;; Relationship to Existing Plans
    ;; =====================================================================

    (~docs/section :title "Relationship to Existing Plans" :id "relationships"

      (table (~tw :tokens "w-full mb-6 text-sm")
        (thead
          (tr (th (~tw :tokens "text-left p-2") "Plan") (th (~tw :tokens "text-left p-2") "Relationship")))
        (tbody
          (tr (td (~tw :tokens "p-2 font-medium") "sx-web") (td (~tw :tokens "p-2") "sx-host defines what a node IS. sx-web defines how nodes CONNECT."))
          (tr (td (~tw :tokens "p-2 font-medium") "Mother Language") (td (~tw :tokens "p-2") "The evaluator that runs on each host. sx-host defines the interface it evaluates against."))
          (tr (td (~tw :tokens "p-2 font-medium") "Rust/WASM Host") (td (~tw :tokens "p-2") "One implementation of the five primitives. Compiles to native or WASM."))
          (tr (td (~tw :tokens "p-2 font-medium") "Isolated Evaluator") (td (~tw :tokens "p-2") "Core/platform split maps directly: core = evaluator, platform = five primitives."))
          (tr (td (~tw :tokens "p-2 font-medium") "sx-pub") (td (~tw :tokens "p-2") "Where the SX protocol libraries and app definitions live. Hosts fetch from sx-pub to bootstrap."))
          (tr (td (~tw :tokens "p-2 font-medium") "Runtime Slicing") (td (~tw :tokens "p-2") "Slicing determines which SX libraries a host needs. Minimal host = evaluator + primitives. Full host = all protocol libraries.")))))))
