Keyword interception at step 0 on the RingCentral rail (MS1 Task 4)

FeatureVOIPService
Shipped
August 27, 2026 at 8:06 PM UTC
Author
Kamo
Commit
2126e63

Today a STOP to a number no MEMBER_VOIP_CONFIG row owns hits the "No member found for to-number" branch and vanishes — and that branch is EXACTLY where an opted-out consumer's number ends up, because a campaign sends from a campaign number and nothing writes campaign numbers into member configs. Step 0 sits after the externalMessageId dedupe (so a RingCentral retry does not reprocess — Decision M1) and before the member and instance lookups' early returns (so an unowned number is not dropped). A keyword returns without storing a VoipMessage: "STOP" sitting unanswered in a member's inbox is not a customer message. Only the member-config READ moved above step 0, so no second query is issued. The `return` it guards stayed below the interceptor, which is the whole point. RESOLVING THE ORG ABOVE THE POINT IT IS RESOLVED — the plan flagged this unsolved. Task 2's org-from-to-number resolver is NOT reused. It scans **************** which is the wrong inventory for this rail: a RingCentral number lives on **************** or **************** and will not appear in a bulk-text carrier row. Reusing it verbatim would search a table that cannot hold the answer and report "unattributable" for every RingCentral STOP — indistinguishable from the real number-inventory gap, so a plain wiring bug would hide inside a known limitation. The approach is reused, the table is not. Its author's "unreliable" judgement carries over for the same underlying reason: there is no number inventory. The only ownership records are two nullable, unindexed columns, and an org receiving on several numbers through one instance is unrepresentable. This is a scan of a small table, not a lookup. Order: member config (so an attributable message is attributed identically whether or not it is a keyword) → active VoipProviderInstance matched on **************** WHEN THE ORG CANNOT BE RESOLVED, plainly: SmsKeywordService writes the SmsInboundReceipt with a NULL org and writes NOTHING else. No ConsentRecord, no AgentContactState. So the STOP is recorded as evidence that one arrived, with the number logged at WARN, and the consumer IS STILL SENT MESSAGES BY THAT TENANT. That is strictly better than today's silence and it is not compliance. It closes when ADD5/MS3 builds the per-number inventory. Two orgs claiming one number resolves to NEITHER (logged at ERROR). Attributing a revocation to the wrong tenant is the failure C1 forbids and is worse than not recording it, because it also stops a tenant who was never told to stop. TDD — observed failures, verbatim. Red before implementing: [ERROR] Tests run: 8, Failures: 0, Errors: 8 <<< FAILURE! [ERROR] **************** » IllegalArgument Could not find field 'keywordService' of type [null] on target object **************** or target class [class **************** Green after: 8/8; full suite 322/322. Mutation — moved the interceptor BELOW the member lookup's early return, i.e. back to the placement that makes it useless: [ERROR] Tests run: 8, Failures: 5, Errors: 0 <<< FAILURE! Wanted but not invoked: Actually, there were zero interactions with this mock. [ERROR] **************** Reverted; 322/322 after revert. DDL HAS NOT LANDED — see the Task 3 commits. Built against a shared-lib jar in a PRIVATE -Dmaven.repo.local; ~/.m2's 1.6.0 jar verified byte-identical throughout (md5 ****************

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing