Development and Security
Access ladder
| Role | Repository | Development data | Production credentials | Production deploy |
|---|---|---|---|---|
| Reader/reviewer | Read | None | None | No |
| Contributor | Pull-request/write as approved | Synthetic local workspaces | None | No |
| Maintainer | Write/admin as assigned | Synthetic plus bounded diagnostics | None by default | No by default |
| Operator | Admin only where required | Bounded diagnostics | Individually granted, scoped, encrypted | Explicit upload and promote |
Repository access never implies secret or production authority. Do not share one person's token with another developer. Add an operator by minting an individual least-privilege credential and adding its encrypted recipient through the operator-controlled secret store.
Reproducible checkout
git clone --recurse-submodules git@github.com:corbet-labs/careervector-corbet-ch.git
cd careervector-corbet-ch
git lfs pull
nix develop .#ci --command bun install --frozen-lockfile
nix develop .#ci --command bun run check
The private Sporewright submodule is required by the full TypeScript and orchestrator graph. Missing access must fail visibly; do not replace it with a copied package or personal token in external CI.
Local data and secrets
*.examplefiles define names and safe defaults only.- Real
.envand.dev.varsfiles are ignored, remain local, and use mode600on Unix. - Transcrypt is retired. Do not add its filters, keys, or metadata; shared operator secrets are stored outside the repository with SOPS and age.
- Use deliberately invalid provider credentials in fixtures.
- Use local Miniflare state and synthetic workspace links. Never paste a live workspace capability into a test, issue, or support transcript.
bun run check:secretsrejects tracked credential files, common token/key shapes, unpinned GitHub actions, GitHub Actions secret use, stale transcrypt configuration, and permissive local credential-file modes.
PUBLIC_GOOGLE_MAPS_KEY is intentionally browser-visible, restricted at Google
to approved HTTP referrers and APIs, and is not a server credential. It must not
be reused for a backend or a different domain.
Production secrets
Deployed Worker secrets are vendor bindings and cannot be read back through the repository. Operator source material is encrypted outside this repository.
The Cloudflare wrapper resolves credentials in this order:
CLOUDFLARE_API_TOKENplusCLOUDFLARE_ACCOUNT_IDalready present in the process environment;- a strict, non-executable, mode-
600file selected byCAREERVECTOR_CLOUDFLARE_ENV; - the encrypted file selected by
CAREERVECTOR_CLOUDFLARE_SOPS_FILE, reading onlycareervector_workers_deploy_tokenandaccount_id.
Contributors do not need any of these. The current deploy token grants only account-level Workers Scripts Write; it does not grant DNS, billing, D1 data, R2 data, or account-settings mutation.
CI trust boundary
- Crow runs the full gate on controlled infrastructure and can consume the private submodule through its repository checkout.
- GitHub Actions jobs are source-read only, use no repository/production secrets, disable persisted checkout credentials, and pin third-party actions by full commit SHA.
- CircleCI jobs are local/synthetic test dispatch only. Do not add vendor, database, signing, release, or production tokens to CircleCI.
- Production deployment is not push-triggered.
Before handoff
bun run check:secrets
bun audit
git diff --check
Run bun run check and bun run test in nix develop .#ci, then the relevant
browser, TUI, Tauri, or deployment-specific evidence gate.
Suspected exposure
Stop copying or displaying the material, preserve the smallest useful evidence,
and report privately according to the root SECURITY.md. Do not rotate or
delete credentials independently: operators first identify every consumer and
then change the source, bindings, and dependent services as one coordinated
action.