Skip to content

refactor: address audit improvements P1–P35 (33 implemented, 2 deferred)#67

Merged
lesnik512 merged 3 commits into
mainfrom
worktree-improvements-p1-p35
Jun 13, 2026
Merged

refactor: address audit improvements P1–P35 (33 implemented, 2 deferred)#67
lesnik512 merged 3 commits into
mainfrom
worktree-improvements-p1-p35

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Summary

Works through the Improvements section of the 2026-06-12 code audit (P1–P35). 33 implemented, each behavior change with a regression test; 2 deferred and 1 skipped, with reasons. Full dockerized suite: 467 passed, 100% coverage; ruff + ty clean.

Producer / command validation

  • P1 empty publish_batch validates the session type up front.
  • P2 a correlation_id kwarg conflicting with headers['correlation_id'] now raises (was silently dropped); the kwarg otherwise wins.
  • P3 encode failures emit the published error metric (encode moved inside the try).
  • P4 OutboxPublishCommand rejects batch-meaningless timer_id / correlation_id.
  • P5 queue validation (non-str / empty / >255) in the command constructor.
  • P6 documents the count=0 convention (error vs timer-conflict).

SQL layer / schema

  • P7 identifier-length guard covers derived index/constraint names, not just the NOTIFY channel.
  • P8 CHECK ((acquired_token IS NULL) = (acquired_at IS NULL)) — a half-set lease is now unrepresentable.
  • P9 timer_id flows into OutboxInnerMessage and the DLQ (column + CTE).
  • P10 delete_with_lease raises if given a dlq_payload with no dlq_table.
  • P11 fetch uses queue = ANY(:queues) for stable SQL / prepared-statement reuse.

Fetch loop

  • P12 positivity validation for fetch intervals / lease_ttl. · P13 reword the "min is a floor" claim. · P14 _on_notify wakes only for served queues. · P15 reword the misleading LISTEN comment. · P16 stop() awaits the cancelled tasks before returning.

Worker / dispatch

  • P17 the outcome metric emits only after a successful flush — lease-lost rows no longer double-count (P34: dlq_written omits exception_type when there's none).
  • P18 a worker _OutboxConfigError is logged + swallowed, not routed through the reconnect/backoff path. · P19 distinct log strings, dead-or removed, clock-skew comment.

Wiring / API

  • P20 snapshot subscribers once in stop(). · P21 foreign-publisher warning names only the decorated queue. · P22 start()-time duplicate-queue check across routers. · P23 retry dataclass __post_init__ validation. · P24 remove dead connect()/disconnect(). · P25 annotate _subscribers as the WeakSet it is. · P26 __aenter__ divergence marker.

Test broker / metrics

  • P28 error-status published total fires at count=0. · P31 feed() rejects naive datetimes. · P32 copy headers at fake boundaries. · P33 document fake-publish session leniency. · P35 reword the "mirrors production" comment.

Deferred / skipped (with reasons)

  • P29 + P30 — deferred (coupled test-infra). P29 dedups FakeOutboxProducer vs _build_fake_publish*; P30's notify-on-feed naturally belongs in the shared helper P29 would extract. Test-only, no behavior/correctness impact — better as a focused follow-up than risking the test broker the whole suite depends on.
  • P27 — skipped. No single static stacklevel is correct for both the direct @broker.subscriber path and the FastAPI-router path (two extra frames).

Test Plan

  • Full dockerized suite (Postgres 17): 467 passed, 100% coverage gate met
  • ruff format + ruff check + ty check clean
  • Every behavior change has a regression test (incl. integration tests for P8/P9/P11)

Follow-up to #61 / #65 / #66. The audit's suspected findings (S1–S5) remain.

🤖 Generated with Claude Code

lesnik512 and others added 3 commits June 13, 2026 11:45
From the 2026-06-12 code audit's improvements section. Each behavior change ships
a regression test; the suite stays at 100% coverage.

Producer / command validation:
- P1 empty publish_batch validates the session type up front.
- P2 a correlation_id kwarg that conflicts with headers['correlation_id'] now
  raises (was silently dropped); the kwarg otherwise wins.
- P3 encode failures emit the published error metric (encode moved into the try).
- P4 OutboxPublishCommand rejects batch-meaningless timer_id / correlation_id.
- P5 queue validation (non-str / empty / >255) in the command constructor.
- P6 documents the count=0 convention (error vs timer-conflict).

SQL layer / schema:
- P7 the identifier-length guard covers derived index/constraint names, not just
  the NOTIFY channel.
- P8 CHECK ((acquired_token IS NULL) = (acquired_at IS NULL)) makes a half-set
  lease unrepresentable.
- P9 timer_id flows into OutboxInnerMessage and the DLQ (column + CTE).
- P10 delete_with_lease raises if given a dlq_payload with no dlq_table.
- P11 fetch uses queue = ANY(:queues) for stable SQL / prepared-statement reuse.

Fetch loop:
- P12 positivity validation for fetch intervals / lease_ttl.
- P13 reword the "min is a floor" claim (jitter is ±50% of the base).
- P14 _on_notify wakes only for queues this subscriber serves.
- P15 reword the misleading LISTEN-connection comment.
- P16 stop() awaits the cancelled tasks before returning.

Worker / dispatch:
- P17 outcome metric emits only after a successful flush (lease-lost no longer
  double-counts); P34 dlq_written omits exception_type when there is none.
- P18 a worker _OutboxConfigError is logged and swallowed, not routed through the
  connection-reconnect/backoff path.
- P19 distinct log strings for the two failure sites; remove a dead `or` in _nack;
  clock-skew comment.

Wiring / API:
- P20 snapshot subscribers once in broker.stop().
- P21 the foreign-publisher warning names only the decorated subscriber's queues.
- P22 a start()-time duplicate-queue check spanning routers.
- P23 retry dataclass __post_init__ validation (jitter, delays, multiplier, caps).
- P24 remove dead OutboxBrokerConfig.connect()/disconnect().
- P25 annotate _subscribers as the WeakSet it actually is.
- P26 add the upstream-divergence marker to __aenter__.
- P27 SKIPPED: no single static stacklevel is correct for both the direct and
  FastAPI-router call paths.

Test broker / metrics:
- P28 published error-status total fires at count=0.
- P31 feed() rejects naive datetimes; P32 copies headers at fake boundaries;
  P33 documents fake-publish session leniency; P35 reword the "mirrors
  production" comment.
- P29 + P30 DEFERRED: coupled test-infra changes (dedup FakeOutboxProducer vs
  _build_fake_publish*, and notify-on-feed which belongs in that shared helper);
  test-only, no behavior impact, better as a focused follow-up than risking the
  test broker the whole suite depends on.

Full dockerized suite: 467 passed, 100% coverage; ruff + ty clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- P22: scope the start()-time duplicate-queue check to overlaps a router
  contributed to. Same-broker duplicates are already flagged at registration
  time, so this avoids warning twice for one mistake (review nit).
- P14: cache the served queues as a frozenset for the NOTIFY-payload filter
  (O(1) membership, intent clearer) instead of scanning the queue list.

P11 verified out-of-band: an EXPLAIN over a populated table confirms the
`queue = ANY(:queues)` form still drives BitmapOr over both partial indexes
(_pending_idx + _lease_idx) — no seq-scan regression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
acked / nacked_retried / nacked_terminal now fire only after the terminal/retry
write lands; a lease-lost row emits lease_lost instead (never a paired ack/nack).
Make that explicit in the event-vocabulary doc so operators understand the
post-P17 behavior change (raised in PR #67 review).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lesnik512
lesnik512 merged commit cbbd8d3 into main Jun 13, 2026
3 checks passed
@lesnik512
lesnik512 deleted the worktree-improvements-p1-p35 branch June 13, 2026 09:07
lesnik512 added a commit that referenced this pull request Jun 13, 2026
Release notes for the post-audit hardening release: B1–B16 bug fixes (#61),
P1–P35 improvements (#67), T1–T8 test-quality guards (#66). Minor bump — new
validation rejects some previously-accepted calls and the schema gains a CHECK
constraint + DLQ timer_id column (migration required).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lesnik512 added a commit that referenced this pull request Jun 13, 2026
…ings (#71)

The 2026-06-12 code audit shipped across 0.9.0 (#61/#66/#67) and
0.9.1 (#68/#69/#70), but the invariant docs still described pre-fix
behavior. Sync the drift the audit flagged plus the drift its own
fixes introduced, and retire the now-resolved findings doc.

CLAUDE.md / architecture:
- relay: `_OutboxConfigError` no longer "rides AcknowledgementMiddleware
  to the nack path" — the worker catches it, logs at ERROR, and the row
  retries via lease expiry, not the retry_strategy (P18). Fixed in both
  CLAUDE.md and architecture/relay.md.
- terminal-write API: `delete_with_lease(conn, …)` /
  `mark_pending_with_lease(conn, …)`, not the `*_with_conn` names.
- NOTIFY: over-long table names now raise ValueError at construction
  (P7), not "silently lose NOTIFY and degrade to polling".
- engine ownership: drop the phantom `EngineState` holder and the dead
  `OutboxBrokerConfig.disconnect()` (removed in P24).
- schema: note the P8 `<table>_lease_ck` CHECK; validate_schema now
  also probes partial-index predicates (S2).
- drain regression-test references point at the real test names (T8
  added them to test_fake.py; integration covers the Postgres path).
- timers NOTIFY-skip: "genuinely future-dated" wording (a past/zero
  activate_at/in does fire NOTIFY).

Archive:
- move planning/active/2026-06-12-code-audit-findings.md →
  planning/archived/ with status: shipped + PR/release provenance.
- repoint the two release-notes "See also" links to archived/.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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