Skip to content

OpenBao KV v2 for Bridge mobile tokens

This document defines the concrete external secret-store adapter for the Bridge mobile delivery boundary. It is a local integration and deployment contract; it does not authorize production initialization, secret creation, APNs enablement, or deployment.

Contract

OpenBaoKV2SecretStore implements the existing ExternalEncryptedSecretStore boundary. A Bridge token vault stores one value at each KV v2 path:

secret/data/heyaira/bridge/mobile/devices/<device-id>/apns-token
{
  "data": {
    "value": "<raw APNs token>"
  }
}

The raw token exists only in the registration/delivery process and the OpenBao request body. HeyAira PostgreSQL stores only the token hash and device metadata. The adapter never logs the token, the OpenBao token, or an OpenBao response body. HTTP errors become bounded codes such as openbao_forbidden, openbao_not_found, or openbao_unavailable.

Configuration

Production uses a mounted secret file for the OpenBao token. The raw token must not be placed in Git, a committed .env, a task receipt, or a log.

HEYAIRA_OPENBAO_ADDR=https://openbao.internal:8200
HEYAIRA_OPENBAO_TOKEN_FILE=/run/heyaira-secrets/openbao.token
HEYAIRA_OPENBAO_KV_MOUNT=secret
HEYAIRA_OPENBAO_KV_PREFIX=heyaira/bridge/mobile
HEYAIRA_OPENBAO_TIMEOUT_SECONDS=3
HEYAIRA_OPENBAO_CA_BUNDLE=/run/heyaira-secrets/openbao-ca.pem

HEYAIRA_ENVIRONMENT=production refuses application startup when the address or token file is absent, unreadable, empty, or invalid. The adapter does not contact OpenBao during configuration validation; connectivity is checked by the supervised delivery path and must be tested separately.

When both values are present, the server constructs the existing ExternalEncryptedMobileTokenVault around this adapter during application startup. The APNs provider and delivery supervisor are still separate deployment controls and remain disabled until they are explicitly wired and accepted.

Local single-node OpenBao (non-dev mode)

The repository includes ops/openbao-compose.yaml. It intentionally has no ports mapping and uses server mode with file storage. This is a private local integration environment, not a production topology. The local service must be on the same private Docker network as the consumer, or the consumer must use a private network route.

  1. Start the service without -dev:
docker compose -f ops/openbao-compose.yaml up -d
  1. Initialize once and store the unseal key and initial root token offline:
docker compose -f ops/openbao-compose.yaml exec openbao \
  bao operator init -key-shares=1 -key-threshold=1
  1. Unseal using the offline key, then enable KV v2. Do not use the initial root token for the application:
docker compose -f ops/openbao-compose.yaml exec openbao bao operator unseal
docker compose -f ops/openbao-compose.yaml exec openbao bao secrets enable -path=secret kv-v2
  1. Create a narrowly scoped policy for the Bridge prefix and issue a token for that policy. Keep the token in a local file with mode 0600, mounted at the path referenced by HEYAIRA_OPENBAO_TOKEN_FILE.

The repository policy at ops/openbao-mobile-policy.hcl grants access only to the Bridge device-token prefix. Review it before applying it with bao policy write heyaira-bridge-mobile ops/openbao-mobile-policy.hcl.

The compose file exposes OpenBao only to its private Docker network. For the existing application Compose topology, use -f compose.yaml -f ops/openbao-production-compose.yaml. This keeps OpenBao on the same private Docker network as the server, exposes no host port, and mounts the application token through the existing secrets directory. The override is a topology adapter; it does not initialize OpenBao or create any credential automatically.

For a real production deployment, use TLS or an equivalently protected private transport, a managed/sealed storage backend, short-lived scoped tokens, rotation, audit logging, and a process-manager health/readiness contract. The application must not start until the token file has been created with mode 0600 and the KV policy has been reviewed.

Test boundary

The tests use a fake HTTP transport and synthetic tokens. They verify KV v2 paths, bounded HTTP responses, stable error mapping, token-file configuration, and the production-startup refusal. They do not initialize OpenBao, contact a real vault, call APNs, or enable the mobile provider.