Skip to content

a float cap or timeout refuses a bool, nan, inf or a value that only rounds to zero (BACKLOG #3432) - #2277

Merged
wshallwshall merged 3 commits into
mainfrom
fix-3432-float-caps
Oct 12, 2026
Merged

wshallwshall merged 3 commits into
mainfrom
fix-3432-float-caps

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Ledger row #3432, filed by the Lander as the follow-up to merged #3431 (engine PR 2272). Engine transports, config readers and tests.

Behaviour change: an operator timeout or float cap refuses a bool (False too), NaN, infinity, a number too large for a float, and text or a Decimal that only rounds to zero ("1e-400", "0e0"). Each refusal names the key and withholds the value. Range refusals now withhold the value too.

Merge danger

Reversible: yes -- a revert undoes it all.

Blast radius:

  • New float_setting and positive_seconds in messagefoundry/transports/base.py; cap_setting's float path uses them.
  • About 30 timeout reads routed through them: MLLP, TCP, X12, DICOM, FHIR, FhirLookup, REST, SOAP, DICOMweb, Email, Direct, the database acquire_timeout reads, reference_sync, the remotefile connect_timeout, File min_age_seconds, Timer interval_seconds, poll_seconds, the OAuth2 and SMART token timeouts and skews, the HTTP reply_timeout and reply_write_timeout (through a new reply_seconds), the runner, and the Http factory.
  • DatabaseRef checks acquire_timeout at declaration and in build_check_registry.
  • Changelog and tests.

Reachable routes: code-first factory calls and env() casts. A connections.toml literal is typed at load. A TOML literal 1e-400 stays off, because tomllib makes it 0.0 before any reader sees it; that is recorded in the float_setting docstring.

Evidence

  • Before (origin/main): float(value) == 0 read "1e-400" as off on a float cap, which would switch off receive_timeout, idle_timeout_seconds, max_frame_seconds and the rate caps. Bare float() timeout reads took True as 1.0 and accepted NaN and infinity. With the new tests run against origin/main's engine code, 368 cases fail and 88 pass.
  • After: all pass. The tables cover 13 float caps where 0 means off, plus 25 timeouts. Each row refuses True, False, nan, inf, -inf, "nan", "inf", "1e400", "1e-400" and [2.5], and accepts 2.5, "2.5", " 2.5 " and Decimal("2.5"). Exact zero spellings, "0_0" and the full-width zero among them, read as off on an off-by-zero cap. A huge int reply_timeout is refused by name, and a bad DatabaseRef acquire_timeout is refused at declaration and at check.

Builder reports (condensed). Branch fix-3432-float-caps, head 064123114e7cc47babf66c2fb0125f57d8573bbd.

  • Round 1: 69e8faef2e, independently reviewed: 6 findings, 2 low shipped defects (a raw OverflowError in the Http factory; a false reason for "0_0").
  • Round 2: 064123114e fixes both, and adds the DatabaseRef declaration and check read plus changelog corrections. Its pre-push review ran on 76a62c992d; 3 findings fixed and amended in, 5 declined as not shipped defects. About 10 amended lines (the build_check_registry read, a docstring, the changelog) are not re-reviewed.
  • Checks:
    • ruff, ruff format, both linux mypy legs.
    • pytest: 2651 passed across 19 named files in round 2; 4634 across the transport families in round 1.
    • Round 1's reviewer ran the full suite: 43600 passed, 2 failed, both local machine state (installed-hook drift; the host-dependent service test, now #3441).
  • Follow-ups, unfiled:
    • zero or negative plain timeouts still build;
    • reference_sync logs only the error class;
    • connections_file._optional_float does not refuse NaN or infinity at load;
    • the scorecard anchors on the removed if float(value) == 0: line need a vault re-read.
  • Proposed banner: SHIPPED -- every operator timeout and float cap read through float_setting refuses a bool, nan, inf, an overflow, or a value that only rounds to zero, naming the key and withholding the value.

wshallwshall added 2 commits October 12, 2026 06:48
…G #3432)

float_setting in transports/base.py refuses a bool, NaN, infinity, a
non-number, and a value float() only rounds to zero ("1e-400"), naming
the key and withholding the value. cap_setting's float path and
poll_interval use it, and so do at least the timeout reads on MLLP,
TCP, X12, DICOM, DATABASE, reference sync, HTTP reply, FHIR, REST,
SOAP, DICOMweb, Email, Direct, REMOTEFILE, File, Timer, OAuth2, SMART.
Range refusals in positive_cap, resolve_poll_ceiling, poll_interval,
max_header_bytes, max_decompressed_members and the MLLP per-host and
frame-seconds guards withhold the value too.

Proposed PR title: a float cap or timeout refuses a bool, nan, inf or a
value that only rounds to zero (BACKLOG #3432)
Banner: BUILT -- engine branch fix-3432-float-caps, awaiting PR.
…cquire_timeout (BACKLOG #3432)

Review fixes on the float-cap reader:
- The Http factory refuses an int too large for a float by name,
  instead of raising a raw OverflowError.
- float_setting reads any exact zero as zero: text whose digits are
  all zeros, with no exponent ("0_0", a full-width zero). Its other
  zero-reading refusals now state a true reason.
- DatabaseRef checks a literal acquire_timeout when declared, and
  build_check_registry reads an env() one once resolved, through the
  sync's own reader. So messagefoundry check refuses a bool or a NaN.
- The changelog fragment scopes the zero-timeout sentence to a
  directly built HttpSource and splits its long sentence into a list.

Proposed PR title: a float cap or timeout refuses a bool, nan, inf or a
value that only rounds to zero (BACKLOG #3432)
Banner: BUILT -- engine branch fix-3432-float-caps, awaiting PR.
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

QA (BACKLOG #3432): (1) Builder round 1 code-review xhigh on the head before its repair; repair amended in. (2) Independent review of 69e8fae: QA: code-review xhigh on 69e8fae, 6 findings, 2 shipped defects (both low: Http factory raw OverflowError on a huge int; false refusal reason for '0_0'); full suite 43600 passed, 2 failed (local machine state). (3) Builder round 2 code-review xhigh on 76a62c992d before push: 8 findings, 3 fixed and amended into 0641231 (env() acquire_timeout at check; cap_setting docstring; changelog over-claim), 5 declined as not shipped defects. ~10 amended lines not re-reviewed -- narrow review please.

@wshallwshall wshallwshall added the qa Builder QA record posted; not a merge gate label Oct 12, 2026
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: narrow review of the amend 76a62c992d..0641231 (code-review skill at xhigh) returned SHIP on the code. The reviewer probed float_setting with bools, nan/inf, overflow, "1e-400", "0e0", Decimal and Fraction; all are refused with the value withheld. All 12 named timeout sites are converted. 1081 + 2814 tests passed, and ruff and mypy are clean on linux and win32. Two touched-file anchors expect the removed if float(value) == 0: line in base.py; the body already lists that for a vault re-read.

Two changelog lines would ship an overclaim, so please fix them before I enqueue:

  1. changelog.d/3432.fixed.md:18-19 says check refuses a bad acquire_timeout "from a literal or from env()". The env() half holds only when the value resolves at check time: _build_check_connectors skips a source whose env() does not resolve. "Not a number" also undersells it, since "1e-400" is refused too. An "at least" phrasing, or a scoped clause, fixes both.
  2. changelog.d/3432.fixed.md:1-10: say plainly that false on a float cap (for example receive_timeout = false in connections.toml) used to read as off and now fails at build. That spelling was reachable.
    Low note, optional: reference_sync.py:122's refusal does not name the reference set; wiring_runner.py:10855 shows how to pass it.

… #3432)

The check refuses an env() acquire_timeout only when it resolves at
check time, and refuses at least a bool, a NaN or "1e-400". A bool on
the bare-float timeouts read as zero or one second and now fails at
build; a cap_setting float cap already refused one (BACKLOG #3431).

Proposed PR title: a float cap or timeout refuses a bool, nan, inf or a
value that only rounds to zero (BACKLOG #3432)
Banner: BUILT -- engine branch fix-3432-float-caps, awaiting PR.
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: line check passed at 67b55ee. On main, mllp.py:753-754 reads timeout_seconds and connect_timeout with a bare float(), and float(False) is 0.0 and float(True) is 1.0, so the new bullet is true. The cap_setting case is correctly attributed to #3431. The acquire_timeout sentence is scoped to a literal and to an env() value that resolves at check time. I enqueue once checks finish.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: enqueuing at pinned head 67b55ee. Review proof: round 1's independent review, the Builder's round-2 pre-push review, and a Lander-dispatched narrow review of the 76a62c992d..0641231 amend, which returned SHIP. My line check passed on the changelog-only 67b55ee. Every check has finished green, including the win32 mypy leg. For the vault record: two anchors on the removed base.py line need a re-read; the body lists them.

@wshallwshall
wshallwshall added this pull request to the merge queue Oct 12, 2026
Merged via the queue into main with commit 1e5bfcc Oct 12, 2026
51 checks passed
@wshallwshall
wshallwshall deleted the fix-3432-float-caps branch October 12, 2026 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

qa Builder QA record posted; not a merge gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant