refactor(webex): converge on the shared nonce minter and byte chunker - #5708
Conversation
Design Review (Fable 5) — ✅ PASSDesign-level review of Design-Verdict: PASS Three verified convergences onto owned primitives; behavior preserved in every reachable case (empty-input [DESIGN-REVIEWED] 12bdca3 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsNo findings. False positive or not applicable? A repository writer can comment: |
First Principles Review (Fable 5) — ✅ PASSPremise-level review of All claims verified. This is a pure-subtraction PR: three duplications removed in favor of existing shared mechanisms, with one declared test-only rider. Final review: First-Principles-Verdict: PASS Every item deletes a second spelling of a mechanism that already exists in What this change shipsIntent: make Webex use the shared messaging helpers instead of three private copies — a FIX (of duplication), not an addition.
WatchThe description defers the [FIRST-PRINCIPLES-REVIEWED] 12bdca3 |
bb4682a to
5798baa
Compare
5798baa to
7690f49
Compare
7690f49 to
9df7db9
Compare
Three duplications of a shared helper, found by auditing #5218's own new code against the messaging layer. The options card minted its nonce with a local secrets.token_hex(8) while every other channel and both shared registries reach new_approval_nonce(). Entropy is the same 64 bits, so no token was weaker -- but the shared minter's own contract says a second generator is what eventually diverges, and the approval card on this same renderer already routes through it, so the file disagreed with itself. outbound_mimetype had no caller outside its own tests. It derived a type from the path extension, which the outbound-files contract forbids (the type comes from the sniffed bytes); the upload path correctly uses item.mime, so the helper was dead on arrival and its tests gave it false life. Deleting it dropped webex/attachments.py below the per-file coverage floor, which is the honest signal that its coverage was resting on a function nothing called: process_webex_attachments had no test at all. It has three now -- a text file through the shared ingest, the empty case, and the audio path that is the reason this channel passes handle_audio=True -- and the file is at 100%. chunk_utf8 re-implemented messaging.split.chunk_utf8_bytes and was missing both of its termination guards, so a non-positive budget or a code point wider than the budget spins forever. Not reachable from its one caller, which passes the 7000-byte default. It now delegates, the arrangement truncate_utf8 beside it already had; test_webex_client.py was already exercising the shared primitive rather than this copy.
9df7db9 to
12bdca3
Compare
Three duplications of a shared messaging helper, all in code #5218 just landed. Found by auditing that branch's own new code against the
messaginglayer rather than by a review finding.The options card minted its own nonce
webex/renderer.pyused a localsecrets.token_hex(8), while every other channel with a clickable control — Discord, Teams (×2), Telegram — and both shared registries (PendingApprovals.reserve,PickerRegistry.mint) reachmessaging.renderer.new_approval_nonce().Being honest about severity: entropy is identical (both 8 bytes / 64 bits), so no token was weaker and this is not a live security hole. What it violates is that helper's stated contract:
The alphabet and length do differ (16 hex chars vs ~11 urlsafe), and the shared 8-byte choice exists because it has to fit Telegram's 64-byte
callback_data— a constraint the next person to touch a local copy has no way to know.Worst of it: the file disagreed with itself. The approval card on this same renderer already routes through the shared minter via
PendingApprovals.reserve, with a comment saying so; the options card 380 lines later rolled its own.outbound_mimetypewas dead on arrivalNo caller anywhere in
src/— only its own three tests, which gave it false life (coverage, plus "it's tested, so something must use it").It was also dead for a good reason: it derived the content type from the path extension, which is what the outbound-files contract forbids —
— and the upload path correctly uses
item.mime, the sniffed type. Removed, with its tests and two now-unused imports.chunk_utf8re-implemented the shared primitive, minus its guardswebex/client.py::chunk_utf8duplicatedmessaging.split.chunk_utf8_bytesloop-for-loop, and was missing both of the shared version's termination guards:chunk_utf8_bytesmax_bytes <= 0return [text]remaining[0]So the copy was the strictly worse one, and its failure mode is a hang rather than an exception. Not reachable today — the single caller passes the 7000-byte default — so this is a latent hazard, not a live bug.
The local wrapper is now gone entirely and
renderer.pycallschunk_utf8_bytes(content, WEBEX_MAX_TEXT)directly. An earlier revision kept it as a one-line delegating wrapper on a claimed symmetry withtruncate_utf8above it; that symmetry does not hold and the claim is withdrawn —truncate_utf8earns its wrapper with three same-file consumers (client.py:447,:494,:522), while this one had zero, its single consumer lives inrenderer.pyand always took the default, andtest_webex_client.pywas already importing and exercising the shared primitive, so the local copy had no test of its own. The guard and fence-blindness rationale moved to the one call site where the choice is actually made.Semantics preserved deliberately: still the fence-blind primitive, not
split_markdown_bytes. Webex's answer path re-seals its own fences and is pinned that way bytest_channel_table_rendering.TestDeliveryFraming.Riding along, declared
test_webex_attachments.pyis not purely a deletion. Removingoutbound_mimetypetook the file's only tests with it, so the same commit addsTestProcessWebexAttachments(3 tests) plus abodies=download capability on the file'sFakeClient— backfilling the only coverage of the ingest wiring attransport_dispatch.py:458. Test-only and coverage-positive, but an addition inside a subtraction PR, so it is stated here rather than left to be discovered in the diff. Its two temp-producing tests keepcleanup(result.temp_paths)in afinallyso a failed assertion cannot leave downloaded bytes behind.Not in scope
The
[OPTIONS:]trailer parse is duplicated across seven sites (Discord, Telegram, Teams, WeCom, Slack, Webex, andrender_options_as_textitself). That is a real convergence but it touches six channels, so it goes in its own PR rather than riding along here.Verified locally: 504 webex-selected tests pass, plus the framing/split pins (
test_channel_table_rendering.py,test_webex_client.py,test_messaging_split.py,test_webex_attachments.py— 316 passed); mypy (1104 files), flake8, isort and the black baseline ratchet all clean. Rebased onto current main; one commit.