Skip to content

feat(supervisor): add WebSocket message introspection middleware #2428

Description

@pimlock

Problem Statement

Supervisor middleware can inspect the HTTP request that upgrades a connection to WebSocket, but it cannot inspect messages exchanged after the upgrade. This leaves a gap for applications that carry sensitive or governed content in post-upgrade messages.

Subscription Codex uses WebSocket mode and sends prompts in post-upgrade messages. OpenShell can parse client-to-upstream text messages for built-in WebSocket policy and credential rewriting, but the current supervisor middleware contract exposes only HTTP_REQUEST/PRE_CREDENTIALS. Privacy Guard and other operator-run middleware therefore cannot inspect, redact, block, or annotate those prompts.

The same capability is needed by #2166 for realtime media carried in WebSocket text or binary messages. That issue also covers gRPC and broader media governance; this issue is limited to WebSocket message-level supervisor middleware.

Proposed Design

Add typed post-upgrade WebSocket message operations to supervisor middleware, corresponding to the WebSocketMessage/before_forward and WebSocketMessage/before_return hooks outlined by RFC 0009.

The middleware boundary should operate on complete logical messages, not raw RFC 6455 frames:

  • OpenShell remains responsible for the WebSocket protocol, including masking, fragmentation and reassembly, compression, control frames, message limits, ordering, backpressure, and reframing.
  • Each evaluation identifies the admitted destination and session, direction, text or binary message type, selected subprotocol, middleware configuration, and complete message content.
  • Middleware returns allow or deny, optional replacement content, audit-safe findings, and metadata using semantics aligned with the existing HTTP request hook.
  • A denied or invalid message terminates the WebSocket session with an appropriate policy-violation close instead of silently dropping the message.
  • Upstream-to-client messages can be inspected or transformed but never receive credential injection or credential placeholder rewriting.
  • Middleware selection and configuration remain policy-controlled. The gateway and supervisor validate that a registered middleware is authorized for the new operation and phase.
  • The session uses one consistent policy and middleware snapshot. Reload behavior must not mix generations within an active session.
  • OCSF events record decisions, limits, failures, and findings without logging message payloads, prompts, binary media, or credentials.

The implementation may use a bidirectional streaming gRPC operation so one middleware invocation can preserve session context, ordering, cancellation, and backpressure across messages. The exact protobuf shape should be finalized with the implementation, but it must keep WebSocket session processing distinct from the one-shot HTTP upgrade request.

Alternatives Considered

Inspect only the HTTP upgrade

The upgrade request does not contain prompts, media messages, or other application data sent after 101 Switching Protocols, so upgrade admission cannot govern message content.

Rely only on built-in WebSocket L7 policy

The existing policy path can evaluate supported client text messages, but it does not provide the external middleware contract, transformations, findings, or binary and return-path coverage needed by Privacy Guard and realtime media use cases.

Expose raw WebSocket frames to middleware

This leaks protocol mechanics into every middleware implementation and makes fragmentation, compression, control frames, and partial disclosure inconsistent. OpenShell should expose reconstructed logical messages and retain ownership of wire correctness.

Use opaque L4 passthrough

L4 passthrough carries bytes but cannot inspect, transform, deny, rate-limit, or audit individual WebSocket messages.

Agent Investigation

  • Reviewed the Slack thread where the subscription Codex and Privacy Guard gap was identified.
  • Reviewed feat: governed realtime media membrane #2166 and separated its WebSocket requirement from its gRPC and broader media scope.
  • Confirmed RFC 0009 defines only HTTP_REQUEST/PRE_CREDENTIALS in v1 and identifies future WebSocketMessage/before_forward and WebSocketMessage/before_return phases.
  • Confirmed the current WebSocket relay reconstructs and evaluates client text messages, while binary messages and upstream-to-client traffic do not pass through supervisor middleware.
  • Searched existing OpenShell issues and found no focused issue for WebSocket message-level supervisor middleware.

Definition of Done

  • Supervisor middleware defines typed post-upgrade WebSocket message operation and phase contracts.
  • The runtime evaluates complete logical text and binary messages without exposing raw frame mechanics to middleware.
  • Policy can select middleware for WebSocket message processing and validation rejects unsupported or unauthorized bindings.
  • Allow, deny, transform, findings, metadata, timeout, fail-open, and fail-closed behavior are defined for message processing.
  • Denials and invalid transformations close the session safely without forwarding the rejected message.
  • Session ordering, backpressure, cancellation, size limits, and reload snapshot behavior are deterministic.
  • Automated tests cover fragmented and compressed messages, text and binary messages, both directions, transformations, denials, middleware failures, and no-middleware behavior.
  • OCSF tests verify useful decision and failure events without payload or credential leakage.
  • RFC 0009, architecture documentation, published middleware documentation, and policy reference documentation describe the new hook.

Checklist

  • I've reviewed existing issues and the architecture docs.
  • This is a design proposal, not a "please build this" request.

Metadata

Metadata

Assignees

Labels

area:supervisorProxy and routing-path workstate:pr-openedPR has been opened for this issuestate:review-readyReady for human reviewtopic:l7Application-layer policy and inspection work

Projects

Status
Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions