Heimdall__AppSecretFile: keep the Heimdall app secret out of the process environment #78

Merged
heimdall merged 3 commits from heimdall/appsecret-file into main 2026-11-12 13:46:26 +00:00
Member

Cuts follow-up heimdall-body:follow_up:bifrost-appsecret-hazard.

  • New option Heimdall:AppSecretFile (systemd LoadCredential style %d/name). Resolved once in an options PostConfigure (HeimdallOptions.ResolveAppSecret); the file wins, one trailing newline is trimmed.
  • Set-but-missing/unreadable/directory/empty file fails startup closed in every environment (validator touches the options first), naming the option and path, never the secret.
  • Heimdall:AppSecret (env) still works and logs a deprecation warning without the value. Neither set: unchanged. Existing header log redaction is untouched and still covers the header.
  • Tests: HeimdallAppSecretFileTests (14). Eight mutations each fail a test (no PostConfigure, no validator touch, Trim vs TrimEnd, env wins, empty accepted, missing swallowed, warning removed, secret logged).
  • Full suite: base 1365 pass, head 1379 pass, 0 failures.
  • Docs: deploy-main-to-live.md, concept-mill-votes-target.md, new docs/heimdall-app-secret-file.md. Ops steps are in the commons handoff note bifrost-appsecret-file-ops-note-20261112.md (not applied; no host files read).

🤖 Generated with Claude Code

Cuts follow-up heimdall-body:follow_up:bifrost-appsecret-hazard. - New option `Heimdall:AppSecretFile` (systemd `LoadCredential` style `%d/name`). Resolved once in an options PostConfigure (`HeimdallOptions.ResolveAppSecret`); the file wins, one trailing newline is trimmed. - Set-but-missing/unreadable/directory/empty file fails startup closed in every environment (validator touches the options first), naming the option and path, never the secret. - `Heimdall:AppSecret` (env) still works and logs a deprecation warning without the value. Neither set: unchanged. Existing header log redaction is untouched and still covers the header. - Tests: `HeimdallAppSecretFileTests` (14). Eight mutations each fail a test (no PostConfigure, no validator touch, Trim vs TrimEnd, env wins, empty accepted, missing swallowed, warning removed, secret logged). - Full suite: base 1365 pass, head 1379 pass, 0 failures. - Docs: deploy-main-to-live.md, concept-mill-votes-target.md, new docs/heimdall-app-secret-file.md. Ops steps are in the commons handoff note bifrost-appsecret-file-ops-note-20261112.md (not applied; no host files read). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The file wins, is read once when the options are built, and a set-but-missing,
unreadable or empty file stops startup in every environment without naming the
secret. Heimdall__AppSecret still works and logs a deprecation warning.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Soul pass on 25b9cc16: the warning level was unpinned (a Trace demotion passed) and the docs said one newline where the code trims all.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/Bifrost!78
No description provided.