• feat(#20): admin (bifrost inspection + admin-events stream) onto the wt adapter (slice-6)

    vh released this 2026-07-19 12:48:04 -07:00 | 49 commits to main since this release

    Slice-6 of the worldtree-sdk cutover: migrate the two admin routes off the
    hand-rolled paths onto the ratatoskr.wt adapter over client.admin.*, and delete
    the retired code. Both are web-only (the coverage-map's tui.py rows were stale —
    corrected to web/server.py).

    Adapter (wt.py): get_session_bifrost → client.admin.sessions.bifrost (open-world
    dict verbatim, any error → SessionApiFailed default); stream_admin_events →
    client.admin.stream_events, re-wrapping the SDK's AdminEvent → ratatoskr's at the
    boundary.

    Decisions (contract § slice-6 notes):

    • Admin auth moves from a per-call Authorization header override to the client's
      admin_auth (_wt_client(admin_key=…), extended this slice) — the SDK's admin.*
      routes use the provider, not a header.
    • AdminEvent re-wrap (chosen over yield-through): the SDK's admin_id(nan)/None-able
      type/data diverge from ratatoskr's id/type/data that the web filter reads;
      re-wrapping (nan→0, None→""/{}) degrades the open-world None/nan ONCE at the adapter
      and keeps the web endpoint + _admin_event_matches_web + the AdminEvent domain type
      unchanged (preserves the web surface). Rejected: yield SDK events + rewire the web
      filter (heavier churn, scattered hardening).
    • Admin-stream error map: a NON-200 open raises ApiError("admin_stream_failed")
      (NOT ConnectFailed) → SseConnectFailed; ConnectionDropped (connect-time OR
      mid-stream/resumable-EOF) → SseConnectionDropped. The web integration test caught the
      ApiError-not-ConnectFailed gotcha the unit fake couldn't.

    Web (web/server.py): both admin endpoints build the wt client with admin_key and call
    wt.*; the bifrost endpoint gains ConnectFailed→502 handling (cutover foot-gun); the
    admin-events endpoint closes the injected transport (INV-CUT-1), never the wt client.

    Deleted the hand-rolled sessions.get_session_bifrost + sse_client.stream_admin_events
    (+ orphaned httpx/httpx_sse/json/AsyncIterator imports); the ratatoskr AdminEvent
    dataclass stays in sse_client.py (re-wrap target, imported by wt + web) until slice-7.
    Retired test_sse_client.py entirely (its last test was the admin stream) and the
    test_sessions.py TestGetSessionBifrost; added the slice-6 adapter tests.

    LIVE SMOKE (:8081, readonly-admin key) — INV-CUT-5 / DEC-4 cleared: the web bifrost
    endpoint returned an admin-authed clean 404 envelope (auth + route + mapping proven);
    a real session.created admin event (id=32) re-wrapped cleanly on live wire (driven by
    a session-create, throwaway session cleaned up).

    Suite 490 green; ruff clean; mypy net-improved on web/server.py (16→12 pre-existing, no
    new). Patch bump 0.21.18 → 0.21.19 (the cutover MINOR is deferred to slice-7, DEC-6).

    Downloads