Repository navigation
Strict env model, sensitive values never shown, and zerops_env action=request - #39
Merged
Merged
Conversation
A value the platform holds with sensitive:true is a person's write-only secret, yet a full token reads it back in clear and discover includeEnvValues, the zerops_env set echo and the generate-dotenv preview diff handed it to the model. RedactEnvValue (successor of RedactCredentialValue) takes the row's flag and masks it as <redacted: sensitive>; every presentation site routes through it and annotates the key isSensitive. Internal value paths and the .env file render keep the raw value.
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
bundleProjectEnvsFromSource dropped the platform's sensitive flag, so a sensitive project env classified plain-config rode into the export or launch bundle verbatim. The flag now reaches the composer, which emits the placeholder for a sensitive value in any bucket that would carry it. The sentinel warning named the value it matched; it names the key only.
Under the strict env model a service's process reads exactly the entries
of its run.envVariables; a Shared, own or another service's value reaches
it only through an entry that references it. ServiceEnvScope classifies
every ${NAME} of a service's entries as zcp measured it live (entry chain,
self-shadow literal, own, Shared, ${host_KEY}, unresolved literal), and
EnvKeyReaders / ReadProjectEnvScopes answer which services read one key,
from the deployed rows.
A service-scope set was always written sensitive and a project-scope set always plain. The set now takes an optional sensitive input for either scope; left out, a key whose name reads as a secret (SECRET, TOKEN, KEY, PASSWORD, PASS, DSN, PRIVATE, CREDENTIAL) is sensitive and any other plain. Every write passes the flag explicitly, since an update without it turns a sensitive value plain. The env schema's other descriptions are trimmed to stay inside its byte budget.
A set or delete restarted every live runtime for a project key, and the
named service for its own key, as if Zerops injected every value. Under the
strict model a process reads only what its run.envVariables references, so
the restart targets are the readers: the runtimes whose deployed entries
reach the key directly, through a chain of entries, or as ${host_KEY}. The
response reports readers per key. Nothing reads it, nothing restarts, and
nextActions says how to reference it. A delete warns each reader that its
reference now reaches the app as the literal; a service whose rows cannot
be read is restarted in case it reads. The tool description states the
strict model.
The planted regression still forces the skipRestart branch of applyAutoRestart; the patch is re-cut against the readers-based code and the README names the unit test it now also breaks.
A ${NAME} in run.envVariables that is not another entry, the service's own
value, a Shared value or a platform key reaches the app as the literal
text. The deploy preflight now reads the project's Shared rows and the
target's own rows and fails such a reference, like the other broken-at-
runtime env checks; a failed read warns. ${host_KEY} stays the env_refs
check's and KEY: ${KEY} the self-shadow check's, whose message now states
the strict model: name the entry what the app reads, the value it
references differently.
The lifecycle spec gains §3b, how a run entry resolves under the strict
model zcp now acts on (renames, chains, own before Shared, KEY: ${KEY}
literal and poisoning, own values absent at build), and corrects what
changed: project-level sensitive persists, ZEROPS_YAML is gone from the
app-version rows, an update without sensitive turns a value plain, and
the duplicate-key guard is case-insensitive. Code comments that claimed
auto-inheritance or a non-persisting project flag follow.
Every value an app reads is a line in its zerops.yaml run.envVariables;
vault values (Shared, or the service's own) reach it only through one.
Since KEY: ${KEY} does not resolve yet, a line carries the name the app
reads and references a value of a different name. Secrets go in the vault
as sensitive, the person manages values in Mate's Vault panel or the
dashboard, and is never asked to paste one into the chat. The env atoms,
the knowledge themes and the recipe scaffold brief drop the auto-inject
advice; atom goldens regenerated.
A value only the person has (an API key, a password) is never asked for
in the chat. action=request validates the key, resolves the scope and
writes nothing: it answers requested {key, scope, sensitive} so Mate can
draw a field that writes straight to the vault, or alreadySet when the
key is in that vault, by presence only. The schema stays within its
byte ceiling (2546) by tightening the action and sensitive wording.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
zcp now acts as if Zerops' strict env isolation were on: a service reads only what its zerops.yml references. It also stops handing a person's sensitive values to the agent. This goes with Mate's vault, its new panel for a project's variables.
Security
zerops_discover includeEnvValues, thezerops_env setecho, and the preview diff of generate-dotenv / env plan. They are now masked as<redacted: sensitive>and flaggedisSensitive.classify_envsno longer drops the sensitive flag.Strict model
${KEY}reads the service's own value, else Shared's;${host_KEY}reads another service's.${host_KEY}resolve.KEY: ${KEY}gives the literal text (measured 2026-10-07). So an entry is named what the app reads, and the vault value carries another name:APP_KEY: ${APP_KEY_SECRET}.zerops_env settakessensitiveon both scopes; when it's left out, the key's name decides. It restarts only the services whose deployed entries read the key and reportsreaders. When nothing reads the key, it restarts nothing and says a reference and a deploy are needed.run.envVariablesreference that nothing resolves.zerops_env action=requestasks the person for a value in Mate. It writes nothing; the value goes straight to the vault, never through the chat.docs/spec-zerops-env-lifecycle.mdrecords the 2026-10-07 measurements.docs/spec-mate.md§5.8 and §10.10 describe the vault and the strict model.Verified
go testpasses forinternal/{ops,tools,content,platform,workflow};make lint-localreports 0 issues.TestInputSchemaByteBudgetholds: the discover text was trimmed andzerops_envsits within its ceiling.Open
env-service-scope-pairexpects an unreferenced value afterset; under the strict model it needs a reference.ZEROPS_YAML, which app versions no longer carry.generate-dotenvstill merges every project value.APP_KEYin Shared with no reference). Recipes usingKEY: ${KEY}break today.🤖 Generated with Claude Code