Skip to content

chore(secrets): rotate cloudflare_api_token to scoped Workers-Edit token#17

Merged
cooper (czxtm) merged 1 commit intomainfrom
chore/rotate-cloudflare-token
Apr 29, 2026
Merged

chore(secrets): rotate cloudflare_api_token to scoped Workers-Edit token#17
cooper (czxtm) merged 1 commit intomainfrom
chore/rotate-cloudflare-token

Conversation

@czxtm
Copy link
Copy Markdown
Contributor

Summary

Rotate the SOPS-stored cloudflare_api_token from cfat_KJ57… to the new cfut_A8wV… token issued with the scopes the Cloudflare provider in alchemy v2 actually needs (Workers Scripts:Edit, Workers Routes:Edit, Account Settings:Read, plus the standard KV / R2 / Secrets-Store edit groups).

This commit was authored on the PR #16 branch but PR #16 was merged before it landed, so main is still using the old token. The post-merge production deploys of Deploy Web and Deploy Docs are 401-ing because the old token lacks Workers Scripts:Read/Edit (the symptom that originally surfaced during PR #16 preview deploys).

Token value pulled from the user's local store via himitsu read cloudflare-api-token and written via sops set --value-stdin so the encryption/recipient set is preserved (the chore: rekey commit on main is fully compatible).

No code change. loadDeployEnv@gen/env reads the new value from SOPS at runtime, so the next push to main picks it up.

Test plan

  • Deploy Web (production) reaches resource creation past the Cloudflare auth check
  • Deploy Docs (production) reaches resource creation past the Cloudflare auth check
  • No regression in PR-preview deploys (which use localState(), no Cloudflare token needed for state)

Replace the old `cfat_KJ57…` token (which lacked Workers Scripts:Edit
and triggered "Unauthorized: Authentication error" 401s during
PR-16 web/docs Worker deploys) with the new `cfut_…` token issued
with the scopes required by the Cloudflare Worker provider:
Workers Scripts:Edit, Workers Routes:Edit, Account Settings:Read,
plus the standard Workers KV / R2 / Secrets Store edit groups so
future Cloudflare.state() bootstrapping works for staging/prod.

Read via `himitsu read cloudflare-api-token`; encrypted into
.stack/secrets/vars/shared.sops.yaml under the same key, so
loadDeployEnv → @gen/env automatically picks it up at runtime
without any code change.
@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 29, 2026

PR Summary

Medium Risk
While the change is small, it directly affects production deployment/authentication to Cloudflare; an incorrect or under-scoped token would break deploys or resource updates.

Overview
Updates the SOPS-encrypted .stack/secrets/vars/shared.sops.yaml to replace the stored cloudflare_api_token with a newly encrypted value (metadata lastmodified/mac updated accordingly).

No application code changes; this is a credentials rotation intended to restore/maintain Cloudflare API access for deployment automation.

Reviewed by Cursor Bugbot for commit 2d1d1db. Configure here.

@czxtm cooper (czxtm) merged commit d9c3b0d into main Apr 29, 2026
1 of 2 checks passed
@czxtm cooper (czxtm) deleted the chore/rotate-cloudflare-token branch April 29, 2026 11:08
cooper (czxtm) added a commit that referenced this pull request Apr 29, 2026
PR #17 rotated the Cloudflare API token in `.stack/secrets/vars/shared.sops.yaml`
but did not regenerate the codegen-emitted runtime payload at
`packages/gen/env/src/runtime/generated-payloads/_envs/deploy.ts`. The
embedded JSON is what `loaders.deploy()` actually decrypts at runtime, so
both `main` and this branch have continued shipping the old `cfat_KJ57…`
token (which lacks `Workers Scripts: Edit`) into CI — explaining why every
post-rotation deploy still fails with `Unauthorized: Authentication error`
despite the underlying SOPS YAML being correct.

Re-running the devshell hook on this branch regenerates both the encrypted
data file and the TypeScript module from the (already-rotated) source YAML.
Decrypting the regenerated payload yields `cfut_A8wV…` (verified locally)
and the `curl` probe earlier confirmed that token has full read+write
scopes for `workers/scripts`, `workers/subdomain`, `kv/namespaces`,
`zones/.../workers/routes`, and `workers/domains` — i.e. exactly what
`Cloudflare.Worker` needs.

Plaintext for every other secret in the payload is unchanged; only IVs and
ciphertext rotated as a side effect of SOPS re-encrypting the whole file.

Follow-up (separate change): `chore: rekey`-style flows and the source SOPS
edit path should both trigger codegen so this drift can't happen silently
again. Filing as a beads issue.
cooper (czxtm) added a commit that referenced this pull request Apr 29, 2026
PR #17 rotated the Cloudflare API token in `.stack/secrets/vars/shared.sops.yaml`
but did not regenerate the codegen-emitted runtime payload at
`packages/gen/env/src/runtime/generated-payloads/_envs/deploy.ts`. The
embedded JSON is what `loaders.deploy()` actually decrypts at runtime, so
both `main` and this branch have continued shipping the old `cfat_KJ57…`
token (which lacks `Workers Scripts: Edit`) into CI — explaining why every
post-rotation deploy still fails with `Unauthorized: Authentication error`
despite the underlying SOPS YAML being correct.

Re-running the devshell hook on this branch regenerates both the encrypted
data file and the TypeScript module from the (already-rotated) source YAML.
Decrypting the regenerated payload yields `cfut_A8wV…` (verified locally)
and the `curl` probe earlier confirmed that token has full read+write
scopes for `workers/scripts`, `workers/subdomain`, `kv/namespaces`,
`zones/.../workers/routes`, and `workers/domains` — i.e. exactly what
`Cloudflare.Worker` needs.

Plaintext for every other secret in the payload is unchanged; only IVs and
ciphertext rotated as a side effect of SOPS re-encrypting the whole file.

Follow-up (separate change): `chore: rekey`-style flows and the source SOPS
edit path should both trigger codegen so this drift can't happen silently
again. Filing as a beads issue.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant