instar 1.3.379 → 1.3.381
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/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +28 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +20 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +12 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +20 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/ghToken.d.ts +21 -0
- package/dist/core/ghToken.d.ts.map +1 -0
- package/dist/core/ghToken.js +56 -0
- package/dist/core/ghToken.js.map +1 -0
- package/dist/monitoring/SessionRecovery.d.ts +15 -0
- package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
- package/dist/monitoring/SessionRecovery.js +31 -1
- package/dist/monitoring/SessionRecovery.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +20 -20
- package/upgrades/1.3.380.md +46 -0
- package/upgrades/1.3.381.md +55 -0
- package/upgrades/context-wall-compact-escalation.eli16.md +42 -0
- package/upgrades/gh-token-vault-spawn-p3b.eli16.md +66 -0
- package/upgrades/side-effects/context-wall-compact-escalation.md +81 -0
- package/upgrades/side-effects/gh-token-vault-spawn-p3b.md +76 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Side-effects review — Vault-backed GH_TOKEN at spawn (Phase-3 increment P3b, option C)
|
|
2
|
+
|
|
3
|
+
## What this change does
|
|
4
|
+
Per-agent GitHub credential isolation for spawned sessions (CMT-1125 gap 1,
|
|
5
|
+
operator-selected design option C). At spawn time, `SessionManager` resolves
|
|
6
|
+
the agent's GitHub token from its encrypted per-agent SecretStore
|
|
7
|
+
(`github_token`, then `github.token`) and injects `GH_TOKEN=<token>` into the
|
|
8
|
+
tmux session environment. The `gh` CLI prefers `GH_TOKEN` over the
|
|
9
|
+
machine-global `~/.config/gh/hosts.yml` seat, so a session's GitHub actions
|
|
10
|
+
authenticate as THIS agent — the shared-machine cross-principal exposure
|
|
11
|
+
behind the 2026-06-05 identity-bleed incident.
|
|
12
|
+
|
|
13
|
+
Three pieces:
|
|
14
|
+
- `src/core/ghToken.ts` — `resolveGhTokenFromVault(stateDir)`: pure fs/crypto
|
|
15
|
+
vault read; trims; returns null on absent vault / absent key / non-string /
|
|
16
|
+
whitespace / any read error. Never throws. No subprocess (the P3a
|
|
17
|
+
GitSync mock-sequence lesson: spawn-path helpers must not consume scripted
|
|
18
|
+
child_process mock values).
|
|
19
|
+
- `SessionManager.ghTokenEnvFlags()` — private helper used by THREE spawn
|
|
20
|
+
sites (headless, rerouted-interactive, warm interactive). Returns
|
|
21
|
+
`['-e', 'GH_TOKEN=…']` or `[]`.
|
|
22
|
+
- `vaultStateDir` — same derivation as the pending-inject ledger
|
|
23
|
+
(StateManager.baseDir, else `<projectDir>/.instar`).
|
|
24
|
+
|
|
25
|
+
## Blast radius
|
|
26
|
+
- **Additive + dark-by-default-shaped.** No config flag, no migration, no new
|
|
27
|
+
route: with no vault token the resolver returns null and the spawn argv is
|
|
28
|
+
unchanged byte-for-byte (tested: env has no `GH_TOKEN=` entry at all).
|
|
29
|
+
- **Fail-soft end to end.** A corrupt vault logs one console.warn and the
|
|
30
|
+
spawn proceeds tokenless (tested with a deliberately garbaged vault file).
|
|
31
|
+
- **The hardened triage spawn is EXCLUDED on purpose.** That site scrubs
|
|
32
|
+
credentials (`ANTHROPIC_API_KEY=`, `DATABASE_URL=` …); handing it a GitHub
|
|
33
|
+
token would invert its security posture. Reviewed and deliberately skipped.
|
|
34
|
+
- **Token visibility (same posture as existing art).** The token rides the
|
|
35
|
+
tmux `new-session -e` argv — momentarily visible in the process list and
|
|
36
|
+
in tmux's session environment, exactly like the existing
|
|
37
|
+
`INSTAR_AUTH_TOKEN` and `ANTHROPIC_API_KEY`/`CLAUDE_CODE_OAUTH_TOKEN`
|
|
38
|
+
injections at the same sites. This increment deliberately matches that
|
|
39
|
+
established posture rather than inventing a second transport; tightening
|
|
40
|
+
all of them together is its own future increment if wanted.
|
|
41
|
+
- **Per-spawn vault read.** One decrypt per spawn (and on macOS possibly one
|
|
42
|
+
read-only keychain probe via the dual-key candidates). Spawns are seconds-
|
|
43
|
+
long, rare operations; no caching added (a fresh read also means a newly
|
|
44
|
+
dropped token is picked up by the very next spawn with no restart).
|
|
45
|
+
|
|
46
|
+
## Why vault-only (no hosts.yml fallback parsing)
|
|
47
|
+
Option C's value is the agent using ITS OWN seat. Parsing the machine-global
|
|
48
|
+
hosts.yml and injecting THAT token would re-create the exposure this exists
|
|
49
|
+
to close — so when the vault has no token we inject nothing and let `gh`
|
|
50
|
+
behave exactly as today. Phase-2 candidates (server-side `gh` calls in
|
|
51
|
+
routes.ts/CiFailurePoller, git-credential-helper for raw https pushes) are
|
|
52
|
+
catalogued in the increment ladder, not smuggled in here.
|
|
53
|
+
|
|
54
|
+
## Deflake that rode along (test-only)
|
|
55
|
+
Both reroute suites — `tests/unit/headless-spawn-reroute.test.ts` and
|
|
56
|
+
`tests/e2e/june15-headless-spawn-reroute.test.ts` — read the REAL host memory
|
|
57
|
+
pressure through the reroute gate: on a loaded dev machine they failed on a
|
|
58
|
+
PRISTINE tree (verified by stashing this change and re-running; unit 8 fails,
|
|
59
|
+
e2e 3 fails). Both now stub `currentMemoryPressure` to 'normal' — they assert
|
|
60
|
+
reroute logic, not host health. No production code touched by the deflake; no
|
|
61
|
+
test in either file asserts the pressure refusal.
|
|
62
|
+
|
|
63
|
+
## Test evidence
|
|
64
|
+
- `tests/unit/gh-token-vault.test.ts` (10): both key paths, precedence,
|
|
65
|
+
trimming, absent vault, wrong-key, non-string, whitespace, corrupt-vault
|
|
66
|
+
never-throws, production-path dual-key file-candidate read.
|
|
67
|
+
- `tests/unit/session-spawn-gh-token.test.ts` (5): REAL StateManager + REAL
|
|
68
|
+
vault + REAL resolver, argv-capturing tmux mock — token present in headless
|
|
69
|
+
env + INSTAR canaries intact; no vault → no flag; corrupt vault → spawn
|
|
70
|
+
succeeds, no flag; whitespace token → no flag; rerouted-interactive lane
|
|
71
|
+
carries the token too.
|
|
72
|
+
- Canaries green: headless-spawn-reroute (23), session-manager behavioral /
|
|
73
|
+
terminate / injection, SecretStore, GitSync, no-silent-fallbacks — 119/119.
|
|
74
|
+
- `tsc --noEmit` clean; `docs-coverage --check` floors hold (no new routes,
|
|
75
|
+
no new PascalCase core class file — `ghToken.ts` is a lowercase module by
|
|
76
|
+
design).
|