Skip to content

Message Flows

This page traces the two critical request paths through the system step by step. Read these carefully — they show exactly what every module does and why it exists.

Flow A — Account Linking (OAuth2)

Account Linking happens once, when a user enables the Alexa Skill for the first time. The goal: exchange a username/password for a pair of JWT tokens that Alexa will attach to every future directive.

Phase status

The OAuth2 server on the home server (right half of the diagram) is fully implemented (Phase 4). The OAuth proxy (left half) runs on a Lambda Function URL (Phase 5). During development you can test OAuth directly at http://localhost:8080/oauth/....

Key security mechanisms

MechanismWhat it does
PKCE (S256)Alexa sends a code_challenge (SHA-256 hash of code_verifier) during authorize. At token exchange it sends the raw code_verifier. The server recomputes the hash and compares — ensures only the original caller can exchange the code.
Auth code is single-useauth_codes.redeem() atomically deletes the entry. A replayed code returns invalid_grant.
Refresh token rotationOn every /oauth/token?grant_type=refresh_token, the old token is revoked before the new pair is issued.
bcryptPasswords are never stored in plain text. Only the bcrypt hash is stored in SQLite.
JWT expiryAccess tokens expire after 60 minutes (configurable). Alexa uses the refresh token to get new ones automatically.

Flow B — Voice Command

This is the hot path — everything that happens between "Alexa, switch to ZDF" and the TV changing channel.

Phase status

The home server portion (FastAPI → Router → Handler → Command → Adapter → Device) is fully implemented (Phase 3 + 2). The Lambda proxy + S3 beacon (the top section) is planned (Phase 5). During development, POST directly to http://localhost:8080/alexa/directive.

What each layer does in this flow

LayerResponsibility in this flow
LambdaLooks up current home server URL; adds Shared-Secret header; forwards raw directive
FastAPI routeExtracts and validates the Bearer JWT; rejects with 401 if invalid
AlexaDirectiveRouterParses the Alexa JSON into a typed model; dispatches to the correct handler by (namespace, name)
PowerHandlerExtracts endpoint ID and correlation token; calls the command; builds the Alexa response
ActivateChannelCommandOrchestrates the two-step TV activation (ensure activity → set channel); raises DeviceNotFoundError or DeviceUnavailableError
DeviceRegistryPortLooks up the ChannelDevice by ID; returns None if not found
TvPort / HarmonyTvAdapterWebSocket calls to the Harmony Hub; maps Hub exceptions to DeviceUnavailableError

Error handling

Every handler wraps the command call in a try/except block and maps domain errors to Alexa error responses:

ExceptionAlexa error typeAlexa behavior
DeviceNotFoundErrorNO_SUCH_ENDPOINT"That device is not available"
DeviceUnavailableErrorENDPOINT_UNREACHABLE"That device is not responding"
ValueErrorVALUE_OUT_OF_RANGE"That value is out of range"
Any other exceptionINTERNAL_ERROR"Sorry, something went wrong"

Flow C — Token Refresh

Alexa automatically refreshes the access token when it expires (every 60 minutes). The refresh token rotates on each use.

Refresh token rotation means a stolen refresh token can only be used once — the legitimate user's next refresh will fail, alerting them to the compromise.

Tiberio — self-hosted Alexa Smart Home backend