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.
- Start the service without
-dev:
docker compose -f ops/openbao-compose.yaml up -d
- 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
- 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
- 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 byHEYAIRA_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.