Ir al contenido

Secrets & Access Management Runbook

Policy: All secrets are stored as GitHub Actions Secrets — never in code or config files.


Secret NameWhat It GrantsUsed By WorkflowsExpiryWhere Stored
INEGI_API_TOKENRead access to INEGI data APIs (census indicators, DENUE economic units)data-ingest.ymlCheck INEGI developer portal (typically no hard expiry, but can be revoked)GitHub Actions Secret
R2_ACCOUNT_IDCloudflare Account ID scoping R2 API callsdata-ingest.yml, data-transform.ymlNever (static identifier)GitHub Actions Secret
R2_ACCESS_KEY_IDS3-compatible access key for urban-transparency-pipeline-rw tokendata-ingest.yml, data-transform.ymlNo expiry unless rotated manuallyGitHub Actions Secret
R2_SECRET_ACCESS_KEYSecret half of the urban-transparency-pipeline-rw R2 tokendata-ingest.yml, data-transform.ymlNo expiry unless rotated manuallyGitHub Actions Secret
CF_ACCOUNT_IDCloudflare Account ID for Pages deploymentdeploy.ymlNever (static identifier)GitHub Actions Secret
CF_API_TOKENCloudflare API token scoped to Pages deploy onlydeploy.ymlNo expiry unless revoked manuallyGitHub Actions Secret
GITHUB_TOKENGitHub API token for posting PR preview commentsdeploy.ymlAuto-rotated per workflow runAuto-injected by GitHub Actions — no setup required

Note: R2_ACCOUNT_ID and CF_ACCOUNT_ID hold the same Cloudflare Account ID value. They are separate secrets because they are consumed by workflows that authenticate to different Cloudflare services with different API tokens.


urban-transparency-pipeline-rw (R2 token → R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY)

Sección titulada «urban-transparency-pipeline-rw (R2 token → R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY)»
  • Permissions: Account → R2 Storage → Edit (read, write, delete objects)
  • Scope: urban-transparency-raw + urban-transparency-processed buckets only
  • Do NOT grant Workers KV, D1, or other Cloudflare services
  • Permissions: Account → Cloudflare Pages → Edit
  • Scope: the urban-transparency-platform Pages project only
  • Do NOT grant R2, Workers, or DNS edit permissions
  • Obtained from the INEGI developer portal
  • Read-only access to public statistical APIs
  • No write capabilities

Rotate R2 API Keys (R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY)

Sección titulada «Rotate R2 API Keys (R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY)»
  1. Go to Cloudflare Dashboard → R2 → Manage R2 API Tokens
  2. Select urban-transparency-pipeline-rw
  3. Click Roll Token (generates new Access Key ID + Secret)
  4. Note both values immediately (shown once)
  5. Update GitHub Actions Secrets:
    • R2_ACCESS_KEY_ID ← new Access Key ID
    • R2_SECRET_ACCESS_KEY ← new Secret Access Key
  6. Delete the old token entry
  7. Verify next pipeline run succeeds
  1. Go to Cloudflare Dashboard → My Profile → API Tokens
  2. Find the Pages deploy token, click Roll
  3. Note the new token value
  4. Update GitHub Actions Secret CF_API_TOKEN
  5. Verify next deploy.yml run succeeds
  1. Log into INEGI developer portal
  2. Navigate to your application → Regenerate Token
  3. Update GitHub Actions Secret INEGI_API_TOKEN
  4. Verify next data-ingest.yml run completes the inegi-ingest job

For a New Board Member (human) who needs to manage secrets

Sección titulada «For a New Board Member (human) who needs to manage secrets»

Prerequisites: GitHub organization owner or admin role on the repository.

  1. Cloudflare access: Request a Cloudflare account invitation with the Administrator role scoped to the relevant account from the existing account owner.
  2. GitHub repo access: Request Admin role on the GitHub repository to be able to manage Actions Secrets.
  3. Review existing secrets: Go to GitHub repo → Settings → Secrets and variables → Actions to view secret names (values are masked).
  4. Review this document to understand what each secret does before rotating or modifying.

For a New Agent (automated) that needs to run pipelines

Sección titulada «For a New Agent (automated) that needs to run pipelines»

Agents do not receive direct secret access. All pipeline execution is via GitHub Actions. An agent that needs to trigger workflows should:

  1. Receive the GITHUB_TOKEN pattern via the workflow’s built-in token (no additional setup).
  2. If a custom PAT is needed to trigger workflow_dispatch from another workflow, request a scoped fine-grained PAT from a board member:
    • Scope: Actions → Write on the specific repository only
    • Store as a new named secret (e.g., GH_DISPATCH_TOKEN)

Secrets an operator needs when provisioning from scratch

Sección titulada «Secrets an operator needs when provisioning from scratch»

If standing up a fresh environment (new Cloudflare account, new GitHub repo), collect these secrets in order:

StepActionSecret(s) Created
1Note your Cloudflare Account ID (Dashboard → top-right account menu)R2_ACCOUNT_ID, CF_ACCOUNT_ID
2Create R2 buckets (docs/r2-setup.md § 1)
3Create R2 API token urban-transparency-pipeline-rw (docs/r2-setup.md § 3)R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY
4Create Cloudflare Pages deploy token (docs/r2-setup.md § 3 pattern, Pages scope)CF_API_TOKEN
5Obtain INEGI API token from INEGI developer portalINEGI_API_TOKEN
6Add all secrets to GitHub repo → Settings → Secrets and variables → Actions
7Trigger workflow_dispatch on data-ingest.yml to validate end-to-end

If R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY are compromised

Sección titulada «If R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY are compromised»
  1. Immediately go to Cloudflare Dashboard → R2 → Manage R2 API Tokens
  2. Delete the urban-transparency-pipeline-rw token — this invalidates all calls immediately
  3. Check R2 access logs for unauthorized reads/writes (Cloudflare Dashboard → R2 → bucket → Metrics)
  4. Re-provision a new token following the rotation procedure (§ 3)
  5. File an incident note in the relevant GitHub issue
  1. Go to Cloudflare Dashboard → My Profile → API Tokens
  2. Click Revoke next to the Pages deploy token — effective immediately
  3. No deployed assets are affected (Cloudflare Pages retains the last successful deploy)
  4. Re-provision following § 3
  1. Log into INEGI developer portal and revoke the token
  2. Request a new token
  3. Update GitHub Actions Secret
  1. Go to GitHub repo → Settings → Secrets and variables → Actions
  2. Delete all secrets
  3. Rotate all underlying credentials (all Cloudflare tokens via Dashboard)
  4. Re-add secrets after the incident is contained

Review this checklist quarterly or after any incident:

  • All secrets listed in § 1 are present in GitHub Actions Secrets
  • urban-transparency-pipeline-rw R2 token is scoped to R2 Storage only (no extra permissions)
  • CF_API_TOKEN is scoped to Cloudflare Pages only
  • No credentials appear in git history (git log -p | grep -i "token\|secret\|key\|password")
  • No credentials appear in .env files or committed config files
  • INEGI token is still active (test: trigger data-ingest.yml manually)
  • All workflows complete without credential errors