Context
The audit found the following:- Shared tokens were copied into many places.
TURBO_TOKENwas in nine places.CLOUDFLARE_API_TOKENwas in four projects.REGISTRY_SIGNING_KEYwas in two projects.
- Projects that no CI identity can read. The stackra project held
/cifolders that no CI identity reaches. - Workflows that read paths which do not exist:
- figentra’s turbo step points at a project its identity cannot read;
install:proreads/install, which no project has;- the observability, Mintlify and release paths are missing.
- Writers that land in the wrong project.
pnpm secrets:importwrites to whatever.infisical.yamlbinds, which is stackra, while the workflow reads another project. - No binding in the product repositories. They had no
.infisical.yaml, so their agent and MCP scripts had no project. - Two models had grown apart:
- the template expected one project per product, holding
/runtime,/ciand/agents; - CI used shared projects split by reader.
- the template expected one project per product, holding
Decision
-
One project per reader. A value has one home. A second reader either reads that home, or gets a differently
scoped token with its own name.
-
Only build tokens in
figentra-ci. A pull request can reachfigentra-ci, so it holds no credential that can write or deploy. -
Fixed folder names.
/ciand/ci/<purpose>for CI./agentsfor people and agents./runtime/<member>for runtimes. This is the folderdeployPlangives each member, and the one ADR 0493’s resource secrets already use.- No other top-level folders.
-
Frontends hold no secret (0371 decision 1).
- Public build values (
VITE_*,EXPO_PUBLIC_*, DSNs, analytics keys) are runwayvars. - A Worker’s server-side secret goes in
/runtime/<app>. - Non-secret ids and URLs are not stored in Infisical. The one exception is
TURBO_APIandTURBO_TEAM, which go in/ci/turbobeside the token their step exports.
- Public build values (
-
Names.
SCREAMING_SNAKE_CASE, vendor first.- The same value has the same name everywhere.
- App Store keys are
ASC_API_KEY_ID,ASC_API_ISSUER_IDandASC_API_PRIVATE_KEY. - Retired names do not return:
NPM_FIGENTRA_*andNPFLARED_AUTH_TOKEN.
-
Bindings.
- A workflow takes project and identity ids only from the org variables (
INFISICAL_GATE_*,INFISICAL_TURBO_*,INFISICAL_CI_IDENTITY_ID,INFISICAL_DEPLOY_PROJECT_ID,INFISICAL_REGISTRY_*), never as a literal. - Every repository’s
.infisical.yamlbindsfigentra-agentsdev. - A product’s
runway.yamlnames only its own runtime workspace and theruntimepath.
- A workflow takes project and identity ids only from the org variables (
-
Writers name the project.
pnpm secrets:importandpnpm vaulttakeprojectfrom the sidecar or--project./agentsdefaults tofigentra-agents; a/citarget without a project is refused.- The confirm token binds the project.
Consequences
- Each identity reads one project, and each value has one copy, so a rotation is one edit.
- The owner moves the values once:
/agentstofigentra-agents, and the store, release and observability names tofigentra-ci-deploy. Then they delete the stackra and Academorix copies. The Academorix project is archived. - Product runtime projects are created at a product’s first runtime secret, together with runway sync (STA-606).
- Enforcement:
secrets-importandvault-keeperrefuse an unbound/citarget.deployPlanemits/runtime/<member>.- Planned: a repo check that no workflow carries an Infisical project id literal.
Alternatives
- Per-product projects for everything (the template’s model). Every shared token is copied into each product, and each copy can drift.
- One project with path-scoped roles. Custom roles are not on the plan, and one leak exposes everything.