Skip to content

feat(env): report project key state in env list --json - #848

Merged
roodboi merged 2 commits into
nextfrom
kit/hack-2218-env-list-key-state
Nov 15, 2026
Merged

roodboi merged 2 commits into
nextfrom
kit/hack-2218-env-list-key-state

Conversation

@roodboi

@roodboi roodboi commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

hack env list --json now reports key_state, which says whether this checkout can read the project env key. The desktop Env tab needs it for its "Locked" state (HACK-2218, request R10).

key_state Meaning
ok A key is present and readable.
missing No key file and no HACK_ENV_SECRET_KEY. An empty or whitespace-only file counts as absent, as it does for the runtime.
unreadable A key file exists but the runtime refuses it (symlink, not a regular file, unreadable, not UTF-8, over 1 MiB).
not_checked Legacy hack.env.json contract, which does not use this key.
  • The lookup reuses the runtime's own read-only resolver: checkout .hack.secret.key, then the shared copy, then the primary checkout's copy, then HACK_ENV_SECRET_KEY. It never creates, repairs or rotates a key. The key text stays inside the probe; only the state is reported.
  • Names are still listed when the key is missing or unreadable, and the exit code is unchanged.
  • ok means only that the key can be read. It does not prove the key decrypts the stored values; hack doctor already reports undecryptable layers.
  • The text output of the layered format gains a project_key row.
flowchart LR
  A[env list --json] --> B{layered env format?}
  B -- no --> N[key_state: not_checked]
  B -- yes --> C[runtime key lookup, read-only]
  C -- key read --> OK[ok]
  C -- nothing found --> M[missing]
  C -- file refused --> U[unreadable]
Loading

Decision for the lead: no envelope. The brief asked for the HACK-2238 shape ({ok, data: {schema}}). But env list --json is a published bare object, and the HACK-2238 rule in #835 keeps published shapes unchanged ("No published payload is silently wrapped"; its inventory lists hack env list --json as legacy bare). Wrapping it would break the MCP projection and existing scripts. So key_state is an additive field, and errors keep using the existing E_* error envelope. If you want an envelope anyway, I would add it as a separate opt-in variant with its own schema id rather than changing the published shape.

Docs: docs/env.md (a table of the states), the v5 command contracts, the short v5 "Share environment" page, and desktop DESIGN.md (R10 marked as existing, plus the Locked row).

Verification (pinned Bun 1.4.4, temporary HOME/TMPDIR, daemon autostart disabled):

  • New tests/env-list-key-state.test.ts: 6 CLI cases (ok, missing, env-var fallback, empty file as absent with and without fallback, refused symlink, legacy). Each also checks that a sentinel secret value never appears in stdout or stderr. With the source change reverted, 0 of the original 5 pass.
  • Neighbouring suites (env-backend-command, mcp-inspect-tools, env-secret-sentinel-scan, missing-project-error-code, recipe-examples, env-key-argument-redaction-cli, portable-container-smoke, daemon-env, and the new file): 139 pass, 0 fail.
  • Root typecheck, Biome on changed files (only the existing complexity warnings), docs:prepare + docs:check: pass.

Not verified: the desktop app consuming the field, macOS, and the full root suite.

🤖 Generated with Claude Code

hack env list --json now carries key_state: ok, missing or unreadable for
the layered format, by the same lookup order the runtime uses, and
not_checked for the legacy hack.env.json contract. Names are still listed
when the key cannot be read. The key and values are never reported.

The payload keeps its published bare-object shape; no envelope is added.

Refs HACK-2218 (R10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 14, 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 14, 2026 4:58pm UTC

Request Review

@linear-code

linear-code Bot commented Nov 14, 2026

Copy link
Copy Markdown

HACK-2218

@roodboi

roodboi commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

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

Review Status Commit Review trigger
📝 Code Review ❌ Failed 2026-11-14T16:55:58.797654Z
We couldn’t complete this review. Comment @codex review to try again.
68985ad 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

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

The runtime skips an empty or whitespace-only key file and uses the next
location, so key_state reports missing (or ok through a fallback), not
unreadable. Align the docs and probe comment and cover both cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roodboi

roodboi commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

Ready for lead: c4d8629

R10 from HACK-2218: key_state (ok | missing | unreadable | not_checked) in hack env list --json, names only. Based on next 8e7242db94; it does not touch #797's files. Merge it after the freeze.

Decision to confirm: no envelope. The brief asked for the HACK-2238 envelope. But #835's rule keeps published shapes unchanged, and it lists hack env list --json as a legacy bare object, so key_state is an additive field and E_* errors are unchanged. The reviewer agreed. If you want an envelope, I would add it as a separate opt-in variant with a schema id. Wrapping the existing output would break the MCP projection and existing scripts.

What I ran (pinned Bun 1.4.4, temporary HOME/TMPDIR, daemon autostart disabled)

  • tests/env-list-key-state.test.ts: 6 pass, 0 fail. With the source change reverted, 0 of the original 5 pass.
  • Neighbouring suites (env-backend-command, mcp-inspect-tools, env-secret-sentinel-scan, missing-project-error-code, recipe-examples, env-key-argument-redaction-cli, portable-container-smoke, daemon-env): 139 pass, 0 fail at the first head. The second commit changes only a comment, the docs and the new test.
  • Root typecheck, Biome on changed files (only the existing complexity warnings), docs:prepare + docs:check: pass.
  • Second-family reviewer (Codex gpt-6.1-sol on codex-dio), one thread for both rounds. Round 1 had one should-fix: an empty key file is treated as absent, not unreadable. I fixed it in c4d862985 and added a test. Round 2: CLEAN at c4d8629. The review was static.
  • computer pr review-status: CLEAR at c4d8629.

Not verified

  • The Codex bot hit its usage limit, so there is no bot review.
  • Hosted CI was still running when I posted this.
  • ok means only that the key can be read, not that it decrypts the stored values; that is documented.
  • Not checked: the desktop app consuming the field, macOS, the full root suite, and the native backend's separate key reader (env list uses the default resolver).
  • I could not update Linear (the connector needs authorization), so status is recorded here.

I will not push to this branch again.

@roodboi

roodboi commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

Clarification for the lead: this PR was opened by the environment-track session that took over HACK-2191 (same session that posted the #797 ready note), as item 2 of its original brief. It is not a second, parallel R10 effort. Per the change of plan I am stopping R10 work here: no further pushes. The ready note above (c4d862985) stands as-is if you want to keep it; the one open decision is the no-envelope choice explained there.

@roodboi

roodboi commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

Addendum to the ready note at c4d862985443974346b62123db7a43d3cff40b77 (no push): the GitHub Codex review bot is out of usage. Per the lead, the second-family review of record for this PR is my Codex reviewer (gpt-6.1-sol on codex-dio), which returned CLEAN at c4d862985443974346b62123db7a43d3cff40b77.

@roodboi
roodboi merged commit d1c2962 into next Nov 15, 2026
23 checks passed
@roodboi
roodboi deleted the kit/hack-2218-env-list-key-state branch November 15, 2026 02:15
roodboi added a commit that referenced this pull request Nov 15, 2026
Conflicts:
- src/commands/env.ts: keep this branch's aliased migration import and
  next's ProjectEnvKeyState (#848).
- scripts/check-native-*-plan-cli.ts: keep this branch's HOME fingerprint
  and refusal-activity gates; the env plan script also keeps next's
  setup-unavailable detached refusal (#794). The shared refusal helper now
  forwards the private inputs to next's assertNativePlanHome check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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