Skip to content

Secrets

Purpose

Explain the difference between GitHub Actions secrets and Cloudflare Worker secrets and document which ones this repository currently requires.

Two different secret stores

GitHub Actions secrets Cloudflare Worker secrets
Where set Repo → Settings → Secrets and variables → Actions wrangler secret put <NAME> --config <path>
Who reads them GitHub Actions workflow runs Deployed Worker runtime via env.<NAME>
Stored in git? No No
Example CLOUDFLARE_API_TOKEN OPERATIONS_API_TOKEN

A GitHub Actions secret authorizes a deployment process. A Cloudflare Worker secret is runtime configuration consumed by deployed code. Setting one does not set the other.

GitHub Actions secrets

Secret Purpose
CLOUDFLARE_API_TOKEN authenticate Wrangler migrations/deployments
CLOUDFLARE_ACCOUNT_ID identify the target Cloudflare account

The D1 database id is a non-secret resource identifier committed in Wrangler configuration. Use a least-privilege Cloudflare API token with only the resources/actions required by this repository's Worker/D1/R2 deployment flow.

Cloudflare Worker secrets

Central API Worker

npm run configure:turnstile:sitekey
npm run configure:turnstile:secret
npm run configure:operations:token

OPERATIONS_API_TOKEN is required for protected Logistics/Commerce operational endpoints. It is server-to-server only and must never appear in VITE_*, React source, browser storage, public config, commits, issues or PR text.

Admin Worker

npm run configure:admin:bootstrap
npm run configure:admin:mfa-key

ADMIN_BOOTSTRAP_TOKEN is required only for the first administrator bootstrap on a fresh database.

ADMIN_MFA_ENCRYPTION_KEY is required before an Admin can enroll TOTP MFA. Use a strong random value of at least 32 characters. The Admin Worker derives an AES-GCM key from it to encrypt authenticator secrets before D1 storage. The key is never returned by an API or sent to browser code.

MFA is opt-in per Admin, so a missing MFA encryption key does not break existing password-only Admin accounts. Setup fails closed until the key is configured. An already-enrolled Admin may still use an unused hashed recovery code if the encryption key is temporarily unavailable.

Rotating ADMIN_MFA_ENCRYPTION_KEY requires a migration/re-encryption plan for existing enrolled TOTP secrets. Do not simply replace it after Admins have enrolled, because the old ciphertext cannot be decrypted with a new key. Recovery codes remain usable because they are independent one-way hashes.

Corporate + Commerce Workers

npm run configure:corporate:commerce-sso-secret
npm run configure:commerce:sso-secret
npm run configure:commerce:operations-token

CUSTOMER_SSO_SECRET must be the exact same strong value on Corporate and Commerce. Corporate signs the short-lived customer handoff token; Commerce verifies it. Both sides require at least 32 characters and fail closed when missing/mismatched.

The Commerce OPERATIONS_API_TOKEN must equal the value on the central API because Commerce is a trusted server-side caller, not a separate security domain.

Logistics Worker

npm run configure:logistics:operations-token

The Logistics Worker also uses the same central OPERATIONS_API_TOKEN for its server-to-server Commerce fulfilment bridge. The React browser never receives this token.

Setting/rotating a Worker secret

npx wrangler secret put <SECRET_NAME> --config <worker-wrangler-path>

Wrangler prompts for the value so it does not need to appear in source or command-line arguments. Rotating a Worker secret changes runtime behavior independently of application source.

For OPERATIONS_API_TOKEN, coordinate rotation across the central API, Commerce Worker and Logistics Worker so all trusted callers use the same value.

Rotating CLOUDFLARE_API_TOKEN

  1. Create a replacement Cloudflare API token with minimum required deployment permissions.
  2. Update repository secret CLOUDFLARE_API_TOKEN.
  3. Confirm a production deployment succeeds with the replacement.
  4. Revoke the old token only after the new one has been proven.

What is not a secret

NOTIFICATION_EMAIL and ALLOWED_ORIGINS are plain Worker vars. Cloudflare resource ids such as a D1 database_id identify resources but do not authenticate access and may be committed.

Security considerations

  • Never echo secret values in Actions logs.
  • Never copy runtime secrets into browser configuration.
  • If a credential is exposed, rotate it immediately; reverting a commit does not invalidate it.
  • Protect main with repository rules in addition to the workflow's merged-PR production gate.