Expand description
REST-like Operator session resource (POST/GET/DELETE /v1/operators + WS upgrade).
REST-like Operator session resource.
Provides the POST/GET/DELETE /v1/operators + WS /v1/operators/:sid/ws
route family — the sole WS Operator session route. session.rs /
protocol.rs are unchanged by this module.
§Login flow
POST /v1/operators { roles?: ["main-ai"], capability_manifest?: {...} }
→ 409 if any role already owns a live entry (roles alias exclusivity,
v1.md §Auth session flow)
→ { sid: "S-<hex>", token: "<10-hex>", roles: [...] }
The manifest is pinned to this session and later resolved through the
Core `AgentBindingProvider` interface before any Runner-backed spawn.
WS /v1/operators/:sid/ws
Authorization: Bearer <token> (mandatory — no empty-string default)
→ 401 missing/empty Bearer, 404 unknown sid, 401 token mismatch
→ registers a `WSOperatorSession` into the engine's 3 registries
(senior_bridge / spawn_hook / operator) + role aliases, same pattern
as `handler::handle_socket`. Reconnect (same sid, matching token)
reuses the existing `WSOperatorSession` via `replace_tx`.
DELETE /v1/operators/:sid (Bearer required)
→ unregisters the 3 registries + role aliases + `operator_sessions`
entry + releases `roles_to_sid` ownership.
GET /v1/operators/:sid (Bearer required)
→ { sid, roles, connected }OperatorSessionEntry is the login-flow record (AppState.operator_sessions),
distinct from mlua_swarm::OperatorSession (the engine-side
attach/session-token record) and from WSOperatorSession (the 3-trait WS
session, session.rs) — this module owns the mapping sid → (token, roles, Option<WSOperatorSession>) that the login flow is built on.
Structs§
- Operator
Session Entry - Login-flow record for a minted Operator session. Held in
AppState.operator_sessions, keyed bysid.ws_sessionstartsNone(login only mints sid+token) and is set on first successful WS connect; on reconnect the sameWSOperatorSessionis reused (replace_tx) rather than re-registered. - Operators
Create Req - Body for
POST /v1/operators. - Operators
Create Resp - Response for
POST /v1/operators. - Operators
Delete ByRole Query - Query string of
DELETE /v1/operators/by-role/:role. - Operators
Info Resp - Response for
GET /v1/operators/:sid. - Operators
List Entry - GH #81 Layer 2 (b): one entry in the
GET /v1/operatorslist response. Bare identity fields (no token, no capability manifest — those live behind Bearer onGET /v1/operators/:sid); this list surface is read-only observability, on the same trust tier asGET /v1/status. - Operators
List Resp - Response body for
GET /v1/operators(GH #81 Layer 2 (b)).
Functions§
- operators_
create POST /v1/operators. Mintssid(S-<hex>— the sharedSessionIdshape; issue #11) + a 10-hex-char token (mlua_swarm::types::secure_hex(5)— OS-RNG hex, unguessable across calls and restarts, which is the point: this token is the sole bearer secret on the short-handle path). Whenrolesis non-empty, checksAppState.roles_to_sidfor conflicts under a single lock (check + insert atomic w.r.t. concurrent mints) and returns409 CONFLICTwith the conflicting role names on collision. Emptyrolesnever conflicts (= no exclusivity is claimed).- operators_
delete DELETE /v1/operators/:sid. Bearer mandatory.404on unknown sid,401on token mismatch. Drops the 3 engine registries + role aliases +ws_operator_factorybindings +operator_sessionsentry, and releases this sid’s ownership inroles_to_sid(re-opening the role names for a future mint).- operators_
delete_ by_ role DELETE /v1/operators/by-role/:role. Releases the session currently holdingrolewithout requiring the caller to know the sid or its Bearer token (GH #81 Layer 2 (c)). Recovery route for a stale session whose driver crashed after minting the sid — pre-#81 the only reliable recovery was a full server restart, which also dropped every OTHER live session. Same trust tier as the server-shutdown surface (mlua_swarm_server_shutdown): admin observability, no Bearer.- operators_
info GET /v1/operators/:sid. Bearer mandatory.404on unknown sid,401on token mismatch.connectedreflects whether the reusable session currently owns a live sender, not merely whether it connected at least once.- operators_
list GET /v1/operators. Read-only enumeration of every live session’s{sid, roles, joined_at_secs, connected}(GH #81 Layer 2 (b)). Same trust tier asGET /v1/status— no Bearer required; sids are identifiers, not secrets. Answers “which sid holdsmain-ai?” without probing every sid individually viaGET /v1/operators/:sid, which was the pre-#81 recovery gap.- operators_
ws_ connect GET /v1/operators/:sid/ws(WS upgrade). Bearer mandatory.404on unknown sid,401on token mismatch. On successful upgrade, registers (or reuses, on reconnect) aWSOperatorSessionundersid— same 3-registry pattern ashandler::handle_socket, plus role-alias registration for every role minted alongside this sid.