Secrets runbook (maintainers)
docs/SECRETS.md · the same file GitHub renders ·Edit on GitHub ·Markdown
The mock services (@crvouga/mockingbird-service-*, the only published packages) are released
automatically on every green push to main (see RELEASING.md) and publish with
npm Trusted Publishing (OIDC).
OIDC can only publish to packages that already exist on npm and trust this repo. For brand-new packages the release job needs one of:
NPM_TOKENActions secret (recommended, fully automated). A granular npm token with read+write on the@crvougascope. The release job uses it only to create new packages (and as a fallback if an OIDC publish is rejected), then runsnpm trust githubso every later release of that package goes through OIDC. It also deprecates every package no longer published (the former helper packages and the archived legacy packages).- Local seed. From any checkout:
bun run release:seed(-- --dry-runto preview). It runsnpm loginif needed, uses npm@11 when yours is too old fornpm trust, buildsorigin/mainin a temporary worktree and runsrelease:publish --localthere. Publishes without provenance with your npm login, pushes the tags and GitHub Releases, attaches the Trusted Publishers and deprecates every package no longer published — i.e. it reconciles npm withorigin/main.
All credentials live in the shared self-hosted Vault / OpenBao at https://vault.chrisvouga.dev,
KV v2 secret/personal/<config> (dev locally, prd for production and CI; same key names in
both, one field per env var). This repo follows the shared-infra contract:
https://raw.githubusercontent.com/crvouga/workspace/main/llms.txt
- Turborepo remote cache (
TURBO_API,TURBO_TOKEN,TURBO_TEAM,TURBO_CACHE) — locally every root turbo script (bun run build|test|check|…) goes throughscripts/vault-run.ts, which wraps it invault runusing.vault.yaml. In CI,.github/actions/setuploads them with Vault GitHub OIDC (rolegithub-actions, policyci-read) — no stored token. - Live parity sandbox keys (
MOCKINGBIRD_*) — inpersonal/prd;bun run parity*runs undervault run --config prd. CI publish never reads them; the Verify workflow reads the Junction key.
Local setup, once per machine (from a crvouga/workspace checkout; needs the vault/bao CLI + jq):
packages/vault-service/scripts/install-cli.sh # ~/.local/bin/vault wrapper (adds `vault run`)
bun run vault:login # userpass login as crvougaWithout the wrapper, turbo scripts still run, with only the local cache.
Inventory:
.vault.yaml— Vault address / mount / project / config (no secrets).env.example— every env var name this repo reads (no values)secrets.manifest.yaml— secrets (Turbo cache,NPM_TOKEN, parity keys) + OIDC checklist
Quick commands
# Log in to self-hosted Vault/OpenBao as crvouga; prompts for password
bun run vault:login
# Verify the remote cache: second run with unchanged inputs → "cache hit, replaying logs"
bun run build && bun run build
# Full report: which packages exist on npm, Trusted Publishing links, Actions secrets
bun run secrets:doctor
# Push NPM_TOKEN from Vault (personal/prd) to the NPM_TOKEN Actions secret
bun run secrets:sync
# Missing NPM_TOKEN? Prompt securely, store + sync it, then rerun and watch failed CI
bun run release:fix-ci # latest failed CI run on main
bun run release:fix-ci -- 35698422509 # specific run
# What the next release would publish
bun run release:plan
bun run release:publish -- --dry-runTrusted Publisher settings
Set automatically by the release job when it has npm account credentials. Manual equivalent, per
package at https://www.npmjs.com/package/<name>/access:
- Organization/user:
crvouga - Repository:
mockingbird - Workflow filename:
ci.yml - Environment: (empty)
Docs: https://docs.npmjs.com/trusted-publishers
Parity credentials (Vault)
Field name = env var name, in secret/personal/prd (API path secret/data/personal/prd):
| Provider | Fields / env vars |
|---|---|
| Stripe | MOCKINGBIRD_STRIPE_SECRET_KEY, MOCKINGBIRD_STRIPE_PUBLISHABLE_KEY |
| Junction | MOCKINGBIRD_JUNCTION_API_KEY |
| GeneByGene | MOCKINGBIRD_GENEBYGENE_CLIENT_ID, MOCKINGBIRD_GENEBYGENE_CLIENT_SECRET |
bun run parity* and bun run verify:junction inject them with vault run --config prd. The
Verify workflow (daily, not a required check) reads only
MOCKINGBIRD_JUNCTION_API_KEY, through the same GitHub OIDC role as the Turborepo cache. Scripts run directly fall back to
@crvouga/mockingbird-openbao, which reads secret/data/personal/prd (override per provider with
MOCKINGBIRD_OPENBAO_PATH_<PROVIDER>) using VAULT_TOKEN / BAO_TOKEN / ~/.vault-token, or a
GitHub OIDC JWT (MOCKINGBIRD_OPENBAO_JWT, role github-actions).
bun run vault:login
bun run parity:stripe
bun run parity:junction
bun run parity:genebygeneWhat exists where
| Credential | Where | Required |
|---|---|---|
| npm Trusted Publisher (OIDC) | each package on npm | Yes (CI publish; attached automatically) |
GITHUB_TOKEN |
Built into GitHub Actions | Automatic |
TURBO_* (remote cache) |
Vault personal/{dev,prd} → vault run locally, OIDC in CI |
Yes (else no remote cache) |
GH_PAT |
Optional Vault personal/prd |
No (local only) |
| Provider sandbox keys | Vault personal/prd |
For live parity only |
NPM_TOKEN |
Vault personal/prd → Actions secret |
Only to create new packages (else bun run release:seed) |