fix(x12): record the seven ADR 0021 connection events its raw-TCP twin already records (BACKLOG #1665) - #1222
Open
wshallwshall wants to merge 3 commits into
Open
wshallwshall wants to merge 3 commits into
wshallwshall wants to merge 3 commits into
Conversation
added 3 commits
September 16, 2026 16:40
… records (BACKLOG #1665) `X12Source` carried no `_emit_event` call at all. An allow-list refusal, a capacity refusal, an over-cap interchange and a peer reset recorded nothing, where `TcpSource` -- the listener X12 is otherwise a near-copy of -- recorded a row for each. On first deployment that would leave an X12 feed's connects and refusals absent from the one stream an operator reads to answer "did the sender connect, and why did it drop". Zero deployments, so no live stream is missing anything today. SEVEN kinds, not the four the row names. Measured by walking the emit sites: `TcpSource` emits `peer_not_allowlisted`, `at_capacity`, `established`, `frame_oversize`, `framing_error`, `peer_reset` and `closed`. The row names the first two, `frame_oversize` and `peer_reset`. Emitting only those four would have left X12 asymmetric with its twin on the three paths an operator most wants -- did it connect at all, did it close cleanly, and was the close an idle drop or a hangup -- and would have left the `docs/PHI.md` row 7 sentence about X12 half-true instead of false, which is harder to notice. None was dropped: the two listeners share an accept path, both gates, the per-chunk decode loop, the outer `OSError` arm and the `finally`, so every TCP kind has an exact X12 analogue. No new kind NAME. `frame_oversize` is reused for the `X12FrameError` arm even though this listener's frame is an interchange: a second name for one condition would red the documented- vocabulary guard, the console filter tuple and the `docs/PHI.md` row together, and would split an operator's query across two spellings for no gain. `closed` is emitted only when the connection was established AND did not fail, so a failure is never also counted as a clean close -- the same `established`/`failed`/`close_reason` bookkeeping `TcpSource` uses, and the reason separates an `eof` hangup from an `idle_timeout` drop. The tests are their own file rather than a hunk in `tests/test_x12_transport.py`, which open PR 1214 is rewriting. Each kind is driven and asserted, and `test_allowlist_refusal_is_recorded_by_both_listeners` carries the positive control: it drives the same refusal on `TcpSource` through the same sink in the same test. Before this change that test failed with `[] vs ['peer_not_allowlisted']` -- the zero on the X12 side was attributable because the TCP arm was non-zero. All eight failed before; all eight pass after. `test_x12_emits_the_same_event_vocabulary_as_its_tcp_twin` derives both kind sets by AST and asserts they are equal, so neither listener can grow a kind the other lacks without a red. Also corrects the `_drain_reply` docstring, which said this listener emits no connection event at all and that its warning was therefore the whole of the engine-side evidence. Both halves are now false: the outer `OSError` arm emits `peer_reset`. The warning is kept for what it still adds -- naming which bound fired, which the redacted `peer_reset` cannot.
…nection event (BACKLOG #1665) The code change beside this one wires `X12Source` to the seven ADR 0021 kinds its raw-TCP twin emits. Shipping that alone would leave CI green while the repository carried an explicit written claim that an X12 feed's connects and refusals are captured nowhere -- a compensating control resting on a false premise, and the more dangerous half of the defect, because prose is what an operator reads when deciding whether to trust a counter. Nothing caught these. All five sites read as correct English and no guard derives them from the emit sites, which is exactly why they are corrected here rather than filed. - `docs/PHI.md` row 7, the connection_event stream's coverage statement. Named X12 as one of two silent listeners and said its connects and refusals were "absent from this stream". - `docs/CONNECTIONS.md`, the accept-rate bullet in Resource management. Said X12 and DICOM "contain zero `_emit_event` call sites", and that X12's at-capacity refusal left "no engine-side evidence of any kind". Its two `transports/x12.py:NNN` line citations went with it; they had already drifted, and a line number is a navigation aid, never evidence. - `docs/CONNECTIONS.md` Table B, the X12 listener row. - `docs/SECURITY.md`, the pre-auth DENY table's X12 row. - `docs/SECURITY.md`, the "Telemetry honesty" note. Three test-prose sites go with them, since a stale docstring misleads the next reader exactly as a stale doc does: the `test_reply_write_drain_is_bounded` docstring in `tests/test_x12_transport.py` (which said there was no `peer_reset` to assert -- so the assertion is added, mirroring the raw-TCP twin), `test_every_socket_listener_that_emits_nothing_is_named_in_row_7`, and the `CONNECTOR_ROW_TOKENS` comment explaining why X12 has a row of its own. THE DICOM HALF OF EVERY ONE OF THESE SENTENCES IS LEFT ALONE. `transports/dicom.py` still contains zero `_emit_event` calls, so each sentence names DICOM correctly and editing that half would turn a true statement false. The asymmetry these sentences exist to disclose is real; it is just smaller. One pinned guard had to move rather than be deleted. `REQUIRED_TRUTHS` in `tests/test_communications_inventory.py` asserted the literal sentence "No ADR 0021 connection_event is emitted" stays present in the resource-management section -- a prior correction, pinned so it could not silently regress. That sentence is now false, so the pin moved to the half that survives, "contains zero `_emit_event` call sites", which still names DICOM as the silent listener. Deleting the pin instead would have retired a live guard on the strength of a change that only narrowed what it guards.
…lure table (BACKLOG #1665) Found by re-sweeping after the first five were fixed, which is the point of sweeping with a known population rather than stopping at the sites the item named. The row's failure column asserted three things that the code change beside it makes false at once: that an allow-list refusal is "log-only (no connection_event)", that a "capacity refusal is silent -- no event and no log", and that "this listener emits no connection_event of any kind". The reply-write bound's own clause is corrected rather than deleted. It said the drop leaves a logged warning only; the warning is still there and still earns its place -- it names which bound fired, which the redacted `peer_reset` cannot -- so the row now carries both.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
X12Sourcecarried no_emit_eventcall at all. An allow-list refusal, a capacity refusal, an over-cap interchange and a peer reset recorded nothing, whereTcpSource-- the listener X12 is otherwise a near-copy of -- recorded a row for each.On first deployment that would leave an X12 feed's connects and refusals absent from the one stream an operator reads to answer "did the sender connect, and why did it drop". Zero deployments, so no live stream is missing anything today. Severity is low and conditional, per the item.
Same shape as BACKLOG #1617, with a smaller reply surface.
The drain half of the item was ALREADY MERGED. Nothing here rebuilds it.
Item #1665 has two halves. The first -- bounding the inbound reply-write drain -- shipped in PR 1122, commit
87c83574c, merged 2026-09-14, under sibling row #1766, which is why a title grep for 1665 finds nothing.Verified in the tree before writing anything, not taken on trust:
_REPLY_DRAIN_GRACEand a_drain_replywrappingwriter.drain()inasyncio.wait_forare present in bothmessagefoundry/transports/x12.pyandmessagefoundry/transports/tcp.py. This PR touches that code only to correct a docstring it left behind, and to add thepeer_resetassertion the docstring said was impossible.SEVEN kinds, not the four the item names
Measured by walking the emit sites, not counted by eye.
TcpSourceemits seven, at seven call sites:peer_not_allowlistedat_capacitymax_connectionsgateestablishedframe_oversizeframing_errorExceptionarmpeer_resetOSErrorarmclosedfinally, when established and not failedNothing was dropped. The two listeners share an accept path, both gates, the per-chunk decode loop, the outer
OSErrorarm and thefinally, so every TCP kind has an exact X12 analogue. After the change both modules report 7 call sites and 7 distinct kinds, with identical sets.Emitting only the four the item names would have left X12 asymmetric on the three paths an operator most wants -- did it connect at all, did it close cleanly, and was the close an idle drop or a hangup -- and would have left the
docs/PHI.mdrow 7 sentence half-true rather than false, which is harder to notice.No new kind name.
frame_oversizeis reused for theX12FrameErrorarm even though this listener's frame is an interchange. A second name for one condition would red the documented-vocabulary guard, the console filter tuple and thedocs/PHI.mdrow together, and would split an operator's query across two spellings. The console tuple anddocs/PHI.mdrow 7 therefore need no change: the vocabulary is unchanged, only its coverage.The positive control
Built and confirmed before any code changed, because a search that finds nothing is indistinguishable from a clean repository.
test_allowlist_refusal_is_recorded_by_both_listenersdrives the same refusal onTcpSourceandX12Source, through the same capture sink, in the same test. Before the change it failed with:The TCP arm was non-zero, so the zero on the X12 side was attributable to the listener rather than to a sink that is never called. All eight tests in the new file failed before; all eight pass after.
test_x12_emits_the_same_event_vocabulary_as_its_tcp_twinderives both kind sets by AST and asserts equality, so neither listener can grow a kind the other lacks without a red.Doc repairs: SIX engine sites, not four
The item's own cited doc was one of them. All six read as correct English, and every guard stayed green with them in place -- confirmed by running the doc-drift suites before touching any prose. That is the whole reason they are corrected here rather than filed.
docs/PHI.mdrow 7 -- the connection_event stream's coverage statement.docs/CONNECTIONS.md-- the accept-rate bullet in Resource management (also drops twotransports/x12.py:NNNcitations that had already drifted).docs/CONNECTIONS.mdTable B -- the X12 listener row.docs/CONNECTIONS.md-- the timeout-and-failure table's X12 row. Missed on the first pass and found by re-sweeping, which is the argument for sweeping with a known population rather than stopping at the sites the item names. It asserted three false things at once.docs/SECURITY.md-- the pre-auth DENY table's X12 row.docs/SECURITY.md-- the "Telemetry honesty" note.Three test-prose sites go with them, since a stale docstring misleads the next reader exactly as a stale doc does: the
test_reply_write_drain_is_boundeddocstring intests/test_x12_transport.py,test_every_socket_listener_that_emits_nothing_is_named_in_row_7, and theCONNECTOR_ROW_TOKENScomment.The DICOM half of every one of these sentences is left alone.
transports/dicom.pystill contains zero_emit_eventcalls, so each sentence names DICOM correctly and editing that half would turn a true statement false. The asymmetry the sentences exist to disclose is real; it is just smaller.One pinned guard moved rather than being deleted
REQUIRED_TRUTHSintests/test_communications_inventory.pypinned the literal sentence"No ADR 0021 connection_event is emitted"as present in the resource-management section -- a prior correction, pinned so it could not silently regress. This change makes that sentence false. The pin moved to the half that survives,"contains zero \_emit_event` call sites"`, which still names DICOM as the silent listener. Deleting it would have retired a live guard on the strength of a change that only narrowed what it guards.FOR THE LANDER: a seventh site is in the vault and I cannot reach it
docs/security/is gitignored in this repository (git ls-files docs/securityreturns 0, and the directory does not exist in this checkout), and the vault is held by another session onvault/close-six-shipped-rows. Naming it is the whole of what I can do.docs/security/THREAT-MODEL.mdRaw TCP / X12 listener(its label is transcribed intests/test_threat_model_doc_drift.py, in the row-token map and in the "covered by" map).connection_event-- or that an X12 allow-list or capacity refusal is log-only or silent. Those are now false in the same way sites 1 to 6 were. Replace with the raw-TCP behaviour: the two listeners now emit the same seven kinds.tests/test_threat_model_doc_drift.pyis structural and numeric, not prose-matching, and it is inert in a public checkout, so a prose edit there should not red it. Worth re-running in the vault after the edit.I did not attempt this edit and made no change under
docs/security/.Checks
Run, from this worktree's venv:
ruff check .-- passruff format --check .-- passmypy messagefoundry(strict) -- pass, 275 source filespytest tests/test_x12_connection_events.py-- 8 passed (all 8 failed before the code change)pytest tests/test_x12_transport.py tests/test_tcp_transport.py-- passpytest tests/test_phi_logging_inventory.py-- pass. Carriestest_connection_event_vocabulary_is_derived_from_the_emit_sites, which is exactly what this change touches, plus the console filter-tuple cross-check.pytest tests/test_communications_inventory.py tests/test_security_doc_drift.py tests/test_connection_event_emit.py-- passSkipped, and why: the full local suite. It has been measured not to finish under fleet contention, so targeted coverage plus named CI legs was the trade. Legs a reviewer must read on the hosted runner: the SQL Server and Postgres store legs,
windows-service-smoke, and the web console leg -- none of which this change should touch, but none of which a Builder can see./simplifywas run as a single review agent over all four angles (reuse, simplification, efficiency, altitude) rather than four passes, given the weekly pool.Possible conflict with open PR 1214
PR 1214 (BACKLOG #1735) is rewriting
tests/test_x12_transport.py'sexpect_replyround-trip tests. The seven new tests here live in their own file,tests/test_x12_connection_events.py, to stay out of its way. What does touchtests/test_x12_transport.pyis a 14-line hunk intest_reply_write_drain_is_bounded-- a different function -- correcting its now-false docstring and adding thepeer_resetassertion. That should merge cleanly, but it is the one place these two PRs meet.Ledger
docs/BACKLOG.mdis a policy stub here and is not edited by this PR. BACKLOG #1665 -- the X12 connection-event half is built; the drain half shipped earlier under #1766 in PR 1122 (87c83574c). One vault site remains, named above for the Lander.#1766 and #1617 are referenced as context only. Neither is closed by this PR.