Commit Graph

12 Commits

Author SHA1 Message Date
iomgaa 152fa264ed feat: parse EXTRA_BODY as a JSON object per source 2026-07-31 21:12:06 -04:00
iomgaa afd6101c08 test: cover the env-key messages left unguarded by mutation testing
Mutation testing showed the negative structured-retries and expected-dim checks
in the env parsing path could be deleted with every test still passing. Their
value is the env key name in the message, so they need tests that assert it.

Changelog now states the real scope of this release and warns that normalising
scope moves the Redis keys, the one change here that silently relocates runtime
state. Records the breaker threshold derivation as deliberately env-only so it
does not resurface as another round.
2026-07-30 02:31:51 -04:00
iomgaa 726f26d8bd fix: normalise scope and blank strings on the construction path too
The verifier found four more env-only behaviours of the same class the branch
was already fixing. The worst is scope: it goes straight into the Redis keys
(pgw:limit:{scope}, pgw:gate:{scope}), so one process using from_env("LLM")
and another constructing scope="LLM" by hand split the rate limit and breaker
state across two namespaces, each tracking its own quota, with no error.

Blank redis_url and pricing_path now collapse to None as from_env has always
done, so they fall into the required-field checks instead of reaching the redis
client as an unparseable URL. EmbeddingSettings gains the __post_init__ it never
had, moving its batch_size and expected_dim checks off the from_env-only path.

Also adds the cache backend whitelist test that mutation testing showed missing.
2026-07-30 02:15:32 -04:00
iomgaa c9fdff9d55 fix: keep credentials out of the DSN rewrite warning
The warning added earlier in this branch logged the whole Postgres DSN, password
included, and nothing else in the library has ever printed a connection string.
It now reports only the scheme segment, which is the part that actually changed.

Regression test asserts the password and host/path never reach the log.
2026-07-30 01:13:45 -04:00
iomgaa a65b504a3d fix: consolidate remaining assembly validation into GatewaySettings
Round two of the from_env-only validation problem. Fifteen checks still lived
in the env parsing functions: six enum domains, the redis_url requirement for
redis-backed limiter/breaker/cache, cache namespace and TTL, telemetry path and
DSN, non-negative structured retries and non-blank scope. from_settings and
direct construction bypassed all of them.

The five asserts in client.py that claimed config had already validated
redis_url and the telemetry targets now hold on every path, so they revert to
what CLAUDE.md permits: internal invariant declarations that also narrow the
Optional for type checkers. Their comments now name the method that guarantees
them, since the previous wording is exactly what went stale.

Postgres DSNs built by hand now get the SQLAlchemy +driver suffix stripped the
way from_env has always stripped it, with a warning so the rewrite is not
silent. The env path strips earlier, so it stays quiet.
2026-07-30 00:58:33 -04:00
iomgaa b8f738f8cb fix: enforce cross-field settings invariants on every construction path
The lease, stall and probe-TTL guards only ran inside GatewaySettings.from_env,
so from_settings() and direct construction could produce settings that violate
the class's own invariants: the permit lease could expire mid-request (silently
exceeding the concurrency quota), a normal slow first token could be killed as a
stall, and a half-open probe could be taken over while still in flight.

Guards move into __post_init__ as _validate_* methods, matching every frozen
dataclass in types.py, so all six factories plus dataclasses.replace are covered
by one check. Adds a non-empty sources invariant that previously only from_env
enforced. Messages now name fields instead of env keys, since callers who build
settings by hand never set those keys.
2026-07-30 00:04:33 -04:00
iomgaa 1231226205 feat: add OcrSettings scope configuration 2026-07-21 22:45:12 -04:00
iomgaa 6b98a89bb3 feat: default two structured re-asks and sharper AIMD cut
Round 5 left three residual failure classes; ladder exhaustion (3.2%
of structured calls with a single re-ask) and 429 leakage (5.8%, AIMD
oscillating above the sustainable point) are addressable: re-ask
default goes 1 to 2 (conservative vs instructor's 3) and the AIMD cut
factor drops to 0.5.
2026-07-21 12:52:32 -04:00
iomgaa e1678e4ff5 style: format M2.5 breaker changes 2026-07-21 09:11:56 -04:00
iomgaa 72b25724d8 feat: add rate-channel breaker config and health_aware default
Threshold auto-raise now uses per-source concurrency only (the M2
global-concurrency formula neutered the breaker at scale). Four new
optional keys: MIN_CALLS, FAIL_RATE, WINDOW_S, MAX_COOLDOWN_S.
2026-07-21 08:49:36 -04:00
iomgaa acc1bcc18a feat: unlock redis/postgres backend config with assembly guards 2026-07-21 00:18:42 -04:00
iomgaa 7b9815f4bc feat: add gateway client with env-driven assembly
Includes config aggregation for multi-source env keys, from_env and
from_settings factories with explicit shared-backend injection,
gather_bounded, top-level exports, tightened import-linter layers with
the gate removed from the Makefile, and the finalized .env.example.
2026-07-20 07:47:05 -04:00