Skip to content

fix(hosts): report owner newcode recovery for an expired identity - #98

Merged
wstein merged 4 commits into
mainfrom
fix/85-expired-identity-recovery
Oct 16, 2026
Merged

wstein merged 4 commits into
mainfrom
fix/85-expired-identity-recovery

Conversation

@wstein

@wstein wstein commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Implements #85: an expired identity with no issued pending certificate now ends the agent with a terminal error naming owner newcode recovery, instead of retrying forever.

  • 3556151: connection.ErrRecoveryRequired and identity.Expired (min of leaf and issuer). A stored pending certificate still goes through activation. workharbor-agent exits 66 with "host identity expired; owner newcode recovery required".

  • 2d520ee: the test(hosts): cover the renewal loop and the expiry watchdog #84 blocked-read test also asserts connected before the deadline.

  • d01f627: records the workharbor-agent exit codes in host-enrollment.md (0 stop, 1 other failure, 66 expired identity; do not restart on 66, systemd RestartPreventExitStatus=66), per owner decision H56:a. Separate from the whr table in ADR 0013.

  • 8046dce: covers an expired issuer with a valid leaf.

Follow-up: #99 (definitive activation refusal after expiry becomes terminal).

Review: CLEAR (Opus 5.5) on 8046dce. make check on this head is pending. Stacked on #93 (#84).

🤖 Generated with Claude Code

@wstein
wstein force-pushed the test/84-renewal-loop-tests branch from 07ac5c7 to 509efb3 Compare October 16, 2026 10:35
@wstein
wstein force-pushed the fix/85-expired-identity-recovery branch from 8046dce to 0045e7c Compare October 16, 2026 10:35
@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Review CLEAR on 8046dce (Opus 5.5). Restacked onto #93 509efb3; range-diff identical. make check on this head: pending.

@wstein
wstein force-pushed the test/84-renewal-loop-tests branch from 509efb3 to 33804a3 Compare October 16, 2026 10:42
@wstein
wstein force-pushed the fix/85-expired-identity-recovery branch from 0045e7c to acfe257 Compare October 16, 2026 10:42
@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto main 54a002f after #95 merged; git range-diff shows every patch identical (for #83 only one context line in docs/index.md differs), so the review carries to acfe257. make check on this head: pending.

@wstein
wstein marked this pull request as ready for review October 16, 2026 10:55
@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Ready per owner: review CLEAR on this head; local make check replaced by one final check on main after the stack merges (owner rule).

@wstein
wstein force-pushed the test/84-renewal-loop-tests branch from 33804a3 to 0ce831f Compare October 16, 2026 11:19
@wstein
wstein marked this pull request as draft October 16, 2026 11:20
@wstein
wstein force-pushed the fix/85-expired-identity-recovery branch from acfe257 to 2583949 Compare October 16, 2026 11:20
@wstein
wstein marked this pull request as ready for review October 16, 2026 11:21
@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Restacked onto #93 0ce831f; conflict in loopback_test.go resolved by keeping both sides. Review CLEAR on 2583949 (Opus 5.5). Follow-up for a refused activation after expiry: #99.

@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Restacked onto main e82167b after #96/#91 merged; range-diff identical, review carries to 8855da6.

Base automatically changed from test/84-renewal-loop-tests to main October 16, 2026 11:39
wstein and others added 4 commits October 16, 2026 14:01
An expired active certificate with no issued pending certificate cannot
stage a replacement, so retrying every 30 s never succeeds and only hides
the failure behind endless disconnected events. Run now returns
ErrRecoveryRequired with all state preserved, and the agent exits 66
(unauthenticated: expired credential, ADR 0013) naming owner newcode
recovery. A stored pending certificate still gets activation attempts,
because activation can succeed after the old certificate expired.

Refs: #85

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The blocked-read test only proved the socket closed at the deadline; a
session that never reached the connected state would pass too. Assert the
connected event was emitted first.

Refs: #85

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The agent's exit 66 for an expired identity needs a stable, citable home so
service managers do not restart into a loop. The table is the agent's own
and separate from the whr table in ADR 0013, so the code comment now cites
the host-enrollment contract instead.

Refs: #85

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The expiry check also covers the issuer, but the fixtures only expired the
leaf, so dropping the issuer check went unnoticed.

Refs: #85

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@wstein
wstein force-pushed the fix/85-expired-identity-recovery branch from 8855da6 to ea4d5e1 Compare October 16, 2026 12:01
@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Restacked onto main 7d1eb0c after #93 merged, which resolves the conflict. The range-diff is identical except for surrounding context in ci-acceptance.json (main now also has #86 IDs). The manifest is valid, with no lost or duplicate IDs and #85's 4 IDs added. check_repo.py, gofmt, vet and go test -race (connection, cmd) pass. Review carries to ea4d5e1.

@wstein
wstein merged commit bf29a36 into main Oct 16, 2026
3 checks passed
@wstein
wstein deleted the fix/85-expired-identity-recovery branch October 16, 2026 12:03
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