Repository navigation
docs(env): env-file operations and encrypted .env values - #676
Conversation
The three operations that edit a component's `.env` file - `get_env_keys`, `set_env_value`, `delete_env_value` - had no page anywhere in the docs, and neither did the `enc:v1:` encrypted-value form that `loadEnv` decrypts at startup. The secrets store was already documented; this fills in the file-based half that shares its envelope format. Adds an Environment File Operations section to the operations reference, covering request and response shapes, the `.env`-only `file` constraint, the key character set, replication, and the masking `get_component_file` and `get_components` apply to protected `.env` files (while `set_component_file` still writes them verbatim). Adds a sibling reference page for encrypted values: what the `enc:v1:` marker means, the Harper Pro custody requirement and the deferral behavior when no decryptor is registered yet, the fetch-encrypt-write client flow, and the threat model. Envelope internals and the reference client stay in the secrets page and are linked rather than duplicated. All of this shipped in v5.2.0, verified by the presence of the operations and the loader path at the v5.2.0 tag and their absence at v5.1.28. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive documentation for Encrypted Environment Values and remote .env file management operations (v5.2.0), including new Operations API endpoints such as get_env_keys, set_env_value, and delete_env_value. The feedback suggests improving readability in the Operations API documentation by presenting critical fallback behaviors in separate, distinct sentences rather than combining them with semicolons.
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-676 This preview will update automatically when you push new commits. |
… leaves behind An edit through set_env_value or delete_env_value changes the file only: loadEnv flags restartRequired on a change to a loaded file and the running workers keep the old values until they restart. A skipped encrypted value leaves an already-set variable in place, a decrypted one follows the same override rule as plaintext, and a late decryptor's replay does not rerun code that already read the variable. Dispatch-Task: fix-kriszyp_documentation_676-7119e128 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a carriage return reads back as a newline The replicated response lists each peer, and an unreachable one is marked failed and not retried. dotenv normalizes \r\n and \r to \n, so a value with a carriage return does not round-trip. The harper dev auto-restart applies only when it runs an application directory. Dispatch-Task: fix-kriszyp_documentation_676-7119e128 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… listed as failed too Dispatch-Task: fix-kriszyp_documentation_676-7119e128 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-676 This preview will update automatically when you push new commits. |
Ethan-Arrowood
left a comment
There was a problem hiding this comment.
LGTM - fix the merge conflict however you best see fit and you're welcome to squash merge without another review (I trust you wont dramatically change this PR when dealing with the conflict). Thanks!
🤖 Reviewed with Codex
Resolve the one positional conflict in reference/operations-api/operations.md:
main's deploy subsections ("Checking what each node installed", "Streaming
deploy progress") stay at the end of the deploy section, and the new
"Environment File Operations" section follows them, before "Deployment
Operations".
Dispatch-Task: fix-kriszyp_documentation_676-7119e128
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nding it again is safe Dispatch-Task: fix-kriszyp_documentation_676-7119e128 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…quest, and note replicated beside the responses Resending an older set_env_value would undo a later rotation on every node, and an older delete would remove a key that was set again since. Dispatch-Task: fix-kriszyp_documentation_676-7119e128 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…asking get_components flags a .env entry protected, get_component_file returns it masked, and set_component_file replaces it whole, so the sibling page no longer contradicts the operations reference. Dispatch-Task: fix-kriszyp_documentation_676-7119e128 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-676 This preview will update automatically when you push new commits. |
🧹 Preview CleanupThe preview deployment for this PR has been removed. |
Documents the component
.envsurface of Harper's secret handling, which had no page anywhere in the docs. The secrets store itself was already covered byreference/security/secrets.mdand the Secrets section of the operations reference; this fills in the file-based half that shares itsenc:v1:envelope.What is documented
reference/operations-api/operations.md— new### Environment File Operationssection (in Components, before Deployment Operations), plus three rows in the Components summary table.get_env_keys,set_env_value,delete_env_value: request and response shapes,project+ optionalfile(defaults to.env, must be.envor.env.<suffix>), the[A-Za-z0-9_.-]+key character set, and the fact that the two writers replicate.set_env_value'skey+valuevsvaluesforms, in-place preservation of comments/formatting/untouched keys, file creation, and the one unrepresentable quoting combination.get_component_fileon a protected.envreturnsprotected: true,keys, and aKEY=********body;get_componentsflags such files;.env.example/.sample/.templateare not masked;set_component_fileis not blocked and writes verbatim.reference/environment-variables/encrypted-values.md— new page (sidebar entry added under Environment Variables).enc:v1:marker, per-value opt-in, coexistence with plaintext.get_secrets_public_keyresponse shape.set_env_valuedoes not validate the envelope the wayset_secretdoes.reference/environment-variables/overview.md— a short "Managing.envFiles Remotely" section pointing at both, plus Related links.reference/security/secrets.md— one line: its existing mention of encrypted.envvalues now links to the new page.Envelope internals and the reference Node.js client stay in
secrets.mdand are linked rather than duplicated.Verified against code
All behavior was read from
HarperFast/harperorigin/main(the working checkout's relevant files are byte-identical toorigin/main— confirmed by diff), not from the prior internal write-up:components/operations.js(getEnvKeys,setEnvValue,deleteEnvValue,getComponentFile),components/operationsValidation.js(getEnvKeysValidator,setEnvValueValidator,deleteEnvValueValidator)..envparsing, masking, quoting rules:utility/envFile.ts(isEnvFile,isProtectedEnvFile,isExampleEnvFile,formatEnvValue,upsertEnvValues,removeEnvKeys,ENV_KEY_REGEX,ENV_ENCRYPTED_PREFIX).resources/loadEnv.ts,resources/secretDecryptor.ts.kidsemantics:utility/secretEnvelope.ts.get_secrets_public_keyresponse is{ public_key, fingerprint }:components/secretOperations.ts.harper-prosecurity/keyCustody.ts,security/fileKeyCustody.ts.unitTests/components/envOperations.test.js.Version badge.
v5.2.0on both new sections. Verified by feature presence at tags rather than ancestry: the three operation names inutility/hdbTerms.ts,components/secretOperations.ts,utility/envFile.ts,isProtectedEnvFileincomponents/operations.js, andisEncryptedEnvValue+deferEncryptedEnvValueinresources/loadEnv.tsare all present atv5.2.0and all absent atv5.1.28.Corrections to the prior internal write-up (
docs/env-secret-encryption.md, commit56511db95), which this PR does not reuse verbatim:get_secrets_public_keyas returning{ publicKey, fingerprint, scheme, algorithm }. The code returns{ public_key, fingerprint }— snake_case, and noschemeoralgorithmfield. The new page uses the real shape.secrets.md.For the human reviewer
Review round on 2026-10-01 (Ethan's requested changes plus the pre-push review). What changed and what was left alone:
loadEnvhas already loaded only setsrestartRequired(resources/loadEnv.ts→requestRestart). Running workers keep the old values, including a deleted key, until they restart.restart_servicewith"replicated": trueis the documented way to apply an edit. Onlyharper devrunning an application directory restarts on its own (autoReloadis set only forRUN_HDB_APP). Theget_statusrestartRequiredrow now mentions.envedits.replicateOperation(harper-proreplication/replicator.ts) sends to each peer once and does not retry. Each peer appears in the response'sreplicatedarray, and a peer that could not be reached or answered with an error is"status": "failed". The request still succeeds, so the page says to checkreplicatedand resend the affected keys' current state, not the original request, which would undo a later edit on every node. This replaces the earlier "an edit reaches every node", and settles the replication-response question the first draft listed as unverified. The restart-semantics question from that list is settled by the bullet above.process.env: a skipped value leaves an already-set variable in place. A decrypted value, live or replayed, follows the plaintext override rule. A replay does not rerun code that already read the variable.reference/components/applications.mdnow notes theprotectedflag inget_components, the masked body fromget_component_file, and thatset_component_filereplaces a.envfile whole, so saving back a masked body writes********as every value.\ris accepted but reads back with\r\nor\rturned into\n(dotenv normalizes line endings before it parses). The page now says so.Declined here as core defects. All four are reproduced or traced in
HarperFast/harper, and the fix belongs in core, not in a docs caveat. Deciding whether to add a temporary caveat until core is fixed is yours:utility/envFile.tsclosesQuote/valueEndLinedisagree with dotenv about where a quoted value ends. GivenWIN_PATH="C:\tools\"followed byAPI_KEY=abc, or an unterminatedA="foo,set_env_valueon that key deletes the following keys on every node. Reproduced with the production helper. This contradicts the page's "every other line … is left exactly as it was".ASSIGNMENT_LINEmatches onlyKEY=value, but dotenv also acceptsKEY: value. On such a line,delete_env_valuereports success and leaves the key, andset_env_valueappends a duplicate. Reproduced.set_env_valueanddelete_env_valueread, modify, and write the file with no lock and no ordering across nodes. Overlapping edits can drop a key or leave nodes with different files.resources/secretDecryptor.tsskipsloadEnv's config-shaping guard. An encryptedHARPER_SET_CONFIGloaded before custody registers ends up inprocess.env.Kept as written:
set_component_filestays documented as an unguarded verbatim write to.env, andset_env_valueas not validatingenc:v1:envelopes. Both are accurate descriptions of current core behavior. Whether core should block either one is a product call.Merged
main(2026-10-13, owner-authorized). The one conflict, inreference/operations-api/operations.md, was positional only.main's deploy subsections (Checking what each node installed,Streaming deploy progress) stay at the end of the deploy section, and### Environment File Operationsfollows them, before### Deployment Operations. The restart guidance still holds aftermainaddedrestart_service'sscope: with noscope, a restart covers every worker, including isolated applications' (harperbin/restart.ts,manageThreads.jsdecodeRestartScope).Overlapping open PRs. docs(learn): add Administration production reliability track edits the operations reference; check it keeps the
.envclause in therestartRequiredrow and does not contradict the restart guidance. docs(deployment): document deployment.startupInstallTimeout edits the deploy subsections directly above the new section, so whichever merges second resolves a positional conflict.Verification
npm run format:check— clean.npm run build— succeeds, no broken-link errors (onBrokenLinks: 'throw').id="environment-file-operations"inbuild/reference/v5/operations-api/operations.htmlandid="reference-client-nodejs"inbuild/reference/v5/security/secrets.html.build/reference/v5/environment-variables/encrypted-values.htmland appears in the sidebar.Uncertain / not verified
enc:v1:value size.set_secretcapsvalue/envelopeat 256 KB;set_env_valuehas no such cap in its validator. I did not document a limit for env values, but I also did not test a large one against the file writer.secrets.mdsays Studio provides a UI for the secrets store. I did not claim anything about Studio's.envediting surface, having no way to check it here.release-notes/v5-lincoln/5.2.mddoes not mention the env operations or.envmasking. I left it alone — adding a retroactive entry felt out of scope for this PR, but it may be worth a follow-up.— Claude Opus 5.5 (review round)
🤖 Generated with Claude Code
Related PRs: #671 overlaps, #683 overlaps, 6 others independent
Review-Coverage: authored=claude; ran=gemini,codex; adjudicated=domain; declined=cursor-grok,cursor-composer,cursor-kimi,cursor-muse; rounds=8; full=3 @ b4c39c9
Review-Attention: read ~3m (decisions: mask-writeback-doc-vs-core-guard, concurrency-caveat-vs-core-lock, envelope-spec-duplicated) @ b4c39c9