Orchestrata Ultimate / Specs / 014-websocket-gateway
014-websocket-gateway: WebSocket Gateway
The WebSocket Gateway is the real-time control plane for Orchestrata. It exposes a bidirectional WebSocket server that allows external clients (web dashboards, CLI tools, mobile apps, external integrations) to observe and control the orchestration system in real-time. Clients can subscribe to CXP traffic, monitor Volk status, inspect governance decisions, query session state, and issue commands to the kernel — all through a structured RPC protocol over WebSocket.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/014-websocket-gateway/ |
| Status line in the spec | Implemented |
| Requirement IDs defined | 207 |
With a @traces citation in src/ |
104 (50.2%) |
With a @traces citation in tests/ |
25 (12.1%) |
| Tracked files | 7 |
| RTM page | 014-websocket-gateway |
Reading this spec
The WebSocket Gateway is the real-time control plane of Orchestrata. It exposes a bidirectional WebSocket server so that external clients (web dashboards, CLI tools, mobile apps and integrations) can observe and control the orchestration system as it runs. Before it, the kernel, postman and orchestrator communicated only internally and were invisible from outside, and there was no way to start sessions or dispatch CXP packets remotely.
The scope is ten user stories: real-time CXP traffic observation, Volk status monitoring, a governance decision stream, session state inspection, remote command execution and gateway authentication (priority 1), then client presence and heartbeat, event replay and history, a metrics and health endpoint, and live knowledge graph queries (priority 2). Requirement IDs use the REQ-014- prefix.
The key decisions are an IGatewayServer interface registered in the DI container as ComponentType.GATEWAY; a server built on the websockets library on a configurable port (default 18790); token-based authentication with configurable strategies; JSON-RPC 2.0 for requests, responses and server-push notifications; a publish and subscribe model for event streams; an RPCDispatcher that routes calls to registered handlers with PAM++ authorization; gateway sessions that track clients with heartbeat and presence; and an audit trail of all gateway operations in Neo4j.
In the code, the package is orchestrata_ultimate/gateway. The largest tracers are orchestrata_ultimate/gateway/server, orchestrata_ultimate/gateway/handlers/session, orchestrata_ultimate/gateway/auth, orchestrata_ultimate/gateway/metrics and orchestrata_ultimate/gateway/handlers/volk. The per-requirement view is on the RTM page.
The spec's status line reads Implemented. It tracks 7 files and defines 207 requirement IDs. The full text follows below.
Measured coverage is 104 of 207 requirements cited by at least one @traces in src/ (50.2%), spread over 34 modules; the module citing the most of them is orchestrata_ultimate/gateway/server (20 requirements). In tests/, 25 requirements are cited by a test-side @traces.
Coverage gaps: 103 requirements have no citing symbol. The largest untraced groups are REQ-014-* (103). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (25 against 104).
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-014-001 |
no | Client subscribes to CXP traffic via cxp.subscribe RPC method |
2 |
REQ-014-002 |
no | Server pushes CXP packets as they flow through the kernel | 2 |
REQ-014-003 |
no | Subscription supports filtering by volk_id (TO or FROM) | 1 |
REQ-014-004 |
no | Subscription supports filtering by thread_id | none |
REQ-014-005 |
no | Subscription supports filtering by subject pattern (glob match) | 1 |
REQ-014-006 |
no | Subscription supports filtering by delivery_status | none |
REQ-014-007 |
no | Multiple filters combine with AND semantics | 2 |
REQ-014-008 |
no | Client unsubscribes via cxp.unsubscribe with subscription_id |
2 |
REQ-014-009 |
no | Packet payloads optionally truncated (configurable max_payload_size) | none |
REQ-014-010 |
no | Subscription confirmation includes subscription_id and active filter summary | none |
REQ-014-011 |
no | Client queries CXP packet status via cxp.status with thread_id |
2 |
REQ-014-012 |
no | Status response includes delivery_status, work_status, timestamps | none |
REQ-014-013 |
no | Status query returns history of status transitions | none |
REQ-014-014 |
no | Status query handles unknown thread_id with clear error | none |
REQ-014-015 |
no | Status query respects PAM++ authorization | none |
REQ-014-016 |
no | Client calls volk.list to get all registered Volks |
3 |
REQ-014-017 |
no | Each Volk entry includes: alias, capabilities, health, active_tasks, last_activity | 2 |
REQ-014-018 |
no | Client calls volk.get with alias for detailed Volk information |
2 |
REQ-014-019 |
no | Detailed info includes: registration_time, protocols, resource_usage, session_id | none |
REQ-014-020 |
no | Volk list supports pagination (offset, limit) | none |
REQ-014-021 |
no | Client subscribes to volk.lifecycle events |
1 |
REQ-014-022 |
no | Events include: registered, deregistered, health_changed, task_started, task_completed | none |
REQ-014-023 |
no | Each event includes volk_alias, event_type, timestamp, details | 1 |
REQ-014-024 |
no | Status updates pushed within 500ms of state change | none |
REQ-014-025 |
no | Subscription supports filtering by volk_alias | none |
REQ-014-026 |
no | Client registers new Volk via volk.register (admin scope required) |
4 |
REQ-014-027 |
no | Registration validates alias uniqueness and capability schema | none |
REQ-014-028 |
no | Client deregisters Volk via volk.deregister (admin scope required) |
4 |
REQ-014-029 |
no | Deregistration handles in-flight messages gracefully | none |
REQ-014-030 |
no | Management operations logged to audit trail | none |
REQ-014-031 |
no | Client subscribes to governance.decisions stream |
2 |
REQ-014-032 |
no | Each decision includes: volk_id, action, resource, result (allow/deny) | none |
REQ-014-033 |
no | Each decision includes: prolog_query, evaluation_latency_ms | none |
REQ-014-034 |
no | Escalation events included with full escalation path and parties | none |
REQ-014-035 |
no | Constitutional article violations include article reference and text | none |
REQ-014-036 |
no | Client queries historical decisions via governance.query |
2 |
REQ-014-037 |
no | Query supports time range filter (date_from, date_to) | none |
REQ-014-038 |
no | Query supports filtering by volk_id, result, action | none |
REQ-014-039 |
no | Query results paginated (offset, limit) | none |
REQ-014-040 |
no | Query results sorted by timestamp descending | none |
REQ-014-041 |
no | Client evaluates governance check via governance.evaluate (read-only) |
3 |
REQ-014-042 |
no | Dry-run returns would-be result without side effects | none |
REQ-014-043 |
no | Dry-run includes Prolog trace showing rule evaluation path | none |
REQ-014-044 |
no | Dry-run logged as audit event with type "dry_run" | none |
REQ-014-045 |
no | Dry-run requires read_write scope minimum | none |
REQ-014-046 |
no | Client lists active Prolog rules via governance.rules (admin scope) |
1 |
REQ-014-047 |
no | Rules returned grouped by category (routing, permission, escalation, budget) | none |
REQ-014-048 |
no | Each rule includes: predicate, arity, source_file, line_number | none |
REQ-014-049 |
no | Rule listing supports filtering by category | none |
REQ-014-050 |
no | Rule listing supports full-text search on predicate names | none |
REQ-014-051 |
no | Client calls session.list to see all active sessions |
2 |
REQ-014-052 |
no | Each session entry includes: id, portfolio_id, status, opened_at, goals | none |
REQ-014-053 |
no | Client calls session.get with session_id for full state |
2 |
REQ-014-054 |
no | Full state includes: context, facts, carryover_tasks, duration, summary | 2 |
REQ-014-055 |
no | Session list supports filtering by portfolio_id and status | none |
REQ-014-056 |
no | Client subscribes to session.events for lifecycle events |
2 |
REQ-014-057 |
no | Events include: opened, closed, recovered, context_updated, error_occurred | 1 |
REQ-014-058 |
no | Each event includes session_id, event_type, timestamp, details | 1 |
REQ-014-059 |
no | Client subscribes to session.facts.subscribe for fact emission events |
2 |
REQ-014-060 |
no | Fact events include fact_type, session_id, data, timestamp | none |
REQ-014-061 |
no | Client opens new session via session.open (read_write scope) |
2 |
REQ-014-062 |
no | Session open accepts: portfolio, goals, context | none |
REQ-014-063 |
no | Client closes session via session.close (read_write scope) |
2 |
REQ-014-064 |
no | Session close accepts: session_id, status, summary, carryover_tasks | 2 |
REQ-014-065 |
no | Session control operations respect PAM++ governance | none |
REQ-014-066 |
no | Client queries portfolio stats via session.portfolio.stats |
none |
REQ-014-067 |
no | Stats include: total_sessions, total_duration, completion_rate, active_count | none |
REQ-014-068 |
no | Stats support filtering by portfolio_id | none |
REQ-014-069 |
no | Stats cached in Redis with 5-minute TTL | none |
REQ-014-070 |
no | Stats queryable with time range filter | none |
REQ-014-071 |
no | Client sends CXP packet via cxp.send (read_write scope) |
6 |
REQ-014-072 |
no | CXP packet validated against SPEC-004 schema before dispatch | none |
REQ-014-073 |
no | PAM++ validates sender authority before routing | none |
REQ-014-074 |
no | Response includes delivery_status and routing decision | none |
REQ-014-075 |
no | Failed dispatch returns structured error with reason | 2 |
REQ-014-076 |
no | Client triggers workflow via workflow.start (read_write scope) |
11 |
REQ-014-077 |
no | Client pauses workflow via workflow.pause (read_write scope) |
9 |
REQ-014-078 |
no | Client resumes workflow via workflow.resume (read_write scope) |
10 |
REQ-014-079 |
no | Client cancels workflow via workflow.cancel (read_write scope) |
9 |
REQ-014-080 |
no | Workflow commands validated against PAM++ governance | 9 |
REQ-014-081 |
no | Client queries current config via config.get (read_only scope) |
9 |
REQ-014-082 |
no | Client queries config by key path via config.get with path parameter |
4 |
REQ-014-083 |
no | Configuration values with secrets are redacted in responses | 2 |
REQ-014-084 |
no | Config response includes last_updated timestamp | 6 |
REQ-014-085 |
no | Config changes not permitted via gateway (read-only for safety) | 2 |
REQ-014-086 |
no | Client authenticates via auth.authenticate RPC method |
3 |
REQ-014-087 |
no | Authentication required before any other RPC method | 1 |
REQ-014-088 |
no | Unauthenticated RPC calls return JSON-RPC error code -32001 (Unauthorized) | none |
REQ-014-089 |
no | Unauthenticated clients disconnected after grace period (default: 5s) | 2 |
REQ-014-090 |
no | Authentication events logged to audit trail | none |
REQ-014-091 |
no | Static token configured via gateway config or GATEWAY_TOKEN env var | 2 |
REQ-014-092 |
no | Token comparison uses constant-time algorithm (hmac.compare_digest) | 1 |
REQ-014-093 |
no | Empty or missing tokens rejected immediately | 2 |
REQ-014-094 |
no | Token rotation supported via Redis-backed token store | 1 |
REQ-014-095 |
no | Static token auth returns read_write scope by default | 1 |
REQ-014-096 |
no | HMAC signature computed as HMAC-SHA256(secret, timestamp + nonce + client_id) | 2 |
REQ-014-097 |
no | Timestamp drift rejected if > configurable window (default: 60s) | 1 |
REQ-014-098 |
no | Nonce replay rejected within drift window (Redis-tracked) | 1 |
REQ-014-099 |
no | Multiple shared secrets supported for key rotation | 1 |
REQ-014-100 |
no | HMAC auth returns scope from client_id to scope mapping | 1 |
REQ-014-101 |
no | Prolog queried for gateway_access(ClientId, Scope) on auth |
1 |
REQ-014-102 |
no | Scoped access enforced: read_only, read_write, admin | 1 |
REQ-014-103 |
no | Auth decisions cached in Redis with configurable TTL (default: 300s) | none |
REQ-014-104 |
no | Cache invalidated on Prolog rule changes | none |
REQ-014-105 |
no | Policy auth failure includes reason from Prolog evaluation | none |
REQ-014-106 |
no | Server sends WebSocket ping every heartbeat_interval (default: 30s) | 1 |
REQ-014-107 |
no | Client must respond with pong within heartbeat_timeout (default: 10s) | none |
REQ-014-108 |
no | Client disconnected after heartbeat_max_misses consecutive missed pongs (default: 3) | 1 |
REQ-014-109 |
no | last_activity updated on any client message (not just pong) | 2 |
REQ-014-110 |
no | Heartbeat timing configurable per gateway instance | 1 |
REQ-014-111 |
no | Connected client list queryable via gateway.clients |
3 |
REQ-014-112 |
no | Each client entry includes: client_id, connected_at, last_activity, auth_scope, subscriptions | 2 |
REQ-014-113 |
no | Client provides metadata on connection (client_name, client_version, purpose) | none |
REQ-014-114 |
no | Presence events pushed to gateway.presence subscribers |
1 |
REQ-014-115 |
no | Presence events include: connected, disconnected, timeout, metadata_updated | none |
REQ-014-116 |
no | Disconnected client subscriptions cleaned up immediately | none |
REQ-014-117 |
no | Client session removed from Redis on disconnect | none |
REQ-014-118 |
no | Disconnect event logged to audit trail | none |
REQ-014-119 |
no | Disconnect reason tracked: clean_close, timeout, error, server_shutdown | none |
REQ-014-120 |
no | Connection cleanup completes within 1 second | none |
REQ-014-121 |
no | Gateway maintains event ring buffer in Redis (configurable size, default: 10,000) | 2 |
REQ-014-122 |
no | Events stored as Redis sorted set with timestamp score | none |
REQ-014-123 |
no | Events older than ring_buffer_ttl auto-expired (default: 24h) | none |
REQ-014-124 |
no | Ring buffer write latency < 5ms per event | none |
REQ-014-125 |
no | Buffer overflow evicts oldest events | 2 |
REQ-014-126 |
no | Client requests replay via gateway.replay with time range (since, until) |
none |
REQ-014-127 |
no | Client requests replay via gateway.replay with event count (last N events) |
2 |
REQ-014-128 |
no | Replay supports topic filter | 2 |
REQ-014-129 |
no | Replay supports same filters as live subscriptions | none |
REQ-014-130 |
no | Replay delivers events in chronological order | none |
REQ-014-131 |
no | Each event carries monotonically increasing sequence number per topic | 2 |
REQ-014-132 |
no | Client detects gaps via sequence numbers | none |
REQ-014-133 |
no | Gap notification includes missing sequence range | none |
REQ-014-134 |
no | Client can request gap fill via gateway.replay with sequence range |
none |
REQ-014-135 |
no | Sequence counter persisted in Redis across gateway restarts | none |
REQ-014-136 |
no | HTTP /health endpoint returns 200 OK when gateway is operational |
2 |
REQ-014-137 |
no | HTTP /health returns 503 when gateway is degraded or shutting down |
none |
REQ-014-138 |
no | HTTP /ready checks Redis, Neo4j, Prolog, and kernel health |
1 |
REQ-014-139 |
no | /ready returns 200 only when all dependencies are healthy |
none |
REQ-014-140 |
no | Health check responses include component-level detail | 2 |
REQ-014-141 |
no | HTTP /metrics returns Prometheus text format |
1 |
REQ-014-142 |
no | Metric: orchestrata_gateway_connected_clients (gauge) |
2 |
REQ-014-143 |
no | Metric: orchestrata_gateway_total_connections (counter) |
1 |
REQ-014-144 |
no | Metric: orchestrata_gateway_messages_received_total (counter) |
1 |
REQ-014-145 |
no | Metric: orchestrata_gateway_messages_sent_total (counter) |
1 |
REQ-014-146 |
no | Metric: orchestrata_gateway_rpc_latency_seconds (histogram, by method) |
1 |
REQ-014-147 |
no | Metric: orchestrata_gateway_subscription_count (gauge, by topic) |
2 |
REQ-014-148 |
no | Metric: orchestrata_gateway_auth_success_total (counter) |
1 |
REQ-014-149 |
no | Metric: orchestrata_gateway_auth_failure_total (counter) |
1 |
REQ-014-150 |
no | Metric: orchestrata_gateway_events_dropped_total (counter, by topic) |
none |
REQ-014-151 |
no | Client calls knowledge.query with Cypher query string |
3 |
REQ-014-152 |
no | Queries validated as read-only (MATCH, RETURN, WITH, OPTIONAL MATCH only) | none |
REQ-014-153 |
no | Mutations rejected (MERGE, CREATE, DELETE, SET, REMOVE, DETACH) | 1 |
REQ-014-154 |
no | Query timeout enforced (configurable, default: 10s) | 1 |
REQ-014-155 |
no | Results returned as JSON-serializable node/relationship structures | 1 |
REQ-014-156 |
no | Client calls knowledge.nodes with node_type and pagination |
1 |
REQ-014-157 |
no | Client calls knowledge.relationships with relationship_type and pagination |
1 |
REQ-014-158 |
no | Node results include all properties and labels | none |
REQ-014-159 |
no | Relationship results include source, target, type, and properties | none |
REQ-014-160 |
no | Browsing supports filtering by property values | none |
REQ-014-161 |
no | PAM++ controls which clients can query which graph segments | none |
REQ-014-162 |
no | Prolog predicate gateway_can_query_kg(ClientId, QueryPattern) enforced |
none |
REQ-014-163 |
no | Query audit records stored in Neo4j | none |
REQ-014-164 |
no | Query results capped at configurable max_results (default: 1000) | none |
REQ-014-165 |
no | Query execution time included in response metadata | none |
REQ-014-166 |
no | Server starts on configured host:port (default: 0.0.0.0:18790) | 6 |
REQ-014-167 |
no | Server accepts concurrent connections up to max_clients (default: 100) | none |
REQ-014-168 |
no | Server handles connection open, message, close, error events | 3 |
REQ-014-169 |
no | Server supports TLS when cert and key paths configured | none |
REQ-014-170 |
no | Server gracefully shuts down on SIGTERM, closing all connections | 4 |
REQ-014-171 |
no | Messages follow JSON-RPC 2.0 specification | none |
REQ-014-172 |
no | Requests have: jsonrpc, id, method, params | none |
REQ-014-173 |
no | Responses have: jsonrpc, id, result or error | 2 |
REQ-014-174 |
no | Server-push notifications have: jsonrpc, method, params (no id) | 2 |
REQ-014-175 |
no | Batch requests supported (array of JSON-RPC messages) | none |
REQ-014-176 |
no | Parse error returns JSON-RPC code -32700 | 1 |
REQ-014-177 |
no | Invalid request returns JSON-RPC code -32600 | 1 |
REQ-014-178 |
no | Method not found returns JSON-RPC code -32601 | 1 |
REQ-014-179 |
no | Invalid params returns JSON-RPC code -32602 | none |
REQ-014-180 |
no | Internal error returns JSON-RPC code -32603 | 2 |
REQ-014-181 |
no | Unauthorized returns custom code -32001 | none |
REQ-014-182 |
no | Rate limited returns custom code -32002 | none |
REQ-014-183 |
no | Budget exceeded returns custom code -32003 | none |
REQ-014-184 |
no | Maximum message size enforced (configurable, default: 1MB) | none |
REQ-014-185 |
no | Oversized messages rejected with error | none |
REQ-014-186 |
no | Rate limiting per client (configurable, default: 500 req/sec) | none |
REQ-014-187 |
no | Rate limited clients receive -32002 error | none |
REQ-014-188 |
no | WebSocket origin validation configurable | none |
REQ-014-189 |
no | Per-client event buffer (configurable, default: 1000 events) | none |
REQ-014-190 |
no | Buffer overflow drops oldest events and notifies client | none |
REQ-014-191 |
no | Gap notification includes dropped count and sequence range | none |
REQ-014-192 |
no | Events delivered asynchronously without blocking kernel EventBus | 2 |
REQ-014-193 |
no | Event serialization happens once, shared across subscribers | 2 |
REQ-014-194 |
no | Maximum subscriptions per client enforced (configurable, default: 50) | none |
REQ-014-195 |
no | Subscription limit exceeded returns structured error | none |
REQ-014-196 |
no | Subscriptions cleaned up on client disconnect | 1 |
REQ-014-197 |
no | Duplicate subscription to same topic+filter returns existing subscription_id | none |
REQ-014-198 |
no | Subscription count per topic queryable via gateway.info |
none |
REQ-014-199 |
no | gateway.info returns: version, uptime, capabilities, topic list |
3 |
REQ-014-200 |
no | gateway.ping returns server timestamp for latency measurement |
1 |
REQ-014-201 |
no | Gateway capabilities list includes supported RPC methods | none |
REQ-014-202 |
no | Gateway uptime measured from server start time | 1 |
REQ-014-203 |
no | METHODS (gateway/method_table.py) is the single declarative table of gateway methods (name, handler dotted path, mutates defaulting to true, expose, optional params_schema), importable without constructing any handler; RPCHandler's dispatch dict is built from it and equals it |
2 |
REQ-014-204 |
no | orchestrata-mcp is a stdio MCP server that is a WebSocket JSON-RPC client of the running gateway at GATEWAY_HOST:GATEWAY_PORT, authenticating with GATEWAY_TOKEN from the deployed environment (never a flag, never the ledger); its tool list is generated from METHODS (one tool per exposed method plus approve), so a method added to the table appears with no transport edit |
2 |
REQ-014-205 |
no | A mutating tool call needs a single-use, tool-bound, 300 s token issued by approve; without one it is refused with {"message":"PERMISSION_DENIED","capability":<tool>,"ledger_row":<id>} and nothing reaches the gateway; reuse, forgery, cross-tool use, approve on a read-only tool and unknown tools are refused with a ledger row; the token never appears in the ledger |
3 |
REQ-014-206 |
no | Streaming methods, legacy aliases and auth.authenticate are expose=False and absent from the tool list; a method not marked read-only is gated (fails closed) |
1 |
REQ-014-207 |
no | deploy/install-claude-config.sh registers codetools and orchestrata at user scope from the deployed release paths (idempotently, through the Claude CLI), writes the flat registration document, and refuses success unless each registered command resolves inside its deployed release |
none |
Code that traces this spec
Checklists
checklists/README.md
WebSocket Gateway (U:GW) Checklists
Project: Orchestrata WebSocket Gateway (Spec 014) Component: U:GW (Gateway) Status: Planning Phase Owner: Architecture Team
Overview
The WebSocket Gateway (U:GW) is the real-time control plane for Orchestrata. It exposes a bidirectional WebSocket server that allows external clients to observe and control the orchestration system. The gateway bridges the internal kernel EventBus to external consumers via JSON-RPC 2.0 over WebSocket, with PAM++ authorization on all operations.
Checklist Summary
| Checklist | Total Items | Completed | Progress |
|---|---|---|---|
| Requirements | 200+ | 0 | 0% |
| Constitutional Compliance | 110+ | 0 | 0% |
| Testing Plan | 350+ | 0 | 0% |
| TOTAL | 660+ | 0 | 0% |
Key Responsibilities
1. WebSocket Server and Protocol
- Accept client connections via WebSocket (ws:// or wss://)
- Handle JSON-RPC 2.0 request/response and server-push notifications
- Manage client connection lifecycle and heartbeat
- Enforce message size limits and rate limiting
2. Authentication and Authorization
- Authenticate clients before granting access (static token, HMAC, PAM++ policy)
- Enforce scoped access (read_only, read_write, admin) on all RPC methods
- Cache auth decisions for performance
- Log all auth events to audit trail
3. Real-Time Event Streaming
- Bridge kernel EventBus events to WebSocket subscribers
- Support topic-based pub/sub with client-side filters
- Maintain per-client event buffers for flow control
- Provide event replay from ring buffer for late-joining clients
4. Remote Command Execution
- Accept CXP packet dispatch via RPC
- Accept session lifecycle commands (open, close)
- Accept Volk management commands (register, deregister)
- Authorize all commands via PAM++ governance
5. Observability
- Serve HTTP health, readiness, and metrics endpoints
- Track connection counts, message rates, RPC latencies
- Export Prometheus-formatted metrics
- Provide gateway diagnostics via RPC
Performance Targets
| Metric | Target | Critical Threshold |
|---|---|---|
| Connection Accept | <50ms p95 | <100ms p99 |
| RPC Dispatch Overhead | <10ms p95 | <20ms p99 |
| Event Delivery | <100ms from kernel event p95 | <200ms p99 |
| Max Concurrent Clients | 100 | 50 minimum |
| Event Broadcast | 10,000 events/sec | 5,000 events/sec |
| RPC Throughput | 500 req/sec per client | 200 req/sec |
Checklist Files
1. requirements.md
Functional requirements organized by user stories:
- US-001: Real-Time CXP Traffic Observation
- US-002: Volk Status Monitoring
- US-003: Governance Decision Stream
- US-004: Session State Inspection
- US-005: Remote Command Execution
- US-006: Gateway Authentication
- US-007: Client Presence and Heartbeat
- US-008: Event Replay and History
- US-009: Metrics and Health Endpoint
- US-010: Knowledge Graph Live Query
2. constitutional.md
Compliance with all 11 constitutional articles:
- Article I: Agent Autonomy
- Article II: Prolog as Single Source of Truth
- Article III: Session Isolation
- Article IV: Hooks for Extensibility
- Article V: Minimal Core, Maximal Extension
- Article VI: Python 3.14t Implementation
- Article VII: Testing Without Mocks
- Article VIII: Metrics and Observability
- Article IX: Graceful Degradation
- Article X: Version Compatibility
- Article XI: Documentation First
3. testing.md
Comprehensive testing strategy:
- Unit Tests (120+ tests): Protocol parsing, auth logic, subscription management
- Integration Tests (100+ tests): WebSocket server, Redis ring buffer, Neo4j audit
- Contract Tests (30 tests): JSON-RPC compliance, event schema validation
- Performance Tests (60+ tests): Connection handling, broadcast throughput, latency
- Compliance Tests (11 tests): Constitutional compliance
- Failure Scenario Tests (40+ tests): Disconnect handling, buffer overflow, dependency failures
Integration Points
Upstream Dependencies
- Kernel EventBus: Source of all system events
- Redis: Ring buffer, auth cache, client sessions
- Neo4j: Audit trail storage, knowledge graph queries
- Prolog: PAM++ authorization for all operations
Downstream Consumers
- Web Dashboard: Real-time visualization of agent activity
- CLI Tools: Remote monitoring and control
- External Integrations: CI/CD, monitoring systems
- Mobile Apps: Remote session management
Dependencies
Required Services
- Redis server (ring buffer, auth cache)
- Neo4j server (audit trail, knowledge graph queries)
- Prolog engine (PAM++ authorization)
- Kernel EventBus (event source)
Required Libraries
- websockets (async WebSocket server)
- orchestrata-core (interfaces)
- orchestrata-kernel (EventBus integration)
- orchestrata-governance (PAM++ queries)
Optional Services
- Prometheus for metrics scraping
- Grafana for dashboard visualization
References
- SPEC-001: Orchestration Kernel
- SPEC-004: CXP Protocol
- SPEC-006: Session Management
- SPEC-007: Prolog Governance
- SPEC-008: Knowledge Graph
- SPEC-011: Provider Manager
Last Updated: 2026-03-27 Version: 1.0.0 Maintained By: Architecture Team
checklists/constitutional.md
WebSocket Gateway (U:GW) - Constitutional Compliance
Component: U:GW (Gateway) Spec: 014-websocket-gateway Status: Compliance Review Total Compliance Items: 110+
Overview
This document tracks compliance of the WebSocket Gateway (U:GW) with all 11 articles of the Orchestrata Constitution. The gateway is an external-facing control plane, making constitutional compliance particularly critical — it is the primary attack surface and must enforce governance rigorously.
Article I: Agent Autonomy
Principle: Volks (agents) retain autonomy; the gateway coordinates but does not control.
Compliance Requirements
Autonomy Preservation
- [ ] CONST-I-001: Gateway relays CXP packets but does not modify agent decisions
- [ ] CONST-I-002: Gateway does not inject responses on behalf of Volks
- [ ] CONST-I-003: Gateway does not override Volk routing preferences
- [ ] CONST-I-004: Gateway does not inspect Volk internal state beyond published metadata
- [ ] CONST-I-005: Remote commands via gateway are routed through kernel, not directly to Volks
- [ ] CONST-I-006: Gateway does not force Volk registration or deregistration
- [ ] CONST-I-007: Volk lifecycle events are observed, not controlled, by gateway
- [ ] CONST-I-008: Gateway respects Volk-declared capabilities and protocols
- [ ] CONST-I-009: Gateway does not prioritize or deprioritize specific Volks
- [ ] CONST-I-010: Gateway provides visibility without interference
Priority: Critical Verification: Integration tests + manual review
Article II: Prolog as Single Source of Truth
Principle: All governance rules are defined in Prolog; the gateway queries Prolog for decisions.
Compliance Requirements
Prolog Integration
- [ ] CONST-II-001: All gateway authentication decisions query Prolog (PAM++ policy mode)
- [ ] CONST-II-002: All RPC method authorization queries Prolog
- [ ] CONST-II-003: All topic subscription authorization queries Prolog
- [ ] CONST-II-004: All knowledge graph access control queries Prolog
- [ ] CONST-II-005: Gateway does not hardcode authorization logic
- [ ] CONST-II-006: Gateway caches Prolog results but invalidates on rule updates
- [ ] CONST-II-007: Gateway falls back to deny on Prolog failure (safe default)
- [ ] CONST-II-008: All governance queries logged for audit
- [ ] CONST-II-009: Gateway-specific Prolog predicates follow PAM++ naming conventions
- [ ] CONST-II-010: Prolog rule changes take effect without gateway restart
Priority: Critical Verification: Prolog integration tests + policy compliance tests
Article III: Session Isolation
Principle: Sessions are isolated; state does not leak between sessions.
Compliance Requirements
State Isolation
- [ ] CONST-III-001: Session queries via gateway return only the requested session's data
- [ ] CONST-III-002: Session event subscriptions are scoped to specific sessions or all (explicit)
- [ ] CONST-III-003: CXP traffic subscriptions do not leak cross-session packets
- [ ] CONST-III-004: Session.open via gateway creates properly isolated sessions
- [ ] CONST-III-005: Session.close via gateway performs full session teardown
- [ ] CONST-III-006: Gateway client sessions (gateway_session_id) are distinct from orchestration sessions
- [ ] CONST-III-007: Gateway does not merge or correlate sessions without explicit request
- [ ] CONST-III-008: Portfolio queries aggregate sessions without exposing cross-session details
- [ ] CONST-III-009: Session recovery via gateway validates session ownership
- [ ] CONST-III-010: Gateway audit records include session_id for traceability
Priority: Critical Verification: Session isolation tests + state leak detection
Article IV: Hooks for Extensibility
Principle: The gateway provides extension points for customization without core modification.
Compliance Requirements
Extension Points
- [ ] CONST-IV-001: Pre-authentication hook for custom auth logic
- [ ] CONST-IV-002: Post-authentication hook for session setup
- [ ] CONST-IV-003: Pre-RPC-dispatch hook for request inspection
- [ ] CONST-IV-004: Post-RPC-dispatch hook for response transformation
- [ ] CONST-IV-005: Pre-event-push hook for event filtering or enrichment
- [ ] CONST-IV-006: Post-event-push hook for delivery tracking
- [ ] CONST-IV-007: Client connect hook for custom validation
- [ ] CONST-IV-008: Client disconnect hook for cleanup
- [ ] CONST-IV-009: Custom RPC method registration via hook API
- [ ] CONST-IV-010: Custom event topic registration via hook API
Priority: High Verification: Hook registration tests + extension tests
Article V: Minimal Core, Maximal Extension
Principle: Gateway core is minimal; features are added via extensions.
Compliance Requirements
Minimal Core
- [ ] CONST-V-001: Core handles only: WebSocket server, JSON-RPC dispatch, auth, pub/sub
- [ ] CONST-V-002: Knowledge graph queries are an extension, not core
- [ ] CONST-V-003: Metrics and health endpoints are extensions, not core
- [ ] CONST-V-004: Event replay is an extension, not core
- [ ] CONST-V-005: Custom auth strategies are pluggable extensions
- [ ] CONST-V-006: Core gateway has zero business logic
- [ ] CONST-V-007: Core gateway dependencies are minimal (websockets, json)
- [ ] CONST-V-008: Core gateway code is < 3000 lines
- [ ] CONST-V-009: Core gateway API is stable and versioned
- [ ] CONST-V-010: Extensions loaded via DI container, not hardcoded imports
Priority: High Verification: Core size metrics + extension loading tests
Article VI: Python 3.14t Implementation
Principle: Gateway is implemented in Python 3.14t with modern async patterns.
Compliance Requirements
Python Version
- [ ] CONST-VI-001: Code requires Python 3.14t or newer
- [ ] CONST-VI-002: Type hints on all public functions and methods
- [ ] CONST-VI-003: Async/await for all I/O operations (WebSocket, Redis, Neo4j, Prolog)
- [ ] CONST-VI-004: No blocking calls in async functions
- [ ] CONST-VI-005: asyncio.gather for concurrent event delivery
- [ ] CONST-VI-006: asyncio.Queue for per-client event buffers
- [ ] CONST-VI-007: websockets library for async WebSocket server
- [ ] CONST-VI-008: aioredis for async Redis operations
- [ ] CONST-VI-009: neo4j async driver for Neo4j operations
- [ ] CONST-VI-010: No global mutable state in gateway module
Code Quality
- [ ] CONST-VI-011: Black formatting enforced
- [ ] CONST-VI-012: Flake8 linting passes
- [ ] CONST-VI-013: Mypy strict mode passes
- [ ] CONST-VI-014: Isort for import sorting
- [ ] CONST-VI-015: Google-style docstrings for all public APIs
- [ ] CONST-VI-016: Test coverage > 90%
- [ ] CONST-VI-017: Cyclomatic complexity < 10 per function
- [ ] CONST-VI-018: Functions < 40 lines
- [ ] CONST-VI-019: No
# type: ignorewithout justification - [ ] CONST-VI-020: Code reviewed before merge
Priority: High Verification: CI/CD checks + static analysis
Article VII: Testing Without Mocks
Principle: Tests use real implementations, not mocks.
Compliance Requirements
Real Systems Testing
- [ ] CONST-VII-001: Tests use real WebSocket connections (client ↔ server)
- [ ] CONST-VII-002: Tests use real Redis instance for ring buffer and caching
- [ ] CONST-VII-003: Tests use real Neo4j instance for audit trail and KG queries
- [ ] CONST-VII-004: Tests use real Prolog for PAM++ authorization
- [ ] CONST-VII-005: No unittest.mock, MagicMock, Mock, AsyncMock, or patch
- [ ] CONST-VII-006: Test fixtures create real resources and clean up after
- [ ] CONST-VII-007: Integration tests use real network I/O (WebSocket frames)
- [ ] CONST-VII-008: Performance tests use real workloads and connections
- [ ] CONST-VII-009: Tests validate real race conditions (concurrent clients)
- [ ] CONST-VII-010: Tests validate real timeout behavior
Priority: Critical Verification: Test code review + mock detector
Article VIII: Metrics and Observability
Principle: All operations are observable and measurable.
Compliance Requirements
Metrics Collection
- [ ] CONST-VIII-001: Connection count metric (connected_clients gauge)
- [ ] CONST-VIII-002: RPC latency metric (histogram by method)
- [ ] CONST-VIII-003: Event delivery latency metric (histogram by topic)
- [ ] CONST-VIII-004: Subscription count metric (gauge by topic)
- [ ] CONST-VIII-005: Auth success/failure counters
- [ ] CONST-VIII-006: Events dropped counter (by topic)
- [ ] CONST-VIII-007: Message throughput counters (sent, received)
- [ ] CONST-VIII-008: Ring buffer size metric
- [ ] CONST-VIII-009: Client session duration histogram
- [ ] CONST-VIII-010: Dependency health status metrics
Observability
- [ ] CONST-VIII-011: Structured logging (JSON format) for all gateway operations
- [ ] CONST-VIII-012: Correlation IDs linking RPC requests to kernel operations
- [ ] CONST-VIII-013: Health check endpoint reflects real component status
- [ ] CONST-VIII-014: Readiness probe checks all dependencies
- [ ] CONST-VIII-015: Prometheus metrics export at /metrics
- [ ] CONST-VIII-016: Debug logging available (disabled in production)
- [ ] CONST-VIII-017: Audit trail queryable for compliance review
- [ ] CONST-VIII-018: Client presence observable via gateway.clients
- [ ] CONST-VIII-019: Event delivery gaps observable via sequence numbers
- [ ] CONST-VIII-020: Gateway version and uptime queryable via gateway.info
Priority: High Verification: Metrics tests + observability review
Article IX: Graceful Degradation
Principle: System degrades gracefully under failure, does not crash.
Compliance Requirements
Failure Handling
- [ ] CONST-IX-001: Redis unavailable: auth defaults to deny, ring buffer writes deferred
- [ ] CONST-IX-002: Neo4j unavailable: audit deferred, KG queries return error
- [ ] CONST-IX-003: Prolog unavailable: cached auth decisions used, uncached defaults to deny
- [ ] CONST-IX-004: Kernel EventBus error: gateway continues serving existing clients
- [ ] CONST-IX-005: Client disconnect: subscriptions cleaned up within 1 second
- [ ] CONST-IX-006: Buffer overflow: oldest events dropped, client notified
- [ ] CONST-IX-007: Rate limit exceeded: client receives structured error, not disconnect
- [ ] CONST-IX-008: Max clients reached: new connections rejected with reason
- [ ] CONST-IX-009: Invalid message: error response sent, connection preserved
- [ ] CONST-IX-010: Handler exception: internal error returned, gateway continues
Recovery
- [ ] CONST-IX-011: Automatic Redis reconnection with exponential backoff
- [ ] CONST-IX-012: Automatic Neo4j reconnection with exponential backoff
- [ ] CONST-IX-013: Automatic Prolog reconnection with exponential backoff
- [ ] CONST-IX-014: EventBus re-subscription after kernel restart
- [ ] CONST-IX-015: Ring buffer recovery from Redis after gateway restart
- [ ] CONST-IX-016: Client sessions recoverable from Redis after gateway restart
- [ ] CONST-IX-017: Graceful shutdown on SIGTERM (close connections, flush buffers)
- [ ] CONST-IX-018: Fast restart with state recovery (< 5 seconds)
- [ ] CONST-IX-019: Health endpoint returns degraded status during partial failure
- [ ] CONST-IX-020: Recovery events logged for debugging
Priority: High Verification: Failure injection tests + chaos tests
Article X: Version Compatibility
Principle: APIs are versioned; breaking changes are avoided.
Compliance Requirements
API Versioning
- [ ] CONST-X-001: JSON-RPC messages include gateway protocol version
- [ ] CONST-X-002: Event schema versioned in event metadata
- [ ] CONST-X-003: RPC method names namespaced (e.g., cxp.send, volk.list)
- [ ] CONST-X-004: Auth protocol versioned in auth.authenticate response
- [ ] CONST-X-005: Semantic versioning for gateway releases
- [ ] CONST-X-006: Deprecation warnings for old methods
- [ ] CONST-X-007: New methods added without breaking existing clients
- [ ] CONST-X-008: Event schema changes are additive (new fields, not removed fields)
- [ ] CONST-X-009: Client capability negotiation on connection
- [ ] CONST-X-010: Backward compatibility for N-1 protocol version
Priority: Medium Verification: Compatibility tests + version migration tests
Article XI: Documentation First
Principle: Documentation precedes implementation.
Compliance Requirements
Design Documentation
- [ ] CONST-XI-001: Gateway architecture documented before implementation
- [ ] CONST-XI-002: JSON-RPC method catalog documented before implementation
- [ ] CONST-XI-003: Event schema documented before implementation
- [ ] CONST-XI-004: Auth strategies documented before implementation
- [ ] CONST-XI-005: Prolog predicates documented with examples
- [ ] CONST-XI-006: Configuration options documented
- [ ] CONST-XI-007: WebSocket connection lifecycle documented
- [ ] CONST-XI-008: Error codes and handling documented
- [ ] CONST-XI-009: Performance targets documented
- [ ] CONST-XI-010: Security model documented
Priority: High Verification: Documentation review + doc tests
Summary Statistics
| Article | Total Items | Completed | Percentage |
|---|---|---|---|
| Article I (Autonomy) | 10 | 0 | 0% |
| Article II (Prolog) | 10 | 0 | 0% |
| Article III (Isolation) | 10 | 0 | 0% |
| Article IV (Hooks) | 10 | 0 | 0% |
| Article V (Minimal Core) | 10 | 0 | 0% |
| Article VI (Python 3.14t) | 20 | 0 | 0% |
| Article VII (No Mocks) | 10 | 0 | 0% |
| Article VIII (Observability) | 20 | 0 | 0% |
| Article IX (Degradation) | 20 | 0 | 0% |
| Article X (Versioning) | 10 | 0 | 0% |
| Article XI (Documentation) | 10 | 0 | 0% |
| TOTAL | 140 | 0 | 0% |
Last Updated: 2026-03-27 Version: 1.0.0 Maintained By: Architecture Team
checklists/requirements.md
The requirement list above comes from this file; 0 of 207 checkbox items are ticked.
checklists/testing.md
WebSocket Gateway (U:GW) - Testing Plan
Component: U:GW (Gateway) Spec: 014-websocket-gateway Status: Test Planning Phase Total Test Cases: 350+
Overview
This document defines the comprehensive testing strategy for the WebSocket Gateway (U:GW). All tests follow the strict "no mocking" policy and use real implementations including real WebSocket connections, real Redis, real Neo4j, and real Prolog for governance evaluation.
Test Categories Summary
| Category | Test Count | Purpose | Priority |
|---|---|---|---|
| Unit Tests | 120+ | Core logic validation | Critical |
| Integration Tests | 100+ | System integration | Critical |
| Contract Tests | 30 | Protocol compliance | High |
| Performance Tests | 60+ | Latency & throughput | High |
| Compliance Tests | 11 | Constitutional compliance | Critical |
| Failure Scenario Tests | 40+ | Error handling & recovery | High |
| TOTAL | 361+ |
Unit Tests (120+)
WebSocket Server Tests (15 tests)
- [ ] TEST-UNIT-WS-001: Server starts on configured host and port
- [ ] TEST-UNIT-WS-002: Server accepts WebSocket connections
- [ ] TEST-UNIT-WS-003: Server rejects connections when max_clients reached
- [ ] TEST-UNIT-WS-004: Server handles clean client disconnect
- [ ] TEST-UNIT-WS-005: Server handles abrupt client disconnect
- [ ] TEST-UNIT-WS-006: Server gracefully shuts down on stop_serving()
- [ ] TEST-UNIT-WS-007: Server closes all connections on shutdown
- [ ] TEST-UNIT-WS-008: Server enforces max_message_size
- [ ] TEST-UNIT-WS-009: Server rejects oversized messages with error
- [ ] TEST-UNIT-WS-010: Server assigns unique gateway_session_id per connection
- [ ] TEST-UNIT-WS-011: Server handles concurrent connection attempts
- [ ] TEST-UNIT-WS-012: Server TLS mode requires cert and key paths
- [ ] TEST-UNIT-WS-013: Server handles connection errors without crashing
- [ ] TEST-UNIT-WS-014: Server tracks connection count accurately
- [ ] TEST-UNIT-WS-015: Server respects GatewayConfig parameters
JSON-RPC Protocol Tests (20 tests)
- [ ] TEST-UNIT-RPC-001: Parse valid JSON-RPC 2.0 request
- [ ] TEST-UNIT-RPC-002: Parse valid JSON-RPC 2.0 batch request
- [ ] TEST-UNIT-RPC-003: Reject request missing jsonrpc field
- [ ] TEST-UNIT-RPC-004: Reject request with wrong jsonrpc version
- [ ] TEST-UNIT-RPC-005: Reject request missing method field
- [ ] TEST-UNIT-RPC-006: Reject request with non-string method
- [ ] TEST-UNIT-RPC-007: Accept request with null id (notification)
- [ ] TEST-UNIT-RPC-008: Accept request without params (optional)
- [ ] TEST-UNIT-RPC-009: Return parse error (-32700) for invalid JSON
- [ ] TEST-UNIT-RPC-010: Return invalid request (-32600) for malformed request
- [ ] TEST-UNIT-RPC-011: Return method not found (-32601) for unknown method
- [ ] TEST-UNIT-RPC-012: Return invalid params (-32602) for schema violations
- [ ] TEST-UNIT-RPC-013: Return internal error (-32603) for handler exceptions
- [ ] TEST-UNIT-RPC-014: Return unauthorized (-32001) for unauthenticated calls
- [ ] TEST-UNIT-RPC-015: Return rate limited (-32002) when rate exceeded
- [ ] TEST-UNIT-RPC-016: Serialize response with result on success
- [ ] TEST-UNIT-RPC-017: Serialize response with error on failure
- [ ] TEST-UNIT-RPC-018: Serialize notification (no id in response)
- [ ] TEST-UNIT-RPC-019: Process batch requests and return batch responses
- [ ] TEST-UNIT-RPC-020: Batch response order matches request order
Authentication Tests (25 tests)
- [ ] TEST-UNIT-AUTH-001: Static token auth succeeds with correct token
- [ ] TEST-UNIT-AUTH-002: Static token auth fails with wrong token
- [ ] TEST-UNIT-AUTH-003: Static token auth fails with empty token
- [ ] TEST-UNIT-AUTH-004: Static token comparison is constant-time
- [ ] TEST-UNIT-AUTH-005: Static token returns read_write scope
- [ ] TEST-UNIT-AUTH-006: HMAC auth succeeds with valid signature
- [ ] TEST-UNIT-AUTH-007: HMAC auth fails with invalid signature
- [ ] TEST-UNIT-AUTH-008: HMAC auth rejects stale timestamp (drift > window)
- [ ] TEST-UNIT-AUTH-009: HMAC auth rejects replayed nonce
- [ ] TEST-UNIT-AUTH-010: HMAC auth accepts multiple shared secrets (rotation)
- [ ] TEST-UNIT-AUTH-011: PAM++ policy auth queries Prolog for access
- [ ] TEST-UNIT-AUTH-012: PAM++ policy auth caches decisions in Redis
- [ ] TEST-UNIT-AUTH-013: PAM++ policy auth invalidates cache on rule change
- [ ] TEST-UNIT-AUTH-014: PAM++ policy auth returns scoped access level
- [ ] TEST-UNIT-AUTH-015: Auth framework rejects unauthenticated RPC calls
- [ ] TEST-UNIT-AUTH-016: Auth framework allows auth.authenticate without prior auth
- [ ] TEST-UNIT-AUTH-017: Grace period disconnects unauthenticated clients
- [ ] TEST-UNIT-AUTH-018: Auth events logged to audit trail
- [ ] TEST-UNIT-AUTH-019: Auth failure logged with client IP
- [ ] TEST-UNIT-AUTH-020: Token rotation via Redis-backed store works
- [ ] TEST-UNIT-AUTH-021: Scope enforcement blocks read_only from write methods
- [ ] TEST-UNIT-AUTH-022: Scope enforcement blocks non-admin from admin methods
- [ ] TEST-UNIT-AUTH-023: Admin scope grants access to all methods
- [ ] TEST-UNIT-AUTH-024: Auth result includes expires_at for time-limited auth
- [ ] TEST-UNIT-AUTH-025: Expired auth requires re-authentication
Subscription Management Tests (20 tests)
- [ ] TEST-UNIT-SUB-001: Client subscribes to topic successfully
- [ ] TEST-UNIT-SUB-002: Client receives subscription_id on subscribe
- [ ] TEST-UNIT-SUB-003: Client unsubscribes with subscription_id
- [ ] TEST-UNIT-SUB-004: Unsubscribe with unknown subscription_id returns error
- [ ] TEST-UNIT-SUB-005: Subscription filters applied correctly (single filter)
- [ ] TEST-UNIT-SUB-006: Subscription filters applied correctly (multiple AND)
- [ ] TEST-UNIT-SUB-007: Subscription supports glob pattern matching on subject
- [ ] TEST-UNIT-SUB-008: Maximum subscriptions per client enforced
- [ ] TEST-UNIT-SUB-009: Subscription limit exceeded returns structured error
- [ ] TEST-UNIT-SUB-010: Duplicate subscription returns existing subscription_id
- [ ] TEST-UNIT-SUB-011: Subscriptions cleaned up on disconnect
- [ ] TEST-UNIT-SUB-012: Subscription count per topic tracked accurately
- [ ] TEST-UNIT-SUB-013: Empty filter subscribes to all events on topic
- [ ] TEST-UNIT-SUB-014: Invalid filter field returns error
- [ ] TEST-UNIT-SUB-015: Subscription persists across reconnection (if client_id same)
- [ ] TEST-UNIT-SUB-016: Topic validation rejects unknown topics
- [ ] TEST-UNIT-SUB-017: PAM++ authorizes topic subscription
- [ ] TEST-UNIT-SUB-018: Unauthorized topic subscription rejected
- [ ] TEST-UNIT-SUB-019: Subscription event logged to audit trail
- [ ] TEST-UNIT-SUB-020: Bulk unsubscribe on disconnect is atomic
Event Delivery Tests (20 tests)
- [ ] TEST-UNIT-EVT-001: Event pushed to subscribed clients
- [ ] TEST-UNIT-EVT-002: Event not pushed to unsubscribed clients
- [ ] TEST-UNIT-EVT-003: Event filtered by subscription filter
- [ ] TEST-UNIT-EVT-004: Event carries monotonic sequence number
- [ ] TEST-UNIT-EVT-005: Event buffered when client send buffer full
- [ ] TEST-UNIT-EVT-006: Buffer overflow drops oldest events
- [ ] TEST-UNIT-EVT-007: Buffer overflow notifies client of gap
- [ ] TEST-UNIT-EVT-008: Gap notification includes dropped count and sequence range
- [ ] TEST-UNIT-EVT-009: Event delivery does not block kernel EventBus
- [ ] TEST-UNIT-EVT-010: Event serialized once and shared across subscribers
- [ ] TEST-UNIT-EVT-011: Multiple subscribers receive same event independently
- [ ] TEST-UNIT-EVT-012: Event delivery within 100ms of kernel event
- [ ] TEST-UNIT-EVT-013: Event payload truncation when max_payload_size configured
- [ ] TEST-UNIT-EVT-014: Truncated event includes truncation indicator
- [ ] TEST-UNIT-EVT-015: Event delivery handles client disconnect mid-send
- [ ] TEST-UNIT-EVT-016: Event delivery continues for remaining clients after one fails
- [ ] TEST-UNIT-EVT-017: Broadcast returns correct delivery count
- [ ] TEST-UNIT-EVT-018: Event timestamp uses ISO 8601 format
- [ ] TEST-UNIT-EVT-019: Event includes source component identifier
- [ ] TEST-UNIT-EVT-020: Events with no subscribers are discarded silently
Heartbeat Tests (10 tests)
- [ ] TEST-UNIT-HB-001: Server sends ping at configured interval
- [ ] TEST-UNIT-HB-002: Client pong resets missed counter
- [ ] TEST-UNIT-HB-003: Missed pong increments counter
- [ ] TEST-UNIT-HB-004: Client disconnected after max_misses consecutive misses
- [ ] TEST-UNIT-HB-005: Any client message updates last_activity
- [ ] TEST-UNIT-HB-006: Presence event emitted on timeout disconnect
- [ ] TEST-UNIT-HB-007: Heartbeat interval configurable per gateway instance
- [ ] TEST-UNIT-HB-008: Heartbeat disabled when interval set to 0
- [ ] TEST-UNIT-HB-009: Heartbeat continues during high message throughput
- [ ] TEST-UNIT-HB-010: Heartbeat timing not affected by event delivery backlog
Ring Buffer Tests (10 tests)
- [ ] TEST-UNIT-RB-001: Events stored in Redis sorted set by timestamp
- [ ] TEST-UNIT-RB-002: Ring buffer respects max size (oldest evicted)
- [ ] TEST-UNIT-RB-003: Events expired by TTL
- [ ] TEST-UNIT-RB-004: Replay by time range returns correct events
- [ ] TEST-UNIT-RB-005: Replay by count returns last N events
- [ ] TEST-UNIT-RB-006: Replay respects topic filter
- [ ] TEST-UNIT-RB-007: Replay respects subscription filters
- [ ] TEST-UNIT-RB-008: Replay delivers events in chronological order
- [ ] TEST-UNIT-RB-009: Sequence counter persisted across gateway restarts
- [ ] TEST-UNIT-RB-010: Ring buffer write latency < 5ms
Integration Tests (100+)
Kernel EventBus Integration (20 tests)
- [ ] TEST-INTEG-EB-001: Gateway subscribes to cxp.* events on initialize
- [ ] TEST-INTEG-EB-002: Gateway subscribes to volk.lifecycle.* events on initialize
- [ ] TEST-INTEG-EB-003: Gateway subscribes to governance.* events on initialize
- [ ] TEST-INTEG-EB-004: Gateway subscribes to session.* events on initialize
- [ ] TEST-INTEG-EB-005: Gateway subscribes to provider.* events on initialize
- [ ] TEST-INTEG-EB-006: CXP event from kernel delivered to gateway subscriber
- [ ] TEST-INTEG-EB-007: Volk lifecycle event from kernel delivered to gateway subscriber
- [ ] TEST-INTEG-EB-008: Governance decision from kernel delivered to gateway subscriber
- [ ] TEST-INTEG-EB-009: Session event from kernel delivered to gateway subscriber
- [ ] TEST-INTEG-EB-010: Provider event from kernel delivered to gateway subscriber
- [ ] TEST-INTEG-EB-011: Gateway unsubscribes from EventBus on stop
- [ ] TEST-INTEG-EB-012: EventBus error does not crash gateway
- [ ] TEST-INTEG-EB-013: High-volume EventBus does not backpressure kernel
- [ ] TEST-INTEG-EB-014: Gateway filters events before pushing to clients
- [ ] TEST-INTEG-EB-015: Gateway maps kernel event types to gateway topics
- [ ] TEST-INTEG-EB-016: Gateway handles kernel restart gracefully
- [ ] TEST-INTEG-EB-017: Gateway re-subscribes to EventBus after reconnection
- [ ] TEST-INTEG-EB-018: Multiple gateway instances receive same events
- [ ] TEST-INTEG-EB-019: EventBus wildcard subscription pattern works
- [ ] TEST-INTEG-EB-020: Gateway subscriber_id is unique across instances
Redis Integration (20 tests)
- [ ] TEST-INTEG-REDIS-001: Client session stored in Redis on connect
- [ ] TEST-INTEG-REDIS-002: Client session removed from Redis on disconnect
- [ ] TEST-INTEG-REDIS-003: Ring buffer events stored in Redis sorted set
- [ ] TEST-INTEG-REDIS-004: Ring buffer TTL auto-expires old events
- [ ] TEST-INTEG-REDIS-005: Auth nonce stored in Redis with TTL
- [ ] TEST-INTEG-REDIS-006: Auth decision cached in Redis
- [ ] TEST-INTEG-REDIS-007: Sequence counter persisted in Redis
- [ ] TEST-INTEG-REDIS-008: Redis connection pool used (not per-operation)
- [ ] TEST-INTEG-REDIS-009: Redis disconnect handled gracefully (in-memory fallback)
- [ ] TEST-INTEG-REDIS-010: Redis reconnection with exponential backoff
- [ ] TEST-INTEG-REDIS-011: Redis pipeline used for bulk operations
- [ ] TEST-INTEG-REDIS-012: Redis key namespace isolation (orchestrata:gateway:*)
- [ ] TEST-INTEG-REDIS-013: Token rotation via Redis reflects immediately
- [ ] TEST-INTEG-REDIS-014: Multiple gateway instances share Redis state
- [ ] TEST-INTEG-REDIS-015: Redis memory usage within expected bounds
- [ ] TEST-INTEG-REDIS-016: Ring buffer sorted set eviction works correctly
- [ ] TEST-INTEG-REDIS-017: Client list from Redis matches connected clients
- [ ] TEST-INTEG-REDIS-018: Portfolio stats cache in Redis with TTL
- [ ] TEST-INTEG-REDIS-019: Redis health check returns accurate status
- [ ] TEST-INTEG-REDIS-020: Redis operations use configurable DB number
Neo4j Integration (15 tests)
- [ ] TEST-INTEG-NEO4J-001: RPC audit records stored as (:GatewayAudit) nodes
- [ ] TEST-INTEG-NEO4J-002: Auth audit records stored as (:GatewayAuth) nodes
- [ ] TEST-INTEG-NEO4J-003: Audit records include all required fields
- [ ] TEST-INTEG-NEO4J-004: Knowledge graph query executes read-only Cypher
- [ ] TEST-INTEG-NEO4J-005: Knowledge graph query rejects mutations
- [ ] TEST-INTEG-NEO4J-006: Knowledge graph query respects timeout
- [ ] TEST-INTEG-NEO4J-007: Knowledge graph results serialized as JSON
- [ ] TEST-INTEG-NEO4J-008: Knowledge graph pagination works correctly
- [ ] TEST-INTEG-NEO4J-009: Neo4j disconnect handled gracefully (audit deferred)
- [ ] TEST-INTEG-NEO4J-010: Neo4j reconnection with exponential backoff
- [ ] TEST-INTEG-NEO4J-011: Audit records immutable after write
- [ ] TEST-INTEG-NEO4J-012: Historical decision query retrieves from Neo4j
- [ ] TEST-INTEG-NEO4J-013: Neo4j health check returns accurate status
- [ ] TEST-INTEG-NEO4J-014: Batch audit writes for performance
- [ ] TEST-INTEG-NEO4J-015: Neo4j connection uses async driver
Prolog Integration (15 tests)
- [ ] TEST-INTEG-PL-001: PAM++ auth queries Prolog for gateway_access
- [ ] TEST-INTEG-PL-002: Per-method authorization queries gateway_can_execute
- [ ] TEST-INTEG-PL-003: Topic subscription authorization queries gateway_can_subscribe
- [ ] TEST-INTEG-PL-004: KG query authorization queries gateway_can_query_kg
- [ ] TEST-INTEG-PL-005: Scope hierarchy enforced (admin > read_write > read_only)
- [ ] TEST-INTEG-PL-006: Prolog query results cached in Redis
- [ ] TEST-INTEG-PL-007: Cache invalidation on rule change
- [ ] TEST-INTEG-PL-008: Prolog timeout falls back to safe default (deny)
- [ ] TEST-INTEG-PL-009: Prolog error logged and escalated
- [ ] TEST-INTEG-PL-010: Governance dry-run evaluates without side effects
- [ ] TEST-INTEG-PL-011: Governance dry-run includes Prolog trace
- [ ] TEST-INTEG-PL-012: Rule listing retrieves from Prolog knowledge base
- [ ] TEST-INTEG-PL-013: Suspended client denied access via Prolog
- [ ] TEST-INTEG-PL-014: Prolog health check returns accurate status
- [ ] TEST-INTEG-PL-015: Multiple concurrent Prolog queries handled
End-to-End Tests (30 tests)
- [ ] TEST-INTEG-E2E-001: Full auth → subscribe → receive event → unsubscribe flow
- [ ] TEST-INTEG-E2E-002: Full auth → cxp.send → observe delivery via subscription
- [ ] TEST-INTEG-E2E-003: Full auth → session.open → session.close via gateway
- [ ] TEST-INTEG-E2E-004: Multiple clients subscribe to different topics simultaneously
- [ ] TEST-INTEG-E2E-005: Client disconnect and reconnect preserves no stale state
- [ ] TEST-INTEG-E2E-006: Admin creates Volk via gateway, other client sees lifecycle event
- [ ] TEST-INTEG-E2E-007: Governance deny decision streamed to subscriber
- [ ] TEST-INTEG-E2E-008: Knowledge graph query returns real data from Neo4j
- [ ] TEST-INTEG-E2E-009: Event replay returns events from before client connected
- [ ] TEST-INTEG-E2E-010: Health endpoint reflects real dependency status
- [ ] TEST-INTEG-E2E-011: Metrics endpoint includes real connection count
- [ ] TEST-INTEG-E2E-012: Rate limiting kicks in at configured threshold
- [ ] TEST-INTEG-E2E-013: Heartbeat timeout disconnects idle client
- [ ] TEST-INTEG-E2E-014: Gateway survives kernel EventBus flood
- [ ] TEST-INTEG-E2E-015: Gateway restarts cleanly after stop_serving + start_serving
- [ ] TEST-INTEG-E2E-016: Audit trail complete for full session lifecycle
- [ ] TEST-INTEG-E2E-017: PAM++ blocks read_only client from cxp.send
- [ ] TEST-INTEG-E2E-018: PAM++ blocks non-admin from volk.register
- [ ] TEST-INTEG-E2E-019: Batch JSON-RPC request returns batch response
- [ ] TEST-INTEG-E2E-020: Gateway handles 50 concurrent clients
- [ ] TEST-INTEG-E2E-021: Event sequence numbers are monotonically increasing
- [ ] TEST-INTEG-E2E-022: Buffer overflow sends gap notification to slow client
- [ ] TEST-INTEG-E2E-023: Ring buffer survives gateway restart (Redis-backed)
- [ ] TEST-INTEG-E2E-024: HMAC auth with nonce replay prevention works
- [ ] TEST-INTEG-E2E-025: Multiple auth strategies can coexist
- [ ] TEST-INTEG-E2E-026: Gateway info RPC returns accurate capabilities
- [ ] TEST-INTEG-E2E-027: Gateway ping measures real round-trip latency
- [ ] TEST-INTEG-E2E-028: Session facts stream delivers real-time fact emissions
- [ ] TEST-INTEG-E2E-029: Portfolio stats query returns accurate data
- [ ] TEST-INTEG-E2E-030: Governance evaluate (dry-run) returns correct result
Contract Tests (30)
JSON-RPC 2.0 Compliance (10 tests)
- [ ] TEST-CONTRACT-RPC-001: Request format matches JSON-RPC 2.0 specification
- [ ] TEST-CONTRACT-RPC-002: Response format matches JSON-RPC 2.0 specification
- [ ] TEST-CONTRACT-RPC-003: Error object includes code, message, data fields
- [ ] TEST-CONTRACT-RPC-004: Notification format has no id field
- [ ] TEST-CONTRACT-RPC-005: Batch request format is valid JSON array
- [ ] TEST-CONTRACT-RPC-006: Error codes match specification (-32700 through -32603)
- [ ] TEST-CONTRACT-RPC-007: Custom error codes in server-defined range (-32000 through -32099)
- [ ] TEST-CONTRACT-RPC-008: Id field preserved between request and response
- [ ] TEST-CONTRACT-RPC-009: Params field accepts positional (array) and named (object)
- [ ] TEST-CONTRACT-RPC-010: Version field is exactly "2.0"
Event Schema Compliance (10 tests)
- [ ] TEST-CONTRACT-EVT-001: CXP traffic events match SPEC-004 packet schema
- [ ] TEST-CONTRACT-EVT-002: Volk lifecycle events include required fields
- [ ] TEST-CONTRACT-EVT-003: Governance decision events include required fields
- [ ] TEST-CONTRACT-EVT-004: Session events include required fields
- [ ] TEST-CONTRACT-EVT-005: Provider events match SPEC-011 event schema
- [ ] TEST-CONTRACT-EVT-006: All events have topic, sequence, timestamp, payload, source
- [ ] TEST-CONTRACT-EVT-007: Timestamps are ISO 8601 format
- [ ] TEST-CONTRACT-EVT-008: Sequence numbers are positive integers
- [ ] TEST-CONTRACT-EVT-009: Source identifiers match registered component names
- [ ] TEST-CONTRACT-EVT-010: Event payloads are JSON-serializable
IComponent Compliance (10 tests)
- [ ] TEST-CONTRACT-COMP-001: IGatewayServer implements initialize()
- [ ] TEST-CONTRACT-COMP-002: IGatewayServer implements start()
- [ ] TEST-CONTRACT-COMP-003: IGatewayServer implements stop()
- [ ] TEST-CONTRACT-COMP-004: IGatewayServer implements get_health()
- [ ] TEST-CONTRACT-COMP-005: get_health returns HealthStatus with correct fields
- [ ] TEST-CONTRACT-COMP-006: Component registered with ComponentType.GATEWAY
- [ ] TEST-CONTRACT-COMP-007: DI container resolves IGatewayServer
- [ ] TEST-CONTRACT-COMP-008: Lifecycle follows: initialize → start → stop
- [ ] TEST-CONTRACT-COMP-009: Double start raises appropriate error
- [ ] TEST-CONTRACT-COMP-010: Stop after stop is idempotent
Performance Tests (60+)
Connection Performance (15 tests)
- [ ] TEST-PERF-CONN-001: Connection accept latency < 50ms p95
- [ ] TEST-PERF-CONN-002: Connection accept latency < 100ms p99
- [ ] TEST-PERF-CONN-003: 100 concurrent connections stable
- [ ] TEST-PERF-CONN-004: Connection accept rate > 50 connections/second
- [ ] TEST-PERF-CONN-005: Memory per connection < 1MB
- [ ] TEST-PERF-CONN-006: Authentication overhead < 20ms p95
- [ ] TEST-PERF-CONN-007: Connection teardown < 10ms p95
- [ ] TEST-PERF-CONN-008: No connection leak after 1000 connect/disconnect cycles
- [ ] TEST-PERF-CONN-009: Server stable under connection churn (rapid connect/disconnect)
- [ ] TEST-PERF-CONN-010: Heartbeat processing overhead < 1ms per client
- [ ] TEST-PERF-CONN-011: TLS handshake overhead < 100ms p95
- [ ] TEST-PERF-CONN-012: Batch auth processing scales linearly
- [ ] TEST-PERF-CONN-013: Client list query < 5ms for 100 clients
- [ ] TEST-PERF-CONN-014: Subscription management < 2ms per subscribe/unsubscribe
- [ ] TEST-PERF-CONN-015: Concurrent auth requests handled without blocking
RPC Performance (15 tests)
- [ ] TEST-PERF-RPC-001: RPC dispatch overhead < 10ms p95
- [ ] TEST-PERF-RPC-002: RPC dispatch overhead < 20ms p99
- [ ] TEST-PERF-RPC-003: 500 RPC requests/second per client sustained
- [ ] TEST-PERF-RPC-004: Batch RPC (10 requests) < 50ms total
- [ ] TEST-PERF-RPC-005: cxp.send round-trip < 50ms p95 (excluding kernel routing)
- [ ] TEST-PERF-RPC-006: session.list response < 20ms for 100 sessions
- [ ] TEST-PERF-RPC-007: volk.list response < 10ms for 50 Volks
- [ ] TEST-PERF-RPC-008: governance.query < 100ms for time-range query
- [ ] TEST-PERF-RPC-009: knowledge.query < 500ms for moderate Cypher query
- [ ] TEST-PERF-RPC-010: gateway.replay < 200ms for 1000 events
- [ ] TEST-PERF-RPC-011: JSON serialization < 1ms for typical response
- [ ] TEST-PERF-RPC-012: Parameter validation < 1ms per request
- [ ] TEST-PERF-RPC-013: PAM++ authorization overhead < 5ms cached
- [ ] TEST-PERF-RPC-014: Error response generation < 1ms
- [ ] TEST-PERF-RPC-015: Method dispatch routing < 0.5ms
Event Broadcast Performance (15 tests)
- [ ] TEST-PERF-BC-001: Event delivery latency < 100ms p95 from kernel event
- [ ] TEST-PERF-BC-002: Event delivery latency < 200ms p99 from kernel event
- [ ] TEST-PERF-BC-003: 10,000 events/second broadcast across all subscribers
- [ ] TEST-PERF-BC-004: 100 subscribers receive event within 200ms
- [ ] TEST-PERF-BC-005: Event serialization overhead < 0.5ms per event
- [ ] TEST-PERF-BC-006: Filter evaluation overhead < 0.1ms per subscription
- [ ] TEST-PERF-BC-007: Ring buffer write < 5ms per event
- [ ] TEST-PERF-BC-008: Ring buffer replay 1000 events < 200ms
- [ ] TEST-PERF-BC-009: Buffer overflow handling < 1ms per dropped event
- [ ] TEST-PERF-BC-010: Sequence number generation < 0.1ms
- [ ] TEST-PERF-BC-011: No CPU spike during sustained broadcast
- [ ] TEST-PERF-BC-012: Memory stable under sustained broadcast (no leaks)
- [ ] TEST-PERF-BC-013: Broadcast scales linearly with subscriber count
- [ ] TEST-PERF-BC-014: Topic-specific broadcast does not scan all subscriptions
- [ ] TEST-PERF-BC-015: Event delivery does not degrade under high RPC load
Health and Metrics Performance (15 tests)
- [ ] TEST-PERF-HM-001: /health response < 10ms
- [ ] TEST-PERF-HM-002: /ready response < 100ms (includes dependency checks)
- [ ] TEST-PERF-HM-003: /metrics response < 50ms
- [ ] TEST-PERF-HM-004: Metrics collection overhead < 1ms per operation
- [ ] TEST-PERF-HM-005: Health checks do not block WebSocket operations
- [ ] TEST-PERF-HM-006: Metrics endpoint handles 100 scrapes/minute
- [ ] TEST-PERF-HM-007: Health endpoint handles 100 checks/minute
- [ ] TEST-PERF-HM-008: Audit logging overhead < 2ms per record
- [ ] TEST-PERF-HM-009: Batch audit write < 20ms for 100 records
- [ ] TEST-PERF-HM-010: Prometheus metric formatting < 10ms for full metric set
- [ ] TEST-PERF-HM-011: Connection count metric updates atomically
- [ ] TEST-PERF-HM-012: Histogram bucket computation < 0.1ms
- [ ] TEST-PERF-HM-013: Metric label cardinality bounded (< 100 unique method labels)
- [ ] TEST-PERF-HM-014: Concurrent health/metrics requests handled without lock contention
- [ ] TEST-PERF-HM-015: Readiness probe fast-fails on first unhealthy dependency
Compliance Tests (11)
- [ ] TEST-COMPLIANCE-001: Article I — Gateway does not interpret or modify agent decisions
- [ ] TEST-COMPLIANCE-002: Article II — All gateway authorization queries Prolog
- [ ] TEST-COMPLIANCE-003: Article III — Gateway respects session isolation
- [ ] TEST-COMPLIANCE-004: Article IV — Gateway provides hook extension points
- [ ] TEST-COMPLIANCE-005: Article V — Gateway is an extension, not core kernel
- [ ] TEST-COMPLIANCE-006: Article VI — Python 3.14t async/await throughout
- [ ] TEST-COMPLIANCE-007: Article VII — No mocks in gateway tests
- [ ] TEST-COMPLIANCE-008: Article VIII — Full metrics and observability
- [ ] TEST-COMPLIANCE-009: Article IX — Graceful degradation on dependency failure
- [ ] TEST-COMPLIANCE-010: Article X — Gateway protocol versioned
- [ ] TEST-COMPLIANCE-011: Article XI — Documentation precedes implementation
Failure Scenario Tests (40+)
Connection Failures (10 tests)
- [ ] TEST-FAIL-CONN-001: Server handles client TCP reset gracefully
- [ ] TEST-FAIL-CONN-002: Server handles client sending invalid WebSocket frames
- [ ] TEST-FAIL-CONN-003: Server handles client sending binary (non-text) frames
- [ ] TEST-FAIL-CONN-004: Server handles max_clients rejection gracefully
- [ ] TEST-FAIL-CONN-005: Server handles rapid connect/disconnect flooding
- [ ] TEST-FAIL-CONN-006: Server handles client that never authenticates
- [ ] TEST-FAIL-CONN-007: Server handles client that sends > max_message_size
- [ ] TEST-FAIL-CONN-008: Server handles WebSocket protocol violation
- [ ] TEST-FAIL-CONN-009: Server handles half-open TCP connections
- [ ] TEST-FAIL-CONN-010: Server handles SIGTERM during active connections
Dependency Failures (15 tests)
- [ ] TEST-FAIL-DEP-001: Redis unavailable: auth falls back to denial
- [ ] TEST-FAIL-DEP-002: Redis unavailable: ring buffer writes deferred
- [ ] TEST-FAIL-DEP-003: Redis unavailable: client sessions tracked in-memory
- [ ] TEST-FAIL-DEP-004: Redis reconnection after transient failure
- [ ] TEST-FAIL-DEP-005: Neo4j unavailable: audit logging deferred
- [ ] TEST-FAIL-DEP-006: Neo4j unavailable: KG queries return service unavailable error
- [ ] TEST-FAIL-DEP-007: Neo4j reconnection after transient failure
- [ ] TEST-FAIL-DEP-008: Prolog unavailable: governance uses cached decisions
- [ ] TEST-FAIL-DEP-009: Prolog unavailable: uncached governance defaults to deny
- [ ] TEST-FAIL-DEP-010: Prolog reconnection after transient failure
- [ ] TEST-FAIL-DEP-011: Kernel EventBus error does not crash gateway
- [ ] TEST-FAIL-DEP-012: Kernel restart: gateway re-subscribes to EventBus
- [ ] TEST-FAIL-DEP-013: All dependencies down: gateway serves health=unhealthy
- [ ] TEST-FAIL-DEP-014: Partial dependency recovery reflected in /ready
- [ ] TEST-FAIL-DEP-015: Dependency failure logged with context
Protocol Failures (10 tests)
- [ ] TEST-FAIL-PROTO-001: Invalid JSON message handled with parse error
- [ ] TEST-FAIL-PROTO-002: Valid JSON but invalid JSON-RPC handled
- [ ] TEST-FAIL-PROTO-003: RPC handler exception returns internal error
- [ ] TEST-FAIL-PROTO-004: Handler timeout returns timeout error
- [ ] TEST-FAIL-PROTO-005: Recursive RPC call (handler calls another RPC) works
- [ ] TEST-FAIL-PROTO-006: Empty message body handled gracefully
- [ ] TEST-FAIL-PROTO-007: Extremely large params object handled
- [ ] TEST-FAIL-PROTO-008: Unicode in method names and params handled
- [ ] TEST-FAIL-PROTO-009: Null params field handled (treated as empty)
- [ ] TEST-FAIL-PROTO-010: Concurrent requests from same client serialized correctly
Resource Exhaustion (5 tests)
- [ ] TEST-FAIL-RES-001: Memory pressure: event buffers trimmed
- [ ] TEST-FAIL-RES-002: CPU pressure: rate limiting applied automatically
- [ ] TEST-FAIL-RES-003: File descriptor exhaustion: new connections rejected gracefully
- [ ] TEST-FAIL-RES-004: Redis memory limit: ring buffer writes fail gracefully
- [ ] TEST-FAIL-RES-005: Sustained overload: gateway remains responsive for health checks
Summary Statistics
| Category | Test Count | Completed | Percentage |
|---|---|---|---|
| Unit Tests | 120 | 0 | 0% |
| Integration Tests | 100 | 0 | 0% |
| Contract Tests | 30 | 0 | 0% |
| Performance Tests | 60 | 0 | 0% |
| Compliance Tests | 11 | 0 | 0% |
| Failure Scenario Tests | 40 | 0 | 0% |
| TOTAL | 361 | 0 | 0% |
Last Updated: 2026-03-27 Version: 1.0.0 Maintained By: Architecture Team
Other tracked files
specs/014-websocket-gateway/compliance-audit.mdspecs/014-websocket-gateway/features/mcp_gateway_transport.feature
Full spec text
Verbatim from specs/014-websocket-gateway/spec.md; headings are pushed down two levels.
SPEC-014: WebSocket Gateway
Metadata
- Spec ID: 014-websocket-gateway
- Title: WebSocket Gateway
- Author: Mohamed
- Status: Implemented
- Created: 2026-03-27
- Last Updated: 2026-03-28
- Priority: P1
- Version: 1.0.0
- Extends: (none)
Overview
What
The WebSocket Gateway is the real-time control plane for Orchestrata. It exposes a bidirectional WebSocket server that allows external clients (web dashboards, CLI tools, mobile apps, external integrations) to observe and control the orchestration system in real-time. Clients can subscribe to CXP traffic, monitor Volk status, inspect governance decisions, query session state, and issue commands to the kernel — all through a structured RPC protocol over WebSocket.
Why
- Orchestrata currently has no external-facing real-time interface — the kernel, postman, and orchestrator communicate internally but are invisible from outside
- Observability through CLI logs is insufficient for a system with 8 agents, Prolog governance, dual storage, and complex session state
- No way for external systems (dashboards, monitoring tools, CI/CD) to integrate with the orchestration layer
- No mechanism for remote control — starting sessions, dispatching CXP packets, or triggering Volk actions from outside the process
- OpenClaw's WebSocket gateway pattern demonstrates the value of a unified real-time control plane for multi-agent systems
How
- IGatewayServer interface registered in DI container as ComponentType.GATEWAY
- WebSocket server on configurable port (default: 18790) using the
websocketslibrary - Token-based authentication with configurable auth strategies (static token, HMAC, PAM++ policy)
- JSON-RPC 2.0 message protocol for request/response and server-push notifications
- Pub/sub subscription model for real-time event streams (CXP traffic, Volk lifecycle, governance decisions)
- RPCDispatcher routes method calls to registered handlers with PAM++ authorization
- Gateway sessions track connected clients with heartbeat and presence
- All gateway operations logged to audit trail via Neo4j
User Scenarios
US-001: Real-Time CXP Traffic Observation (P1)
As a developer or monitoring dashboard I want to subscribe to live CXP packet flow between Volks So that I can observe agent communication in real-time
Acceptance Criteria:
- [ ] Client subscribes to CXP traffic stream via
cxp.subscribeRPC method - [ ] Server pushes CXP packets as they flow through the kernel
- [ ] Subscriptions support filtering by: volk_id, thread_id, subject pattern, delivery_status
- [ ] Client can unsubscribe at any time via
cxp.unsubscribe - [ ] Packet payloads are optionally truncated for bandwidth (configurable max_payload_size)
US-002: Volk Status Monitoring (P1)
As a system operator I want to see real-time status of all registered Volks So that I can detect failures and monitor agent health
Acceptance Criteria:
- [ ] Client calls
volk.listto get all registered Volks with current status - [ ] Client subscribes to
volk.lifecyclefor registration, deregistration, health change events - [ ] Each Volk status includes: alias, capabilities, health, active_tasks, last_activity
- [ ] Status updates pushed within 500ms of state change
- [ ] Client can query individual Volk detail via
volk.get
US-003: Governance Decision Stream (P1)
As a compliance auditor or developer I want to observe PAM++ governance decisions in real-time So that I can verify policy enforcement and debug authorization issues
Acceptance Criteria:
- [ ] Client subscribes to
governance.decisionsstream - [ ] Each decision includes: volk_id, action, resource, result (allow/deny), prolog_query, latency_ms
- [ ] Escalation events included in the stream with full escalation path
- [ ] Constitutional article violations highlighted with article reference
- [ ] Historical decisions queryable via
governance.querywith time range
US-004: Session State Inspection (P1)
As a developer I want to inspect active session state and context So that I can debug session issues and verify state persistence
Acceptance Criteria:
- [ ] Client calls
session.listto see all active sessions - [ ] Client calls
session.getwith session_id for full state including context, facts, carryover - [ ] Client subscribes to
session.eventsfor open, close, recovery, context_update events - [ ] Session fact stream available via
session.facts.subscribe - [ ] Portfolio statistics queryable via
session.portfolio.stats
US-005: Remote Command Execution (P1)
As a system operator or external integration I want to issue commands to the orchestration system remotely So that I can control agent workflows without direct process access
Acceptance Criteria:
- [ ] Client sends CXP packets via
cxp.sendRPC method - [ ] Client can open/close sessions via
session.openandsession.close - [ ] Client can register/deregister Volks via
volk.registerandvolk.deregister - [ ] All commands validated against PAM++ governance before execution
- [ ] Command responses include execution result and any governance decisions
US-006: Gateway Authentication (P1)
As a security administrator I want to authenticate gateway clients before granting access So that unauthorized clients cannot observe or control the system
Acceptance Criteria:
- [ ] Client authenticates on connection via
auth.authenticatewith token - [ ] Static token auth supported for development (configurable in gateway config)
- [ ] HMAC-based auth supported for production (shared secret + timestamp + nonce)
- [ ] PAM++ policy-based auth supported for fine-grained access control
- [ ] Unauthenticated clients disconnected after configurable grace period (default: 5s)
- [ ] Authentication events logged to audit trail
US-007: Client Presence and Heartbeat (P2)
As the gateway server I want to track connected client health via heartbeat So that stale connections are cleaned up and presence is accurate
Acceptance Criteria:
- [ ] Server sends ping every configurable interval (default: 30s)
- [ ] Client must respond with pong within configurable timeout (default: 10s)
- [ ] Failed heartbeat disconnects client and cleans up subscriptions
- [ ] Connected client list queryable via
gateway.clients - [ ] Client presence events pushed to
gateway.presencesubscribers
US-008: Event Replay and History (P2)
As a developer debugging an issue I want to replay recent events from before I connected So that I can see what happened leading up to the current state
Acceptance Criteria:
- [ ] Gateway maintains configurable event ring buffer (default: 10,000 events)
- [ ] Client requests replay via
gateway.replaywith time range or event count - [ ] Replay delivers events in chronological order
- [ ] Replay respects the same subscription filters as live streams
- [ ] Ring buffer stored in Redis for persistence across gateway restarts
US-009: Metrics and Health Endpoint (P2)
As a monitoring system (Prometheus, Grafana) I want to scrape gateway health and connection metrics So that I can monitor gateway availability and load
Acceptance Criteria:
- [ ] HTTP health endpoint at
/healthreturns gateway status - [ ] HTTP metrics endpoint at
/metricsreturns Prometheus-formatted metrics - [ ] Metrics include: connected_clients, active_subscriptions, messages_per_second, rpc_latency_p95
- [ ] Health endpoint returns degraded status when dependencies are unhealthy
- [ ] Readiness probe at
/readyfor Kubernetes integration
US-010: Knowledge Graph Live Query (P2)
As a developer or dashboard I want to query the knowledge graph through the gateway So that I can explore the graph without direct Neo4j access
Acceptance Criteria:
- [ ] Client calls
knowledge.querywith Cypher query string - [ ] Queries are validated and sanitized (read-only, no mutations)
- [ ] Query results returned as JSON-serializable node/relationship structures
- [ ] Query timeout enforced (configurable, default: 10s)
- [ ] PAM++ governance controls which clients can query which graph segments
Functional Requirements
Core Gateway
FR-001: IGatewayServer Interface (P1)
- System SHALL define IGatewayServer as an abstract base class in orchestrata-core interfaces
- System SHALL register IGatewayServer with ComponentType.GATEWAY in DI container
- System SHALL implement IComponent lifecycle (initialize, start, stop, get_health)
- System SHALL accept GatewayConfig with: host, port, auth_strategy, max_clients, heartbeat_interval
FR-002: WebSocket Server (P1)
- System SHALL start WebSocket server on configurable host:port (default: 0.0.0.0:18790)
- System SHALL accept concurrent client connections up to configurable max_clients (default: 100)
- System SHALL handle connection lifecycle: open, message, close, error
- System SHALL use TLS when certificate and key paths are configured
- System SHALL gracefully shut down on SIGTERM, closing all client connections
FR-003: JSON-RPC Protocol (P1)
- System SHALL use JSON-RPC 2.0 as the message protocol
- System SHALL support request/response (id + method + params → id + result/error)
- System SHALL support server-push notifications (method + params, no id)
- System SHALL reject malformed messages with JSON-RPC error codes
- System SHALL support batch requests (array of JSON-RPC messages)
FR-004: RPC Method Dispatch (P1)
- System SHALL maintain a registry of RPC method handlers
- System SHALL dispatch incoming method calls to registered handlers
- System SHALL validate method parameters against registered schemas
- System SHALL enforce PAM++ authorization before executing handlers
- System SHALL return structured errors for: method not found, invalid params, unauthorized, internal error
Authentication
FR-005: Authentication Framework (P1)
- System SHALL require authentication before processing any RPC method (except auth.authenticate)
- System SHALL support pluggable auth strategies via IAuthStrategy protocol
- System SHALL ship three auth strategies: StaticTokenAuth, HMACAuth, PrologPolicyAuth
- System SHALL disconnect clients that fail authentication
- System SHALL log all authentication attempts (success and failure) to audit trail
FR-006: Static Token Auth (P1)
- System SHALL accept a pre-shared token configured in gateway config or environment variable
- System SHALL compare client-provided token using constant-time comparison
- System SHALL reject blank or missing tokens
- System SHALL support token rotation without gateway restart (Redis-backed)
FR-007: HMAC Auth (P2)
- System SHALL validate HMAC signature: HMAC-SHA256(shared_secret, timestamp + nonce + client_id)
- System SHALL reject requests with timestamp drift > configurable window (default: 60s)
- System SHALL reject replayed nonces within the drift window (nonce stored in Redis with TTL)
- System SHALL support multiple shared secrets for key rotation
FR-008: PAM++ Policy Auth (P2)
- System SHALL query Prolog for
gateway_access(ClientId, Scope)on authentication - System SHALL support scoped access: read_only, read_write, admin
- System SHALL cache auth decisions in Redis with configurable TTL (default: 300s)
- System SHALL invalidate cached decisions on policy rule changes
Pub/Sub Event Streams
FR-009: Subscription Management (P1)
- System SHALL support topic-based pub/sub subscriptions
- System SHALL support subscription filters (key-value predicates on event fields)
- System SHALL track subscriptions per client connection
- System SHALL clean up subscriptions on client disconnect
- System SHALL enforce maximum subscriptions per client (configurable, default: 50)
FR-010: Event Topics (P1)
- System SHALL define the following event topics:
cxp.traffic— CXP packets flowing through kernelvolk.lifecycle— Volk registration, deregistration, health changesgovernance.decisions— PAM++ allow/deny decisions and escalationssession.events— Session open, close, recovery, context updatessession.facts— Fact emission eventsprovider.events— Provider request completion, fallback, budget (SPEC-011)kernel.events— Kernel-level system events (startup, shutdown, errors)gateway.presence— Client connect/disconnect events
- System SHALL push events to subscribed clients within 100ms of occurrence
FR-011: Event Delivery (P1)
- System SHALL deliver events asynchronously without blocking the kernel event bus
- System SHALL buffer events per client when the WebSocket send buffer is full (configurable buffer: 1000 events)
- System SHALL drop oldest events when buffer overflows and notify client of gap
- System SHALL include sequence numbers on events for gap detection
- System SHALL support backpressure signaling from client to server
Event History
FR-012: Event Ring Buffer (P2)
- System SHALL maintain a ring buffer of recent events in Redis (configurable size, default: 10,000)
- System SHALL store events as Redis sorted set with timestamp score
- System SHALL support replay queries by time range or count
- System SHALL apply subscription filters to replay results
- System SHALL expire events older than configurable TTL (default: 24h)
Gateway Sessions
FR-013: Client Session Tracking (P1)
- System SHALL assign a unique gateway_session_id to each connected client
- System SHALL track per-client: connected_at, last_activity, subscriptions, auth_scope, client_metadata
- System SHALL support client-provided metadata on connection (client_name, client_version, purpose)
- System SHALL expose connected client list via
gateway.clientsRPC method
FR-014: Heartbeat (P2)
- System SHALL send WebSocket ping frames at configurable interval (default: 30s)
- System SHALL disconnect clients that miss configurable consecutive pongs (default: 3)
- System SHALL update last_activity on any client message (not just pong)
- System SHALL emit
gateway.presenceevent on client timeout disconnect
RPC Methods
FR-015: CXP Methods (P1)
- System SHALL implement
cxp.send— Send CXP packet through the kernel (PAM++ authorized) - System SHALL implement
cxp.subscribe— Subscribe to CXP traffic with optional filters - System SHALL implement
cxp.unsubscribe— Unsubscribe from CXP traffic - System SHALL implement
cxp.status— Query delivery status of a CXP packet by thread_id - System SHALL validate CXP packets against SPEC-004 schema before dispatch
FR-016: Volk Methods (P1)
- System SHALL implement
volk.list— List all registered Volks with status - System SHALL implement
volk.get— Get detailed Volk information by alias - System SHALL implement
volk.register— Register a new Volk (admin scope required) - System SHALL implement
volk.deregister— Deregister a Volk (admin scope required) - System SHALL implement
volk.lifecycle— Subscribe to Volk lifecycle events
FR-017: Session Methods (P1)
- System SHALL implement
session.list— List active sessions - System SHALL implement
session.get— Get session state by ID (context, facts, carryover) - System SHALL implement
session.open— Open a new session (PAM++ authorized) - System SHALL implement
session.close— Close a session (PAM++ authorized) - System SHALL implement
session.events— Subscribe to session lifecycle events - System SHALL implement
session.facts.subscribe— Subscribe to fact emission events
FR-018: Governance Methods (P1)
- System SHALL implement
governance.decisions— Subscribe to governance decision stream - System SHALL implement
governance.query— Query historical decisions with filters - System SHALL implement
governance.evaluate— Dry-run a governance check (read-only, no side effects) - System SHALL implement
governance.rules— List active Prolog governance rules (admin scope)
FR-019: Knowledge Graph Methods (P2)
- System SHALL implement
knowledge.query— Execute read-only Cypher query - System SHALL implement
knowledge.nodes— List nodes by type with pagination - System SHALL implement
knowledge.relationships— List relationships by type - System SHALL sanitize all Cypher queries to prevent mutations (reject MERGE, CREATE, DELETE, SET, REMOVE)
- System SHALL enforce query timeout (configurable, default: 10s)
FR-020: Gateway Methods (P1)
- System SHALL implement
gateway.clients— List connected clients - System SHALL implement
gateway.replay— Replay recent events from ring buffer - System SHALL implement
gateway.ping— Application-level ping for latency measurement - System SHALL implement
gateway.info— Return gateway version, uptime, capabilities
Observability
FR-021: HTTP Health Endpoints (P2)
- System SHALL serve HTTP endpoints alongside the WebSocket server
- System SHALL implement
/health— Returns gateway health status (200 OK or 503 Service Unavailable) - System SHALL implement
/ready— Returns readiness status (dependent services checked) - System SHALL implement
/metrics— Returns Prometheus-formatted metrics - System SHALL check Redis, Neo4j, Prolog, and kernel health for readiness
FR-022: Gateway Metrics (P2)
- System SHALL track: connected_clients (gauge), total_connections (counter), messages_received (counter), messages_sent (counter)
- System SHALL track: rpc_latency_seconds (histogram by method), subscription_count (gauge by topic)
- System SHALL track: auth_success (counter), auth_failure (counter), events_dropped (counter)
- System SHALL track: replay_requests (counter), knowledge_queries (counter)
Governance
FR-023: PAM++ Gateway Predicates (P1)
- System SHALL extend PAM++ with gateway-specific Prolog predicates:
gateway_access(ClientId, Scope)— Client access levelgateway_can_execute(ClientId, Method)— Per-method authorizationgateway_can_subscribe(ClientId, Topic)— Topic subscription authorizationgateway_can_query_kg(ClientId, QueryPattern)— Knowledge graph query authorization
- System SHALL log all gateway governance decisions to audit trail
FR-024: Audit Trail (P1)
- System SHALL record all RPC method calls with: timestamp, client_id, method, params_hash, result_status, latency_ms
- System SHALL record all authentication events with: timestamp, client_id, auth_strategy, result, ip_address
- System SHALL record all subscription events with: timestamp, client_id, topic, action (subscribe/unsubscribe)
- System SHALL store audit records in Neo4j (:GatewayAudit) nodes
Non-Functional Requirements
Performance
NFR-001: Connection Handling
- WebSocket connection accept: < 50ms (P95)
- RPC method dispatch: < 10ms overhead (P95, excluding handler execution)
- Event delivery to subscribers: < 100ms from kernel event (P95)
- Maximum concurrent clients: 100 (configurable)
NFR-002: Throughput
- Event broadcast: 10,000 events/second across all subscribers
- RPC requests: 500 requests/second per client
- Event ring buffer write: < 5ms per event
- Replay delivery: 1,000 events/second
Reliability
NFR-003: Availability
- Gateway available when kernel is running
- Graceful degradation: Continue serving cached data when Neo4j unavailable
- Automatic reconnection to Redis on disconnect
- Zero event loss for connected clients (within buffer limits)
NFR-004: Data Integrity
- Event sequence numbers monotonically increasing per topic
- No duplicate events delivered to a single client
- Audit trail records immutable after write
- Authentication tokens never logged in plaintext
Security
NFR-005: Transport Security
- TLS 1.2+ enforced when certificates configured
- WebSocket origin validation configurable
- Rate limiting per client IP (configurable, default: 100 connections/minute)
- Maximum message size enforced (configurable, default: 1MB)
NFR-006: Access Control
- All methods require authentication (except auth.authenticate)
- Scoped access prevents read_only clients from executing commands
- Knowledge graph queries restricted to read-only operations
- Admin methods require explicit admin scope
Technical Design
Architecture
┌────────────────────────────────────────────────────────────────┐
│ WebSocket Gateway (U:GW) │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ WebSocket │ │ JSON-RPC │ │ Auth │ │
│ │ Server │──│ Dispatcher │──│ Framework │ │
│ │ (websockets) │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Client │ │ RPC │ │ Subscription│ │
│ │ Sessions │ │ Handlers │ │ Manager │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Kernel EventBus Integration │ │
│ │ (subscribes to kernel events, pushes to clients) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Redis │ │ Neo4j │ │ Prolog │ │
│ │ (ring buf, │ │ (audit, │ │ (PAM++ │ │
│ │ auth cache) │ │ history) │ │ gateway) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────────┘
Key Interfaces
class IGatewayServer(IComponent, ABC):
"""WebSocket gateway control plane."""
@abstractmethod
async def start_serving(self) -> None:
"""Start the WebSocket server and begin accepting connections."""
@abstractmethod
async def stop_serving(self) -> None:
"""Gracefully stop the server, closing all client connections."""
@abstractmethod
async def broadcast(
self,
topic: str,
event: GatewayEvent,
) -> int:
"""Broadcast event to all subscribers of a topic. Returns delivery count."""
@abstractmethod
async def send_to_client(
self,
client_id: str,
message: dict,
) -> bool:
"""Send a message to a specific client. Returns True if delivered."""
@abstractmethod
def get_connected_clients(self) -> list[GatewayClientInfo]:
"""Return list of connected clients with metadata."""
@abstractmethod
def get_subscription_count(self, topic: str) -> int:
"""Return number of active subscriptions for a topic."""
@abstractmethod
async def replay_events(
self,
*,
topic: str | None = None,
since: datetime | None = None,
count: int | None = None,
filters: dict | None = None,
) -> list[GatewayEvent]:
"""Replay events from the ring buffer."""
class IAuthStrategy(Protocol):
"""Protocol for gateway authentication strategies."""
async def authenticate(
self,
credentials: dict,
) -> AuthResult:
"""Authenticate a client. Returns AuthResult with scope and client_id."""
def get_strategy_name(self) -> str:
"""Return the name of this auth strategy."""
class GatewayEvent:
topic: str
sequence: int
timestamp: datetime
payload: dict
source: str
class GatewayClientInfo:
client_id: str
gateway_session_id: str
connected_at: datetime
last_activity: datetime
auth_scope: str
subscriptions: list[str]
client_metadata: dict
class AuthResult:
authenticated: bool
client_id: str
scope: str # "read_only" | "read_write" | "admin"
expires_at: datetime | None
metadata: dict
class GatewayConfig:
host: str = "0.0.0.0"
port: int = 18790
auth_strategy: str = "static_token" # "static_token" | "hmac" | "prolog_policy"
static_token: str | None = None
hmac_secret: str | None = None
max_clients: int = 100
heartbeat_interval_seconds: float = 30.0
heartbeat_timeout_seconds: float = 10.0
heartbeat_max_misses: int = 3
max_subscriptions_per_client: int = 50
event_buffer_per_client: int = 1000
ring_buffer_size: int = 10000
ring_buffer_ttl_seconds: int = 86400
max_message_size_bytes: int = 1_048_576
tls_cert_path: str | None = None
tls_key_path: str | None = None
JSON-RPC Message Format
Request:
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "cxp.subscribe",
"params": {
"filters": {"volk_id": "U:Cd", "delivery_status": "delivered"}
}
}
Response:
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"subscription_id": "sub-abc123",
"topic": "cxp.traffic",
"filters": {"volk_id": "U:Cd", "delivery_status": "delivered"}
}
}
Server Push (notification):
{
"jsonrpc": "2.0",
"method": "cxp.traffic",
"params": {
"sequence": 42,
"timestamp": "2026-03-27T14:30:22Z",
"payload": {
"to": "U:Cd",
"from": "U:Ox",
"thread_id": "thread-001",
"subject": "code_generation_request",
"delivery_status": "delivered"
}
}
}
Redis State Persistence
Client sessions:
orchestrata:gateway:client:{client_id} — HASH {connected_at, auth_scope, client_metadata}
orchestrata:gateway:clients — SET of client_ids
TTL: None (cleaned on disconnect).
Event ring buffer:
orchestrata:gateway:events:{topic} — ZSET (score=timestamp, member=event_json)
orchestrata:gateway:events:sequence:{topic} — STRING (int, monotonic counter)
TTL: Configurable (default: 86400s).
Auth nonce tracking (HMAC):
orchestrata:gateway:nonce:{nonce} — STRING ("used")
TTL: Matches drift window (default: 60s).
Auth decision cache (Prolog policy):
orchestrata:gateway:auth:{client_id}:{scope} — STRING ("allow" | "deny")
TTL: Configurable (default: 300s).
Neo4j Audit Schema
Nodes:
(:GatewayAudit {audit_id, client_id, method, params_hash, result_status, latency_ms, timestamp})(:GatewayAuth {auth_id, client_id, auth_strategy, result, ip_address, timestamp})
Relationships:
(:GatewayAudit)-[:FROM_CLIENT]->(:GatewayClient)(:GatewayAuth)-[:FOR_CLIENT]->(:GatewayClient)(:GatewayAudit)-[:DURING]->(:Session)
Prolog Governance Predicates
%% Gateway access control
gateway_access(ClientId, admin) :-
registered_admin(ClientId).
gateway_access(ClientId, read_write) :-
registered_operator(ClientId),
\+ suspended(ClientId).
gateway_access(ClientId, read_only) :-
registered_client(ClientId),
\+ suspended(ClientId).
%% Per-method authorization
gateway_can_execute(ClientId, Method) :-
gateway_access(ClientId, Scope),
method_requires_scope(Method, RequiredScope),
scope_sufficient(Scope, RequiredScope).
scope_sufficient(admin, _).
scope_sufficient(read_write, read_write).
scope_sufficient(read_write, read_only).
scope_sufficient(read_only, read_only).
%% Method scope requirements
method_requires_scope('cxp.send', read_write).
method_requires_scope('cxp.subscribe', read_only).
method_requires_scope('session.open', read_write).
method_requires_scope('session.close', read_write).
method_requires_scope('volk.register', admin).
method_requires_scope('volk.deregister', admin).
method_requires_scope('governance.rules', admin).
method_requires_scope(_, read_only). % default
%% Topic subscription authorization
gateway_can_subscribe(ClientId, Topic) :-
gateway_access(ClientId, Scope),
topic_requires_scope(Topic, RequiredScope),
scope_sufficient(Scope, RequiredScope).
topic_requires_scope('governance.decisions', read_write).
topic_requires_scope('kernel.events', read_write).
topic_requires_scope(_, read_only). % default
Kernel EventBus Integration
The gateway subscribes to kernel events during initialize() and bridges them to WebSocket clients:
# During initialize()
await kernel.event_bus.subscribe(
"cxp.*",
self._on_cxp_event,
subscriber_id="SYS:GATEWAY",
)
await kernel.event_bus.subscribe(
"volk.lifecycle.*",
self._on_volk_event,
subscriber_id="SYS:GATEWAY",
)
await kernel.event_bus.subscribe(
"governance.*",
self._on_governance_event,
subscriber_id="SYS:GATEWAY",
)
await kernel.event_bus.subscribe(
"session.*",
self._on_session_event,
subscriber_id="SYS:GATEWAY",
)
await kernel.event_bus.subscribe(
"provider.*",
self._on_provider_event,
subscriber_id="SYS:GATEWAY",
)
Configuration
# configs/monolithic.yaml
gateway:
enabled: true
host: "0.0.0.0"
port: 18790
auth_strategy: "static_token"
static_token: «redacted»
max_clients: 100
heartbeat_interval_seconds: 30
heartbeat_timeout_seconds: 10
heartbeat_max_misses: 3
max_subscriptions_per_client: 50
event_buffer_per_client: 1000
ring_buffer_size: 10000
ring_buffer_ttl_seconds: 86400
max_message_size_bytes: 1048576
tls:
enabled: false
cert_path: null
key_path: null
http:
health_enabled: true
metrics_enabled: true
metrics_port: 9090
Integration Points
| Component | Integration |
|---|---|
| orchestrata-core | IGatewayServer interface, ComponentType.GATEWAY |
| orchestrata-kernel | EventBus subscription for all system events |
| orchestrata-cxp | CXP packet validation and dispatch |
| orchestrata-session | Session state queries and lifecycle commands |
| orchestrata-governance | PAM++ authorization for all gateway operations |
| orchestrata-knowledge | Read-only Cypher query execution |
| orchestrata-provider | Provider event forwarding (SPEC-011) |
| orchestrata-di | DI registration and dependency resolution |
| configs/monolithic.yaml | Gateway configuration source |
Integration Points
orchestrata-core
- IGatewayServer interface registration
- ComponentType.GATEWAY lifecycle management
- IComponent protocol implementation (initialize, start, stop, get_health)
orchestrata-kernel
- EventBus subscription for all system events (CXP, Volk, Session, Provider, Governance, Kernel)
- Real-time event forwarding to connected WebSocket clients
- Event filtering based on client subscriptions
orchestrata-cxp
- CXP packet validation against SPEC-004 schema
- CXP packet dispatch via Postman
- Delivery status tracking and reporting
orchestrata-session
- Session state queries and management
- Session lifecycle event subscription
- Portfolio statistics reporting
orchestrata-governance
- PAM++ authorization before all RPC operations
- Governance decision logging to audit trail
- Dry-run governance evaluation support
orchestrata-knowledge
- Read-only Cypher query execution
- Knowledge graph exploration without direct Neo4j access
- Query sanitization to prevent mutations
orchestrata-provider
- LLM provider event forwarding (SPEC-011)
- Provider lifecycle and error events
- Budget and fallback events
Redis
- Event ring buffer for event history
- Client session state persistence
- Authentication cache (nonce tracking, auth decision cache)
- Rate limiting counters
Neo4j
- Audit trail storage (:GatewayAudit, :GatewayAuth nodes)
- Knowledge graph queries
- Historical governance decision queries
Prolog Engine
- PAM++ policy evaluation
- Gateway access control rules
- Governance decision logic
Success Criteria
- Server Running: WebSocket gateway starts and accepts connections on configured port
- Authentication: Clients authenticate before accessing any RPC method
- Real-Time Events: CXP traffic, Volk lifecycle, and governance decisions streamed to subscribers within 100ms
- Remote Control: Clients can send CXP packets and manage sessions through the gateway
- Governance: All gateway operations authorized via PAM++ before execution
- Observability: Health, readiness, and Prometheus metrics endpoints operational
- Resilience: Gateway handles client disconnects, buffer overflows, and dependency failures gracefully
- Audit: All operations recorded in Neo4j audit trail
- Performance: < 10ms RPC overhead, 10,000 events/second broadcast capacity
Dependencies
- Python 3.14t
- websockets (async WebSocket server)
- orchestrata-core (IComponent, ComponentType, interfaces)
- orchestrata-kernel (EventBus, Volk registry, routing)
- orchestrata-cxp (CXP packet validation and schema)
- orchestrata-session (session state queries, lifecycle)
- orchestrata-governance (PAM++ policy engine)
- orchestrata-knowledge (Neo4j read-only queries)
- orchestrata-di (dependency injection container)
- Redis (ring buffer, auth cache, client sessions)
- Neo4j (audit trail)
- configs/monolithic.yaml (gateway configuration)
Terminology
- Gateway: The WebSocket Gateway component (U:GW) that serves as the real-time control plane for Orchestrata
- Client: Any external system (dashboard, CLI, mobile app) that connects to the gateway via WebSocket
- RPC Method: A JSON-RPC 2.0 method exposed by the gateway for client invocation
- Subscription: A persistent event stream from the gateway to a client, filtered by topic and optional criteria
- Topic: A named event channel (e.g.,
cxp.traffic,volk.lifecycle) that clients subscribe to - Ring Buffer: A Redis-backed circular buffer that stores recent events for replay
- Scope: An access level granted during authentication —
read_only,read_write, oradmin - Gateway Session: A server-side representation of a connected client, distinct from an orchestration session
- Heartbeat: A WebSocket ping/pong mechanism to detect stale connections
- Server Push: A JSON-RPC 2.0 notification (no
id) sent from gateway to client without a request - Auth Strategy: A pluggable authentication mechanism (static token, HMAC, PAM++ policy)
- Event Replay: The ability to retrieve historical events from the ring buffer after connecting
Data Models
JSON-RPC Request Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GatewayRPCRequest",
"type": "object",
"required": ["jsonrpc", "method"],
"properties": {
"jsonrpc": {
"type": "string",
"const": "2.0"
},
"id": {
"oneOf": [
{"type": "string"},
{"type": "integer"},
{"type": "null"}
],
"description": "Request identifier. Omit or null for notifications."
},
"method": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$",
"description": "Namespaced method name (e.g., cxp.subscribe, session.open)."
},
"params": {
"oneOf": [
{"type": "object"},
{"type": "array"},
{"type": "null"}
],
"description": "Method parameters. Named (object) preferred over positional (array)."
}
},
"additionalProperties": false
}
JSON-RPC Response Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GatewayRPCResponse",
"type": "object",
"required": ["jsonrpc", "id"],
"properties": {
"jsonrpc": {
"type": "string",
"const": "2.0"
},
"id": {
"oneOf": [
{"type": "string"},
{"type": "integer"},
{"type": "null"}
]
},
"result": {
"description": "Present on success. Absent on error."
},
"error": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": {"type": "integer"},
"message": {"type": "string"},
"data": {"description": "Optional structured error details."}
}
}
},
"additionalProperties": false
}
GatewayEvent Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GatewayEvent",
"type": "object",
"required": ["topic", "sequence", "timestamp", "payload", "source"],
"properties": {
"topic": {
"type": "string",
"description": "Event topic (e.g., cxp.traffic, volk.lifecycle)."
},
"sequence": {
"type": "integer",
"minimum": 0,
"description": "Monotonically increasing sequence number per topic."
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp of event occurrence."
},
"payload": {
"type": "object",
"description": "Event-specific payload."
},
"source": {
"type": "string",
"description": "Component that generated this event."
}
}
}
auth.authenticate Params Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AuthenticateParams",
"type": "object",
"required": ["strategy"],
"properties": {
"strategy": {
"type": "string",
"enum": ["static_token", "hmac", "prolog_policy"]
},
"token": {
"type": "string",
"description": "Required for static_token strategy."
},
"client_id": {
"type": "string",
"description": "Required for hmac and prolog_policy strategies."
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "Required for hmac strategy."
},
"nonce": {
"type": "string",
"description": "Required for hmac strategy."
},
"signature": {
"type": "string",
"description": "HMAC-SHA256 signature. Required for hmac strategy."
},
"client_metadata": {
"type": "object",
"properties": {
"client_name": {"type": "string"},
"client_version": {"type": "string"},
"purpose": {"type": "string"}
}
}
}
}
auth.authenticate Result Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AuthenticateResult",
"type": "object",
"required": ["authenticated", "client_id", "scope"],
"properties": {
"authenticated": {"type": "boolean"},
"client_id": {"type": "string"},
"scope": {
"type": "string",
"enum": ["read_only", "read_write", "admin"]
},
"expires_at": {
"type": ["string", "null"],
"format": "date-time"
},
"gateway_version": {"type": "string"},
"capabilities": {
"type": "array",
"items": {"type": "string"}
}
}
}
cxp.subscribe Params Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "CXPSubscribeParams",
"type": "object",
"properties": {
"filters": {
"type": "object",
"properties": {
"volk_id": {"type": "string", "pattern": "^U:[A-Z][a-z]$"},
"thread_id": {"type": "string", "format": "uuid"},
"subject": {"type": "string", "description": "Glob pattern match."},
"delivery_status": {
"type": "string",
"enum": ["queued", "delivered", "acknowledged", "failed"]
}
}
},
"max_payload_size": {
"type": "integer",
"minimum": 0,
"description": "Truncate payload beyond this size in bytes."
}
}
}
cxp.send Params Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "CXPSendParams",
"type": "object",
"required": ["target", "payload"],
"properties": {
"target": {
"type": "string",
"pattern": "^U:[A-Z][a-z]$",
"description": "Destination Volk alias."
},
"payload": {
"oneOf": [
{"type": "object"},
{"type": "string"},
{"type": "null"}
]
},
"subject": {
"type": "string",
"maxLength": 200
},
"priority": {
"type": "integer",
"minimum": 0,
"maximum": 10,
"default": 5
},
"thread_id": {
"type": "string",
"format": "uuid",
"description": "Optional. Auto-generated if omitted."
}
}
}
session.open Params Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "SessionOpenParams",
"type": "object",
"properties": {
"portfolio": {"type": "string"},
"goals": {
"type": "array",
"items": {"type": "string"}
},
"context": {
"type": "object",
"description": "Initial session context data."
}
}
}
gateway.replay Params Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GatewayReplayParams",
"type": "object",
"properties": {
"topic": {"type": "string"},
"since": {"type": "string", "format": "date-time"},
"until": {"type": "string", "format": "date-time"},
"count": {"type": "integer", "minimum": 1, "maximum": 10000},
"sequence_from": {"type": "integer", "minimum": 0},
"sequence_to": {"type": "integer", "minimum": 0},
"filters": {"type": "object"}
}
}
knowledge.query Params Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "KnowledgeQueryParams",
"type": "object",
"required": ["cypher"],
"properties": {
"cypher": {
"type": "string",
"description": "Read-only Cypher query. Mutations are rejected."
},
"params": {
"type": "object",
"description": "Cypher query parameters."
},
"timeout_seconds": {
"type": "number",
"minimum": 1,
"maximum": 60,
"default": 10
},
"max_results": {
"type": "integer",
"minimum": 1,
"maximum": 10000,
"default": 1000
}
}
}
Error Conditions
| ID | Condition | Handling |
|---|---|---|
| ERR-001 | Client sends RPC method before auth.authenticate |
Reject with JSON-RPC error -32001 (Unauthorized), disconnect after 5-second grace period |
| ERR-002 | Client provides invalid or expired authentication token | Return error -32001 with data.reason (e.g., "token_expired", "invalid_signature") |
| ERR-003 | Client exceeds configured rate limit (default: 500 req/sec) | Reject with error -32002 (Rate Limited), include data.retry_after_ms in response |
| ERR-004 | Client sends message exceeding max_message_size_bytes (default: 1MB) |
Reject frame with WebSocket close code 1009 (Message Too Big) |
| ERR-005 | Client attempts to subscribe to more than max_subscriptions_per_client topics (default: 50) |
Reject subscription with error -32602 and data.current_count |
| ERR-006 | cxp.send targets non-existent Volk alias |
Return error -32602 with data.reason set to "unknown_target_volk" |
| ERR-007 | knowledge.query contains mutation keywords (CREATE, MERGE, DELETE, SET, REMOVE, DETACH) |
Reject query with error -32602 and data.reason set to "mutation_not_allowed" |
| ERR-008 | knowledge.query exceeds configured timeout (default: 10s) |
Cancel query, return error -32603 with data.reason set to "query_timeout" |
| ERR-009 | Redis becomes unavailable during operation | Switch to in-memory fallback for client sessions, defer ring buffer writes, default deny for uncached auth |
| ERR-010 | Neo4j becomes unavailable | Defer audit writes, return error -32603 for knowledge.* methods with data.reason set to "neo4j_unavailable" |
| ERR-011 | Prolog engine becomes unavailable | Use cached governance decisions where available, deny all uncached authorization requests (fail-closed) |
| ERR-012 | Client connection drops mid-RPC (WebSocket close before response) | Cancel in-flight operations, clean up subscriptions within 1 second |
| ERR-013 | Two clients attempt HMAC authentication with same nonce within drift window | Accept first, reject second with error -32001 and data.reason set to "nonce_replay" |
| ERR-014 | Per-client event buffer overflows (default: 1000 events) | Drop oldest events, send gap notification with dropped count and sequence range |
| ERR-015 | max_clients reached (default: 100) and new connection arrives |
Reject connection with WebSocket close code 1013 (Try Again Later), log rejection |
| ERR-016 | governance.evaluate dry-run encounters Prolog evaluation error |
Return Prolog error in data.prolog_error with error code -32603 |
| ERR-017 | Batch JSON-RPC request contains more than 50 individual requests | Reject entire batch with error -32600 and data.reason set to "batch_too_large" |
| ERR-018 | Client sends WebSocket binary frame (non-text) | Reject frame with WebSocket close code 1003 (Unsupported Data) |
Testing
- [TC-001] The JSON-RPC protocol parser SHALL be implemented as a pure function accepting raw bytes and returning a parsed request structure, enabling isolated unit testing without WebSocket infrastructure.
- [TC-002] Authentication strategies SHALL implement the
IAuthStrategyprotocol, allowing each strategy to be tested independently with real Redis instances. - [TC-003] Event filtering logic SHALL be extracted into a standalone filter evaluator function, testable with synthetic events and filter specifications.
- [TC-004] Integration tests SHALL use real WebSocket connections (client and server in the same process or via loopback), real Redis (test database), real Neo4j, and real Prolog.
- [TC-005] Performance tests SHALL measure actual latency percentiles using
time.perf_counter_ns()under controlled load profiles. - [TC-006] Failure scenario tests SHALL simulate dependency outages by stopping actual Redis/Neo4j containers, not by mocking connection errors.
- [TC-007] Contract tests SHALL validate that every JSON-RPC method's request and response structures match the JSON Schema definitions in this specification.
- [TC-008] The ring buffer SHALL be testable by writing events to a real Redis sorted set and verifying replay retrieval with time range and count queries.
- [TC-009] Concurrent client tests SHALL spawn real WebSocket connections (minimum 50) and verify event delivery ordering and subscription isolation.
- [TC-010] Heartbeat timeout tests SHALL use real time delays (not mocked timers) to verify client disconnection after missed pongs.
Definition of Done
- [DoD-001] All acceptance criteria across all user stories are met and verified with automated tests.
- [DoD-002] Unit test coverage >= 90% for all gateway modules (protocol parser, auth strategies, subscription manager, event delivery, ring buffer).
- [DoD-003] Integration tests pass with real WebSocket connections, real Redis, real Neo4j, and real Prolog instances in the CI environment.
- [DoD-004] Performance benchmarks meet or exceed all PR-001 through PR-014 thresholds under specified conditions.
- [DoD-005] This specification document is updated to reflect the final implemented design, including any deviations.
- [DoD-006] API documentation for all JSON-RPC methods is generated or written, including request/response schemas and examples.
- [DoD-007] Security review completed covering: authentication mechanism strength, authorization enforcement, input validation, rate limiting, TLS configuration, and audit trail completeness.
- [DoD-008] All changes are backward compatible with the stated API version, or migration guidance is provided for breaking changes.
Examples
Example: Authentication Flow (Static Token)
Request:
{
"jsonrpc": "2.0",
"id": "auth-001",
"method": "auth.authenticate",
"params": {
"strategy": "static_token",
"token": "my-secret-gateway-token",
"client_metadata": {
"client_name": "vizint-command-center",
"client_version": "1.0.0",
"purpose": "dashboard"
}
}
}
Response:
{
"jsonrpc": "2.0",
"id": "auth-001",
"result": {
"authenticated": true,
"client_id": "client-a1b2c3d4",
"scope": "read_write",
"expires_at": null,
"gateway_version": "1.0.0",
"capabilities": ["cxp", "session", "volk", "governance", "knowledge", "gateway"]
}
}
Example: Subscribe to CXP Traffic
Request:
{
"jsonrpc": "2.0",
"id": "req-002",
"method": "cxp.subscribe",
"params": {
"filters": {
"volk_id": "U:Cd",
"delivery_status": "delivered"
}
}
}
Response:
{
"jsonrpc": "2.0",
"id": "req-002",
"result": {
"subscription_id": "sub-abc123",
"topic": "cxp.traffic",
"filters": {"volk_id": "U:Cd", "delivery_status": "delivered"}
}
}
Subsequent Server Push:
{
"jsonrpc": "2.0",
"method": "cxp.traffic",
"params": {
"sequence": 42,
"timestamp": "2026-03-28T14:30:22Z",
"payload": {
"message_id": "msg-e4f5a6b7",
"to": "U:Cd",
"from": "U:Ox",
"thread_id": "thread-001",
"subject": "code_generation_request",
"delivery_status": "delivered",
"work_status": "pending",
"priority": 5
},
"source": "kernel.postman"
}
}
Example: Send CXP Packet
Request:
{
"jsonrpc": "2.0",
"id": "req-003",
"method": "cxp.send",
"params": {
"target": "U:Vz",
"subject": "generate_component",
"payload": {
"component": "UserService",
"language": "python",
"framework": "fastapi"
},
"priority": 7
}
}
Response:
{
"jsonrpc": "2.0",
"id": "req-003",
"result": {
"status": "sent",
"thread_id": "thread-8f9e0d1c",
"message_id": "msg-2b3c4d5e",
"routed_via": "U:PS"
}
}
Example: Error Response (Unauthorized)
{
"jsonrpc": "2.0",
"id": "req-004",
"error": {
"code": -32001,
"message": "Unauthorized",
"data": {
"reason": "authentication_required",
"hint": "Call auth.authenticate before any other method."
}
}
}
Example: Event Replay
Request:
{
"jsonrpc": "2.0",
"id": "req-005",
"method": "gateway.replay",
"params": {
"topic": "cxp.traffic",
"count": 10,
"filters": {"volk_id": "U:Vz"}
}
}
Response:
{
"jsonrpc": "2.0",
"id": "req-005",
"result": {
"events": [
{
"topic": "cxp.traffic",
"sequence": 35,
"timestamp": "2026-03-28T14:25:00Z",
"payload": {"from": "U:Ox", "to": "U:Vz", "subject": "task_assignment"},
"source": "kernel.postman"
},
{
"topic": "cxp.traffic",
"sequence": 38,
"timestamp": "2026-03-28T14:28:12Z",
"payload": {"from": "U:Vz", "to": "U:Ox", "subject": "task_progress"},
"source": "kernel.postman"
}
],
"total_matched": 2,
"buffer_range": {"oldest_sequence": 1, "newest_sequence": 42}
}
}
Security
Authentication and Authorization
All gateway operations require authentication before access. The gateway supports three authentication strategies:
- Static Token: Pre-shared token for development environments
- HMAC: Timestamped signatures using shared secret for production
- PAM++ Policy: Prolog-based policy evaluation for fine-grained access control
Authentication scopes:
read_only: Observe events and query stateread_write: Execute commands and manage sessionsadmin: Full access including configuration changes
Transport Security
- TLS 1.2+ enforced when certificates configured
- WebSocket origin validation prevents cross-site attacks
- Rate limiting per client IP (configurable, default: 100 connections/minute)
- Maximum message size enforced (configurable, default: 1MB)
Access Control
- All RPC methods require authentication (except
auth.authenticate) - PAM++ governance enforces authorization for all operations
- Knowledge graph queries restricted to read-only operations
- Admin methods require explicit admin scope
Audit and Logging
- All authentication events logged to Neo4j with client_id, strategy, result, IP
- All RPC method calls logged with timestamp, client_id, method, latency
- Audit trail records are immutable after write
- Authentication tokens never logged in plaintext
Governance
PAM++ Gateway Predicates
The gateway extends PAM++ with governance predicates for authorization:
% Client access levels
gateway_access(ClientId, admin).
gateway_access(ClientId, read_write).
gateway_access(ClientId, read_only).
% Per-method authorization
gateway_can_execute(ClientId, Method).
% Topic subscription authorization
gateway_can_subscribe(ClientId, Topic).
% Knowledge graph query authorization
gateway_can_query_kg(ClientId, QueryPattern).
Method Scope Requirements
cxp.send,session.open,session.close: Requiresread_writescopevolk.register,volk.deregister,governance.rules: Requiresadminscopecxp.subscribe,volk.list,knowledge.query: Requiresread_onlyscope (default)
Topic Subscription Requirements
governance.decisions,kernel.events: Requiresread_writescopecxp.traffic,volk.lifecycle,session.events: Requiresread_onlyscope
Governance Decisions
All gateway operations log governance decisions to the audit trail including:
- Whether the operation was allowed or denied
- Which Prolog rules were evaluated
- Latency of governance evaluation
- Any escalation paths taken
API Contracts
Contract: Gateway JSON-RPC API (contracts/gateway/rpc-v1.0.0.yaml)
info:
title: Orchestrata Gateway JSON-RPC 2.0 API
version: 1.0.0
spec_id: 014-websocket-gateway
spec_version: 1.0.0
maturity: experimental
transport: websocket
protocol: json-rpc-2.0
methods:
auth.authenticate:
description: Authenticate a client with the gateway
scope_required: null
params:
type: object
required: [strategy]
properties:
strategy:
type: string
enum: [static_token, hmac, prolog_policy]
token:
type: string
client_id:
type: string
timestamp:
type: string
format: date-time
nonce:
type: string
signature:
type: string
client_metadata:
type: object
result:
type: object
required: [authenticated, client_id, scope]
properties:
authenticated:
type: boolean
client_id:
type: string
scope:
type: string
enum: [read_only, read_write, admin]
expires_at:
type: string
format: date-time
nullable: true
gateway_version:
type: string
capabilities:
type: array
items:
type: string
cxp.subscribe:
description: Subscribe to CXP packet traffic
scope_required: read_only
params:
type: object
properties:
filters:
type: object
properties:
volk_id:
type: string
pattern: "^U:[A-Z][a-z]$"
thread_id:
type: string
format: uuid
subject:
type: string
delivery_status:
type: string
enum: [queued, delivered, acknowledged, failed]
max_payload_size:
type: integer
minimum: 0
result:
type: object
required: [subscription_id, topic]
properties:
subscription_id:
type: string
topic:
type: string
filters:
type: object
cxp.unsubscribe:
description: Unsubscribe from a CXP traffic subscription
scope_required: read_only
params:
type: object
required: [subscription_id]
properties:
subscription_id:
type: string
result:
type: object
required: [unsubscribed]
properties:
unsubscribed:
type: boolean
cxp.send:
description: Send a CXP message through the Postman
scope_required: read_write
params:
type: object
required: [target, payload]
properties:
target:
type: string
pattern: "^U:[A-Z][a-z]$"
payload:
oneOf:
- type: object
- type: string
- type: "null"
subject:
type: string
maxLength: 200
priority:
type: integer
minimum: 0
maximum: 10
thread_id:
type: string
format: uuid
result:
type: object
required: [status, thread_id]
properties:
status:
type: string
enum: [sent, failed, queued]
thread_id:
type: string
message_id:
type: string
routed_via:
type: string
cxp.status:
description: Query status of a CXP thread
scope_required: read_only
params:
type: object
required: [thread_id]
properties:
thread_id:
type: string
format: uuid
result:
type: object
required: [thread_id, delivery_status, work_status]
properties:
thread_id:
type: string
delivery_status:
type: string
work_status:
type: string
transitions:
type: array
items:
type: object
properties:
status:
type: string
timestamp:
type: string
format: date-time
volk.list:
description: List all registered Volks
scope_required: read_only
params:
type: object
properties:
offset:
type: integer
minimum: 0
limit:
type: integer
minimum: 1
maximum: 100
result:
type: object
required: [volks, total]
properties:
volks:
type: array
items:
type: object
required: [alias, capabilities, health]
properties:
alias:
type: string
capabilities:
type: array
items:
type: string
health:
type: string
active_tasks:
type: integer
last_activity:
type: string
format: date-time
total:
type: integer
session.open:
description: Open a new orchestration session
scope_required: read_write
params:
type: object
properties:
portfolio:
type: string
goals:
type: array
items:
type: string
context:
type: object
result:
type: object
required: [session_id, status]
properties:
session_id:
type: string
status:
type: string
opened_at:
type: string
format: date-time
session.close:
description: Close an active orchestration session
scope_required: read_write
params:
type: object
required: [session_id]
properties:
session_id:
type: string
status:
type: string
summary:
type: string
carryover_tasks:
type: array
items:
type: string
result:
type: object
required: [session_id, status, duration_seconds]
properties:
session_id:
type: string
status:
type: string
duration_seconds:
type: number
closed_at:
type: string
format: date-time
gateway.replay:
description: Replay historical events from the ring buffer
scope_required: read_only
params:
type: object
properties:
topic:
type: string
since:
type: string
format: date-time
until:
type: string
format: date-time
count:
type: integer
minimum: 1
maximum: 10000
filters:
type: object
result:
type: object
required: [events, total_matched]
properties:
events:
type: array
items:
$ref: "#/schemas/GatewayEvent"
total_matched:
type: integer
buffer_range:
type: object
properties:
oldest_sequence:
type: integer
newest_sequence:
type: integer
gateway.info:
description: Get gateway metadata and capabilities
scope_required: read_only
params: null
result:
type: object
required: [version, uptime_seconds, capabilities, topics]
properties:
version:
type: string
uptime_seconds:
type: number
capabilities:
type: array
items:
type: string
topics:
type: array
items:
type: string
gateway.ping:
description: Ping the gateway for latency measurement
scope_required: read_only
params: null
result:
type: object
required: [server_timestamp]
properties:
server_timestamp:
type: string
format: date-time
knowledge.query:
description: Execute a read-only Cypher query against the knowledge graph
scope_required: read_only
params:
type: object
required: [cypher]
properties:
cypher:
type: string
params:
type: object
timeout_seconds:
type: number
default: 10
max_results:
type: integer
default: 1000
result:
type: object
required: [records, execution_time_ms]
properties:
records:
type: array
execution_time_ms:
type: number
truncated:
type: boolean
governance.evaluate:
description: Dry-run a governance evaluation
scope_required: read_write
params:
type: object
required: [volk_id, action]
properties:
volk_id:
type: string
action:
type: string
resource:
type: string
result:
type: object
required: [result, prolog_trace]
properties:
result:
type: string
enum: [allow, deny, escalate]
prolog_trace:
type: string
articles_applied:
type: array
items:
type: string
error_codes:
-32700:
message: Parse error
description: Invalid JSON received
-32600:
message: Invalid request
description: JSON-RPC structure invalid
-32601:
message: Method not found
description: Unknown RPC method
-32602:
message: Invalid params
description: Parameter validation failed
-32603:
message: Internal error
description: Server-side processing error
-32001:
message: Unauthorized
description: Authentication required or failed
-32002:
message: Rate limited
description: Client exceeded rate limit
-32003:
message: Budget exceeded
description: Token or resource budget exceeded
event_topics:
cxp.traffic:
description: CXP packet flow between Volks
scope_required: read_only
volk.lifecycle:
description: Volk registration, deregistration, health changes
scope_required: read_only
governance.decisions:
description: PAM++ governance decisions and escalations
scope_required: read_write
session.events:
description: Session lifecycle events
scope_required: read_only
kernel.events:
description: Kernel-level system events
scope_required: read_write
gateway.presence:
description: Client connection and disconnection events
scope_required: read_only
provider.events:
description: LLM provider events
scope_required: read_only
performance:
connection_accept_p95_ms: 50
rpc_dispatch_overhead_p95_ms: 10
event_delivery_p95_ms: 100
broadcast_throughput_eps: 10000
max_concurrent_clients: 100
ring_buffer_write_p95_ms: 5
security:
authentication_required: true
authorization_scopes: [read_only, read_write, admin]
tls_supported: true
rate_limit_default_rps: 500
max_message_size_bytes: 1048576
observability:
emits_metrics: true
metric_names:
- orchestrata_gateway_connected_clients
- orchestrata_gateway_total_connections
- orchestrata_gateway_messages_received_total
- orchestrata_gateway_messages_sent_total
- orchestrata_gateway_rpc_latency_seconds
- orchestrata_gateway_subscription_count
- orchestrata_gateway_auth_success_total
- orchestrata_gateway_auth_failure_total
- orchestrata_gateway_events_dropped_total
health_endpoint: /health
ready_endpoint: /ready
metrics_endpoint: /metrics
spec_traceability:
spec_id: "014-websocket-gateway"
spec_version: "1.0.0"
user_stories:
- "US-001"
- "US-002"
- "US-003"
- "US-004"
- "US-005"
- "US-006"
- "US-007"
- "US-008"
- "US-009"
- "US-010"
- "US-011"
- "US-012"
Observability
Logging Requirements
- Component Logging
- Log all major operations with appropriate log levels
- Include correlation IDs for request tracing
- Log performance metrics for critical operations
- Log errors with full context for debugging
Metrics Requirements
- Performance Metrics
- Operation duration histograms
- Request/error rate counters
- Resource utilization gauges
- Business metrics relevant to domain
Tracing Requirements
- Distributed Tracing
- Trace propagation across component boundaries
- Span attributes for domain-specific context
- Trace sampling based on operational needs
Alerting Requirements
- Critical Alerts
- Error rate spikes
- Performance degradation
- Resource exhaustion
- Business metric anomalies
Dashboard Requirements
- Operational Dashboard
- Real-time system health
- Performance trends
- Error analysis
- Resource monitoring
Revision History
| Date | Version | Author | Changes |
|---|---|---|---|
| 2026-03-27 | 1.0.0 | Mohamed | Initial specification |
| 2026-03-28 | 1.0.0 | Mohamed | Added Data Models, Error Conditions, Performance Requirements, Testability, DoD, Terminology, Examples, Contracts sections per spec standard improvements |