Skip to content

0.10.1 — delta-audit closure (fixes + hardening)#52

Merged
lesnik512 merged 6 commits into
mainfrom
fix/0.10.1-delta-audit
Jun 13, 2026
Merged

0.10.1 — delta-audit closure (fixes + hardening)#52
lesnik512 merged 6 commits into
mainfrom
fix/0.10.1-delta-audit

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Closes the 0.10.0 delta audit (1 High, 6 Medium, 8 Low, 2 nits) as a patch release. No breaking changes; one additive observability field.

Production fixes

  • AsyncTimeout rejects non-finite values (M1): timeout=nan|inf was accepted (<= 0 is False for both) → nondeterministic / never-firing deadline. Now requires a finite positive number.
  • Observability can't break the request path (M2): _emit_event previously called OTel span.add_event(...) unguarded; a raising span propagated into the caller and could strand the circuit breaker permanently in HALF_OPEN. OTel emission now degrades silently on failure (the log record has already fired) — fixed at the root for all middleware.

Observability (additive)

  • Each event log record now carries a structured event field with the event-name string (e.g. event="circuit.opened"). Previously the name reached only OTel span events. Additive — no existing attribute changed.

Test hardening

  • Event names are now asserted (H1): the five stable event strings were previously matched only by message substring (the name never reached the log record), so a rename passed silently. Now asserted via the new event field.
  • Exact retry_after value + clamp (M3); 429-resets-the-failure-streak via the StatusError-success branch (M4); sync probe-release mirror, success_threshold>1 mid-streak probe failure (made discriminating via a mutation check), reset_timeout=0, empty failure_status_codes, failures=1 on probe-reopen (L5–L8).

Docs

  • docs/index.md observability section lists all four loggers + events with levels; CircuitOpenError added to README/index error lists; README logging example surfaces INFO recovery events; OPEN-state lazy-transition wording and the AsyncRetry timeout-knob note corrected (M5, M6, L1–L4, N2).

Verified sound (no change needed)

Async atomicity, sync lock coverage, cross-loop guard, cm.expired() discriminator, exception-clause disjointness, pickle round-trip, export symmetry, and the property/concurrent tests' soundness all hold.

Test Plan

  • just lint-ci clean
  • just test — 569 passed, 100% coverage
  • M2 fix behaviorally verified (raising add_event swallowed; CancelledError still propagates)
  • L6 rewrite verified discriminating via mutation check (removing the success-counter reset fails the test)

🤖 Generated with Claude Code

lesnik512 and others added 6 commits June 13, 2026 15:23
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lure-safe + event field

M1: AsyncTimeout(timeout=nan|inf) was accepted (<=0 is False for both) — now rejected
via `not math.isfinite(timeout) or timeout <= 0`; message updated to "finite number > 0".
M2: _emit_event wraps OTel add_event in contextlib.suppress(Exception) so a broken
exporter cannot strand circuit-breaker state (permanent HALF_OPEN wedge) or break any
request path; CancelledError/KeyboardInterrupt still propagate.
H1 enabler: event_name now emitted as structured "event" field on the log record so
log-based users can filter by event name; OTel add_event attributes unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eset, boundaries, probe-reopen

Closes audit H1, M3, M4, L5-L8: assert the stable event-name strings via the new
record.event field; pin exact retry_after; prove 429 resets the failure streak via
the StatusError-success branch; sync probe-release mirror; success_threshold>1 with
mid-streak probe failure; reset_timeout=0 and empty failure_status_codes; failures=1
on probe-reopen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The prior assertions (handler.calls==7, final 200) held whether or not the
success counter was reset on reopen. Rewrite so a missing reset leaves the
circuit OPEN at the end and the final request is rejected — verified via a
mutation check (removing the reset now fails the test).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, timeout knob)

M5 index observability + new loggers/events; M6 README INFO recovery events;
L1 AsyncRetry 'no timeout knob' now points to AsyncTimeout; L2 CircuitOpenError
in index/README error lists; L3 OPEN-state lazy-transition wording; L4 observability
docstring loggers; N2 note TransportError is foreign to the breaker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit dfd6f55 into main Jun 13, 2026
5 checks passed
@lesnik512 lesnik512 deleted the fix/0.10.1-delta-audit branch June 13, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant