Never commit or return:
- APNs
.p8private key - Home Assistant tokens
- Spotify tokens
- Cloudflare API tokens
- Relay/bootstrap shared secret
- Per-install DJConnect relay tokens
Store production secrets with wrangler secret put.
The repository also provides scripts/provision_cloudflare.sh for automated
setup. It is dry-run by default, supports explicit --dry-run, refuses shell
tracing and does not echo secret values. Provide APNs key material through
--apns-private-key-file and the relay secret through an environment variable such as
DJCONNECT_RELAY_SECRET_VALUE. Provide the APNs token encryption key through
an environment variable such as APNS_TOKEN_ENCRYPTION_KEY_VALUE; never pass
secret values directly in shell arguments.
In execute mode, the script requires and verifies CLOUDFLARE_API_TOKEN before
running Cloudflare-changing actions. A valid token alone is not enough for every
operation; it must also have account permissions for Workers, D1 and custom
domain management.
Secrets and production configuration must be set only through Cloudflare secrets/configuration. Do not place secrets in source files, tests, docs, fixtures, .dev.vars, .env, or migration files.
Required Cloudflare secrets:
APNS_PRIVATE_KEY: full Apple.p8private key content. Paste it intonpx wrangler secret put APNS_PRIVATE_KEYwhen prompted. Never print, log, commit or paste the key into issues.DJCONNECT_RELAY_SECRET: long random relay shared secret for authenticated trusted bootstrap/operator calls that issue per-install tokens. Never commit the value. Do not ship it in HACS or client code.DJCONNECT_PAIRING_ISSUER_SECRET: separate long random shared secret for the trusted Apple pairing issuer flow. Never commit the value. Do not ship it in HACS or client code.APNS_TOKEN_ENCRYPTION_KEY: base64-encoded 32-byte key used to encrypt APNs device tokens before D1 storage. Generate withopenssl rand -base64 32. Never commit, print, log, or copy it into GitHub Actions.DJCONNECT_SMOKE_TEST_MODE: optional Worker secret. Set toenabledonly to allow CI to run the staging-safe E2E path withexample-...APNs tokens without contacting APNs. The Worker still uses real APNs for all non-example tokens.
The APNs public metadata is allowed in source/config:
APNS_TEAM_IDAPNS_KEY_ID- APNs topics for iOS, macOS and watchOS
APNS_ENVIRONMENT
Cloudflare API tokens are operator credentials. Do not commit them, put them in docs, or include them in command output shared publicly.
GitHub Actions may contain DJCONNECT_RELAY_SECRET only for the staging-safe
E2E smoke test. Do not expose it to pull requests from untrusted forks, logs, or
non-CI tooling.
CI maps that GitHub secret to the runtime environment variable
DJCONNECT_RELAY_SECRET_VALUE only for scripts/smoke_e2e.sh. The script does
not enable shell tracing, does not print secret values or raw token-bearing
response bodies, and skips live staging coverage when the secret is absent.
Local and CI contract tests use only example-... fixture values.
Public HACS integrations must not contain a global DJConnect secret.
The production auth model is:
DJCONNECT_RELAY_SECRETstays server/operator-side and is used only for trusted admin/pairing calls such asPOST /v1/install/bootstrap-proof.POST /v1/pairing/bootstrap-proofis client-safe for Apple apps and does not require embedded relay, pairing issuer, APNs provider or backend tokens. It issues proofs only after validating known DJConnect Apple app metadata.- Each Home Assistant installation receives its own
djci_...install token. The HACS integration provisions this automatically during setup; users do not normally paste tokens manually.POST /v1/install/tokenrequires a short-lived one-timedjcboot_...proof and does not acceptDJCONNECT_RELAY_SECRETas a fallback. - Bootstrap proofs are stored hashed, bound to
ha_install_id,client_typeanddevice_id, expire quickly and are marked used after successful token issuance. They are only for Apple push clients (ios,macos,watchos); ESP32, Raspberry Pi, Windows and Assist-agent-only entries do not use APNs push and must not request central API bootstrap proofs. - Bootstrap proof consumption is D1 rate-limited by hashed IP, install ID and device ID keys. Rate-limit rows must not store raw proofs or tokens.
/v1/push/register,/v1/push/unregister,/v1/push/eventand/v1/install/rotaterequire the per-install token for the exactha_install_idin the request body.- Install tokens are stored in D1 only as SHA-256 hashes. The raw token is returned once and is stored by the integration in Home Assistant config entry options.
- Rotate tokens with
/v1/install/rotateusing the current per-install token, or disable a compromised token with the operator-only/v1/operator/install-token/revokeendpoint. Revoke requests useha_install_idplus token ID, never rawdjci_...token material, and do not issue a replacement token. - Admin endpoints such as
GET /v1/admin/registrationsrequire the bootstrap/operator secret and explicitly reject per-installdjci_...tokens.
Support/options UI may expose API URL/token inspection, replacement or rotation controls, but those are operator support paths. They are not the standard user onboarding path and must not reveal global secrets.
This API stores only push routing metadata and minimal audit rows. It must not store:
- raw user prompts
- raw assistant responses
- full chat history
- memory
- Home Assistant API tokens
- Spotify tokens
- APNs provider key material
Apple push payloads are generic wake/sync signals. Send APNs only for
ask_dj_response and ask_dj_confirm; do not push playback, track, queue,
volume, mood, idle, status, polling or Spotify progress updates. Clients fetch
current data from their own Home Assistant instance after opening.
Admin views must be privacy-safe summaries. GET /v1/admin/registrations
returns only operational metadata needed by the DJConnect admin website:
registration ID, hashed install/device identifiers, Home Assistant user hash,
client type, APNs environment, APNs topic, app metadata, locale, categories,
disabled/invalid flags and timestamps.
Admin responses must never include raw APNs tokens, APNs token ciphertext, nonces, encryption key versions, provider keys, relay secrets, Home Assistant tokens, Spotify tokens, raw prompts, assistant responses or chat history. The admin website must read through the admin API and must not query D1 directly.
Logs must only contain token hashes or redacted token snippets. Do not log request bodies for /v1/push/register or /v1/push/event.
APNs tokens are hashed for lookup/audit and encrypted before D1 storage with
AES-GCM using APNS_TOKEN_ENCRYPTION_KEY. New registrations write encrypted
token material to apns_token_ciphertext, apns_token_nonce and
apns_token_key_version; the raw nullable apns_token column is retained only
as a legacy migration fallback for older rows.
Rotate the encryption key only with a deliberate re-encryption/backfill plan.
Do not log decrypted APNs tokens; use hashes or redacted snippets only.
The operator procedure lives in OPERATOR_RUNBOOK.md.
Please report security issues privately to the DJConnect maintainers instead of opening a public issue with exploit details, secrets, tokens, or user data. Include enough information to reproduce the issue without sharing production credentials.