{
  "layer": "CONSENT_FLOW",
  "name": "Consent flow",
  "url": "https://ekas.io/rules/10dlc/consent-flow/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/",
  "count": 101,
  "rules": [
    {
      "id": "CON-008",
      "slug": "con-008",
      "title": "The live CTA and the declared message flow must say the same thing",
      "statement": "The consent wording quoted in the message flow must be the wording actually printed on the live opt-in surface.",
      "rationale": "The flow is the brand's account of the consent and the page is the consent itself, so where they differ the page wins and the registration describes something that does not happen. It is rarely dishonest: the flow was written from the disclosure the team intended to ship, and the page was changed afterwards by someone who never saw the campaign record.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow vs live opt-in page",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "Bandwidth",
        "Twilio",
        "TCR"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "chat",
          "social",
          "email"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party, chat, social and email.",
      "universal": false,
      "remediation": "Copy the consent sentence off the live page into the message flow verbatim, rather than paraphrasing it. Where the page is the thing that is wrong, fix the page first and then quote it. Done when the quoted sentence and the printed one match word for word.",
      "example": "Customers opt in at https://acmecoffee.com/checkout by ticking an unchecked box reading: \"Text me Acme Coffee offers and rewards updates.\" — quoted exactly as printed.",
      "pitfalls": [
        "Tidying the punctuation or capitalisation while copying is enough to read as a different disclosure to a reviewer comparing them side by side."
      ],
      "notes": "The catalog classes this DETERMINISTIC, and it would be, given a crawl that says WHICH page each block of text came from. The registry carries one undifferentiated websiteText, so a string comparison cannot tell \"the CTA was reworded\" from \"we fetched the homepage and the CTA is at /checkout\" — and failing a compliant registration for the second is the worse error. Authored as judged until the crawler carries a per-page map; both audits the catalog asks for (CON-009) fall out of the same comparison.",
      "catalogIds": [
        "CON-009"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-010",
      "slug": "con-010",
      "title": "The three subscriber-management attributes must be declared true",
      "statement": "The subscriberOptin, subscriberOptout and subscriberHelp campaign attributes must each be set true, and the HELP declaration must have a keyword set behind it.",
      "rationale": "These attributes assert that the programme collects consent, honours opt-outs and answers HELP, which is the baseline claim a campaign makes about itself. Leaving any of them false or unset contradicts every other field in the submission and is a fast, mechanical rejection — Plivo will not even accept the API call. They are also what a carrier relies on when a complaint lands, so declaring HELP with no keyword configured is a claim you will be held to and cannot meet.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.subscriber_optin + subscriber_optout + subscriber_help",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Plivo",
        "Twilio"
      ],
      "applicability": {
        "excludeUseCases": [
          "M2M"
        ]
      },
      "applicabilityText": "Applies when the use case is NOT M2M.",
      "universal": false,
      "remediation": "Set all three attributes true, declare at least one HELP keyword, and make sure the claims are real — opt-in evidence attached, opt-out keywords honoured by your platform, and a HELP reply configured. Done when the declaration matches what your platform actually does.",
      "example": "subscriberOptin: true · subscriberOptout: true · subscriberHelp: true · help_keywords: HELP, INFO",
      "notes": "Three catalog rows, one declaration block: CON-010 (opt-in) is universal except M2M; CON-011 (opt-out) additionally exempts 2FA, which the check applies rather than the applicability tag, since only part of the rule is exempt; CON-012 (help) is universal. The registry spells that use case TWO_FACTOR_AUTH; the catalog spells it 2FA. CON-012 also requires a HELP reply body behind the keyword set — that half is CON-HELP-BACKED, so this rule stops at the keyword set to avoid reporting the same missing message twice. Whether HELP is really answered at runtime is UNDETECTABLE_PRE_SUBMISSION and is not claimed here.",
      "catalogIds": [
        "CON-011",
        "CON-012"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-013",
      "slug": "con-013",
      "title": "Subscriber attributes must agree with the message bodies supplied",
      "statement": "A campaign must not declare a subscriber attribute that its supplied opt-in, STOP and HELP message bodies contradict.",
      "rationale": "The attributes and the reply bodies are two accounts of the same programme, and a reviewer reads them together: declaring that you honour opt-outs while supplying no STOP reply says the declaration was ticked rather than meant. The contradiction usually comes from an integration that sets the flags from a template and leaves the bodies to a human who never filled them in, so the submitter believes both halves are done.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign attributes vs optin/optout/help message bodies",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "AWS",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30887",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Write the reply body for every attribute you declared true, and turn the attribute on for every body you supplied. Done when each of the three pairs agrees: opt-out declared and a STOP confirmation written, HELP declared and a HELP reply written.",
      "example": "subscriberOptout: true · optout_message: \"Acme Coffee Rewards: you are unsubscribed and will receive no further messages. Reply HELP for help.\"",
      "pitfalls": [
        "Supplying a STOP or HELP reply while leaving the matching attribute false is the same mismatch in the other direction, and providers reject it just as readily."
      ],
      "notes": "Judges only the pairs where both facts are known: an attribute that has not been declared yet leaves this UNCLEAR rather than failing, because the missing declaration is already CON-010's finding and reporting it twice tells the user nothing new. The opt-in confirmation body is deliberately not required by the true-attribute direction — only keyword programmes must have one, which is CMP-096.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-017",
      "slug": "con-017",
      "title": "An offline opt-in still needs a findable business behind it",
      "statement": "A brand collecting consent entirely offline must still have a verifiable online presence a reviewer can find.",
      "rationale": "With no opt-in URL to inspect, the website is the only independent evidence that the business exists and does what the campaign says. A brand that is invisible online and collecting numbers on paper is indistinguishable, from a reviewer's side, from one that does not exist — which is why offline programmes are held to a higher bar on the brand record rather than a lower one.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "brand website vs offline consent method",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicability": {
        "consentMethods": [
          "paper",
          "pos",
          "verbal_live",
          "verbal_ivr",
          "employer_hr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by paper form, point of sale, live verbal, IVR and employer / HR.",
      "universal": false,
      "remediation": "Supply a website that names the business, describes what it does, and carries the SMS terms and privacy policy. Where the business genuinely has no site, a complete and consistent listing — a verified profile with the same name, address and phone as the brand record — is what a reviewer will look for instead. Done when the campaign can be corroborated without the opt-in surface.",
      "pitfalls": [
        "A social profile alone rarely satisfies this, because the policy pages have nowhere to live on it."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-023",
      "slug": "con-023",
      "title": "Evidence URLs must resolve without a login",
      "statement": "A submitted evidence URL must resolve, be publicly reachable, and not require authentication.",
      "rationale": "The most common evidence failure in practice is a cloud-storage link that shows a \"request access\" wall to anyone outside the organisation. The submitter tested it while logged in and saw their own file, so the failure is invisible from their side.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact URL",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Set the link to \"anyone with the link can view\", or host the file somewhere public, then open it in a private browsing window to confirm.",
      "pitfalls": [
        "Google Drive and Dropbox default to organisation-only access, which looks fine to you and shows a wall to everyone else.",
        "A viewer page is not the file — link the direct image or PDF."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-024",
      "slug": "con-024",
      "title": "The opt-in URL must serve a certificate that verifies",
      "statement": "The opt-in URL must present a valid, verifiable TLS certificate — not expired, self-signed, or issued for another hostname.",
      "rationale": "A crawler that hits a certificate error stops there and reports the opt-in as unverifiable, so the rejection reads as \"we could not see your consent surface\" rather than as a certificate problem. Brands lose days to that translation, because the page loads perfectly in a browser that has been clicking through the warning for months.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in URL TLS chain",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Bandwidth/DCA",
          "code": "2103",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Renew or reissue the certificate for the exact hostname in the submitted URL, including the www or bare-domain form you actually registered. Test it from outside your network — an internal proxy or a pinned certificate hides the failure from everyone inside. Done when an external SSL checker reports a complete, valid chain.",
      "example": "opt_in_url: https://acmecoffee.com/checkout — certificate valid for acmecoffee.com, chain complete.",
      "pitfalls": [
        "A certificate valid for acmecoffee.com and not for www.acmecoffee.com fails whenever the submitted URL uses the other form, which is the most common version of this.",
        "An expired intermediate still lets most browsers through and fails a strict crawler — the browser test is not the test that matters."
      ],
      "notes": "CRAWLER GAP, now half closed. RuleInput carries per-URL fetch outcomes (`urlFetches`), which WEB-073 and POL-015 read deterministically for the brand and policy hosts. This rule covers the opt-in URL, which is often a third address the crawler is not yet asked to fetch, so it stays judged and returns UNCLEAR until a `urlFetches` entry exists for that URL. Recorded rather than omitted: the obligation is real and the remaining gap is the fetch layer's.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-027",
      "slug": "con-027",
      "title": "The opt-in URL must land on a page that carries the opt-in",
      "statement": "The page at the submitted opt-in URL must contain the opt-in form itself, not merely mention or link to it.",
      "rationale": "A reviewer opens the URL and expects to see the thing being registered. Landing on a homepage, a marketing page, or a page whose signup lives one click further in reads as evidence that could not be produced, and it is rejected without anyone hunting for the real page. Brands submit the wrong URL constantly because the opt-in is a modal or a footer widget and the page they think of as \"the signup page\" is the one that advertises it.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in page DOM",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "AWS",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Bandwidth/DCA",
          "code": "2125",
          "remediable": true
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "qr",
          "third_party"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, QR code and third party.",
      "universal": false,
      "remediation": "Submit the URL of the page the form is actually on, opening the modal first if that is where it lives and using the deep link if one exists. Done when loading that URL in a fresh browser shows the phone field and the consent control without any further clicks.",
      "example": "opt_in_url: https://acmecoffee.com/checkout — not https://acmecoffee.com",
      "pitfalls": [
        "A form that only appears after a delay, a scroll, or an exit-intent trigger is not on the page as far as a crawler is concerned — host a permanent version and register that."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-033",
      "slug": "con-033",
      "title": "Opt-in evidence must be the live surface, not a mockup of it",
      "statement": "The artifact must depict the brand's own working opt-in surface — not stock imagery, a design template, or a mockup of a page that does not exist yet.",
      "rationale": "A designed mockup shows what the brand intends to build, and reviewers approve against what exists. When the campaign starts sending, the real page is whatever was actually shipped, and nobody has ever checked it. Honest brands produce these because the compliance step lands before the launch, which is why the fix is usually a date rather than a design change.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in screenshot vs live page",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30909",
          "remediable": true,
          "generation": "gen1"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Capture the page as it renders in a browser today, at the URL you submitted, with your own copy and product names in it. If the surface is genuinely not live yet, say so in the campaign description and register once it is — a mockup submitted without that statement reads as an attempt to pass off a plan as a page.",
      "pitfalls": [
        "A Figma frame and a browser screenshot look similar at a glance; a reviewer spots the missing browser chrome, placeholder copy, and lorem-ipsum product names immediately."
      ],
      "notes": "Marked [INFERRED] in the research: derived from AWS's placeholder-text ban on samples rather than published in these words. Cite the underlying obligation — evidence must depict the live consent surface — if a user pushes back on the rule as stated.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-034",
      "slug": "con-034",
      "title": "The business name on the artifact must match the registered brand",
      "statement": "The business name visible on the consent artifact must match the registered brand legal name or DBA.",
      "rationale": "An artifact showing a different business is the clearest possible evidence that the consent was collected by someone other than the registrant, which is the consent-transfer problem the framework exists to prevent. It also catches the honest version — a screenshot borrowed from a sister brand because it looked similar enough.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact + brand.company_name",
      "severity": "BLOCKING",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Supply an artifact from the registered brand's own consent surface. If the site trades under a different name, register that name as the DBA so the two match.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-036",
      "slug": "con-036",
      "title": "Platform-hosted evidence must show the end business, not the platform",
      "statement": "Where consent is collected on a platform, agency, or franchisee surface, the evidence must identify the end business the consumer is agreeing to hear from.",
      "rationale": "A consumer looking at a form carrying only the marketing platform's branding cannot tell whose messages they just agreed to, so the consent names nobody and the brand that later sends is not the brand they said yes to. This is the honest version of the consent-transfer problem: the form genuinely is the platform's, so screenshotting it as-is feels like screenshotting the opt-in, and nothing on screen tells you it is not.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact branding",
      "severity": "BLOCKING",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "Twilio",
        "AT&T"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30506",
          "remediable": true
        }
      ],
      "applicability": {
        "consentMethods": [
          "third_party",
          "imported",
          "franchise_agent",
          "chat"
        ]
      },
      "applicabilityText": "Applies when consent was collected by third party, imported list, franchise or agent and chat.",
      "universal": false,
      "remediation": "Re-capture the evidence with the end business's name or logo inside the same frame as the consent control — usually by setting the platform form's header or logo field, or by capturing the branded page the widget is embedded in rather than the bare widget. Done when somebody who has never heard of your platform can name the business from the image alone.",
      "pitfalls": [
        "Naming the brand in the campaign record does not fix the artifact — the reviewer is judging the picture, not the field beside it.",
        "A franchisee form that names only the franchisor fails the same way as an ISV form: the entity on the artifact must be the entity registered."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-038",
      "slug": "con-038",
      "title": "Verbally-collected informational campaigns need the mockup and the messages",
      "statement": "An informational campaign collecting consent by phone must supply both a mockup of the opt-in workflow and the message content that will be sent under it.",
      "rationale": "With no page to crawl and no marketing copy to read, a reviewer assessing a phone opt-in has only two things: how the ask is made and what arrives afterwards. AWS asks for both together because either alone is unfalsifiable — a reasonable script proves nothing if the messages turn out to be promotional, and reasonable messages prove nothing if nobody agreed to them.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact + campaign.sample_messages",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "AWS"
      ],
      "applicability": {
        "consentMethods": [
          "verbal_live",
          "verbal_ivr"
        ],
        "excludeUseCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE"
        ]
      },
      "applicabilityText": "Applies when consent was collected by live verbal and IVR, and the use case is NOT MARKETING, MIXED and SWEEPSTAKE.",
      "universal": false,
      "remediation": "Attach the workflow mockup — the script page, call flow, or agent screen, whichever the consumer's consent actually passes through — and populate the sample messages with the real notifications you intend to send. Done when the two read as one story: the script promises a category of message and the samples are that category.",
      "example": "Attached: the agent screen showing the consent step and the script read from it. Samples: \"Acme Coffee: your service appointment is confirmed for Tue 9am. Reply STOP to opt out, HELP for help.\"",
      "pitfalls": [
        "Samples that are more promotional than the script promised fail the use-case check as well — the script is what scopes the consent, so it is the samples that have to move."
      ],
      "notes": "The catalog conditions this on an informational use case; the registry has no \"informational\" flag, so it is expressed as an exclusion of the promotional use cases. AWS states it for verbal collection only, which the consent-method tag carries.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-040",
      "slug": "con-040",
      "title": "The consent basis must be an explicit opt-in, not an implied one",
      "statement": "The submission must rest on a consumer act that agreed to messaging — not on an existing relationship, a published number, or a prior transaction.",
      "rationale": "Implied consent is the theory behind most of the numbers that generate complaints: the consumer gave a number to book a table or buy a part, and reads the marketing text that follows as a stranger having got hold of it. Carriers therefore treat \"they are our customers\" as no consent at all, and a submission that argues the relationship rather than describing an act is rejected on the argument itself.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow + consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "AWS",
        "Bandwidth",
        "FCC"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Describe the moment the consumer agreed — what they ticked, said, signed or texted, and where — and attach the evidence of it. Where no such moment exists, collect fresh consent before registering: an existing customer list cannot be argued into an opt-in. Done when the flow names an act rather than a relationship.",
      "example": "Customers tick an unchecked box reading \"Text me Acme Coffee offers\" at https://acmecoffee.com/checkout before the order is placed; the ticked state, timestamp and disclosure version are stored against the order.",
      "pitfalls": [
        "\"Customers provide their number when booking\" describes collection, not consent — the number arriving is not the same event as agreeing to be texted."
      ],
      "notes": "The catalog classes this VISION on the toll-free path (Bandwidth TFV 1402). Authored as AI_FORM because the implied-consent claim is made in the message flow rather than visible in the artifact, and the artifact half is already judged by CON-ART-002. Bandwidth applies it specifically to toll-free verification; it is left universal because the underlying FCC standard is.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-041",
      "slug": "con-041",
      "title": "The opt-in form must have a phone-number field",
      "statement": "The opt-in form must collect a mobile number through a field of its own.",
      "rationale": "A form with no number field cannot be where SMS consent is collected, whatever its consent text says — so the registration points at a surface that does not do what it claims. The usual cause is honest: the brand registered their newsletter page, where the only field is an email address, because that is where the SMS checkbox was added.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in form phone input",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "Bandwidth",
        "Ringover"
      ],
      "codes": [
        {
          "provider": "Bandwidth/DCA",
          "code": "2139",
          "remediable": true
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "qr",
          "third_party"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, QR code and third party.",
      "universal": false,
      "remediation": "Add a mobile-number input to the form the consent control sits on, and label it as a mobile number rather than a generic \"phone\". Done when a consumer can give you a number and their agreement in the same submission.",
      "pitfalls": [
        "Collecting the number on a later step than the consent control splits the two, and a reviewer looking at the registered page sees consent with nothing to attach it to."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-042",
      "slug": "con-042",
      "title": "The phone field must be optional on a general-purpose form",
      "statement": "On a form that exists for something other than SMS signup, the phone-number field must not be required to submit.",
      "rationale": "A required number on a contact or quote form takes the number as the price of the enquiry, and everything downstream treats that as a collected lead rather than an opt-in. Bandwidth states it flatly — phone numbers cannot be a required field on the website where opt-in is collected — because a number given under compulsion cannot be told apart later from one given willingly.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in form phone field required attribute",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Bandwidth",
        "Telnyx",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30931",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "Twilio",
          "code": "30923",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "account_settings",
          "third_party"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, account settings and third party.",
      "universal": false,
      "remediation": "Drop the required attribute and the asterisk from the phone input on any form whose purpose is not SMS signup, and confirm the form submits without it. Done when a visitor can send you an enquiry giving only an email address.",
      "pitfalls": [
        "A form whose entire purpose IS SMS signup may require the number — the field is the point of the form, and this rule does not apply to it."
      ],
      "notes": "DIVERGENCE, canonical form taken: Bandwidth forbids a required phone field outright; Telnyx and the website-evidence research allow one provided the SMS consent control is itself optional. The strict-superset rule takes Bandwidth, so this fires wherever the form has another purpose. Where the phone field genuinely must stay required for that purpose, CON-043 and CON-044 are the rules that make it survivable.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-043",
      "slug": "con-043",
      "title": "A mandatory phone field needs its own separate, optional SMS opt-in",
      "statement": "Where the phone field is mandatory for another purpose, an additional and separately optional SMS consent control is required.",
      "rationale": "A phone number collected for delivery coordination is not consent to be marketed to, so the two must be separable. Businesses frequently reason that because the number is required, the consent is implied — which is precisely the inference the rule exists to block.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "FCC",
        "CTIA",
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Keep the phone field mandatory for its operational purpose, and add a separate optional checkbox for messaging consent beside it.",
      "example": "Phone number (required — for delivery updates)\n☐ Also text me promotional offers from Acme Coffee (optional).",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-044",
      "slug": "con-044",
      "title": "A required phone field must carry an SMS disclaimer beside it",
      "statement": "Where the phone-number field is mandatory, the text next to it must say whether the number will be used for text messages.",
      "rationale": "Somebody typing a mandatory number needs to know at that moment what it will be used for — a number given for a delivery call is not a number given for marketing texts, and the difference is decided by what was written beside the box. This is the disclosure half of the required-field problem: even a form that legitimately needs the number owes the consumer that sentence.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "text adjacent to the phone field",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Telnyx",
        "Zoom (ISV)"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "qr",
          "third_party"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, QR code and third party.",
      "universal": false,
      "remediation": "Put a one-line disclaimer directly under the phone input saying what the number is for and whether texts are part of it. Done when the sentence sits within the field's own block rather than in a disclosure lower down the page.",
      "example": "Mobile number (required — we text delivery updates to this number). Marketing texts are separate and optional; see the box below.",
      "pitfalls": [
        "A disclaimer that appears only after the field is focused or filled is not present at the moment the consumer decides to type."
      ],
      "notes": "Distinct from CON-043, which requires a separate optional CONTROL where the number is mandatory. This rule is about the TEXT beside the field, and a form can satisfy one and fail the other.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-045",
      "slug": "con-045",
      "title": "The opt-in page must be reachable without logging in",
      "statement": "The registered opt-in page must load for an anonymous visitor, not sit behind a login, paywall, or member area.",
      "rationale": "Reviewers verify anonymously, so a page that renders perfectly for you and shows a sign-in wall to them is, from their side, no evidence at all. It is a silent failure: the submitter tests the link while logged in, sees their own form, and cannot reproduce the rejection.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in page auth state",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Telnyx",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Telnyx",
          "code": "804",
          "remediable": true
        },
        {
          "provider": "Twilio",
          "code": "30922",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "chat",
          "social",
          "email"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party, chat, social and email.",
      "universal": false,
      "remediation": "Either move the opt-in to a public page, or keep it gated and supply a hosted screenshot instead, saying in the message flow that the surface is login-gated and the screenshot is attached. Done when you can open the URL in a private browsing window and see the form.",
      "pitfalls": [
        "A preference centre inside a customer account is legitimately gated — that case is served by attaching the screenshot, not by making the account public."
      ],
      "notes": "Where the surface genuinely is gated, CMP-065 (hosted evidence) and CMP-127 (declare it) are the rules that carry the registration, and this one is discharged by that route rather than failed.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-048",
      "slug": "con-048",
      "title": "Every page that collects a number needs consent language",
      "statement": "SMS opt-in language and a consent control must appear on every page of the site that collects a mobile number, not only the page named in the registration.",
      "rationale": "Numbers reach the sending list from every form on the site — contact, booking, quote, donation, callback — and the ones collected on unlabelled forms carry no consent at all. Reviewers crawl for phone inputs rather than trusting the registered URL, which makes this the single highest-yield finding in the corpus, and the one brands are most surprised by: they fixed the signup page and never thought of the contact form.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "all pages containing a phone input",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Telnyx",
        "Commio",
        "Bird"
      ],
      "codes": [
        {
          "provider": "Telnyx",
          "code": "803",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Inventory every form on the site that takes a phone number, and add the consent control and disclosure to each one — or remove the phone field from the forms that do not need it, which is usually the cheaper fix. Done when a site-wide search for phone inputs returns nothing without a consent block beside it.",
      "pitfalls": [
        "Forms embedded from a booking or scheduling vendor are the ones most often missed, because nobody thinks of them as pages on the site."
      ],
      "notes": "Needs a whole-site crawl for phone inputs. The current crawler fetches the registered page only, so this rule will return UNCLEAR in production until that lands — recorded here rather than omitted, because the requirement is real and the gap is the crawler's.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-049",
      "slug": "con-049",
      "title": "Secondary collection pages owe the full disclosure, not a token line",
      "statement": "The consent language on a secondary phone-collecting page must carry the opt-out instruction and the policy links, not merely mention texting.",
      "rationale": "Having added a line to the contact form, brands stop there — so the secondary pages end up with \"we may text you\" and none of the elements that make an opt-in valid. A consumer who consents on that page has been given materially less than one who consented on the signup page, and their consent is correspondingly weaker.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "secondary phone-collecting pages",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Telnyx"
      ],
      "codes": [
        {
          "provider": "Telnyx",
          "code": "803",
          "remediable": true
        },
        {
          "provider": "Telnyx",
          "code": "861",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "dependsOn": [
        "CON-048"
      ],
      "remediation": "Reuse the same consent block on every form rather than writing a shorter one per page — one snippet, included everywhere, is both less work and the only way the pages stay in step when the wording changes. Done when the contact form shows the same disclosure as the signup page.",
      "example": "Include the same block used at checkout: consent sentence, \"Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe, HELP for help.\", and links to the Acme Coffee Terms of Service and Privacy Policy.",
      "notes": "Depends on CON-048: until we know which secondary pages exist, there is nothing to judge the wording of. Subject to the same whole-site crawl limitation.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-059",
      "slug": "con-059",
      "title": "The consent control label must name the programme, not just contact",
      "statement": "The label on the consent control must say what the consumer is subscribing to — a bare \"Text me\" or \"Contact me\" is not specific enough.",
      "rationale": "The label is the only sentence many consumers read before ticking, so it is the whole of what they agreed to. \"We may contact you\" agrees to nothing in particular, which means the brand cannot later show that recurring marketing was within it — and Bandwidth reads the same defect as a failure to name the specific message programme.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent checkbox label text",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Telnyx",
        "Bandwidth",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Telnyx",
          "code": "611",
          "remediable": true
        },
        {
          "provider": "Twilio",
          "code": "30513",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Rewrite the label to name the brand and what the messages are about. Done when the label alone, with the rest of the page covered up, tells a stranger who will text them and why.",
      "example": "☐ Text me Acme Coffee offers and rewards updates.",
      "pitfalls": [
        "\"I agree to receive SMS messages\" names the channel but not the programme, and Bandwidth rejects it for the same reason as \"Contact me\"."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-060",
      "slug": "con-060",
      "title": "The opt-in language must actually say SMS or text message",
      "statement": "The consent wording must name text messaging explicitly rather than referring generally to being contacted.",
      "rationale": "Consent runs to a channel. Agreeing to be \"contacted\" or to \"receive updates\" does not agree to texts, and the carriers reading that wording cannot tell whether the consumer expected a phone call, an email, or nothing at all. Twilio rejects it under a code whose whole description is that the opt-in flow does not explicitly mention SMS — it is a wording defect with a one-word fix that brands miss because they know what they meant.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "CTIA"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30513",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Put the words \"text messages\" or \"SMS\" into the consent sentence itself. Done when the sentence names the channel without relying on the page around it — a heading saying \"SMS signup\" above a box that says \"keep me updated\" does not carry it.",
      "example": "I agree to receive recurring automated marketing text messages (SMS) from Acme Coffee.",
      "pitfalls": [
        "An email opt-in reused for SMS is the usual source: the wording was written for a newsletter and the channel word was never added."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-063",
      "slug": "con-063",
      "title": "Labelling the consent control \"optional\" pre-empts the gating rejection",
      "statement": "The messaging consent control should be labelled optional where the form around it collects anything required.",
      "rationale": "Reviewers decide whether a control is required by looking at it, not by submitting the form, so a consent box that sits in a column of asterisked fields reads as required even when it is not. The word \"optional\" is what Twilio itself offers as the fix for that rejection, which makes it the cheapest way to avoid an argument you would otherwise win slowly.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent checkbox label",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30923",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Add \"(optional)\" to the consent control's label, and remove any asterisk or required marker near it. Done when the label says optional in words rather than relying on the absence of an asterisk.",
      "example": "☐ Text me Acme Coffee offers and rewards updates (optional).",
      "notes": "Twilio documents this as a solution to error 30923 rather than as an independent requirement, so it is graded MEDIUM and worded as a recommendation. The requirement it protects — that consent is genuinely not required — is CON-NOT-GATED.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-064",
      "slug": "con-064",
      "title": "A kiosk or terminal must not pre-fill the consumer's number",
      "statement": "A payment terminal or kiosk collecting messaging consent must require the consumer to enter their number, not present one already filled in.",
      "rationale": "A number the terminal already knows — from the card, the loyalty account, or the last transaction — turns the consent step into a confirmation of something the consumer never supplied for this purpose. They tap Yes to a number on screen without deciding to hand it over, and the resulting record cannot show that they did.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "kiosk consent screen",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30925",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "consentMethods": [
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by point of sale.",
      "universal": false,
      "remediation": "Configure the terminal to present an empty number field at the consent step, even where the number is already on the account. Done when the screenshot shows a blank field and a keypad rather than a masked number and a Confirm button.",
      "pitfalls": [
        "Masking the pre-filled number does not fix it — the consumer still did not type it, and a reviewer reads the mask as evidence the number came from somewhere else."
      ],
      "notes": "Sourced from vendor guidance rather than published carrier text; the underlying obligation is that consent must be an affirmative act by the consumer, which the pre-filled field removes. Cite that if a user pushes back on the rule as stated.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-070",
      "slug": "con-070",
      "title": "Declining messages must not degrade the service afterwards",
      "statement": "A consumer who declines SMS at signup must retain the same access to the underlying service as one who accepted.",
      "rationale": "Consent that is free at the form and expensive afterwards is not free. Where declining quietly costs the customer their booking reminders, their delivery window or their account alerts, the pressure to accept is real even though every control on the page was optional — and the consumer discovers it only after they have chosen.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "post-signup service access",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM",
        "HUMAN"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "FCC"
      ],
      "applicability": {
        "excludeUseCases": [
          "TWO_FACTOR_AUTH",
          "SECURITY_ALERT",
          "FRAUD_ALERT"
        ]
      },
      "applicabilityText": "Applies when the use case is NOT TWO_FACTOR_AUTH, SECURITY_ALERT and FRAUD_ALERT.",
      "universal": false,
      "remediation": "Walk the journey yourself with the box unticked: create the account, place the order, make the booking, and check that everything a subscriber would receive still reaches you by another channel. Fix whatever only arrives by text. Done when the two journeys differ in the channel and nothing else.",
      "notes": "DETECTABLE ONLY BY THE CUSTOMER. Nothing we can crawl shows what happens to an account after signup, so this is surfaced as a warning with the test the user must run themselves: sign up twice, once declining, and compare what the declining account can do and receive. Twilio applies it as the post-signup half of the same standard CON-069 tests at the form.",
      "phase": "approval",
      "automated": true,
      "attestation": {
        "question": "Have you walked the signup yourself with the SMS box left unticked, and confirmed the account still gets everything a subscriber gets, by some other channel?",
        "howToCheck": [
          "Create two accounts, place two orders or make two bookings: one accepting SMS, one declining.",
          "Compare what each receives and can do — confirmations, reminders, delivery windows, account alerts, support access.",
          "Anything the declining account never receives at all is the defect. Move it to email or in-app."
        ],
        "failureLooksLike": "The declining customer gets no appointment reminder, because reminders were only ever built as texts. Every control on the form was optional, and declining still cost them the service."
      }
    },
    {
      "id": "CON-071",
      "slug": "con-071",
      "title": "The decline path must be as usable as the accept path",
      "statement": "The control that lets a consumer skip or decline messaging must not be disabled, greyed out, or hidden.",
      "rationale": "A greyed-out \"No thanks\" is a refusal the interface has already made for the consumer, and it produces opt-ins that look voluntary in the data and were not. Design teams reach for the muted style to steer people toward the primary action without realising that here the primary action is a legal consent, where steering is the violation.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "decline/skip control rendering",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "FCC"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30931",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "excludeConsentMethods": [
          "verbal_live",
          "verbal_ivr",
          "keyword",
          "qr",
          "imported"
        ]
      },
      "applicabilityText": "Applies when consent was NOT collected by live verbal, IVR, text-to-join keyword, QR code and imported list.",
      "universal": false,
      "remediation": "Render the decline control enabled, at a legible contrast, and in the same visual weight class as the accept control. Keep it in the same place on the screen — a \"No thanks\" moved below the fold is hidden even when it is styled correctly.",
      "pitfalls": [
        "Making the decline control a plain text link beside a large button is the usual compromise, and it is normally accepted; making it grey-on-grey or 10px is not."
      ],
      "notes": "Excluded from the methods where declining means simply not acting — a caller who says no, a consumer who never texts the keyword, a code nobody scans. There is no rendered control to grey out, so the rule would be asking a question the registration cannot answer. The catalog states the same carve-out as CON-069's method list.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-072",
      "slug": "con-072",
      "title": "An alternative to SMS must exist where the service needs to reach the consumer",
      "statement": "A programme must not make receiving text messages the only way to sign up or to be served, with no other channel offered.",
      "rationale": "A consumer who must accept texts because the confirmation, the code or the receipt arrives no other way has not chosen SMS — they have chosen the service. The defect is invisible to the usual checks because there is often no consent control to mark optional: the coercion lives in the product design rather than in the form, and the brand reads their own flow as \"we just text people their booking\".",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "signup flow alternatives",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "FCC",
        "Twilio"
      ],
      "applicability": {
        "excludeUseCases": [
          "TWO_FACTOR_AUTH",
          "SECURITY_ALERT",
          "FRAUD_ALERT"
        ]
      },
      "applicabilityText": "Applies when the use case is NOT TWO_FACTOR_AUTH, SECURITY_ALERT and FRAUD_ALERT.",
      "universal": false,
      "remediation": "Offer at least one non-SMS route to the same outcome — email the confirmation, show it on screen, or let the customer pick a channel — and say so where the number is collected. Done when a customer who never gives a mobile number can still complete the signup and receive whatever the text would have carried.",
      "pitfalls": [
        "Offering an alternative that is worse on purpose (\"email delivery may take up to 5 days\") is the same coercion with a fig leaf, and reads that way to a reviewer.",
        "A 2FA or fraud-alert programme genuinely has no alternative channel — those use cases are excluded from this rule rather than argued out of it."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-074",
      "slug": "con-074",
      "title": "The \"not a condition of purchase\" claim must be true in practice",
      "statement": "Where the disclosure says consent is not a condition of purchase, the form or checkout must actually complete with the SMS box unticked.",
      "rationale": "Ranked #7 most-missed. The sentence is necessary but not sufficient: reviewers test the behaviour, and a form that validates the consent box as required contradicts its own disclosure. Passing the wording check while failing the behaviour is the classic false green.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface behaviour",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "FCC",
        "TCR",
        "Twilio",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Remove required-field validation from the consent control and submit the form with it unticked to confirm it completes. Fix the form, not the sentence.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-075",
      "slug": "con-075",
      "title": "A promotion must be open to people who do not join the SMS programme",
      "statement": "Participation in a promotion, loyalty scheme or offer must not require the consumer to be enrolled in text messaging.",
      "rationale": "T-Mobile puts it flatly: participation in text promotions should never be a requirement. When the only way to get the member price is to be on the list, the enrolment is the price of the discount rather than a decision about messaging, and the carrier reads the resulting numbers as coerced. Brands arrive here by building the offer around the channel — the promotion genuinely runs over SMS — without noticing they have made the channel compulsory.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "promotion terms; CTA copy",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "T-Mobile",
        "AT&T",
        "FCC"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30475",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Give the promotion a second route in — a web account, an email sign-up, a code at the till — and price it the same. Keep the SMS enrolment as one way to participate rather than the gate. Done when the terms describe SMS as optional and a non-subscriber can claim the same offer.",
      "example": "Join Acme Coffee Rewards online, in store, or by text. Members get 10% off however they joined; text alerts are optional and you can reply STOP at any time.",
      "pitfalls": [
        "An SMS-only tier that is materially better than every other tier is a requirement in practice, whatever the terms say."
      ],
      "notes": "Distinct from CON-076: there the prize is what buys the opt-in, here the opt-in is what buys the promotion. They fail in opposite directions and are fixed differently — 076 by decoupling the entry, this one by opening a second route in.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-076",
      "slug": "con-076",
      "title": "Opt-in must not be bought with a prize or giveaway entry",
      "statement": "A messaging opt-in must not be offered in exchange for entry to a prize draw, giveaway, raffle or contest.",
      "rationale": "An opt-in given to enter a draw says nothing about wanting the messages, so the list that results behaves like a purchased one: high opt-out rates, high complaint rates, and recipients who do not recognise the sender by the second send. The research names this the highest-frequency trap for legitimate brands, because \"enter to win — text WIN to join\" is a normal-looking retail promotion that nobody involved thinks of as a compliance decision.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in offer copy",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "CTIA",
        "T-Mobile"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30945",
          "remediable": false,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Separate the two decisions: let people enter the draw without joining the list, and offer the messaging opt-in beside it as its own optional control with its own disclosure. Done when the entry form completes with the SMS box unticked and the prize is never described as what the opt-in earns.",
      "example": "☐ Enter me in the monthly Acme Coffee hamper draw.\n☐ Separately, text me Acme Coffee offers. Consent is not a condition of entry. Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe.",
      "pitfalls": [
        "Making the draw entry the reward for opting in and the opt-in optional \"in theory\" still fails — the question is what the copy offers, not what the checkbox allows.",
        "A genuine sweepstakes can be registered, under the sweepstakes use case with official rules; what cannot be done is paying for opt-ins with entries."
      ],
      "notes": "Twilio 30945 is non-remediable at that provider — the campaign cannot be resubmitted once rejected for it — which is why catching it before submission matters more here than for most rules. Whether contest content in the samples needs the sweepstakes use case is MSG-155, not this rule.",
      "catalogIds": [
        "MSG-208"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-078",
      "slug": "con-078",
      "title": "Printed and in-store consent must not gate the transaction",
      "statement": "Paper forms, till screens and printed advertising must not make SMS consent a condition of the purchase, the discount, or completing the form.",
      "rationale": "The counter is where consent is most easily coerced and least easily evidenced: a customer being asked in front of a queue for their number to \"finish the transaction\" says yes to get out of the shop. Nothing about that is legible afterwards, which is exactly why carriers judge the printed artwork and the terminal screen rather than the brand's account of what staff say.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "paper form copy; POS screen; print CTA artwork",
      "severity": "BLOCKING",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "paper_consent_form",
      "authorities": [
        "FCC",
        "T-Mobile",
        "Klaviyo"
      ],
      "applicability": {
        "consentMethods": [
          "paper",
          "pos",
          "employer_hr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by paper form, point of sale and employer / HR.",
      "universal": false,
      "remediation": "Reprint the form or artwork so the messaging tick box sits apart from anything required, carrying \"Consent is not a condition of any purchase.\" Change the till prompt so staff can complete the sale without the number, and brief them that \"skip\" is a normal answer. Done when a customer who declines gets the same price and the same receipt.",
      "pitfalls": [
        "Artwork reading \"Text JOIN to 55512 for 20% off\" makes the discount conditional on the opt-in even where the paper form beside it is clean — the print is the CTA a reviewer judges.",
        "A required phone line on an intake or warranty form gates it just as effectively as a tick box does, because staff will not hand back an incomplete form."
      ],
      "catalogIds": [
        "CON-077",
        "CON-079"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-080",
      "slug": "con-080",
      "title": "The disclosure must name the programme the consumer is joining",
      "statement": "The point-of-consent disclosure must carry a programme or product description — what this particular messaging programme is.",
      "rationale": "CTIA lists the programme description first among the call-to-action elements because it is what the consumer will recognise later: the name in the confirmation text, in the HELP reply, and on the unsubscribe page. Without it a consumer who joined three programmes from one brand cannot tell which one is texting them, and the opt-out they send lands against the wrong list.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "T-Mobile",
        "TCR",
        "AWS",
        "Bandwidth",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Name the programme in the consent sentence and use that same name in the opt-in confirmation, the HELP reply and the terms. Where the programme has no name, describe the product instead — \"coffee subscription updates\" is a description; \"updates\" is not. Done when the same words appear at the point of consent and in the first message that arrives.",
      "example": "☐ Join Acme Coffee Rewards: text me offers and rewards balance updates.",
      "pitfalls": [
        "Naming the programme only in the page heading leaves the consent sentence generic, and the sentence is what a reviewer quotes."
      ],
      "notes": "Distinct from CON-DISC-PURPOSE, which asks for the message CATEGORY (marketing, reminders, order updates). This asks which programme — CTIA MPBP §5.1.1(1) treats them as separate elements, and a disclosure can name a category without naming a programme.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-088",
      "slug": "con-088",
      "title": "Customer-care contact must be reachable from the point of consent",
      "statement": "The call-to-action must give the consumer a way to reach a person — a support email, phone number, or help page.",
      "rationale": "A consumer who wants to ask a question before agreeing, or to complain afterwards, needs somewhere that is not the messaging channel itself. Where there is nowhere, the complaint goes to the carrier instead, and carrier complaints are the input that throttles a campaign. CTIA lists it as a call-to-action element for that reason rather than as a courtesy.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "T-Mobile",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add a support email or phone number to the consent block, or link a contact page from inside it. Use the same contact that your HELP auto-reply gives, so the two agree. Done when a consumer can reach you without having joined the programme first.",
      "example": "Questions? Email support@acmecoffee.com or call 415-555-0134. Reply STOP to unsubscribe, HELP for help.",
      "pitfalls": [
        "Pointing only at the HELP keyword is circular for someone deciding whether to opt in — they cannot text HELP to a programme they have not joined."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-090",
      "slug": "con-090",
      "title": "The disclosure should say which number the messages come from",
      "statement": "The call-to-action should state the phone number or short code the programme will send from.",
      "rationale": "An unrecognised number is the most common reason a legitimate message gets reported as spam. Telling the consumer at signup which number to expect is what lets them recognise the first message instead of blocking it, and it is the cheapest protection a programme has against its own delivery rates.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text + campaign number set",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "T-Mobile"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add the sending number or short code to the consent block, and update it if you change numbers. Where you send from a pool, say so and name the range or the short code rather than listing every number. Done when the consumer knows what will appear on their screen.",
      "example": "Messages come from short code 55512. Msg frequency varies. Msg & data rates may apply.",
      "pitfalls": [
        "Publishing a number you later migrate away from is worse than publishing none — treat the disclosure as something to keep current, not to set once."
      ],
      "notes": "Graded MEDIUM, matching the catalog. CTIA lists it as element (2) of the call to action but no provider rejects on it alone, so it is surfaced as an improvement rather than a blocker.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-093",
      "slug": "con-093",
      "title": "The policy links must say which document they open",
      "statement": "The links to the Privacy Policy and the Terms & Conditions must be labelled as those documents, and the pages they open must title themselves the same way.",
      "rationale": "A consumer deciding whether to read the terms needs to know that is what the link is. \"Learn more\", \"details\", or a bare \"here\" tells them nothing, and a reviewer checking whether the required links are present cannot confirm it either. The document side matters for the same reason: a page reachable from a link labelled Privacy Policy that never calls itself one is not obviously the policy at all.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "link text and document titles of the policy links",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA"
      ],
      "applicability": {
        "excludeConsentMethods": [
          "verbal_live",
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was NOT collected by live verbal and IVR.",
      "universal": false,
      "remediation": "Use the document names as the link text — \"Privacy Policy\" and \"Terms of Service\" — and make sure each page carries the matching title as a heading. Done when both the link and the page it opens use the same name.",
      "example": "By checking this box you agree to Acme Coffee's <a href=\"/sms-terms\">Terms of Service</a> and <a href=\"/privacy\">Privacy Policy</a>.",
      "pitfalls": [
        "Bundling both documents behind one link labelled \"our policies\" fails even when the destination contains both, because the consumer cannot tell what they are agreeing to before they click."
      ],
      "notes": "Excluded from the verbal methods, which have no link text to label — a script names the policy aloud instead, which CON-VERBAL-ELEMENTS already checks as its eighth element.",
      "catalogIds": [
        "POL-032",
        "POL-120"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-094",
      "slug": "con-094",
      "title": "The policy links at the opt-in must open real policy pages",
      "statement": "The Terms and Privacy Policy links beside the consent control must resolve to live pages carrying those documents — not 404s, placeholders, or unfinished templates.",
      "rationale": "A dead policy link is worse than a missing one: the consent block claims the documents exist and the reviewer proves they do not, which puts the whole submission's accuracy in question rather than just the link. It happens most on sites where the policies were generated during a rebuild and the routes changed afterwards.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "policy links on the opt-in surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_POLICY",
      "artifact": "privacy_policy",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Open both links from a private browsing window and confirm each returns a real, finished document. Fix the routes rather than the link text, and check for template markers — a generated policy that still says {{COMPANY_NAME}} resolves fine and fails just as hard. Done when both links return a page that names your business.",
      "pitfalls": [
        "A link that redirects to the homepage rather than 404ing looks healthy to a link checker and is treated as a missing policy by a reviewer."
      ],
      "notes": "Partially settleable today: where the policy text has been fetched, this can be judged from the content. Where the fetch failed, the registry carries no HTTP status, so the rule returns UNCLEAR rather than assuming a 404 — the same crawler gap CON-024 records.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-095",
      "slug": "con-095",
      "title": "The no-sharing statement must be reachable from the consent point",
      "statement": "The disclosure, or the privacy policy it links to, must state that mobile information is not shared with third parties for marketing purposes.",
      "rationale": "This is the single clause carriers care most about, because number-sharing is the mechanism behind most of the traffic 10DLC exists to suppress. It has to be findable from the opt-in rather than buried, since it is the promise the consumer is relying on when they hand over the number — and it is the clause free policy generators are least likely to include.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text; privacy policy body",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_POLICY",
      "artifact": "privacy_policy",
      "authorities": [
        "Telnyx",
        "Bandwidth",
        "Twilio",
        "AWS",
        "Sinch",
        "Infobip",
        "Bird"
      ],
      "codes": [
        {
          "provider": "Telnyx",
          "code": "805",
          "remediable": true
        },
        {
          "provider": "Twilio",
          "code": "30908",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add the sentence \"Mobile information will not be sold or shared with third parties for promotional or marketing purposes.\" to the privacy policy, and make sure the opt-in links to that policy. \"Sold\" alone is not enough — Telnyx requires both words, because sharing without payment is the case that actually happens.",
      "example": "We will not sell or share your mobile information with third parties for promotional or marketing purposes. Text messaging originator opt-in data is not shared with any third parties.",
      "pitfalls": [
        "A general \"we do not sell your personal data\" clause does not satisfy this — the clause must name mobile information or phone numbers specifically."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-096",
      "slug": "con-096",
      "title": "Nothing in the flow may contradict the no-sharing promise",
      "statement": "No part of the opt-in surface or its linked policy may indicate that opt-in data is shared with third parties.",
      "rationale": "A policy routinely carries the required no-sharing sentence in its SMS section while a general data-sharing clause elsewhere says the opposite, and reviewers read the whole document and treat the permissive clause as controlling. A checker that only looks for the good sentence therefore passes a policy that will be rejected — which is worse than not checking, because the brand submits believing it is covered.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in surface + linked privacy policy",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_POLICY",
      "artifact": "privacy_policy",
      "authorities": [
        "AWS",
        "Twilio",
        "GoHighLevel"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "dependsOn": [
        "CON-095"
      ],
      "remediation": "Find the permissive clause and carve mobile data out of it explicitly, rather than adding a second sentence that contradicts it. Done when the sharing section itself says mobile information is excluded — a reviewer reading only that section reaches the right answer.",
      "example": "We may share aggregated, non-identifying data with partners. This sharing expressly excludes mobile phone numbers and SMS opt-in data, which are never shared with third parties for marketing purposes.",
      "pitfalls": [
        "A cookie or advertising-partner section is where this usually hides — the SMS section is clean and the marketing section three headings earlier is not."
      ],
      "notes": "The inverse trap, on the consent surface rather than the policy page. Depends on CON-095: until the no-sharing statement is located, there is nothing for a contradiction to contradict. POL-064 states the same trap for the policy document read on its own.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-099",
      "slug": "con-099",
      "title": "The opt-in and its advertising must not mislead",
      "statement": "The consent disclosure and the programme advertising must not misrepresent what the programme is, what it costs, or what the consumer gets.",
      "rationale": "Deceptive opt-in copy produces subscribers who did not understand what they joined, and they behave exactly like people who never opted in: they complain, they report, and they tell the carrier the message was unsolicited. CTIA bans it at the call to action rather than only in the messages because the deception that matters most happens before consent, where it manufactures the consent itself.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text; programme advertising copy",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "T-Mobile",
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Make the copy describe the programme accurately: what arrives, how often, what it costs, and what the consumer has to do. Remove anything implying a benefit the programme does not deliver or a cost it does not carry. Done when someone who reads only the CTA is not surprised by the first message.",
      "example": "Join Acme Coffee Rewards for offers and your rewards balance. Msg frequency varies. Msg & data rates may apply. No purchase necessary to join.",
      "pitfalls": [
        "Describing a paid programme as \"free\" is the specific case with its own rule and its own penalty — CON-101 — but any overstated benefit fails here."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-101",
      "slug": "con-101",
      "title": "\"Free\" must not be used loosely in the call to action",
      "statement": "The word \"free\" must not appear in the CTA except for genuine free-to-end-user programmes; synonyms must be paired with the rates disclosure.",
      "rationale": "Improper use of \"free\" is a standalone audit violation because it contradicts the message-and-data-rates disclosure sitting beside it — the consumer is told the programme is free and that it may cost them money. Synonyms like \"complimentary\" and \"no charge\" carry the same problem.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow + consent disclosure",
      "severity": "MEDIUM",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "CTIA",
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Remove \"free\" from the CTA, or pair it with the rates disclosure so the two statements do not contradict.",
      "example": "Join our complimentary rewards texts. Message and data rates may apply.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-108",
      "slug": "con-108",
      "title": "The disclosure must be on the same page as the phone-number field",
      "statement": "The consent disclosure must appear on the same page, popup, or form as the phone-number field — not on a separate linked page.",
      "rationale": "Consent is given at the moment the number is submitted, so a disclosure the consumer would have to navigate away to read was not part of that decision. This is subtly different from the terms-link rule: here the disclosure text itself is on another page.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Move the disclosure text onto the same form as the phone field, immediately beside the consent control.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-109",
      "slug": "con-109",
      "title": "The disclosure must sit next to the button the consumer presses",
      "statement": "The consent language must appear directly beneath the phone field or immediately above the submit control.",
      "rationale": "Consent is given at the instant of submitting, so the words that count are the ones in view at that instant. A disclosure at the top of a long form has scrolled away by the time the consumer acts, which is why the placement is specified as a position relative to the button rather than as presence on the page.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "disclosure position relative to the submit control",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Klaviyo",
        "Infobip",
        "Salesmsg",
        "Quo"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Move the disclosure into the gap between the last input and the submit button. Done when a screenshot cropped to the submit button still contains the whole disclosure.",
      "pitfalls": [
        "Long forms pass on desktop and fail on mobile, where the same block falls a full screen above the button — check the narrow viewport before capturing evidence."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-110",
      "slug": "con-110",
      "title": "The disclosure must be visible without the consumer opening anything",
      "statement": "The consent disclosure must be rendered on the page as it loads — not behind a tooltip, an accordion, a \"read more\" toggle, or pushed out of the main content.",
      "rationale": "A disclosure the consumer has to reveal is one nearly all of them never see, and the law asks what a reasonable consumer would notice rather than what the page technically contains. Design teams collapse it in good faith, because a five-line legal block ruins a checkout — which is why the fix is usually about where the text sits rather than whether anyone wanted to hide it.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "disclosure rendering and DOM position",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Attentive",
        "Twilio",
        "Infobip",
        "FCC"
      ],
      "applicability": {
        "excludeConsentMethods": [
          "verbal_live",
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was NOT collected by live verbal and IVR.",
      "universal": false,
      "remediation": "Render the disclosure expanded by default in the main content, beside the control. Where the block is too long for the layout, shorten the wording rather than collapsing it — every required element fits in about forty words. Done when the text is readable on first paint with nothing clicked.",
      "example": "☐ Text me Acme Coffee offers. Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe, HELP for help. Terms · Privacy",
      "pitfalls": [
        "An accordion that is open by default still fails on mobile, where the same component usually ships collapsed."
      ],
      "notes": "Excluded from the verbal methods, which render nothing — a spoken script has no default state to reveal. Paper, POS and printed CTAs stay in scope: fine print on the reverse of a form is the same defect in another medium.",
      "catalogIds": [
        "CON-111"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-113",
      "slug": "con-113",
      "title": "The disclosure must read as a disclosure, not as more marketing copy",
      "statement": "The consent disclosure must be clear and conspicuous, and set apart from the advertising copy and any other disclosures around it.",
      "rationale": "This is the legal standard the specific placement rules exist to serve, and it catches the cases they miss: a disclosure that is present, visible, adjacent, and still lost inside a paragraph of promotional text. A consumer skimming an offer does not parse a sentence about message rates buried in the middle of it, so the words were technically supplied and functionally absent.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "rendered disclosure",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "FCC",
        "CTIA",
        "T-Mobile",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Give the disclosure its own block: its own lines, separated from the promotional copy and from any other agreement text on the page. Done when a reader can point to where the marketing stops and the terms begin.",
      "example": "Get 20% off your first order when you join Acme Coffee Rewards.\n\n☐ Text me Acme Coffee offers. Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe, HELP for help.",
      "pitfalls": [
        "Merging the SMS disclosure into the same paragraph as the email and cookie notices makes all three unreadable, and reviewers treat the SMS one as the casualty."
      ],
      "notes": "The standard itself rather than one of its mechanical proxies, so it is deliberately the last resort: where CON-107, CON-109 and CON-110 all pass and the disclosure is still not conspicuous, this is the rule that says so.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-123",
      "slug": "con-123",
      "title": "Every entity allowed to send must be named in the consent",
      "statement": "The consent language must name each business that will send under it, not only the one the consumer is transacting with.",
      "rationale": "AT&T requires consent to explicitly name the entities authorised to send, because the consumer's expectation is set by the name they read. A franchise group, a dealer network or a parent with several trading brands routinely collects once and sends from all of them, and every message from a name the consumer never saw reads to them as a leak of their number.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AT&T",
        "T-Mobile"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30506",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "List each sending entity by name in the consent sentence, or narrow the programme so only the named brand sends. Where the list is long, name the group and link a page that enumerates the members — the page must be reachable before the consumer agrees. Done when every number that will appear as a sender traces to a name in the disclosure.",
      "example": "By checking this box you agree to receive recurring automated marketing texts from Acme Coffee and from your local Acme Coffee franchise location.",
      "pitfalls": [
        "Naming a parent company the consumer has never heard of instead of the trading name they recognise satisfies the letter and defeats the purpose — name both."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-124",
      "slug": "con-124",
      "title": "The sending entities must be named before consent is captured",
      "statement": "The authorised sending entities must be disclosed before the consumer acts, not on the confirmation screen or in the first message.",
      "rationale": "Consent is given at the moment of the act, so a name disclosed afterwards was not part of what was agreed to. Brands get this wrong in a specific and understandable way: the confirmation page is where they put the full legal detail, because that is the page nobody has to be persuaded by.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "disclosure ordering on the opt-in surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "dependsOn": [
        "CON-123"
      ],
      "remediation": "Move the entity names above the consent control, inside the sentence the consumer is agreeing to. Keep them on the confirmation as well if you like — the requirement is that they appear before the act, not that they appear only there. Done when the names are on screen at the moment the box is ticked.",
      "example": "☐ Text me offers from Acme Coffee and my local Acme Coffee franchise location.\n\n[Join] — the names appear above this button, not on the page it leads to.",
      "notes": "Depends on CON-123: where no entity is named at all, that is CON-123's finding and this rule has no ordering to judge.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-125",
      "slug": "con-125",
      "title": "Consent must not be claimed on behalf of unnamed partners",
      "statement": "The opt-in language must not purport to grant consent to \"our partners\", \"affiliates\", \"third parties\", or a linked partner list.",
      "rationale": "A consumer cannot consent to being messaged by a set of businesses they have not been told about, so this wording grants nothing while looking like it grants everything — and every carrier treats a number sent under it as having no consent behind it. It is standard boilerplate in lead-generation templates, which is how it reaches brands that have no intention of sharing anything.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "CTIA",
        "AWS",
        "Twilio",
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Delete the partner and affiliate wording from the consent sentence and name only the entities that will actually send. If a partner genuinely needs to message these consumers, they must collect their own consent under their own brand. Done when the sentence contains no open-ended category of recipient.",
      "example": "By checking this box you agree to receive recurring automated marketing texts from Acme Coffee. (No partner, affiliate, or third-party clause.)",
      "pitfalls": [
        "Linking a page that lists the partners does not cure it: the consumer would have to read a list to know who they are agreeing to, and reviewers reject the pattern rather than the length of the list."
      ],
      "notes": "Distinct from CON-NO-TRANSFER, which is about where the consent CAME FROM. This rule is about a consent the brand did collect itself, worded to extend to senders it cannot bind. A brand can pass that rule and fail this one on the same page.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-130",
      "slug": "con-130",
      "title": "Each messaging programme needs its own opt-in control",
      "statement": "A single opt-in control must not enrol the consumer into several messaging programmes or use cases at once.",
      "rationale": "One tick enrolling somebody into offers, delivery alerts and service notices gives them no way to keep the one they wanted and drop the two they did not — so the only exit is STOP, and the brand loses the whole relationship over a programme the consumer never asked for. It also makes the consent unprovable per programme, which is what a reviewer is checking.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in surface control set",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Infobip",
        "Bandwidth",
        "CTIA"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Give each programme its own checkbox with its own description, and register each as its own campaign. Done when a consumer can join the rewards texts without joining the service alerts.",
      "example": "☐ Acme Coffee Rewards: offers and rewards balance updates.\n☐ Acme Coffee order updates: delivery and pickup notifications.",
      "pitfalls": [
        "Splitting the controls but sending both programmes from one campaign puts the split back where it started — the campaign registration has to match the control set."
      ],
      "notes": "The surface half of the scope rule. CON-SCOPE-SPLIT covers the specific and most common instance — promotional bundled with transactional — while this rule covers a control that spans several programmes of any kind. Where the only bundling is marketing-plus-transactional, report it there rather than twice.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-132",
      "slug": "con-132",
      "title": "Email or voice consent does not become SMS consent",
      "statement": "Consent collected for email or phone calls must not be treated as consent to text, and an email list must not be migrated to SMS without a fresh opt-in.",
      "rationale": "Consent runs to a channel, and the consumer who gave an address for a newsletter made no decision about their phone. Migrating a list is the single most common way a careful brand acquires numbers it has no consent for, because the numbers were genuinely volunteered and the brand genuinely has a relationship — everything about it feels legitimate except the part that matters.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent scope; list provenance",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Bandwidth",
        "T-Mobile",
        "Twilio",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Numbers whose only consent was for another channel cannot be messaged under any use case. Re-permission them first: email the list asking them to opt in to texts, and send only to those who complete the SMS opt-in. The email invitation is not the consent — the landing page they submit is.",
      "notes": "HARD_STOP because there is no field that fixes it: the defect is which numbers are on the list, not how the campaign is described. The remediation is a real path, but it happens before registration rather than inside it.",
      "catalogIds": [
        "CON-136"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-134",
      "slug": "con-134",
      "title": "SMS consent needs its own control and its own sentence",
      "statement": "Messaging consent must not share a control or a sentence with email or phone-call consent.",
      "rationale": "One box reading \"yes, contact me by email and text\" produces a record that cannot show which channel the consumer wanted, and the honest answer is usually email — that is the one they were thinking about. Klaviyo warns against collecting both on one surface for the same reason: the combined control converts better precisely because it captures people who did not decide.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "opt-in surface control set; consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Telnyx",
        "Twilio",
        "TextUs",
        "Infobip",
        "Bird",
        "Sakari",
        "Klaviyo"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Split into two controls with two sentences: one for email, one for text. The SMS sentence carries the SMS disclosures; the email one does not need them. Done when a consumer can take the newsletter and decline the texts in one submission.",
      "example": "☐ Email me Acme Coffee news.\n☐ Text me Acme Coffee offers. Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe, HELP for help.",
      "pitfalls": [
        "Two checkboxes sharing one sentence above them is the same defect with extra steps — each control needs wording of its own that names its channel."
      ],
      "notes": "Distinct from CON-BOX-BUNDLED, which is about bundling with terms acceptance. Here both halves are genuine consents and the defect is that they are one act. WEB-100 states the same rule for a QR landing page, and CON-133 the wording half.",
      "catalogIds": [
        "CON-133",
        "WEB-100"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-137",
      "slug": "con-137",
      "title": "The consent record must capture the number it authorises",
      "statement": "The consent record must store the specific telephone number the consumer authorised messages to be sent to.",
      "rationale": "The federal definition of written consent turns on the number the signatory authorised, so a record proving somebody consented without recording which number they consented for cannot be matched to the message that was sent. It is the failure that surfaces late and badly: the brand has thousands of consent records and cannot tie any of them to the number in the complaint.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact phone field",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "FCC",
        "SIP.US"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Store the number on the consent record itself, in the form it was given, next to the timestamp and the disclosure version. Done when you can take any number from your sending list and produce the record that authorised it.",
      "example": "Each consent record stores: phone number, timestamp, collection surface, disclosure version shown, and the session or agent identity.",
      "pitfalls": [
        "Storing consent against a customer account rather than a number breaks the moment somebody changes their number, and the old number stays on the sending list with a record that no longer describes it."
      ],
      "notes": "Judged from what the flow and the artifact say about the record, since the record itself is the brand's own system. OPS-205 states the same field requirement on the retained record.",
      "catalogIds": [
        "OPS-205"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-139",
      "slug": "con-139",
      "title": "A business built on acquiring opt-in lists cannot be registered",
      "statement": "A campaign whose business model is acquiring, aggregating or monetising opt-in subscriber lists must not be registered.",
      "rationale": "Where the list IS the product, no amount of documentation fixes the campaign, because the consumers on it agreed to hear from whoever collected them and not from whoever bought them. Carriers name lead generation specifically in their prohibited categories for this reason, and the enforcement history behind 10DLC is largely this business model.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign business model",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "AT&T",
        "Bandwidth",
        "Twilio",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "A lead-generation or list-acquisition programme cannot be registered under any use case. The only messaging that can be is to consumers who opted in to hear from this brand directly, under this brand's own name.",
      "notes": "Distinct from CON-NO-TRANSFER, which asks where one list came from. This asks what the business does: a retailer that once bought a list has a fixable provenance problem, while a lead vendor has nothing to fix.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-145",
      "slug": "con-145",
      "title": "Consent must come from the consumer, not from a legal process",
      "statement": "Permission to message obtained by court order, or by any other mechanism the consumer did not initiate, is not consent.",
      "rationale": "Consent is a decision the consumer makes, so an order compelling contact is the opposite of one however lawful the order is. Bandwidth is unusually blunt about the consequence: if you can obtain opt-in another way, resubmit — and if you cannot, do not, because the opt-in will never be compliant. That sentence is worth surfacing before submission rather than after.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent provenance declaration",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "AWS",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Bandwidth",
          "code": "2126",
          "remediable": false
        },
        {
          "provider": "Bandwidth/DCA2",
          "code": "714",
          "remediable": false
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Messaging on this basis cannot be registered. Where the same consumers can be asked directly — a form, a call, a signed document — collect that consent and describe it instead. Where they cannot, there is no route to registration and resubmitting will not produce one.",
      "notes": "Bandwidth marks 2126 conditionally remediable: remediable only if consent can be re-obtained lawfully by another method, and not remediable at all otherwise. Recorded as non-remediable because the rule fires on the court-order basis itself, which is the unfixable case.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-146",
      "slug": "con-146",
      "title": "A TCPA exemption is not a substitute for opt-in",
      "statement": "An organisational or governmental exemption from the TCPA does not remove the requirement to obtain an opt-in.",
      "rationale": "Being exempt from a federal statute says nothing about the carriers' own code of conduct, and it is the carriers who decide whether traffic is delivered. Non-profits and public bodies reach this conclusion honestly — their lawyer is right that the TCPA does not reach them — and are then surprised by a rejection that is not about the law at all.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent basis declaration",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "Bandwidth",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Bandwidth",
          "code": "1415",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Describe and evidence a real opt-in as well as the exemption. The exemption is worth keeping in the submission — it explains your legal position — but it must sit alongside a collection surface, not in place of one. Done when the flow names an act of consent, whatever else it also says.",
      "example": "Riverside Shelter is a 501(c)(3) and relies on the non-profit exemption for TCPA purposes. Supporters additionally opt in at riversideshelter.org/alerts by ticking an unchecked box; screenshot attached.",
      "pitfalls": [
        "Bandwidth is stricter here than the statute, and says so — arguing the law in a resubmission does not change the outcome."
      ],
      "notes": "Flagged in the research as stricter than the law: the exemption is genuine and the carrier requirement is separate. Say that plainly to a user who pushes back, rather than implying their legal analysis is wrong.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-147",
      "slug": "con-147",
      "title": "An exemption relied on must be met in every one of its conditions",
      "statement": "Where a 47 CFR 64.1200(a)(9) exemption is relied on, every condition attached to it must be satisfied — free to the end user, within the message caps, sender identified, and opt-out in each message.",
      "rationale": "These exemptions are narrow and conditional, and failing any single condition collapses the whole thing back to needing consent — retrospectively, for everything already sent. The healthcare cap is the one most often missed: one message per day and three per week combined across voice and text, counted per patient rather than per programme.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "exemption claim",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "FCC"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Go through the conditions for the specific exemption you are claiming and evidence each: that the messages are free to the recipient, that your declared frequency is inside the cap, that every message identifies you, and that every message carries an opt-out. Where any fails, collect consent instead and stop relying on the exemption.",
      "example": "Package-delivery exemption: notifications are free to the recipient, one per shipment, identify Acme Coffee by name, and carry \"Reply STOP to opt out\" — honoured within six business days.",
      "pitfalls": [
        "The healthcare cap counts voice calls and texts together, so a practice already making reminder calls is usually over it before the SMS programme sends anything."
      ],
      "notes": "The registry holds no free-to-end-user fact and no per-recipient frequency, so the conditions are pushed into the judgement criteria rather than expressed as applicability, and the rule only fires where the submission itself claims an exemption.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-150",
      "slug": "con-150",
      "title": "A toll-free number must belong to one business",
      "statement": "A single toll-free number must be associated with exactly one business.",
      "rationale": "A number shared across businesses makes every consent on it ambiguous — the consumer agreed to hear from one of them and cannot tell which is texting, and neither can a reviewer tracing a complaint. It is a common shape in franchise groups and agencies, where one number is provisioned centrally and used by several trading entities because that is how the phone system was set up years earlier.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "toll-free number to brand mapping",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM",
        "HUMAN"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Provision a separate toll-free number per business and register each against its own brand. Where a number is already shared, move the other businesses off it before submitting — a verification approved against one brand does not extend to the others using the number.",
      "notes": "NOT VISIBLE TO US. The registry holds no number inventory, so we cannot see which numbers a brand has or who else is sending from them. Surfaced as a warning with the check the user must run themselves: list every business currently sending from the toll-free number on this registration, and confirm the answer is one. Their carrier or messaging platform can produce that list; we cannot.",
      "catalogIds": [
        "OPS-019"
      ],
      "phase": "approval",
      "automated": true,
      "attestation": {
        "question": "Is exactly one business sending from the toll-free number on this registration?",
        "howToCheck": [
          "Ask your carrier or messaging platform for the list of accounts and sub-accounts provisioned against this number.",
          "Read the list as a consumer would: every distinct trading entity on it is a separate business claiming the same number.",
          "Common in franchise groups and agencies, where one number was provisioned centrally years earlier."
        ],
        "failureLooksLike": "Three franchisees share the number their head office bought. A verification approved for one of them does not extend to the other two, and a complaint against any of them lands on all three."
      }
    },
    {
      "id": "CON-151",
      "slug": "con-151",
      "title": "Promotional messaging needs consent in writing, and must say so",
      "statement": "A campaign carrying promotional content must rest on prior express written consent, and the submission must describe that consent as a written record.",
      "rationale": "Marketing by automated text is the case the TCPA requires a writing for, and a writing is what the brand will have to produce if the consent is ever challenged. The reason to check it at registration is that the alternative is discovering years of sends rested on a verbal yes nobody wrote down — at which point every message already delivered is exposed.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent basis; consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "FCC",
        "CTIA",
        "AWS",
        "Bandwidth",
        "Twilio"
      ],
      "applicability": {
        "useCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE",
          "LOW_VOLUME"
        ]
      },
      "applicabilityText": "Applies when the use case is MARKETING, MIXED, SWEEPSTAKE and LOW_VOLUME.",
      "universal": false,
      "remediation": "Describe the written record: a ticked box with a stored timestamp, a signed form, a captured e-signature. Say where it is retained and what it contains. Where the consent was spoken, move the marketing programme onto a written opt-in before registering it and keep the verbal consent for the informational messages it can carry.",
      "example": "Marketing consent is captured in writing at checkout: the ticked box, the disclosure version shown, the timestamp and the session id are stored against the order and retained for four years.",
      "pitfalls": [
        "An electronic record only counts as the writing once the E-SIGN predicate is met — the consumer must have received the E-SIGN disclosures and agreed electronically, which most checkout flows have never done."
      ],
      "notes": "Oral consent remains adequate for purely informational or transactional programmes, which is why this is tagged to the promotional use cases rather than left universal.",
      "catalogIds": [
        "CON-152"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-156",
      "slug": "con-156",
      "title": "A call recording is not the written consent",
      "statement": "A recording of the consumer agreeing does not satisfy a requirement for consent in writing.",
      "rationale": "E-SIGN gives electronic records the force of a writing but expressly excludes oral recordings, so a recorded yes is strong evidence of consent and is still not the writing the rule asks for. Call centres reach for it in good faith because the recording feels more probative than a tick box — and it is, on every question except the one that decides the case.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact medium",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "E-SIGN Act",
        "FCC"
      ],
      "applicability": {
        "useCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE",
          "LOW_VOLUME"
        ]
      },
      "applicabilityText": "Applies when the use case is MARKETING, MIXED, SWEEPSTAKE and LOW_VOLUME.",
      "universal": false,
      "remediation": "Keep the recording, and add a writing beside it: send a confirmation link the consumer submits, capture a DTMF keypress, or follow the call with a double opt-in text they reply to. Done when a written record exists for each number, with the recording as corroboration rather than as the consent itself.",
      "example": "Agents capture spoken agreement (call recorded), then send a confirmation text the customer replies YES to; the reply, its timestamp and the number are stored as the written record.",
      "pitfalls": [
        "A transcript of the recording is not a cure — it is a record of speech, and the exclusion is about the consent being oral rather than about it being unwritten down."
      ],
      "notes": "Tagged to the promotional use cases for the same reason as CON-151: informational programmes may rest on oral consent, so the writing requirement does not reach them. A DTMF keypress is a stronger theory than a recording, which CON-IVR-CONFIRM already asks IVR flows for.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-160",
      "slug": "con-160",
      "title": "A marketing programme must say \"marketing\" everywhere it describes itself",
      "statement": "For a marketing campaign, the call to action, the message flow and the campaign description must each state that the messages are marketing or promotional.",
      "rationale": "Reviewers compare the three, and a campaign registered as MARKETING whose consent language only mentions \"updates\" is either mislabelled or collecting consent too narrow for what it will send. Both readings get rejected, and the second is the one that actually happens: the CTA was written for a service programme and the marketing was added later.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text; campaign.message_flow; campaign.description",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "Telnyx",
        "CTIA"
      ],
      "applicability": {
        "useCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE",
          "LOW_VOLUME"
        ]
      },
      "applicabilityText": "Applies when the use case is MARKETING, MIXED, SWEEPSTAKE and LOW_VOLUME.",
      "universal": false,
      "remediation": "Put the word marketing or promotional into all three: the consent sentence on the surface, the message flow, and the campaign description. Fix the CTA first — the other two are fields you control, and a flow claiming marketing consent that the live page does not collect is the worse defect. Done when all three agree.",
      "example": "CTA: \"…recurring automated marketing text messages from Acme Coffee.\" · Flow: \"Customers opt in to marketing texts at checkout.\" · Description: \"Acme Coffee sends weekly promotional offers…\"",
      "pitfalls": [
        "Adding the word to the two form fields and not to the live page is the version that fails hardest, because the mismatch now proves the consent is narrower than the registration."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-162",
      "slug": "con-162",
      "title": "A chat conversation is not a marketing opt-in",
      "statement": "Consent inferred from a chat widget or an inbound conversation must not be used to justify a marketing use case.",
      "rationale": "Somebody who opened a support chat consented to that conversation, not to a promotional programme. The two get conflated because the chat platform holds a phone number and an apparent agreement to be contacted, so the marketing list builds itself out of support enquiries — which is exactly the mismatch between what was agreed and what arrives that drives complaints.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent basis vs use case",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "CTIA"
      ],
      "applicability": {
        "consentMethods": [
          "chat"
        ],
        "useCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE",
          "LOW_VOLUME"
        ]
      },
      "applicabilityText": "Applies when consent was collected by chat, and the use case is MARKETING, MIXED, SWEEPSTAKE and LOW_VOLUME.",
      "universal": false,
      "remediation": "Either register the programme as customer care, matching what the chat consent actually covers, or add a marketing opt-in inside the chat flow with the full disclosure and record it separately. Done when the use case and the consent describe the same thing.",
      "example": "In-chat: \"Want Acme Coffee offers by text too? Reply YES to opt in — msg frequency varies, msg & data rates may apply, reply STOP to unsubscribe.\" Only repliers join the marketing list.",
      "pitfalls": [
        "A conversational opt-in inside the chat is fine and is the fix; what fails is treating the existence of the conversation as the consent."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-163",
      "slug": "con-163",
      "title": "Keyword consent is bounded by what the advertisement promised",
      "statement": "Consent given by texting a keyword extends only to the programme advertised alongside that keyword.",
      "rationale": "With text-to-join, the advertisement is the whole disclosure — the consumer decided before the first message existed. So a keyword advertised for shipping alerts collects consent for shipping alerts, and the promotional programme it actually enrols people into was never disclosed to anybody who joined.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "keyword advertisement copy vs campaign content",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "keyword_cta_copy",
      "authorities": [
        "Klaviyo",
        "CTIA"
      ],
      "applicability": {
        "consentMethods": [
          "keyword"
        ]
      },
      "applicabilityText": "Applies when consent was collected by text-to-join keyword.",
      "universal": false,
      "remediation": "Make the advertised copy describe everything the keyword enrols the consumer into, or split the programmes and advertise a keyword for each. Done when the samples contain nothing a reader of the advertisement would not have expected.",
      "example": "Text JOIN to 55512 for Acme Coffee offers and rewards updates. Msg frequency varies. Msg & data rates may apply. Reply STOP to cancel, HELP for help.",
      "pitfalls": [
        "Running one keyword across several campaigns is the usual cause, and it fails here even when each campaign is individually compliant."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-164",
      "slug": "con-164",
      "title": "Text-to-join marketing still owes the written-consent elements",
      "statement": "A marketing text-to-join CTA must carry the federal written-consent elements — the ATDS disclosure, the not-a-condition statement, and the number being authorised.",
      "rationale": "An inbound keyword is unambiguous express consent, and that is not the same as express WRITTEN consent, which is what automated marketing requires. The gap is easy to miss precisely because the keyword feels stronger than a checkbox: the consumer actively texted you, so nobody thinks to check whether the advertisement carried the elements a form would have had to.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "keyword CTA copy",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "keyword_cta_copy",
      "authorities": [
        "FCC"
      ],
      "applicability": {
        "consentMethods": [
          "keyword"
        ],
        "useCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE",
          "LOW_VOLUME"
        ]
      },
      "applicabilityText": "Applies when consent was collected by text-to-join keyword, and the use case is MARKETING, MIXED, SWEEPSTAKE and LOW_VOLUME.",
      "universal": false,
      "remediation": "Add the missing elements to the advertised copy: that the messages are automated and recurring, that consent is not a condition of purchase, and that the number texted from is the number being authorised. Done when the advertisement would satisfy the written-consent test if it were a form.",
      "example": "Text JOIN to 55512 to get recurring automated marketing texts from Acme Coffee at the number you text from. Consent is not a condition of purchase. Msg frequency varies. Msg & data rates may apply. Reply STOP to cancel, HELP for help.",
      "pitfalls": [
        "The number element is the one keyword programmes almost always miss, and it is the easiest to add: the number they text from is the number they are authorising, and saying so costs eight words."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-166",
      "slug": "con-166",
      "title": "A donation programme must disclose that it solicits donations",
      "statement": "Where the programme solicits donations, the point of consent must say so.",
      "rationale": "A supporter who signed up for news about a charity's work did not agree to be asked for money, and the ask is the message most likely to be reported when it was not expected. Saying it at the outset costs a clause and converts the complaint into an opt-out that never happens.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Infobip",
        "Bandwidth",
        "Telnyx"
      ],
      "applicability": {
        "useCases": [
          "CHARITY",
          "POLITICAL"
        ]
      },
      "applicabilityText": "Applies when the use case is CHARITY and POLITICAL.",
      "universal": false,
      "remediation": "Add donation solicitation to the message-type disclosure at the point of consent, and use the same wording in the campaign description. Done when the consent sentence names fundraising alongside whatever else the programme sends.",
      "example": "☐ Text me Riverside Shelter updates and occasional donation requests. Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe.",
      "pitfalls": [
        "A charity that sends both service information and appeals owes separate opt-ins for the two, so adding the donation clause to a single combined control fixes this rule and fails CON-SCOPE-SPLIT."
      ],
      "catalogIds": [
        "MSG-269"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-AGE-GATE",
      "slug": "con-age-gate",
      "title": "Age-gated programs require real age verification at opt-in",
      "statement": "A campaign declaring age-gated content must verify age at the point of consent, not merely ask for self-attestation.",
      "rationale": "Robust age verification means electronic confirmation of age and identity, which in practice means collecting a full date of birth. The carrier discretion to waive age gating was removed in SCMH v1.8, so a self-attest tick box that used to be tolerated now fails, and the underlying content categories carry per-message violation fees.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "T-Mobile",
        "TCR"
      ],
      "applicability": {
        "attributes": {
          "ageGated": true
        }
      },
      "applicabilityText": "Applies when `ageGated` is true.",
      "universal": false,
      "remediation": "Collect a full date of birth (MM/DD/YYYY) at opt-in and reject under-age submissions server-side. Replace any \"I am 21 or older\" checkbox — self-attestation is not robust verification and is no longer waivable.",
      "catalogIds": [
        "WEB-108",
        "WEB-113"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-ART-001",
      "slug": "con-art-001",
      "title": "An artifact proving consent collection must be attached",
      "statement": "The opt-in / message flow must reference a durable artifact evidencing how consent is collected — a screenshot of the opt-in screen, a PDF or scan of the paper form, the verbal script, or a capture of the QR landing page.",
      "rationale": "Every provider reject list is dense with \"opt-in could not be verified\" reasons, and a reviewer who cannot see your consent surface has no way to distinguish a compliant one from a claim. CTIA MPBP 5.1.2 separately requires you to retain \"a capture of the experience\" used to secure consent — so the artifact is something you are obliged to hold anyway. Producing it at registration converts the single most common soft rejection into a solved problem.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow + consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "Ekas (product policy)",
        "CTIA",
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Attach proof of your opt-in and reference it in the message flow. For a web form, a full-width screenshot of the form with the consent text visible. For phone consent, the script your agents read. For paper, a scan of the signed form. For QR, a capture of the landing page. Host it somewhere publicly reachable — a reviewer must be able to open it without logging in.",
      "example": "Consent is collected at https://acmecoffee.com/signup via an unchecked checkbox. Screenshot of the live form: https://cdn.acmecoffee.com/compliance/optin-2026-07.png",
      "pitfalls": [
        "A Google Drive or Dropbox share link that shows a \"request access\" wall is treated as no evidence at all.",
        "A viewer page is not an image — link the file directly so it opens as a picture."
      ],
      "notes": "STRICTER THAN THE BASELINE BY DESIGN, per product policy. TCR does not universally demand an artifact; we do. That is also why CON-037 (a mockup or script for 2FA and OTP campaigns) and CON-039 (an opt-in description or screenshot on toll-free verification) are aliased here rather than written separately: both are this requirement narrowed to one path, and a rule that already demands the artifact from everyone discharges them outright.",
      "catalogIds": [
        "CON-018",
        "CON-037",
        "CON-039"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-ART-002",
      "slug": "con-art-002",
      "title": "The consent artifact must actually show a consent surface",
      "statement": "The attached artifact must depict the point of consent collection, not an unrelated page, logo, or product screen.",
      "rationale": "The most common evidence failure is not a missing screenshot but the wrong one — a homepage, a logo, or a dashboard. Reviewers read that as an attempt to satisfy the requirement without meeting it, and it costs more credibility than attaching nothing. Catching it before submission avoids a rejection that is embarrassing as well as expensive.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Replace the attachment with an image of the actual screen or form where the customer gives consent. Three things must appear together in one frame: the phone-number field, the control they act on (checkbox, toggle, or signature line), and the disclosure text beside it.",
      "pitfalls": [
        "A screenshot of the confirmation page after signup shows the outcome, not the consent — capture the form itself."
      ],
      "catalogIds": [
        "CON-028"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-ART-003",
      "slug": "con-art-003",
      "title": "The consent artifact must be legible",
      "statement": "The artifact must be readable at the resolution supplied — cropped, blurred, or truncated evidence does not establish consent.",
      "rationale": "A reviewer who cannot read your disclosure treats it as absent, so an illegible screenshot fails the same way a missing disclosure does, while looking to you like the requirement was met. This is a silent failure mode: the brand believes it supplied evidence and cannot understand the rejection.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Re-capture at full width with the disclosure text readable without zooming. Capture the whole consent block rather than cropping tightly to the checkbox, and avoid photographing a screen with a phone — screenshot it directly.",
      "notes": "whenUnreadable is FAIL, against the default, because illegibility IS the defect this rule tests — returning UNCLEAR would make the rule unable to ever fail. Only the user can fix it: they must re-capture the artifact themselves, since we cannot reach their consent surface.",
      "catalogIds": [
        "CMP-121"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-BOX-BUNDLED",
      "slug": "con-box-bundled",
      "title": "Messaging consent must be separate from terms acceptance",
      "statement": "The messaging opt-in must be its own control, not bundled into a general \"I accept the Terms and Privacy Policy\" checkbox.",
      "rationale": "A consumer ticking a box to create an account is agreeing to the account, not to marketing texts. Bundling makes the messaging consent unprovable — you cannot show a reviewer, or a court, that the tick meant yes to SMS specifically.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "AWS"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Split into two adjacent checkboxes: one for accepting the Terms and Privacy Policy, one for agreeing to receive text messages. Only the second one is your consent record.",
      "example": "☐ I agree to the Terms of Service and Privacy Policy.\n☐ Text me: I agree to receive recurring automated marketing text messages from Acme Coffee. Consent is not a condition of any purchase. Msg frequency varies. Msg & data rates may apply. Reply STOP to unsubscribe.",
      "catalogIds": [
        "CON-055"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-BOX-PRESENT",
      "slug": "con-box-present",
      "title": "An explicit affirmative opt-in control must exist",
      "statement": "Consent must be captured by a deliberate affirmative action — a checkbox, toggle, or signature — never inferred from form submission.",
      "rationale": "Express written consent requires an act that means \"yes to messages\" and nothing else. When consent is bundled into pressing Submit, there is no way to distinguish someone who wanted texts from someone who wanted an account, and no way to evidence the difference later.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "FCC",
        "Twilio"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Add a dedicated checkbox the customer must tick, unchecked by default, with the consent disclosure printed beside it. Replace any \"by submitting this form you agree to receive texts\" wording with a real control.",
      "example": "☐ By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help. See our Terms of Service and Privacy Policy.",
      "catalogIds": [
        "CON-051",
        "CON-054"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-BOX-UNCHECKED",
      "slug": "con-box-unchecked",
      "title": "The consent control must be unchecked by default",
      "statement": "The opt-in control must not be pre-selected; consent must be a deliberate act.",
      "rationale": "A pre-ticked box collects consent from everyone who did not notice it, which is the definition of consent that was not affirmatively given. It is one of the few defects a reviewer can confirm from a single screenshot, so it is caught reliably and rejected without discussion.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "FCC",
        "TCR",
        "Twilio",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30925",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "pos"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party and point of sale.",
      "universal": false,
      "remediation": "Render the checkbox unchecked on first paint. Check your form builder's default — Shopify, Klaviyo and most form plugins ship marketing consent pre-enabled, so this is usually a settings toggle rather than a code change.",
      "pitfalls": [
        "Capturing the screenshot after you clicked the box proves nothing — take it on a fresh page load."
      ],
      "catalogIds": [
        "CON-052"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-ADJACENT",
      "slug": "con-disc-adjacent",
      "title": "Disclosures must appear at the point of opt-in, not only in linked documents",
      "statement": "The required disclosures must be visible on the consent surface itself; burying them in a linked Terms page does not satisfy the requirement.",
      "rationale": "AWS states the point directly: disclosures must be presented at the time of opt-in rather than housed inside a linked policy document. A consumer deciding whether to tick a box does not open a terms page first, so a disclosure they must navigate to is a disclosure they never saw.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "CTIA",
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Move the disclosure text into the same visual block as the checkbox. Keep the links to Terms and Privacy as well — they are required in addition to the inline disclosure, never as a substitute for it.",
      "example": "By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help. See our Terms of Service and Privacy Policy.",
      "catalogIds": [
        "CON-107"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-AUTOMATED",
      "slug": "con-disc-automated",
      "title": "Consent disclosure must disclose automated, recurring messaging",
      "statement": "The consumer must be told the messages are automated and recurring — a TCPA express-written-consent element.",
      "rationale": "TCPA consent is specifically consent to be contacted by an automatic telephone dialing system. A disclosure that reads like a human will occasionally text does not obtain that consent, so the opt-ins collected under it are legally weaker than they appear.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "FCC",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Use \"recurring automated marketing text messages\" in the consent sentence. Both words matter: \"automated\" carries the TCPA element and \"recurring\" sets the frequency expectation.",
      "example": "By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help. See our Terms of Service and Privacy Policy.",
      "catalogIds": [
        "CON-097",
        "CON-098"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-BRAND",
      "slug": "con-disc-brand",
      "title": "Consent disclosure must identify the sending brand by name",
      "statement": "The disclosure at the point of consent must name the business that will send the messages.",
      "rationale": "Consent runs to a specific sender, not to messaging in general — that is what makes it non-transferable. A consumer who agreed to hear from \"us\" on a page they no longer remember cannot meaningfully have consented to the brand that later appears in their inbox, which is precisely the complaint pattern carriers built 10DLC to suppress.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "T-Mobile"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Put the registered brand name inside the consent sentence itself, not just in the page header or logo. Use the same name you registered — if you registered \"Acme Coffee Co, LLC\" with DBA \"Acme Coffee\", either is fine, but a third marketing alias is not.",
      "example": "By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help. See our Terms of Service and Privacy Policy.",
      "catalogIds": [
        "CON-081"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-FREQ",
      "slug": "con-disc-freq",
      "title": "Consent disclosure must state message frequency",
      "statement": "The disclosure must tell the consumer how often messages will arrive.",
      "rationale": "Frequency is the expectation that determines whether your third message of the week reads as a service or as spam. Undisclosed frequency is a leading driver of opt-outs and complaints, and a high opt-out rate is itself a signal carriers use to throttle a campaign.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add a frequency statement to the disclosure. \"Message frequency varies\" is accepted everywhere and is the safe default if your volume is irregular; a concrete cap like \"up to 4 messages per month\" is stronger if you can honour it.",
      "example": "Message frequency varies. Message and data rates may apply.",
      "pitfalls": [
        "Promising a numeric cap you exceed is worse than saying \"varies\" — the cap becomes a claim you are held to."
      ],
      "catalogIds": [
        "CON-084"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-HELP",
      "slug": "con-disc-help",
      "title": "Consent disclosure must explain how to get help",
      "statement": "The disclosure must tell the consumer they can reply HELP for assistance.",
      "rationale": "HELP is the industry-standard way a confused recipient finds out who is texting them and how to reach a human. Without it, a consumer who does not recognise your sender ID has no route other than reporting the message as spam.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add \"Reply HELP for help.\" to the consent disclosure, and make sure your HELP auto-reply actually names your brand and gives a real support contact.",
      "example": "Reply STOP to unsubscribe, HELP for help.",
      "catalogIds": [
        "CON-087"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-NO-POPUP",
      "slug": "con-disc-no-popup",
      "title": "Terms must not be presented only in a pop-up",
      "statement": "A modal or pop-up is not an acceptable method of displaying the required terms.",
      "rationale": "CTIA excludes pop-ups explicitly because they are dismissed reflexively, blocked by browsers, and absent from any screenshot a reviewer takes. A term the consumer can close without reading has not been presented.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "chat",
          "social",
          "email"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party, chat, social and email.",
      "universal": false,
      "remediation": "Render the consent terms inline on the page beneath the checkbox rather than behind a modal, tooltip, or expandable \"read more\" that starts collapsed.",
      "catalogIds": [
        "CON-116"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-NOT-CONDITION",
      "slug": "con-disc-not-condition",
      "title": "Promotional consent must state it is not a condition of purchase",
      "statement": "A promotional opt-in must carry the explicit statement that consent is not a condition of any purchase.",
      "rationale": "This is a required element of TCPA express written consent, not a courtesy. Consent extracted as the price of completing a purchase is not freely given, and a plaintiff can void every opt-in collected that way — which is why carriers treat the missing sentence as a blocking defect rather than a wording preference.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "FCC",
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicability": {
        "useCases": [
          "MARKETING",
          "MIXED",
          "SWEEPSTAKE",
          "LOW_VOLUME"
        ]
      },
      "applicabilityText": "Applies when the use case is MARKETING, MIXED, SWEEPSTAKE and LOW_VOLUME.",
      "universal": false,
      "remediation": "Add the sentence \"Consent is not a condition of any purchase.\" to the disclosure, and make sure it is true — the form must submit with the box unchecked.",
      "example": "By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help. See our Terms of Service and Privacy Policy.",
      "pitfalls": [
        "Adding the sentence while the form still refuses to submit without the box ticked fails the stricter CON-NOT-GATED rule instead."
      ],
      "catalogIds": [
        "CON-073"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-PRIVACY-LINK",
      "slug": "con-disc-privacy-link",
      "title": "A Privacy Policy link must sit at the point of consent",
      "statement": "A link to the Privacy Policy must be present beside the opt-in control, not only in the page footer.",
      "rationale": "The privacy policy is where the consumer learns their number will not be sold on — the single clause carriers care most about. CTIA requires all applicable privacy policies to be referenced in and accessible from the initial call to action, so distance from the opt-in is itself the violation.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "chat",
          "social",
          "email"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party, chat, social and email.",
      "universal": false,
      "remediation": "Add a Privacy Policy hyperlink inside or immediately beneath the consent sentence. Make sure the page it points at actually contains the SMS data clause, or you will pass this rule and fail the policy-page one.",
      "example": "By checking this box you agree to Acme Coffee's <a href=\"/terms\">Terms of Service</a> and <a href=\"/privacy\">Privacy Policy</a>.",
      "catalogIds": [
        "CON-092"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-PURPOSE",
      "slug": "con-disc-purpose",
      "title": "Consent disclosure must state the message type or purpose",
      "statement": "The consumer must be told what kind of messages they are agreeing to receive.",
      "rationale": "Consent is scoped to what was disclosed. A consumer who opted in for order updates and then receives promotions did not consent to those promotions, and their complaint is well-founded — this is the single most common source of consumer-initiated spam reports, which are what drive carrier filtering against your numbers.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Name the message category explicitly and make it match your declared use case — \"marketing and promotional messages\", \"appointment reminders\", \"order and delivery updates\". If you send more than one category, say so, and consider whether they need separate opt-ins.",
      "example": "By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help. See our Terms of Service and Privacy Policy.",
      "pitfalls": [
        "Declaring MARKETING as the use case while the disclosure only mentions \"account updates\" fails both this rule and the use-case consistency check."
      ],
      "catalogIds": [
        "CON-083"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-RATES",
      "slug": "con-disc-rates",
      "title": "Consent disclosure must carry the message and data rates notice",
      "statement": "\"Message and data rates may apply\" (or a clear equivalent) must appear at the point of consent.",
      "rationale": "The consumer may be paying their carrier per message, and the disclosure exists so nobody is billed for something they did not knowingly accept. It is one of the oldest and most mechanically-checked elements in the industry, which makes its absence a cheap and very common rejection.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add \"Message and data rates may apply.\" to the consent disclosure, adjacent to the checkbox. A rates notice that lives only in your Terms page does not count.",
      "example": "Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe, HELP for help.",
      "catalogIds": [
        "CON-085"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-STOP",
      "slug": "con-disc-stop",
      "title": "Consent disclosure must explain how to opt out",
      "statement": "The disclosure must tell the consumer they can reply STOP to stop receiving messages.",
      "rationale": "A consumer who does not know how to leave complains to their carrier instead, and carrier complaints are what trigger number blocking and violation fees. Telling them the exit at the moment they enter is both a legal requirement and the cheapest protection you have against a spam report.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent disclosure text",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "FCC",
        "T-Mobile"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add \"Reply STOP to unsubscribe.\" to the consent disclosure. Name the keyword — a general promise that they can unsubscribe any time does not tell them how.",
      "example": "Reply STOP to unsubscribe, HELP for help.",
      "catalogIds": [
        "CON-086"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DISC-TERMS-LINK",
      "slug": "con-disc-terms-link",
      "title": "A Terms of Service link must sit at the point of consent",
      "statement": "A link to the Terms of Service must be present beside the opt-in control, not only in the page footer.",
      "rationale": "The terms are where the full program description lives, and CTIA requires them to be reachable from the initial call to action rather than hunted for. A footer link at the bottom of a long checkout page is not, in practice, available at the moment of decision.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "account_settings",
          "third_party",
          "chat",
          "social",
          "email"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party, chat, social and email.",
      "universal": false,
      "remediation": "Add a Terms of Service hyperlink inside or immediately beneath the consent sentence, next to the checkbox. Keep the footer link as well — this is in addition to it, not instead of it.",
      "example": "By checking this box you agree to Acme Coffee's <a href=\"/terms\">Terms of Service</a> and <a href=\"/privacy\">Privacy Policy</a>.",
      "catalogIds": [
        "CON-091"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-DOUBLE-OPTIN-CART",
      "slug": "con-double-optin-cart",
      "title": "Abandoned-cart programs require double opt-in",
      "statement": "Abandoned-cart messaging requires a confirmed double opt-in and must not treat cart placement as consent.",
      "rationale": "Putting an item in a cart is explicitly not consent to be texted about it, and the number is usually linked to the cart by a cookie the consumer never saw. T-Mobile therefore mandates a confirmed double opt-in for this pattern specifically — one of the very few places double opt-in is required rather than optional.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "T-Mobile",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add a confirmation step so the consumer opts in twice, disclose in your terms how the phone number is linked to the cart, send at most one notification per shopping event within 48 hours, and never allow order completion by text reply.",
      "notes": "Double opt-in is OPTIONAL under CTIA generally. Do not generalise this rule into a universal double-opt-in requirement.",
      "catalogIds": [
        "MSG-070"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-FLOW-METHOD-MATCH",
      "slug": "con-flow-method-match",
      "title": "The described opt-in method must match the evidence supplied",
      "statement": "The collection method described in the message flow must be consistent with the artifact and the website.",
      "rationale": "A mismatch between the description and the evidence reads to a reviewer as either carelessness or misdirection, and both get rejected. It also usually means one of your real collection surfaces is undocumented and therefore unaudited.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow + consent artifact",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Make the flow describe the same method the evidence shows. If you genuinely collect consent several ways, describe each one and attach evidence for each — partial evidence is what triggers the mismatch.",
      "example": "Consent is collected two ways: (1) the web form at acmecoffee.com/signup [screenshot attached], and (2) verbally at our counter using the attached script.",
      "catalogIds": [
        "CON-007"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-FLOW-SPECIFIC",
      "slug": "con-flow-specific",
      "title": "The message flow must describe a real, specific opt-in",
      "statement": "The message flow must name where consent happens concretely enough for a reviewer to find and verify it.",
      "rationale": "Reviewers verify by going and looking. A flow that says \"customers opt in on our website\" gives them nowhere to go, so they reject rather than hunt — this is the single most common campaign-level rejection reason across every provider.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30896",
          "remediable": true,
          "generation": "gen1"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Name the exact surface — the page URL, the form, the physical location, or the script — and quote the consent wording the consumer agrees to. Add the link to your hosted evidence.",
      "example": "Customers opt in at https://acmecoffee.com/signup by ticking an unchecked box reading: \"By checking this box, you agree to receive recurring automated marketing text messages from Acme Coffee at the number provided. Consent is not a condition of any purchase. Message frequency varies. Message and data rates may apply. Reply STOP to unsubscribe or HELP for help.\" Screenshot: https://cdn.acmecoffee.com/compliance/optin.png",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-HELP-BACKED",
      "slug": "con-help-backed",
      "title": "Declared HELP support must have a help message behind it",
      "statement": "A campaign declaring HELP keywords must supply the help reply that will be sent.",
      "rationale": "Declaring HELP support without configuring a reply produces the worst possible outcome: a consumer asks who is texting them and gets silence or an error. CTIA requires HELP to always produce a response, whether or not the requester is even subscribed.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.help_keywords + campaign.help_message",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "CTIA",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Write the HELP auto-reply, naming the brand and giving a real support contact a person can actually reach.",
      "example": "Acme Coffee: for help, email support@acmecoffee.com or call 415-555-0134. Msg & data rates may apply. Reply STOP to unsubscribe.",
      "catalogIds": [
        "CMP-185",
        "CMP-191"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-IMPORTED-LIST",
      "slug": "con-imported-list",
      "title": "Imported or legacy lists must evidence original consent",
      "statement": "A campaign messaging a pre-existing list must describe when and how that consent was originally obtained.",
      "rationale": "An existing customer relationship is not by itself consent to send marketing texts. Where the original opt-in cannot be described, there is nothing to audit, and the practical risk is that the list predates any SMS disclosure at all.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "CTIA",
        "TCR",
        "FCC"
      ],
      "applicability": {
        "consentMethods": [
          "imported"
        ]
      },
      "applicabilityText": "Applies when consent was collected by imported list.",
      "universal": false,
      "remediation": "Describe the original collection surface and approximate date, and attach evidence of the disclosure used then. Where you cannot, re-permission the list with a fresh opt-in before messaging it.",
      "example": "Numbers were collected between 2023 and 2026 at checkout on acmecoffee.com using the disclosure shown in the attached screenshot; the consent date is stored per record.",
      "catalogIds": [
        "CON-140"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-IVR-CONFIRM",
      "slug": "con-ivr-confirm",
      "title": "IVR opt-in must capture an unambiguous confirmation step",
      "statement": "An IVR flow must require a distinct keypress or spoken confirmation specifically for messaging consent.",
      "rationale": "In an automated menu it is trivially easy for a caller to reach the end of a flow without having agreed to anything in particular. A dedicated confirmation step is what makes the resulting log entry mean \"yes to texts\" rather than \"completed the call\".",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "ivr_script",
      "authorities": [
        "TCR",
        "FCC"
      ],
      "applicability": {
        "consentMethods": [
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by IVR.",
      "universal": false,
      "remediation": "Add a dedicated consent step with its own keypress, after the disclosure has been read, and log the keypress with a timestamp.",
      "example": "\"To agree to receive recurring automated text messages from Acme Coffee at this number — message frequency varies, message and data rates may apply, reply STOP to cancel — press 1 now. To continue without text messages, press 2.\"",
      "catalogIds": [
        "CON-157"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-KEYWORD-CONFIRM",
      "slug": "con-keyword-confirm",
      "title": "Keyword opt-in requires a compliant confirmation reply",
      "statement": "The auto-reply sent after a keyword opt-in must carry the brand, frequency, rates, STOP and HELP.",
      "rationale": "The confirmation message is the consumer’s receipt: it is where they learn what they just joined and how to leave. CTIA treats it as a required disclosure surface in its own right, and it is the one element of a keyword program you control completely.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.optin_message",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "CTIA",
        "TCR",
        "Bandwidth",
        "AWS"
      ],
      "applicability": {
        "consentMethods": [
          "keyword"
        ]
      },
      "applicabilityText": "Applies when consent was collected by text-to-join keyword.",
      "universal": false,
      "remediation": "Write the opt-in confirmation to include all five elements within the 320-character limit.",
      "example": "Acme Coffee: you're subscribed to offers. Msg frequency varies. Msg & data rates may apply. Reply HELP for help, STOP to cancel.",
      "catalogIds": [
        "CMP-181"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-KEYWORD-CTA",
      "slug": "con-keyword-cta",
      "title": "Keyword opt-in requires the advertised call to action",
      "statement": "A text-to-join campaign must supply the advertisement wherever the keyword is promoted, carrying the full disclosure.",
      "rationale": "With text-to-join, the advertisement is the disclosure — by the time the consumer texts your keyword the decision is already made. Whatever the poster, page or ad said at that moment is the entire basis of their consent, so that is the artifact that has to be compliant.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow + consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "keyword_cta_copy",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicability": {
        "consentMethods": [
          "keyword"
        ]
      },
      "applicabilityText": "Applies when consent was collected by text-to-join keyword.",
      "universal": false,
      "remediation": "Supply a capture of the advertised CTA — the web page, sign, or print ad — showing the keyword, the number, and the disclosure elements together.",
      "example": "Text JOIN to 55512 to get offers from Acme Coffee. Msg frequency varies. Msg & data rates may apply. Reply STOP to cancel, HELP for help. Terms: acmecoffee.com/terms · Privacy: acmecoffee.com/privacy",
      "catalogIds": [
        "CMP-098",
        "CMP-099"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-KW-REVOCATION-SET",
      "slug": "con-kw-revocation-set",
      "title": "Declared opt-out keywords should cover the FCC per-se set",
      "statement": "The declared opt-out keywords should include the FCC per-se revocation words: STOP, QUIT, END, REVOKE, OPT OUT, CANCEL, UNSUBSCRIBE.",
      "rationale": "Since the FCC revocation rule took effect, those seven words are per se reasonable ways to revoke consent — a consumer using any of them has legally opted out whether or not your platform recognises the keyword. Declaring the full set is how you make your configuration match the legal reality instead of relying on STOP alone.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.optout_keywords",
      "severity": "HIGH",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "FCC",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Declare all seven per-se keywords, and confirm your sending platform honours each of them. Keywords must be alphanumeric, so use OPTOUT rather than \"OPT OUT\".",
      "example": "STOP, QUIT, END, REVOKE, OPTOUT, CANCEL, UNSUBSCRIBE",
      "notes": "Registration-side twin of the runtime obligation — we verify the declared set, not runtime handling. Absorbs OPS-028, the platform-extended keyword set: OPTOUT is one of the seven required here, and the two remaining extras, HALT and STOPALL, are surfaced on a pass rather than required, because they are one provider's published list rather than the industry baseline and failing every other sender for them would be wrong.",
      "catalogIds": [
        "CMP-186",
        "OPS-028"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-NO-TRANSFER",
      "slug": "con-no-transfer",
      "title": "Consent must not be purchased, shared, or transferred",
      "statement": "Only the business that collected the consent may message the consumer; purchased lists and shared opt-ins are prohibited.",
      "rationale": "Consent is non-transferable and non-assignable — it names a sender, and it does not survive being sold, shared with affiliates, or inherited by a sister brand. This is the rule behind the affiliate-marketing prohibition and behind most of the enforcement actions that produced 10DLC in the first place, which is why it is a hard stop rather than a fixable finding.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "CTIA",
        "FCC",
        "TCR",
        "T-Mobile",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "A purchased, rented, affiliate-sourced or partner-shared list cannot be registered under any use case. The only remedy is to collect fresh consent directly, under this brand, before messaging those numbers.",
      "catalogIds": [
        "CON-126",
        "CON-127",
        "CON-128"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-NOT-GATED",
      "slug": "con-not-gated",
      "title": "Declining messages must not block the primary action",
      "statement": "The consumer must be able to decline SMS and still complete the purchase, signup, or account creation.",
      "rationale": "Consent that is the price of checkout is coerced, and coerced consent is not consent — the FCC treats it as void and carriers treat it as a blocking defect. It is also self-defeating commercially: a list built this way has the opt-out and complaint rates of a purchased list.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "FCC",
        "TCR",
        "Twilio",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30923",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "Twilio",
          "code": "30931",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "excludeUseCases": [
          "TWO_FACTOR_AUTH",
          "SECURITY_ALERT",
          "FRAUD_ALERT"
        ]
      },
      "applicabilityText": "Applies when the use case is NOT TWO_FACTOR_AUTH, SECURITY_ALERT and FRAUD_ALERT.",
      "universal": false,
      "remediation": "Remove any required-field validation on the consent control and test the form end to end with the box unchecked. Remove asterisks or \"required\" markers from the messaging opt-in, and offer email or voice as an alternative channel where a contact method is genuinely needed.",
      "pitfalls": [
        "A 2FA or fraud-alert program legitimately requires the number — those use cases are excluded from this rule rather than exempted by argument."
      ],
      "catalogIds": [
        "CON-066",
        "CON-067"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-OPTOUT-CONFIRM",
      "slug": "con-optout-confirm",
      "title": "Opt-out confirmation must acknowledge and must not promote",
      "statement": "The opt-out confirmation must confirm no further messages will be sent, name the brand, and contain no promotional content.",
      "rationale": "The confirmation is the last message you are permitted to send, and using it to pitch a discount is treated as continuing to market to someone who just revoked consent. It is a Severity-0 style finding precisely because it happens after the consumer said stop.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.optout_message",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "CTIA",
        "FCC",
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Reduce the confirmation to an acknowledgement: brand, confirmation that messages have stopped, and optionally how to get help. Remove any offer, discount, survey, or \"are you sure\" retention prompt.",
      "example": "Acme Coffee: you have been unsubscribed and will receive no further messages. Reply HELP for help.",
      "pitfalls": [
        "\"Sorry to see you go — here's 10% off if you stay\" is a marketing message sent after revocation."
      ],
      "catalogIds": [
        "CMP-189",
        "MSG-084"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-PAPER-ELEMENTS",
      "slug": "con-paper-elements",
      "title": "Paper consent form must carry the disclosure, a tick box, and a signature line",
      "statement": "The form must show the full consent disclosure, a messaging tick box separable from the phone field, and a signature and date.",
      "rationale": "A phone-number line on an intake form is contact information, not consent to be marketed to. The separable tick box is what turns a form someone filled in for another purpose into an auditable messaging opt-in, and the signature and date are what let you evidence when it happened.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "paper consent form",
      "severity": "BLOCKING",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "paper_consent_form",
      "authorities": [
        "TCR",
        "CTIA",
        "FCC"
      ],
      "applicability": {
        "consentMethods": [
          "paper",
          "employer_hr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by paper form and employer / HR.",
      "universal": false,
      "remediation": "Redesign the form so SMS consent is its own tick box with the full disclosure printed beside it, positioned so a customer can give a phone number without ticking it, plus a signature and date line.",
      "notes": "whenUnreadable is FAIL, against the default. A paper form is evidence the brand chose to submit; if we cannot read the tick box or the disclosure, neither can a reviewer holding the same scan, so an unreadable form fails the same way an absent one does. The user must re-scan it themselves — flatbed or a document-scanner app, not a photograph of a page at an angle.",
      "catalogIds": [
        "CON-153"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-PAPER-FORM",
      "slug": "con-paper-form",
      "title": "Paper opt-in requires a copy of the form",
      "statement": "A campaign collecting consent on paper must supply the form, showing the disclosure and the consent control.",
      "rationale": "Like a verbal script, a paper form is invisible to a crawler — the only way anyone verifies it is if you produce it. Intake forms, waivers and applications are also where messaging consent most often gets bundled into a signature that meant something else entirely.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "paper_consent_form",
      "authorities": [
        "TCR",
        "Aerialink",
        "CTIA"
      ],
      "applicability": {
        "consentMethods": [
          "paper",
          "pos",
          "employer_hr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by paper form, point of sale and employer / HR.",
      "universal": false,
      "remediation": "Attach a scan or PDF of the blank form (not a completed one with customer data on it). We can generate a compliant form with the disclosure, a dedicated tick box, and a signature and date line.",
      "pitfalls": [
        "Do not upload a completed form containing a real customer’s number — supply the blank template."
      ],
      "catalogIds": [
        "CMP-107"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-QR-DEST",
      "slug": "con-qr-dest",
      "title": "QR opt-in must resolve to a compliant surface",
      "statement": "A QR code used for opt-in must land on a page carrying the full consent disclosure, or the disclosure must be printed beside the code.",
      "rationale": "A QR code carries no information a consumer can evaluate — it is an opaque instruction to trust wherever it goes. The disclosure therefore has to exist either next to the code or on the page it opens, and a QR that fires a pre-filled SMS bypasses both.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "qr_landing_copy",
      "authorities": [
        "CTIA",
        "TCR"
      ],
      "applicability": {
        "consentMethods": [
          "qr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by QR code.",
      "universal": false,
      "remediation": "Point the QR at a hosted opt-in page carrying the full disclosure and a real checkbox, and supply that URL or a capture of it. If the code appears on print where you also control the surrounding space, print the disclosure beside it as well.",
      "pitfalls": [
        "A QR that opens a pre-filled \"text JOIN to 55512\" message collects no disclosed consent at all — the consumer never saw terms."
      ],
      "catalogIds": [
        "WEB-102"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-RECORD-FIELDS",
      "slug": "con-record-fields",
      "title": "Consent records must capture the required fields",
      "statement": "The flow should evidence retention of the consent record: number, timestamp, medium, the exact wording agreed to, and the consenting party.",
      "rationale": "CTIA enumerates the fields a consent record must hold, including a capture of the language and action used to secure it. Recording only \"opted in: true\" leaves you unable to show WHAT was agreed to, which is the question every complaint turns on.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "MEDIUM",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "State in the flow that you retain the consent record, and store the disclosure version alongside the timestamp so you can reproduce what the consumer actually saw.",
      "example": "For each opt-in we store the phone number, timestamp, collection medium, the disclosure version shown, and the session or agent identity.",
      "notes": "Registration-side twin of a runtime obligation — we verify the flow claims retention, not that retention happens.",
      "catalogIds": [
        "OPS-200",
        "OPS-206"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-SCOPE-SPLIT",
      "slug": "con-scope-split",
      "title": "Promotional consent must be separate from transactional consent",
      "statement": "A single opt-in must not bundle promotional marketing with informational or transactional messaging.",
      "rationale": "These are different consents with different legal standards: transactional messages can often be sent as part of delivering a service, while marketing requires express written consent that must be optional. One combined box forces the stricter standard onto the whole program and leaves you unable to prove marketing consent for anyone.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "consent surface",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "AWS",
        "CTIA"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30913",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Offer two independently checkable boxes — one for order and account updates, one for promotional offers. The promotional box must be optional and unchecked; the transactional one may be required if the messages are the service.",
      "example": "☐ Send me order and delivery updates by text.\n☐ Send me promotional offers and marketing by text (optional). Consent is not a condition of any purchase.",
      "catalogIds": [
        "CON-159"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-VERBAL-ELEMENTS",
      "slug": "con-verbal-elements",
      "title": "Verbal script must contain all eight required consent elements",
      "statement": "The script must capture explicit consent and state the brand, message types, frequency, rates, opt-out, help, and the privacy policy.",
      "rationale": "Each of the eight elements carries its own DCA reject code, so a script missing one is rejected for that specific reason rather than generically — and the fix is correspondingly specific. Oral consent is only valid where it captures the same substance a written disclosure would, which is why the element list mirrors the web one.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "verbal script",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "verbal_script",
      "authorities": [
        "TCR",
        "FCC",
        "CTIA"
      ],
      "codes": [
        {
          "provider": "TCR/DCA",
          "code": "2105",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "2108",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "2109",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "2110",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "2111",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "2112",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "2119",
          "remediable": true
        },
        {
          "provider": "TCR/DCA",
          "code": "7107",
          "remediable": true
        }
      ],
      "applicability": {
        "consentMethods": [
          "verbal_live",
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by live verbal and IVR.",
      "universal": false,
      "remediation": "Amend the script so every element is spoken, and have the agent capture an explicit \"yes\" rather than treating silence or continuing the call as agreement. Record the call or log the consent timestamp against the customer record.",
      "example": "\"Before we finish — would you like to receive text messages from Acme Coffee about your orders and our promotions? Message frequency varies, message and data rates may apply, you can reply STOP at any time to unsubscribe or HELP for help, and our privacy policy is at acmecoffee.com/privacy. Can I confirm you agree to receive these texts at the number ending 4471?\"",
      "catalogIds": [
        "CMP-109"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-VERBAL-RECORD",
      "slug": "con-verbal-record",
      "title": "Verbal consent must describe how assent is recorded",
      "statement": "The flow must state how the consumer’s spoken agreement is captured and retained — recording, transcript, IVR log, or timestamped CRM entry.",
      "rationale": "Spoken consent evaporates unless it is written down. If a complaint arrives eighteen months later, the retained record is the only thing standing between you and an unprovable claim, and both the FCC and CTIA expect the record to exist.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "FCC",
        "CTIA",
        "TCR"
      ],
      "applicability": {
        "consentMethods": [
          "verbal_live",
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by live verbal and IVR.",
      "universal": false,
      "remediation": "Add a sentence to the message flow describing capture and retention. Name the system of record and what is stored against the customer.",
      "example": "Calls are recorded, and the agent logs the consent timestamp, the script version read, and the number consented against the customer record in our CRM. Records are retained for at least 4 years.",
      "pitfalls": [
        "Two-party consent states constrain call recording — where you cannot record, log the timestamp and script version instead."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "CON-VERBAL-SCRIPT",
      "slug": "con-verbal-script",
      "title": "Verbal opt-in requires the documented script",
      "statement": "A campaign collecting consent by phone must supply the exact script read to the consumer.",
      "rationale": "A verbal opt-in leaves no artifact unless you make one — there is no page to crawl and no box to screenshot. The script IS the consent surface, so it is the only thing a reviewer can inspect to decide whether what your agents say actually obtains consent.",
      "layer": "CONSENT_FLOW",
      "layerSlug": "consent-flow",
      "object": "campaign.message_flow + consent artifact",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_ARTIFACT",
      "artifact": "verbal_script",
      "authorities": [
        "TCR",
        "FCC",
        "Aerialink"
      ],
      "applicability": {
        "consentMethods": [
          "verbal_live",
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by live verbal and IVR.",
      "universal": false,
      "remediation": "Attach the verbatim script your agents read, not a summary of it. We can generate a compliant script covering all eight required elements, which you can adapt and hand to your team.",
      "pitfalls": [
        "\"Agents ask for permission to text\" describes a policy, not a script — a reviewer cannot audit it."
      ],
      "catalogIds": [
        "CMP-108"
      ],
      "phase": "approval",
      "automated": true
    }
  ]
}
