feat(12factor-env, pi): opt-in dotenv, schema-level validators/checks/secret redaction, injectable pi context - #1718
Merged
Merged
Conversation
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…entry stays bundler-safe
…ed env vars resolveProjectContext takes values (a record, a lookup fn, or process.env via fromEnvironment) instead of only a cwd, so a headless host - container, Job, CI - supplies credentials as environment variables with nothing written into the git clone. Passing a cwd still reads <cwd>/.env, keeping desktop behavior unchanged. Injected names are prefixed (CONSTRUCTIVE_ACCESS_TOKEN etc.), bare names still resolve for project .env files. Drops pi's hand-rolled parser for 12factor-env/dotenv's parseDotenv.
…cross-field checks, secret redaction
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.
Summary
Fixes the config lane end-to-end for #1645 and #1650. Three pieces, one package boundary:
1.
.envbecomes an opt-in input builder, not a hard-coded file read. New node-only deep entry12factor-env/dotenv; the main entry stays free of node builtins (a test fails if that regresses) so browser / Next-client / Electron-renderer bundles are unaffected. Nothing reads a file unless you calldotenv(), andprocess.envis never mutated:2.
pitakes a context source instead of always reading<cwd>/.env— which is what made a headless coding-agent Job impossible and put credentials in a git clone the agent could commit:Injected vars are
CONSTRUCTIVE_-prefixed (CONSTRUCTIVE_ACCESS_TOKEN,CONSTRUCTIVE_DATABASE_ID,…_API_ENDPOINT,…_MODULES_ENDPOINT,…_DATABASE_NAME,…_OWNER_ID); bare names still resolve for project.envcompatibility, prefixed wins. pi's hand-rolledparseEnvis gone in favor ofparseDotenv. Failure codes are unchanged, and the security boundary is unchanged and now covered by a test: source-supplied endpoints pin only the data plane; the control plane keeps the host's backend config, so a cloned project can never redirect the account bearer.3. The library features consumers were hand-rolling after
env()(#1650). Each of these previously lived in an ad-hocif/splitwith its ownthrow, outside the one consolidated report:Notable semantics:
list()treats set-but-empty ('',',') as an error rather than returning[]— a typo'd allowlist silently meaning "allow nothing" is the failure mode this exists to prevent.parseEnvList's lenient behavior is untouched for non-schema callers.checkis skipped when any var it names already failed, so "both unset" isn't also reported as "both equal"; failures are attributed to the named vars and join the sameEnvError.Invalid url: "postgres://u:pw@h/db"), which put passwords in crash logs. Anything inenv()'ssecretsargument — orstr({ secret: true })— reports asInvalid url: "[redacted]" (value redacted, 42 chars), and the cleaned env redacts underJSON.stringify/util.inspectwhile property access still returns the real value. A missing secret keeps itsdescverbatim (no value to leak).redactEnvError(err, [known])for errors you build yourself.Implementation note: redaction needs
customCleanEnv+applyDefaultMiddlewarerather thancleanEnv, becausecleanEnvfreezes its strict proxy — the serializers have to be defined on the plain cleaned object before that.Compatibility:
env()/cleanEnv()signatures are additive (4thoptionsarg),numis a superset of envalid's,resolveProjectContext(cwd)still works. constructive-desktop needs no change; adoptingfromEnvironment()there is optional follow-up.@agentic-kit/pineeds a re-publish after this lands.Verification
12factor-env: 70 tests, lint + build clean.pi: 73 tests, lint + build clean. Also rebuilt every in-repo consumer of the package (pgpm/env,graphql/env,pg-env,pg-cache,graphile-cache,postmaster,pi) and re-ran the env test suites (snapshots included) to confirm thenum/serialization changes are non-breaking.Link to Devin session: https://app.devin.ai/sessions/450ce6d6659c47759c184ae6ec19a2a8
Requested by: @pyramation