diff --git a/README.md b/README.md
index 0d95425b..389d48a6 100644
--- a/README.md
+++ b/README.md
@@ -1123,6 +1123,24 @@ on demand without changing them.
These helpers expose credentials metadata only. RTTP does not evaluate CORS
requests, attach credentials to requests, or grant credentials automatically.
+### Bounded Access-Control-Allow-Private-Network response metadata
+
+`Response::access_control_allow_private_network()` parses a singleton
+`Access-Control-Allow-Private-Network` response field into bounded
+`AccessControlAllowPrivateNetwork` metadata. The value is the exact,
+case-sensitive `true` token after surrounding SP and HTAB trimming and is
+serialized canonically as `true`. Empty, malformed, duplicate, control-byte,
+or over-64-KiB values return an error while raw response fields remain
+available through `Response::header_value()` and `Response::header_values()`.
+
+On the server, `HttpAccessControlAllowPrivateNetwork::parse()` validates the
+same syntax, `HttpResponse::with_access_control_allow_private_network()`
+replaces same-name fields only after successful validation, and
+`HttpResponse::access_control_allow_private_network()` parses attached fields
+without changing them. These helpers expose metadata only; RTTP does not grant
+private-network access, decide preflight behavior, or apply CORS or Private
+Network Access policy.
+
### Bounded NEL response metadata
`Response::nel()` parses the `NEL` response field as bounded W3C Network Error
@@ -1865,8 +1883,9 @@ gain additional HTTP/2 header-block handling.
| X-Forwarded compatibility metadata | Client `x_forwarded_for`, `x_forwarded_host`, and `x_forwarded_proto` emit bounded compatibility request metadata through shared protocol types; server `Request`/`HttpRequest` helpers parse ordered node, authority, and scheme values while preserving raw headers on errors | No forwarded identity trust, client address selection, routing rewrite, scheme rewrite, redirect, upgrade, enforcement, or trusted-proxy selection; applications must choose trusted proxies |
| Via | Client `via` emits bounded HTTP `Via` hop metadata through the shared protocol type; `Response::via` parses received hops; server `Request`/`HttpRequest` helpers and `HttpResponse::with_via`/`via` parse or declare caller-supplied chains while preserving raw headers on errors | No automatic hop insertion or removal, trusted-proxy inference, identity rewrite, or HTTP/1.1 or HTTP/2 proxy-policy changes |
| Accept-Language | Client `accept_language` emits bounded `Accept-Language` request metadata through the protocol `AcceptLanguage` type; server `Request::accept_language()` and `HttpRequest::accept_language()` parse typed received values as `HttpAcceptLanguages` while preserving raw headers on errors | No locale matching, fallback selection, translation lookup, routing, or automatic response choice |
-| Preflight request metadata | Client `origin`, `access_control_request_method`, `access_control_request_headers`, and `access_control_request_private_network` emit bounded `Origin`, `Access-Control-Request-Method`, `Access-Control-Request-Headers`, and `Access-Control-Request-Private-Network` request metadata and reject invalid input before connecting | No automatic preflight decision, `Access-Control-Allow-*` response parsing, CORS policy, or Private Network Access policy |
+| Preflight request metadata | Client `origin`, `access_control_request_method`, `access_control_request_headers`, and `access_control_request_private_network` emit bounded `Origin`, `Access-Control-Request-Method`, `Access-Control-Request-Headers`, and `Access-Control-Request-Private-Network` request metadata and reject invalid input before connecting | No automatic preflight decision, CORS policy, or Private Network Access policy |
| Access-Control-Allow-Credentials | Client `Response::access_control_allow_credentials` and server `HttpAccessControlAllowCredentials`, `HttpResponse::with_access_control_allow_credentials`, and `HttpResponse::access_control_allow_credentials` parse or declare bounded singleton `Access-Control-Allow-Credentials` `true`-token metadata while preserving raw headers on parse failures | No CORS request evaluation, automatic credential attachment, or automatic credentials granting |
+| Access-Control-Allow-Private-Network | Client `Response::access_control_allow_private_network` and server `HttpAccessControlAllowPrivateNetwork`, `HttpResponse::with_access_control_allow_private_network`, and `HttpResponse::access_control_allow_private_network` parse or declare bounded singleton `Access-Control-Allow-Private-Network` `true`-token metadata while preserving raw headers on parse failures | No private-network access grant, preflight decision, CORS policy, or Private Network Access policy |
| Digest preferences | `want_content_digest`, `want_content_digest_with_q`, `want_repr_digest`, and `want_repr_digest_with_q` emit bounded `Want-Content-Digest` and `Want-Repr-Digest` request metadata; server `Request::want_content_digest()`, `HttpRequest::want_content_digest()`, `Request::want_repr_digest()`, and `HttpRequest::want_repr_digest()` parse received preference fields | No algorithm selection, digest computation, response body hash validation, retries, or signing |
| Accept-Encoding | Client `accept_encoding`, `accept_encoding_with_q`, and gzip/deflate/br/identity helpers format bounded `Accept-Encoding` request metadata through the shared `rttp-protocol` type; server `Request::accept_encoding()` and `HttpRequest::accept_encoding()` parse received fields into `HttpRequestAcceptEncodings` | No compression, decompression, content negotiation, retries, or transport changes |
| Upgrade and tunnel handoff | `CONNECT` returns the tunnel socket after a successful `200`; `upgrade()` returns the socket after `101 Switching Protocols` and skips interim `1xx` responses | Upgraded protocols are handed to the caller and are not parsed by `rttp_client` |
diff --git a/crates/rttp-client/README.md b/crates/rttp-client/README.md
index 448768e0..3fb57853 100644
--- a/crates/rttp-client/README.md
+++ b/crates/rttp-client/README.md
@@ -1329,8 +1329,22 @@ retain raw-header control with `header(("Origin", "..."))` and the other
`header` forms.
These are declaration helpers only. RTTP does not decide whether a preflight
-is needed, read `Access-Control-Allow-*` response fields, apply CORS policy, or
-apply Private Network Access policy.
+is needed, apply CORS policy, or apply Private Network Access policy.
+
+## Bounded Access-Control-Allow-Private-Network response metadata
+
+`Response::access_control_allow_private_network()` parses a singleton
+`Access-Control-Allow-Private-Network` response field through the shared
+`AccessControlAllowPrivateNetwork` protocol type. The value is the exact,
+case-sensitive `true` token with surrounding SP or HTAB trimmed and canonical
+lowercase `true` serialization. Values and duplicate fields are bounded and
+validated to reject malformed, control-byte, and oversized input. Absent
+metadata returns `Ok(None)`; parse errors leave the original raw field
+available through `Response::header_value()` and `Response::header_values()`.
+
+This accessor exposes response metadata only. It does not grant private-network
+access, decide whether a preflight is needed, apply CORS policy, or apply
+Private Network Access policy.
## Bounded Save-Data request metadata
@@ -1802,7 +1816,8 @@ header-block model.
| W3C Baggage | `baggage` validates and emits bounded W3C Baggage request metadata through the shared protocol type, replacing an existing same-name field and redacting member and property values from typed debug output | No application-data interpretation, request-context storage, tracing backend, span model, or automatic propagation |
| CDN-Loop | `cdn_loop` validates and emits bounded RFC 8586 `CDN-Loop` request metadata through the shared protocol type, combining an existing same-name field with the new member in wire order and rejecting malformed or oversized values before connecting | No CDN identifier insertion, loop detection or rejection, automatic forwarding, or hop-by-hop handling |
| Via | `via` validates and emits bounded HTTP `Via` request metadata through the shared protocol type, combining an existing same-name field with the new hops in wire order and rejecting malformed or oversized values before connecting; `Response::via` parses received hop chains while preserving raw headers on parse failures | No automatic hop insertion or removal, trusted-proxy inference, identity rewrite, or HTTP/1.1 or HTTP/2 proxy-policy changes |
-| Preflight request metadata | `origin`, `access_control_request_method`, `access_control_request_headers`, and `access_control_request_private_network` emit bounded `Origin`, `Access-Control-Request-Method`, `Access-Control-Request-Headers`, and `Access-Control-Request-Private-Network` request metadata and reject invalid input before connecting | No automatic preflight decision, `Access-Control-Allow-*` response parsing, CORS policy, or Private Network Access policy |
+| Preflight request metadata | `origin`, `access_control_request_method`, `access_control_request_headers`, and `access_control_request_private_network` emit bounded `Origin`, `Access-Control-Request-Method`, `Access-Control-Request-Headers`, and `Access-Control-Request-Private-Network` request metadata and reject invalid input before connecting | No automatic preflight decision, CORS policy, or Private Network Access policy |
+| Access-Control-Allow-Private-Network | `Response::access_control_allow_private_network` parses bounded singleton `Access-Control-Allow-Private-Network` `true` metadata while preserving raw headers on parse failures | No private-network access grant, preflight decision, CORS policy, or Private Network Access policy |
| Digest preferences | `want_content_digest`, `want_content_digest_with_q`, `want_repr_digest`, and `want_repr_digest_with_q` emit bounded `Want-Content-Digest` and `Want-Repr-Digest` request metadata; server `Request::want_content_digest()`, `HttpRequest::want_content_digest()`, `Request::want_repr_digest()`, and `HttpRequest::want_repr_digest()` parse received preference fields | No algorithm selection, digest computation, response body hash validation, retries, or signing |
| Accept | `accept` and `accept_with_q` format bounded `Accept` request metadata through the shared `rttp-protocol` type, replacing existing same-name fields after validating helper-built and existing raw values | No content negotiation, representation selection, MIME sniffing, body decoding, cache `Vary` synthesis, or response choice |
| Accept-Charset | `accept_charset` and `accept_charset_with_q` format bounded `Accept-Charset` request metadata through the shared `rttp-protocol` type | No content negotiation, charset transcoding, body decoding, MIME sniffing, or response selection |
diff --git a/crates/rttp-client/src/response/mod.rs b/crates/rttp-client/src/response/mod.rs
index 5d749dc3..75672832 100644
--- a/crates/rttp-client/src/response/mod.rs
+++ b/crates/rttp-client/src/response/mod.rs
@@ -46,6 +46,9 @@ pub use rttp_protocol::access_control_allow_methods::{
pub use rttp_protocol::access_control_allow_origin::{
AccessControlAllowOrigin, AccessControlAllowOriginParseError,
};
+pub use rttp_protocol::access_control_allow_private_network::{
+ AccessControlAllowPrivateNetwork, AccessControlAllowPrivateNetworkParseError,
+};
pub use rttp_protocol::access_control_expose_headers::{
AccessControlExposeHeaders, AccessControlExposeHeadersParseError,
};
diff --git a/crates/rttp-client/src/response/response.rs b/crates/rttp-client/src/response/response.rs
index 40b82cd2..17e97cec 100644
--- a/crates/rttp-client/src/response/response.rs
+++ b/crates/rttp-client/src/response/response.rs
@@ -45,6 +45,7 @@ use rttp_protocol::access_control_allow_credentials::AccessControlAllowCredentia
use rttp_protocol::access_control_allow_headers::AccessControlAllowHeaders;
use rttp_protocol::access_control_allow_methods::AccessControlAllowMethods;
use rttp_protocol::access_control_allow_origin::AccessControlAllowOrigin;
+use rttp_protocol::access_control_allow_private_network::AccessControlAllowPrivateNetwork;
use rttp_protocol::access_control_expose_headers::AccessControlExposeHeaders;
use rttp_protocol::access_control_max_age::AccessControlMaxAge;
use rttp_protocol::age::Age;
@@ -687,6 +688,20 @@ impl Response {
.map_err(|parse_error| error::bad_response(parse_error.to_string()))
}
+ /// Parses bounded `Access-Control-Allow-Private-Network` response metadata
+ /// without applying Private Network Access or CORS policy.
+ pub fn access_control_allow_private_network(
+ &self,
+ ) -> error::Result