feat(serve): HTTPS on dig.local (127.0.0.2:443) + live leaf rotation (#624)#41
Merged
Conversation
…(#624) Serve the SAME local content router over TLS on 127.0.0.2:443 (https://dig.local), plus a best-effort [::1]:443 IPv6-loopback sibling (SS5.2), beside the kept plaintext :80 listener. TLS material comes from the dig-cert crate (pinned git-dep tag v0.1.0, release-first): the reloadable rustls ServerConfig is built via load_server_config. Leaf rotation is delegated to dig-cert's RenewalManager (the node is the runtime OWNER): a startup + daily maintain pass re-issues the leaf from ca.key at <30d remaining, atomically swaps the pair, and fires resolver.reload() so the running listener serves the new leaf with no downtime. The CA anchor is NEVER auto-rotated here (only ca_renewal_due is reported; rotate_ca is installer-coordinated). Fail-soft: when the installer (#623) has not provisioned a CA/leaf, or the leaf cannot be loaded, HTTPS is skipped and the node serves plaintext only -- HTTPS is never a hard requirement to start. SECURITY-CRITICAL: touches the ca.key rotation read path -> dual gate + loop-security required before merge. Windows rollout gates on #623's DACL (noted, non-blocking). Tests: config addressing units; tls fail-soft + load units; an end-to-end HTTPS integration test (client trusting the CA gets the content; a live rotation swaps the served leaf with the listener staying up). Bump 0.32.0 -> 0.33.0 (feat -> minor). Closes #624 Refs #620, #622 Co-Authored-By: Claude <noreply@anthropic.com>
MichaelTaylor3d
force-pushed
the
feat/624-https-serve
branch
from
July 16, 2026 09:10
fc3ebc0 to
8e5e962
Compare
MichaelTaylor3d
marked this pull request as ready for review
July 16, 2026 09:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #624 — local HTTPS for
dig.local(the #620 epic, consuming dig-cert #622 v0.1.0)Serve the SAME local content router over TLS on
127.0.0.2:443(https://dig.local), plus a best-effort[::1]:443IPv6-loopback sibling (§5.2), beside the kept plaintext:80listener. No plaintext consumer breaks — this is additive.How it pins dig-cert v0.1.0 (release-first, §4.1)
dig-node-servicegit-depsdig-cert = { git = ".../dig-cert", tag = "v0.1.0" }— the released tag, nevermain. The rustlsServerConfigis built withdig_cert::load_server_config(a hot-reloadableReloadableCertResolver).rustlsis pinned byte-identical (0.23,ring, no aws-lc) so exactly oneCryptoProviderinstalls.Rotation (live reload, no anchor auto-rotate)
The node is the runtime rotation OWNER but delegates the HOW to dig-cert's
RenewalManager. Amaintainpass at service start + once daily re-issues the leaf fromca.keyat <30d remaining, atomically swapsleaf.{key,crt}, and firesresolver.reload()so the running listener presents the new leaf without a restart or dropped connections. The CA trust anchor is NEVER auto-rotated — onlyca_renewal_dueis reported; anchor rotation is the installer-coordinateddig-cert rotate_ca.Cross-verify handling (from the #622 review note)
dig-cert's resolver does not cross-verify the leaf key vs cert on reload, but its
RenewalManageris safe (reload only after both atomic writes; a torn read keeps the previous cert). This PR uses dig-cert'sRenewalManagerdirectly rather than a bespoke file-watcher, so the mismatch window never opens.Fail-soft when no CA/leaf (installer #623 not yet run)
crate::tls::load_https_materialreturnsNone(⇒ plaintext only, informational log) whenleaf.{crt,key}are absent/unloadable. HTTPS is never a hard requirement to start — the:443bind is best-effort like:80.Version
0.32.0→0.33.0(feat → minor).Tests (
gh pr checksafter CI)config:dig_local_https_addr=127.0.0.2:443, v6 =[::1]:443, bothNonewhen disabled.tls: fail-softNonewhen no leaf;Some+ reloadable when a leaf is present.tests/https_serve.rs(e2e): a client trusting the per-machine CA gets the content over TLS; a live rotation swaps the served leaf while the listener stays up and keeps serving.cargo test -p dig-node-service(170 tests) green;cargo fmt --check+cargo clippy -D warningsclean.Blast radius (gitnexus/manual)
Additive: new
src/tls.rs, newserve_https/bring_up_local_httpsinserver.rs(called once fromserve_with_shutdown, best-effort spawned tasks — mirrors the existing mTLS listener pattern), two newConfigaccessors, one new const. No existing handler/route/bind semantics change; the plaintext path is untouched. SPEC §4.1a added.Touches the
ca.keyrotation read path → dual gate (loop-reviewer + adversarial loop-decider) + loop-security required before merge.Windows rollout note (non-blocking)
The Windows rollout gates on #623's DACL on the TLS root (installer provisions + locks down the CA). The build/tests here do not depend on it (fail-soft when no leaf).
SYSTEM.md / canonical coherence (for the orchestrator to commit — superproject-owned)
https://dig.local=127.0.0.2:443(+[::1]:443), leaf from dig-cert, rotation owner = dig-node, no anchor auto-rotate.dig.localHTTPS =127.0.0.2:443.🤖 Generated with Claude Code