Metadata-Version: 2.4
Name: hank-sec-egress
Version: 0.2.4
Summary: Shared SEC identity and paced portable or managed HTTP transport
Requires-Python: >=3.10
Requires-Dist: requests<3,>=2.31
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.11; extra == 'dev'
Description-Content-Type: text/markdown

# hank-sec-egress

`hank-sec-egress` owns SEC HTTP identity, URL containment, retry/redirect policy,
and pacing. Its explicit backends serve different deployment contracts:

- `hank_sec_egress.portable.get()` is for independently installed public clients.
  It admits at most one request start per second per process, including redirects.
  It returns HTTP errors without automatic retries or server-directed sleeps,
  preserving MCP worker availability. It honors standard Requests proxy and CA
  environment settings, including destination-specific `NO_PROXY` exclusions on
  redirects, and needs no private host configuration, `fcntl`, or
  `~/.sec_budget`. `SEC_USER_AGENT` overrides the public EDGAR client identity;
  caller-supplied User-Agent headers cannot override this owner.
  Requests owns redirect preparation and cross-origin credential isolation;
  the adapter checks SEC URL containment and paces every actual request hop.
- `hank_sec_egress.get()` / `async_get()` are for managed Unix services. They
  coordinate the version-1 machine limiter at
  `~/.sec_budget/machine_limiter.state`, including socket-write admission.
  They require `SEC_BUDGET_SITE` (`prod` or `dev`), `SEC_USER_AGENT`, and, starting
  with 0.2.0, `SEC_EXPECTED_MACHINE_IDENTITY`. The latter is deployment-owned
  configuration compared against `socket.getfqdn()`; it does not override the
  actual machine identity. No private hostnames ship in the package.

Both APIs require a nonempty product-owned `caller_label`. Both accept only
`sec.gov` URLs, replace caller User-Agent headers, and apply the same compression
and redirect bounds. Managed admission retains its bounded retry count. Managed
consumers may call `effective_headers()` for request-time identity projection.
Limiter implementation classes and mutable
host configuration are not package-root exports.

Public EDGAR MCP submissions metadata deliberately calls SEC directly through
`portable.get()`. Scratch document extraction remains an HTTP call to the hosted
EDGAR API. Managed deployments remain pinned to their existing package versions
until their deployment configuration and dependency locks are updated together.
