Skip to content

max_message_len is unverified across 8 adapters: the caps are asserted against themselves #934

Description

@FerroxLabs

Every adapter declares a single-message length cap through Channel::max_message_len().
ChannelManager::send_to_keyed chunks on it — and, per docs/delivery-semantics.md §4.1,
drops the idempotency key above it. So the cap is now load-bearing for the only
exactly-once guarantee the product has, and it is the one number nothing measures.

What is actually tested today

Six adapters have a test of this shape:

assert_eq!(ch.max_message_len(), Some(1600));
  • wcore-channel-sms/src/lib.rs:502Some(1600)
  • wcore-channel-msteams/src/lib.rs:697Some(28_000)
  • wcore-channel-discord/src/lib.rs:916Some(2000)
  • wcore-channel-telegram/src/lib.rs:602Some(4096)
  • wcore-channel-whatsapp/src/lib.rs:942Some(4096)
  • wcore-channel-slack/src/lib.rs:1150Some(39_000)

Each asserts the literal that the function on the line above it returns. It cannot fail
except by someone editing both halves, and it would keep passing if the number were wrong
about the platform — which is the only way it can be wrong that matters. It restates the
code; it does not test it.

Two more declare a cap with no test of any kind:

  • wcore-channel-matrix/src/lib.rsSome(32_768)
  • wcore-channel-whatsapp/src/bridge/mod.rs

Partially closed on 2026-07-31

lane/guarantee-honesty made Matrix's cap load-bearing rather than decorative:
docs/delivery-semantics.md now carries matrix.cap = 32768 in its machine-readable block,
and crates/wcore-channels-registry/tests/delivery_semantics_declaration.rs asserts that
number against the adapter the production factory builds
(the_declared_cap_is_the_adapters_real_cap, plus
comparator_rejects_a_cap_that_does_not_match_the_adapter as the negative control).

That closes doc-vs-code drift for Matrix. It does not close this issue, because it still
compares two numbers we wrote to each other.

What is left, and why it is not free

The unmeasured claim is: does the declared cap equal the platform's real limit? Only a live
send at cap and at cap + 1 against each real destination can answer that, and being wrong
is not cosmetic in either direction:

  • Cap set too high — the platform rejects the message. Chunking exists precisely to stop an
    over-long reply being rejected and dropped (HIGH-6), so a too-high cap silently reinstates
    that bug.
  • Cap set too low — bodies are chunked that did not need to be, and per §4.1 chunking is
    what drops the idempotency key. A too-low Matrix cap therefore downgrades exactly-once to
    at-least-once for messages that should have been covered by it.

Eight platforms means eight sets of live credentials. We hold Slack, Discord and Matrix; we
hold no Twilio or Meta credential at all (measured — see the 2026-07-30 correction in
docs/delivery-semantics.md), and the Matrix token was found dead on 2026-07-31
(M_UNKNOWN_TOKEN).

Suggested shape

  1. Extend the <platform>.cap declaration in docs/delivery-semantics.md to every adapter,
    not just Matrix, so all eight caps are machine-checked against the constructed adapter.
    This is cheap and kills the tautology as drift detection.
  2. Add a gated live boundary probe per platform — send at cap, expect accept; send at
    cap + 1 unchunked, expect the platform's rejection — following the
    live_twilio_whatsapp_identity.rs pattern: written, credential-gated, and panicking
    rather than skipping
    when configuration is absent.
  3. Until (2) runs for a given platform, mark that cap NOT MEASURED in the docs rather than
    letting the assert_eq! imply it is verified.

Provenance

Raised by lane/guarantee-honesty (B1.4). Recorded as an issue rather than fixed in-lane
because the residual needs credentials for platforms we do not hold, which is not a lane
decision. Filed so the debt is falsifiable in a tracker instead of asserted in a lane note.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreWayland Core engine / backends

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions