Repository navigation
feat(bep): rotate the signing certificate over the control socket - #2545
norrietaylor merged 2 commits into
Conversation
`bep --rotate-signing` now sends {"op":"rotate_signing"} on the control
socket of the running `bep serve`. The proxy runs Ca::renew_signing on a
blocking thread and answers with the old and new signing fingerprints,
which the command prints on one line (BEP-061).
The SIGUSR1 request, the lock file and the fingerprint file beside the
socket are gone: the socket bind already refuses a second live proxy.
…unning-proxy-s-signing-certificate-thr # Conflicts: # crates/bep/src/control.rs
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
|
Approved: no findings at Nothing to do. Verdict APPROVE, posted as a comment: the App cannot review its own pull request; the check and the label carry it. Clobber: none seen. |
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The change conforms to Gatehouse section 6.10 line 839. The signing CA rotates under the same root, and the boxes see no change. The test validates a leaf from before the rotation and a leaf from after it against the root alone. The rotation uses the existing owner-only control socket, and that socket refuses another uid before it reads. No conditions.
Ruled at 8fc643f against gominimal/arch@109541a48c31 by claude-opus-5-5.
There was a problem hiding this comment.
Babysitter verification at 8fc643f. I read the full diff: bep --rotate-signing now sends {"op":"rotate_signing"} on the control socket and reads a RotationReply with both fingerprints, in place of SIGUSR1 plus the lock and fingerprint files beside the socket, which are removed with their tests. Control::with_rotation adds the CA; a socket bound without one refuses the request, and the control socket keeps refusing a peer of another user, so only the operator who runs bep serve can rotate. rotate() runs Ca::renew_signing on a blocking thread, the root is never touched, and rotate_signing_over_control_socket_keeps_leaves_valid validates a pre-rotation leaf and a post-rotation leaf against the root alone. Every refusal the command prints names the socket and the next step. Arch ruled PASS at this head. Both files are in T51's layers; zero open threads. Squash title feat(bep): rotate the signing certificate over the control socket passes commitlint. Residual #2510 (the end-to-end rotation under a running box) is T52.
Generated by Claude Code
There was a problem hiding this comment.
Babysitter approval at 8fc643f: every merge gate passes at this head (arch PASS, zero open threads, every lane aggregator green including ci-macos-success). Squash title feat(bep): rotate the signing certificate over the control socket and the squashed message pass commitlint. Queued for squash merge.
Generated by Claude Code
T51 — Rotate a running proxy's signing certificate through the control socket
slice: S9
kind: task
covers: BEP-061
size: M
est: 220 code, 140 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: the command prints one line naming the old and new signing fingerprints, and the proxy's info log line records the same rotation
observability: the info log line T36 added, for operator-driven and scheduled rotations alike
layers:
- control:
- crates/bep/src/control.rs: accepts a rotate-signing request from the host and runs
Ca::renew_signingon the serving proxy's CA under the same root and key identifier- crates/bep/src/main.rs:
bep rotate-signingsends the request over the control socket and prints the resulttest: cargo nextest run -p bep rotate_signing_over_control_socket_keeps_leaves_valid
produces: none
consumes: none
proof: An operator rotates the serving proxy's signing certificate now, and a leaf issued before and one issued after both validate against the root a box holds.
depends on:
- blocked by T36
Generated by Claude Code
Proof
An operator runs
bep --rotate-signingagainst a runningbep serve. The request goes over the control socket, and the proxy issues a new signing certificate under the unchanged root. The command printsSigning certificate rotated from <old fingerprint> to <new fingerprint>. Running boxes keep working; nothing inside them changes.The test rotate_signing_over_control_socket_keeps_leaves_valid shows that a leaf issued before the rotation and a leaf issued after it both validate against the root that a box holds.Notes from the agent: The task says
bep rotate-signing. The binary already has this command as the flagbep --rotate-signing, with--control <PATH>, so I kept the flag and changed only how it reaches the proxy. Before, it sent SIGUSR1 and polled a fingerprint file. Now it sends {"op":"rotate_signing"} on the control socket, and the reply carries old_fingerprint and new_fingerprint. I removed the SIGUSR1 handler, ServeState (the lock file and the fingerprint file beside the socket) and their tests. The control socket bind already refuses a socket that a live process holds, so the lock has no job now. The rotate op uses its own types, RotationRequest and RotationReply, and Request and Reply stay as they were. A new variant or field on those types breaks the exhaustive matches and the struct literals in crates/minimal/src/tests.rs, and that file is outside the layers. Control::bind keeps its signature. Control::with_rotation adds the CA, and a socket without one refuses the rotation. The rotation runs on a blocking thread. Ca::renew_signing still writes the T36 info line with both fingerprints, for a rotation on request and for a scheduled one. ROTATE_TIMEOUT went from 10 s to 60 s, because the keychain can wait for a prompt. Printed text: the success line keeps the earlier fixed sentenceRunning boxes keep working; nothing inside them changes., and that sentence has a semicolon, which the prose rule does not allow. I did not reword it. …[truncated]Tests
cargo nextest run -p bep rotate_signing_over_control_socket_keeps_leaves_validVerify
min task run agent-verifypassed ([tasks.verify]).Base
The base branch moved while the coder worked and was merged in before the tests ran. These files changed on BOTH sides since the branch point — read them first, because a rewrite from a stale reading can undo a merge without a conflict:
crates/bep/src/control.rsCloses #2532