# alexa-bridge `alexa-bridge` is a self-hosted Alexa Custom Skill backend. It verifies that incoming HTTPS requests actually came from Alexa, resolves the spoken device name against entities discovered from `ha-gateway`, and executes the resulting action over gRPC. Unlike the other three services in this repo, it is internet-facing — Alexa's servers call directly into it — so it is the one service whose own inbound edge is untrusted by default and needs its own request verification, on top of the mTLS it uses (like `ai-gateway` and `discord-bot`) to call `ha-gateway`. See [plan.md](plan.md) for the full design, the action-table mapping from Alexa intents to `ha-gateway` RPCs, and the resolved "Decisions on open questions" section documenting scope choices (single-setpoint-only climate control, exact-match-only entity name resolution, no remote/SwitchBot support, etc.). ## Runtime Flow 1. The service loads `.env`, configures logging and telemetry, blocking-fetches the initial entity list from `ha-gateway`'s `EntityService` (failing startup if that fails — nothing can resolve a device name without it), then starts serving HTTP on `HTTP_PORT`. 2. A background goroutine refreshes the entity list every `ENTITY_REFRESH_INTERVAL`; a failed periodic refresh only logs and keeps serving the last-known-good list. 3. Each incoming Alexa request is verified: `SignatureCertChainUrl`/ `Signature` headers (cert chain fetched from Amazon's S3 host and cached, RSA-SHA1 signature over the raw body), request timestamp (150s replay tolerance), and the request envelope's application ID against `ALEXA_SKILL_ID`. 4. Verified `IntentRequest`s are routed by intent name; the `Device` slot is resolved (exact match, normalized) against the cached entity list, and the resulting `(entity_id, action, params)` triple is executed via `ha-gateway`'s `Light`/`Switch`/`Climate` services over mTLS. 5. Resolution and execution failures produce a spoken failure response rather than an HTTP error — a Dispatch-layer error would surface as Alexa's own generic failure speech instead of a message this skill controls. ## Configuration Environment variables: | Variable | Default | Description | | --- | --- | --- | | `HTTP_PORT` | `8080` | HTTP listen port | | `ALEXA_SKILL_ID` | — (required) | Verified against the request envelope's application ID | | `HA_GATEWAY_ADDR` | `ha-gateway.home-services.svc.cluster.local:50051` | gRPC address for `ha-gateway` | | `HA_GATEWAY_SERVER_NAME` | `ha-gateway.home-services.svc.cluster.local` | Expected server name for mTLS | | `TLS_DIR` | `/tls` | mTLS client cert dir for the `ha-gateway` call. Unlike `ai-gateway`/`discord-bot`, this defaults **on** rather than empty — alexa-bridge is internet-facing, so mTLS to `ha-gateway` should be on by default rather than opt-in. Set empty to disable for local plaintext dev. | | `ENTITY_REFRESH_INTERVAL` | `5m` | Periodic entity list refresh cadence | | `OTEL_ENDPOINT` | empty | OTLP gRPC collector endpoint; empty disables telemetry | | `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, or `error` | | `LOG_FORMAT` | `json` | `json` or `text` | Example env file: [.env.example](.env.example) When `TLS_DIR` is set, the directory must contain `tls.crt`, `tls.key`, and `ca.crt`. ## Local Run Start `ha-gateway` first, then run: ```bash cd alexa-bridge cp .env.example .env # edit .env: set ALEXA_SKILL_ID, leave TLS_DIR empty for plaintext local dev go run ./cmd/bridge ``` `alexa-bridge` doesn't register with Alexa on its own — during development, point Alexa's request signature verification at a tunneled local endpoint (e.g. `ngrok`) and set that HTTPS URL as the skill's endpoint in the Alexa developer console. `/healthz` returns `200 OK` for liveness/readiness probes. ## HTTP API There is no gRPC surface here (unlike the other three services) — this is a plain HTTP server: - `POST /`: the Alexa Custom Skill endpoint. Expects the standard Alexa request envelope as JSON, with `SignatureCertChainUrl` and `Signature` headers. - `GET /healthz`: unauthenticated liveness/readiness check, always `200 OK`. ## Deployment Kubernetes manifests (Deployment/Service, the `alexa-bridge-tls` mTLS client cert, and the public HTTPS ingress) live in the separate `homelab` repo, not here — see [plan.md](plan.md)'s mTLS section and "Decisions on open questions" #2 for what's drafted there.