Skip to content

fix(env): contain child keys and env diagnostics (HACK-2163) - #756

Merged
roodboi merged 7 commits into
nextfrom
codex/hack-2163-env-secret-leaks
Nov 13, 2026
Merged

roodboi merged 7 commits into
nextfrom
codex/hack-2163-env-secret-leaks

Conversation

@roodboi

@roodboi roodboi commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Problem and change

Contain Hack credential variables at every child-process boundary by default, including explicit overrides and the Compose client, so host commands, lifecycle hooks, session shells and background commands cannot inherit the project decryption key. Deliberate Hack re-execs use an explicit exception; their tool children filter credentials again. The native backend keeps its stricter HACK_* restriction.

Replace forwarded env parser messages with fixed syntax diagnostics and numeric file coordinates. Env layers, legacy contracts, materialization state and secret stores share the rule, so their CLI, daemon and MCP consumers cannot surface parser source snippets. Accepted input still uses the original parser; structured diagnostics run only for rejected input.

Ignore legacy .env.* overlays in both managed ignore paths, diagnose tracked or unignored files in doctor, and refuse POST /v1/env/set and POST /v1/env/unset for YAML-layer projects with yaml_env_mutation_unsupported. Existing maintenance operations upgrade ignore rules. .env.state.json remains ignored and diagnosed if tracked.

Audit verification

The key-inheritance and legacy-write/ignore findings are confirmed at c89f4fd. Raw parser-message forwarding is also present. JSON reflection is reproduced with an unquoted synthetic token and covered through daemon GET and mutation tests. YAML source-line leakage was not reproduced with malformed YAML samples on pinned Bun 1.4.4: those samples returned generic Unexpected token/Unexpected EOF messages. The parser boundary is hardened defensively instead of claiming that unobserved result. Bun error line/column fields describe the JavaScript callsite; the new diagnostic uses input offsets instead.

Validation

  • bun run typecheck: passed; CLI uncached, DB cached.
  • bun run check: passed, including privacy scan; existing complexity warnings remain.
  • Changed tests lint: passed. bun run build: passed.
  • Focused regressions: 144 passed across env config, legacy env, secret store, lifecycle child, background process, Compose CLI and key-ignore files.
  • Added sentinel coverage: real host-exec and lifecycle children; detached background command; real docker compose config interpolation with isolated client configuration and no engine access; four malformed YAML layer kinds through resolver, mutation and CLI text/JSON; malformed legacy contract and secret-store JSON; daemon YAML refusal; tracked/unignored overlays and both ignore upgrades.
  • Test-isolation scanner and explicit Hack re-exec regression: passed.
  • fix(ci): select pull-request tests and block draft merges #733 selector selects the full suite because the dependency/lockfile changed. Full-suite compiler preflight is unavailable on this host; no compatible Linux compiler is prepared and the host has no C toolchain. Hosted Linux CI is the wider gate; no macOS or Docker qualification is claimed.

Release and review

fix(env) corrects credential exposure and legacy file handling. The daemon mutation endpoints now return a named 409 instead of writing a legacy file for YAML-layer projects. Follow-up output and encryption-migration work is tracked separately in HACK-2166. The persistent cross-family reviewer was clean at d44a6fe; the final two-line revision preserves the native SyntaxError kind identified by hosted CI and corrects a docs verb. Its final re-review and current-head hosted checks remain pending. No unresolved bot threads were present at d44a6fe.

Hosted CI identified a native metadata error-kind regression (SyntaxError became Error). The final fix preserves SyntaxError while keeping the sanitized message; all 42 tests in native-env-metadata and env-parse-diagnostic now pass locally.

@vercel

vercel Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hack-docs Ready Ready Preview Nov 13, 2026 9:20am UTC

Request Review

@linear-code

linear-code Bot commented Nov 13, 2026

Copy link
Copy Markdown

HACK-2163

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T09:25:00.572983Z f245f70 Manual request
🔒 Security Review ✅ Completed 2026-11-13T09:29:24.278404Z f245f70 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: ef5a669e54

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: ef5a669e54

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Audit mapping:

  • S2: fix(env): contain child keys and env diagnostics (HACK-2163) #756 removes custody keys from default child environments, including background supervisors and the Compose client. Native background commands are explicit Hack re-execs and retain the keys until their eventual user child applies the filter. Managed global plaintext still reaching non-Compose Docker helpers is not yet covered; that least-privilege correction is queued in HACK-2166 alongside scope isolation.
  • S4: fix(env): contain child keys and env diagnostics (HACK-2163) #756 refuses both legacy set and unset mutations for YAML-layer projects. Modern-format metadata for daemon GET is not yet covered and is queued in HACK-2166.
  • F2: covered by .env.* in both managed ignore paths, upgrade tests, and doctor detection of tracked/unignored overlays. .env.state.json keeps its existing treatment.
  • S6: covered here by fixed JSON diagnostics at the contract boundary. A synthetic unquoted JSON token is reflected by pinned Bun's raw parser error; new daemon GET and mutation tests verify that the token never reaches either response. The YAML source-snippet claim remains qualified as described in the PR body.
  • F10/S5: queued as HACK-2171 after HACK-2166: revalidate migration cleanup content/identity under writer locks, and return an explicit failure/unknown-outcome status when secret deletion fails.

The persistent reviewer found and helped close the native-background re-exec regression. Its follow-up review and hosted Linux results remain pending; this is not the readiness comment.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: d44a6fe747

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: a0b1043767

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@roodboi

roodboi commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor Author

Ready for lead:

Head: a0b1043. The persistent cross-family reviewer is clean at this exact commit after three rounds. No merge is requested from this session; the independent lead review remains a gate.

  • Child keys: one shared filter removes both decryption keys plus the other identified Hack auth variables, including overrides and the Compose client. Deliberate Hack re-execs retain keys explicitly and filter their eventual user children. Tests exercise real host exec, lifecycle hooks, detached background work, the native re-exec/supervisor chain and a real Compose config render with isolated client configuration and no engine access.
  • Parser diagnostics: env layers, legacy contracts, materialization state and secret stores emit fixed syntax diagnostics and numeric positions. Tests place sentinels on malformed lines across all four YAML layer kinds, CLI text/JSON, daemon GET/set and secret-store JSON. A synthetic unquoted JSON token reproduces the original reflection. The pinned Bun YAML samples did not reproduce source-snippet leakage; the PR states that qualification. Hosted CI caught an error-class regression; the final correction preserves SyntaxError, and all 42 native-metadata/parser tests now pass locally and in the reviewer's rerun.
  • Legacy overlays: .env.* is ignored through both managed paths and existing maintenance upgrades them. Doctor detects tracked/unignored overlays. .env.state.json keeps its previous treatment. Daemon set AND unset refuse YAML-layer projects before legacy/backend mutations. Tests cover upgrades, tracking detection, unchanged legacy contents under refusal and named errors.

Local evidence: typecheck, root lint/privacy, changed-test lint and build passed; the focused env/background/lifecycle/store/Compose regressions passed. The reviewer independently ran 66 focused tests before the final two-line correction and 42 after it. The full selector chooses the full suite because a dependency changed; this host cannot satisfy the compiler preflight, so full local-suite coverage is not claimed.

Hosted status when this comment was prepared: Linux test shards 4/8–8/8 and docs site were still running; change scope, test focus and secret scan passed. The draft test and docker-e2e fan-ins intentionally fail until the PR is marked ready. Current-head bot code review was still running, with no unresolved findings; the review-thread audit returned CLEAR at a0b1043. The clean bot receipts on earlier commits are not presented as current-head approval. macOS/Docker qualification has not been awaited, per the work-unit instructions.

Material limits: native background behavior is proven at the Linux process boundary, not the macOS runtime. Existing tmux servers are not retroactively scrubbed. Adopted-project ignore repair retains its existing ownership policy. Rust runtime parsers are outside this patch.

Follow-up grouping and ownership:

  • HACK-2166: metadata-only env listing, explicit interactive value reveal, selected lifecycle scopes, refusing secret values in argv, names-only plaintext inventory plus in-place encryption migration, non-Compose Docker helper env isolation (remaining S2), and modern daemon GET metadata (remaining S4).
  • HACK-2171: cleanup content/identity receipts under source-writer locks (F10), and explicit failed/unknown daemon deletion outcomes (S5). S6's legacy JSON diagnostic leak is already covered here.
  • The assigned at-rest/local-layer/temporary-file and doctor-hygiene work stays with HACK-2165; store/key integrity with HACK-2169; lifecycle logs with HACK-2170; dead-supervisor storage with HACK-2162; broader doc corrections with HACK-2167. These are separate PRs, not duplicated in this patch.

@roodboi
roodboi marked this pull request as ready for review November 13, 2026 06:13
@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: a0b1043767

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Hosted evidence update at a0b1043: Linux test shards 4/8–8/8 and the Docker checks are now successful. The remaining queued jobs are macOS compiler/candidate and test shards 1/8–3/8. An older draft/cancelled-run test fan-in still appears red; it is not a new test assertion failure. No required gate has been changed or bypassed.

The persistent review is clean and the bot-thread status is CLEAR at a0b1043. Per the work-unit instruction, this session is not waiting on macOS or Docker qualification. The lead's independent review and merge decision remain separate gates; implementation continues in HACK-2166.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Ready for lead: #756 is updated at 5d9e230, merging next e7a7039. The native-log-follow conflict keeps all of #747's new session/restart/output handling and applies childEnvironment(runtimeEnvironment()) at its new sole spawn. The diff from next for that file is exactly the import and that environment wrapper. Persistent review is clean at this full head.

  • MUST1: doctor no longer untracks shared .env.* overlays, templates or backups. It reports overlays separately, reuses the migration exclusion helper, and directs them to doctor --migrate-env-config before removal. The lower-level untracking helper also refuses them. .env.state.json retains its previous generated-file behavior. Shared template names are re-included in both committed ignore rules and info/exclude. Real Git regressions check that the index entries survive and new templates remain visible.
  • MUST2: the Compose interpolation test probes the plugin with the same isolated Docker configuration and skips if that configuration cannot find it. The isolated test passes on this Linux host; no Mac plugin installation is read or changed.
  • The tmux note is fixed: explicit new-session -e values also pass the shared key-material filter.
  • Compiled re-exec verification: the freshly built current executable does not load a fixture project bunfig preload or .env, even when the deliberate re-exec carries a synthetic key. A control build without the no-autoload flags executes the preload and fails the same test. The existing package build disables dotenv, bunfig, tsconfig and package-json autoload. No actual key or user config was read.

Pinned-Bun typecheck, lint and build pass. Verification includes 31 doctor/ignore/child cases (one separate macOS ACL case skipped), 30 mocked doctor-fix cases, 7 tmux cases, and 49 native log follow/process/restart/source cases after merging Batch A. The fresh compiled-autoload check also passes after that merge. Hosted Linux CI and the new bot review are still pending; macOS and Docker qualification are not being waited on.

Audit mapping: S2's key containment is here; managed-value isolation follows in #767. S4's YAML set/unset refusal is here; canonical GET metadata follows in #767. F2 now preserves shared overlays/templates while ignoring private overlays. S6 parser redaction remains covered by direct daemon/parser sentinel tests.

Known notes retained: existing tmux server environments are not purged; crash-capture re-execs keep the default filtered environment, which can limit diagnostics for environment-only keys; runner unset keys apply before explicit overrides by its existing contract. The urgent live-key cleanup fix is independently reviewable in #769 and should land ahead of the stack. No merge performed by this session; lead review and hosted gates remain.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 5d9e230d61

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 5d9e230d61

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Ready for lead: HACK-2163 is complete at f245f70. Merged next 2afb5c4 additively; no conflicts or history rewrite.

The three containment fixes remain: shared child-environment key filtering with deliberate Hack re-execs; source-free env parse diagnostics; legacy overlay ignore/doctor handling and YAML-project daemon mutation refusal. Lead MUST fixes preserve tracked overlays/templates, never auto-untrack them, un-ignore templates, and probe Compose under the test's isolated config before running its interpolation test. The tmux override filter remains.

Sentinel regressions cover host/lifecycle/background/Compose, parser and daemon replies, Git index/template preservation and ignore maintenance. A fresh compiled CLI passes the project bunfig-preload/dotenv autoload regression; its earlier unsafe control build failed the same test. On the final integrated tree, 103 startup/native-convention/child-environment cases pass, plus the opt-in compiled test separately; root typecheck/lint/build pass. The persistent reviewer is clean at this exact merge and verified the env delta is unchanged from the prior reviewed head. Review-thread audit: CLEAR at f245f70; earlier bot findings are fixed/replied/resolved. A new-head bot review is requested.

Hosted jobs have not yet reported for this new merge head; Linux test shards, typecheck/lint and required fan-ins remain pending, as do any selected macOS/Docker jobs. Previous-head passes are not promoted to current-head proof. No macOS or real Docker qualification is claimed locally.

S2 key containment is here; remaining managed-value/lifecycle isolation and S4 canonical metadata are in #767. F2 is here; S6 JSON diagnostic redaction is here. Follow-ups remain split across HACK-2165, HACK-2169, HACK-2170, HACK-2162 and HACK-2167; HACK-2171/#768 owns cleanup receipts/deletion outcomes, HACK-2172/#769 preserves live keys, and HACK-2173 owns secret-to-plaintext downgrade refusal.

Full head SHA: f245f70. Independent lead review and hosted gates remain; no merge performed.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: f245f70d27

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: f245f70d27

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

roodboi added a commit that referenced this pull request Nov 13, 2026
Legacy migration cleanup could remove `.hack.secret.key` when an
encrypted-file backend reused it as its own key file. The migration
encrypted YAML entries with that key, then offered the same file for
deletion. Removing it made the migrated entries unreadable.

Cleanup candidate selection now excludes live project inputs: the local,
shared Git and primary-checkout project keys, YAML env layers and
project config. Paths and device/inode identities protect aliases
through symlinked directories, hard links and case-insensitive
spellings. Both `.hack` and legacy `.dev` inputs are covered. The
deletion boundary independently refuses any request containing a live
input before removing any files, and rechecks before each unlink. The
env guide states that legacy backend configuration cannot make those
files disposable.

The real-files regression fails against `next` at
`cce4b5954a4b1889b095bda796bea561142d6b52`: cleanup removes the reused
key and the next YAML read throws `ProjectEnvKeyMissingError`. With this
change the legacy store and contract are removed, the key remains and
the migrated value decrypts. A second regression covers shared/local
keys, YAML/config candidates, and refusal before an earlier ordinary
file can be deleted. Fixtures use synthetic values and temp directories
only.

Validation: pinned Bun typecheck and lint pass; five regressions pass
(40 assertions), and all 60 focused project-env-config cases pass. The
regression includes a real migration through a symlinked parent and a
legacy `.dev` deletion guard. Case-variant coverage runs when the
fixture filesystem supports it; no macOS qualification is claimed. The
selector chooses 677 files; the full compiler-dependent local suite is
unavailable, so hosted Linux CI remains the wider gate. No host Docker
or real credential state was used.

This is an urgent, independent HACK-2172 fix directly against `next`,
ahead of #756/#767/#768. F10 content/identity receipts and broader
cleanup failure reporting remain in #768. No history rewrite or merge is
performed by this session; lead review remains required.

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
@roodboi
roodboi merged commit c96c444 into next Nov 13, 2026
30 checks passed
@roodboi
roodboi deleted the codex/hack-2163-env-secret-leaks branch November 13, 2026 10:41
roodboi added a commit that referenced this pull request Nov 13, 2026
next (c96c444) conflicts in src/lib/hack-env.ts: #756 (HACK-2163)
added envParseDiagnostic; this branch reads every legacy dotenv file
through the no-follow readLegacyDotenvText, so readTextFile is no longer
imported. Both are kept.

Co-Authored-By: Claude <noreply@anthropic.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
… environment (HACK-2165)

Second-family review of the merge with next (723ee60): #756 filters
Hack key material out of the git probes' environment, but this
branch's extra `ls-files :(icase,literal)` probe was added after that
base and auto-merged without it, so git inherited
HACK_ENV_SECRET_KEY and the other credentials. It now passes
childEnvironment(). Test: a local `env set` with a key sentinel in
Hack's environment records the probe's child environment through the
spawn recorder; it is explicit and holds no sentinel.

Co-Authored-By: Claude <noreply@anthropic.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
…K-2166) (#767)

Env listings exposed migrated plaintext, legacy lifecycle commands
received service values outside their scope, and secret writes accepted
values in argv. Listings now show metadata by default, lifecycle
delivery is scoped, and chosen plaintext entries can be encrypted in
place without copying values through a terminal.

- Text and JSON listings expose names, scope, source layer and set
state. Revealing values requires an explicit flag and an interactive
terminal. This reduces accidental output exposure; it is not access
control against a local process.
- `env add/set --secret` refuses positional values with stdin guidance
before effects. Malformed add keys are validated before that guard, so
pasted assignments receive a fixed, value-free refusal in either
interactivity mode.
- Legacy lifecycle hooks/processes receive only global values. Docker
inspection/log/event helpers receive OS and transport settings,
preserving Docker, Podman, SSH and XDG context variables without
application values.
- `env protect` lists plaintext names; `env protect KEY...` encrypts
matching entries in their existing scopes, overlays and local layers.
Existing ciphertext must decrypt before conversion; missing/wrong keys
refuse before writes. Local-overlay overrides remain part of the local
overlay. Doctor prints a names-only inventory and protection guidance
after migration.
- Daemon GET uses canonical YAML metadata without values; YAML-project
legacy set/unset routes retain the parent's HTTP 409 refusal. Agent
source, generated plugin, repository examples, ownership fingerprints,
security model and diagram agree with these boundaries.

Breaking change: scripts must replace `env list --json --show-secrets`
with explicit `hack env get KEY` reads for only the keys needed; never
log those plaintext reads. Use `has_value` for availability checks. Pipe
secret input with `--value-stdin`. Update text parsers for modern
key/scope/set/layer columns (value only on reveal) and legacy set/layer
columns 7/8. Review legacy hooks that depended on service values and
move only their required values to global scope. Use `env protect` to
inventory and encrypt chosen plaintext entries while keeping existing
key backups.

Next.17's generated release notes carry this breaking change, the
migration commands, daemon API changes and HACK-2172's live-key
preservation fix. The upgrade guide distinguishes planned next.17
behavior from the published next.16 snapshot. Publish next.17 only after
this PR is included; no release is performed here. Existing
secret-to-plaintext downgrade without `--secret` remains HACK-2173.

Validation on pinned Bun 1.4.4: root typecheck/lint/build, docs
generation/checks, 19 argument/exposure cases, 21 daemon/dependency
cases, 37 guidance/matrix cases, 51 scanner/background-process cases,
release-note tests and ownership tests pass. Additional original
listing/protection/worktree regressions remain in the branch. One plugin
release-preparation fixture cannot complete locally because a managed
runtime refuses an untrusted host toolchain config; no trust approval is
bypassed. Prepared-host verification or hosted CI is still needed for
that fixture. The selector chooses 742/full; the compiler-dependent full
local suite remains unavailable. Local checks do not qualify Mac VM or
real Docker behavior.

Targets `next` and includes next 021b16b. #756 and #769 have landed;
their squash history is reconciled additively. The merge-only comparison
tree for the lead's earlier verification is 814fbd1; later deliberate
changes are the refusal ordering, release notes, current-base
integration and guidance/audit reconciliation. HACK-2171/#768 follows
with cleanup receipts and truthful deletion failures. Other sessions
retain ownership of at-rest, store/key and lifecycle-log findings.

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
…ne key (HACK-2169) (#766)

Fixes HACK-2169 (env/secret audit items F7, F8, F9 and S3) and HACK-2036
(key file hygiene), and adds a `hack doctor` migration path for setups
those bugs already damaged.

## What changes

**Encrypted secret store (`encrypted_file`, and the `cloud` shim)**
- **F7:** a store that exists but cannot be read is never treated as
empty. Every reader classifies the store through one no-follow read: a
symlinked, non-regular or oversized store is refused, and any other read
failure raises `SecretStoreUnreadableError`. So a `set` can never
replace an unreadable store.
- **F9:** the process-wide key cache holds only keychain material. A key
read from one store's key file, or from the environment, never stands in
for another store's key.
- **HACK-2036:** the key file is read without following a link. It is
refused when group or other users can read or write it (mode `0600` is
required), or when git tracks it.
- The tracking check runs `git ls-files --literal-pathspecs
--error-unmatch` with a 5 s bound, and only when the key's real
directory (symlinks resolved, as git does) is inside a work tree.
- Inside a work tree where git cannot answer, the key is refused rather
than guessed untracked.
- **S3, explicit provisioning** (`hack env backend --provision-key` with
`HACK_SECRETS_FILE_KEY`):
- It **never replaces a different existing key**, or one it cannot read.
A key path can serve more than one store (the default one is shared),
and a key that does not open one store may be the only key for another.
Changing a key is a rotation, which re-encrypts; the refusal says to
move a key file aside yourself, keeping a copy, only once no store needs
it.
- With no key file, it writes the key only when the configured store is
absent or empty, or opens under that key. An unreadable or symlinked
store is refused, because a new key file could shadow the key that opens
it today.
- **Every key writer** (explicit provisioning, keychain persistence and
the first-use key) holds the key file's own `<key>.lock`, and each write
checks the file again just before it lands. A concurrent writer's key is
kept, never overwritten.

**Project env layers**
- **F8:** `hack env add --secret` and `hack env set --secret` refuse,
before writing anything, in two cases:
- `HACK_ENV_SECRET_KEY` is set but no `.hack.secret.key` exists (a new
key file would shadow the environment key);
- a secret already in the layer does not open under the key readers use.

Replacing the one entry being set is allowed. Legacy env migration
refuses the same way instead of creating a shadowing key.

**`hack doctor`: new `secret integrity` check**
- It reports, without values:
  - a store that is unreadable or refused;
  - a store key that is missing or refused;
  - a key that does not open its store;
  - an env layer with no available key, or the wrong key;
  - a layer with secrets under more than one key.
- It inspects every layer runtime can read, each read the way runtime
reads it: committed and machine-local layers, local-only overlays,
in-project symlinked layers, and, in a linked worktree, the primary
checkout's inherited local layers.
- For a mixed layer it names the secrets that do not open, with the
`--service`, `--env` and `--local` options needed to address them.
Recovery: read those values with the old key, `hack env unset` each one
(unset needs no key), then `hack env set --secret` again. For inherited
layers it says to run those steps in the primary checkout, and to fix a
divergent key first (the "worktree keys" check).
- Anything it cannot inspect is an **error, never success**: a layer
that exists but cannot be read or parsed, a directory that cannot be
listed, inheritance that cannot be resolved, or an inspection that
throws.

## Behavior changes to note in the release
- An `encrypted_file` key file that group or other users can read is now
refused until someone runs `chmod 600`. Hack has always written `0600`,
so this affects only key files made or changed by hand.
- `--provision-key` with a different `HACK_SECRETS_FILE_KEY` no longer
overwrites an existing key file; it refuses.
- A key file inside a git work tree whose git cannot report tracking
(git fails, is missing, or takes more than 5 s) is refused.

## Shared files
- `src/lib/project-env-config.ts`. All of these are outside #756's areas
and HACK-2165's local-layer writes:
- the secret branch of `setProjectEnvValue`, which now uses the
hydration key rules;
  - the new read-only inspector and its helpers;
  - a pre-write check in `migrateLegacyProjectEnv`.
- `src/commands/doctor.ts`: one new check (`secret integrity`), not in
the hygiene section.
- `shell.ts`, the env parse errors and the ignore list are untouched.
- HACK-2172 (#768): this PR adds no key-deletion path, so it has no "can
this key still decrypt something" predicate to share. If #768 needs one,
the read-only store listing here (`listFileSecretStoreEntries`, with its
new `reason`) is the building block.

## Follow-up (not in this PR)
- The project env key's own git-tracking check (the `.hack.secret.key`
helper in `project-env-config.ts`) still passes the file name without
`--literal-pathspecs`. The name is fixed, so the risk is low, but it
should match the store key check.

## Validation
- An independent persistent reviewer was clean after 9 rounds. The
lead's second-family review then ran three rounds and found the issues
fixed in the last four commits; its final round is clean on the code at
`9fc9e26f`.
- Every Codex finding (5) is fixed with a regression test, replied to
and resolved.
- Tests:
  - `tests/secret-store.test.ts`:
- F7, F9, HACK-2036 (mode, symlink, tracked, a key reached through a
symlinked directory, a git that cannot answer);
- provisioning refusals, including a different key shared with another
store, and unreadable or refused stores;
    - three concurrent provisions writing exactly one key;
- a first-use bootstrap that waits for the key lock and adopts the key
written meanwhile.
  - `tests/project-env-secret-key-integrity.test.ts`: F8.
- `tests/doctor-secret-integrity.test.ts`, isolated from the real home
and global config:
    - every finding is value-free;
- mixed-key recovery runs end to end, with the old values read under the
old key;
    - local-only, symlinked, legacy and inherited layers;
    - unreadable, unparseable and unlistable layers reported as errors.
  - `tests/env-migration-safety.test.ts`: the migration refusal.
- Local gates (Bun 1.4.4): `bun run typecheck`; `bun run check` at the
39-warning baseline; `privacy:check`; gitleaks over `origin/next..HEAD`.
574 tests across the related env, secret, doctor, inheritance,
migration, hermeticity and CI-selection suites pass.

```mermaid
stateDiagram-v2
    [*] --> Locked: --provision-key with HACK_SECRETS_FILE_KEY (holds <key>.lock)
    Locked --> Refused: key file unreadable
    Locked --> Refused: a different key is there
    Locked --> CheckStore: no key file, or an empty one
    Locked --> Write: the same key (0600 rewrite)
    CheckStore --> Refused: store unreadable or refused
    CheckStore --> Refused: store has entries the key does not open
    CheckStore --> Write: store absent or empty, or opens under the key
    Write --> Written: file unchanged just before the write lands
    Write --> Refused: another key landed meanwhile
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
…ent; close threat-model gaps 17 and 18

isKeyFileTrackedByGit (from #766) spawned git with the full environment,
so HACK_ENV_SECRET_KEY and other Hack key material reached the child.
It now passes childEnvironment(), as #756 requires for tool children.
Regression: a fresh process with a recording git first on PATH checks a
key inside a work tree with a sentinel project key set; git sees no Hack
key variable. It fails without the change.

The threat model's gaps 17 (HACK-2169, closed by #766) and 18 (HACK-2165,
closed by #762 and this branch) now describe the implemented guards and
their remaining limits, and the rows that pointed at them as open agree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
…768)

Migration cleanup could delete a newer legacy env file after an earlier
confirmation decision. It now carries bounded content and file-identity
receipts from before migration, rechecks current scoped delivery and
Compose references under writer locks after consent, and checks each
target again before unlinking.

- Source files and YAML destinations use their existing env-layer writer
locks; the encrypted store and key use their separate owner locks in the
same sorted lock set. The key lock is shared by every store using that
path. Cleanup creates no repository-root `.internal/` for a key.
- Changed inputs, unavailable receipts or delivery drift preserve
remaining files. Partial failures retain every confirmed removal; the
key is removed only after its store.
- Automatic cleanup catches cleanup errors and warns so env/up/session
commands can continue. Explicit doctor cleanup fails closed. Recovery
advice preserves `--local`, secrecy, scopes and overlays and uses stdin
rather than promising a migration rerun imports changed values into
existing YAML.
- Doctor puts an untracked legacy key in its tracked store's
confirmation batch. Declining that batch keeps both; accepting it
removes the store before its key. The key-only deletion refusal remains
intact.
- Legacy daemon secret deletion failure returns HTTP 500
`partial_failure`, fixed `secret_delete_unconfirmed` text and
`secretDeleted: null`, preserving the completed `dotenvChanged` result.
It does not claim backend absence or rollback.

This addresses audit F10 and S5. S6's value-free legacy JSON diagnostics
arrived in merged #756. HACK-2172/#769 already preserves live
project/shared keys, config and YAML inputs, including aliases; this PR
keeps those guards before/under locks and immediately before unlink.

The integration includes next `ab29d491` and the landed parent fixes. A
held-key-writer regression fails without adopting the new HACK-2169
key-owner lock and passes with it. A real temporary Git regression
reproduces the tracked-store/untracked-key batching refusal without the
fix and passes afterward.

Pinned Bun validation: 39 cleanup/live-key/daemon cases, 56
store/integrity cases and 14 selected doctor migration cases passed
before the final batching change. For the batching change, 19 legacy
cleanup cases (117 assertions), both doctor store batches (19
assertions), typecheck, root and changed-file lint, build and docs
checks pass. The plugin release-preparation fixture also passes (13
assertions) after an owner-approved trust step scoped to an isolated
test home; no global trust setting changed. Persistent review is clean
at exact head `6cf07d3801ba00c6f4399b4eadc6ae8e85fa051f`. Hosted checks
and the refreshed GitHub review remain pending. The full
compiler-dependent suite remains a hosted gate; no new Mac VM or real
Docker qualification is claimed locally.

Noncooperating writers can still race the last unlink. The reverse
consent case (untracked store, tracked key, initial cleanup declined)
retains its existing safe refusal. Opposing future lock nesting can time
out safely; normal key writers hold only the key lock and normal store
writers resolve the key before taking the store lock. No cipher-format
or rotation change is made.

Targets `next`; all parent PRs have landed and their squash ancestry is
reconciled by additive merge. No history rewrite, merge to next or
publication is performed here. The lead arranges independent review
before merge.

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
roodboi added a commit that referenced this pull request Nov 14, 2026
The next.17 section omitted the tmux breaking-change warning that
already existed at the page tail. Move it into the release section and
put its v4 stop procedure before the v5 trial. The env breaking entry
was already correct; keep its scoped single-key/terminal/stdin migration
guidance.

Audit all **71 commits** from `v5.0.0-next.16` (`b21c3b1898`) through
candidate **`5002cf87bb50686b17ceae8a4c835f524ee1b3a5`** against merged
code and PR text. Add missing upgrade-assistant, activity,
observe/plan/version, interactive exec, recovery, background-command and
host/secret-custody notes. Preserve the complete native env-file
behavior table and mark the four new JSON contracts **shape may change
before 5.0.0**, with the planned HACK-2238 envelope migration.

Correct stale native interactive-exec/network/metadata/Ctrl-C claims and
the short upgrade assistant wording. Credit the publisher-shutdown fix
to #719, already in next.16; keep next.17 lifecycle-command retirement
separate. Retake a private stopped-state backup after v4 stops zellij,
keeping the first copy too. Keep next.16 warnings scoped to that bundle.
Keep original-key backups before older Doctor migrations and distinguish
file rollback from runtime/data recovery.

Only eight Markdown files change. Runtime, tests, workflows, generated
CLI reference, diagrams, immutable snapshots and the site pin are
unchanged. No diagram changed, so a new visual would add nothing. The
site re-pin remains a separate release follow-up.

Merge timing: respect the lead's candidate freeze; intended for the
batch immediately after next.17 publication and the site re-pin. The
moved tmux breaking-change notice is called out for the lead's pre-cut
decision. This PR does not merge or publish anything.

Validation at **`d95cfc554fabc4a0d70e3ba6caeb6746f63a198c`**:
- Bun 1.4.4, frozen dependencies. Docs prepare/check/typecheck/build and
site tests (2 passed, 25 assertions) pass. Production-mode HTTP smoke:
97 docs, 82 SVGs, 217 local links/anchors; task server stopped.
- All 50 Hack commands named anywhere in the notes exist in the current
generated CLI reference; 19 option contracts checked. CLI-reference
regeneration has no diff.
- All 71 commits have one row below, including the test commit and merge
for #786. All 70 source evidence paths exist at the fixed candidate.
Source release-note local links/anchors pass.
- Privacy and complete reachable-history Gitleaks pass (1,330 commits,
no findings). Persistent Claude Opus second-family review is CLEAN at
this exact head. Hosted run 43585059152 passed docs site, secret scan
and every planned Linux unit shard (4–8), plus the required test fan-in.
Typecheck/privacy/quality ran on shard 8. Focus had no selected tests.
Compiler, native core, runtime images/models, process-lifetime and
Docker execution were out of scope; a green Docker fan-in is not Docker
execution evidence. All bot comments were read; CLEAR at d95cfc5,
zero unresolved threads/change requests. Codex code/security reviews
found no issues.
- No real install, migration, daemon/DNS/trust change, Docker or native
VM run was performed for this documentation audit. Native acceptance and
the candidate's hosted release qualification remain separate.

## Candidate commit coverage

`entry present` means the behavior already had an entry within the
next.17 section (some now have fuller detail). `added` means missing
behavior or migration guidance was added there; #824 moves the existing
warning into that section. `not user-visible` means no shipped
CLI/runtime change: documentation, test/CI/repository housekeeping or
the internal desktop preview. Source links pin the candidate, rather
than a moving branch.

| Commit / PR | Coverage | Entry or reason | Audited source |
| --- | --- | --- | --- |
|
[70d328e](70d328e)
[#743](#743) | added | Host
setup: privileged/NSS safeguards |
[src/lib/linux-trust-setup.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/linux-trust-setup.ts)
|
|
[51f15c8](51f15c8)
[#746](#746) | not user-visible |
Docs-only upgrade checklist and site generation; no installed behavior |
[scripts/docs/prepare.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/docs/prepare.ts)
|
|
[c14f3f5](c14f3f5)
[#744](#744) | added | Native
setup JSON accounting |
[packages/runtime-core/src/provider/setup.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/provider/setup.rs)
|
|
[b0c6bcd](b0c6bcd)
[#705](#705) | added | Retained
background exec/run and cursor tools |
[src/commands/background-command-start.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/background-command-start.ts)
|
|
[c89f4fd](c89f4fd)
[#745](#745) | added | Linux
daemon query/home refusals |
[src/commands/daemon-systemd.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/daemon-systemd.ts)
|
|
[cce4b59](cce4b59)
[#752](#752) | not user-visible |
Site pin/snapshots and editorial pages only |
[scripts/docs/versions.json](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/docs/versions.json)
|
|
[56676fc](56676fc)
[#754](#754) | added | Setup
reuse/offline accounting; pin-watch changes are internal |
[packages/runtime-core/src/provider/setup.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/provider/setup.rs)
|
|
[7a496f1](7a496f1)
[#755](#755) | added | MCP
registered selectors and background tool guidance |
[src/mcp/server.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/mcp/server.ts)
|
|
[e7a7039](e7a7039)
[#747](#747) | entry present |
Native follow text shape; added session ends/restart recovery |
[src/backends/native-log-follow.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-log-follow.ts)
|
|
[87a6df5](87a6df5)
[#758](#758) | added | Compose
short one-shot startup |
[src/lib/compose-startup-state.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/compose-startup-state.ts)
|
|
[2afb5c4](2afb5c4)
[#761](#761) | added | Native
Hack networks and inert generated labels |
[src/lib/native-hack-compose-conventions.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/native-hack-compose-conventions.ts)
|
|
[342a585](342a585)
[#771](#771) | not user-visible |
Docs-only next.16 trial record |
[docs/versions/v5/guides/upgrade-from-v4.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/versions/v5/guides/upgrade-from-v4.md)
|
|
[6f0acf1](6f0acf1)
[#769](#769) | entry present |
Migration live-key/alias preservation |
[src/lib/project-env-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-env-config.ts)
|
|
[c96c444](c96c444)
[#756](#756) | added | Child key
filtering, fixed diagnostics, legacy ignore/YAML API refusals |
[src/lib/child-environment.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/child-environment.ts)
|
|
[e2c73c6](e2c73c6)
[#748](#748) | not user-visible |
Contributor CI selection/coalescing, outside product release notes |
[scripts/ci-change-scope.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/ci-change-scope.ts)
|
|
[ebf794e](ebf794e)
[#760](#760) | added |
Agent/output custody warning; runtime unchanged |
[src/agents/instruction-source.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/agents/instruction-source.ts)
|
|
[021b16b](021b16b)
[#763](#763) | added | One-pass
background redaction scan; no public benchmark claim |
[src/lib/background-command/output-scanner.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/background-command/output-scanner.ts)
|
|
[8564ec4](8564ec4)
[#765](#765) | added | Shared
preflight/start admission and detached failure reporting |
[src/backends/native-project-review.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-project-review.ts)
|
|
[0c0fba2](0c0fba2)
[#767](#767) | entry present |
Breaking env exposure/protect/stdin/scope/API guidance |
[src/commands/env.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/env.ts)
|
|
[9435da9](9435da9)
[#762](#762) | added | Local
Git/link refusals and no-follow dotenv |
[src/lib/project-env-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-env-config.ts)
|
|
[edf23ae](edf23ae)
[#753](#753) | added | Daemon
stop proves the live Hack home |
[src/commands/daemon-systemd.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/daemon-systemd.ts)
|
|
[573ceec](573ceec)
[#766](#766) | entry present |
Doctor layer/integrity error; added store/key write refusals |
[src/lib/secret-store.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/secret-store.ts)
|
|
[a0e9760](a0e9760)
[#757](#757) | added | Orphan
output truncation and final-sync evidence |
[src/lib/background-command/recovery.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/background-command/recovery.ts)
|
|
[10e1958](10e1958)
[#759](#759) | added | Private
lifecycle logs/FIFO and expiring mux payloads |
[src/lib/private-file.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/private-file.ts)
|
|
[bd899ee](bd899ee)
[#775](#775) | not user-visible |
Portable test fixtures only |
[tests/single-file-tar.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/single-file-tar.test.ts)
|
|
[80dae3d](80dae3d)
[#776](#776) | added | Candidate
missing-daemon diagnosis is optional/healthy |
[src/commands/doctor.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/doctor.ts)
|
|
[5b2a2d0](5b2a2d0)
[#772](#772) | added | Bounded
attaching-network retry; strict saved reads remain |
[src/lib/native-compose-ownership.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/native-compose-ownership.ts)
|
|
[ab29d49](ab29d49)
[#777](#777) | not user-visible |
CI scheduling only |
[docs/reference/ci-test-selection.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/reference/ci-test-selection.md)
|
|
[31339c7](31339c7)
[#770](#770) | entry present |
Native inferred readiness, 240 s, HTTP/service_healthy limits |
[packages/runtime-core/src/project/compose/service.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/project/compose/service.rs)
|
|
[156ee7f](156ee7f)
[#773](#773) | entry present |
Loopback proxy port/Doctor/open checks |
[src/lib/proxy-loopback.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/proxy-loopback.ts)
|
|
[a7ec3c7](a7ec3c7)
[#768](#768) | entry present |
Cleanup receipts/partial outcomes and tracked-file wording |
[src/lib/project-env-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-env-config.ts)
|
|
[ceb3e23](ceb3e23)
[#778](#778) | entry present |
Native bridge socket readiness |
[packages/runtime-core/src/provider/bridge.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/provider/bridge.rs)
|
|
[af91049](af91049)
[#783](#783) | entry present |
Pointer reconciliation after partial cleanup |
[src/commands/doctor.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/doctor.ts)
|
|
[0a0bfdb](0a0bfdb)
[#780](#780) | not user-visible |
Site-only Linux guide publication; no CLI behavior |
[scripts/docs/versions.json](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/docs/versions.json)
|
|
[d0cf767](d0cf767)
[#786](#786) | not user-visible |
Consent test wording only (both commits) |
[tests/env-migration-tracked-consent.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/env-migration-tracked-consent.test.ts)
|
|
[7e2e630](7e2e630)
[#786](#786) | not user-visible |
Consent test wording only (both commits) |
[tests/env-migration-tracked-consent.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/env-migration-tracked-consent.test.ts)
|
|
[91c311e](91c311e)
[#779](#779) | entry present |
Restore or reversible retire; missing store keys scoped to readers |
[src/lib/secret-store-retire.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/secret-store-retire.ts)
|
|
[6ab1ace](6ab1ace)
[#785](#785) | not user-visible |
Docs-only release/upgrade/env notes |
[docs/guides/v5-release-notes.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/guides/v5-release-notes.md)
|
|
[25bd63c](25bd63c)
[#764](#764) | entry present |
Doctor hygiene, local modes, ignored staging and live-input protection |
[src/lib/secrets-hygiene.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/secrets-hygiene.ts)
|
|
[d9df57c](d9df57c)
[#784](#784) | not user-visible |
Resolver/proxy and consent test corrections only |
[tests/project-open-loopback.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/project-open-loopback.test.ts)
|
|
[2c1f665](2c1f665)
[#791](#791) | added | Detached
failure names, open DNS hint, init placeholder; prune guidance |
[src/commands/project.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/project.ts)
|
|
[f6fe55f](f6fe55f)
[#787](#787) | not user-visible |
Docs-only retirement/hygiene follow-up |
[docs/guides/v5-release-notes.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/guides/v5-release-notes.md)
|
|
[7f9548c](7f9548c)
[#792](#792) | not user-visible |
Start-here docs, navigation and contributor rule only |
[docs/versions/v5/install.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/versions/v5/install.md)
|
|
[a0cfc73](a0cfc73)
[#793](#793) | added | Verified
updater publication, backups and reversible candidate removal |
[src/lib/self-update.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/self-update.ts)
|
|
[292d312](292d312)
[#782](#782) | added | Lock-free
native ps and proved failed-start down |
[src/backends/native-project-observe.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-project-observe.ts)
|
|
[b1e123b](b1e123b)
[#796](#796) | added | Doctor
reader count/worktree grouping in store recovery |
[src/lib/doctor-secret-integrity.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/doctor-secret-integrity.ts)
|
|
[286d00f](286d00f)
[#789](#789) | added | Foreground
command-before-wrapper retirement |
[src/lib/project-lifecycle-processes.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-lifecycle-processes.ts)
|
|
[bb6a7d1](bb6a7d1)
[#788](#788) | not user-visible |
Linux qualification runbook only |
[docs/guides/linux-host-qualification.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/guides/linux-host-qualification.md)
|
|
[a262d42](a262d42)
[#800](#800) | not user-visible |
Internal desktop design; outside supported CLI release scope |
[apps/desktop/DESIGN.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/apps/desktop/DESIGN.md)
|
|
[6b161ba](6b161ba)
[#774](#774) | added | Native
interactive exec, finite fallback and receipt recovery |
[src/backends/native-project-exec.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-project-exec.ts)
|
|
[1249272](1249272)
[#799](#799) | not user-visible |
Portable output-contract CI selection only |
[scripts/test-shard-plan.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/test-shard-plan.ts)
|
|
[fa3f03d](fa3f03d)
[#790](#790) | added | Read-only
upgrade check, snapshot and rollback |
[src/commands/upgrade.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/upgrade.ts)
|
|
[c3b79bc](c3b79bc)
[#807](#807) | added |
Observe-only global status and unknown evidence |
[src/commands/global-status-observe.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/global-status-observe.ts)
|
|
[29be043](29be043)
[#812](#812) | added | Read-only
local CA trust diagnosis |
[src/lib/ca-trust-status.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/ca-trust-status.ts)
|
|
[f0102fd](f0102fd)
[#814](#814) | not user-visible |
Prepared-base verifier test fixture only |
[tests/qualify-provider-pin.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/qualify-provider-pin.test.ts)
|
|
[b4ebfec](b4ebfec)
[#815](#815) | added | Compact
upgrade plan, snapshot-backed apply/resume |
[src/lib/upgrade-apply.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/upgrade-apply.ts)
|
|
[c44b266](c44b266)
[#801](#801) | not user-visible |
Internal optional desktop preview; not shipped CLI behavior |
[apps/desktop/Cargo.toml](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/apps/desktop/Cargo.toml)
|
|
[56d1d0f](56d1d0f)
[#804](#804) | added | Automatic
mux sweep preserves live/retired config inputs |
[src/lib/live-inputs.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/live-inputs.ts)
|
|
[1958363](1958363)
[#805](#805) | added | MCP
timedOut result and Codex installer timeout |
[src/mcp/server.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/mcp/server.ts)
|
|
[e6207e8](e6207e8)
[#810](#810) | added | Lifecycle
activity writes including handler refusals; activity JSON |
[src/commands/lifecycle-activity.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/lifecycle-activity.ts)
|
|
[23fe08f](23fe08f)
[#825](#825) | added | Read-only
batch review and permission-only key repair |
[src/lib/upgrade-review.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/upgrade-review.ts)
|
|
[cab596c](cab596c)
[#781](#781) | entry present |
Full native env-file behavior table; added support/precedence summary |
[src/backends/native-compose-environment.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-compose-environment.ts)
|
|
[1e84684](1e84684)
[#798](#798) | not user-visible |
Rust test process isolation/nextest; internal qualification only |
[scripts/test-runtime-core.sh](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/test-runtime-core.sh)
|
|
[518af29](518af29)
[#817](#817) | not user-visible |
Remove accidental empty checkout files; no installed CLI change |
[.gitignore](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/.gitignore)
|
|
[07192f7](07192f7)
[#824](#824) | added | BREAKING
warning moved from page tail into next.17; v4 stop procedure retained |
[src/mux/mux-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/mux/mux-config.ts)
|
|
[fe09a5b](fe09a5b)
[#816](#816) | added | Read-only
install/trust admin plans and exits |
[src/commands/global.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/global.ts)
|
|
[8977676](8977676)
[#827](#827) | added |
Registry-preserving project observe, runtime opt-in |
[src/commands/projects.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/projects.ts)
|
|
[5965b23](5965b23)
[#828](#828) | added | Running
CLI version identity JSON |
[src/lib/version-report.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/version-report.ts)
|
|
[2922210](2922210)
[#830](#830) | added | Upgrade
safe/admin/manual action kinds |
[src/lib/upgrade-action-kind.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/upgrade-action-kind.ts)
|
|
[51b55c0](51b55c0)
[#820](#820) | not user-visible |
Archive/plan/shared-helper verification fixtures only |
[tests/python-free-download.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/python-free-download.test.ts)
|
|
[5002cf8](5002cf8)
[#809](#809) | added | Retirement
read retry, second Ctrl-C and native cancellation cleanup |
[src/lib/project-lifecycle-processes.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-lifecycle-processes.ts)
|

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant