Skip to content

feat: bound HTTP/1.1 semantics to authenticated streams - #11

Draft
seonghobae wants to merge 332 commits into
mainfrom
feat/http11-semantics
Draft

feat: bound HTTP/1.1 semantics to authenticated streams#11
seonghobae wants to merge 332 commits into
mainfrom
feat/http11-semantics

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Buyer-visible problem

OriginWeave now authenticates a canonical HTTPS service on the exact previously authorized TCP stream, but it cannot yet perform a bounded HTTP exchange. Ambiguous framing, conflicting lengths, malformed chunks, unbounded content, decompression expansion, incomplete responses, misleading MIME metadata, unsafe filenames, or automatic redirect behavior would break the authority and evidence chain.

Approved design

This draft implements issue #9 as an independently reusable originweave-http Rust crate. The approved design and task-level TDD plan are committed at:

  • docs/superpowers/specs/2026-08-07-http11-semantics-design.md
  • docs/superpowers/plans/2026-08-07-http11-semantics.md

Intended vertical slice

  • one HTTP/1.1 GET or HEAD exchange over an existing AuthenticatedTlsConnection;
  • no DNS, socket connect, reconnect, proxy/PAC, pool, redirect follow, cookie jar, file write, Chromium, or model call;
  • strict RFC 9110/9112 response syntax and framing;
  • explicit byte/count/deadline budgets;
  • bounded gzip and zlib-deflate decoding;
  • RFC 9530 SHA-256/SHA-512 digest validation;
  • conservative MIME, no-sniff, disposition, and redirect metadata;
  • immutable credential-free evidence;
  • exact 100% production function, line, region, and branch coverage;
  • full rustdoc, ADR, architecture, CHANGELOG, roadmap, quality gates, and APA 7th doctoring.

TDD state

The design and implementation plan are committed first. Production code and failing contract tests will be added task by task. Keep this pull request in Draft until the complete exact head passes CI, Security Scan, SAST, independent review, and all coverage/doc gates.

Closes #9

Summary by CodeRabbit

  • 새로운 기능

    • 인증된 TLS 연결에서 제한된 HTTP/1.1 GET·HEAD 요청과 응답 처리를 지원합니다.
    • 청크 본문, 압축 해제, 헤더·트레일러, MIME, 무결성 검증 및 안전한 리디렉션 메타데이터를 처리합니다.
    • 요청·응답 크기, 시간, 청크 수 등 리소스 제한을 적용합니다.
    • HTTP 교환 결과와 검증 정보, 응답 사유 구문 진단 정보를 제공합니다.
  • 문서

    • HTTP/1.1 보안, 프레이밍, 무결성 및 설계 기준을 문서화했습니다.
  • 테스트

    • TLS 통합 테스트와 다양한 형식 오류·경계 조건·보안 시나리오 검증을 추가했습니다.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 54f8fc2c-2bef-4c7a-b511-ccd6983dc7c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

인증된 TLS 연결에서 단일 HTTP/1.1 GET/HEAD 교환을 수행하는 originweave-http 크레이트를 추가했습니다. 요청·응답 검증, 자원 예산, 콘텐츠 디코딩, digest·MIME·redirect 메타데이터, 불변 증거, typed error, 통합 테스트 및 reason phrase 진단 보존을 포함합니다.

Changes

HTTP/1.1 의미론

Layer / File(s) Summary
정책 및 요청 계약
Cargo.toml, crates/originweave-http/Cargo.toml, crates/originweave-http/src/{error,policy,field,target,request,lib}.rs, crates/originweave-http/tests/{policy,request}_contract.rs
워크스페이스 등록, 의존성, 정책 제한, typed error, 요청 필드, origin-bound target 및 결정적 GET/HEAD 요청 직렬화를 추가했습니다.
응답 파싱 및 콘텐츠 검증
crates/originweave-http/src/{response_head,framing,chunked,content,integrity,mime,disposition}.rs, crates/originweave-http/src/tests/*
엄격한 응답 헤드·프레이밍·chunked body 파서와 bounded decoding, digest 검증, MIME 분류, 안전한 disposition·redirect 메타데이터를 추가했습니다.
TLS 교환 및 증거
crates/originweave-http/src/{exchange,evidence}.rs, crates/originweave-http/tests/*integration.rs
인증된 TLS 연결의 peer·ALPN·origin을 검증하고, deadline 기반 I/O와 응답 검증을 수행한 뒤 본문, 원시 reason phrase 및 불변 증거를 반환합니다.
통합 검증 및 저장소 계약
crates/originweave-http/tests/*, tests/test_http_governance.py, tests/test_repository_contract.py
계약, loopback TLS, 오류 회귀, 금지 API, 의존성, 문서 및 모듈 경계를 검증합니다.
설계 문서 및 커버리지 진단
docs/adr/*, docs/doctoring*, docs/superpowers/*, scripts/ci/verify_coverage.py, tests/test_verify_coverage.py
HTTP/1.1 범위, chunked 메시지 경계, reason phrase 처리 및 표준 근거를 문서화하고 LLVM coverage 진단에 파일·region·segment·expansion 위치를 포함합니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant HttpExchangePlan
  participant AuthenticatedTlsConnection
  participant ResponseParser
  participant ContentDecoder
  participant Evidence
  Caller->>HttpExchangePlan: 요청 및 정책으로 계획 생성
  HttpExchangePlan->>AuthenticatedTlsConnection: peer·origin·ALPN 검증
  HttpExchangePlan->>AuthenticatedTlsConnection: HTTP/1.1 요청 쓰기
  AuthenticatedTlsConnection->>ResponseParser: 응답 헤드와 본문 전달
  ResponseParser->>ContentDecoder: framing된 본문 디코딩
  ContentDecoder->>Evidence: 콘텐츠·digest·MIME 결과 기록
  Evidence-->>Caller: AuthenticatedHttpResponse 반환
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 79.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive 주요 요구사항은 구현되었지만 Cargo.lock은 필터링되었고, 실제 100% 커버리지와 권한 흐름 다이어그램은 검증할 수 없습니다. Cargo.lock을 포함한 의존성 검토와 실제 커버리지 결과 및 Mermaid 권한 흐름 다이어그램을 확인하십시오.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 인증된 스트림에서 HTTP/1.1 의미론을 제한하는 주요 변경 사항을 간결하게 설명합니다.
Out of Scope Changes check ✅ Passed 변경 사항은 bounded HTTP/1.1 교환, 테스트, 커버리지 검증 및 관련 문서라는 연결 이슈의 범위에 포함됩니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/http11-semantics

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Standards-conformance finding on exact head 9032b5f7aeaac2626be926a05ab0252f3e8ba06d: response_head::parse_status_line currently accepts HTTP/1.1 200 without the mandatory separator SP, while rejecting HTTP/1.1 200 when the reason phrase is absent. RFC 9112 §4 defines status-line = HTTP-version SP status-code SP [ reason-phrase ] and explicitly requires the server to send the separator SP even when the reason phrase is absent. Add the regression contract first (accept the empty reason phrase after the mandatory SP; reject a missing second SP), then adjust the parser. Keep strict CRLF and field parsing unchanged. Primary source: RFC 9112 §4, https://www.rfc-editor.org/rfc/rfc9112.html#section-4

Comment thread .github/workflows/repair-http-reachability.yml Fixed

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@opencode-agent @cwl-noema-review

Review-only request for exact current head 85ec324d4914c485a95772cb4e69d10447cc45ec against protected base b228693f9e0a11d1794c1e4b0f7a3a38559a5491. Do not mutate the branch or merge. Re-review the complete base-to-head HTTP/1.1 slice, treating all predecessor-head evidence as historical. In particular verify RFC 9110/9112 status-line and framing semantics, RFC 9530/RFC 8941 digest parsing including omitted Base64 padding with malformed-alphabet/impossible-length/nonzero-trailing-bit rejection, header-before-trailer last-occurrence-wins behavior, representation-vs-content digest byte domains, bounded chunked-wire memory behavior, redirect reauthorization boundaries, MIME/disposition safety, timeout/error causality, credential-free evidence, exact-head CI/SAST/Security Scan success, absence of temporary write-capable repair workflows, and zero unresolved valid review findings. Submit a formal non-author GitHub APPROVE review only if this exact unchanged head satisfies repository policy; otherwise report only current-head actionable findings.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

@seonghobae I will perform a full independent review of PR #11 from base b228693f9e0a11d1794c1e4b0f7a3a38559a5491 to head 85ec324d4914c485a95772cb4e69d10447cc45ec.

I will verify the specified HTTP semantics, security boundaries, CI evidence, and workflow restrictions. I will report only findings that reproduce on this exact head. I will not mutate the branch or merge it.

⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 1 minute.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Trigger the previously requested full review for exact current head 85ec324d4914c485a95772cb4e69d10447cc45ec against protected base b228693f9e0a11d1794c1e4b0f7a3a38559a5491. Automatic review is currently paused and the latest attempt for this exact range was rate-limited, so this is the supported single-review path rather than a duplicate active review. Reassess the complete base-to-head HTTP/1.1 diff, including the RFC 8941 omitted-padding decoder configuration and regressions, RFC 9530 header/trailer merge semantics, reason-phrase handling, chunked wire bound, content/repr digest byte domains, resource limits, TLS-stream authority, exact coverage, and absence of temporary write-capable repair workflows. Do not mutate the branch or merge. Report only findings applicable to this exact unchanged head.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

@seonghobae I will perform a full independent review of PR #11 from base b228693f9e0a11d1794c1e4b0f7a3a38559a5491 to exact head 85ec324d4914c485a95772cb4e69d10447cc45ec.

I will reassess the complete HTTP/1.1 diff. I will report only findings that reproduce on this exact head. I will not mutate the branch or merge it.

⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 28 minutes.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Run the previously requested full review for the exact unchanged current head 85ec324d4914c485a95772cb4e69d10447cc45ec against protected base b228693f9e0a11d1794c1e4b0f7a3a38559a5491. The last exact-range request was rate-limited at 2026-08-08T13:19:47Z with a 28-minute cooldown, which has now elapsed by several hours, and no completed equivalent exact-head full review is present. Reassess the complete base-to-head HTTP/1.1 slice, especially RFC 9110/9112 framing and status-line behavior, RFC 9530/RFC 8941 digest parsing and header/trailer merge order, omitted Base64 padding rejection boundaries, content-vs-representation digest domains, bounded chunked wire memory, TLS stream authority, redirect/MIME/disposition safety, timeout/error causality, exact 100% owned-production coverage, and absence of temporary write-capable repair workflows. Do not mutate the branch or merge. Report only findings that reproduce on this exact head. This automated review is not a qualifying independent non-author approval.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

@seonghobae I will run a full review of PR #11 for exact head 85ec324d4914c485a95772cb4e69d10447cc45ec against base b228693f9e0a11d1794c1e4b0f7a3a38559a5491.

I will assess only findings that reproduce on that range. I will not mutate the branch or merge the PR. This review does not provide a qualifying independent non-author approval.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Actionable comments posted: 10

🧹 Nitpick comments (10)
crates/originweave-http/src/tests/chunked_wire_budget_contract.rs (1)

4-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

기대 상한값의 산출 근거를 남기십시오.

라인 7은 18_104_340을 상수로 고정합니다. 이 값이 어떤 정책 기본값에서 나오는지 파일에 설명이 없습니다. DEFAULT_MAX_ENCODED_CONTENT_BYTES, DEFAULT_MAX_CHUNK_COUNT, DEFAULT_MAX_TRAILER_SECTION_BYTES 중 하나가 바뀌면 이 테스트는 실패합니다. 그때 어떤 입력이 바뀌었는지, 새 기대값이 무엇이어야 하는지 알 수 없습니다.

산출식을 주석으로 남기거나, 정책 기본값에서 기대값을 유도하십시오. 라인 8의 18 MiB 상한 어서션은 그대로 유지하십시오. 그 어서션이 실제 불변식을 표현합니다.

♻️ 산출 근거를 남기는 형태
 #[test]
 fn default_chunked_wire_prefix_stays_below_eighteen_mib() {
-    let maximum = maximum_chunked_wire_bytes(&HttpClientPolicy::strict_defaults());
-    assert_eq!(maximum, 18_104_340);
+    let policy = HttpClientPolicy::strict_defaults();
+    let maximum = maximum_chunked_wire_bytes(&policy);
+    // 인코딩된 콘텐츠 상한에 청크별 크기 줄과 CRLF 오버헤드, 그리고 trailer 구간 상한을
+    // 더한 값입니다. 정확한 항은 `maximum_chunked_wire_bytes`의 정의를 따릅니다.
+    assert_eq!(maximum, 18_104_340);
+    assert!(maximum > policy.max_encoded_content_bytes());
     assert!(maximum < 18 * 1024 * 1024);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/tests/chunked_wire_budget_contract.rs` around
lines 4 - 9, Update default_chunked_wire_prefix_stays_below_eighteen_mib so the
expected 18_104_340 value is derived from or documented against
DEFAULT_MAX_ENCODED_CONTENT_BYTES, DEFAULT_MAX_CHUNK_COUNT, and
DEFAULT_MAX_TRAILER_SECTION_BYTES. Preserve the 18 MiB upper-bound assertion
unchanged.
tests/test_repository_contract.py (2)

124-129: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

실패 메시지에 문서 이름을 포함하십시오.

이 반복문은 두 문서를 같은 어서션으로 검사합니다. 어서션에 msg 인자가 없습니다. 검사가 실패하면 ADR과 설계 문서 중 어느 쪽이 원인인지 알 수 없습니다. 라인 81-88의 기존 반복문은 relative를 전달하여 이 문제를 피합니다. 같은 방식을 적용하십시오.

♻️ 문서 이름을 전달하는 수정
-        for text in [adr, design]:
-            self.assertIn("originweave-http", text)
-            self.assertIn("HTTP/1.1", text)
-            self.assertIn("AuthenticatedTlsConnection", text)
-            self.assertIn("never follow", text.lower())
-            self.assertIn("RFC 9112", text)
+        for relative, text in [
+            ("docs/adr/0007-bounded-http11-semantics.md", adr),
+            ("docs/superpowers/specs/2026-08-07-http11-semantics-design.md", design),
+        ]:
+            self.assertIn("originweave-http", text, relative)
+            self.assertIn("HTTP/1.1", text, relative)
+            self.assertIn("AuthenticatedTlsConnection", text, relative)
+            self.assertIn("never follow", text.lower(), relative)
+            self.assertIn("RFC 9112", text, relative)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_repository_contract.py` around lines 124 - 129, Update the
assertions in the loop over adr and design to include a msg identifying the
current document, matching the existing loop pattern that passes relative.
Preserve all assertion checks and use the loop’s document-name variable so
failures distinguish the ADR from the design document.

62-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

required_paths에 새 문서를 추가하십시오.

tests/test_repository_contract.pyrequired_paths에 다음 경로를 추가하십시오.

  • docs/adr/0008-http-reason-phrase-diagnostics.md
  • docs/superpowers/specs/2026-08-08-http11-reason-phrase-addendum.md

현재 테스트는 두 파일이 삭제되어도 통과합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_repository_contract.py` around lines 62 - 70, Update the
required_paths collection in tests/test_repository_contract.py to include
docs/adr/0008-http-reason-phrase-diagnostics.md and
docs/superpowers/specs/2026-08-08-http11-reason-phrase-addendum.md, preserving
the existing required path entries.
crates/originweave-http/src/policy.rs (1)

79-97: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

동일 타입 위치 인자 14개는 builder 또는 설정 구조체로 대체하십시오.

newusize 인자 13개를 연속으로 받습니다. 인접 인자를 바꿔 전달해도 각 값이 자기 상한 이내이면 검증을 통과합니다. 따라서 잘못된 정책이 조용히 생성될 수 있습니다. #[allow(clippy::too_many_arguments)]는 이 위험을 숨깁니다.

HttpClientPolicy::strict_defaults()를 기준으로 하는 builder, 또는 이름이 있는 입력 구조체를 도입하십시오. 그러면 각 예산이 이름으로 결합되고 기존 검증 로직은 그대로 유지됩니다.

♻️ 입력 구조체 방식 예시
/// Named resource budgets for one HTTP/1.1 exchange policy.
pub struct HttpClientPolicyBudgets {
    /// Largest serialized request size.
    pub max_request_bytes: usize,
    /// Largest response status-line size.
    pub max_status_line_bytes: usize,
    // ... 나머지 예산 필드
}

impl HttpClientPolicy {
    /// Validate every time, count, byte, and expansion budget.
    pub fn from_budgets(
        exchange_timeout: Duration,
        budgets: HttpClientPolicyBudgets,
        alpn_policy: AlpnHttp11Policy,
        integrity_requirement: IntegrityRequirement,
    ) -> Result<Self, HttpError> {
        // 기존 validate_limit 호출을 그대로 재사용합니다.
        todo!()
    }
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/policy.rs` around lines 79 - 97, Replace the
positional usize parameters in HttpClientPolicy::new with a named budgets
structure or builder, using HttpClientPolicy::strict_defaults() as the baseline.
Bind each limit by field name, remove the too_many_arguments allowance, and
preserve the existing validation logic by routing the new constructor through
the same validate_limit checks.
crates/originweave-http/src/tests/region_contract.rs (1)

67-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

확장자 매핑 결과를 어서션하십시오.

이 테스트는 parse_content_disposition을 호출하고 결과를 두 번 언랩한 뒤 버립니다. 어서션이 없습니다. 테스트 이름은 모든 확장자 매핑을 검증한다고 말하지만, 실제로는 수락 여부만 확인합니다.

관측 MIME은 classify_observed_mime(b"plain text", None)로 고정되어 있어 text/plain입니다. 따라서 notes.txtpage.html은 서로 다른 extension_mime_relation 값을 만들어야 합니다. 현재는 두 결과가 같아져도 테스트가 통과합니다.

각 확장자에 기대하는 extension_mime_relation을 함께 두고 어서션하십시오. 같은 문제로 crates/originweave-http/src/tests/coverage_contract.rs의 MIME 테스트가 이전 리뷰에서 지적되었고 수정되었습니다.

💚 기대 매핑을 고정하는 형태
-    for filename in [
-        "page.html",
-        "page.htm",
+    let cases: &[(&str, ExtensionMimeRelation)] = &[
+        ("page.html", ExtensionMimeRelation::Mismatched),
+        ("page.htm", ExtensionMimeRelation::Mismatched),
+        ("notes.txt", ExtensionMimeRelation::Consistent),
+        ("README", ExtensionMimeRelation::Unknown),
         // ... 나머지 확장자에 기대 관계를 붙입니다.
-    ] {
-        let value = format!("attachment; filename={filename}");
-        parse_content_disposition(
-            &fields(&[("content-disposition", value.as_bytes())]),
-            &observed,
-        )
-        .expect("safe mapped filename")
-        .expect("disposition");
-    }
+    ];
+    for (filename, expected_relation) in cases {
+        let value = format!("attachment; filename={filename}");
+        let disposition = parse_content_disposition(
+            &fields(&[("content-disposition", value.as_bytes())]),
+            &observed,
+        )
+        .expect("safe mapped filename")
+        .expect("disposition");
+        assert_eq!(
+            disposition.extension_mime_relation(),
+            *expected_relation,
+            "filename {filename}"
+        );
+    }

정확한 변형 이름과 기대값은 crates/originweave-http/src/disposition.rs의 실제 매핑 규칙에 맞추어 채우십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/tests/region_contract.rs` around lines 67 - 96,
Update every_filename_extension_mapping_is_exercised_before_download_handoff to
pair each filename with the expected extension_mime_relation value from
disposition.rs, then capture the parse_content_disposition result and assert
that relation for each case. Preserve the existing successful parsing assertions
while ensuring notes.txt and page.html produce distinct expected relations under
the fixed text/plain observed MIME.
crates/originweave-http/src/tests/coverage_contract.rs (1)

233-248: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

오류 어서션이 타입을 고정하지 않습니다. 세 곳의 반복문과 테스트가 is_err()만 확인합니다. 반환되는 HttpError 변형은 확인하지 않습니다. 각 입력은 서로 다른 오류 종류를 겨냥하므로, 파서가 이들을 하나의 오류로 뭉뚱그려도 테스트는 통과합니다. PR 목표는 결정적이고 타입이 지정된 실패를 요구합니다.

  • crates/originweave-http/src/tests/coverage_contract.rs#L233-L248: 12개 응답 입력 각각에 기대 HttpError 변형을 붙이고 assert!(matches!(...))로 어서션하십시오. 같은 파일 라인 255-283이 이미 이 방식을 사용합니다.
  • crates/originweave-http/src/tests/coverage_contract.rs#L293-L303: 7개 chunked 본문 입력 각각에 기대 변형을 붙이십시오. 라인 300의 금지된 trailer 필드 사례는 chunk 오류가 아니라 trailer 오류로 고정하십시오.
  • crates/originweave-http/src/tests/region_contract.rs#L362-L371: parse_chunked_body가 trailer 구간 크기 오류를 반환하는지 어서션하십시오. 현재는 Incomplete가 아닌 임의의 오류도 통과합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/tests/coverage_contract.rs` around lines 233 -
248, Replace broad is_err() assertions with assert!(matches!(...)) assertions
that verify the expected HttpError variant for every case. In
crates/originweave-http/src/tests/coverage_contract.rs:233-248, assign a
specific expected variant to each of the 12 parse_response_head inputs; also do
so for each of the 7 chunked-body inputs at lines 293-303, classifying the
prohibited trailer-field case as a trailer error. In
crates/originweave-http/src/tests/region_contract.rs:362-371, assert that
parse_chunked_body returns the trailer-section size error rather than merely any
error, following the existing typed assertion pattern around lines 255-283.
crates/originweave-http/src/evidence.rs (1)

358-362: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

response_complete는 항상 true입니다.

From<EvidenceInput>가 이 필드를 상수 true로 설정합니다. 증거는 성공 경로에서만 생성되므로 이 접근자는 값을 구분하지 못합니다. 공개 API 소비자는 이 값이 변할 수 있다고 오해할 수 있습니다.

두 가지 중 하나를 선택하십시오. 첫째, 문서에 "이 값은 항상 true입니다"를 명시합니다. 둘째, 미래에 부분 완료 증거가 필요하지 않다면 필드와 접근자를 제거합니다.

Also applies to: 437-437

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/evidence.rs` around lines 358 - 362, Update the
documentation for response_complete to explicitly state that it is always true
because EvidenceInput initializes the field to the constant true, or remove the
field and response_complete accessor if partial completion is not intended to be
supported; keep the public API consistent with the chosen behavior.
crates/originweave-http/tests/error_contract.rs (1)

14-160: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

변형 목록이 컴파일 시점에 강제되지 않습니다.

HttpError 변형을 추가해도 이 테스트는 계속 통과합니다. 목록은 수동 유지 보수에 의존합니다.

목록 순회 후 각 오류에 대해 모든 변형을 나열하는 match를 수행하십시오. 그러면 변형 추가 시 컴파일이 실패하고 테스트 갱신이 강제됩니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/tests/error_contract.rs` around lines 14 - 160,
Update the test around every_public_http_error_has_a_nonempty_operator_message
so each error is exhaustively matched against all HttpError variants after the
list is constructed. Use a wildcard-free match to enforce compile-time coverage,
while retaining the existing nonempty-message assertion and requiring future
variants to be added to the test cases.
scripts/ci/verify_coverage.py (1)

13-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

진단 목록의 절단이 표시되지 않습니다.

다섯 개 함수가 결과를 MAX_REGION_DIAGNOSTICS(100)개로 자릅니다. 오류 메시지는 절단 사실을 표시하지 않습니다. 미커버 영역이 100개를 넘으면 운영자는 목록이 전부라고 오해할 수 있습니다.

목록 길이가 한계에 도달하면 메시지에 "…(추가 N개 생략)"과 같은 표시를 추가하십시오. 게이트 동작은 변하지 않습니다.

Also applies to: 304-323

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/verify_coverage.py` at line 13, Update the five
diagnostic-producing functions that truncate results at MAX_REGION_DIAGNOSTICS
to append an omission marker such as "…(추가 N개 생략)" when more entries exist,
where N is the omitted count. Preserve the existing diagnostic content and gate
behavior when no entries are omitted.
crates/originweave-http/tests/framing_integration.rs (1)

37-236: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

loopback TLS 테스트 하니스가 다섯 파일에 중복됩니다. 인증 기관 생성, 리프 인증서 생성, ServerConfig 구성, origin_for, direct_connection, authenticated_connection, 정책 빌더가 거의 동일하게 반복됩니다. 공통 원인은 공유 테스트 지원 모듈이 없다는 점입니다. 이 때문에 read_requestUnexpectedEof 처리처럼 동작이 파일마다 갈라집니다.

crates/originweave-http/tests/common/mod.rs를 추가하고 각 파일이 이를 사용하도록 정리하십시오.

  • crates/originweave-http/tests/framing_integration.rs#L37-L236: 인증서·서버·연결·정책 헬퍼를 공용 모듈로 옮기고, read_request 구현을 공용 버전으로 사용하십시오.
  • crates/originweave-http/tests/exchange_integration.rs#L39-L179: 동일 헬퍼를 공용 모듈에서 가져오고, ALPN 값만 매개변수로 전달하십시오.
  • crates/originweave-http/tests/exchange_region_integration.rs#L42-L203: 동일 헬퍼를 공용 모듈에서 가져오고, policy_with_timeout을 공용 정책 빌더로 대체하십시오.
  • crates/originweave-http/tests/transport_failure_integration.rs#L44-L218: 동일 헬퍼를 공용 모듈에서 가져오고, policy_with_exchange_timeout을 공용 정책 빌더로 대체하십시오.
  • crates/originweave-http/tests/chunked_persistence_integration.rs#L38-L243: 동일 헬퍼를 공용 모듈에서 가져오고, 서버 스레드 오류 처리를 공용 ServerResult 방식으로 통일하십시오.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/tests/framing_integration.rs` around lines 37 - 236,
Extract the duplicated loopback TLS test harness into a new shared
tests/common/mod.rs, including certificate creation, server configuration,
origin_for, direct_connection, authenticated_connection, the shared policy
builder, and read_request with consistent UnexpectedEof handling. In
crates/originweave-http/tests/framing_integration.rs#L37-236, replace the local
helpers with the shared module; do the same in
crates/originweave-http/tests/exchange_integration.rs#L39-179 while passing ALPN
as a parameter,
crates/originweave-http/tests/exchange_region_integration.rs#L42-203 by
replacing policy_with_timeout, and
crates/originweave-http/tests/transport_failure_integration.rs#L44-218 by
replacing policy_with_exchange_timeout. In
crates/originweave-http/tests/chunked_persistence_integration.rs#L38-243, use
the shared helpers and standardize server-thread errors through ServerResult.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/originweave-http/Cargo.toml`:
- Line 5: Update the workspace rust-version configuration inherited by all
crates to the exact string "1.97.1", replacing the current workspace reference
in the Cargo.toml configuration.

In `@crates/originweave-http/src/chunked.rs`:
- Around line 105-110: Update the trailer parsing path around find_crlf so an
over-budget trailer section is mapped from ChunkLineTooLarge to
TrailerSectionTooLarge, preserving the trailer budget as maximum_bytes. Keep
other find_crlf errors and incomplete parsing behavior unchanged.

In `@crates/originweave-http/src/disposition.rs`:
- Around line 316-321: The is_windows_device_name function must also reject
Windows reserved device names ending in superscript digits ¹, ², or ³ for both
COM and LPT prefixes. Extend its matching logic while preserving existing
checks, and add regression cases in the security contract tests for UTF-8
filename* values COM¹.txt and LPT².txt expecting InvalidContentDisposition.

In `@crates/originweave-http/src/exchange.rs`:
- Around line 437-460: Update read_chunked_body to preserve resumable parser
state across reads instead of passing the full wire buffer to parse_chunked_body
from offset zero each time. Track the cursor through completed chunks and resume
parsing from that position after appending new bytes, while retaining
incomplete-chunk state and existing maximum_wire_bytes and response-byte
validation behavior.

In `@crates/originweave-http/src/response_head.rs`:
- Around line 221-231: Remove the local trim_optional_whitespace function from
response_head.rs and reuse the shared crate::field::trim_optional_whitespace
instead. Extend the existing crate::field import in this module to include that
symbol, and update all local call sites to use it; do not modify the shared
implementation or unrelated parsing logic.

In `@crates/originweave-http/src/tests/exchange_error_contract.rs`:
- Around line 1-41: Update the `exchange_error_contract` test-module declaration
in `lib.rs` to apply the `coverage_nightly` `coverage(off)` attribute,
preventing its tests from affecting the exact 100% coverage gate. Also update
the governance coverage check to recognize this `#[path]` module.

In `@crates/originweave-http/tests/exchange_region_integration.rs`:
- Around line 115-121: Update the TLS request-reading loop around `tls.read` to
handle `ErrorKind::UnexpectedEof` as a normal termination, matching
`read_request` in the other integration tests. Preserve the existing behavior
for successful reads, clean EOF, and other errors so `assert_request` does not
fail when the client disconnects without `close_notify`.

In `@crates/originweave-http/tests/request_contract.rs`:
- Around line 144-162: Extend field_name_and_value_sizes_are_bounded to also
assert that RequestField::new accepts a 256-byte name and an 8,192-byte value,
while retaining the existing rejection assertions for 257 and 8,193 bytes. Cover
both sides of each boundary so the maximum values remain valid.

In `@crates/originweave-http/tests/transport_failure_integration.rs`:
- Around line 26-28: Increase EXCHANGE_TIMEOUT from 75 ms to 250 ms in the
transport failure integration tests, matching exchange_region_integration.rs,
and proportionally increase the WriteThenStall delay to 1 second so the test
still exercises the timeout behavior reliably.

In `@tests/test_verify_coverage.py`:
- Around line 149-153: Update the generic_covered region literal in the test
fixture to contain exactly eight elements by removing its trailing 0, matching
the expected LLVM region format and other region literals.

---

Nitpick comments:
In `@crates/originweave-http/src/evidence.rs`:
- Around line 358-362: Update the documentation for response_complete to
explicitly state that it is always true because EvidenceInput initializes the
field to the constant true, or remove the field and response_complete accessor
if partial completion is not intended to be supported; keep the public API
consistent with the chosen behavior.

In `@crates/originweave-http/src/policy.rs`:
- Around line 79-97: Replace the positional usize parameters in
HttpClientPolicy::new with a named budgets structure or builder, using
HttpClientPolicy::strict_defaults() as the baseline. Bind each limit by field
name, remove the too_many_arguments allowance, and preserve the existing
validation logic by routing the new constructor through the same validate_limit
checks.

In `@crates/originweave-http/src/tests/chunked_wire_budget_contract.rs`:
- Around line 4-9: Update default_chunked_wire_prefix_stays_below_eighteen_mib
so the expected 18_104_340 value is derived from or documented against
DEFAULT_MAX_ENCODED_CONTENT_BYTES, DEFAULT_MAX_CHUNK_COUNT, and
DEFAULT_MAX_TRAILER_SECTION_BYTES. Preserve the 18 MiB upper-bound assertion
unchanged.

In `@crates/originweave-http/src/tests/coverage_contract.rs`:
- Around line 233-248: Replace broad is_err() assertions with
assert!(matches!(...)) assertions that verify the expected HttpError variant for
every case. In crates/originweave-http/src/tests/coverage_contract.rs:233-248,
assign a specific expected variant to each of the 12 parse_response_head inputs;
also do so for each of the 7 chunked-body inputs at lines 293-303, classifying
the prohibited trailer-field case as a trailer error. In
crates/originweave-http/src/tests/region_contract.rs:362-371, assert that
parse_chunked_body returns the trailer-section size error rather than merely any
error, following the existing typed assertion pattern around lines 255-283.

In `@crates/originweave-http/src/tests/region_contract.rs`:
- Around line 67-96: Update
every_filename_extension_mapping_is_exercised_before_download_handoff to pair
each filename with the expected extension_mime_relation value from
disposition.rs, then capture the parse_content_disposition result and assert
that relation for each case. Preserve the existing successful parsing assertions
while ensuring notes.txt and page.html produce distinct expected relations under
the fixed text/plain observed MIME.

In `@crates/originweave-http/tests/error_contract.rs`:
- Around line 14-160: Update the test around
every_public_http_error_has_a_nonempty_operator_message so each error is
exhaustively matched against all HttpError variants after the list is
constructed. Use a wildcard-free match to enforce compile-time coverage, while
retaining the existing nonempty-message assertion and requiring future variants
to be added to the test cases.

In `@crates/originweave-http/tests/framing_integration.rs`:
- Around line 37-236: Extract the duplicated loopback TLS test harness into a
new shared tests/common/mod.rs, including certificate creation, server
configuration, origin_for, direct_connection, authenticated_connection, the
shared policy builder, and read_request with consistent UnexpectedEof handling.
In crates/originweave-http/tests/framing_integration.rs#L37-236, replace the
local helpers with the shared module; do the same in
crates/originweave-http/tests/exchange_integration.rs#L39-179 while passing ALPN
as a parameter,
crates/originweave-http/tests/exchange_region_integration.rs#L42-203 by
replacing policy_with_timeout, and
crates/originweave-http/tests/transport_failure_integration.rs#L44-218 by
replacing policy_with_exchange_timeout. In
crates/originweave-http/tests/chunked_persistence_integration.rs#L38-243, use
the shared helpers and standardize server-thread errors through ServerResult.

In `@scripts/ci/verify_coverage.py`:
- Line 13: Update the five diagnostic-producing functions that truncate results
at MAX_REGION_DIAGNOSTICS to append an omission marker such as "…(추가 N개 생략)"
when more entries exist, where N is the omitted count. Preserve the existing
diagnostic content and gate behavior when no entries are omitted.

In `@tests/test_repository_contract.py`:
- Around line 124-129: Update the assertions in the loop over adr and design to
include a msg identifying the current document, matching the existing loop
pattern that passes relative. Preserve all assertion checks and use the loop’s
document-name variable so failures distinguish the ADR from the design document.
- Around line 62-70: Update the required_paths collection in
tests/test_repository_contract.py to include
docs/adr/0008-http-reason-phrase-diagnostics.md and
docs/superpowers/specs/2026-08-08-http11-reason-phrase-addendum.md, preserving
the existing required path entries.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 29497017-d596-415c-a337-a794ef744e0b

📥 Commits

Reviewing files that changed from the base of the PR and between b228693 and 85ec324.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (49)
  • CHANGELOG.md
  • Cargo.toml
  • crates/originweave-http/Cargo.toml
  • crates/originweave-http/src/chunked.rs
  • crates/originweave-http/src/content.rs
  • crates/originweave-http/src/disposition.rs
  • crates/originweave-http/src/error.rs
  • crates/originweave-http/src/evidence.rs
  • crates/originweave-http/src/exchange.rs
  • crates/originweave-http/src/field.rs
  • crates/originweave-http/src/framing.rs
  • crates/originweave-http/src/integrity.rs
  • crates/originweave-http/src/lib.rs
  • crates/originweave-http/src/mime.rs
  • crates/originweave-http/src/policy.rs
  • crates/originweave-http/src/request.rs
  • crates/originweave-http/src/response_head.rs
  • crates/originweave-http/src/target.rs
  • crates/originweave-http/src/tests/chunked_wire_budget_contract.rs
  • crates/originweave-http/src/tests/coverage_contract.rs
  • crates/originweave-http/src/tests/exchange_error_contract.rs
  • crates/originweave-http/src/tests/integrity_padding_contract.rs
  • crates/originweave-http/src/tests/mime_contract.rs
  • crates/originweave-http/src/tests/reachability_contract.rs
  • crates/originweave-http/src/tests/reason_phrase_contract.rs
  • crates/originweave-http/src/tests/region_contract.rs
  • crates/originweave-http/src/tests/security_contract.rs
  • crates/originweave-http/tests/chunked_persistence_integration.rs
  • crates/originweave-http/tests/error_contract.rs
  • crates/originweave-http/tests/exchange_integration.rs
  • crates/originweave-http/tests/exchange_region_integration.rs
  • crates/originweave-http/tests/framing_integration.rs
  • crates/originweave-http/tests/policy_contract.rs
  • crates/originweave-http/tests/request_contract.rs
  • crates/originweave-http/tests/response_failure_regressions.rs
  • crates/originweave-http/tests/transport_failure_integration.rs
  • docs/adr/0007-bounded-http11-semantics.md
  • docs/adr/0008-http-reason-phrase-diagnostics.md
  • docs/doctoring.md
  • docs/doctoring/http-chunked-message-boundary.md
  • docs/doctoring/http-reason-phrase-diagnostics.md
  • docs/doctoring/http11-security-evidence.md
  • docs/superpowers/plans/2026-08-07-http11-semantics.md
  • docs/superpowers/specs/2026-08-07-http11-semantics-design.md
  • docs/superpowers/specs/2026-08-08-http11-reason-phrase-addendum.md
  • scripts/ci/verify_coverage.py
  • tests/test_http_governance.py
  • tests/test_repository_contract.py
  • tests/test_verify_coverage.py

Comment thread crates/originweave-http/Cargo.toml
Comment thread crates/originweave-http/src/chunked.rs
Comment thread crates/originweave-http/src/disposition.rs
Comment on lines +437 to +460
loop {
match parse_chunked_body(&wire, policy)? {
ChunkParseResult::Complete(result) => {
if result.consumed != wire.len() {
return Err(HttpError::UnexpectedResponseBytes {
byte_count: wire.len() - result.consumed,
});
}
return Ok(result);
}
ChunkParseResult::Incomplete => {}
}

let remaining_capacity = maximum_wire_bytes.saturating_sub(wire.len());
let mut scratch = [0_u8; IO_BUFFER_BYTES];
let read_limit = remaining_capacity.saturating_add(1).min(scratch.len());
let byte_count = require_read_progress(read_with_deadline(
connection,
&mut scratch[..read_limit],
deadline,
timeout,
)?)?;
extend_chunked_wire(&mut wire, &scratch[..byte_count], maximum_wire_bytes)?;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

청크 본문을 매 읽기마다 처음부터 다시 파싱합니다.

parse_chunked_body는 항상 커서 0에서 시작합니다. read_chunked_body는 읽기마다 누적된 전체 wire를 다시 넘깁니다. 그래서 파싱 비용이 수신 바이트 수에 대해 이차적으로 증가합니다.

기본 정책에서 maximum_chunked_wire_bytes는 수천만 바이트 규모이고, 읽기 단위는 IO_BUFFER_BYTES(8 KiB)입니다. 그러면 재파싱 횟수는 수천 회이고, 각 회차가 누적 버퍼 전체를 다시 스캔합니다. 이는 bounded exchange의 CPU 예산을 약화합니다.

재개 가능한 파서 상태를 유지하십시오. 최소한 이미 완결된 청크까지의 커서를 보존하고, 다음 호출에서 그 지점부터 스캔하십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/exchange.rs` around lines 437 - 460, Update
read_chunked_body to preserve resumable parser state across reads instead of
passing the full wire buffer to parse_chunked_body from offset zero each time.
Track the cursor through completed chunks and resume parsing from that position
after appending new bytes, while retaining incomplete-chunk state and existing
maximum_wire_bytes and response-byte validation behavior.

Comment on lines +221 to +231
fn trim_optional_whitespace(value: &[u8]) -> &[u8] {
let start = value
.iter()
.position(|byte| !matches!(byte, b' ' | b'\t'))
.unwrap_or(value.len());
let end = value
.iter()
.rposition(|byte| !matches!(byte, b' ' | b'\t'))
.map_or(start, |index| index + 1);
&value[start..end]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

중복된 trim_optional_whitespace를 제거하고 crate::field의 공유 함수를 사용하십시오.

이 함수는 crates/originweave-http/src/field.rs 라인 238-248의 pub(crate) fn trim_optional_whitespace와 본문이 동일합니다. crates/originweave-http/src/mime.rs 라인 427-437에도 같은 사본이 있습니다. 사본은 세 개입니다.

crates/originweave-http/src/framing.rs는 이미 공유 함수를 가져와 사용합니다. 이 파일도 라인 3에서 crate::field를 가져오므로 심볼 하나만 추가하면 됩니다. 세 개의 파서가 같은 wire 데이터를 처리하므로, 사본이 서로 달라지면 OWS 처리 결과가 갈라집니다.

♻️ 공유 함수로 통합하는 수정
-use crate::field::{FieldBlock, FieldLine, FieldSyntaxError};
+use crate::field::{FieldBlock, FieldLine, FieldSyntaxError, trim_optional_whitespace};
-fn trim_optional_whitespace(value: &[u8]) -> &[u8] {
-    let start = value
-        .iter()
-        .position(|byte| !matches!(byte, b' ' | b'\t'))
-        .unwrap_or(value.len());
-    let end = value
-        .iter()
-        .rposition(|byte| !matches!(byte, b' ' | b'\t'))
-        .map_or(start, |index| index + 1);
-    &value[start..end]
-}
-

코딩 가이드라인에 따라: "Rust crates must remain independently understandable and reusable."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn trim_optional_whitespace(value: &[u8]) -> &[u8] {
let start = value
.iter()
.position(|byte| !matches!(byte, b' ' | b'\t'))
.unwrap_or(value.len());
let end = value
.iter()
.rposition(|byte| !matches!(byte, b' ' | b'\t'))
.map_or(start, |index| index + 1);
&value[start..end]
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/response_head.rs` around lines 221 - 231, Remove
the local trim_optional_whitespace function from response_head.rs and reuse the
shared crate::field::trim_optional_whitespace instead. Extend the existing
crate::field import in this module to include that symbol, and update all local
call sites to use it; do not modify the shared implementation or unrelated
parsing logic.

Source: Coding guidelines

Comment on lines +1 to +41
#![allow(clippy::expect_used)]

use std::io;

use crate::HttpError;

fn restoration_failure() -> HttpError {
HttpError::TimeoutRestorationFailed {
source: io::Error::other("expected restoration failure"),
}
}

#[test]
fn primary_exchange_failure_precedes_timeout_restoration_failure() {
let result = crate::exchange::combine_exchange_and_restoration(
Err::<usize, _>(HttpError::IncompleteResponse),
Err(restoration_failure()),
);
assert!(matches!(result, Err(HttpError::IncompleteResponse)));
}

#[test]
fn restoration_failure_is_reported_after_a_successful_exchange() {
let result = crate::exchange::combine_exchange_and_restoration(
Ok::<usize, HttpError>(42),
Err(restoration_failure()),
);
assert!(matches!(
result,
Err(HttpError::TimeoutRestorationFailed { .. })
));
}

#[test]
fn successful_exchange_and_restoration_preserve_the_response() {
assert_eq!(
crate::exchange::combine_exchange_and_restoration(Ok::<usize, HttpError>(42), Ok(()))
.expect("successful exchange and restoration"),
42
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify the #[path]-included test modules carry cfg(test) and coverage(off).
set -euo pipefail

rg -n -B 4 -A 1 '#\[path = "tests/' crates/originweave-http/src/lib.rs

Repository: ContextualWisdomLab/OriginWeave

Length of output: 1317


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- module declarations ---'
sed -n '1,65p' crates/originweave-http/src/lib.rs

printf '%s\n' '--- governance test references ---'
rg -n -A 20 -B 8 'coverage_nightly|inline test module|path.*tests/' tests crates/originweave-http

Repository: ContextualWisdomLab/OriginWeave

Length of output: 29991


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- coverage configuration and commands ---'
rg -n -i -C 3 'llvm-cov|coverage_nightly|coverage\(off\)|grcov|tarpaulin|100%|production coverage' . \
  -g '!target' -g '!node_modules'

printf '%s\n' '--- path-included test modules and coverage attributes ---'
python3 - <<'PY'
from pathlib import Path
import re

path = Path("crates/originweave-http/src/lib.rs")
lines = path.read_text(encoding="utf-8").splitlines()
for i, line in enumerate(lines):
    if '#[path = "tests/' in line:
        context = lines[max(0, i - 2):i + 2]
        print(f"{i + 1}: " + " | ".join(context))
PY

Repository: ContextualWisdomLab/OriginWeave

Length of output: 40279


exchange_error_contract를 프로덕션 커버리지에서 제외하십시오.

crates/originweave-http/src/lib.rs:26의 선언에 #[cfg_attr(coverage_nightly, coverage(off))]가 없습니다. 정확한 100% 커버리지 게이트가 이 테스트 모듈을 포함할 수 있으므로 속성을 추가하고, 거버넌스 검사에도 해당 #[path] 모듈을 포함하십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/src/tests/exchange_error_contract.rs` around lines 1
- 41, Update the `exchange_error_contract` test-module declaration in `lib.rs`
to apply the `coverage_nightly` `coverage(off)` attribute, preventing its tests
from affecting the exact 100% coverage gate. Also update the governance coverage
check to recognize this `#[path]` module.

Comment on lines +115 to +121
while !request.windows(4).any(|window| window == b"\r\n\r\n") {
match tls.read(&mut scratch) {
Ok(0) => break,
Ok(count) => request.extend_from_slice(&scratch[..count]),
Err(error) => return Err(error.to_string()),
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

요청 읽기 루프에서 TLS UnexpectedEof를 처리하지 않습니다.

crates/originweave-http/tests/framing_integration.rsread_requestcrates/originweave-http/tests/transport_failure_integration.rs의 동일 루프는 ErrorKind::UnexpectedEof를 정상 종료로 처리합니다. 이 파일의 루프는 해당 분기를 생략합니다. 클라이언트가 close_notify 없이 연결을 끊으면 서버 스레드가 Err를 반환합니다. 그러면 assert_requestexpect("server exchange")가 패닉하고 테스트가 불안정해집니다.

동일한 분기를 추가하여 동작을 일치시키십시오.

🛠️ 제안 수정
         while !request.windows(4).any(|window| window == b"\r\n\r\n") {
             match tls.read(&mut scratch) {
                 Ok(0) => break,
                 Ok(count) => request.extend_from_slice(&scratch[..count]),
+                Err(error) if error.kind() == std::io::ErrorKind::UnexpectedEof => {
+                    if request.is_empty() {
+                        break;
+                    }
+                    return Err(error.to_string());
+                }
                 Err(error) => return Err(error.to_string()),
             }
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while !request.windows(4).any(|window| window == b"\r\n\r\n") {
match tls.read(&mut scratch) {
Ok(0) => break,
Ok(count) => request.extend_from_slice(&scratch[..count]),
Err(error) => return Err(error.to_string()),
}
}
while !request.windows(4).any(|window| window == b"\r\n\r\n") {
match tls.read(&mut scratch) {
Ok(0) => break,
Ok(count) => request.extend_from_slice(&scratch[..count]),
Err(error) if error.kind() == std::io::ErrorKind::UnexpectedEof => {
if request.is_empty() {
break;
}
return Err(error.to_string());
}
Err(error) => return Err(error.to_string()),
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/tests/exchange_region_integration.rs` around lines
115 - 121, Update the TLS request-reading loop around `tls.read` to handle
`ErrorKind::UnexpectedEof` as a normal termination, matching `read_request` in
the other integration tests. Preserve the existing behavior for successful
reads, clean EOF, and other errors so `assert_request` does not fail when the
client disconnects without `close_notify`.

Comment on lines +144 to +162
#[test]
fn field_name_and_value_sizes_are_bounded() {
let long_name = "a".repeat(257);
assert!(matches!(
RequestField::new(&long_name, b"value"),
Err(HttpError::RequestFieldNameTooLarge {
byte_count: 257,
maximum_bytes: 256,
})
));
let long_value = vec![b'a'; 8_193];
assert!(matches!(
RequestField::new("x-test", &long_value),
Err(HttpError::RequestFieldValueTooLarge {
byte_count: 8_193,
maximum_bytes: 8_192,
})
));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

허용 경계값도 함께 검증하십시오.

이 테스트는 거부 측(257바이트 이름, 8_193바이트 값)만 확인합니다. 허용 측(256바이트 이름, 8_192바이트 값)은 확인하지 않습니다. FieldLine::new의 비교 연산자가 >에서 >=로 바뀌어도 이 테스트는 통과합니다. 라인 79-93의 요청 대상 테스트는 양쪽 경계를 모두 확인합니다. 같은 방식을 적용하십시오.

💚 경계 쌍을 추가하는 수정
 fn field_name_and_value_sizes_are_bounded() {
+    let exact_name = "a".repeat(256);
+    assert!(RequestField::new(&exact_name, b"value").is_ok());
     let long_name = "a".repeat(257);
     assert!(matches!(
         RequestField::new(&long_name, b"value"),
         Err(HttpError::RequestFieldNameTooLarge {
             byte_count: 257,
             maximum_bytes: 256,
         })
     ));
+    let exact_value = vec![b'a'; 8_192];
+    assert!(RequestField::new("x-test", &exact_value).is_ok());
     let long_value = vec![b'a'; 8_193];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[test]
fn field_name_and_value_sizes_are_bounded() {
let long_name = "a".repeat(257);
assert!(matches!(
RequestField::new(&long_name, b"value"),
Err(HttpError::RequestFieldNameTooLarge {
byte_count: 257,
maximum_bytes: 256,
})
));
let long_value = vec![b'a'; 8_193];
assert!(matches!(
RequestField::new("x-test", &long_value),
Err(HttpError::RequestFieldValueTooLarge {
byte_count: 8_193,
maximum_bytes: 8_192,
})
));
}
#[test]
fn field_name_and_value_sizes_are_bounded() {
let exact_name = "a".repeat(256);
assert!(RequestField::new(&exact_name, b"value").is_ok());
let long_name = "a".repeat(257);
assert!(matches!(
RequestField::new(&long_name, b"value"),
Err(HttpError::RequestFieldNameTooLarge {
byte_count: 257,
maximum_bytes: 256,
})
));
let exact_value = vec![b'a'; 8_192];
assert!(RequestField::new("x-test", &exact_value).is_ok());
let long_value = vec![b'a'; 8_193];
assert!(matches!(
RequestField::new("x-test", &long_value),
Err(HttpError::RequestFieldValueTooLarge {
byte_count: 8_193,
maximum_bytes: 8_192,
})
));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/tests/request_contract.rs` around lines 144 - 162,
Extend field_name_and_value_sizes_are_bounded to also assert that
RequestField::new accepts a 256-byte name and an 8,192-byte value, while
retaining the existing rejection assertions for 257 and 8,193 bytes. Cover both
sides of each boundary so the maximum values remain valid.

Comment on lines +26 to +28
const TRUSTED_TIME_SECONDS: u64 = 1_767_225_600;
const TEST_TIMEOUT: Duration = Duration::from_secs(3);
const EXCHANGE_TIMEOUT: Duration = Duration::from_millis(75);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

75 ms 교환 타임아웃은 부하가 큰 CI에서 불안정할 수 있습니다.

EXCHANGE_TIMEOUTexecute() 시작 시점부터 계산합니다. 러너 부하가 크면 TLS 요청 쓰기 단계에서 데드라인이 만료될 수 있습니다. 그 경우 서버는 완전한 요청을 받지 못하고 assert_server_received_requestexpect("server exchange")가 패닉합니다.

crates/originweave-http/tests/exchange_region_integration.rs는 같은 이유로 이미 250 ms를 사용합니다. 이 파일도 같은 값으로 맞추고 WriteThenStall 지연을 비례해서 늘리십시오. 예: 250 ms 타임아웃과 1초 지연.

🛠️ 제안 수정
-const EXCHANGE_TIMEOUT: Duration = Duration::from_millis(75);
+const EXCHANGE_TIMEOUT: Duration = Duration::from_millis(250);
-        ServerBehavior::WriteThenStall(response, Duration::from_millis(300)),
+        ServerBehavior::WriteThenStall(response, Duration::from_secs(1)),
         policy_with_exchange_timeout(EXCHANGE_TIMEOUT),

Also applies to: 259-288

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/originweave-http/tests/transport_failure_integration.rs` around lines
26 - 28, Increase EXCHANGE_TIMEOUT from 75 ms to 250 ms in the transport failure
integration tests, matching exchange_region_integration.rs, and proportionally
increase the WriteThenStall delay to 1 second so the test still exercises the
timeout behavior reliably.

Comment on lines +149 to +153
{
"name": "generic_covered",
"filenames": ["src/partial.rs"],
"regions": [[42, 9, 42, 15, 3, 0, 0, 0, 0]],
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

영역 리터럴의 원소 개수가 다릅니다.

generic_covered의 영역은 원소가 9개입니다. 다른 모든 영역 리터럴은 8개입니다. _function_region_locationsregion[:8]만 사용하므로 테스트는 통과합니다. 그러나 이 리터럴은 LLVM 영역 형식과 맞지 않고 오타로 보입니다.

마지막 0을 제거하여 8개 원소로 맞추십시오.

🛠️ 제안 수정
-                "regions": [[42, 9, 42, 15, 3, 0, 0, 0, 0]],
+                "regions": [[42, 9, 42, 15, 3, 0, 0, 0]],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
"name": "generic_covered",
"filenames": ["src/partial.rs"],
"regions": [[42, 9, 42, 15, 3, 0, 0, 0, 0]],
},
{
"name": "generic_covered",
"filenames": ["src/partial.rs"],
"regions": [[42, 9, 42, 15, 3, 0, 0, 0]],
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_verify_coverage.py` around lines 149 - 153, Update the
generic_covered region literal in the test fixture to contain exactly eight
elements by removing its trailing 0, matching the expected LLVM region format
and other region literals.

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.

[Product Gap] Bound HTTP/1.1 semantics over the authenticated TLS stream

2 participants