feat(dashboard-auth): single-use WS tickets + POST /api/auth/ws-ticket
Phase 5 task 5.1. Browsers cannot set Authorization on a WebSocket
upgrade, so in gated mode the SPA needs an alternative way to bind the
upgrade to its authenticated session.
hermes_cli/dashboard_auth/ws_tickets.py — in-memory single-use ticket
store with 30s TTL. Thread-safe (threading.Lock), token_urlsafe(32)
values, ticket value truncated to 8 chars in error messages for log
hygiene. Module-level state with _reset_for_tests() helper.
hermes_cli/dashboard_auth/routes.py — adds POST /api/auth/ws-ticket.
Auth-required (the gate middleware already attaches Session to
request.state.session). Returns {ticket, ttl_seconds}; emits
WS_TICKET_MINTED audit event with user_id + provider + ip.
hermes_cli/dashboard_auth/audit.py — adds WS_TICKET_REJECTED enum
value for the consume-side rejection event (wired into the WS
endpoints in task 5.2).
11 new tests covering round-trip, single-use, TTL boundary, unknown
ticket rejection, secret-hygiene truncation in error messages, and
concurrent mint+consume from 20 threads.
This commit is contained in:
@@ -46,6 +46,7 @@ class AuditEvent(enum.Enum):
|
||||
REVOKE = "revoke"
|
||||
SESSION_VERIFY_FAILURE = "session_verify_failure"
|
||||
WS_TICKET_MINTED = "ws_ticket_minted"
|
||||
WS_TICKET_REJECTED = "ws_ticket_rejected"
|
||||
|
||||
|
||||
def _resolve_log_path() -> Path:
|
||||
|
||||
Reference in New Issue
Block a user