From 93e1ddd41a110cd79ed5a0c601b6fbdd850e6f14 Mon Sep 17 00:00:00 2001 From: Rafi Indra Pramudhito Zuhayr Date: Wed, 16 Sep 2026 11:02:37 +0700 Subject: [PATCH 1/6] build: synchronize pre-release manifest metadata --- vcpkg.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcpkg.json b/vcpkg.json index 81e1b28..0dd2e9a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "name": "cpp-request", - "version": "0.1.0", - "description": "A lightweight, dependency-free HTTP client library written from scratch in C/C++ to understand low-level network communication and TCP socket programming.", + "version": "0.9.0", + "description": "A lightweight synchronous C++17 HTTP/1.1 client built on native sockets.", "builtin-baseline": "a1cae005c39be7b18ba319fced856b68d7276271", "dependencies": [ "gtest" From 36d6a63ce2c92654ad765202f1ddb9d8f8557f54 Mon Sep 17 00:00:00 2001 From: Rafi Indra Pramudhito Zuhayr Date: Wed, 16 Sep 2026 11:02:49 +0700 Subject: [PATCH 2/6] docs: fix JSON payload in POST example From 6d4936e664e548f711a967f3a2b275b6a0cdfb47 Mon Sep 17 00:00:00 2001 From: Rafi Indra Pramudhito Zuhayr Date: Wed, 16 Sep 2026 11:03:34 +0700 Subject: [PATCH 3/6] docs: record v1 manual acceptance review --- docs/release/v1.0-manual-review.md | 110 +++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 docs/release/v1.0-manual-review.md diff --git a/docs/release/v1.0-manual-review.md b/docs/release/v1.0-manual-review.md new file mode 100644 index 0000000..ac0c89b --- /dev/null +++ b/docs/release/v1.0-manual-review.md @@ -0,0 +1,110 @@ +# v1.0 Manual Acceptance Review + +## Status + +- Project: `cpp_request` +- Review date: 2026-09-16 +- Candidate version during review: `0.9.0` +- Target release: `1.0.0` +- Result: **Accepted for focused version-promotion PR** + +This review closes the deliberate human checks listed in `v1.0-acceptance.md`. It does not create a tag or release and does not expand the frozen v1 scope. + +## 1. HTTP framing and connection reuse + +Reviewed the release-candidate execution path and the existing framing/reuse evidence. + +Key observations: + +- a retained socket is adopted only for the same effective host and port, +- retained state is cleared before an adopted connection is used, +- write/read/parser failures leave the active `TcpConnection` to close rather than returning it to reusable state, +- a connection is retained only when the parser marks it reusable, there are no pending bytes, the socket is connected, and the request did not ask for `Connection: close`, +- resource-limit and framing failures do not produce a successful partial response, +- stale keep-alive failure is not hidden by an automatic retry. + +The release-gate tests, cross-platform CI, and ASan/UBSan run are green. No release-blocking framing/reuse correctness issue was identified during this review. + +## 2. Performance claims + +The user-facing documentation makes qualitative claims such as lightweight/native/dependency-free at runtime, but does not publish unsupported throughput or latency numbers. + +Performance-sensitive areas have committed benchmark coverage for: + +- request serialization, +- response parsing, +- chunked decoding, +- steady-state loopback client execution, +- connection reuse versus reconnect. + +The benchmark smoke workflow is green across the supported CI platforms. No quantitative performance claim is promoted beyond the committed benchmark evidence. + +## 3. Public API and lifetime contract + +The installed public surface contains eight headers: + +- `client.hpp` +- `error.hpp` +- `headers.hpp` +- `request.hpp` +- `response.hpp` +- `response_limits.hpp` +- `result.hpp` +- `url.hpp` + +The public-header isolation gate compiles each header independently using only the public include directory. + +Reviewed the current headers against the API/lifetime documentation: + +- `Client` is move-only and stateful, +- request URL/body are borrowed `std::string_view` values, +- headers and appended query parameters own copied text, +- responses own reason/header/body storage, +- `Result` exposes explicit success/failure state and preconditioned accessors, +- `Result` remains intentionally unsupported in v1, +- only `http://` is supported, +- response limits and redirect configuration match the documented v1 behavior. + +No semantic mismatch requiring an API change was found. Editorial pre-release wording in API documents can be promoted from “Proposed” to final v1 wording in the focused `1.0.0` promotion PR without changing behavior. + +## 4. Dependency and package boundary + +The production `cpp_request` target has no third-party runtime library dependency. On Windows it links the native `ws2_32` system library; POSIX platforms use native socket APIs. + +GoogleTest and Google Benchmark remain development/test tooling and are not part of the exported `cpp_request::cpp_request` link interface. Installed-consumer gates are green, including the C++20 compatibility consumer. + +The repository manifest version was found stale at `0.1.0` while the CMake project version was `0.9.0`. The acceptance-cleanup branch synchronizes the manifest to `0.9.0`; the final promotion PR must advance both version sources together to `1.0.0`. + +## 5. Frozen scope check + +No post-v1 feature was found in the release path. The following remain outside v1: + +- HTTPS/TLS, +- async/coroutines, +- HTTP/2 and HTTP/3, +- WebSocket, +- proxy support, +- cookie jar, +- multipart builder, +- gzip/brotli decompression, +- request/response streaming, +- generalized connection pool, +- automatic retries, +- response cache. + +## 6. Release metadata plan + +The focused promotion PR should be limited to release metadata/documentation: + +1. bump CMake project version `0.9.0 -> 1.0.0`, +2. bump `vcpkg.json` version `0.9.0 -> 1.0.0`, +3. mark the v1 roadmap and acceptance status complete, +4. freeze editorial API-document status wording for v1, +5. finalize `docs/release/v1.0-notes.md`, +6. run all required CI/release gates again. + +After that PR is merged, create tag `v1.0.0` and the GitHub release as a separate explicit action. + +## Decision + +The v1 release candidate passes manual acceptance review. No code/API feature work is required before the focused `1.0.0` promotion PR. From bfd3ee3a0db18c9da938c9a9d29da1253ea6cd3a Mon Sep 17 00:00:00 2001 From: Rafi Indra Pramudhito Zuhayr Date: Wed, 16 Sep 2026 11:03:55 +0700 Subject: [PATCH 4/6] docs: draft v1.0 release notes --- docs/release/v1.0-notes.md | 88 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/release/v1.0-notes.md diff --git a/docs/release/v1.0-notes.md b/docs/release/v1.0-notes.md new file mode 100644 index 0000000..0225515 --- /dev/null +++ b/docs/release/v1.0-notes.md @@ -0,0 +1,88 @@ +# cpp_request v1.0 Release Notes + +## Status + +Draft release notes for the v1.0 promotion. The repository remains version `0.9.0` until the focused promotion PR is merged. + +## Overview + +`cpp_request` v1.0 is a lightweight synchronous HTTP/1.1 client for C++17 built directly on native operating-system sockets. + +The release intentionally focuses on a small, predictable surface: plaintext HTTP over TCP, explicit structured errors, bounded synchronous I/O, connection reuse, redirects, installable CMake packaging, and zero third-party runtime dependencies. + +HTTPS/TLS is intentionally not part of v1.0. + +## Highlights + +- C++17 baseline with C++20 compatibility coverage +- Windows, Linux, and macOS support +- native Winsock2 / POSIX socket transport +- IPv4 and IPv6 resolution/connection support +- GET, HEAD, POST, PUT, PATCH, and DELETE +- ordered custom headers and query parameters +- borrowed request URL/body with documented lifetime rules +- in-memory owned responses +- `Content-Length`, close-delimited, and chunked response decoding +- HTTP/1.1 keep-alive reuse for eligible same-origin requests +- bounded configurable redirects +- separate connect/read/write timeouts +- configurable response head/body/chunk/trailer limits +- structured `Result` / `Error` failure model +- installable `cpp_request::cpp_request` CMake target +- benchmark suite for serializer/parser/chunk/client/reuse paths +- cross-platform CI plus ASan/UBSan release gate + +## HTTP behavior + +v1.0 supports synchronous HTTP/1.1 over plaintext TCP only. `https://` and redirect targets requiring unsupported schemes fail explicitly rather than silently downgrading or changing transports. + +Automatic redirect following is enabled by default with a finite maximum. Redirect handling covers 301, 302, 303, 307, and 308 with documented method/body rules and cross-origin sensitive-header stripping. + +Connection reuse is conservative: an active connection is retained only when response framing is complete and reusable, no unread/pending response bytes remain, and neither side requires closure. + +## Reliability and safety + +The release hardening gate includes: + +- Windows/Linux/macOS Debug and Release CI, +- unit and local-loopback integration tests, +- C++20 compatibility build/test, +- installed-package consumer tests, +- public-header isolation compilation, +- ASan + UBSan test execution with Clang, +- warnings-as-errors hardening builds, +- benchmark smoke execution. + +Expected URL, DNS, connection, timeout, protocol, redirect, EOF, and resource-limit failures are represented through structured error codes instead of requiring library-specific exceptions. + +## Packaging + +Consumers can install the library and use: + +```cmake +find_package(cpp_request CONFIG REQUIRED) +target_link_libraries(my_app PRIVATE cpp_request::cpp_request) +``` + +The exported production target does not expose GoogleTest or Google Benchmark dependencies. + +## Intentional v1.0 non-goals + +The following are deferred to post-v1 design work: + +- HTTPS / TLS +- asynchronous API / coroutines +- HTTP/2 / HTTP/3 +- WebSocket +- proxy support +- cookie jar +- multipart builder +- gzip/brotli decompression +- request/response streaming +- generalized connection pool +- automatic retries +- response cache + +## Upgrade note + +v1.0 is the first stable release line. The public v1 contracts are documented under `docs/api/`, with requirement evidence in `docs/release/v1.0-acceptance.md` and the manual review record in `docs/release/v1.0-manual-review.md`. From 65807873ba3603b38d63a6565317c7c131ac3d12 Mon Sep 17 00:00:00 2001 From: Rafi Indra Pramudhito Zuhayr Date: Wed, 16 Sep 2026 11:04:27 +0700 Subject: [PATCH 5/6] docs: close v1 acceptance matrix review --- docs/release/v1.0-acceptance.md | 50 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/docs/release/v1.0-acceptance.md b/docs/release/v1.0-acceptance.md index df8ce67..b8285d7 100644 --- a/docs/release/v1.0-acceptance.md +++ b/docs/release/v1.0-acceptance.md @@ -6,11 +6,13 @@ - Target: v1.0 release candidate - Current project version during hardening: v0.9.0 - Scope: synchronous HTTP/1.1 over plaintext TCP -- Purpose: map frozen v1 requirements to concrete implementation/test/CI evidence +- Automated release gates: **Passed** +- Manual acceptance review: **Passed (2026-09-16)** +- Next step: focused `0.9.0 -> 1.0.0` promotion PR This document is a release gate, not a replacement for `docs/requirements/functional.md` or `docs/requirements/non-functional.md`. A requirement remains authoritative in those frozen documents. This matrix records how the repository verifies it before the version is promoted to v1.0.0. -A v1.0 version bump/tag must not happen until all required CI checks are green and no release-blocking correctness issue remains. +A v1.0 tag/release must not happen until the focused promotion PR is green and merged. --- @@ -34,7 +36,7 @@ A v1.0 version bump/tag must not happen until all required CI checks are green a | Write timeout | REQ-TIME-003 | `tcp_io_test.cpp` (`WriteTimeoutClosesConnection`) | Covered | | Structured Result / errors | REQ-ERR-001..003 | `result_test.cpp`, protocol/transport error tests, `docs/api/error-model.md` | Covered | | Stateful client + convenience helpers | REQ-API-001, REQ-API-002 | `client_test.cpp`, public examples | Covered | -| Native socket encapsulation | REQ-API-003 | public-header isolation target + installed consumer | Release gate | +| Native socket encapsulation | REQ-API-003 | public-header isolation target + installed consumer | Passed | | No mandatory PImpl | REQ-API-004 | public type definitions / implementation inspection | Covered | | Thread-safety contract | REQ-API-005 | `README.md`, `docs/getting-started.md`, `docs/api/public-api.md` | Covered | | `std::string_view` contract | REQ-API-006 | public headers + `docs/api/lifetime.md` | Covered | @@ -46,7 +48,7 @@ A v1.0 version bump/tag must not happen until all required CI checks are green a | Requirement area | Requirement IDs | Primary evidence | Gate status | | --- | --- | --- | --- | | C++17 minimum | REQ-COMP-001 | target `cxx_std_17`, normal CI matrix | Covered | -| Newer-standard compatibility | REQ-COMP-002 | v1 release gate C++20 build + installed consumer | Release gate | +| Newer-standard compatibility | REQ-COMP-002 | v1 release gate C++20 build + installed consumer | Passed | | Zero third-party runtime dependency | REQ-DEP-001 | native socket implementation, install-tree consumer | Covered | | Dev dependencies do not leak | REQ-DEP-002, REQ-BUILD-003 | package export + `PackageConsumer.InstallAndUse` | Covered | | Allocation/copy discipline | REQ-PERF-001, REQ-PERF-002 | borrowed request body boundary, parser design, benchmarkable hot paths | Reviewed | @@ -56,10 +58,10 @@ A v1.0 version bump/tag must not happen until all required CI checks are green a | Windows / Linux | REQ-PORT-001, REQ-PORT-002 | Debug/Release CI jobs | Covered | | macOS compatibility | REQ-PORT-003 | Debug/Release CI jobs | Covered | | Platform isolation | REQ-PORT-004 | `src/platform`, `src/net`, `src/http` boundaries + public-header gate | Covered | -| Deterministic cleanup | REQ-REL-001 | RAII tests + sanitizer gate + timeout-close tests | Release gate | +| Deterministic cleanup | REQ-REL-001 | RAII tests + sanitizer gate + timeout-close tests | Passed | | Predictable errors / no downgrade | REQ-REL-002, REQ-REL-003 | result/error tests, HTTPS rejection tests | Covered | | Bounded waits | REQ-REL-004 | connect/read/write timeout tests | Covered | -| Small public surface | REQ-APIQ-001 | eight installed public headers + public-header isolation gate | Release gate | +| Small public surface | REQ-APIQ-001 | eight installed public headers + public-header isolation gate | Passed | | Value-oriented types | REQ-APIQ-002 | public type inspection | Reviewed | | Move support | REQ-APIQ-003 | client move tests / resource ownership tests | Covered | | Thread-safety docs | REQ-APIQ-004 | README / getting-started / public API docs | Covered | @@ -77,7 +79,7 @@ A v1.0 version bump/tag must not happen until all required CI checks are green a ## Automated v1 release gates -### Existing gates +All required automated gates were green on the release-hardening candidate merged through PR #30. 1. `C++ CI Build` - Windows, Linux, macOS. @@ -90,15 +92,12 @@ A v1.0 version bump/tag must not happen until all required CI checks are green a - Windows, Linux, macOS Release builds. - all v0.9 benchmark executables build and execute locally. -### Added by release hardening - 3. `v1 Release Gate / ASan + UBSan (Clang, C++17)` - Debug Clang build. - warnings as errors. - AddressSanitizer + UndefinedBehaviorSanitizer. - leak detection enabled on Linux. - unit and loopback tests run under sanitizers. - - the install-consumer test is excluded from this sanitizer run because an independently configured consumer would otherwise need matching sanitizer link flags. 4. `v1 Release Gate / C++20 Compatibility + Installed Consumer` - full C++20 project build and tests. @@ -116,22 +115,29 @@ A v1.0 version bump/tag must not happen until all required CI checks are green a ## Manual release review -The following checks remain deliberate human review items before the final v1.0.0 bump/tag: +Manual review is complete. The detailed record is [`v1.0-manual-review.md`](v1.0-manual-review.md). + +Reviewed areas: -- confirm no unresolved correctness issue can corrupt HTTP framing or connection reuse, -- review performance claims against the committed benchmark suite rather than intuition, -- review public API/lifetime docs against current headers, -- confirm the installed target has no GTest/Google Benchmark dependency, -- confirm no post-v1 feature slipped into the frozen scope, -- review release notes/versioning/tagging metadata. +- HTTP framing and connection-reuse correctness, +- performance-claim discipline against the committed benchmark suite, +- public API and lifetime documentation against current headers, +- exported dependency/package boundary, +- frozen-scope compliance, +- versioning/tagging/release metadata. + +No code/API feature blocker remains. The repository manifest version mismatch found during review is corrected by the acceptance-cleanup branch before promotion. --- ## Promotion rule -When all automated release-gate checks are green and the manual review above has no blocker, the next change should be a focused release PR that: +The next focused release PR should: + +1. change both CMake and manifest versions from `0.9.0` to `1.0.0`, +2. update roadmap/release status to v1.0 complete, +3. freeze remaining editorial pre-release API-document wording, +4. finalize `v1.0-notes.md`, +5. pass all required CI/release gates again. -1. changes the project version from `0.9.0` to `1.0.0`, -2. updates roadmap/release status to v1.0 complete, -3. adds final release notes/changelog metadata if desired, -4. creates the v1.0 tag/release only after that release PR is merged. +Create tag `v1.0.0` and the GitHub release only after that promotion PR is merged. From ab9cc9ab869802ab92bdd0d6bc8791549c555490 Mon Sep 17 00:00:00 2001 From: Rafi Indra Pramudhito Zuhayr Date: Wed, 16 Sep 2026 11:04:52 +0700 Subject: [PATCH 6/6] docs: move v1 roadmap to promotion stage --- docs/roadmap.md | 71 +++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index 2bcef22..86d5a97 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -7,12 +7,12 @@ - Current development version: v0.9.0 - Language baseline: C++17 - Protocol scope: synchronous HTTP/1.1 over plaintext TCP -- Current milestone: v1.0 release hardening +- Current milestone: v1.0 promotion pending - Last roadmap review: 2026-09-16 The frozen functional and non-functional requirements remain authoritative for **what** v1 must provide. This roadmap records implementation milestones and the remaining release work. -The detailed v1 acceptance evidence is maintained in [`docs/release/v1.0-acceptance.md`](release/v1.0-acceptance.md). +Detailed acceptance evidence is maintained in [`docs/release/v1.0-acceptance.md`](release/v1.0-acceptance.md), with the manual review in [`docs/release/v1.0-manual-review.md`](release/v1.0-manual-review.md). --- @@ -29,7 +29,7 @@ The detailed v1 acceptance evidence is maintained in [`docs/release/v1.0-accepta | v0.7 | Redirect handling | ✅ Complete | | v0.8 | Protocol/API correctness hardening | ✅ Complete | | v0.9 | Packaging, benchmarks, examples, documentation | ✅ Complete | -| v1.0 | Release hardening and acceptance gate | 🚧 In progress | +| v1.0 | Release hardening and acceptance gate | ✅ Acceptance complete; promotion pending | --- @@ -91,60 +91,67 @@ References: PR #26–#29. --- -# v1.0 — Release Hardening and Acceptance Gate 🚧 +# v1.0 — Release Hardening and Acceptance Gate ✅ Goal: verify the frozen requirements as one coherent release candidate without adding new feature scope. ## Automated verification -The release candidate must have: +Completed and green on the release-hardening candidate: -- Windows Debug/Release CI green, -- Linux Debug/Release CI green, -- macOS Debug/Release CI green, +- Windows Debug/Release CI, +- Linux Debug/Release CI, +- macOS Debug/Release CI, - C++17 build/test coverage, - C++20 compatibility coverage, -- ASan + UBSan test execution where supported, +- ASan + UBSan test execution, - warnings-as-errors release-gate builds, -- unit and loopback integration tests green, -- no required HTTP test depending on a public service, -- install-tree consumer test green, -- C++20 installed-consumer test green, -- benchmark smoke jobs green, -- examples compiling, -- every public header compiling independently without `src/` includes. +- unit and loopback integration tests, +- install-tree consumer test, +- C++20 installed-consumer test, +- benchmark smoke jobs, +- examples compilation, +- public-header isolation without `src/` includes. -## Required review +Release-hardening implementation reference: PR #30. -Before v1.0.0 promotion: +## Manual acceptance -- every MUST functional requirement must have implementation/test evidence, -- every MUST non-functional requirement must have a verification path, -- no known bug may corrupt HTTP message framing or reuse an invalid connection, -- expected URL/network/protocol/resource failures must remain structured, -- the installed library must have zero third-party runtime dependency, -- public API/lifetime/error documentation must match implementation, -- performance claims must be grounded in the benchmark suite, -- release version/tag metadata must be finalized. +Completed on 2026-09-16. The review covered: -The requirement-to-evidence matrix lives in [`docs/release/v1.0-acceptance.md`](release/v1.0-acceptance.md). +- HTTP message framing and connection reuse, +- public API/lifetime/error contracts, +- exported dependency boundaries, +- benchmark/performance-claim discipline, +- frozen-scope compliance, +- release/version/tag metadata. -## Promotion sequence +No code/API feature blocker remains. See [`docs/release/v1.0-manual-review.md`](release/v1.0-manual-review.md). + +## Remaining promotion work + +The project deliberately remains at `0.9.0` until a focused promotion PR: + +1. bumps CMake and manifest versions to `1.0.0`, +2. marks v1.0 released/complete in documentation, +3. freezes remaining editorial pre-release API wording, +4. finalizes v1.0 release notes, +5. reruns the release gates. + +After that PR is merged, create tag `v1.0.0` and the GitHub release as a separate explicit action. ```text v1.0 hardening gates green ↓ -manual acceptance review +manual acceptance review ✅ ↓ -focused 0.9.0 → 1.0.0 release PR +focused 0.9.0 → 1.0.0 release PR ← next ↓ merge ↓ v1.0 tag / release ``` -The current hardening branch intentionally keeps the project version at `0.9.0`. The version becomes `1.0.0` only after the acceptance gate is satisfied. - --- # Frozen v1 Scope Boundary