Straight to the point: this Worker rotates two bootstrap secrets on a schedule using a strict 2-slot model: PRIMARY (active) and SECONDARY (previous). No grace windows, no extra slots — deterministic swap only.
Each scheduled run does the following in order:
- Read current PRIMARY bootstrap tokens.
- Copy them to SECONDARY.
- Create two new tokens in parallel.
- Verify both new tokens.
- Overwrite PRIMARY with the new tokens.
A short KV lock prevents overlapping runs. All errors are logged and trigger a single email alert.
- Required bootstrap secrets (must exist):
PRIMARY_TOKEN_CREATION_TOKEN— token used to create Cloudflare account API tokens.PRIMARY_SECRET_EDIT_TOKEN— token used to PUT/UPDATE Secrets Store entries.
- Secondary names written by the worker:
SECONDARY_TOKEN_CREATION_TOKENSECONDARY_SECRET_EDIT_TOKEN
- Lock:
KV_CACHE(KV namespace) used as a short-TTL mutex to avoid concurrent runs. - Handler:
export default { async scheduled(...) }, configured viatriggers.crons. - Alerting: single mail via configured
mailer.send(...)on any failure path.
This design purposefully removes a separate "grace window" state by relying on token TTL and a deterministic two-slot swap. The important properties are:
- New tokens are created with a ~2 hour TTL (configurable in code).
- Rotation runs every hour by default. Because a freshly created token remains valid for ~2 hours, the SECONDARY slot (which holds the previous PRIMARY values) is always a valid fallback if the PRIMARY is unavailable, pending, or otherwise failing during an operation (for example, when the SECRET_EDIT token is used to rotate other secrets).
- In other words: SECONDARY is guaranteed to work as a fallback for at least the next rotation cycle, avoiding complex grace-window logic. This gives deterministic behavior when consumers try to use a token during a rotate: try PRIMARY; if it fails, fallback to SECONDARY.
This simplifies coordination and reduces edge-case complexity: no separate next/current/grace states — just PRIMARY and a guaranteed working SECONDARY.
src/index.ts— TypeScript Worker implementation (scheduled handler + helpers).wrangler.jsonc— bindings (Secrets Store, KV, cron). Populate secret bindings before deploy.worker-configuration.d.ts— generated bynpx wrangler types(recommended for editor types).
- Add these Secrets Store entries (binding name → secret name in the store):
PRIMARY_TOKEN_CREATION_TOKEN,PRIMARY_SECRET_EDIT_TOKEN,SECONDARY_TOKEN_CREATION_TOKEN(can be dummy"1"),SECONDARY_SECRET_EDIT_TOKEN(can be dummy). - Ensure the creation bootstrap token (PRIMARY_TOKEN_CREATION_TOKEN) has rights to create account API tokens.
- Ensure the secret-edit bootstrap token (PRIMARY_SECRET_EDIT_TOKEN) can write to Secrets Store for the target store.
- Set
account_idandKV_CACHEnamespace id inwrangler.jsonc. - Generate types for editor support:
npx wrangler types.
Important operational note: the SECONDARY secret entries must already exist in the Secrets Store at bootstrap time (they can hold any value, including an empty string ""). The worker expects the secondary secret names to be present so the first scheduled run can atomically stage PRIMARY → SECONDARY and then populate PRIMARY with newly-created tokens. The system becomes fully operational only after the first successful rotation when both PRIMARY and SECONDARY contain valid token values.
- Generate types (recommended):
npx wrangler types- Test scheduled handler locally:
npx wrangler dev --test-scheduled- Deploy (use
deploy,publishis deprecated):
npx wrangler deploy- Acquire KV lock (TTL ≈ 300s). If lock is held, exit.
- Read
PRIMARY_TOKEN_CREATION_TOKENandPRIMARY_SECRET_EDIT_TOKEN. - Stage: PUT current PRIMARY values into
SECONDARY_*names (idempotent). - Create: two new tokens in parallel (creation + secret-edit) using the creation bootstrap.
- Verify: confirm both tokens via Cloudflare verify endpoint. If verify fails → abort (PRIMARY unchanged, SECONDARY staged).
- Promote: PUT new tokens into
PRIMARY_*names (overwrite). - Release lock.
- On any error: one log + one notification email; scheduled handler swallows (does not rethrow).
- Keep bootstrap tokens in Cloudflare Secrets Store only — do not commit them to source.
- Scope bootstrap tokens with least privilege. The worker assumes the generated tokens are short-lived (code defaults to ≈2h expiry). Adjust if needed.
- If rotation fails repeatedly, inspect
SECONDARY_*values for last-known-good and logs for failure reasons. - For stronger lock guarantees, replace KV lock with a Durable Object coordinator.
- Run:
npx wrangler types- Include the generated
worker-configuration.d.tsin yourtsconfig.jsonviaincludeorcompilerOptions.typesso your editor recognizesEnvand bindings.
- Two bootstrap bindings only: token-creation + secret-edit.
- Deterministic 2-slot swap:
PRIMARY ← new,SECONDARY ← previous. - Because tokens live ~2 hours and rotation runs every hour, SECONDARY is always a valid fallback if PRIMARY fails.
- KV lock prevents concurrent runs.
- Single email alert on failure.
- Use
npx wrangler deployto deploy.