hq: keep key-store-codex-login active (exited) to stop switch start-limit failures (isolated fix) #279
No reviewers
Labels
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
key-store/key.store!279
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "infra/hq-codex-login-remain-clean"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Supersedes #277 with the reviewed one-option delta isolated.
WHY A NEW PR: root verified #277's branch (infra/hq-codex-login-remain @
6b829e8d) sits on the unmerged GoAlert stack (parentc5a35d2c= PR #270 head), so its diff vs main is 11 files including the entire GoAlert implementation. This branch is cut clean from origin/main @0b80bf41and contains ONLY the bootstrap fix (1 file, +12). Original branch/history kept as-is for the record; do NOT merge #277 (would implicitly merge unreviewed #270).CHANGE: RemainAfterExit = true on systemd.services.key-store-codex-login (nixos/keystore-hq.nix). Type=oneshot without it returns to inactive/dead after every success, so concurrent start sources during switch-to-configuration re-run the script until StartLimitBurst trips (activation exit 4, Result=start-limit-hit, ExecMainStatus=0 — observed 2026-09-13/14). Duplicate starts become no-ops; rotation semantics unchanged (units ordering, empty restartUnits, manual systemctl restart re-executes).
ROLLBACK: revert this one commit; unit returns to prior oneshot behavior (recurrence of #47 start-limit symptom possible on next switch, no other effect).
ON-HOST VERIFICATION (needs privileged host; impossible from sandbox):
Ref: Redmine #47.
Senior security review — exact head
ad0a7514(ad0a7514bb9ccd16d263066775b83ef827fe8ca0) — APPROVE.Reviewed against actual current main
0b80bf41(refetched; not stale origin/main): the diff is exactly one file,nixos/keystore-hq.nix, +12 lines — eleven comment lines plusRemainAfterExit = trueon the existingsystemd.services.key-store-codex-loginoneshot. Correctly isolated: PR #277 is superseded (inherited the unmerged GoAlert stack) and was not reviewed as the isolated fix.Verified: (1) Unit dependencies —
wantedBy multi-user.target,after/wants network-online.target; nothingRequires=the unit (line 356), so stayingactive (exited)cannot wedge dependent startups. (2) Duplicate-start behavior — withRemainAfterExit, post-success concurrent starts during switch are no-ops instead of re-runs, which removes the observedstart-limit-hitactivation failure (exit 4 with ExecMainStatus=0). Failed runs still enterfailed, so a genuinely broken script is still retried on next switch — no masking. (3) Auth/config-refresh and rotation semantics — script, User=root, file modes (0700 CODEX_HOME, 0600 config/auth) all unchanged; no new secret channels, values, or legacy SMS paths.openaiApiKeyentry keepsunits=[codexLogin](ordering only) with emptyrestartUnits, so rotation still needs the documented manualsystemctl restart, which re-executes the script — confirmed accurate. (4) No resident-session/memory impact: the oneshot holds no credentials in memory; same assistant session and signed memory survive by construction.Non-blocking operational note: under the old behavior an unrelated switch would re-run the script and
install_auth_seed_if_newercould pick up a rotated seed opportunistically; now a plain switch is a no-op, so post-rotationsystemctl restart key-store-codex-loginis the only refresh path. The in-code comment already says this — ensure the rotation runbook states it explicitly if it does not.Review only — root handles merge/deploy under existing founder approval; no reviewer merge, deploy, secret, or spending action.
Senior security review — exact head
ad0a7514(ad0a7514bb9ccd16d263066775b83ef827fe8ca0) — APPROVE.Reviewed against actual current main
0b80bf41(refetched; not stale origin/main): the diff is exactly one file,nixos/keystore-hq.nix, +12 lines — eleven comment lines plusRemainAfterExit = trueon the existingsystemd.services.key-store-codex-loginoneshot. Correctly isolated: PR #277 is superseded (inherited the unmerged GoAlert stack) and was not reviewed as the isolated fix.Verified: (1) Unit dependencies —
wantedBy multi-user.target,after/wants network-online.target; nothingRequires=the unit (line 356), so stayingactive (exited)cannot wedge dependent startups. (2) Duplicate-start behavior — withRemainAfterExit, post-success concurrent starts during switch are no-ops instead of re-runs, which removes the observedstart-limit-hitactivation failure (exit 4 with ExecMainStatus=0). Failed runs still enterfailed, so a genuinely broken script is still retried on next switch — no masking. (3) Auth/config-refresh and rotation semantics — script, User=root, file modes (0700 CODEX_HOME, 0600 config/auth) all unchanged; no new secret channels, values, or legacy SMS paths.openaiApiKeyentry keepsunits=[codexLogin](ordering only) with emptyrestartUnits, so rotation still needs the documented manualsystemctl restart, which re-executes the script — confirmed accurate. (4) No resident-session/memory impact: the oneshot holds no credentials in memory; same assistant session and signed memory survive by construction.Non-blocking operational note: under the old behavior an unrelated switch would re-run the script and
install_auth_seed_if_newercould pick up a rotated seed opportunistically; now a plain switch is a no-op, so post-rotationsystemctl restart key-store-codex-loginis the only refresh path. The in-code comment already says this — ensure the rotation runbook states it explicitly if it does not.Review only — root handles merge/deploy under existing founder approval; no reviewer merge, deploy, secret, or spending action.
Canonical HQ build and live acceptance passed for
ad0a7514. The isolated diff is only nixos/keystore-hq.nix. Good infra SSH signature verified; exact-head senior approval is review4749.A fresh HQ resident backup completed02:22:19Z before activation. The same assistant session9e3b242a and clean signed memory0cc1854 were preserved; the supervisor was released after the switch. RemainAfterExit now keeps key-store-codex-login active(exited), Result=success, ExecMainStatus=0, without reset-failed.
The first switch still exited4 because of a separate pre-existing D-Bus transition: live PID694 was /nix/store/c9cnbxhxbagj7gfpc1g5hl4x4f8dzayv-dbus-1.16.2/bin/dbus-daemon, startedMarch15, while the deployed unit points to dbus-broker37 with Type=notify-reload. ReloadResult was timeout. dbus-broker37 introduced that reload protocol (upstream release notes: https://github.com/bus1/dbus-broker/releases/tag/v37). Completing the already-configured daemon transition by restarting that unit started the expected broker37 binary; explicit systemctl reload then returned0. The old systemd-logind connection also needed a restart after the bus transition: its stale connection caused one activation exit11, then loginctl succeeded after restart. Re-running the exact target's switch-to-configuration then returned0. No reload error was masked or ignored, and no additional code or secret change was needed.
Final state: zero failed units; dispatcher API/supervisor, headscale and forge PG tunnel active; dbus reload successful; bootstrap active(exited). Detailed audit on HQ: /root/work/codex-hq-bootstrap-20260914/{before.json,backup.json,activation.json,dbus-transition.json}. Target: /nix/store/kacbfgjj3v1v4ybbgxwbxqz64bppcf6m-nixos-system-keystore-hq-26.05.20260914.ad0a7514. This completes #47's HQ activation acceptance. HQ's external PG/MCP dependency remains separate work.