Skip to content

feat(audit): audit supervisor session establishment (connect, relay, tunnel) #3018

Description

@mattj-monad

User Story

As a security or compliance owner running OpenShell, I want supervisor session establishment — a sandbox connecting its supervisor, a relay stream being claimed, a WebSocket tunnel opening — recorded as structured audit events, so I can see when and by which principal a live control channel into a sandbox was opened and closed, not only what happened over it.

Problem Statement

OpenShell is gaining a structured audit trail for state-changing gateway operations (#2911) and for authentication and authorization outcomes (#2912). Neither covers the establishment of the supervisor↔gateway session and the relay and tunnel channels that ride it. ConnectSupervisor, RelayStream, and the WebSocket tunnel open and close are the moments a live channel into a sandbox comes up and goes down; today they surface only as ordinary diagnostic logs. Session establishment is not a resource mutation, so it is outside #2911's scope, and a successful, authorized establishment is not an authentication failure, so it is outside #2912. It falls between the two.

Impact / Why This Matters

An operator investigating a sandbox cannot reconstruct when its control channel was established, by which principal, or how long it stayed open — the session boundary that frames every exec, forward, and relay that follows. The exec and forward events (from #2911) presuppose a session that is already up; without a record of establishment and teardown, the trail has the actions but not the sessions that carried them, and cannot answer "when did a live channel into this sandbox exist, and who held it?" The current workaround is to infer session lifetime from surrounding diagnostic logs, which is neither stable nor attributable.

Proposed Design

Emit one structured OCSF audit event on establishment and one on teardown for each session-bearing path — ConnectSupervisor, RelayStream, and the WebSocket tunnel — naming the authenticated principal (sandbox or user), the sandbox, the channel type, the outcome, and a correlation id. The events never carry session input/output or bearer material. They reuse the audit helper, actor model, and master toggle that govern the control-plane audit events. The OCSF class is left to the implementer — an Entity Management (3004) session lifecycle event, in the spirit of the existing ssh-session records, is a natural fit. Emission is governed by the [openshell.gateway.audit] master toggle.

Acceptance Criteria

  • Each session-bearing path (ConnectSupervisor, RelayStream, WebSocket tunnel) emits an establishment record and a teardown record.
  • Each record names the authenticated principal, the sandbox, the channel type, the outcome, and a correlation id.
  • No session input/output, bearer token, or other secret material appears in any record; automated tests cover representative secret canaries.
  • Emission is governed by the existing [openshell.gateway.audit] master toggle.
  • Establishment and teardown for the same session share a correlation id so a session's lifetime can be reconstructed.
  • The events, their fields, and redaction behavior are documented for operators.

Alternatives Considered

  • Fold into feat(audit): emit structured gateway control-plane mutation events #2911. Rejected: session establishment is not a resource mutation, and modeling a channel's open/close as a CRUD event on a resource distorts the mutation catalog.
  • Infer sessions from exec/forward events. Rejected: those events assume a session is already established, so the session boundary and its lifetime are lost, and a session that carried no exec would leave no trace at all.
  • Accept the gap. Leaves the control-channel lifecycle — a first-order security fact about a sandbox — unrecorded.

Agent Investigation

Checklist

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions