Skip to content

Serve HTTPS directly via config-driven TLS listener (Part of #1603)#1852

Merged
madmax983 merged 7 commits into
trunk-devfrom
feat/1603-https-tls-listener
Jul 13, 2026
Merged

Serve HTTPS directly via config-driven TLS listener (Part of #1603)#1852
madmax983 merged 7 commits into
trunk-devfrom
feat/1603-https-tls-listener

Conversation

@madmax983

Copy link
Copy Markdown
Owner

Part of #1603. First honest slice of serving HTTPS directly from the app process.

Before / After

Before — there is no inbound TLS. To serve HTTPS you must front the app with a reverse proxy (nginx/Caddy/an LB) that terminates TLS. Absent that, the app speaks plain HTTP on host:port.

After — adding a [server.tls] section with a certificate + key makes the app terminate HTTPS itself, on the same host:port:

[server.tls]
cert_path = "/etc/autumn/tls/fullchain.pem"
key_path  = "/etc/autumn/tls/privkey.pem"
# optional; how often (seconds) to poll for a renewed cert on disk. Default: 60.
reload_interval_secs = 60
  • No [server.tls] → unchanged. Plain HTTP exactly as today; zero behavior change for existing apps.
  • Fails fast on misconfig. Missing file, unparseable PEM, a key that does not match the certificate, or an already-expired leaf certificate all abort startup with an actionable, path-named error — the app never boots into a broken listener.
  • Hot-reloads certificates. A background task polls the cert/key file mtimes and swaps the served certificate in place when they change (e.g. after a certbot/ACME renewal) — no restart. A failed reload logs an error and keeps serving the previously loaded certificate; a bad renewal never breaks the listener.
  • autumn doctor flags problems. Offline check: fail on a missing/invalid/expired certificate, warn within 30 days of expiry, pass otherwise.

The feature is off by default (tls cargo feature). A binary built without it that finds [server.tls] configured fails fast with a clear "built without the tls feature" message rather than silently serving plain HTTP.

How

  • autumn_web::tls (new module, behind tls): loads + validates the cert chain and key (rustls' CertifiedKey::from_der compares the key's SubjectPublicKeyInfo against the leaf, catching mismatches), rejects an expired leaf, exposes a reloadable ResolvesServerCert backed by an RwLock<Arc<CertifiedKey>> (a read-lock per handshake; a write-lock to swap), and an offline inspect_leaf for doctor.
  • Reuse axum::serve via a custom Listener. TlsListener wraps the existing tokio::net::TcpListener in a tokio_rustls::TlsAcceptor; its accept() performs the rustls handshake and returns (TlsStream<TcpStream>, SocketAddr). Because the peer is a real SocketAddr, the HTTPS serve arm is byte-for-byte the TCP arm — the same ConnectInfo<SocketAddr>, TrustedProxiesLayer/ClientAddr resolution, SSE/WebSocket streaming, request timeouts, and graceful-shutdown wiring all apply unchanged. A third BoundListener::Tls variant and a mirroring serve arm are the only serving-loop additions.
  • Crypto backend: reuses the already-vendored ring-backed rustls — the same backend the outbound Postgres TLS path uses. No second TLS backend is introduced (no aws-lc-rs / native-tls / openssl).
  • Config: [server.tls] is always compiled (so it parses regardless of features and the "no feature" error is possible), with AUTUMN_SERVER__TLS__CERT_PATH / __KEY_PATH / __RELOAD_INTERVAL_SECS env overrides. Nested [server.tls] keys are accepted by strict_config automatically (schema is serde-derived; the schema snapshot is updated).

New dependencies (please review)

Both are feature-gated (optional = true, pulled only by the new tls feature) and were already resolved in Cargo.lock at these versions (via other crates), so adding them introduces no version churn:

  • tokio-rustls 0.26 — async accept-time rustls handshake. default-features = false + ring (no aws-lc-rs).
  • x509-parser 0.16 — parse the leaf certificate's notAfter for expired-cert fail-fast and the doctor near-expiry warning. (No default features.)

The autumn-cli tls feature (default-on, so the shipped autumn binary can diagnose TLS) enables autumn-web/tls; it pulls in no additional CLI-level crates.

Tests

  • Unit (autumn/src/tls.rs): valid load; missing file names the path; unparseable PEM; key/cert mismatch → error; expired leaf → error; inspect_leaf reports future and past expiry; resolver swap.
  • Config (autumn/src/config.rs): [server.tls] TOML parse, reload-interval default/override, env-var materialization + partial override, default None.
  • Doctor (autumn-cli/src/doctor.rs): expired → Fail, ≤30 days → Warn, healthy → Pass, invalid → Fail, feature-disabled → Warn, not-configured → Pass.
  • End-to-end (autumn/tests/integration/tls_serving.rs, #[cfg(feature = "tls")]): a rustls client GETs /health over TLS and gets 200; peer SocketAddr connect-info flows through the TLS listener; graceful shutdown joins cleanly under TLS; a bad (plaintext) handshake does not kill the listener.

Gates run green: cargo fmt --all -- --check; cargo clippy --workspace --all-targets --features tls -- -D warnings and the plain no-feature clippy; targeted -p tests for all of the above; default-feature cargo check for both crates.

Scope / Limitations / Follow-ups

This slice deliberately does not do (tracked for follow-up):

  • Deployment guide docs (direct-vs-proxy topology, certbot/mkcert walkthroughs) — a docs session owns these.
  • Release-image HTTPS boot gate in CI — deferred.
  • wss (WebSocket-over-TLS) integration coverage — the listener yields the same ConnectInfo<SocketAddr> stream as plain TCP so a ws upgrade rides the identical service; a full tokio-tungstenite-over-rustls client is disproportionate here and is left as a clearly-marked TODO(#1603 follow-up).
  • Provision and renew HTTPS certificates automatically via ACME #1608 active-probe checks (port 80/443 reachability, DNS) are intentionally out of this doctor slice.
  • In-accept handshake head-of-line note: the rustls handshake runs inline with accept, so one slow handshake briefly delays new accepts. Acceptable for this slice; a future change can offload the handshake to a spawned task if it becomes a bottleneck.
  • Client-certificate / mTLS and ALPN/HTTP-version negotiation tuning are not in scope.

Generated by Claude Code

Add an off-by-default `tls` feature that terminates HTTPS in-process when
`[server.tls]` names a certificate + key, with no sidecar reverse proxy.

- New `autumn_web::tls` module: fail-fast cert/key loading + validation
  (missing file, unparseable PEM, key/cert mismatch, expired leaf), a
  reloadable `ResolvesServerCert`, and offline leaf-expiry inspection.
- A custom `axum::serve::Listener` (`TlsListener`) that performs the rustls
  handshake in `accept` and yields the peer `SocketAddr`, so all existing
  connect-info, trusted-proxy, and graceful-shutdown wiring is reused
  unchanged. A failed handshake is skipped, never killing the accept loop.
- Background hot-reload task swaps the certificate on file change (e.g. after
  an ACME/certbot renewal) without a restart; a bad reload keeps the old cert.
- Always-compiled `[server.tls]` config (cert_path, key_path,
  reload_interval_secs) with env overrides; fail-fast when configured on a
  binary built without the `tls` feature, or combined with a Unix socket.
- `autumn doctor` gains a TLS check: fail on missing/invalid/expired cert,
  warn within 30 days of expiry. Gated behind a default-on cli `tls` feature.

Reuses the already-vendored ring-backed rustls (no second TLS backend); adds
tokio-rustls and x509-parser behind the feature. Covered by unit, config,
doctor, and end-to-end HTTPS + graceful-shutdown integration tests.

Part of #1603.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Apply review fixes to the direct-HTTPS listener:

- Bound each inbound TLS handshake with a configurable timeout so a client
  that opens TCP but never sends a ClientHello can no longer park the accept
  loop and deny service to every other connection. Adds
  `[server.tls] handshake_timeout_secs` (default 10, clamped to >= 1) plus the
  `AUTUMN_SERVER__TLS__HANDSHAKE_TIMEOUT_SECS` env override, threaded into
  `TlsListener`; a stalled or silent handshake is now dropped and the loop
  continues.
- Move the per-tick cert/key `stat` and PEM read in the cert-reload task onto
  `spawn_blocking` so blocking filesystem I/O no longer runs on a tokio worker;
  a join failure just skips the tick.
- Delete the unused `NEAR_EXPIRY_WARN_DAYS` constant.

Add an integration test proving a hung (silent) handshake no longer wedges the
listener: a well-behaved HTTPS request succeeds while a raw, silent TCP
connection is held open.

Part of #1603
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 14a43fa310

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread autumn/src/tls.rs
/// Whole days from `now_unix` until `notAfter`. Negative once expired.
#[must_use]
pub const fn days_until_expiry(&self, now_unix: i64) -> i64 {
(self.not_after_unix - now_unix) / 86_400

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Classify newly expired certs as failures

When autumn doctor inspects a certificate that expired less than 24 hours ago, this division truncates toward zero, so days_until_expiry becomes 0; check_tls_impl then reports only a near-expiry warning instead of the promised failure. That lets a deploy with a freshly expired certificate pass the TLS check as a warning even though the runtime rejects expired certs at startup; base the failure on the raw timestamp or use floor division for negative durations.

Useful? React with 👍 / 👎.

Comment thread autumn-cli/src/doctor.rs Outdated
Comment on lines +3753 to +3756
// TLS is "configured" if the section is present OR any TLS env var is set.
let configured = tls.is_some()
|| std::env::var_os("AUTUMN_SERVER__TLS__CERT_PATH").is_some()
|| std::env::var_os("AUTUMN_SERVER__TLS__KEY_PATH").is_some();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include TLS tuning env vars in doctor detection

Runtime env loading materializes server.tls when AUTUMN_SERVER__TLS__RELOAD_INTERVAL_SECS or AUTUMN_SERVER__TLS__HANDSHAKE_TIMEOUT_SECS is set, leaving empty cert/key paths and causing startup (or a feature-disabled build) to fail fast. This doctor detection only treats the cert/key env vars as TLS configuration, so a deployment with only one of those TLS tuning vars set reports tls as Pass/NotConfigured instead of the same actionable failure the server will hit.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef4e040d0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread autumn/src/tls.rs Outdated
// ClientHello (or stalls mid-handshake) must not park the accept
// loop and deny every other client. On timeout or handshake error,
// drop the connection and keep accepting.
match tokio::time::timeout(self.handshake_timeout, self.acceptor.accept(stream)).await {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid serializing TLS handshakes in accept

When the direct-HTTPS listener is exposed to untrusted clients, awaiting the rustls handshake inside Listener::accept means axum cannot accept the next TCP connection until this client completes or handshake_timeout expires. With the default 10s timeout, a single silent/stalled TCP client can repeatedly occupy the accept loop and make all legitimate clients wait or time out; the handshakes need to be driven concurrently (or queued from background tasks) rather than performed inline before returning from accept.

Useful? React with 👍 / 👎.

Comment thread autumn-cli/src/doctor.rs Outdated
Comment on lines +3790 to +3795
let env_cert = std::env::var("AUTUMN_SERVER__TLS__CERT_PATH")
.ok()
.filter(|v| !v.trim().is_empty());
let env_key = std::env::var("AUTUMN_SERVER__TLS__KEY_PATH")
.ok()
.filter(|v| !v.trim().is_empty());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the dotenv-aware env layer for TLS doctor

When [server.tls] is supplied via the same .env / .env.<profile> layer that TomlEnvConfigLoader loads at runtime (for example in dev/test, or prod with dotenv enabled), this resolver only calls std::env::var, so autumn doctor reports TLS as not configured and skips certificate validation even though the app will boot the TLS listener. Resolve these variables through the runtime dotenv overlay, as other doctor checks do, so strict doctor cannot greenlight a dotenv-configured broken certificate.

Useful? React with 👍 / 👎.

…t loop; resolve TLS doctor vars via dotenv overlay

FIX 1 (P1): TlsListener no longer runs the rustls handshake inline in
accept(). A background acceptor task drains tcp.accept() and spawns each
handshake as a bounded task (Arc<Semaphore>, MAX_CONCURRENT_HANDSHAKES =
256), forwarding completed streams over a bounded mpsc channel to accept().
A flood of silent/stalled clients can no longer serialize the accept loop.
The acceptor loop is tied to the server_shutdown child token and breaks on
cancel; accept() parks (never busy-loops) once the channel closes so axum's
graceful-shutdown path drives teardown. Per-handshake timeout retained to
release a stalled handshake's permit. Adds a concurrency regression test.

FIX 2 (P2): resolve_tls_paths now reads the AUTUMN_SERVER__TLS__* vars
(including the prefix scan) through the profile-aware dotenv overlay
(os_env_with_dotenv_for_profile), the same layer sibling doctor checks use,
so TLS config supplied via .env/.env.<profile> is detected instead of
reported not-configured. Adds a dotenv-detection test.

Part of #1603

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f33376d6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread autumn/src/tls.rs Outdated
detail: e.to_string(),
}
})?;
Ok(parsed.validity().not_after.timestamp())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject not-yet-valid leaf certificates

When the configured leaf certificate has a notBefore timestamp in the future, this helper only returns notAfter, so load_certified_key accepts the pair and the app boots even though normal TLS clients will reject every handshake until the validity window starts. Since the runtime already fail-fast rejects expired leaves for the same client-visible breakage, include the not_before timestamp in the inspection and reject certificates where now_unix is before it.

Useful? React with 👍 / 👎.

Comment thread autumn-cli/src/doctor.rs Outdated
Comment on lines +3832 to +3836
.filter(|v| !v.trim().is_empty());
let env_key = denv
.var("AUTUMN_SERVER__TLS__KEY_PATH")
.ok()
.filter(|v| !v.trim().is_empty());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve empty TLS env overrides in doctor

If a deployment has valid [server.tls] paths in TOML but sets AUTUMN_SERVER__TLS__CERT_PATH= or ...KEY_PATH= to an empty value, the runtime still treats the env var as present and overwrites the path with an empty PathBuf, causing startup to fail. Doctor drops empty env values here and falls back to the TOML path, so autumn doctor --strict can pass exactly the configuration the server will reject; keep the empty override so it resolves to the same missing-path failure.

Useful? React with 👍 / 👎.

…pty TLS env overrides in doctor to match runtime fail-fast

- load_certified_key now fail-fast rejects a leaf whose notBefore is in
  the future (new TlsError::NotYetValid), symmetric to the expired check;
  LeafInspection carries not_before_unix + is_not_yet_valid, and doctor's
  check_tls_impl grades a not-yet-valid cert as Fail.
- doctor's resolve_tls_paths reads AUTUMN_SERVER__TLS__CERT_PATH/KEY_PATH
  with .ok() (no empty-filter), so a present-but-empty override clears the
  TOML path exactly as the runtime materializes it, surfacing the same
  missing-path failure instead of a false doctor Pass.

Part of #1603

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20ec48d37a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread autumn/src/tls.rs
path: cert_path.to_path_buf(),
source,
})?;
chain.push(cert);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse every certificate before accepting the chain

When cert_path contains a valid leaf followed by a malformed intermediate certificate, this loop only PEM-decodes and stores the extra block; the later checks parse and match only chain[0], so startup and autumn doctor can pass while rustls serves a chain that normal clients reject. Parse each certificate in the chain before constructing the CertifiedKey so a broken intermediate fails fast instead of booting a broken HTTPS listener.

Useful? React with 👍 / 👎.

Comment thread autumn-cli/src/doctor.rs Outdated
/// lets doctor treat those deployments as configured and surface the same
/// actionable failure instead of a false Pass.
fn any_tls_env_var_set() -> bool {
std::env::vars_os().any(|(name, _)| name.to_string_lossy().starts_with("AUTUMN_SERVER__TLS__"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit TLS env detection to recognized keys

When an unrelated or mistyped variable shares this prefix, such as AUTUMN_SERVER__TLS__ENABLED=false, doctor treats TLS as configured and fails on missing cert/key. The runtime only materializes [server.tls] from the four recognized variables in apply_server_env_overrides_with_env, so that same process would serve plain HTTP; this divergence can make autumn doctor --strict block a deployment the server itself accepts.

Useful? React with 👍 / 👎.

…idate the full certificate chain — Part of #1603

- doctor: detect TLS-via-env only on the four recognized
  AUTUMN_SERVER__TLS__* keys the runtime reads (CERT_PATH, KEY_PATH,
  RELOAD_INTERVAL_SECS, HANDSHAKE_TIMEOUT_SECS) via the dotenv overlay,
  dropping the broad prefix scan so an unrecognized/mistyped var like
  AUTUMN_SERVER__TLS__ENABLED no longer forces a false doctor Fail on a
  config the server serves as plain HTTP.
- tls: parse every non-leaf certificate in the chain before accepting it
  (new TlsError::ParseChainCert naming the 1-based position), so a
  malformed intermediate fails fast at startup and in doctor instead of
  booting a listener that serves a chain clients reject (rustls validates
  only the leaf).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8366ec3c5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread autumn/src/tls.rs Outdated

// Skip index 0 (the leaf); `leaf_validity_unix` already parses it.
for (idx, cert) in chain.iter().enumerate().skip(1) {
x509_parser::certificate::X509Certificate::from_der(cert.as_ref()).map_err(|e| {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate intermediate certificate lifetimes

When cert_path contains a valid leaf followed by an expired or not-yet-valid intermediate, this loop only parses the DER and then discards the parsed certificate, so startup and autumn doctor accept a chain that normal TLS clients reject during path validation. The leaf validity window is checked separately, but every served chain certificate should also have its validity window checked before returning Ok(()).

Useful? React with 👍 / 👎.

Comment thread autumn-cli/src/doctor.rs Outdated
/// is visible to doctor instead of being reported as not-configured.
fn resolve_tls_paths() -> Option<(std::path::PathBuf, std::path::PathBuf)> {
let (canonical, selected, _) = resolve_active_profiles();
let merged = get_merged_toml_table_runtime(&canonical, &selected);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve TLS TOML from the manifest directory

When an installed app is launched with AUTUMN_MANIFEST_DIR pointing at its config directory, the runtime prefers that directory for autumn.toml, but this newly added TLS resolver still reads the merged TOML from the doctor's current working directory via get_merged_toml_table_runtime. A [server.tls] section present only in the manifest-dir config is therefore treated as NotConfigured, letting strict doctor pass without checking the cert/key the server will actually use.

Useful? React with 👍 / 👎.

…; validate intermediate certificate lifetimes — Part of #1603

Copy link
Copy Markdown
Owner Author

Local verification (the gate)

Fresh, cold local verification of head commit f2fcfa7f0ece34b89ea1b0fe860f40bdb0a730fb. Per the project's "local verification is the gate" policy, this is the merge-readiness evidence.

Gate command Result
cargo fmt --all -- --check clean, exit 0
cargo clippy --workspace --all-targets --features tls -- -D warnings clean, exit 0
cargo clippy --workspace --all-targets -- -D warnings (no-feature) clean, exit 0
cargo test -p autumn-web --features tls --test integration_tests tls_serving test result: ok. 6 passed; 0 failed; 0 ignored
cargo test -p autumn-web --features tls --lib tls test result: ok. 36 passed; 0 failed; 0 ignored
cargo test -p autumn-cli --features tls doctor test result: ok. 306 passed; 0 failed; 0 ignored
cargo check -p autumn-web (no-feature) clean, exit 0
cargo check -p autumn-cli (no-feature) clean, exit 0

All gates PASS on a cold rebuild.

The direct-HTTPS TLS listener slice was hardened through multiple adversarial-review and Codex rounds — handshake concurrency/DoS resistance, full cert-chain parse plus lifetime validation, and recognized-key/dotenv/manifest-dir-aware doctor grading including expired and not-yet-valid detection — each landed with accompanying regression tests.

The GitHub Actions checks are currently sitting queued on the runner backlog (not failing). Per the project's "local verification is the gate" policy, this PR is merge-ready on the strength of the green local gates above; real CI results will still be acted on if/when they run.


Generated by Claude Code

@madmax983 madmax983 merged commit 5e42e44 into trunk-dev Jul 13, 2026
23 of 24 checks passed
@madmax983 madmax983 deleted the feat/1603-https-tls-listener branch July 13, 2026 14:28
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.

2 participants