# Request and Push Flows ## Public Auth Flow ```mermaid sequenceDiagram participant Client participant Gateway participant Limiter as Public anti-abuse participant Backend as backendclient.RESTClient Client->>Gateway: POST /api/v1/public/auth/send-email-code Gateway->>Limiter: classify + rate-limit + body checks Limiter-->>Gateway: allowed Gateway->>Backend: POST /api/v1/public/auth/send-email-code Backend-->>Gateway: 200 {challenge_id} Gateway-->>Client: 200 {challenge_id} Client->>Gateway: POST /api/v1/public/auth/confirm-email-code Gateway->>Limiter: classify + rate-limit + body checks Limiter-->>Gateway: allowed Gateway->>Backend: POST /api/v1/public/auth/confirm-email-code Backend-->>Gateway: 200 {device_session_id} Gateway-->>Client: 200 {device_session_id} ``` ## Authenticated ExecuteCommand Flow ```mermaid sequenceDiagram participant Client participant Gateway participant Backend as backendclient.RESTClient participant Replay as ReplayStore participant Policy as Rate limit / policy Client->>Gateway: ExecuteCommand(envelope, payload_bytes, signature) Gateway->>Gateway: validate envelope + protocol_version Gateway->>Backend: GET /api/v1/internal/sessions/{device_session_id} Backend-->>Gateway: session record Gateway->>Gateway: verify payload_hash Gateway->>Gateway: verify Ed25519 signature Gateway->>Gateway: verify freshness window Gateway->>Replay: reserve(device_session_id, request_id, ttl) Replay-->>Gateway: accepted Gateway->>Policy: apply IP/session/user/message_type budgets Policy-->>Gateway: allowed Gateway->>Backend: PATCH/POST/GET /api/v1/user/... Backend-->>Gateway: JSON success or error Gateway->>Gateway: hash payload + sign response Gateway-->>Client: ExecuteCommandResponse + signature ``` ## SubscribeEvents Lifecycle ```mermaid sequenceDiagram participant Client participant Gateway participant Backend as backend Push.SubscribePush participant Hub as PushHub participant Dispatcher Client->>Gateway: SubscribeEvents(envelope, signature) Gateway->>Gateway: validate envelope + verify request Gateway->>Gateway: lookup session via backend REST Gateway->>Client: gateway.server_time event Gateway->>Hub: register(user_id, device_session_id) Backend-->>Dispatcher: PushEvent{ClientEvent} Dispatcher->>Hub: Publish(push.Event) Hub-->>Client: matching event delivery (signed envelope) Backend-->>Dispatcher: PushEvent{SessionInvalidation} Dispatcher->>Hub: RevokeDeviceSession or RevokeAllForUser Hub-->>Client: stream closes with FAILED_PRECONDITION Note over Gateway,Hub: During shutdown the gateway closes PushHub before gRPC graceful stop. Hub-->>Client: stream closes with UNAVAILABLE ```