Amended by 0107: tenant-owned credentials (API
keys, certificates, OAuth tokens) are a third class, kept in the
@stackra/connections store. The
two mechanisms here are unchanged for our own keys.Amendment proposed in 0257: rule 3 becomes
“a human or the secret-manager flow sets a value; nobody reads one”.
Context
Secret values leak through files, logs, test fixtures, chat transcripts and CI debug steps. Every extra store is another place to leak from and another thing to rotate. Developer tooling tokens and application secrets have different readers and need different homes.Decision
Two kinds of secret, two mechanisms, never a third.- Names in git, values in the vault. A file may list a secret’s name and purpose, never its value.
- Infisical is canonical for developer and CI tokens.
/agentsis read only bytools/scripts/mcp.sh, which passes a token to the server process; agents never read it. CI reads/cionly, and authenticates by GitHub OIDC (no static token stored as a CI variable). - A human sets, rotates and deletes every value. An agent declares the secret in code and names key and purpose in its report.
- No
.envand no.env.example. There is no file fallback. - Worker secrets and EAS secret variables are application secrets too. The store differs, the rule does not.
- CI must never run
infisical export,infisical secrets getwithout--silent,printenv,encore secret get, or any step that echoes a token or its length. pnpm verifyand tests need zero secrets.- Alternative recorded, not adopted: Infisical Secret Sync pushing values into runtime stores. It makes a second writer per store. Revisit when more than one runtime holds the same secret (revival trigger below).
Consequences
- Onboarding needs vault access, not a copied file.
- Where Encore is not deployed (0011), the application-secret store is chosen by the first service that needs one, by ADR.
Enforcement
.agents/hooks/guard-bash.mjsdeniesencore secret set/get,wrangler secret put/bulk, reading.envand.dev.vars, andprintenv; gitleaks runs inlefthook.ymland aspnpm secrets:scan.- Planned, in the same change as
/constitution/secrets: guard-bash rules forinfisical exportandinfisical secrets getwithout--silent, with a hook test. - Planned: a
secrets-doctorscript (names only), a no-.envvalidator check, and a CI workflow allowlist forsecrets.*.
Revival trigger
Reopen Secret Sync when a secret must be identical in three or more runtime stores and a human-only write has caused drift twice.Supersedes and sources
Supersedes: none. Sources: platformdocs/adr/0005-secrets-infisical-and-encore, 0018-secrets-constitution, 0019-application-secrets-single-source-and-propagation; user rules secrets.md.