Environment Entries
Vars and secrets, project attachment, and the frozen run snapshot.
An organization defines reusable environment entries — plain variables and encrypted secrets — and attaches them to projects; a project can add its own entries that override an attached entry on the same key. At dispatch, the resolved map is frozen into one encrypted snapshot that travels with the run, so editing an entry never changes an in-flight run. Secret values are write-only: the API returns them to nobody, and the decrypted value exists only inside the run's container.
How to test it
Covered by pnpm vp run @firops/api#test: entry CRUD proves secrets are
absent from every response, reserved keys are rejected at write time, deletion
is blocked while an entry is attached, and dispatched runs receive the resolved
snapshot with project entries winning over organization entries.
Manual smoke: Manage → Credentials → Environment — add a secret, attach it
to a project, dispatch, and confirm the run sees it while the list shows only
Secret stored.
Decisions
- The run environment is frozen at dispatch — a run's behavior must not change under it mid-flight because someone edited an entry; reproducing a run means reproducing its snapshot, not the current entry state.
- Reserved keys are enforced twice: at write and at snapshot build — the
runtime's own vocabulary (the
DEVBOX_andOPENCODE_prefixes, the Git identity, the token names, and core process keys likePATHandHOME) can never be shadowed, even by a row that predates a policy change. - Secrets are write-only — there is no reveal affordance to leak through; replacing the value is the only edit, which keeps the audit story one-directional.
- Project entries override organization entries per key — the specific scope beats the general one, so a project can diverge without forking the org-wide set.
- The snapshot is capped at 1 MiB — an oversized environment fails the dispatch with a clear error instead of producing a container that breaks in stranger ways downstream.
Next: Runners & provider credentials — how a claimed run gets its model provider credential.