boxdown 1.0.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -12
- package/assets/devcontainer/README.md +65 -21
- package/assets/devcontainer/devcontainer.json +27 -15
- package/assets/devcontainer/hooks/initialize.sh +76 -22
- package/assets/devcontainer/hooks/post-create.sh +70 -12
- package/assets/devcontainer/hooks/post-start.sh +20 -13
- package/assets/devcontainer/ssh-config-install.sh +12 -3
- package/assets/devcontainer/start.sh +721 -44
- package/assets/devcontainer/utils/coding-agent-cli-update.sh +267 -3
- package/assets/devcontainer/utils/deps-install.sh +68 -0
- package/assets/devcontainer/utils/git-config-bootstrap.sh +128 -0
- package/assets/devcontainer/utils/git-signing-bootstrap.sh +109 -0
- package/assets/devcontainer/utils/python-bootstrap.sh +69 -0
- package/assets/devcontainer/utils/secret-env-bootstrap.sh +22 -0
- package/assets/devcontainer/utils/ssh-agent-proxy-bootstrap.sh +27 -0
- package/assets/devcontainer/utils/ssh-agent-proxy.mjs +39 -0
- package/assets/devcontainer/utils/ssh-bootstrap.sh +9 -0
- package/dist/bin/cli.cjs +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/main-BDgyf2t5.cjs +5758 -0
- package/dist/main-J4_2Up3o.mjs +5718 -0
- package/dist/main-J4_2Up3o.mjs.map +1 -0
- package/dist/main.cjs +5 -2
- package/dist/main.d.cts +501 -4
- package/dist/main.d.cts.map +1 -1
- package/dist/main.d.mts +501 -4
- package/dist/main.d.mts.map +1 -1
- package/dist/main.mjs +2 -2
- package/docs/README.md +1 -0
- package/docs/architecture.md +32 -0
- package/docs/development.md +13 -6
- package/docs/features/README.md +2 -0
- package/docs/features/commit-signing.md +94 -0
- package/docs/features/generated-config-and-state.md +73 -5
- package/docs/features/github-auth-refresh.md +15 -2
- package/docs/features/lifecycle.md +103 -11
- package/docs/features/setup.md +66 -0
- package/docs/features/ssh-config-and-proxy.md +228 -7
- package/docs/features/start-and-shell.md +45 -5
- package/docs/superpowers/plans/2026-07-11-default-commit-signing.md +110 -0
- package/docs/superpowers/plans/2026-07-11-progress-ci-regression.md +125 -0
- package/docs/superpowers/plans/2026-07-17-node-ssh-agent-proxy-signing.md +132 -0
- package/docs/superpowers/plans/2026-07-17-runtime-secret-environment.md +174 -0
- package/docs/superpowers/specs/2026-07-11-default-commit-signing-design.md +416 -0
- package/docs/superpowers/specs/2026-07-11-progress-ci-regression-design.md +43 -0
- package/docs/superpowers/specs/2026-07-17-node-ssh-agent-proxy-design.md +63 -0
- package/docs/superpowers/specs/2026-07-17-runtime-secret-environment-design.md +194 -0
- package/docs/testing.md +35 -2
- package/docs/todo.md +2 -2
- package/package.json +1 -1
- package/src/claude-app-config.ts +304 -0
- package/src/cli-style.ts +43 -0
- package/src/codex-app-config.ts +656 -0
- package/src/config.ts +80 -10
- package/src/constants.ts +12 -0
- package/src/devcontainer.ts +511 -64
- package/src/doctor.ts +292 -30
- package/src/git-signing.ts +267 -0
- package/src/interactive-prompts.ts +692 -0
- package/src/list.ts +16 -2
- package/src/logging.ts +164 -0
- package/src/main.ts +1214 -63
- package/src/metadata.ts +52 -3
- package/src/package-info.ts +18 -0
- package/src/paths.ts +71 -11
- package/src/process.ts +80 -2
- package/src/progress.ts +593 -0
- package/src/purge.ts +216 -0
- package/src/shell.ts +25 -0
- package/src/ssh-config.ts +134 -16
- package/src/ssh-install-targets.ts +111 -0
- package/src/ssh-key.ts +53 -13
- package/src/status.ts +5 -0
- package/dist/main-BuEptwlL.cjs +0 -1707
- package/dist/main-ZFTrSVgt.mjs +0 -1685
- package/dist/main-ZFTrSVgt.mjs.map +0 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Node SSH-Agent Proxy Signing Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Enable best-effort SSH commit signing for the non-root Boxdown user while preserving explicit user Git-signing preferences.
|
|
6
|
+
|
|
7
|
+
**Architecture:** A root Node proxy forwards the raw mounted agent socket to a node-owned socket. The post-create hook starts and verifies that proxy before signing bootstrap. The bootstrap applies Boxdown's SSH default only when neither global nor local Git configuration expresses a signing preference.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** TypeScript, Node `net` Unix sockets, Bash lifecycle hooks, Node test runner.
|
|
10
|
+
|
|
11
|
+
## Global Constraints
|
|
12
|
+
|
|
13
|
+
- Do not read, copy, mount, or log private keys.
|
|
14
|
+
- Signing and proxy failures must never block lifecycle commands or commits.
|
|
15
|
+
- Preserve explicit user `commit.gpgsign`, `gpg.format`, `user.signingkey`, and `gpg.program` settings.
|
|
16
|
+
- Existing containers require `--recreate`.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
### Task 1: Add the node-accessible SSH-agent proxy
|
|
21
|
+
|
|
22
|
+
**Files:**
|
|
23
|
+
|
|
24
|
+
- Create: `assets/devcontainer/utils/ssh-agent-proxy.mjs`
|
|
25
|
+
- Modify: `assets/devcontainer/hooks/post-create.sh`
|
|
26
|
+
- Test: `__tests__/app.test.ts`
|
|
27
|
+
|
|
28
|
+
- [ ] **Step 1: Write a failing proxy forwarding test**
|
|
29
|
+
|
|
30
|
+
Create a temporary raw Unix server, launch the proxy with a temporary target
|
|
31
|
+
socket and the current test user's UID/GID, send bytes through the target, and
|
|
32
|
+
assert the raw server receives and echoes them.
|
|
33
|
+
|
|
34
|
+
- [ ] **Step 2: Run the focused test to verify it fails**
|
|
35
|
+
|
|
36
|
+
Run: `fnm exec --using v24.15.0 -- node --import tsx --test --test-name-pattern='forwards node SSH-agent connections' __tests__/app.test.ts`
|
|
37
|
+
|
|
38
|
+
Expected: FAIL because the proxy asset does not exist.
|
|
39
|
+
|
|
40
|
+
- [ ] **Step 3: Implement the proxy and lifecycle startup helper**
|
|
41
|
+
|
|
42
|
+
Implement a Node `net.createServer()` bridge that unlinks stale target sockets,
|
|
43
|
+
listens with mode `0600`, changes ownership to the supplied UID/GID, and pipes
|
|
44
|
+
each client to the raw socket. Start it with `sudo` in post-create, wait for
|
|
45
|
+
the target socket, and run `ssh-add -L` through it before signing bootstrap.
|
|
46
|
+
|
|
47
|
+
- [ ] **Step 4: Run the focused test to verify it passes**
|
|
48
|
+
|
|
49
|
+
Run the Task 1 command. Expected: PASS.
|
|
50
|
+
|
|
51
|
+
### Task 2: Route generated configuration and diagnostics through the proxy
|
|
52
|
+
|
|
53
|
+
**Files:**
|
|
54
|
+
|
|
55
|
+
- Modify: `src/config.ts`
|
|
56
|
+
- Modify: `assets/devcontainer/utils/git-signing-bootstrap.sh`
|
|
57
|
+
- Test: `__tests__/app.test.ts`
|
|
58
|
+
|
|
59
|
+
- [ ] **Step 1: Write failing generated-config and hook tests**
|
|
60
|
+
|
|
61
|
+
Assert enabled plans set `SSH_AUTH_SOCK` to `/run/boxdown/ssh-agent-node.sock`,
|
|
62
|
+
retain the raw source only in `BOXDOWN_GIT_SIGNING_SOURCE_SOCKET`, and disable
|
|
63
|
+
signing with `container-agent-proxy-unavailable` when proxy readiness fails.
|
|
64
|
+
|
|
65
|
+
- [ ] **Step 2: Run the focused tests to verify they fail**
|
|
66
|
+
|
|
67
|
+
Run: `fnm exec --using v24.15.0 -- node --import tsx --test --test-name-pattern='node SSH-agent proxy|proxy-unavailable' __tests__/app.test.ts`
|
|
68
|
+
|
|
69
|
+
Expected: FAIL because generated configuration still exposes the raw socket.
|
|
70
|
+
|
|
71
|
+
- [ ] **Step 3: Implement proxy socket configuration and failure reporting**
|
|
72
|
+
|
|
73
|
+
Add constants or literal paths for raw and node-facing sockets, update generated
|
|
74
|
+
container environment, and teach the bootstrap to report the proxy reason
|
|
75
|
+
without replacing user configuration.
|
|
76
|
+
|
|
77
|
+
- [ ] **Step 4: Run the focused tests to verify they pass**
|
|
78
|
+
|
|
79
|
+
Run the Task 2 command. Expected: PASS.
|
|
80
|
+
|
|
81
|
+
### Task 3: Preserve explicit user signing configuration
|
|
82
|
+
|
|
83
|
+
**Files:**
|
|
84
|
+
|
|
85
|
+
- Modify: `assets/devcontainer/utils/git-signing-bootstrap.sh`
|
|
86
|
+
- Modify: `docs/features/commit-signing.md`
|
|
87
|
+
- Modify: `docs/superpowers/specs/2026-07-11-default-commit-signing-design.md`
|
|
88
|
+
- Test: `__tests__/app.test.ts`
|
|
89
|
+
|
|
90
|
+
- [ ] **Step 1: Write failing bootstrap tests**
|
|
91
|
+
|
|
92
|
+
Add separate tests for repository-local `commit.gpgsign=false`, global
|
|
93
|
+
non-SSH `gpg.format`, and an explicit SSH signing key. Assert the first two
|
|
94
|
+
remain unchanged; assert the SSH case maps only its public-key path to the
|
|
95
|
+
mounted snapshot and signs successfully.
|
|
96
|
+
|
|
97
|
+
- [ ] **Step 2: Run the focused tests to verify they fail**
|
|
98
|
+
|
|
99
|
+
Run: `fnm exec --using v24.15.0 -- node --import tsx --test --test-name-pattern='preserves explicit.*signing' __tests__/app.test.ts`
|
|
100
|
+
|
|
101
|
+
Expected: FAIL because the bootstrap currently overwrites global SSH settings.
|
|
102
|
+
|
|
103
|
+
- [ ] **Step 3: Implement explicit-preference detection**
|
|
104
|
+
|
|
105
|
+
Check local configuration first, then copied global configuration. Preserve an
|
|
106
|
+
explicit opt-out or non-SSH configuration; use Boxdown defaults only with no
|
|
107
|
+
explicit preference. For explicit SSH configuration, replace only an
|
|
108
|
+
unavailable public-key path with the selected mounted key.
|
|
109
|
+
|
|
110
|
+
- [ ] **Step 4: Run the focused tests to verify they pass**
|
|
111
|
+
|
|
112
|
+
Run the Task 3 command. Expected: PASS.
|
|
113
|
+
|
|
114
|
+
### Task 4: Document and verify
|
|
115
|
+
|
|
116
|
+
**Files:**
|
|
117
|
+
|
|
118
|
+
- Modify: `docs/features/commit-signing.md`
|
|
119
|
+
- Modify: `docs/superpowers/specs/2026-07-11-default-commit-signing-design.md`
|
|
120
|
+
- Create: `.changeset/<generated-name>.md`
|
|
121
|
+
|
|
122
|
+
- [ ] **Step 1: Document the proxy, user-precedence policy, and `--recreate` requirement**
|
|
123
|
+
|
|
124
|
+
- [ ] **Step 2: Add a patch changeset**
|
|
125
|
+
|
|
126
|
+
- [ ] **Step 3: Run complete verification**
|
|
127
|
+
|
|
128
|
+
Run: `pnpm test`, `pnpm lint`, `pnpm build`, `bash -n assets/devcontainer/utils/git-signing-bootstrap.sh`, `node --check assets/devcontainer/utils/ssh-agent-proxy.mjs`, and `git diff --check`.
|
|
129
|
+
|
|
130
|
+
- [ ] **Step 4: Commit**
|
|
131
|
+
|
|
132
|
+
Use: `git commit -m "fix: proxy SSH agent for commit signing"`
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Runtime Secret Environment Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Keep Boxdown-provided secrets available in Bash sessions without writing their values to the repository, persistent Boxdown state, Docker environment configuration, or workspace logs.
|
|
6
|
+
|
|
7
|
+
**Architecture:** A private per-workspace runtime directory holds three secret files and is mounted read-only at `/run/boxdown/secrets`. A Bash bootstrap exports values for interactive, non-interactive, SSH, and Boxdown coding-agent Bash sessions. Docker configuration carries only paths; metadata inspection requests only image fields; logging structurally redacts known assignments.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Node.js 24, TypeScript, Bash, `node:test`, Docker/Dev Containers configuration.
|
|
10
|
+
|
|
11
|
+
## Global Constraints
|
|
12
|
+
|
|
13
|
+
- Do not print, log, serialize, or place a secret value in generated configuration, command arguments, metadata, or diagnostics.
|
|
14
|
+
- Fixed Boxdown secret names: `ANTHROPIC_API_KEY`, `SNYK_TOKEN`, and `OP_SERVICE_ACCOUNT_TOKEN`.
|
|
15
|
+
- Missing values and unavailable 1Password access are non-blocking; the affected variable is absent.
|
|
16
|
+
- `.env.development` is project-owned: Boxdown does not create, edit, delete, or migrate it.
|
|
17
|
+
- Runtime secret directories/files use `0700`/`0600` and are outside `workspaceDataDir`.
|
|
18
|
+
- Existing containers require `boxdown start --recreate`; do not add legacy cleanup or `doctor --fix-secrets`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## File Structure
|
|
23
|
+
|
|
24
|
+
| File | Responsibility |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `src/constants.ts`, `src/paths.ts` | Runtime secret paths and fixed secret-name constants. |
|
|
27
|
+
| `src/config.ts`, `assets/devcontainer/devcontainer.json` | Read-only mount and non-secret Bash bootstrap config. |
|
|
28
|
+
| `assets/devcontainer/hooks/initialize.sh` | Atomically create/remove runtime secret files. |
|
|
29
|
+
| `assets/devcontainer/utils/secret-env-bootstrap.sh` | Read fixed files and export present values without output. |
|
|
30
|
+
| `assets/devcontainer/hooks/post-create.sh`, `src/shell.ts` | Source bootstrap for interactive and Boxdown-launched Bash sessions. |
|
|
31
|
+
| `src/main.ts`, `src/purge.ts` | Remove workspace runtime state after down/purge. |
|
|
32
|
+
| `src/devcontainer.ts`, `src/logging.ts` | Narrow Docker inspection and structural redaction. |
|
|
33
|
+
| `src/doctor.ts`, docs, `__tests__/app.test.ts` | Safety checks, documentation, and regression tests. |
|
|
34
|
+
|
|
35
|
+
### Task 1: Define runtime secret state and remove workspace injection
|
|
36
|
+
|
|
37
|
+
**Files:**
|
|
38
|
+
|
|
39
|
+
- Modify: `src/constants.ts`, `src/paths.ts`, `src/config.ts`, `assets/devcontainer/devcontainer.json`, `assets/devcontainer/hooks/initialize.sh`, `assets/devcontainer/hooks/post-start.sh`, `__tests__/app.test.ts`
|
|
40
|
+
|
|
41
|
+
**Interfaces:**
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
export const BOXDOWN_SECRET_ENV_NAMES = ['ANTHROPIC_API_KEY', 'SNYK_TOKEN', 'OP_SERVICE_ACCOUNT_TOKEN'] as const
|
|
45
|
+
export const BOXDOWN_CONTAINER_SECRET_ENV_DIR = '/run/boxdown/secrets'
|
|
46
|
+
export const BOXDOWN_CONTAINER_SECRET_ENV_BOOTSTRAP = '/opt/boxdown/devcontainer/utils/secret-env-bootstrap.sh'
|
|
47
|
+
export function defaultRuntimeRoot (env?: NodeJS.ProcessEnv): string
|
|
48
|
+
// WorkspaceContext adds runtimeRoot, workspaceRuntimeDir, workspaceSecretEnvDir.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- [ ] **Step 1: Write failing tests**
|
|
52
|
+
|
|
53
|
+
Create a context with `BOXDOWN_RUNTIME_HOME`. Assert that its secret directory starts below runtime root but not persistent workspace data. Assert generated config mounts that directory read-only at `/run/boxdown/secrets`, sets the non-secret bootstrap `BASH_ENV`, retains `NODE_ENV`, and serializes none of `--env-file`, `.env.development`, or the three secret names.
|
|
54
|
+
|
|
55
|
+
- [ ] **Step 2: Verify red**
|
|
56
|
+
|
|
57
|
+
Run `pnpm test -- --test-name-pattern "runtime secret|generated config"`. Expected: FAIL because the current config injects workspace-file and Docker-environment secrets.
|
|
58
|
+
|
|
59
|
+
- [ ] **Step 3: Implement paths and config**
|
|
60
|
+
|
|
61
|
+
Add the fixed constants. Resolve runtime root in this order: `BOXDOWN_RUNTIME_HOME`; then `join(XDG_RUNTIME_DIR, PACKAGE_NAME)`; then `join(tmpdir(), package-name plus UID)`. Add workspace-ID scoped runtime/secret paths. Append the read-only secret mount and `BASH_ENV`; remove the base `--env-file` pair and secret `containerEnv` values while preserving non-secret entries.
|
|
62
|
+
|
|
63
|
+
- [ ] **Step 4: Implement host runtime-file refresh**
|
|
64
|
+
|
|
65
|
+
Pass only `BOXDOWN_SECRET_ENV_DIR` to `initializeCommand`. Set `umask 077`; create the directory at `0700`; write each nonempty file through `mktemp` plus `chmod 0600` plus atomic rename; remove a file when its host value is absent. Read the existing 1Password reference into a local variable and never echo it. Remove all `.env.development` preparation/upsert logic and post-start deletion.
|
|
66
|
+
|
|
67
|
+
- [ ] **Step 5: Verify green and commit**
|
|
68
|
+
|
|
69
|
+
Run `pnpm test -- --test-name-pattern "runtime secret|generated config|devcontainer git config hooks"` and `bash -n assets/devcontainer/hooks/initialize.sh assets/devcontainer/hooks/post-start.sh`; expect both to pass. Commit the listed sources and tests as `feat: mount runtime secret environment`.
|
|
70
|
+
|
|
71
|
+
### Task 2: Export secret files in supported Bash sessions and clean runtime state
|
|
72
|
+
|
|
73
|
+
**Files:**
|
|
74
|
+
|
|
75
|
+
- Create: `assets/devcontainer/utils/secret-env-bootstrap.sh`
|
|
76
|
+
- Modify: `assets/devcontainer/hooks/post-create.sh`, `src/shell.ts`, `src/main.ts`, `src/purge.ts`, `__tests__/app.test.ts`
|
|
77
|
+
|
|
78
|
+
**Interfaces:**
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Bootstrap reads /run/boxdown/secrets/<fixed-name> and exports only present values.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- [ ] **Step 1: Write failing tests**
|
|
85
|
+
|
|
86
|
+
Run the bootstrap against a temporary secret directory with sentinel values. Assert each present value is exported, an absent file remains unset, and stdout/stderr do not contain a sentinel. Assert interactive shell/agent scripts source the bootstrap before `exec`. Assert down/purge remove only workspace runtime state.
|
|
87
|
+
|
|
88
|
+
- [ ] **Step 2: Verify red**
|
|
89
|
+
|
|
90
|
+
Run `pnpm test -- --test-name-pattern "secret bootstrap|runtime secret cleanup|interactive shell setup"`. Expected: FAIL because no bootstrap or runtime cleanup exists.
|
|
91
|
+
|
|
92
|
+
- [ ] **Step 3: Implement bootstrap/session loading**
|
|
93
|
+
|
|
94
|
+
Create a no-output script that reads the three fixed files with `IFS= read -r`, exports only nonempty values, and never sources secret file contents as code. Add an idempotent source line to the node user's `.bashrc` in post-create. Add the same bootstrap source before final `exec` in both shell script builders; never add a value to `interactiveShellEnvArgs`.
|
|
95
|
+
|
|
96
|
+
- [ ] **Step 4: Implement safe runtime cleanup**
|
|
97
|
+
|
|
98
|
+
Add a path-contained helper that removes only `context.workspaceRuntimeDir`, accepts absence, and never removes `runtimeRoot`. Invoke it after successful down and during purge before persistent state removal.
|
|
99
|
+
|
|
100
|
+
- [ ] **Step 5: Verify green and commit**
|
|
101
|
+
|
|
102
|
+
Run `pnpm test -- --test-name-pattern "secret bootstrap|runtime secret cleanup|interactive shell setup"` and `bash -n assets/devcontainer/utils/secret-env-bootstrap.sh assets/devcontainer/hooks/post-create.sh`; expect pass. Commit as `feat: export runtime secrets in Bash sessions`.
|
|
103
|
+
|
|
104
|
+
### Task 3: Replace full Docker inspection and harden logging
|
|
105
|
+
|
|
106
|
+
**Files:**
|
|
107
|
+
|
|
108
|
+
- Modify: `src/devcontainer.ts`, `src/logging.ts`, `__tests__/app.test.ts`
|
|
109
|
+
|
|
110
|
+
**Interfaces:**
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
export function parseDockerInspectImage (output: string, containerId: string): DockerImageInfo | undefined
|
|
114
|
+
export function redactKnownSecretEnvironmentAssignments (value: string): string
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- [ ] **Step 1: Write failing tests**
|
|
118
|
+
|
|
119
|
+
Test parsing two JSON-string lines representing image ID/name. Add a fake Docker complete-inspect fixture containing an OP sentinel, assert the lifecycle log omits it and inspect uses a narrow format. Test plain and Docker-JSON assignment forms for each known secret variable.
|
|
120
|
+
|
|
121
|
+
- [ ] **Step 2: Verify red**
|
|
122
|
+
|
|
123
|
+
Run `pnpm test -- --test-name-pattern "docker inspect|known secret|workspace logger"`. Expected: FAIL because inspect uses `{{json .}}` and logging is value-only.
|
|
124
|
+
|
|
125
|
+
- [ ] **Step 3: Implement projection/redaction**
|
|
126
|
+
|
|
127
|
+
Use Docker format `{{json .Image}}` followed by `{{json .Config.Image}}`; parse exactly two scalar JSON lines and provide a container-ID-specific malformed-output error. Redact values after each fixed name before dynamic redactions and apply it through logger `#redact` for arguments, sections, errors, and child output while preserving the names.
|
|
128
|
+
|
|
129
|
+
- [ ] **Step 4: Verify green and commit**
|
|
130
|
+
|
|
131
|
+
Run `pnpm test -- --test-name-pattern "docker inspect|known secret|workspace logger"`; expect pass. Commit as `fix: keep container secrets out of workspace logs`.
|
|
132
|
+
|
|
133
|
+
### Task 4: Doctor coverage and documentation
|
|
134
|
+
|
|
135
|
+
**Files:**
|
|
136
|
+
|
|
137
|
+
- Modify: `src/doctor.ts`, `__tests__/app.test.ts`, `assets/devcontainer/README.md`, `docs/features/generated-config-and-state.md`, `docs/features/start-and-shell.md`
|
|
138
|
+
|
|
139
|
+
- [ ] **Step 1: Write failing tests**
|
|
140
|
+
|
|
141
|
+
Extend doctor fake-command tests to require a disposable runtime-secret mount probe and a warning when generated config contains env-file, `.env.development`, or a fixed secret name in `containerEnv`. Add existing-style static documentation assertions for session exposure and `--recreate`.
|
|
142
|
+
|
|
143
|
+
- [ ] **Step 2: Verify red**
|
|
144
|
+
|
|
145
|
+
Run `pnpm test -- --test-name-pattern "doctor|generated config|runtime secret"`. Expected: FAIL because doctor does not inspect those conditions.
|
|
146
|
+
|
|
147
|
+
- [ ] **Step 3: Implement non-blocking checks/docs**
|
|
148
|
+
|
|
149
|
+
Add `workspaceSecretEnvDir` to disposable mount probes. Add a `secret-environment-config` doctor result: missing generated config is warning, unsafe config is warning, safe config is ok; never read secret file contents. Update docs: values are ordinary Bash-session variables but not Docker config; `.env.development` is ignored; missing values are non-blocking; existing containers need recreate; legacy leaked values/logs require manual removal and rotation.
|
|
150
|
+
|
|
151
|
+
- [ ] **Step 4: Verify green and commit**
|
|
152
|
+
|
|
153
|
+
Run `pnpm test -- --test-name-pattern "doctor|generated config|runtime secret"`; expect pass. Commit as `docs: describe runtime secret environment handling`.
|
|
154
|
+
|
|
155
|
+
### Task 5: Full verification
|
|
156
|
+
|
|
157
|
+
- [ ] **Step 1: Run the complete suite**
|
|
158
|
+
|
|
159
|
+
Run `pnpm test`, `pnpm lint`, `pnpm build`, `bash -n` for all changed hooks/utilities, `git diff --check`, and `git diff main...HEAD --check`. Expected: every command exits 0.
|
|
160
|
+
|
|
161
|
+
- [ ] **Step 2: Review secret-safety diff**
|
|
162
|
+
|
|
163
|
+
Run `git diff main...HEAD -- assets/devcontainer/devcontainer.json src/config.ts src/devcontainer.ts src/logging.ts`. Confirm no implementation path writes `.env.development`, uses `--env-file`, or contains literal token-like values.
|
|
164
|
+
|
|
165
|
+
- [ ] **Step 3: Commit a verification-only correction when required**
|
|
166
|
+
|
|
167
|
+
If verification requires a source correction, commit only that correction as `test: cover runtime secret environment regression`.
|
|
168
|
+
|
|
169
|
+
## Plan Self-Review
|
|
170
|
+
|
|
171
|
+
- Tasks 1–2 implement runtime-only state and compatible Bash-session exports.
|
|
172
|
+
- Task 3 removes the full-inspect log leak and adds a logging backstop.
|
|
173
|
+
- Task 4 adds doctor/documentation coverage without legacy cleanup.
|
|
174
|
+
- Task 5 runs full test, lint, build, Bash syntax, and diff checks.
|