PERF: compress production JS and CSS on the static asset path (#663) #803

Open
opened 2026-10-02 13:12:30 +00:00 by kayg · 3 comments
Owner

Parent: #663 (bundle/loading architecture audit). Non-blocking performance finding.

Context: a self-hosted Instance must have a fast cold load without requiring undocumented edge middleware. Source audited at origin/dev c4a61e8cf0. Round 7a leaves this asset path unchanged.

Evidence: crates/calternal-server/src/main.rs:1074–1096 serves Frontend bytes, and :1131–1160 builds an uncompressed Body and cache policy. There is no CompressionLayer or Accept-Encoding negotiation in calternal-server. apps/web/svelte.config.js configures adapter-static without precompression. deploy/cloud/README.md delegates Traefik configuration to a private repository; this audit does not assert that the live public edge lacks compression.

Measured production graph (bun run build; bench/bundle-audit.mjs): shared shell JS is 1,091,341 B raw versus 369,672 B in separately gzipped files. CSS is 341,572 B raw versus 60,533 B gzip. These are file sizes, not wire captures or latency samples. Direct serving therefore loses about 1 MB of possible transfer reduction for the shell alone. Compression does not remove parse cost.

Concrete fix: emit compressed JS/CSS at build time and negotiate gzip/Brotli on the static asset path with Vary: Accept-Encoding. Keep correct MIME, hashed immutable policy and variant validators. Leave streams, range media and authenticated content outside this change. Do not compress every asset at request time. A runtime compression fallback is acceptable if build-time variants are not available, but report its CPU cost.

Test: real local production server GET and HEAD with identity/gzip/br;q=0 and supported encodings; decode each response and compare original bytes. Assert Vary, cache policy, Content-Type, HEAD semantics and validators. Measure repeated cold route transfer and server CPU/RSS on the perf VM under /root/perf.lock. Reuse #497 and #164 for route budget reporting. Search before filing: open/all issues for compression and gzip; #497 is about code size, #515/#492 about MCP; no static delivery owner found.

Parent: #663 (bundle/loading architecture audit). Non-blocking performance finding. Context: a self-hosted Instance must have a fast cold load without requiring undocumented edge middleware. Source audited at origin/dev c4a61e8cf090170f35b1bed3350d9de20c83ecd5. Round 7a leaves this asset path unchanged. Evidence: crates/calternal-server/src/main.rs:1074–1096 serves Frontend bytes, and :1131–1160 builds an uncompressed Body and cache policy. There is no CompressionLayer or Accept-Encoding negotiation in calternal-server. apps/web/svelte.config.js configures adapter-static without precompression. deploy/cloud/README.md delegates Traefik configuration to a private repository; this audit does not assert that the live public edge lacks compression. Measured production graph (bun run build; bench/bundle-audit.mjs): shared shell JS is 1,091,341 B raw versus 369,672 B in separately gzipped files. CSS is 341,572 B raw versus 60,533 B gzip. These are file sizes, not wire captures or latency samples. Direct serving therefore loses about 1 MB of possible transfer reduction for the shell alone. Compression does not remove parse cost. Concrete fix: emit compressed JS/CSS at build time and negotiate gzip/Brotli on the static asset path with Vary: Accept-Encoding. Keep correct MIME, hashed immutable policy and variant validators. Leave streams, range media and authenticated content outside this change. Do not compress every asset at request time. A runtime compression fallback is acceptable if build-time variants are not available, but report its CPU cost. Test: real local production server GET and HEAD with identity/gzip/br;q=0 and supported encodings; decode each response and compare original bytes. Assert Vary, cache policy, Content-Type, HEAD semantics and validators. Measure repeated cold route transfer and server CPU/RSS on the perf VM under /root/perf.lock. Reuse #497 and #164 for route budget reporting. Search before filing: open/all issues for compression and gzip; #497 is about code size, #515/#492 about MCP; no static delivery owner found.
Author
Owner

Starting work on job/webperf, based on 2f4482ded066d9c5d9c59130377907f7fd2916c9 (job/merge-round-7a). I am reading the matching audit evidence and will report the concrete finding, regression coverage, measurements, and gate output here when finished.

Starting work on `job/webperf`, based on `2f4482ded066d9c5d9c59130377907f7fd2916c9` (`job/merge-round-7a`). I am reading the matching audit evidence and will report the concrete finding, regression coverage, measurements, and gate output here when finished.
Author
Owner

Finding: static assets were served without negotiated compression or representation validators. The production build now writes Brotli/gzip sidecars; the server negotiates encodings and sends Vary, representation ETags, HEAD/304 behavior and font revalidation headers. Static-sidecar tests passed as part of the web suite; the server test is still compiling.

Finding: static assets were served without negotiated compression or representation validators. The production build now writes Brotli/gzip sidecars; the server negotiates encodings and sends Vary, representation ETags, HEAD/304 behavior and font revalidation headers. Static-sidecar tests passed as part of the web suite; the server test is still compiling.
Author
Owner

F7 — P3: Static negotiation ignores wildcard exclusion for identity

Owner: #803. Introduced by cba42bdf3.
Evidence: crates/calternal-server/src/main.rs:1373.
identity.unwrap_or(1000) accepts identity even when the header is *;q=0.
It also selects identity for gzip;q=0.5, *;q=0 with a gzip sidecar. The client
excluded identity and asked for gzip. This differs from RFC 9110 §12.5.3.
This is a protocol defect with uncommon input, not a security blocker.

Fix: an explicit identity weight takes precedence; without it, wildcard zero
excludes identity. Keep the default identity acceptance for other headers.
Test idea: cover wildcard zero alone, gzip with wildcard zero, and an explicit
identity override in the existing negotiation test. Search: encoding, #803.
Use #803 for the shared negotiation fix.

## F7 — P3: Static negotiation ignores wildcard exclusion for identity Owner: #803. Introduced by `cba42bdf3`. Evidence: `crates/calternal-server/src/main.rs:1373`. `identity.unwrap_or(1000)` accepts identity even when the header is `*;q=0`. It also selects identity for `gzip;q=0.5, *;q=0` with a gzip sidecar. The client excluded identity and asked for gzip. This differs from [RFC 9110 §12.5.3](https://www.rfc-editor.org/rfc/rfc9110.html#section-12.5.3). This is a protocol defect with uncommon input, not a security blocker. Fix: an explicit identity weight takes precedence; without it, wildcard zero excludes identity. Keep the default identity acceptance for other headers. Test idea: cover wildcard zero alone, gzip with wildcard zero, and an explicit identity override in the existing negotiation test. Search: `encoding`, #803. Use #803 for the shared negotiation fix.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#803
No description provided.