Status: Phase 2 in progress — Cloudflare rename complete (#754); other vendors pending Owner: operator / sre-agent Last updated: 2026-05-01 UTC Tracking: #754 (CF token rename), refs #81 (Epic: SDLC, Tooling, and Security Hardening)
Related issues: #402 (secrets-store org review), #596 (env coverage audit), #747 (WAF token gap), #253 (rotation pipelines)
As of 2026-04-30 the vault at vault.raxx.app has 20+ credentials across 8 vendors. Several pain points have emerged:
CLOUDFLARE_RAXX_AUTOMATION_API_TOKEN was tested against multiple CF endpoints before an SRE agent confirmed it was missing WAF Edit scope (see #747).This document locks in a taxonomy that solves all four.
<VENDOR>_<FUNCTION>_<SCOPE><VENDOR> two-to-four-letter vendor code (CF, HK, PM, AWS, ANT, GH, STR, ALP, INF, SL)
<FUNCTION> verb-noun describing what the token does (DNS_EDIT, WAF_EDIT, PAGES_DEPLOY, etc.)
<SCOPE> optional — only present when a vendor issues the same function-type for multiple targets
Examples:
| Proposed name | Vendor | Function | Scope |
|---|---|---|---|
CF_DNS_EDIT_RAXX_APP |
Cloudflare | DNS record write | raxx.app zone |
CF_DNS_EDIT_GETRAXX_COM |
Cloudflare | DNS record write | getraxx.com zone |
CF_WAF_EDIT_RAXX_APP |
Cloudflare | WAF rule write | raxx.app zone |
CF_PAGES_DEPLOY |
Cloudflare | Pages project deploy | account-wide |
CF_ACCESS_MGMT |
Cloudflare | Access app configuration | account-wide |
CF_ACCESS_SVC_VAULT |
Cloudflare | CF Access service token — vault bypass | vault.raxx.app |
CF_ACCESS_SVC_CONSOLE |
Cloudflare | CF Access service token — console bypass | console.raxx.app |
HK_PLATFORM_FULL |
Heroku | Platform API full-account | account-wide |
PM_SERVER_MAIL |
Postmark | Transactional email send (server scope) | raxx.app server |
PM_ACCOUNT_MGMT |
Postmark | Account admin (create servers, view stats) | account-wide |
AWS_INFISICAL_BOOTSTRAP |
AWS IAM | Lightsail + Cloudflare bootstrap only | infisical-bootstrap user |
AWS_BILLING_READ |
AWS IAM | Cost Explorer read | account-wide |
ANT_CLAUDE_SDK |
Anthropic | Claude API SDK calls | account-wide |
GH_READONLY |
GitHub | Read-only repo + org API | MooseQuest org |
GH_APP_DEV_BOT |
GitHub App | dev-bot installation token source | raxx-dev-bot App |
GH_APP_OPS_BOT |
GitHub App | ops-bot installation token source | raxx-ops-bot App |
GH_APP_PM_BOT |
GitHub App | pm-bot installation token source | raxx-pm-bot App |
STR_BILLING_WRITE |
Stripe | Restricted key — billing/subscription write | account-wide |
ALP_PAPER_TRADING |
Alpaca | Paper trading API | paper account |
ALP_LIVE_TRADING |
Alpaca | Live trading API | live account |
INF_SVC_DISPATCHER |
Infisical | Service token — agent dispatcher read | /MooseQuest/raxx--bot/ |
SL_BOT_NOTIFY |
Slack | Bot token — Slack notification DMs | MooseQuest workspace |
Two alternatives were evaluated:
Option A — deeper path, shorter names:
/MooseQuest/cloudflare/dns-edit/RAXX_APP_TOKEN
/MooseQuest/cloudflare/waf-edit/RAXX_APP_TOKEN
Advantage: path carries the metadata, secret name is just TOKEN.
Problem: Infisical's feedback_vault_folder_must_exist.md constraint means every leaf folder must be pre-created. Four Cloudflare function-types = four folders to manage. More surface area for folder-creation 404s. Path segments do not appear in audit log snippets — you need the full path context to understand the audit trail.
Option B — vendor flat with fully-qualified name (chosen):
/MooseQuest/cloudflare/CF_DNS_EDIT_RAXX_APP
/MooseQuest/cloudflare/CF_WAF_EDIT_RAXX_APP
Advantage: the secret name is self-describing. Audit log entries, vault list output, Slack alerts, and console UI all show the key name without needing path context. One folder per vendor (already created). Consumer code reads CF_DNS_EDIT_RAXX_APP and anyone reading the code knows the function and scope without looking up a mapping.
Decision: Option B. One folder per vendor, self-describing key names. The <VENDOR>_<FUNCTION>_<SCOPE> pattern carries enough context in the name alone.
HK_PLATFORM_FULL — Heroku has one account).CF_DNS_EDIT_RAXX_APP vs. CF_DNS_EDIT_GETRAXX_COM)._FULL suffix when the token has unrestricted (admin) access to its function domain — signals to provisioners that least-privilege is not achieved and a scoped replacement should be prioritized.Companion metadata fields use double-underscore suffix convention:
CF_DNS_EDIT_RAXX_APP__EXPIRES_AT — ISO-8601 UTC expiryCF_DNS_EDIT_RAXX_APP__SCOPES — space-separated vendor scope names (for quick audit without hitting vendor API)CF_ACCESS_SVC_VAULT__CLIENT_ID — paired ID for CF Access service tokensTags are applied in Infisical on each secret. Four dimensions — no more.
function: — What the token does| Tag | Meaning |
|---|---|
function:dns-edit |
Write DNS records at vendor |
function:waf-edit |
Create/modify WAF / firewall rules |
function:pages-deploy |
Deploy to Cloudflare Pages or equivalent CDN |
function:access-mgmt |
Configure CF Access apps, policies, service tokens |
function:access-bypass |
CF Access service token that bypasses Access gate |
function:platform-api |
Full platform admin key (Heroku, AWS account-level) |
function:mail-send |
Send transactional email |
function:mail-admin |
Manage mail servers / accounts |
function:billing-read |
Read billing + cost data |
function:billing-write |
Write billing / subscription (Stripe) |
function:trading-paper |
Paper trading API calls |
function:trading-live |
Live trading API calls (production money) |
function:ai-sdk |
Call LLM API (Anthropic Claude) |
function:ci-deploy |
Used by CI/CD pipelines for deploy |
function:agent-identity |
GitHub App identity source for bot agents |
function:repo-read |
Read-only access to version control / repo API |
function:vault-read |
Read secrets from Infisical |
function:notify |
Send notifications (Slack, webhook) |
sensitivity: — Production risk if leaked| Tag | Criteria |
|---|---|
sensitivity:critical |
Leak enables live-money trades, production data deletion, or account takeover. E.g., live trading key, Heroku full platform key. |
sensitivity:high |
Leak enables production write on infra (DNS, WAF, Access, deploy). E.g., CF_DNS_EDIT_RAXX_APP, CF_WAF_EDIT_RAXX_APP. |
sensitivity:medium |
Leak enables staging/paper operations, cost exposure, or operational disruption without production data risk. E.g., paper trading keys, billing-read. |
sensitivity:low |
Read-only or dev-only tokens. Leak is embarrassing but not operationally damaging. E.g., GH_READONLY. |
consumer: — Which system uses the token| Tag | Meaning |
|---|---|
consumer:ci |
GitHub Actions workflows |
consumer:console |
raxx-console backend (vault.py reads at boot) |
consumer:agent |
Agent dispatch (mint_github_token.py, sre-agent, pm-agent, etc.) |
consumer:operator |
Direct operator CLI use (terraform, ad-hoc scripts) |
consumer:raptor |
backend_v2 (Raptor) runtime |
consumer:terraform |
Terraform provider auth |
Multiple consumer tags are allowed on one secret (e.g., a DNS token used by both Terraform and CI).
rotation: — Cadence| Tag | Meaning |
|---|---|
rotation:30d |
Monthly — high-privilege programmatic keys (AWS IAM access keys) |
rotation:60d |
Every two months — live trading keys |
rotation:90d |
Quarterly — standard rotation for most tokens |
rotation:180d |
Semi-annual — lower-risk tokens, operator-heavy rotation |
rotation:annual |
Once a year — GitHub App private keys, long-lived identities |
rotation:non-rotating |
Does not rotate by design (e.g., AWS Account ID — a config value, not a secret) |
__SCOPES field. Tags say what the token broadly does; __SCOPES documents the exact vendor permission strings.sensitivity:critical requires a paired ops review in the provisioning PR — no solo provisioning.Infisical environments: prod, staging, dev.
Rule 1 — Env-specific credentials live in both prod and staging with different values. If the vendor isolates accounts or projects by environment (separate Heroku apps, separate Alpaca paper accounts), the token must have env-specific values. Both envs are populated, values differ.
Rule 2 — Account-wide tokens that serve all environments live in prod only, consumed by both.
A Cloudflare account token (DNS, WAF, CF Access) controls the whole account regardless of whether a staging or prod deploy calls it. There is one Cloudflare account. Store in prod; consumers in staging read from prod path explicitly. Do NOT duplicate with an identical value into staging — duplicates drift and cause "which env's value is real?" confusion.
Rule 3 — Dev environment is populated only for tokens that have a dev-mode analog.
Most secrets do not have a dev analog (there is no "dev CF account"). Dev env in Infisical stays sparse. Local dev uses .env files (gitignored). Infisical dev is used only for tokens where the vendor offers sandbox/test mode keys (e.g., Stripe test-mode key = dev env).
| Token | Prod | Staging | Dev | Notes |
|---|---|---|---|---|
CF_DNS_EDIT_RAXX_APP |
yes | no — reads prod | no | One CF account; staging CI uses the same token |
CF_DNS_EDIT_GETRAXX_COM |
yes | no | no | Same |
CF_WAF_EDIT_RAXX_APP |
yes | no | no | Same |
CF_PAGES_DEPLOY |
yes | no | no | CF Pages has one project; envs are CF Pages environments not Infisical envs |
CF_ACCESS_MGMT |
yes | no | no | Account-wide |
CF_ACCESS_SVC_VAULT |
yes | yes (separate token) | no | Staging may need its own service token if Access policies differ |
CF_ACCESS_SVC_CONSOLE |
yes | yes (separate token) | no | Same |
HK_PLATFORM_FULL |
yes | yes (different key) | no | Heroku has separate staging + prod apps; platform key may be same account but should be scoped per app post-hardening |
PM_SERVER_MAIL |
yes | yes (different key) | no | Separate Postmark servers for prod/staging |
PM_ACCOUNT_MGMT |
yes | no | no | Account-wide admin |
AWS_INFISICAL_BOOTSTRAP |
yes | no | no | Single IAM user; not replicated |
AWS_BILLING_READ |
yes | no | no | Account-wide |
ANT_CLAUDE_SDK |
yes | no | no | One Anthropic account; staging + dev share prod key |
GH_READONLY |
yes | no | no | One GitHub org |
GH_APP_DEV_BOT |
yes | no | no | One GitHub App installation |
GH_APP_OPS_BOT |
yes | no | no | Same |
GH_APP_PM_BOT |
yes | no | no | Same |
STR_BILLING_WRITE |
yes | no | dev (test key) | Stripe test-mode key goes in dev env |
ALP_PAPER_TRADING |
yes | yes (different key) | no | Paper account can have separate keys per env |
ALP_LIVE_TRADING |
yes | no | no | Never in staging |
INF_SVC_DISPATCHER |
yes | no | no | Dispatcher reads only prod secrets |
SL_BOT_NOTIFY |
yes | no | no | One Slack workspace |
All tokens currently known in vault or referenced in rotation matrix / issues, grouped by vendor.
/MooseQuest/cloudflare/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
CLOUDFLARE_EDIT_DNS |
CF_DNS_EDIT_RAXX_APP |
Write DNS records for raxx.app zone | Zone > DNS > Edit, Zone > Zone > Read | consumer:terraform, consumer:ci |
sensitivity:high |
rotation:90d |
CLOUDFLARE_RAXX_AUTOMATION_API_TOKEN |
CF_PAGES_DEPLOY |
Deploy to CF Pages + Access app read | Account > Cloudflare Pages > Edit, Zone > Zone > Read | consumer:ci |
sensitivity:high |
rotation:90d |
CLOUDFLARE_ACCESS_MGMT_TOKEN |
CF_ACCESS_MGMT |
Manage CF Access applications and policies | Account > Access: Apps and Policies > Edit | consumer:terraform, consumer:operator |
sensitivity:high |
rotation:90d |
CLOUDFLARE_PAGES_DEPLOY_TOKEN |
CF_PAGES_DEPLOY |
Deploy to CF Pages (if distinct from automation token) | Account > Cloudflare Pages > Edit | consumer:ci |
sensitivity:high |
rotation:90d |
| (missing) | CF_WAF_EDIT_RAXX_APP |
Write WAF + rate-limit rules for raxx.app zone | Zone > WAF > Edit, Zone > Zone > Read | consumer:ci, consumer:operator |
sensitivity:high |
rotation:90d |
| (missing) | CF_DNS_EDIT_GETRAXX_COM |
Write DNS records for getraxx.com zone | Zone > DNS > Edit, Zone > Zone > Read | consumer:terraform |
sensitivity:high |
rotation:90d |
Note:
CLOUDFLARE_RAXX_AUTOMATION_API_TOKENandCLOUDFLARE_PAGES_DEPLOY_TOKENmay overlap in scope — Kristerpher should confirm whether these are the same token stored under two names or two distinct tokens. If the same, one should be deprecated after migration. See Section 7 open question.
/MooseQuest/cloudflare/)| Current name | Proposed name | Function | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|
CF_ACCESS_SERVICE_TOKEN_CONSOLE |
CF_ACCESS_SVC_CONSOLE |
Bypass CF Access gate for console.raxx.app | consumer:ci, consumer:console |
sensitivity:medium |
rotation:90d |
CF_ACCESS_SERVICE_TOKEN_VAULT_PROBE |
CF_ACCESS_SVC_VAULT |
Bypass CF Access gate for vault.raxx.app (agent dispatcher) | consumer:agent |
sensitivity:high |
rotation:90d |
/MooseQuest/heroku/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
HEROKU_API_KEY |
HK_PLATFORM_FULL |
Full Heroku platform admin — all apps | Full account (Heroku tokens are not scoped) | consumer:ci |
sensitivity:critical |
rotation:90d |
HEROKU_PLATFORM_API_TOKEN |
HK_PLATFORM_FULL |
Appears to duplicate the above — confirm | Full account | consumer:ci |
sensitivity:critical |
rotation:90d |
Note: Two Heroku entries in the rotation matrix (
HEROKU_API_KEYandHEROKU_PLATFORM_API_TOKEN) likely refer to the same logical credential. Confirm and deduplicate; see Section 7.
/MooseQuest/postmark/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
POSTMARK_SERVER_API_KEY |
PM_SERVER_MAIL |
Send transactional email from raxx.app server | Server token (send only for one server) | consumer:raptor |
sensitivity:medium |
rotation:180d |
POSTMARK_ACCOUNT_API_KEY |
PM_ACCOUNT_MGMT |
Account admin — create/configure servers | Account API token | consumer:operator |
sensitivity:high |
rotation:180d |
/MooseQuest/aws/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
AWS_ACCESS_KEY_ID |
AWS_INFISICAL_BOOTSTRAP (key component) |
Lightsail VM ops + CF bootstrap | Lightsail full, limited IAM user (claude-infisical-bootstrap) |
consumer:operator |
sensitivity:high |
rotation:30d |
AWS_SECRET_ACCESS_KEY |
AWS_INFISICAL_BOOTSTRAP (secret component) |
Paired with above | Same | consumer:operator |
sensitivity:high |
rotation:30d |
AWS key pairs are stored as companion secrets:
AWS_INFISICAL_BOOTSTRAP__ACCESS_KEY_IDandAWS_INFISICAL_BOOTSTRAP__SECRET_ACCESS_KEY. The base key name is the logical credential; suffixes are the two components. This avoids a_KEY_ID/_SECRET_KEYnaming ambiguity.
/MooseQuest/anthropic/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
ANTHROPIC_API_KEY |
ANT_CLAUDE_SDK |
Call Claude API (all SDK-capable models) | Account-level API key | consumer:agent, consumer:raptor |
sensitivity:high |
rotation:90d |
/MooseQuest/github/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
GITHUB_API_READONLY_TOKEN |
GH_READONLY |
Read-only repo + org metadata | Contents:read, Metadata:read | consumer:agent |
sensitivity:low |
rotation:90d |
/MooseQuest/raxx-dev-bot/, /MooseQuest/raxx-ops-bot/, /MooseQuest/raxx-pm-bot/)Each bot path holds three companion secrets (APP_ID, INSTALLATION_ID, PRIVATE_KEY_PEM). Under the new taxonomy these are grouped as one logical credential per bot:
| Logical credential | Path | Function | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|
GH_APP_DEV_BOT |
/MooseQuest/raxx-dev-bot/ |
Source of installation tokens for raxx-dev-bot[bot] | consumer:agent |
sensitivity:high |
rotation:annual |
GH_APP_OPS_BOT |
/MooseQuest/raxx-ops-bot/ |
Source of installation tokens for raxx-ops-bot[bot] | consumer:agent |
sensitivity:high |
rotation:annual |
GH_APP_PM_BOT |
/MooseQuest/raxx-pm-bot/ |
Source of installation tokens for raxx-pm-bot[bot] | consumer:agent |
sensitivity:high |
rotation:annual |
Bot key paths retain their existing path structure (
/MooseQuest/raxx-*-bot/) because mint_github_token.py hard-codes these paths. Rename only after updating the script.
/MooseQuest/stripe/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
STRIPE_RESTRICTED_KEY |
STR_BILLING_WRITE |
Create/manage subscriptions, customers, invoices | Restricted key: Customers write, Subscriptions write, Invoices read | consumer:raptor |
sensitivity:critical |
rotation:90d |
/MooseQuest/alpaca/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
ALPACA_PAPER_API_KEY_ID |
ALP_PAPER_TRADING (key component) |
Paper trading API | Paper trading (key+secret pair) | consumer:raptor |
sensitivity:medium |
rotation:180d |
ALPACA_PAPER_API_SECRET_KEY |
ALP_PAPER_TRADING (secret component) |
Paired with above | Same | consumer:raptor |
sensitivity:medium |
rotation:180d |
ALPACA_LIVE_API_KEY_ID |
ALP_LIVE_TRADING (key component) |
Live trading API (real money) | Live trading (key+secret pair) | consumer:raptor |
sensitivity:critical |
rotation:60d |
ALPACA_LIVE_API_SECRET_KEY |
ALP_LIVE_TRADING (secret component) |
Paired with above | Same | consumer:raptor |
sensitivity:critical |
rotation:60d |
Alpaca key pairs use the
__KEY_ID/__SECRET_KEYcompanion pattern:ALP_PAPER_TRADING__KEY_IDandALP_PAPER_TRADING__SECRET_KEY.
/MooseQuest/infisical/)| Current name | Proposed name | Function | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|
INFISICAL_SERVICE_TOKEN |
INF_SVC_DISPATCHER |
Machine identity client secret — agent dispatcher reads bot key paths | consumer:agent |
sensitivity:high |
rotation:90d |
/MooseQuest/slack/)| Current name | Proposed name | Function | Required vendor scopes | Consumer(s) | Sensitivity | Rotation |
|---|---|---|---|---|---|---|
BOT_USER_SLACK_TRADING_MASTER_API |
SL_BOT_NOTIFY |
Send Slack DM notifications to operator | chat:write, im:write | consumer:raptor, consumer:agent |
sensitivity:medium |
rotation:annual |
| Current name | Proposed name | Function | Consumer(s) | Sensitivity | Rotation | Notes |
|---|---|---|---|---|---|---|
DREAMHOST_API_KEY |
DH_DNS_MGMT |
DreamHost hosting/DNS management | consumer:operator |
sensitivity:medium |
rotation:90d |
Evaluate whether still needed |
DYN_PASSWORD |
DYN_DNS_UPDATE |
Oracle Dyn DNS update | consumer:operator |
sensitivity:medium |
rotation:180d |
Migration off Dyn recommended (#402 follow-up) |
When a new token needs to be created, walk these steps in order. Steps 1-4 are one-time per token; step 5 is done whenever a new consumer is wired up.
function: tag if possible; if new, propose to this doc as a PR first).<VENDOR>_<FUNCTION>[_<SCOPE>]/MooseQuest/<vendor-lowercase>/ — verify the folder exists in Infisical before writing. If not, create via POST /api/v1/folders (per feedback_vault_folder_must_exist.md).| Vendor | Dashboard URL | Notes |
|---|---|---|
| Cloudflare | https://dash.cloudflare.com/profile/api-tokens |
Use "Create Custom Token"; set Zone Resources to the specific zone |
| Cloudflare Access | CF Zero Trust → Access → Service Auth → Service Tokens | Duration = 1 year; apply Service Auth policy to the target Access app |
| Heroku | https://dashboard.heroku.com/account → "API Key" |
No scope isolation available; treat as full account |
| Postmark | https://account.postmarkapp.com/servers → Server → API Tokens |
Server token is per-server; account token is global |
| AWS | AWS Console → IAM → Users → claude-infisical-bootstrap → Security credentials |
Rotate the existing key; do not create additional users without approval |
| Anthropic | https://console.anthropic.com/settings/keys |
Account-level; no scope isolation |
| GitHub (PAT) | https://github.com/settings/tokens |
Fine-grained PATs preferred; limit to MooseQuest org and minimum permissions |
| GitHub (App) | https://github.com/apps/<appname> → Settings → Private Keys |
Generate new key on existing App; do NOT create a new App without architectural review |
| Stripe | https://dashboard.stripe.com/apikeys → "Create restricted key" |
Specify only the write permissions needed; never use secret key directly |
| Alpaca | https://app.alpaca.markets → Account → API → Create New Key |
Separate keys for paper vs. live environments |
| Infisical | vault.raxx.app → Access Control → Identities → Create Machine Identity |
Use Universal Auth; assign read-only role scoped to the paths needed |
# 1. Verify folder exists (or create it)
curl -s -H "Authorization: Bearer $INFISICAL_TOKEN" \
-H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
-H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
"https://vault.raxx.app/api/v1/folders?workspaceId=$PROJECT_ID&environment=prod&path=/MooseQuest/<vendor>"
# 2. Create the secret
# (Use Infisical UI for first provisioning; use rotation pipeline for subsequent rotations)
# 3. Create companion secrets (always):
# <NAME>__EXPIRES_AT = ISO-8601 UTC expiry or "non-expiring"
# <NAME>__SCOPES = space-separated vendor scope strings
In Infisical UI → select secret → Tags → add the four required tags:
function:<tag>
sensitivity:<level>
consumer:<primary-consumer>
rotation:<cadence>
If the secret is sensitivity:critical, add a comment in the provisioning PR describing who was notified.
For each consumer type, add the new key name to the canonical reference location:
| Consumer | Reference location |
|---|---|
| CI (GitHub Actions) | .github/workflows/*.yml — add to the env: block or secrets mapping. Document in PR description. |
| Terraform | terraform/<module>/variables.tf + comment header in terraform.tfvars.example naming the vault path |
| Raptor (backend_v2) | backend_v2/api/vault.py — add to the bootstrap list + os.environ.get call site |
| Console | console/vault.py or equivalent config loader |
| Agent scripts | scripts/agents/*.py — add to the env-var resolution list |
| Operator runbooks | docs/ops/runbooks/rotation/INDEX.md — add a row to the rotation matrix |
Step 5 is required. No orphan tokens — every token in vault must have at least one documented consumer reference.
Open docs/ops/runbooks/rotation/INDEX.md and add a row:
| <NEW_NAME> | <Vendor> | operator-assisted | <sop-link> | <cadence> | TBD | TBD |
If no vendor-specific SOP exists yet, create one under docs/ops/runbooks/rotation/ before filing the provisioning PR.
No token is renamed or moved. Existing consumers are unaffected. The taxonomy doc is the reference for all net-new tokens provisioned from this point forward.
Starting with CF_WAF_EDIT_RAXX_APP (#747) — the first token to be provisioned after this doc exists — all new tokens use the new naming and tagging convention.
For each vendor:
Vendor order (suggested — highest impact first):
After all vendor renames complete, update docs/ops/runbooks/rotation/INDEX.md to use new names. Old entries marked [archived].
During the parallel rename window (old + new names both exist):
CLOUDFLARE_RAXX_AUTOMATION_API_TOKEN and CLOUDFLARE_PAGES_DEPLOY_TOKEN the same physical token?The rotation matrix and the memory reference (reference_cloudflare_tokens.md) name both tokens. If they are the same token stored under two names, one name should be deprecated immediately after the canonical new name is provisioned. If they are distinct (different scopes), the function mapping needs to reflect that. The taxonomy proposes CF_PAGES_DEPLOY for the Pages-deploy function — confirm whether the automation token also has Pages scope or whether it is truly distinct.
Infisical supports setting an expiration date on a secret (it will be flagged as expired in the UI and rotation alerts fire). The taxonomy documents cadences, but does not mandate using Infisical's expiration field. Recommendation: use the __EXPIRES_AT companion secret for auditable tracking and let the console rotation UI read it (#253, #254). Infisical's native expiration is a belt-and-suspenders option. Kristerpher to decide whether to enable native expiration (no implementation work — just a UI toggle per secret) or rely solely on the rotation pipeline's scheduling.
Option A — one token with both zones in scope: simpler rotation, wider blast radius if leaked.
Option B — two tokens, one per zone: least-privilege, higher provisioning overhead.
The taxonomy proposes Option B (CF_DNS_EDIT_RAXX_APP and CF_DNS_EDIT_GETRAXX_COM) as the default. If Kristerpher prefers Option A for operational simplicity, the scope suffix becomes CF_DNS_EDIT_ACCOUNT (or just CF_DNS_EDIT) and the __SCOPES companion documents both zones. Either is valid — but the decision should be made before any migration PR is filed.
This index is built from the rotation matrix (INDEX.md), the vault README, issues #402/#596/#747, and the memory notes. If any tokens exist in vault that are not listed here — particularly any remaining CLOUDFLAREROLLED, legacy bootstrap tokens, or per-agent access tokens — they should be audited against this taxonomy before the Phase 2 migration starts. Kristerpher's live read of vault contents (using the CF Access service token and Infisical list API) would surface any gaps.
ALP_LIVE_TRADING ever exist in vault at all pre-launch?The live trading keys control real money. Before Raxx has live-trading users, these keys belong to the operator's personal Alpaca account. The taxonomy includes them for completeness, but the provisioning decision — whether to store live keys in vault now or defer until first live user — is Kristerpher's call. Recommendation: store in vault under sensitivity:critical with consumer:raptor and rotation:60d even pre-launch, so the rotation pipeline can enforce cadence on the keys that matter most.
| Code | Vendor |
|---|---|
CF |
Cloudflare |
HK |
Heroku |
PM |
Postmark |
AWS |
Amazon Web Services |
ANT |
Anthropic |
GH |
GitHub |
STR |
Stripe |
ALP |
Alpaca |
INF |
Infisical |
SL |
Slack |
DH |
DreamHost |
DYN |
Oracle Dyn |
[ ] Name follows <VENDOR>_<FUNCTION>[_<SCOPE>] pattern
[ ] Path folder verified to exist (or created via POST /api/v1/folders first)
[ ] Secret created in correct Infisical environment(s) per Section 3 table
[ ] __EXPIRES_AT companion secret set
[ ] __SCOPES companion secret set (exact vendor permission strings)
[ ] All four tag dimensions applied (function, sensitivity, consumer, rotation)
[ ] If sensitivity:critical — ops review noted in PR description
[ ] Consumer reference added (CI workflow / Terraform / vault.py / runbook)
[ ] Row added to docs/ops/runbooks/rotation/INDEX.md
[ ] Vendor-specific SOP exists at docs/ops/runbooks/rotation/<vendor>.md