Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
during trusted construction. Timeout-policy subclasses are rejected before
transport dispatch can dynamically invoke an overridden `as_httpcore_timeout()`,
preserving the reviewed finite ceilings as the authoritative configuration.
- Require the connection pool policy to use the exact `EgressConnectionPoolPolicy`
type during trusted construction. Connection-pool policy subclasses are
rejected before subclass-controlled attributes can diverge from reviewed
finite pool capacity and fingerprinting.
- Remove the repository-write publisher from the autonomous product scheduler
and disable hourly scheduler auto-merge. Verified model output now ends at a
short-lived handoff; any pull-request merge remains current-head reviewed and
Expand Down
36 changes: 26 additions & 10 deletions docs/research/connection-pool-resource-limits.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ idle connections, and a five-second idle keep-alive lifetime. Operators can set
smaller or larger finite values for a specific integration without importing
HTTPX private configuration or constructing an HTTPCore-specific object.

At trusted policy construction, `connection_pool_policy` must be the exact
`EgressConnectionPoolPolicy` type. Subclass polymorphism is not a supported
configuration extension mechanism because retaining a subclass would allow
later attribute dispatch to diverge from the finite capacities that were
reviewed and fingerprinted. Integrations that need different limits construct
an exact `EgressConnectionPoolPolicy` with different documented field values
instead. This boundary does not claim EgressWeave sandboxes arbitrary Python
code already executing inside the embedding process.

`max_connections` must be a positive integer or ASCII decimal string.
`max_keepalive_connections` may be zero to retain no idle connections but must
not exceed total capacity. `keepalive_expiry_seconds` must be a finite
Expand Down Expand Up @@ -43,18 +52,20 @@ and portable across standalone and modular integrations.
## Enforcement invariants

1. Both public `EgressPolicy` constructors accept the same immutable pool policy.
2. Total connection capacity is always positive and finite.
3. Idle capacity is finite, may be zero, and cannot exceed total capacity.
4. Idle expiry is finite and non-negative; `None` cannot disable reclamation.
5. Synchronous and asynchronous HTTPCore pools receive the exact normalized
2. Trusted construction accepts only the exact `EgressConnectionPoolPolicy`
type; subclasses are rejected before transport pool values are read.
3. Total connection capacity is always positive and finite.
4. Idle capacity is finite, may be zero, and cannot exceed total capacity.
5. Idle expiry is finite and non-negative; `None` cannot disable reclamation.
6. Synchronous and asynchronous HTTPCore pools receive the exact normalized
values from the policy.
6. No transport imports HTTPX's private `DEFAULT_LIMITS` object.
7. The normalized pool policy participates in deterministic policy and decision
7. No transport imports HTTPX's private `DEFAULT_LIMITS` object.
8. The normalized pool policy participates in deterministic policy and decision
fingerprints without recording live connection state.
8. Defaults, valid environment-style count text, invalid configuration,
relational invariants, sync/async delegation, public API exposure, and
fingerprint drift are covered by offline regression tests with complete
production statement and branch coverage.
9. Defaults, valid environment-style count text, invalid configuration,
relational invariants, exact policy-type enforcement, sync/async delegation,
public API exposure, and fingerprint drift are covered by offline regression
tests with complete production statement and branch coverage.

## Operational guidance

Expand All @@ -67,6 +78,11 @@ and expiry to zero disables reuse and is stricter for retention, but it can
increase connection and TLS-handshake cost; measure that trade-off rather than
assuming it is universally safer.

Applications that previously subclassed `EgressConnectionPoolPolicy` must
migrate to an exact instance and configure the supported finite fields directly.
The exact-type check runs during trusted startup, before a pool or request can
consume those values.

## References

Encode OSS Ltd. (n.d.). *Resource limits*. HTTPX. Retrieved August 5, 2026, from
Expand Down
4 changes: 1 addition & 3 deletions src/egressweave/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,7 @@ def __post_init__(self) -> None:
raise TypeError(
"request_timeout_policy must be an EgressTimeoutPolicy"
)
if not isinstance(
self.connection_pool_policy, EgressConnectionPoolPolicy
):
if type(self.connection_pool_policy) is not EgressConnectionPoolPolicy:
raise TypeError(
"connection_pool_policy must be an EgressConnectionPoolPolicy"
)
Expand Down
52 changes: 52 additions & 0 deletions tests/test_connection_pool_policy_type_boundary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Regression contracts for the exact connection-pool policy type boundary."""

from __future__ import annotations

import pytest

from egressweave import EgressConnectionPoolPolicy, EgressPolicy


class _HostileConnectionPoolPolicy(EgressConnectionPoolPolicy):
"""Model a subclass that changes a reviewed pool limit after construction."""

def __init__(self) -> None:
"""Build valid base state before arming hostile attribute dispatch."""
super().__init__()
object.__setattr__(self, "_armed", True)

def __getattribute__(self, name: str) -> object:
"""Replace the retained connection ceiling after base normalization."""
if name == "max_connections":
try:
armed = object.__getattribute__(self, "_armed")
except AttributeError:
armed = False
if armed:
return 1_000_000_000
return super().__getattribute__(name)


def _hostile_pool_policy() -> EgressConnectionPoolPolicy:
"""Return one valid subclass whose later pool ceiling is dynamically replaced."""
policy = _HostileConnectionPoolPolicy()
assert policy.max_connections == 1_000_000_000
return policy


def test_host_policy_rejects_connection_pool_policy_subclass() -> None:
"""Reject non-exact pool policy types at trusted policy construction."""
with pytest.raises(TypeError, match="connection_pool_policy"):
EgressPolicy.from_hosts(
"api.example.com",
connection_pool_policy=_hostile_pool_policy(),
)


def test_exact_authority_policy_rejects_connection_pool_policy_subclass() -> None:
"""Apply the same exact-type boundary to the authority-pair constructor."""
with pytest.raises(TypeError, match="connection_pool_policy"):
EgressPolicy.from_authorities(
[("api.example.com", 443)],
connection_pool_policy=_hostile_pool_policy(),
)
41 changes: 41 additions & 0 deletions tests/test_connection_pool_policy_type_documentation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Documentation contracts for exact connection-pool policy configuration."""

from __future__ import annotations

from pathlib import Path

REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
POOL_GUIDE_PATH = (
REPOSITORY_ROOT / "docs" / "research" / "connection-pool-resource-limits.md"
)
CHANGELOG_PATH = REPOSITORY_ROOT / "CHANGELOG.md"


def _read(path: Path) -> str:
"""Return one repository text file as normalized UTF-8 text."""
return " ".join(path.read_text(encoding="utf-8").split())


def test_pool_guide_requires_exact_reviewed_policy_type() -> None:
"""Explain why pool-policy subclass polymorphism is not a supported boundary."""
guide = _read(POOL_GUIDE_PATH)

for fragment in (
"exact `EgressConnectionPoolPolicy` type",
"subclass",
"trusted policy construction",
"`connection_pool_policy`",
):
assert fragment in guide


def test_changelog_records_connection_pool_policy_type_hardening() -> None:
"""Expose the pre-1.0 pool-policy integrity tightening to integrators."""
changelog = _read(CHANGELOG_PATH)

for fragment in (
"connection pool policy",
"exact `EgressConnectionPoolPolicy`",
"subclass",
):
assert fragment in changelog
Loading