Skip to content

Flow Relay Status Summary

Use this status memo when deciding whether to finish the remaining relay runtime features first or proceed with a narrower relay gate around the current control-plane surface.

Status date: 2026-05-03.

The flow relay is no longer only a proposal. The canonical contract exists, the wap-flow relay command group is implemented, relay-owned generated state has a durable ledger, inspect relay and relay status expose aligned read-only projections, and relay serve exposes the same ledger through a foreground HTTP plus server-sent events boundary.

The implementation is still a control-plane relay, not a managed provider runtime. It records runtime metadata, provider profiles, session records, leases, control requests, event/result cursors, token digests, and quarantine records. It does not spawn provider subprocesses, keep a live Codex session pool, run heartbeat-driven renewal, execute tasks, or repair crashed provider sessions.

That means a relay gate can be implemented now if the gate is scoped to ledger/projection/transport readiness. A gate that claims live managed session pooling or provider execution readiness would be premature.

The relay owner is now canonical in flow/specs/flow-relay-contract.md. The contract defines a single-host, wap-flow-owned relay control plane with durable truth in flow/state/relay/relay-state.json and rebuildable runtime scratch under flow/tmp/relay/**.

The relay is explicitly non-authoritative for task, acceptance, PR, worktree, memory, and provider-health truth. It may render or route source references to those owners, but it must not mutate them or become a generic scheduler.

The CLI contract in flow/specs/flow-cli-contract.md is also aligned with the current command surface:

  • relay status and inspect relay are read-only.
  • relay bootstrap and relay shutdown record runtime metadata only.
  • relay profile register/list records provider runtime profiles.
  • relay session create/list records managed session ledger entries only.
  • relay borrow, relay release, and relay lease grant/release/renew/revoke manage explicit borrow leases.
  • relay control record records idempotent control requests.
  • relay event append/list and relay result append/list provide cursor-backed stream records.
  • relay quarantine session/clear and relay recover provide quarantine and recovery classification.
  • relay serve starts a foreground HTTP plus SSE relay over the existing ledger.

wap-flow relay status --json currently reports a healthy relay projection:

  • status: pass
  • projection: relay_generated_state_v1
  • relay_mode: ready
  • ledger_path: flow/state/relay/relay-state.json
  • state_present: true
  • tmp_present: true
  • ledger_present: true
  • durable artifacts: 1
  • tmp artifacts: 1
  • warnings: 0
  • profiles: 0
  • sessions: 0
  • active leases: 0
  • active quarantines: 0
  • control requests: 0
  • events: 0
  • results: 0

The current ledger contains only loopback runtime metadata:

  • endpoint: http://127.0.0.1:9876
  • status: ready
  • bootstrapped at: 2026-05-01T11:35:03Z
  • token id: none

There are no registered runtime profiles, managed sessions, leases, quarantines, control requests, events, or results in the current workspace ledger.

The Rust implementation is split cleanly:

  • flow/wap-flow/src/relay/state.rs: typed relay state model and domain transitions.
  • flow/wap-flow/src/relay/store.rs: ledger read/write, validation, and lock orchestration.
  • flow/wap-flow/src/relay/inspection.rs: generated-state inspection and freshness summary.
  • flow/wap-flow/src/relay_cli.rs: public wap-flow relay command group.
  • flow/wap-flow/src/relay_server.rs: HTTP plus SSE serving boundary.

The current model supports the important control-plane invariants:

  • durable relay truth is centralized in flow/state/relay/relay-state.json
  • relay mutations are serialized with flow/tmp/relay/relay-state.lock
  • matching duplicate control requests return duplicate without rewriting the ledger
  • shared-read leases may coexist
  • exclusive-write leases require no active readers or writer
  • waiting writers block new readers until readers release and the writer retries
  • lease renewal records last_renewed_at and expires_at
  • lease revocation records a reason and removes active occupancy
  • event and result streams use per-session monotonic sequence numbers
  • recovery classification distinguishes mutable lease blocks, quarantine repair, resumable sessions, and replacement-session starts
  • active quarantines keep sessions failed until cleared under safe conditions
  • token secrets are stored only as SHA-256 digests
  • trusted-LAN runtime endpoints must use private-network IPs and require bearer token authentication for serving

wap-flow relay serve exists as a foreground Axum server. It records served runtime metadata and exposes:

  • GET /health
  • GET /api/relay/status
  • GET /api/relay/profiles
  • GET /api/relay/sessions
  • GET /api/relay/events
  • GET /api/relay/results
  • GET /events

The server authenticates API and stream requests when the current runtime has a token id. It compares bearer-token digests against the persisted token digest. Loopback serving may run without a token; trusted-LAN serving requires one.

flow-relay-web/ is present as a separate, non-authoritative companion facade. The Rust gateway proxies relay status, profiles, sessions, events, and results, and intentionally returns not_configured for task projections because tasks are not exposed through relay serve yet. The React frontend is a polling JSON dashboard rather than an operational session-borrowing app.

Generated-state ownership is in place:

  • flow/state/relay/relay-state.json is the schema-backed singleton relay ledger.
  • other flow/state/relay/** descendants are reserved relay-owned durable artifacts and are not parsed as the relay ledger.
  • flow/tmp/relay/** is rebuildable relay scratch.
  • state inventory validates the singleton ledger and reports malformed relay state as owner-scoped warnings.
  • state cleanup --owner relay --apply removes eligible relay tmp cache material while preserving flow/tmp/relay/relay-state.lock.

This is enough foundation for a gate that checks relay-generated-state health.

The following capabilities are still future work or only partially shaped:

  • real provider subprocess ownership
  • live Codex pooled subprocess reuse
  • supervised one-borrow subprocess execution for Claude or Kimi
  • automatic heartbeat-driven lease renewal
  • automatic lease expiry handling
  • provider crash detection
  • provider-health integration
  • automatic session quarantine after crash, heartbeat loss, or tmp corruption
  • repair flows that rebuild or replace unsafe provider sessions
  • token rotation and revocation commands
  • companion-app mutating request paths for profile/session/borrow/release
  • task projections through relay serve
  • rich frontend controls for borrowing, releasing, streaming, or repairing sessions

The current relay recover command classifies what should happen; it does not perform repair.

A relay gate is viable now if it answers this question:

Is the relay control-plane projection healthy enough for operators and companion tooling to trust the current ledger state?

That gate could check:

  • relay status --json returns status=pass
  • inspect relay --json exposes the same projection fields
  • flow/state/relay/relay-state.json parses and validates when present
  • tmp relay cleanup preserves the relay lock
  • trusted-LAN serving is rejected without a token
  • persisted token records contain SHA-256 digests, not raw tokens
  • pooled profiles are Codex-only
  • event/result cursor order is valid
  • active quarantine/session-state invariants hold
  • HTTP read endpoints and SSE replay do not mutate flow/state

A relay gate should not yet require:

  • an active provider session pool
  • a running Codex subprocess
  • provider task execution through relay
  • heartbeat renewal
  • automatic crash repair
  • frontend borrowing workflows
  • task projection through the relay server

The practical next step is therefore to implement a narrow relay gate as a readiness and safety gate for relay-owned generated state and the HTTP/SSE projection. Treat runtime pooling as a follow-up feature track with its own acceptance criteria.

  1. Implement a narrow relay gate around the stable control-plane invariants.
  2. Add a small operator-facing report that names the failed relay invariant and the owner-scoped repair command or next diagnostic.
  3. Decide separately whether token rotation/revocation belongs before or after live provider runtime work. It is security-relevant, but not required for a loopback-only readiness gate.
  4. Finish live runtime design before claiming pooled-session readiness: provider subprocess lifecycle, heartbeat renewal, crash quarantine, repair, and safe idle re-borrow cleanup.
  5. Expand flow-relay-web only after the relay server has modeled mutating request paths; until then the facade should remain read-oriented.

Commands run on 2026-05-03:

Terminal window
cargo run -q --manifest-path flow/Cargo.toml -p wap-flow -- relay status --json
cargo test --manifest-path flow/Cargo.toml -p wap-flow --test local_cli local_relay
cargo check --manifest-path flow-relay-web/server/Cargo.toml

Results:

  • relay status: pass
  • relay-focused local CLI tests: 13 passed, 0 failed
  • flow-relay-web server check: passed

Frontend checks were not run because flow-relay-web/frontend/node_modules is not installed in this workspace.

Primary files reviewed:

  • flow/specs/flow-relay-contract.md
  • flow/specs/flow-cli-contract.md
  • flow/specs/flow-inspection-contract.md
  • flow/specs/flow-generated-state-contract.md
  • flow/specs/flow-state-placement-contract.md
  • flow/playbooks/managed-cli-relay.md
  • flow/candidates/fc-2026-029--managed-cli-relay-and-session-pooling.md
  • flow/wap-flow/src/relay_cli.rs
  • flow/wap-flow/src/relay/state.rs
  • flow/wap-flow/src/relay/store.rs
  • flow/wap-flow/src/relay/inspection.rs
  • flow/wap-flow/src/relay_server.rs
  • flow/wap-flow/tests/local_cli.rs
  • flow-relay-web/README.md
  • flow-relay-web/AGENTS.md
  • flow-relay-web/server/src/main.rs
  • flow-relay-web/frontend/src/main.tsx