Fluxheim 1.7.12 Release Notes
Fluxheim 1.7.12 adds standards-based response metadata generated from native
runtime outcomes and final response bytes. It also adds reproducible,
CI-only proof environments for both FIPS-capable TLS backend profiles.
All new response metadata remains opt-in. Existing configurations and response
headers are unchanged unless an operator enables the new metadata policy.
Snapshot Lifecycle Proof and Hardening
- Add a dedicated real-binary smoke that captures a running baseline through
the authenticated admin API, publishes and live-applies a candidate config,
verifies changed serving behavior, performs a live rollback, runs snapshot
integrity doctor, and proves the rolled-back current pointer survives restart. - Serialize snapshot candidates behind one clone-shared admission lock, bounding
concurrent near-limit serialization buffers without creating store state for
rejected oversized candidates. - Create snapshot directories as
0700at the operating-system creation call,
closing the permissive-umask interval before any follow-up mode enforcement. - Build a complete replacement host router before atomically swapping it into
the native listener. Snapshot-safe reload and rollback now affect real data
plane requests while each in-flight HTTP/1 or HTTP/2 request retains one
router generation across all handler phases. - Reject live router replacement while background load-balancer health or
discovery services are active, avoiding a router/service state split; use a
zero-downtime process upgrade for those deployments.
Standards-Based Response Metadata
- Add RFC 9211
Cache-Statusderived from actual cache results, including hit,
URI miss/store, stale forwarding, revalidation, expiry, and bypass outcomes. - Add RFC 9209
Proxy-Statusfor Fluxheim-generated proxy failures using only
standardized low-cardinality error tokens. - Require a bounded Structured Fields token as the public Fluxheim deployment
identifier when either status field is enabled. - Do not expose cache keys, internal storage tiers, policy reasons, backend
addresses, DNS names, certificate details, or raw error strings. - Preserve existing origin status members and append Fluxheim's member, making
multi-proxy status chains visible only when the operator explicitly opts in.
Example:
[headers.response.metadata]
identifier = "edge-gateway"
cache_status = true
proxy_status = true
content_digest = true
repr_digest = trueThe metadata policy inherits through global, vhost, and route response-header
configuration. Every field defaults to disabled.
Response Digests
- Add RFC 9530 SHA-256
Content-Digestover final HTTP message content. - Add
Repr-Digestonly when Fluxheim holds a complete selected
representation: a completeGETresponse with status200, no range, and a
body consistent with its declared content length. - Compute digest fields after Fluxheim compression so they describe the bytes
actually delivered to the client. - Suppress
Repr-DigestforHEAD,206,304, and other incomplete
representation paths instead of guessing an unseen full representation. - Cover bodyless
HEADand304content as empty message content and cover a
206response's returned range withContent-Digest. - Remove origin digest fields when Fluxheim compression changes the body and
digest generation is disabled, preventing stale integrity metadata. - Apply digest metadata once after Wasm response-header hooks, and share one
SHA-256 computation when both digest fields describe the same bytes. - Compute immutable cache-body digests once when objects are stored and reuse
them for memory and disk hits. New disk metadata is versioned and existing
v1 and v2 cache objects remain readable. - Invalidate a precomputed cache digest whenever compression replaces the body,
then hash the final encoded bytes before emission.
The native response model remains bounded and buffered. Digest generation
hashes the final response buffer without another body copy; unbuffered digest
trailers are not part of this release.
Wasm Loader Hardening
- Require SHA-256 pins at the final public manifest and loader boundary for
access-decision, route-decision, and cache-store phases, matching the
existing configuration invariant. - Remove detached Wasmtime compilation workers. Compilation is synchronous,
limited to two process-wide startup/reload slots, and releases its permit
before an over-deadline result is returned. - Add
max_compiled_artifact_bytes, defaulting to 32 MiB and capped at 256
MiB, and reject compiled modules above that ceiling before registry
admission. - Document
compile_timeout_msaccurately as an in-process result deadline,
not native compiler preemption; hard cancellation requires future
process-isolated compilation and execution. - Open plugin files with no-follow/reparse-point semantics during validation,
retain that exact regular-file handle, and read module bytes from it without
reopening the pathname. This closes final-file replacement races on Windows,
ReFS, Unix, and macOS without identity inference or unsafe code.
Downstream TLS Hardening
- Add optional
tls.client_auth.crl_pathsupport to rustls and OpenSSL with an
8 MiB input bound, a 1-to-64 PEM CRL bundle limit, strict full-chain
revocation, and expired-CRL rejection. Root/intermediate/client regression
handshakes prove hierarchical mTLS succeeds only when every required issuer
CRL is present. - Require a CRL bundle when required client authentication is combined with a
FIPS/ISO-required compliance mode; ordinary client auth retains explicit
opt-in revocation behavior. - Stage OpenSSL CRLs from the exact bounded bytes already admitted by Fluxheim,
preventing an OpenSSL pathname reopen from bypassing input admission. - Index one-label wildcard SNI certificates by normalized suffix, replacing an
attacker-triggerable linear scan with expected constant-time lookup. - Build complete, policy-equivalent OpenSSL contexts for every SNI certificate
and atomically switch contexts during ClientHello processing. Certificate/key
mismatches now reject reload before the active context store is replaced. - Parse OpenSSL client-auth policy once per SNI store generation, share admitted
CA objects across contexts, reject projected active-plus-reload policy input
above 128 MiB, and divide a 4096-entry session cache budget across contexts. - Serialize OpenSSL SNI reload construction and attach generation leases to
selected SSL connections. A reload that would create a third live generation
now marks the oldest generation for drain; native OpenSSL HTTP/1, HTTP/2, and
takeover streams use per-connection wake registrations so every retained
connection closes before a bounded automatic retry. Reloads still fail closed
if the generation cannot drain within 10 seconds. The connection lease uses
one process-global OpenSSL ex-data index, preventing index growth when
certificate stores are reconstructed in-process. Every attachment is read
back immediately, and Fluxheim terminates if OpenSSL cannot preserve the
lease.
Shared Cache Policy Hardening
- Always bypass shared-cache lookup and storage for requests carrying
AuthorizationorProxy-Authorization. - Parse response
Cache-Controlas a strict quoted-string-aware policy,
prioritizes-maxageovermax-age, and reject malformed or conflicting
security/freshness directives instead of falling back to configured TTLs. - Parse response
Cache-Controlwithout a directive vector and reject more
than 16 KiB or 128 directives cumulatively. - Remove unused compatibility helpers that could collapse malformed freshness
into an absent policy or split quoted extension values at commas. - Preserve the first received
Agelist member when calculating peer-fill
remaining freshness. - Persist mandatory-revalidation state with native disk-cache metadata and
prohibit stale reuse formust-revalidate,proxy-revalidate, and
s-maxage; v1 and v2 metadata remain readable and derive the restriction
from stored response headers. - Require one consistent satisfied
Content-RangeandContent-Lengthbefore
range admission, reject impossible totals and duplicate metadata, and make
zero-sized public slice planning return no slices instead of dividing by
zero. - Reject percent-decoded forward-path segments that are not canonical UTF-8 or
contain encoded Unicode control characters, preventing disagreement with
permissive upstream decoders. - Detect symlinks in every existing configured web-path prefix even when a
later child is absent, and deny non-UTF-8 dotfile components by their OS path
representation. - Bound storage-bin manifests to 4 KiB and use no-follow, nonblocking regular
file reads so oversized or special persistent files fail closed at startup.
Native Buffer and Cache-Encryption Hardening
- Add
server.limits.max_buffered_request_body_bytes, defaulting to1GiB, as
one weighted process-wide admission budget shared by HTTP/1 and HTTP/2.
Fluxheim reserves validatedContent-Lengthvalues in 64 KiB units and grows
unknown-length HTTP/1 chunked and HTTP/2 reservations before each buffer
extension. Public native-server handlers without an explicit policy share a
mandatory 1 GiB process budget, and pinned HTTP/1 handlers provide the
effective request budget. Exhaustion returns a bounded503with retry
guidance. - Move content-length bodies out of the reusable HTTP/1 parser buffer without
constructing a second full-body copy, release oversized connection-buffer
capacity before keep-alive, and clear full body and chunk-decoder
allocations throughsanitization.
Request types are no longer cloneable; compression, static, cache, and
revalidation workers receive metadata-only snapshots, while body-bearing
requests are never automatically retried or failed over. - Transfer HTTP/1 request-body ownership directly into HTTP/2 DATA frames
through an owner-backedBytesvalue instead of making two additional body
copies. The process-budget reservation travels with the sanitizing body owner
and every queued H2 slice, so handler completion cannot admit replacement
memory before the transport releases the original allocation. H2C
negotiation retains the body until fallback is decided, secure HTTP/1 and
HTTP/2 growth admits old-plus-new allocation overlap, unknown-length HTTP/2
bodies use budgeted geometric growth instead of repeated exact-size copies,
and fragmented final chunks preserve pipelined request bytes before clearing
the read buffer. - Move static-file resolution and reads to the bounded blocking-work pool and
cap retained static response bodies with a weighted 256 MiB process-wide
budget. Fluxheim resolves metadata first, admits the planned response bytes
before reading or cloning a body, and conservatively accounts for a second
local-static cache copy. The permit follows an HTTP/1 response through HTTP/2
adaptation and remains held until the downstream write completes. - Give generic native HTTP/1 responses bounded defaults: a 30-second write
timeout, a 300-second total response lifetime, and an 8 KiB/s minimum send
rate. Explicit proxy policies continue to override these defaults. - Write confidential disk-cache envelope v2 objects without plaintext combined
cache keys. Encrypted filesystem names and storage-bin indexes now use
HMAC-SHA-256 identities derived separately from the data-encryption key, so
offline candidate URLs cannot be verified against persisted lookup metadata. - Create a persistent random cache-root identity and derive independent local
data and index keys for every root. Replace advisory process-local AES-GCM
invocation tracking with a locked, durable counter for that effective root
key; missing or damaged established state fails closed. - Remove encrypted envelope v1 compatibility. The first startup with the new
root-bound format, and every local-key rotation, cold-purges that encrypted
cache root before serving traffic. OpenBao protects its random index key with
Transit rather than deriving persisted identities from the bearer token.
Socket-Activation Hardening
- Bound
LISTEN_FDSto 1 through 128 inside the focused systemd adoption crate
before libsystemd can allocate descriptor storage, independently preserving
the root runtime's existing launch-environment validation. - Require every inherited internet stream listener to report
SO_PROTOCOL=TCP, in addition to the existing socket-family, stream-type,
listening-state, planned-address, and one-shot ownership checks.
Stream Proxy Hardening
- Reject IANA special-purpose IPv4 and IPv6 DNS answers that can represent
translation, transition, discard-only, benchmarking, documentation,
site-local, or SRv6 SID destinations. Explicit IP-literal upstreams and the
existing trusted private-DNS opt-in remain unchanged. - Add
proxy_header_timeout_secs, defaulting to 10 seconds and capped at 60,
as one absolute deadline for the complete downstream PROXY v1/v2 preamble.
Byte-drip input from a trusted proxy cannot refresh this deadline. - Refresh the shared stream idle deadline after every successful partial write
and immediately sanitize each forwarded plaintext range, preserving active
connections under slow backpressure without extending truly idle sessions.
Snapshot Store Hardening
- Reject filesystem roots as snapshot stores and require pre-existing store
directories to already be private. Fluxheim never chmods an arbitrary
existing directory; only a dedicated directory it creates is initialized as
0700. - Enforce the 16 MiB snapshot reader limit before store locking, generation
allocation, transaction publication, orcurrentupdates. - Give persisted self-healing state a symmetric 64 KiB read/write envelope and
limit impact and rollback diagnostics to 4 KiB without control characters. - Preserve existing
current, generation, snapshot, and recovery files when
any new size or diagnostic admission check rejects input. - Create new snapshot-store directories relative to a no-symlink parent
directory handle, closing the path-resolution race around directory
creation and keeping filesystem safety checks effective under concurrency.
Reproducible FIPS-Backend Evidence
- Add separately pinned OpenSSL-FIPS and rustls/AWS-LC-FIPS proof
Containerfiles undercontainers/fips/. - Build the exact
profile-fips-opensslandprofile-fips-rustlsbinaries
inside their corresponding proof environments. - Run the built binary, verify the selected provider and dependency boundary,
exercise real downstream TLS and certificate-verified upstream TLS, and
prove incompatible TLS policy fails closed. - Record compiler, provider, dependency, binary, and image identity evidence.
- Add a manual GitHub workflow, a deep-gate entry, a static plan validator, and
an interactive test-starter entry for the proof.
These proof containers are CI evidence environments, not Fluxheim release
images. They do not claim that Fluxheim as a complete product or deployment is
FIPS validated. Operators remain responsible for the validated module,
platform, configuration, key handling, and required compliance evidence.
Testing
- Live native listener tests cover complete-body digests, compressed wire-byte
digests, conditional304,HEAD,206, cache MISS/HIT, and refused-origin
proxy status. - Live Wasm route coverage verifies post-hook digest emission and rejects
duplicateContent-Digestoutput; unit coverage verifies cache-digest reuse,
compression invalidation, and v1/v2 disk-metadata compatibility. - Config tests cover opt-in parsing, identifier validation, missing-identifier
rejection, and inherited overlay behavior. - Status metadata application is idempotent when a response policy is applied
more than once. - Shared-cache unit and live-listener tests cover credential bypass, malformed
freshness with an operator TTL,s-maxageprecedence, mandatory
revalidation, contradictory range metadata, zero-sized slice policy, and
oversized/FIFO storage-bin manifests. - Body-admission tests cover process-shared defaults, pinned HTTP/1 handlers,
exact HTTP/2 declared lengths, incremental unknown-length growth, aggregate
exhaustion, logarithmic growth under highly fragmented HTTP/2 DATA frames,
owner-backed H2 DATA retention, post-handler body retention, and permit
recovery. Static error-page and cache tests preserve fallback behavior while
admission precedes body materialization. - Cache-encryption tests cover cross-root key separation, opaque HMAC lookup
identities, restart continuity, missing-counter failure, local-key rotation,
v1 rejection, and cold removal of legacy encrypted filesystem objects. - Cache-header tests cover cumulative byte/directive ceilings and quoted-comma
parsing. - Shared path-safety and live redirect tests cover invalid UTF-8, overlong
slash encodings, encoded Unicode controls, and valid encoded Unicode. - Static-web tests cover missing children below valid and broken symlinked
parents plus hidden non-UTF-8 Unix filenames. - Systemd unit and process-level smoke coverage verifies explicit TCP protocol
admission, bounded declarations before receipt, one-shot ownership,
complete-set closure on validation failure, and normal listener adoption. - Paused-time stream tests prove v1 and v2 PROXY byte-drip input cannot extend
the absolute preamble deadline and that partial writes keep an active,
backpressured stream alive beyond one idle period. - The real-binary stream smoke drip-feeds an incomplete PROXY preamble beyond
its deadline, verifies rejection, and then proves the listener still accepts
a complete authenticated preamble and proxies traffic. - Stream DNS-admission tests cover the blocked IANA special-purpose ranges and
the two globally reachable IPv4 protocol-assignment anycast exceptions. - Snapshot tests prove filesystem roots and existing non-private directories
are rejected without permission changes, oversized snapshots publish no
layout or state, and invalid recovery diagnostics preserve prior state.
Checksums And Signatures
- Commit:
ab02c4f3c717004ae0be631fa51a83305380448a - Local gate: GitHub CI green before tag; local release metadata checks passed
- CodeQL/code scanning: no open release-blocking alerts before tag
- Source archive checksums:
000bf8027fb206333cf6fa1eddaa86bb6cec9833cfba4389b53a2a51add7205e fluxheim-1.7.12.tar.gz0ae822fbeb3a7223efe2a545b1d3a8a2c2f043c8ac245df8eb909d27313fbf85 fluxheim-1.7.12.zip
- Binary checksums:
- x86_64:
9f48a39afa7ed4ff6deed73d233e6afc597b1825dda64ca0eaa84c1b242d7297 fluxheim-1.7.12-full-x86_64-linux.tar.gz844ca1cce29a892eb8d761cacf652dba1cb48a21726c0fce7e00b43158b65ac2 fluxheim-1.7.12-cache-x86_64-linux.tar.gz49cc792303f7f2680add5fbfb268b26534620599c56f5c65ac2c581e70715156 fluxheim-1.7.12-proxy-x86_64-linux.tar.gzf5c7076afa4275dfa184faf243e9a8324d9052dcf6addd96f39d6868e63a73cb fluxheim-1.7.12-php-x86_64-linux.tar.gze158557258cc596ba4f79f0e0aa802bec73446dc59fa997eb92b797cdf670bf4 fluxheim-1.7.12-load-balancer-x86_64-linux.tar.gza6a5672da7859e91353ac2a67f3f40ba49814027eccd515e6c9aaeecbc6772b0 fluxheim-1.7.12-config-tester-x86_64-linux.tar.gz
- aarch64:
b70f594674a4494fc4a91c4b97dd7396a9f4f6a4982e180d1626aba5e5b09e2f fluxheim-1.7.12-full-aarch64-linux.tar.gz0663324b16de0ab6789872aefbe938f8c3fdf0df8d537ced34cf8095292c70aa fluxheim-1.7.12-cache-aarch64-linux.tar.gz5f3f512ed9888ddb5fd391282aef8754377ec2305fbc87e7d31011d9fc4df7d8 fluxheim-1.7.12-proxy-aarch64-linux.tar.gza18e5c3cbe1c019466e8721f882b9f4b9a97fd87e51f24d436fc1e634a23bc67 fluxheim-1.7.12-php-aarch64-linux.tar.gz743636a049ceb16545a3928dec2a5a7b7492cea5ce4d5399103ec80f6ecc8fd3 fluxheim-1.7.12-load-balancer-aarch64-linux.tar.gzcb396ff8d8c0f356e98cf05feb968774f45b705d8fda62aca56710dbcad6e7d5 fluxheim-1.7.12-config-tester-aarch64-linux.tar.gz
- macos:
638c1e084437e347ddaf1da32e47d4b5faa501d2b8d627cc1c82f1f65de01a76 fluxheim-1.7.12-dev-aarch64-macos.tar.gz
- x86_64:
- SBOM checksums:
fca0990a3be23254f0829ceef4146e420267d6af4957499750c1fcd3eb8d8ba8 fluxheim.spdx.json070ae8f98a59a55128f8e46cce41ca6ca69611d06dc10df61a5e7f8da1aa6136 fluxheim.cyclonedx.json
- Reproducible build:
5e737adce035f842e9c864473db45d18b6f7e9bb68075c8473fbe44a93f1a0ffx86_64fd3742fcc1ca1ea3e93aa54280f10e62c2bacc473ffbab059e78dd8944d4213eaarch6479e481e79ba5feae8b1c419f18e1e86bbb470606c7a056e9f5380b27f442f759macos
- Full Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:453e4eb0d658c60e35fa4f8257bd1435547fb5fbec9cc32896ea7614f7711d50 - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:074a0d5eda79125881c39b98f3a90c180ba7855f62e65b66b0cbed731a2c2a2f - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:1dd59c20c8ca9976a03ca73e1d8e06346f53c2e2efbc5df969c2af3c914a2af1 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:4bb3be6642539d565e921307987b50be11d7975f913ebc9bce461d4f8a2425eb
- Wolfi:
- Cache Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:bce02b1595b3a5790958174bc50074cea23f5397f3f34bbd76a53e5edc88558d - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:6590fe8709069038cce21aecdb5ad5203ce41b288bb508f295072a9ac943325c - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:e57332e596ebd52b4636ebd6d7e360c3e89f7f1bbff9334685f01ebb9f7ca0f6 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:d66dd9fbe0002f1cb6416268703d7d7df1c81079ad8f9b1d8f70a54616fe5115
- Wolfi:
- Proxy Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:7e4bac2fed8067115c84ea9a57bf7105497e3459ad78a28b4fe561ff3353d082 - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:0f5b93725d1d3bc2fbdf686f39965ac4b67165d79056116b0be3fcd8ecaec477 - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:6dc5de572b4075d30e7cf47575a35e2e4f3a17c2ccbb24121785acf0db4f3688 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:0ab59683426f70b126b7f15e5f934cb7f6060c5e3f90002d25e8c5c1d1033c68
- Wolfi:
- PHP Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:1fe83e140fb9802866b0d126c3f204a613644690ac8ddf36afbf49a87eaeff46 - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:39ef92de722bf6844d60c8103d8d2dd74a9788874d795fcfa1e9561d35f35c4b - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:97bd13f632a293caa805c97e9f2e6f58d9cb2a222c63d7154a5423711ca3217a - Debian:
ghcr.io/valkyoth/fluxheim@sha256:590024badbf9160d1af54288e4011eac05f214b198f1573afd40c77909477f9c
- Wolfi:
- Load Balancer Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:44de1eb9efa8c59ae2a8742c53447915c6c1a38ecb0ba4fa63258c2bc96ea083 - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:d88d5154dbab6189c2517eb88a256c09f4ec2f6393be1c9d0104b4b4867d744e - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:2f3f810f8c62513ea53794e00a7575dafe32d2e2ab7f6305887724180bc6f5b7 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:2374228474fab8dbfbff75e8080e701855c3052ddcca567ffeb3d3fc1fbe402d
- Wolfi:
- Tag signature:
Good "git" signature for 1921261+eldryoth@users.noreply.github.com with ED25519 key SHA256:EoLRQ5k4J5pYz3UMFmkrV798gYFNkToGS2xEPvebqB4