Repository navigation
[Product Gap] Bound HTTP/1.1 semantics over the authenticated TLS stream #9
Description
Buyer-visible problem
OriginWeave can now authorize a canonical origin, bind it to an approved resolved destination, prove the exact operating-system TCP peer, and authenticate the requested HTTPS service on that same stream. It still cannot safely perform an HTTP exchange. A buyer-visible navigation path remains vulnerable to ambiguous message framing, unbounded headers or content, compression bombs, method/status mistakes, incomplete responses, integrity mismatches, MIME confusion, unsafe filenames, and redirects that bypass the existing origin/destination/transport/TLS authorities.
Required bounded vertical slice
Create an independently reusable Rust originweave-http crate that performs one bounded HTTP/1.1 request/response exchange over an existing AuthenticatedTlsConnection. It must never resolve a hostname, open or reconnect a socket, select a proxy, parse PAC, weaken TLS, control Chromium, or persist a download directly.
HTTP/2 and HTTP/3 remain separate later adapters. The first slice supports only a negotiated http/1.1 ALPN value or an explicitly documented direct-test policy where ALPN absence is permitted; it must reject h2, h3, and any other application protocol.
Request authority
- Accept the authenticated TLS stream and immutable TLS evidence, the exact canonical request target, one bounded HTTP policy, and an explicit method.
- Require the request origin to equal the authenticated TLS origin.
- Permit only an explicit bounded method allow-list. The first slice should support
GETandHEAD; state-changing methods remain a later action-policy integration. - Generate the request target and
Hostfield from the canonical origin and target contract; do not accept caller-supplied framing, connection, proxy, authorization, cookie, or hop-by-hop fields in the general header collection. - Reject control characters, obsolete line folding, whitespace before field names, invalid field names, invalid field values, duplicate singleton fields, excessive field count, excessive field-name/value bytes, and total header-section overflow before emitting bytes.
- Never place credential values in evidence, errors, logs, or model-visible output.
HTTP/1.1 framing
Implement RFC 9112 message parsing and framing fail closed:
- strict CRLF start-line and field-line handling;
- bounded status-line and header-section parsing;
- exact response body-length determination from request method, response status,
Transfer-Encoding,Content-Length, and connection close; - reject a message containing both
Transfer-EncodingandContent-Length; - reject unsupported transfer codings, invalid chunk sizes, chunk extensions outside a small explicit policy, malformed trailers, conflicting or invalid
Content-Length, incomplete bodies, premature EOF, and bytes that would make the next-message boundary ambiguous; - treat
HEAD,1xx,204,304, successfulCONNECT, and other no-content semantics according to RFC 9110/9112 rather than merely following header presence; - disable connection reuse in the first slice so parser state cannot leak across requests.
Resource budgets
Validate every limit before use and enforce a single monotonic exchange deadline:
- request bytes;
- status-line bytes;
- header-field count;
- one field-name and field-value size;
- total header-section bytes;
- chunk count;
- encoded content bytes;
- decoded content bytes;
- content-coding expansion ratio;
- trailer count and bytes;
- interim response count;
- total elapsed time and per-read/per-write blocking;
- redirect metadata retained for the caller.
Content codings must stream through bounded decoders. No implementation may allocate from untrusted declared lengths, buffer an entire unbounded response, or retry beyond the total deadline. When a limit is crossed, stop reading, close the owned stream, and return a typed failure without exposing a partial authenticated response as complete.
Semantics and redirects
- Retain the exact status code and reason-phrase bytes separately; do not derive behavior from the reason phrase.
- Return redirect evidence, not an automatically followed redirect.
- A caller must submit every redirect target through canonical origin parsing, destination approval, direct TCP binding, TLS authentication, and a new HTTP exchange plan.
- Preserve secure-scheme downgrade, redirect-cycle, target digest, hop-limit, capability, and action-risk checks as separate existing authority boundaries.
- Make response completeness explicit. A partial or truncated response cannot be represented as a successful complete response.
Integrity fields
Support optional RFC 9530 validation after exact message framing:
- parse
Content-DigestandRepr-Digestas HTTP Structured Fields; - support an explicit algorithm allow-list, initially
sha-256andsha-512only; - distinguish absent, verified, unsupported, malformed, and mismatched integrity evidence;
- never claim malicious-tamper protection from an unsigned digest alone;
- record that RFC 9530 obsoletes RFC 3230 and the legacy
Digest/Want-Digestfields.
MIME and download handoff
- Parse the supplied
Content-Typewith a deterministic MIME record rather than string-prefix heuristics. - Compute an observed MIME type from a bounded resource header using the current WHATWG MIME Sniffing contract or a separately versioned compatible adapter.
- Preserve supplied MIME, computed MIME,
X-Content-Type-Optionsno-sniff state, and mismatch classification as evidence. - Treat HTML, XML, JavaScript, SVG, and PDF as scriptable/high-risk content classes for downstream policy.
- Do not infer MIME from a URL extension.
- Parse
Content-Dispositioninto a safe metadata record, but do not create files. Normalize or reject control characters, path separators, absolute paths, device names, ambiguous Unicode, excessive names, and extension/type mismatch before any download adapter can persist bytes. - Pass bytes and evidence to a later download/MIME authority; this crate must not execute, render, extract, or save content.
Evidence and errors
Emit immutable, credential-free HttpExchangeEvidence containing at minimum:
- authenticated canonical origin and exact TCP peer identifiers inherited from TLS evidence;
- request method and canonical target digest without query credential retention;
- HTTP version and status code;
- bounded response-header names plus allow-listed non-sensitive values only;
- encoded and decoded byte counts;
- transfer/content coding decisions;
- response completeness;
- supplied and computed MIME types, no-sniff state, and mismatch classification;
- integrity-field status and algorithm identifiers;
- redirect target digest and canonical origin when present, with sensitive query values excluded;
- exchange duration and configured budgets;
- source hashes sufficient for replay and audit without retaining secrets.
Public errors must implement deterministic Display and std::error::Error, preserve underlying I/O/decode failures as sources, and distinguish invalid policy, request authority mismatch, invalid request fields, malformed status/headers, framing ambiguity, unsupported transfer/content coding, incomplete response, timeout, each resource-budget violation, integrity mismatch, invalid MIME, unsafe disposition metadata, unexpected ALPN, and peer/TLS evidence mismatch.
Realistic tests
Use real loopback HTTP/1.1 servers over the authenticated TLS test authority. Cover at least:
- bounded
GETwithContent-Lengthsuccess; - bounded
HEADand no-content status semantics; - valid chunked content and trailers;
- conflicting
Content-Lengthvalues; Transfer-EncodingplusContent-Lengthrejection;- whitespace-before-field-name and obsolete folding rejection;
- malformed status lines, invalid chunk syntax, premature EOF, and incomplete TLS close;
- oversized line, field count, header section, body, decoded body, trailer, chunk count, and interim response count;
- gzip/deflate expansion-ratio enforcement with streamed decoding;
- hard total deadline before and after each blocking operation;
Content-Digest/Repr-Digestvalid, absent, unsupported, malformed, and mismatch cases;- supplied/computed MIME agreement, mislabeled scriptable content, no-sniff behavior, ZIP/PDF/HTML signatures, and extension spoofing;
- safe and hostile
Content-Dispositionnames across Unix and Windows path conventions; - redirect returned as evidence without follow-up network I/O;
- exact proof that no reconnect, DNS, proxy, PAC, Chromium, unrestricted logging, credential retention, or file persistence path exists;
- exact 100% production function, line, region, and branch coverage and complete public rustdoc.
Architecture and documentation
- Add an ADR separating HTTP semantics from origin parsing, destination approval, TCP peer proof, TLS identity, proxy/PAC routing, redirect authorization, MIME/download persistence, Chromium integration, and content execution.
- Update
AGENTS.md,CLAUDE.md,ARCHITECTURE.md,README.md,CHANGELOG.md,docs/product-roadmap.md,docs/quality-gates.md, anddocs/doctoring.md. - Record all adopted limits as product safety budgets, not protocol-validity claims.
- Add a Mermaid sequence diagram from authenticated TLS stream through bounded exchange evidence and redirect reauthorization.
- Preserve independent crate usability for OriginWeave, naruon, or another CWL service.
Commercial proof
A deterministic loopback suite demonstrates that the same authenticated TLS stream yields a complete HTTP response only when message framing is unambiguous, all resource budgets hold, optional integrity evidence verifies, and content metadata is safely classified. Redirects are surfaced but never followed without repeating the full authority chain.
Standards references — APA 7th
Fielding, R., Nottingham, M., & Reschke, J. (2022). HTTP semantics (RFC 9110). Internet Engineering Task Force. https://doi.org/10.17487/RFC9110
Fielding, R., Nottingham, M., & Reschke, J. (2022). HTTP/1.1 (RFC 9112; STD 99). Internet Engineering Task Force. https://doi.org/10.17487/RFC9112
Polli, R., & Pardue, L. (2024). Digest fields (RFC 9530). Internet Engineering Task Force. https://doi.org/10.17487/RFC9530
WHATWG. (2026, July 17). MIME sniffing: Living Standard. https://mimesniff.spec.whatwg.org/
Out of scope
HTTP/2, HTTP/3, proxy/PAC, connection pooling, caching, cookies, authentication, client certificates, WebSocket, WebTransport, range assembly, multipart form upload, automatic redirect following, file persistence, archive extraction, active-content rendering, Chromium Network Service integration, and browser UI remain later independently reviewable slices.
Activity
seonghobae commentedon Aug 7, 2026
Standards addendum for the implementation spec
Current primary-source review adds two normative parsing contracts that should be explicit before implementation:
Content-DigestandRepr-Digestwith an RFC 9651 Structured Fields implementation, while retaining the field-specific dictionary and byte-sequence constraints defined by RFC 9530. RFC 9651 obsoletes RFC 8941 and is backward-compatible with fields defined against the earlier revision; malformed Structured Fields must be rejected or ignored only according to the strict RFC 9651 and field-specific policy, never partially recovered.Content-Dispositionaccording to RFC 6266, and decodefilename*extended parameters according to RFC 8187, which obsoletes RFC 5987. When bothfilenameandfilename*are present, prefer the validfilename*value, but continue to treat every server-provided filename as advisory and apply the existing fail-closed path, device-name, control-character, Unicode, and extension/MIME safety policy before any persistence handoff.RFC 9530 currently has verified editorial errata; implementation tests should use the normative RFC text and maintain an errata review record without treating editorial corrections as protocol changes.
Additional APA 7th references
Nottingham, M., & Kamp, P.-H. (2024). Structured field values for HTTP (RFC 9651). Internet Engineering Task Force. https://doi.org/10.17487/RFC9651
Reschke, J. F. (2011). Use of the Content-Disposition header field in the Hypertext Transfer Protocol (HTTP) (RFC 6266). Internet Engineering Task Force. https://doi.org/10.17487/RFC6266
Reschke, J. F. (2017). Indicating character encoding and language for HTTP header field parameters (RFC 8187). Internet Engineering Task Force. https://doi.org/10.17487/RFC8187
seonghobae commentedon Aug 7, 2026
Reviewable implementation sequence
To avoid another oversized authority-boundary PR while still producing usable, fail-closed increments, implement the issue as four ordered changes on one independently reusable
originweave-httpcrate. Each change must keep the workspace green, preserve the authenticated TLS stream as the only transport authority, and end with exact 100% production function/line/region/branch coverage.1. Request authority and fixed-length response kernel
HttpMethod, canonical request-target/Host derivation, bounded policy types, forbidden hop-by-hop/credential field validation, deterministic request serialization, strict status/header parsing,GET/HEAD, no-content status semantics, exactContent-Length, and explicitConnection: closeownership.http/1.1or an explicit ALPN-absence direct-test policy; reject every other negotiated protocol.AuthenticatedTlsConnection; no DNS, reconnect, proxy/PAC, redirects, persistence, content coding, or MIME inference.2. Complete RFC 9112 framing
Transfer-Encoding/Content-Lengthambiguity rejection, unsupported transfer-coding rejection, and exact next-message-boundary checks.3. Bounded content codings and digest evidence
Content-Digest/Repr-Digestverification using RFC 9651 Structured Fields, with explicitsha-256/sha-512allow-lists and absent/verified/unsupported/malformed/mismatch evidence.4. MIME, disposition, redirect, and audit handoff
HttpExchangeEvidence, deterministic errors with preserved sources, architecture/ADR/doctoring/roadmap/quality-gate updates, and the Mermaid authority-chain sequence.filename*precedence, redirect evidence, query redaction, and proof that no file write/render/extract/execute path exists.The first implementation PR should be stacked only after the TLS PR’s exact head is stable and should target the TLS branch until that prerequisite merges; reviews, approvals, and checks must not transfer when it is retargeted to
main.seonghobae commentedon Sep 22, 2026
2026-09-23 current repair evidence for canonical HTTP authority: PR #37 is now at exact
15e7c97dc1102934fa1e3ca8517b86938a808565, ordinary-forward on protectedmain@87c4daa1830bac5a5228b6036752ad5633232085.Predecessor
367e9f62714215b032ae10df6fea730b7e254a56finally cleared hosted-runner admission and produced a real repository-contract RED. CI35778361555admitted both jobs: Production coverage106917229967completed SUCCESS, while Rust contracts106917229535failed atCheck Python repository contractsbefore formatting/tests/Clippy/rustdoc. SAST35778361885independently completed SUCCESS. RCA found no HTTP/runtime defect:tests/test_http_content_coding_documentation_contract.pyrequired lowercase literalstacked content codings, while ADR 0011 correctly begins the sentenceStacked content codings .... The contract was coupled to prose capitalization rather than the semantic interoperability restriction.Minimal ordinary-forward repair
15e7c97d...changes only that assertion to searchadr.lower(). Production Rust, decoder semantics, design/ADR wording, dependencies, workflows, rulesets, and coverage denominators are unchanged. Fresh exact-head runs are live and nonterminal: CI35789840659, SAST35789840604, Security35789840636, CodeQL35789840612. The earlier central queue report was corrected at.github#712comment5784887730; no blind rerun or source-neutral wake was used.Issue #9 remains open until one unchanged exact head receives native repository/security evidence, eligible independent approval, all required central verdicts, and normal protected-main integration. Predecessor workflow/review results do not transfer.
seonghobae commentedon Sep 22, 2026
PR #37 HTTP/1.1 reconstruction has a new standards-conformance repair on the ordinary-forward branch.
Fresh review found that the
Content-Encoding: gzippath treated a second valid gzip member as trailing garbage. That is stricter than the coding it advertises: RFC 9110 defines HTTPgzipby reference to RFC 1952, and RFC 1952 defines a gzip file as a series of concatenated members.Repair lineage:
da736d43153bef1d3488aa8df389a4200a0ca5b8: adds a regression requiring two independently encoded RFC 1952 members to decode as one representation; hosted workflows for this intermediate head were superseded/cancelled before an executable RED completed, so no hosted RED is claimed.5994acab7e58a76edd9cc80800c7dfc8acca0fd6: replaces the single-memberbufread::GzDecoderpath withbufread::MultiGzDecoder, preserving the existing aggregate decoded-size and expansion-ratio limits. Concatenated members are accepted; malformed non-gzip trailing bytes still fail asContentDecodingFailed.28321dec3a812ff63886de8d33fb102d4894a3fe: records RFC 1952/RFC 9110 authority and also removes a stale Content-Length sentinel/EOF statement that contradicted the already-landed self-delimitingContent-Lengthrepair.Issue #9 remains open. No protected-main shipment is claimed until the exact current head receives its required CI/security/CodeQL/review evidence and normal integration.
seonghobae commentedon Sep 22, 2026
PR #37 ordinary-forward currentness update: exact head is now
2f9ab91e28b0570e69fbb00ba011baa3d8b02e66on unchanged protectedmain@87c4daa1830bac5a5228b6036752ad5633232085.The remaining documentation-to-code gap from the RFC 1952 repair is now closed:
2f9ab91e...adds anUnreleased/ChangedCHANGELOG entry stating thatgzipaccepts concatenated RFC 1952 members through the bounded multi-member decoder while retaining aggregate decoded-size/expansion-ratio limits and typed failure for malformed trailing data. Runtime behavior is unchanged from5994acab...; this is documentation currentness only.The immediately superseded
28321dec...exact-head workflows never reached executable steps: CI Rust/coverage, Semgrep, Security scope detection, and CodeQL language detection were allrunner_id=0,steps=[]queue-admission waits. That exact specimen is recorded at canonical queue owner.github#712comment5782294990; predecessor queue evidence does not transfer to2f9ab91e.... Fresh exact-head workflows/review remain mandatory before normal integration.seonghobae commentedon Sep 22, 2026
PR #37 current authority advanced ordinary-forward to
4869038c23f4fecb88a8b5d36b980f6a800fccaa. Fresh compare from doctoring head28321dec...is 2 commits ahead / 0 behind with an aggregate delta of exactly one addedCHANGELOG.mdline: the RFC 1952 multi-member gzip release note.4869038c...only restores the terminal newline that the preceding full-file Contents API write had unintentionally removed.Fresh exact-head CI/SAST/Security/CodeQL generations all materialized but remain blocked before executable steps on runner admission: CI
35772008929, SAST35772008869, Security35772008659, CodeQL35772008774. The exact specimen is recorded at canonical queue owner.github#712comment5782414546. No current-head GREEN, source failure, independent approval, or merge acceptance is claimed.seonghobae commentedon Sep 22, 2026
Current #37 HTTP authority update on exact
367e9f62714215b032ae10df6fea730b7e254a56(basemain@87c4daa1830bac5a5228b6036752ad5633232085). Fresh code/docs review found the approved design and Proposed ADR lagging the already-repaired decoder: production accepts concatenated RFC 1952 gzip members viaMultiGzDecoderand records bounded raw RFC 1951 DEFLATE fallback asDeflateRawCompatibility, but the design still said raw deflate was rejected and the ADR still described zlib-only deflate. Test-first documentation contracts were added (1b3d569b..., then ADR coverage6d6e8c09...); ordinary-forward repairsfdbdad4b...and367e9f62...make design + ADR match executable behavior and preserve RFC 9110/RFC 1951/RFC 1952 boundaries. No HTTP production code changed in this repair.The same standards review makes the next buyer-visible interoperability gap explicit rather than hiding it: RFC 9110 permits an ordered list of content codings, while the bounded first slice intentionally rejects stacked codings. Safe expansion needs a reviewed maximum coding depth, reverse-order decoding, cumulative decoded-byte/expansion accounting across the whole chain, evidence-schema support, and realistic TLS loopback fixtures including malformed inner layers and expansion attacks. This remains follow-up work; it is not justification to widen #37 while exact-head gates are unresolved.
Current exact-head CI
35778361555, SAST35778361885, Security35778361631, and CodeQL35778361641are all still pre-step queued. The actionable jobs have no runner andsteps=[]; Security gitleaks is conditionally skipped while scope detection is unresolved, so no hosted GREEN is claimed. Exact specimen is recorded at canonical runner-admission owner.github#712comment5783349121. Keep #9 open through normal protected integration; no predecessor check/review transfers to this head.seonghobae commentedon Sep 23, 2026
Canonical HTTP authority #37 is now exact
7007140e95f94d1601259384bf646b8bde6a240c. Predecessor15e7c97...finally received a hosted runner: exact production coverage is GREEN, while Rust contracts failed specifically at rustfmt after Python repository contracts passed. The uploaded canonical rustfmt artifact identified only three formatting deltas (two missing terminal newlines and one import layout); commit7007140e...applies that artifact verbatim with no runtime semantic change. Fresh CI/SAST/Security/CodeQL generations exist and predecessor evidence does not transfer. Stacked-coding successor #327 has non-force adopted the repaired parent atb7e056a781297d570c908710737028ecd8ed5abdand remains test-only pending executable RED.seonghobae commentedon Sep 23, 2026
HTTP authority currentization: canonical parent #37 is now exact
219b43bfa87ab4fd90a77bb962df2797925bf661. Predecessor7007140e...did run: Production coverage was SUCCESS, while Rust contracts reached strict Clippy after repository contracts/format/tests passed and failed only on fourexpect_usedplus onepanicin the chunked committed-prefix regression. Ordinary-forward test-only repairsda7ffb29189b089d536efd925df4de2e36d3b402and219b43bfa87ab4fd90a77bb962df2797925bf661remove those violations without suppressions or gate changes. Fresh exact CI35816715517is non-terminal, so #9 remains open and no predecessor GREEN is promoted.The stacked-coding successor #327 has been non-force restacked onto this exact parent at child
beabc7d3e27c5c407d2847ff179eb16682ad86cd; compare is 5 ahead / 0 behind and still only one +235-line integration-test delta. Production stacked decoding is still withheld until that exact child produces its intended executable RED.