{
  "layer": "WEBSITE",
  "name": "Website",
  "url": "https://ekas.io/rules/10dlc/website/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/",
  "count": 93,
  "rules": [
    {
      "id": "WEB-001",
      "slug": "web-001",
      "title": "A brand website URL is required",
      "statement": "Every brand registration must carry a website URL or an equivalent hosted online-presence artifact.",
      "rationale": "The website is the primary artifact a reviewer uses to decide the business is real and does what the campaign claims. Without one there is nothing to corroborate the registration against, and most providers will not vet a brand at all.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "Telnyx",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add the business website. If the business genuinely has no site, a public, indexable business profile page can substitute at some providers — but expect additional scrutiny and a slower vet.",
      "example": "https://acmecoffee.com",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-004",
      "slug": "web-004",
      "title": "The website value must fit the provider field limit",
      "statement": "The website URL must fit within the provider field cap (100 characters at the tightest).",
      "rationale": "Some providers cap the website field at 100 characters and truncate silently rather than erroring, which produces a stored URL that no longer resolves. A deep link with tracking parameters overruns easily.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website",
      "severity": "MEDIUM",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "Telnyx",
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Use the bare site root without tracking parameters or deep paths in the brand website field.",
      "example": "https://acmecoffee.com",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-006",
      "slug": "web-006",
      "title": "The website should sit on a custom domain",
      "statement": "The brand website should be on a domain the business owns, not a free platform subdomain.",
      "rationale": "A free platform subdomain costs nothing and takes minutes to create, so it carries almost no evidential weight about a business existing. Reviewers treat it as a weak signal rather than an automatic rejection, but it materially raises the chance of a manual review.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website",
      "severity": "MEDIUM",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Point a custom domain at the site and register that domain as the brand website. Keep the brand email on the same domain so the two corroborate each other.",
      "example": "https://acmecoffee.com rather than https://acmecoffee.myshopify.com",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-009",
      "slug": "web-009",
      "title": "The website must resolve and return content",
      "statement": "The submitted website URL must resolve to a live host and return a successful response.",
      "rationale": "A site that does not load cannot be assessed, and DNS or timeout failures are indistinguishable to a reviewer from a business that does not exist. This is checked at submission and again during vetting, so intermittent hosting fails it twice.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Confirm the URL loads from a clean network with no VPN, and check DNS resolves publicly. Fix hosting before submitting rather than resubmitting hopefully.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-012",
      "slug": "web-012",
      "title": "A parked or for-sale domain is not a website",
      "statement": "A registrar placeholder, parked domain, or domain-for-sale page is rejected.",
      "rationale": "A parked domain proves someone bought a name, not that a business operates. It is a strong fraud signal because it is exactly what a registration created to obtain numbers looks like.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish the real site at that domain, or submit the domain where the business actually operates.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-013",
      "slug": "web-013",
      "title": "A pre-launch placeholder is not a website",
      "statement": "A \"coming soon\" or \"under construction\" page is rejected as the brand website.",
      "rationale": "A business not yet open to customers has no consenting subscribers to message, so the placeholder page and the campaign contradict each other. Reviewers read it as registering ahead of having a programme.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Launch the site before registering. Register once you have a live site and real subscribers.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-014",
      "slug": "web-014",
      "title": "Staging, admin and internal hosts must not be the brand website",
      "statement": "Non-production hosts — staging, dev, preview, admin, internal — are not acceptable brand websites.",
      "rationale": "A staging host is not the business's public presence, is frequently access-gated, and often disappears between submission and review. Submitting one usually means someone pasted the URL they had open rather than the live site.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Submit the public production URL customers actually visit. If the staging host is the only one currently live, launch the production site before registering — the vetter will re-fetch this URL days later and a staging box is usually gone by then.",
      "example": "https://acmecoffee.com rather than https://staging.acmecoffee.com",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-015",
      "slug": "web-015",
      "title": "Pages the registration points at must not be broken",
      "statement": "Any page the registration references must load — no broken internal links, 404s, or links pointing at the wrong page.",
      "rationale": "A reviewer following a link from the registration into a 404 concludes the site is unmaintained, and unmaintained sites are the ones that disappear between submission and the vet weeks later. The links that break are almost always the ones nobody clicks: the policy page renamed during a redesign, the old opt-in path left in the message flow.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "internal links on the referenced pages",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Bandwidth",
        "Telnyx",
        "Bird",
        "Aerialink"
      ],
      "codes": [
        {
          "provider": "Bandwidth/DCA",
          "code": "804",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Click every URL in the registration and every link on the pages they open, and fix or remove the ones that fail. Done when the policy, terms and opt-in links all resolve to the pages they name.",
      "notes": "Needs a multi-page crawl to settle properly. Against the current single-page fetch it can only see links on the one page retrieved, and must say so rather than reporting the rest as sound.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-016",
      "slug": "web-016",
      "title": "The website must be machine-crawlable",
      "statement": "The site must be fetchable by an automated vetter — no robots.txt disallow, no noindex, no JS-only render, no geofence.",
      "rationale": "Vetting uses a headless fetcher, not a browser. A single-page app that renders only after JavaScript returns an empty shell to the reviewer, so a fully compliant opt-in becomes invisible and the campaign is rejected for having no discoverable consent flow.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Server-render the opt-in page, or provide a server-rendered alternative URL carrying the same consent surface. Remove robots.txt disallows on that path and confirm the page returns content from a US IP with JavaScript disabled.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-017",
      "slug": "web-017",
      "title": "The site must not be gated by geo, bot challenge or app wall",
      "statement": "A geo-gate, bot challenge, captive portal, or app-install wall blocking the reviewer is rejected.",
      "rationale": "Vetting fetches from a US datacentre IP, which aggressive bot protection frequently blocks outright. The site works perfectly for customers and returns a challenge page to the reviewer, so the failure is invisible from the brand's side.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Allowlist datacentre traffic for the policy and opt-in pages, or lower the bot-protection level on them. Confirm the pages load from a cloud IP, not just from your office.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-018",
      "slug": "web-018",
      "title": "The site must be readable in English",
      "statement": "The website must be renderable in English, or an English version must be supplied.",
      "rationale": "US 10DLC reviewers assess against US requirements in English. A site with no English version cannot be evaluated for the disclosures and business description the registration depends on.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Provide an English version of the site, or at minimum English pages for the business description, privacy policy, and SMS terms.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-019",
      "slug": "web-019",
      "title": "The site must stay live for the whole vetting window, not just at submission",
      "statement": "The brand website must remain live and publicly reachable for the entire vetting period, which runs weeks after submission.",
      "rationale": "Vetting re-fetches the site days or weeks later, so a site that was up when the form was filled in is not the thing being judged. The named failure is a password-protected storefront: a shop put into maintenance mode for a redesign, or a trial plan that lapses, takes the brand down with it and the rejection arrives with no hint that timing was the cause.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website over the review window",
      "severity": "HIGH",
      "detectability": [
        "UNDETECTABLE_PRE_SUBMISSION"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "AWS",
        "Bandwidth",
        "Klaviyo",
        "Postscript"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Keep the site public and unchanged until the brand and campaign are approved. Do not schedule a migration, a password gate or a plan downgrade during the window; AWS states 10DLC review takes at least four to six weeks and toll-free three to ten business days.",
      "notes": "Nothing at submission time can settle this — the failure happens after we stop looking. Surfaced as a warning with the deadline: the user has to hold the site up, and to hold off any redesign or hosting change, until approval lands.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Is any redesign, migration, password gate or hosting downgrade scheduled between now and approval?",
        "howToCheck": [
          "Ask whoever runs the site what is planned for the next six weeks. AWS states 10DLC review takes at least four to six weeks and toll-free three to ten business days.",
          "Hold the site public and unchanged until the brand and campaign are approved.",
          "Check any trial plan or hosting subscription that could lapse mid-review."
        ],
        "failureLooksLike": "A shop is put into maintenance mode for a redesign three weeks after submission. Vetting re-fetches the site, finds a password-protected storefront, and the rejection gives no hint that timing was the cause."
      }
    },
    {
      "id": "WEB-021",
      "slug": "web-021",
      "title": "The site must not be behind a login or access wall",
      "statement": "The brand website must be publicly reachable without authentication.",
      "rationale": "A reviewer with no account cannot assess a site they cannot open, so an SSO or password wall is functionally identical to a site that does not exist. This is a distinct code from a broken site because the fix is different: expose a public surface rather than repair anything.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "TCR",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30921",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish a public marketing site describing the business, even where the product itself sits behind a login. Where the opt-in genuinely lives inside the authenticated area, supply a screenshot of it instead.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-022",
      "slug": "web-022",
      "title": "A login-gated product needs a public description page",
      "statement": "Where the brand's service genuinely sits behind a login, a public page describing the business and its messaging programme is required.",
      "rationale": "Plenty of legitimate businesses are entirely authenticated products, and rejecting them outright would be wrong. The requirement is a public surface a reviewer can read — not that the product itself be open.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish a public marketing or about page describing what the business does, who it serves, and what the SMS programme sends, and register that URL as the brand website.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-024",
      "slug": "web-024",
      "title": "The site must not look inauthentic",
      "statement": "A site judged to be a shell, an unmodified template, scraped or fabricated content, or stock-imagery-only is rejected.",
      "rationale": "Fraudulent registrations stand up a plausible-looking site to satisfy the website requirement, so reviewers learned to judge authenticity rather than mere existence. This is distinct from a site being incomplete: an unmodified theme demo with lorem text fails even though every required page exists.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "AWS",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish real content: actual products or services with real descriptions and prices, a real About page, real contact details, and photography of the actual business.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-026",
      "slug": "web-026",
      "title": "The site must look established rather than erected for the registration",
      "statement": "The website should show signs of being an operating business, not a shell created to pass vetting.",
      "rationale": "Reviewers weigh apparent age and depth because a site built the week before registration is the standard fraud pattern. Thin, brand-new sites are not automatically rejected but attract manual review and slower vetting.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish real depth before registering: products or services with detail, an about page, contact information, and any customer-facing content that shows the business operating.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-027",
      "slug": "web-027",
      "title": "The site must be more than a bare lead-capture form",
      "statement": "A URL resolving to a standalone lead form with no surrounding business site is rejected.",
      "rationale": "A page whose only content is a form collecting a phone number is the archetypal lead-generation surface, and lead generation is precisely what the consent-transfer rules prohibit. Reviewers therefore treat a bare form as evidence of the business model rather than as a thin website.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "TCR",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30920",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Point the brand website at your full site — home, about, contact, and product or service pages — rather than at the campaign landing page. Keep the landing page for the message flow field.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-028",
      "slug": "web-028",
      "title": "A campaign landing page is not the brand website",
      "statement": "Where the business runs a main site, that site must be registered as the brand website rather than a single campaign landing page.",
      "rationale": "A landing page is written to sell one thing, so it describes an offer rather than a business — and the reviewer needs the business. This is distinct from a bare lead form: the page can be perfectly substantial and still be the wrong page, which is why the fix is to change the URL rather than to build anything.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website vs the discoverable main site",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "Twilio",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30920",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Put the main business domain in brand.website and keep the landing page where it belongs, in the message flow as the opt-in URL. Done when brand.website opens a site with navigation to the rest of the business.",
      "example": "website: https://acmecoffee.com · message flow opt-in URL: https://acmecoffee.com/rewards-signup",
      "notes": "Different fix from WEB-027, which rejects a bare lead-capture form with no business behind it at all. Here the business exists and the wrong URL was submitted.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-030",
      "slug": "web-030",
      "title": "E-commerce brands need a published catalog",
      "statement": "An e-commerce brand must show a real, populated product catalog rather than a placeholder store.",
      "rationale": "An empty or demo store is the e-commerce version of a shell site, and it directly contradicts a campaign describing order and promotional messaging. There are no orders to notify anyone about.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio"
      ],
      "applicability": {
        "verticals": [
          "RETAIL"
        ]
      },
      "applicabilityText": "Applies when the vertical is RETAIL.",
      "universal": false,
      "remediation": "Publish the real catalog with products, prices and descriptions before registering.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-031",
      "slug": "web-031",
      "title": "The business name on the site must match the registered brand",
      "statement": "The name displayed on the website must match the registered legal name or DBA.",
      "rationale": "The name match is how a reviewer connects the registration to the site, and it is the check that catches a reseller registering a client's traffic under the wrong entity. A mismatch with no stated relationship is treated as an identity failure rather than a branding choice.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + brand.company_name",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Display the registered name prominently in the header, footer, or about page. Where the site trades under a different name, register that name as the DBA on the brand record.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-032",
      "slug": "web-032",
      "title": "The business name must be visible on the page, not only in the markup",
      "statement": "The business name or branding must be displayed in the logo, header or footer of the rendered page, not carried only in the title tag or metadata.",
      "rationale": "A reviewer decides whose site this is by looking at it for a few seconds. A name that lives only in the page title, or only in an image with no text near it, means the answer is \"nobody in particular\" — which is the impression a template site left unbranded also gives, and it is the one this rule exists to catch.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "rendered header, footer and logo region",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30492",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth",
          "code": "TFV 1205",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Put the business name in the site header or footer as text, next to or instead of the logo image. Done when the name is legible in a screenshot of the top of the page without opening the source.",
      "notes": "Whether the name is present in the text at all is WEB-031, which reads the body. This rule is about prominence, which only the rendered page shows — hence VISION.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-034",
      "slug": "web-034",
      "title": "The site must describe the business and the messaging programme",
      "statement": "The website must carry enough information about the business, and ideally the messaging programme, for a reviewer to understand what is being registered.",
      "rationale": "Reviewers cross-check the site against the campaign, so a site that never says what the business does leaves nothing to check against. Twilio codes this separately from \"site is a bare form\" because a site can be substantial and still never explain the business.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "TCR",
        "AWS"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30919",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add a clear description of what the business does and who it serves, plus a page describing the SMS programme and linking to the SMS terms.",
      "catalogIds": [
        "WEB-029",
        "WEB-042"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-035",
      "slug": "web-035",
      "title": "The reseller platform website must not stand in for the customer site",
      "statement": "An ISV or reseller must not submit its own platform website in place of the end customer's.",
      "rationale": "This is the website-side twin of registering the wrong entity. It looks harmless — the platform site is real and substantial — but it means the brand being vetted is not the business that will send the messages.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website + brand.company_name",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Submit the end customer's own website. Your platform belongs on the CSP record, never on the brand.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-037",
      "slug": "web-037",
      "title": "The site, the registered name and the registered address must agree",
      "statement": "The business described on the website, the registered company name and the registered postal address must corroborate one another.",
      "rationale": "Verification works by finding the same business in two independent places, so a site that names a different company, or shows an address in another state, leaves the reviewer with two businesses and no way to join them. The honest version of this is common: the registration carries the legal entity and the accountant's address while the site carries the trading name and the shop, and nothing on either says they are the same people.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "website content vs brand.company_name + brand address",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish the legal entity name and the registered address somewhere on the site — the footer, the contact page or the terms — even where the business trades under a shorter name. Done when a stranger reading the site can find both values exactly as the registration states them.",
      "pitfalls": [
        "A registered agent or accountant address on the brand record and the shop address on the site is a mismatch even though both are true. Publish both on the site, or register the one the site shows."
      ],
      "notes": "The catalog scopes this to the toll-free verification path, where AWS applies it as the business-verification standard. It is authored universally because the same corroboration is what every vetting path performs; where a provider does not apply it, satisfying it costs nothing.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-039",
      "slug": "web-039",
      "title": "Contact details on the site must match the brand record",
      "statement": "The support phone and contact shown on the website should match the brand registration.",
      "rationale": "Corroboration between site and registration is what turns two weak signals into one strong one. Divergent contact details are a common sign that the registration was assembled from someone else's business information.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + brand.phone + brand.email",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Make the contact details on the site and on the registration the same, or explain the difference (for example a separate support line) somewhere visible.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-043",
      "slug": "web-043",
      "title": "The site must have an About page and a Contact page",
      "statement": "An About page and a Contact page must exist on the brand domain.",
      "rationale": "These two pages are where a reviewer goes first, because between them they answer who this is and how to reach them — the two questions the whole website requirement exists to settle. A site that answers both somewhere in a scrolling home page still fails the reviewer's habit of looking for them in the navigation.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "site navigation",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Plivo",
        "TCR",
        "MessageIQ"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30919",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add an About page describing the business and a Contact page carrying an address, a phone number and an email, and link both from the site navigation. Done when both are reachable in one click from the home page.",
      "notes": "Absorbs POL-039, which states the same page inventory and adds the privacy policy and terms — those two are already required by WEB-045 and WEB-046. Severity divergence in the catalog: Plivo lists the missing pages among its rejection reasons while the row itself is graded MEDIUM; graded HIGH here because two of the four pages it names are separately BLOCKING.",
      "catalogIds": [
        "POL-039"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-044",
      "slug": "web-044",
      "title": "The footer should carry a phone number, an email and a street address",
      "statement": "The site footer should show a business phone number, an email address and a physical street address rather than a PO box.",
      "rationale": "The footer is the one place a reviewer can check on every page without navigating, so a business that puts all three there answers the corroboration question wherever the crawl happens to land. This is the stricter, conjunctive form of the contact requirement, and the street address is the element most often missing — a PO box proves a mailbox was rented, not that anyone works anywhere.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "site footer",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add all three to the site footer template so they appear on every page, using the same values as the brand record. Done when the footer of an interior page carries a street address, a phone number and an email.",
      "notes": "Single secondary source in the catalog, flagged unverified, and the \"not a PO box\" element in particular has no carrier code behind it — hence MEDIUM and worded as an expectation. The weaker, disjunctive requirement that contact information appear somewhere is WEB-047, which is the one that fails a site outright.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-045",
      "slug": "web-045",
      "title": "A privacy policy must be reachable from the website",
      "statement": "The brand website must link to a reachable privacy policy.",
      "rationale": "Reviewers navigate from the site to the policy rather than trusting the URL field alone, and a policy that exists but is unlinked reads as one created solely for the registration. CTIA also requires it to be reachable from the call to action.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Link the privacy policy from the site footer and from the opt-in surface.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-046",
      "slug": "web-046",
      "title": "Terms must be reachable from the website",
      "statement": "The brand website must link to reachable Terms & Conditions or SMS Terms.",
      "rationale": "The terms are where the messaging programme is documented for consumers, so an unlinked terms page is unreachable by the people it exists to inform. Reviewers check the path a real consumer would take.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Link the terms (or a dedicated SMS terms page) from the site footer and from the opt-in surface.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-047",
      "slug": "web-047",
      "title": "The site must show business contact information",
      "statement": "The website must display contact details — an address, phone number, or support email identifying the business.",
      "rationale": "Contact details are how a reviewer corroborates that the business is real and matches the brand record, and CTIA separately requires that a message URL and its destinations identify the owner with contact information. A site with no way to reach anyone reads as a front.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish a contact page with the business address, a phone number, and a support email on the brand domain, and check they match the brand registration.",
      "catalogIds": [
        "WEB-041"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-054",
      "slug": "web-054",
      "title": "A brand with a website must publish its policies as web pages, not as PDFs",
      "statement": "Where the brand has a website, the privacy policy and terms URLs must serve an HTML page rather than a PDF or other downloadable file.",
      "rationale": "Vetters read policy pages with a text fetcher, and a PDF frequently comes back as an empty body — so a complete, correct policy is scored as a missing one. It also breaks the consumer path the rules exist to protect: a phone that downloads a file instead of showing a page is a dead end at exactly the moment someone is deciding whether to consent.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "Content-Type of privacyPolicyUrl and termsOfServiceUrl",
      "severity": "MEDIUM",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "7102",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Publish the policy as an HTML page on the brand domain and submit that URL; keep the PDF as an extra download if you want one. Done when the policy URL returns text/html.",
      "example": "privacy_policy_url: https://acmecoffee.com/privacy (text/html), not https://acmecoffee.com/files/privacy.pdf",
      "pitfalls": [
        "Uploading a PDF is the sanctioned route for a brand with NO website — this rule only fires when a site exists, and swapping a working page for a file to satisfy a provider that accepts uploads makes things worse."
      ],
      "notes": "Absorbs POL-019, the same warning stated from the policy-page side. The catalog marks the underlying source unverified — inferred from Twilio 7102 rather than published as a rule — so it is graded MEDIUM and worded as an expectation rather than a refusal.",
      "catalogIds": [
        "POL-019"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-055",
      "slug": "web-055",
      "title": "The site should describe the SMS programme",
      "statement": "The website should carry information about what the messaging programme sends, to whom, and why.",
      "rationale": "A programme described only inside the registration exists only for the reviewer. Documenting it publicly is both a CTIA expectation and the thing that lets a consumer verify the messages they receive are legitimate.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add a short SMS programme section to the site or the SMS terms page: what you send, how often, who it is for, and how to stop.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-056",
      "slug": "web-056",
      "title": "Opt-in and opt-out information must be clear on the site",
      "statement": "The website must display how to opt in and how to opt out.",
      "rationale": "A consumer who wants to stop should not have to wait for the next message to find out how. Publishing both routes on the site is a CTIA expectation and materially reduces the complaint rate that drives carrier filtering.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "State on the site how to join and how to leave, naming the keywords: \"Reply STOP to any message to unsubscribe.\"",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-057",
      "slug": "web-057",
      "title": "Website content must be consistent with the declared use case",
      "statement": "What the website shows the business doing must be consistent with the campaign use case.",
      "rationale": "The use case determines the consent standard and throughput a campaign receives, so reviewers verify it against the business rather than accepting the selection. A site that is plainly an e-commerce store behind a 2FA-only registration reads as an attempt to obtain transactional treatment for marketing traffic.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign.usecase",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "AWS",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Choose the use case that matches what the site shows the business doing. Where you genuinely send several categories, use MIXED and collect promotional-grade consent.",
      "example": "A retail site sending promotions and order updates → MIXED, not ACCOUNT_NOTIFICATION.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-058",
      "slug": "web-058",
      "title": "Website, description, flow and samples must identify one sender",
      "statement": "The website, campaign description, message flow and sample messages must all identify the same sending business.",
      "rationale": "Each artifact is written separately, so a single inconsistent name is common and innocent — but a reviewer cannot distinguish that from a registration assembled out of several businesses. Consistency across all four is what makes the sender verifiable.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign fields + samples",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Use one customer-facing name everywhere, and make it the registered brand display name or DBA.",
      "example": "Website header, description, message flow and every sample all say \"Acme Coffee\".",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-059",
      "slug": "web-059",
      "title": "The site referenced in the message flow must be the registered brand site",
      "statement": "The website referenced inside the message flow must belong to the same business as the registered brand website.",
      "rationale": "A message flow pointing at a different domain usually means consent is collected on a partner or platform property, which raises the consent-transfer question directly. Where it is legitimate, it needs explaining rather than leaving for a reviewer to infer.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "campaign.message_flow + brand.website",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Reference the brand's own domain in the message flow. Where consent is collected on a third-party platform, say so explicitly and explain the relationship.",
      "example": "Brand website acmecoffee.com; message flow references acmecoffee.com/signup.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-060",
      "slug": "web-060",
      "title": "Declared attributes must be consistent with the crawled site",
      "statement": "The declared campaign attributes must be consistent with what the website shows, not only internally consistent with the form.",
      "rationale": "Attributes are self-declared, so the website is the only independent evidence available. A site showing age-restricted products behind a campaign declaring no age gating is a contradiction the form alone can never reveal.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign attributes",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Reconcile each attribute against the website: age-gated products, lending offers, links and phone numbers in messaging.",
      "example": "Site sells age-restricted products → age gated: true.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-062",
      "slug": "web-062",
      "title": "An undeclared additional use case must be surfaced",
      "statement": "Where the website or description implies a message category the campaign has not declared, it must be flagged.",
      "rationale": "Live traffic must match the registered use case, and an undeclared category is a violation waiting to happen the first time that content is sent. Catching it at registration is the difference between adding a use case and being filtered later.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign.description",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Sinch"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Declare every category you will send, or remove the undeclared one from your plans. MIXED covers promotional plus transactional.",
      "example": "Site shows cart-abandonment flows → declare MARKETING (or MIXED), not ACCOUNT_NOTIFICATION alone.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-063",
      "slug": "web-063",
      "title": "Charitable solicitation on the site forces the charity use case",
      "statement": "Where the website, description, or samples solicit donations, the charity use case must be used.",
      "rationale": "Donation solicitation carries eligibility requirements — verified 501(c)(3) status — that exist precisely to stop fraudulent charity messaging. Running it under a marketing use case bypasses that check, so reviewers force the correction.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign.usecase",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Infobip"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Register under the CHARITY use case with 501(c)(3) status declared on the brand, or remove the donation ask from both the campaign and the messaging programme.",
      "example": "Entity type: NON_PROFIT · Tax exempt status: 501(c)(3) · Use case: CHARITY",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-064",
      "slug": "web-064",
      "title": "Political content on the site forces the political use case",
      "statement": "Where the website, description, or samples carry political-campaign content, the political use case must be used.",
      "rationale": "Political messaging requires external vetting recognised by both major carriers, and that requirement is meaningless if the category can be avoided by choosing a different label. Reviewers therefore assess the content, not the selection.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign.usecase",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "AT&T",
        "T-Mobile"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Register under POLITICAL on a NON_PROFIT brand with political vetting imported, or remove political content from the programme entirely.",
      "example": "Use case: POLITICAL, on a NON_PROFIT brand with Campaign Verify vetting.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-066",
      "slug": "web-066",
      "title": "Lending content anywhere requires the direct-lending declaration",
      "statement": "Where lending content appears in the description, the message flow, or the website, directLending must be declared.",
      "rationale": "The attribute exists so carriers can apply the right scrutiny to credit messaging, and it is assessed against the website as well as the form. Undeclared lending is treated as concealment rather than oversight, which is a much worse posture than declaring it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + campaign.direct_lending",
      "severity": "BLOCKING",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Set the direct-lending attribute true when the business offers credit of any kind. Declaring it is a fixable attribute question; concealing it is a business-model rejection.",
      "example": "Site offers financing → direct lending: true.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-068",
      "slug": "web-068",
      "title": "A cart-reminder programme must say so in the opt-in terms on the site",
      "statement": "Where the programme sends shopping-cart reminders, the opt-in terms shown at the call to action must disclose it.",
      "rationale": "A cart reminder is a message about something the consumer did not finish doing, sent because their behaviour was tracked — so T-Mobile requires it to be disclosed where consent is given rather than discovered when the first one arrives. Retailers add abandoned-cart flows through a platform months after the checkbox copy was written, and nothing in that flow prompts anyone to go back and update it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "opt-in disclosure text on the site",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "T-Mobile"
      ],
      "codes": [
        {
          "provider": "T-Mobile",
          "code": "8003",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add cart reminders to the message types named in the opt-in disclosure beside the consent control. Done when the text at the checkbox names them alongside whatever else the programme sends.",
      "pitfalls": [
        "Updating the SMS terms page is not enough on its own — T-Mobile asks for the disclosure at the call to action, which is the checkbox copy, and POL-109 separately asks the privacy policy to say how abandonment is detected."
      ],
      "notes": "Conditional on cart-reminder traffic being in scope, which no applicability dimension expresses — there is no cart-reminder attribute. The condition is carried in the criteria, which pass immediately when the programme sends no cart reminders.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-069",
      "slug": "web-069",
      "title": "The described opt-in and the live opt-in must both pass, separately",
      "statement": "The call to action as described in the registration and the call to action as it appears live on the website must be audited as two separate passes.",
      "rationale": "Ranked the #2 most-missed check in the catalog. A brand can describe a perfect opt-in that does not exist on the site, or run a compliant opt-in and describe it badly — those are different failures with different fixes, and collapsing them into one verdict hides whichever one is broken. Reviewers genuinely do both passes.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "campaign.message_flow + live website opt-in",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Reconcile the two: make the live page carry everything the description claims, and make the description match what the page actually shows. Where they diverge, fix the page first — the page is what the consumer saw.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-070",
      "slug": "web-070",
      "title": "The call to action described in the registration must exist on the site",
      "statement": "Where consent is collected on the site, the call to action the registration describes must be findable on the crawled site.",
      "rationale": "A described opt-in that cannot be found reads to a reviewer as consent that does not exist, which is the strongest possible reason to refuse a campaign — and it is usually true by accident: the page moved in a redesign, the form sits behind an interaction the crawler never triggers, or the description was written from the plan rather than from the site. The consumer-side stake is the same one: an opt-in nobody can locate is one nobody can audit.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "live site vs campaign.message_flow",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "Zoom"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30891",
          "remediable": true,
          "generation": "gen1"
        }
      ],
      "applicability": {
        "consentMethods": [
          "web_form",
          "checkout",
          "qr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by web form, checkout and QR code.",
      "universal": false,
      "remediation": "Give the exact URL of the page holding the consent control in the message flow, and confirm the control is present in the page source rather than injected after an interaction. Done when opening that URL in a private window shows the opt-in without clicking anything.",
      "pitfalls": [
        "A consent box that only appears after a product is added to the cart is invisible to a crawler that never adds one. Supply a screenshot of the checkout step as well, or the reviewer sees a page with no opt-in on it."
      ],
      "notes": "The twin of WEB-069, which audits the described and live opt-ins as two passes. This rule is the narrower question underneath it: does the described surface exist at all.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-072",
      "slug": "web-072",
      "title": "A verbal-only programme should not point at a website with no consent surface",
      "statement": "Where verbal opt-in is the only declared consent method, the registration must not supply a website opt-in URL that shows no SMS consent surface.",
      "rationale": "A reviewer given a URL looks for the opt-in on it, finds nothing, and records that the consent surface could not be verified — which is a worse outcome than the honest one, where a phone script is the evidence and the site was never offered as such. Brands do this by reflex because the form asks for a URL, so they paste the home page.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website vs the declared consent method",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "AWS"
      ],
      "applicability": {
        "consentMethods": [
          "verbal_live",
          "verbal_ivr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by live verbal and IVR.",
      "universal": false,
      "remediation": "Describe the call in the message flow and attach the script or recording as the evidence, rather than pointing at a page that does not collect consent. Keep the website on the brand record, where it belongs — this rule is about the opt-in URL only.",
      "example": "message flow: \"Consent is captured verbally during the support call; the agent reads the disclosure from the attached script.\" No opt-in URL supplied.",
      "notes": "Flagged unverified in the catalog — an inference from the AWS UNCLEAR_OPT_IN reason rather than a published rule. Tagged to the two verbal methods, so a brand that also collects consent on the web is never asked about it.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-073",
      "slug": "web-073",
      "title": "The brand website must serve a certificate that verifies",
      "statement": "The brand website must present a valid TLS chain — not expired, not self-signed, and issued for the hostname actually submitted.",
      "rationale": "A vetting crawler stops at a certificate error and never reads a word of the site, so the rejection arrives as \"the website could not be verified\" rather than as anything about a certificate. Browsers hide this: the people who work at the business have been clicking through the warning for months, and a certificate valid for the bare domain but not for the www form fails only for whoever submitted the other one.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website TLS chain",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Bandwidth",
        "TCR",
        "Twilio",
        "Plivo"
      ],
      "codes": [
        {
          "provider": "Bandwidth",
          "code": "1103",
          "remediable": true
        },
        {
          "provider": "Bandwidth/DCA",
          "code": "2103",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Reissue the certificate for the exact hostname in brand.website, covering both the www and bare-domain forms, and renew before expiry. Done when an external SSL checker — not your own browser — reports a complete, valid chain for the URL you are about to submit.",
      "pitfalls": [
        "A certificate valid for acmecoffee.com and not for www.acmecoffee.com fails whenever the submitted URL uses the other form. Submit the form the certificate actually covers.",
        "An expired intermediate is invisible in Chrome, which caches the issuer, and fatal to a strict crawler that does not. Test from outside your own network."
      ],
      "notes": "Absorbs BRD-128, which states the same certificate requirement from the brand-record side. Severity divergence in the catalog: website-evidence-012 and CARR-008 grade a TLS failure HIGH; Bandwidth, Plivo and Twilio grade it BLOCKING. Strictest kept.",
      "catalogIds": [
        "BRD-128"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-074",
      "slug": "web-074",
      "title": "Pages must not load sub-resources over HTTP",
      "statement": "A page must not load sub-resources over, or redirect through, unencrypted HTTP — mixed content fails.",
      "rationale": "Mixed content produces browser warnings on the exact page where a consumer is about to hand over a phone number, which undermines the trust the whole framework is built on. It also frequently signals an unmaintained site.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "opt-in landing page",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Serve every asset over https and remove any http:// redirect hop in the chain to the opt-in page.",
      "notes": "Not decidable from a markdown-only fetch — needs the raw HTML and the sub-resource list. Recorded so the crawler gap is visible rather than silently unchecked.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-075",
      "slug": "web-075",
      "title": "Submitted URLs must not redirect",
      "statement": "A URL submitted to TCR must resolve directly rather than returning a 30x redirect.",
      "rationale": "TCR forbids redirection on fetched URLs. This is deeply counter-intuitive because the link works perfectly in a browser — including the http-to-https upgrade almost every site performs — so brands submit a URL they have personally tested and are rejected anyway.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website + campaign URLs",
      "severity": "HIGH",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Submit the canonical URL you land on after all redirects resolve — with https, the final host (www or bare), and the final path.",
      "example": "Submit https://www.acmecoffee.com/signup rather than http://acmecoffee.com/signup",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-077",
      "slug": "web-077",
      "title": "The website must not redirect to an unrelated brand",
      "statement": "A brand website that redirects to a business other than the registered brand is rejected, whatever the submitted URL says.",
      "rationale": "A domain that forwards to somebody else is the signature of a registration assembled from a bought or borrowed domain, and it is also what happens innocently when a business is acquired and its old domain is pointed at the new owner. Reviewers cannot tell those apart from the outside, so the one that gets explained on the registration is the one that survives.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website final host + landing content",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "TCR",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30907",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth/DCA",
          "code": "603",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Register the domain the business actually trades under. Where the redirect is deliberate — a rebrand, an acquisition, a franchisor site — say so in the campaign description and make the destination state the relationship in visible page content.",
      "notes": "Absorbs BRD-131. The ambiguous case named in the catalog is a redirect to a parent company or franchisor: legitimate, and indistinguishable from a hijack unless the destination says so on the page.",
      "catalogIds": [
        "BRD-131"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-079",
      "slug": "web-079",
      "title": "A redirected URL is reviewed at its destination, not where it was submitted",
      "statement": "Where a submitted URL redirects off the registered domain, the full content review applies to the destination, so the destination is what the registration must be able to survive.",
      "rationale": "Reviewers follow the chain and judge whatever they land on, which means a brand can be assessed against a site it did not submit and does not control — a marketing shortener, an agency landing page, a marketplace storefront. The business believes its own site was reviewed and cannot understand the finding, because nothing in the rejection names the page that produced it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website redirect chain",
      "severity": "BLOCKING",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "CTIA",
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Register the URL the chain actually ends on, or remove the off-domain hop so the submitted address serves the content directly. Done when brand.website and the final URL of the fetch are the same registrable domain.",
      "example": "brand.website: https://acmecoffee.com — fetch ends on acmecoffee.com, not on a link-shortener or an agency landing page.",
      "pitfalls": [
        "Pointing the registration at the destination fixes this and can still fail WEB-077 if the destination belongs to a different business — moving the URL does not change whose site is being judged."
      ],
      "notes": "A scoping rule: it changes what every other content check reads. Fenced against its two neighbours — WEB-075 fails any redirect at all because TCR forbids 30x on a fetched URL, and WEB-077 judges whether the destination is an unrelated brand. This one is the mechanical fact that the destination is a different domain, which is what makes the other two matter.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-081",
      "slug": "web-081",
      "title": "A newly registered domain is scored as higher risk",
      "statement": "A recently registered, disposable or short-lived domain raises the risk score on the brand, independently of what the site contains.",
      "rationale": "Fraudulent registrations need a domain, and the cheapest one is bought the same week. No provider publishes a threshold, so this is scored rather than refused — which is worse to be on the wrong side of than a rejection, because the brand verifies and then quietly underperforms with no finding to point at. A genuinely new business is in exactly the same position and can do nothing about it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website domain registration date",
      "severity": "HIGH",
      "detectability": [
        "EXTERNAL_DATA"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30961",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Where the business owns an older domain, register that one. Where it does not, expect slower vetting and stronger scrutiny of everything else, and make the rest of the registration corroborate the business as heavily as it can — matching contact details, a published address, an active social presence.",
      "notes": "Absorbs WEB-086, which states the same signal together with its remediability: no form edit changes a domain's age. We run no WHOIS lookup, so the user is the one who has to know how old their domain is — and if it is weeks old, to plan for a slower vet rather than resubmitting into the same score.",
      "catalogIds": [
        "WEB-086"
      ],
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "How old is this domain — and if it is only weeks old, have you planned for a slower vet rather than a resubmission?",
        "howToCheck": [
          "Check the registration date in your registrar account or a public WHOIS lookup.",
          "Where the business owns an older domain, register that one instead.",
          "Where it does not, make the rest of the record corroborate the business as heavily as it can: matching contact details, a published address, an active social presence."
        ],
        "failureLooksLike": "Nothing is refused. The brand verifies and quietly underperforms, and resubmitting an unchanged registration produces the same score — no form edit changes a domain's age."
      }
    },
    {
      "id": "WEB-083",
      "slug": "web-083",
      "title": "Hosting shared with malicious neighbours is scored against the domain",
      "statement": "A domain resolving to an IP or ASN shared with known-malicious sites carries that reputation into the brand score.",
      "rationale": "Reputation is assessed at the address as well as the name, so a business on cheap shared hosting inherits whatever its neighbours did. Nothing about the business causes it and nothing on the site reveals it, which makes it one of the hardest findings to act on — the brand looks clean from every angle the operator can see.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "resolved IP and ASN neighbours",
      "severity": "MEDIUM",
      "detectability": [
        "EXTERNAL_DATA"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30961",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Where vetting repeatedly stalls with no finding on the content, move the site to a dedicated IP or a reputable host and re-submit. Done when the domain resolves to an address whose other tenants you can account for.",
      "notes": "We resolve no addresses and hold no reputation feed. The user can check this themselves with a reverse-IP lookup on their domain: if it shares an address with hundreds of unrelated sites, that is the signal, and changing host is the only fix.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Does this domain share its IP address with sites you cannot account for?",
        "howToCheck": [
          "Run a reverse-IP lookup on the domain.",
          "Hundreds of unrelated sites on the same address is the signal — cheap shared hosting inherits whatever its neighbours did.",
          "The only fix is moving to a dedicated IP or a reputable host, then resubmitting."
        ],
        "failureLooksLike": "Vetting stalls repeatedly with no finding on the content. Nothing about the business caused it and nothing on the site reveals it, so the brand looks clean from every angle the operator can see."
      }
    },
    {
      "id": "WEB-084",
      "slug": "web-084",
      "title": "A lookalike domain is treated as a phishing signal",
      "statement": "A domain that imitates a better-known brand through misspelling, homoglyphs or an added word is screened as a phishing indicator.",
      "rationale": "Impersonation domains are the standard vehicle for credential phishing over SMS, so screening the name itself is cheap and catches attacks before any content exists to judge. Legitimate businesses collide with it innocently — a reseller whose domain contains the manufacturer's name, a regional franchise — and the rejection reads as an accusation rather than a score.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website domain string",
      "severity": "HIGH",
      "detectability": [
        "EXTERNAL_DATA"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30960",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Where the domain contains another company's brand, be able to show the relationship — an authorised-reseller page, a franchise agreement named on the site. Where it does not, expect a slower vet and make the brand record and the site agree on the business name exactly.",
      "notes": "The catalog flags this as unverified: no primary source names homoglyph domains as a rule, and the nearest hooks are Twilio's obfuscated-URL language and codes 30960/30961. Recorded as a heuristic, not as a quoted requirement. We run no similarity screen, so the user should judge their own domain against the brands it resembles.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Does this domain contain, or closely resemble, another company's brand name?",
        "howToCheck": [
          "Read the domain as a stranger would and name the brand it resembles — misspellings, homoglyphs and an added word all count.",
          "Where the resemblance is a real relationship, publish it: an authorised-reseller page or a franchise agreement named on the site.",
          "Where it is coincidence, expect a slower vet and make the brand record and the site agree on the business name exactly."
        ],
        "failureLooksLike": "A reseller whose domain carries the manufacturer's name is screened as a phishing indicator, and the rejection reads as an accusation rather than as a score."
      }
    },
    {
      "id": "WEB-085",
      "slug": "web-085",
      "title": "Adverse reputation on the domain blocks the brand",
      "statement": "Third-party reputation signals on the domain — prior compromise, complaint volume, adverse media, blocklist entries — block the registration.",
      "rationale": "Carriers buy reputation data and apply it before anyone reads the site, so a domain that was compromised two owners ago arrives already refused. The business has no visibility into which feed flagged it or why, and the rejection names none of that, which is why brands re-submit unchanged registrations several times before anyone tells them the domain is the problem.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website domain reputation",
      "severity": "BLOCKING",
      "detectability": [
        "EXTERNAL_DATA"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Bandwidth",
          "code": "TFV 1604",
          "remediable": true
        },
        {
          "provider": "Bandwidth",
          "code": "TFV 1609",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Check the domain against the public blocklists and safe-browsing services before registering, and clear whatever they report — a compromised page, an old redirect, a listing from a previous owner. Where the history belongs to a previous owner, expect to have to appeal with evidence of the transfer.",
      "notes": "Absorbs WEB-082, prior compromise being one of the signals the same lookup returns. We query no reputation source. The user has to run this themselves — Google Safe Browsing, VirusTotal and the major blocklists are the ones the vendors draw on — and to do it before submitting, because a blocked domain burns the registration rather than pausing it.",
      "catalogIds": [
        "WEB-082"
      ],
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Is this domain clean on the public blocklists and safe-browsing services today?",
        "howToCheck": [
          "Check it against Google Safe Browsing, VirusTotal and the major blocklists — these are the feeds the vendors draw on.",
          "Clear whatever they report: a compromised page, an old redirect, a listing left by a previous owner.",
          "Where the history belongs to a previous owner, have evidence of the transfer ready for an appeal."
        ],
        "failureLooksLike": "A domain compromised two owners ago arrives already refused. The rejection names no feed and no reason, so unchanged registrations are submitted several times before anyone mentions the domain."
      }
    },
    {
      "id": "WEB-090",
      "slug": "web-090",
      "title": "The message flow must deep-link the opt-in page, not the homepage",
      "statement": "The URL given in the message flow must point at the page carrying the consent surface, not at the site root.",
      "rationale": "A reviewer given a homepage has to hunt for the opt-in, and if they do not find it quickly they reject. Deep-linking converts a search into a single click, and it is one of the cheapest possible improvements to approval odds.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "campaign.message_flow",
      "severity": "HIGH",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Twilio",
        "Bandwidth",
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Replace the homepage link in the message flow with the direct URL of the page holding the consent checkbox.",
      "example": "https://acmecoffee.com/signup rather than https://acmecoffee.com",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-098",
      "slug": "web-098",
      "title": "The QR landing page must be publicly reachable",
      "statement": "The page a QR code opens must be fetchable by anyone — no login, geo-gate, app-install wall or captive portal in front of it.",
      "rationale": "A QR code is scanned in a shop, on a table, at an event — and if the page behind it demands an app or a login, the consumer never opts in and the reviewer never sees the surface either. The captive-portal case is the one that catches careful operators: a code that works perfectly on the store Wi-Fi opens nothing at all for someone on a mobile network, and nobody tests it that way.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "QR destination fetch",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "Bird"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30909",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth/DCA",
          "code": "804",
          "remediable": true
        }
      ],
      "applicability": {
        "consentMethods": [
          "qr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by QR code.",
      "universal": false,
      "remediation": "Host the QR destination on a public https page on the brand domain, with no login, no app interstitial and no dependence on the venue network. Done when scanning the code on a phone with mobile data and no app installed shows the opt-in.",
      "pitfalls": [
        "Test the printed code, not the URL. A code printed from a draft, or one pointing at a short link whose account has lapsed, opens something entirely different from what was designed."
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-101",
      "slug": "web-101",
      "title": "The QR landing page must display the registered brand name",
      "statement": "The page a QR code opens must display the brand name as registered, so the consumer can see whose programme they are joining.",
      "rationale": "A QR code is opaque by design: the consumer has no idea where it goes until the page loads, so the page is the first and only chance to say who is asking for their number. An unbranded hosted form — the platform's template with the merchant name left at its default — gives them nothing to recognise, and gives the reviewer nothing to tie the surface to the brand.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "QR landing page branding",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Aerialink"
      ],
      "codes": [
        {
          "provider": "Aerialink",
          "code": "806",
          "remediable": true
        }
      ],
      "applicability": {
        "consentMethods": [
          "qr"
        ]
      },
      "applicabilityText": "Applies when consent was collected by QR code.",
      "universal": false,
      "remediation": "Put the registered brand name or DBA in the heading of the landing page, not only in the page title or the platform footer. Done when someone who has just scanned the code can see whose programme it is without scrolling.",
      "notes": "Distinct from WEB-102, which asks whether the landing page carries the full disclosure set. A page can carry every required sentence and still never say who is sending.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-107",
      "slug": "web-107",
      "title": "Age-restricted content on the site must sit behind a working age gate",
      "statement": "Where the site or the campaign carries age-restricted content, the site must present a functioning age gate in front of it.",
      "rationale": "The gate is what keeps a minor from reaching alcohol, tobacco, firearms or adult material through a link in a text message, and carriers charge per-message violation fees rather than merely rejecting, so the cost of getting it wrong keeps accruing. Businesses that gate their checkout often leave the marketing pages open, which is the version of this a compliance-minded operator is most likely to trip.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "age-gate interstitial on the site",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL",
        "HUMAN"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "T-Mobile",
        "Twilio",
        "AWS",
        "CTIA"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30956",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "T-Mobile",
          "code": "706",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Put a date-of-birth gate in front of every page carrying restricted content, enforced server-side so a direct link cannot skip it. Done when opening a product URL in a private window shows the gate before the product.",
      "pitfalls": [
        "Gating the checkout and leaving the catalog open fails: the reviewer opens a product page directly and never sees the gate."
      ],
      "notes": "Absorbs MSG-176, which states the requirement from the message-copy side, and BRD-280 from the brand-eligibility side. The gate's form is WEB-108 (a full date of birth), its position WEB-109, its threshold WEB-112, and whether it survives a determined visitor WEB-110 — that last one is why HUMAN is declared alongside CRAWL here: a crawl can see a gate and cannot tell whether it holds. The user has to try to bypass their own gate, by opening a restricted URL directly in a fresh browser, and confirm they are stopped.",
      "catalogIds": [
        "MSG-176",
        "BRD-280"
      ],
      "phase": "approval",
      "automated": true,
      "attestation": {
        "question": "Opening a restricted product URL directly, in a fresh private window, are you stopped by the gate before you see the product?",
        "howToCheck": [
          "Copy a deep link to a restricted page — not the homepage — and open it in a private window.",
          "Confirm the gate appears before any restricted content is rendered.",
          "Repeat for the marketing and catalog pages, not just the checkout."
        ],
        "failureLooksLike": "The checkout is gated and the catalog is open. The reviewer opens a product page directly, never sees the gate, and carriers charge per-message violation fees rather than merely rejecting."
      }
    },
    {
      "id": "WEB-109",
      "slug": "web-109",
      "title": "The age gate must come before the restricted content, not after it",
      "statement": "The age gate must be presented before any age-restricted content is accessible, including on a page reached by a direct link.",
      "rationale": "A gate that appears after the visitor has already seen the product has protected nobody — the harm the rule addresses happened on page load. The usual cause is a gate wired into the home page template only, so every deep link from a message, a search result or a QR code lands past it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "page flow ordering",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "Aerialink"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30956",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Enforce the gate on every restricted URL rather than on the home page, and check the answer server-side before the page renders. Done when pasting a product URL into a fresh browser shows the gate first.",
      "pitfalls": [
        "For a QR opt-in the date of birth must be captured before consent is collected, not on the confirmation step — a gate after the number has been submitted is too late for both requirements."
      ],
      "notes": "Conditional on age-restricted content being present, the same condition as WEB-107, and carried in the criteria for the same reason: tagging on the declared ageGated attribute would exempt exactly the brands that under-declare.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-110",
      "slug": "web-110",
      "title": "The age gate must not be trivially bypassable",
      "statement": "The age gate must not be defeatable by dismissing it, by loading a page directly, or by clearing a cookie.",
      "rationale": "A gate implemented in front-end code is decoration: it stops nobody who does not want to be stopped, and it stops the reviewer not at all, since the first thing they try is the direct URL. Businesses build it this way because that is what the plugin does, and because the version that actually holds requires the server to know the answer.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "age-gate implementation",
      "severity": "HIGH",
      "detectability": [
        "HUMAN"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30956",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Enforce the gate server-side: refuse to render restricted pages until the age has been submitted and recorded for the session. Done when a direct link, a dismissed dialog and a cleared cookie all still land on the gate.",
      "notes": "Nothing we fetch can tell a real gate from a dismissible overlay, so this one is on the user to test: open a restricted product URL directly in a private window, press Escape on the dialog, and clear the cookie between attempts. If any of the three gets through, the gate is decoration and WEB-107 will be judged on it.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Does the gate still hold after a direct link, a dismissed dialog and a cleared cookie?",
        "howToCheck": [
          "Open a restricted URL directly in a private window.",
          "Press Escape on the dialog, and try to interact with the page behind it.",
          "Clear the cookie and reload. If any of the three gets through, the gate is decoration."
        ],
        "failureLooksLike": "A front-end plugin renders the page and covers it with an overlay. It stops nobody who does not want to be stopped, and it stops the reviewer not at all — the first thing they try is the direct URL."
      }
    },
    {
      "id": "WEB-111",
      "slug": "web-111",
      "title": "Alcohol delivery must gate the ordering flow, not just a splash page",
      "statement": "An alcohol delivery brand must present the age gate on the ordering flow itself, not only on a marketing splash page.",
      "rationale": "Delivery is the case where the gate has to hold, because the transaction ends with alcohol arriving at a door rather than with someone standing at a counter. A splash gate on the marketing site is satisfying to build and does nothing for the ordering app or the checkout subdomain, which is usually a different system entirely.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "checkout and ordering flow",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30956",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicability": {
        "verticals": [
          "alcohol_delivery"
        ]
      },
      "applicabilityText": "Applies when the vertical is alcohol_delivery.",
      "universal": false,
      "remediation": "Add the date-of-birth gate to the ordering flow — the cart, the checkout, and the app — as well as to the marketing site, and verify age again at handover. Done when the order path itself refuses an under-21 date of birth.",
      "notes": "Twilio scopes 30956 to \"all linked websites and opt-in flows\", which is what makes a splash-page-only gate insufficient here. Tagged to the alcohol_delivery vertical per the catalog condition; the general alcohol threshold rule is WEB-112 and applies whether or not delivery is involved.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-112",
      "slug": "web-112",
      "title": "An alcohol age gate must enforce 21, not 18",
      "statement": "Where the restricted content is alcohol, the age gate must enforce a 21+ threshold rather than 18+.",
      "rationale": "Twenty-one is the US drinking age, so an 18+ gate admits a whole cohort the rule exists to exclude and does it while looking compliant. The mistake travels with software: templates and plugins ship with 18 as the default because that is the threshold most of the world uses, and nobody changes it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "age-gate threshold",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "CTIA"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30955",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Set the gate's minimum age to 21 wherever alcohol content is served, and check the plugin default rather than assuming it. Done when entering a date of birth for a twenty-year-old is refused.",
      "notes": "Conditional on alcohol content being present, carried in the criteria rather than as a tag — there is no alcohol attribute on the registration, and the declared ageGated flag says nothing about which substance is behind the gate.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-115",
      "slug": "web-115",
      "title": "A landing page reached from a message must publish a postal address",
      "statement": "Any landing site a message links to must publish contact information including a postal mailing address.",
      "rationale": "CTIA requires the destination of a bulk message to identify who is behind it, and a postal address is the element that makes the owner findable by someone who has no account and no relationship with them. It is also the element businesses drop first when they build a campaign landing page separately from the main site, because the page is designed to convert rather than to inform.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "landing page contact block",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Add the business postal address to the footer of every page a message can reach, alongside a phone number or email. Done when the landing page shows a street address, a city, a state and a postal code.",
      "notes": "Distinct from WEB-114, which requires the landing page to name the owner: this rule is about the address specifically, which is the part most often missing from an otherwise identified page.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-116",
      "slug": "web-116",
      "title": "A landing page that collects personal information must publish a privacy policy",
      "statement": "Any landing site collecting personal information must carry a conspicuously accessible privacy policy.",
      "rationale": "The page where a consumer types their phone number is the page where they are entitled to know what happens to it, and a policy two clicks away on a different domain does not reach them at the moment it matters. Campaign landing pages are built to convert and routinely ship without the footer the main site has, so this fails on exactly the page the messages point at.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "landing page policy link",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AT&T",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "7100",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Link the privacy policy from the landing page itself, next to the form rather than only in a footer nobody scrolls to. Done when the policy is reachable in one click from the page that collects the number.",
      "notes": "WEB-045 asks the same question of the brand home page. Both are kept because a brand routinely satisfies one and not the other: the main site has a footer and the campaign landing page does not.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-119",
      "slug": "web-119",
      "title": "The whole site must be screened for prohibited content, not just the landing page",
      "statement": "Prohibited-content screening must cover the entire website, not only the page the campaign points at.",
      "rationale": "Vetting crawls the brand's whole site, so a compliant campaign landing page does not protect a business whose shop sells vape hardware two clicks away. This is a common and expensive surprise: the campaign content is clean and the registration still fails on the brand.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website (all pages)",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio",
        "AWS",
        "T-Mobile"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Audit the whole site against the prohibited-content list before registering. Where the business genuinely sells a restricted category alongside a compliant one, expect the brand to be judged on the restricted category.",
      "notes": "Requires multi-page crawling. Today the product fetches a single page, so this rule is a known coverage gap rather than an implemented check.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-122",
      "slug": "web-122",
      "title": "No adult content on the site or any page it links to",
      "statement": "The brand website must not host or promote adult, pornographic, escort or nudity content.",
      "rationale": "Adult content is the category carriers refuse outright rather than gate, because the recipient of an unwanted message has no way to un-see it and the complaint goes straight to the carrier. The site is screened as well as the messages because the brand is what carries the traffic: a compliant booking campaign registered by an adult venue is refused on the venue, not on the campaign.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Twilio",
        "AT&T",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30953",
          "remediable": false,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This category cannot be registered for 10DLC in the US. There is no age gate or paywall that makes it registrable, and no re-framing of the campaign that separates it from the brand.",
      "notes": "The message-side twin is MSG-SHAFT-SEX. Both are kept because they fail independently: this one fires on a clean campaign whose brand website carries the content.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-123",
      "slug": "web-123",
      "title": "No hate-group brand",
      "statement": "The brand website must not host or promote the identity, materials or fundraising of a hate group.",
      "rationale": "CTIA names hate groups as a category carriers will not carry, and the assessment is of the organisation rather than of any particular message — so nothing in the campaign can rescue it. Public listings are consulted alongside the site, which means a brand can be refused on an identification it has never seen and cannot argue with inside the registration.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Bandwidth",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This category cannot be registered. Where the brand is a research, journalism or advocacy organisation whose site quotes such material to counter it, say so in the campaign description and expect the registration to be reviewed by a person.",
      "notes": "Judged partly from external listings the product does not hold, so a PASS here is a PASS on the retrieved content only. Ranked alongside WEB-122 as a refusal rather than a finding.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-124",
      "slug": "web-124",
      "title": "No advertising that ridicules a protected group or trivialises an atrocity",
      "statement": "The brand website must not host or promote advertising that misrepresents or ridicules people by age, colour, national origin, race, religion, sex, sexual orientation or disability, or that trivialises a historic atrocity.",
      "rationale": "AT&T bars this in its own schedule, separately from hate-group content, because the harm is done by ordinary marketing rather than by an extremist organisation — an edgy campaign, a joke about a disability, a genocide used as a punchline in a sale. Businesses get here through a copywriter reaching for shock rather than through anything anyone would call a policy, which is why the fix is usually one page.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "HIGH",
      "detectability": [
        "AI_FORM"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Remove or rewrite the offending copy and imagery, then re-crawl before resubmitting. Done when nothing on the site sells a product by reference to who somebody is.",
      "example": "Replace a campaign page joking about an ethnicity with the same offer stated plainly: \"Acme Coffee — 20% off all espresso blends this weekend.\"",
      "notes": "Severity divergence inside the single source: AT&T Schedule 1 grades the discrimination clause HIGH and the atrocity-trivialisation clause MEDIUM. Strictest kept.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-125",
      "slug": "web-125",
      "title": "No graphic violence on the linked site",
      "statement": "The brand website must not host or promote excessive or graphic violence.",
      "rationale": "The rule exists for the person who follows a link from a text message and is shown something they did not ask to see, which is why it is assessed on the destination rather than on the message. It reaches ordinary businesses through imagery chosen for impact — a self-defence course, a game studio, a haunted attraction — where nothing about the business is objectionable and one page is.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "HIGH",
      "detectability": [
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AT&T",
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Move graphic imagery behind the age gate rather than onto the public landing page, and choose a different image for the page the messages link to. Done when the destination of every campaign link is safe to open in public.",
      "example": "Campaign link points at https://acmecoffee.com/events — a text-and-photography event page — rather than at the artwork gallery.",
      "notes": "VISION because the finding is in the pictures: a site whose copy is unremarkable can fail on a single image, and a text-only crawl sees none of it.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-126",
      "slug": "web-126",
      "title": "No firearms, ammunition or explosives sales on the site",
      "statement": "The brand website must not host or promote the sale of firearms, ammunition, explosives or fireworks.",
      "rationale": "Two carriers treat firearms as age-gateable and two providers ban them outright, so the same site is registrable at one destination and refused at another — and a brand that builds around the permissive reading discovers the strict one at submission. The harm the strict reading protects against is a channel that reaches a phone without any of the checks a gun sale otherwise carries.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Twilio",
        "Bandwidth",
        "Telnyx",
        "T-Mobile",
        "Verizon"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30957",
          "remediable": false,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This category cannot be registered under the strict reading the registry applies. Where the business sells instruction, membership or non-firearm goods, separate that site from the sales catalog and register the one with no purchase path.",
      "notes": "Genuine divergence, not a strictness difference: T-Mobile §5.7 and Verizon treat firearms as age-gateable, Telnyx permits education-only content but bans sales, and Twilio and Bandwidth ban the category outright. The strict-superset model takes the outright ban as the default; a brand submitting only to a permissive destination should read this as a warning rather than a refusal.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-127",
      "slug": "web-127",
      "title": "No tobacco or vape product content on the site",
      "statement": "The brand website must not host or promote tobacco, vape, e-cigarette or nicotine product content.",
      "rationale": "Nicotine marketing reaching a phone is the specific harm the age-gating regime exists to prevent, and carriers found that gates on retail sites do not survive contact with a link in a text message. Operators in this trade are usually compliant with every rule their own regulator imposes, which is why the refusal lands as a surprise: the sector's own age verification is not the standard being applied.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Twilio",
        "Telnyx",
        "Bandwidth",
        "T-Mobile"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30958",
          "remediable": false,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This category cannot be registered under the strict reading. Where a general retailer carries a small nicotine range, expect the brand to be judged on that range rather than on the rest of the catalog.",
      "notes": "Age-gateable under T-Mobile §5.7 and banned outright by Twilio, so this is a real divergence between destinations. Strictest kept, per the superset model. The message-side twin is MSG-SHAFT-TOBACCO.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-128",
      "slug": "web-128",
      "title": "No cannabis, CBD, hemp or kratom content anywhere on the site",
      "statement": "The brand website must not host or promote cannabis, CBD, hemp, kratom, dispensary or drug-paraphernalia content.",
      "rationale": "The industry applies federal law where federal and state law diverge, so a fully licensed dispensary in a legal state is refused exactly like an unlicensed one — and this is the rule that surprises operators more than any other, because everything about their business is lawful where they stand. The screen covers the whole site rather than the landing page, so a wellness retailer with one CBD line fails on that line.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Twilio",
        "Bandwidth",
        "Telnyx",
        "AWS",
        "TCR"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30940",
          "remediable": false,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth/DCA",
          "code": "701",
          "remediable": false
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This category cannot be registered for 10DLC in the US regardless of state licensing. Removing the product pages does not help while the business is the dispensary; the refusal is on the brand.",
      "notes": "AWS marks the category non-remediable, and Telnyx extends the prohibition to shipping services for these products and cites a T-Mobile fine. State legality is irrelevant to the outcome and saying so early saves the appeal.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-129",
      "slug": "web-129",
      "title": "No gambling content on the site",
      "statement": "The brand website must not host or promote casino, sportsbook, lottery or online gambling content.",
      "rationale": "Gambling is banned by some providers and routed to a special use case by others, so the safe default is refusal — and the split is invisible from outside, which is how a licensed operator ends up registering into a destination that will not take it. The consumer harm behind the strict reading is the same one age gates exist for, arriving on a device with no gate in front of it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "AWS",
        "Bandwidth",
        "Telnyx"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30944",
          "remediable": false,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Confirm before registering whether your destination offers a gambling or sweepstakes use case; several refuse the category outright. Where one exists, register under it rather than under marketing.",
      "notes": "Telnyx allows a licensed-and-age-gated carve-out and AWS marks the category non-remediable. Strictest kept. The message-side twin is MSG-GAMBLING.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-130",
      "slug": "web-130",
      "title": "No high-risk financial services on the site",
      "statement": "The brand website must not host or promote payday and short-term high-interest lending, third-party loan solicitation, debt collection, credit repair, debt forgiveness, crypto or retail investment content.",
      "rationale": "This is the category most associated with consumer-harm complaints on SMS, and AWS records it as not eligible for resubmission at all — a rejection here ends the registration rather than opening a fix loop. The line that decides an outcome is first-party versus third-party: a bank servicing its own loans is a different business from a site that solicits borrowers for other lenders, and the site is where the difference shows.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "AWS",
        "Bandwidth",
        "Telnyx",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30942",
          "remediable": false,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth/DCA",
          "code": "709",
          "remediable": false
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This business model cannot be registered. A regulated lender servicing its own customers is a different category — if that is you, remove the acquisition-style offers from the site and declare the direct-lending attribute instead of concealing the lending.",
      "notes": "AWS states the category is \"not eligible for resubmission under A2P 10DLC\" — permanently non-remediable, unlike most BLOCKING findings. The first-party carve-out is what keeps a licensed lender registrable and must not be dropped: it is the same carve-out MSG-HIGH-RISK-FINANCIAL carries on the message side.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-131",
      "slug": "web-131",
      "title": "No lead-generation, affiliate-marketing or SEO-services content on the site",
      "statement": "The brand website must not host or promote lead generation, affiliate marketing or SEO and marketing-agency services.",
      "rationale": "Selling consumer contact details onward is the activity the whole consent framework exists to stop, so a site that advertises it describes a business model carriers refuse rather than a page they want edited. The trap for honest businesses is the word rather than the trade: an ordinary shop with a partner or referral programme page reads, to a screen looking for exactly this, like a lead broker.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "Bandwidth",
        "Telnyx",
        "Twilio"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30951",
          "remediable": false,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth/DCA",
          "code": "708",
          "remediable": false
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Remove lead-generation, affiliate and SEO-services copy from the brand website and re-crawl before resubmitting; Telnyx states the remediation in exactly those terms. Done when nothing on the site offers to pass a visitor's details to anybody else. Where that copy describes what the business actually does, the registration cannot be saved by editing.",
      "example": "Replace \"Join our affiliate network and monetise your traffic\" with \"Refer a friend and you both get $10 credit — we never share your friend's details.\"",
      "pitfalls": [
        "AWS and Twilio both mark their codes non-remediable, so a rejection under this heading ends that campaign even where the site edit would have been enough. Fix the site before submitting, not after."
      ],
      "notes": "failureClass is TERMINAL_WEBSITE because the common case is removable copy and Telnyx publishes exactly that remediation, while the provider codes are marked non-remediable. The two answer different questions — ours is what to do before submitting, theirs is what happens after a rejection.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-133",
      "slug": "web-133",
      "title": "Sweepstakes content on the site must be registered as sweepstakes",
      "statement": "The brand website must not host or promote sweepstakes, prize-draw or contest-entry content that the registration does not declare.",
      "rationale": "Prize promotions carry their own use case and their own disclosure obligations, and a brand running one under a marketing registration has skipped both. AWS rejects on the brand rather than the campaign, so a business whose messages never mention the giveaway is still refused for the page that hosts it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Register under the sweepstakes use case where the promotion is live, and publish the official rules alongside the entry page. Where the promotion is over, take the page down or mark it closed before resubmitting.",
      "example": "Use case: SWEEPSTAKE, with official rules published at https://acmecoffee.com/rules and linked from the entry page.",
      "notes": "Related to but distinct from MSG-206, which reads the campaign copy. This one fires on site evidence alone, which is the case a campaign-only screen cannot see.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-134",
      "slug": "web-134",
      "title": "No multilevel-marketing content on the site",
      "statement": "The brand website must not host or promote multilevel-marketing or distributor-recruitment content.",
      "rationale": "MLM recruitment over SMS produces complaint volumes carriers treat as a category problem rather than a sender problem, so the screen is applied to the business rather than to the messages. Individual distributors are caught by it while believing they are registering an ordinary small retail business, because from the inside that is what it is.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Telnyx"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This business model cannot be registered. An independent distributor cannot separate themselves from it by registering the personal brand instead — the site is what is screened.",
      "notes": "Single-source in the catalog (Telnyx AUP) but authored universally: the message-side twin MSG-LEAD-GEN carries the same prohibition on recruitment content across several providers, so narrowing this to one provider would drop a real requirement.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-135",
      "slug": "web-135",
      "title": "No site impersonating another service to collect credentials",
      "statement": "The brand website must not host or promote impersonation of a legitimate service in order to capture credentials, identity numbers or other sensitive data.",
      "rationale": "This is the phishing pattern the whole landing-page review exists to catch: a page that looks like a bank, a carrier or a delivery service, reached from a text message, collecting whatever the real one would ask for. It is judged from design and form fields together, because the copy alone is by construction indistinguishable from the genuine article.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Twilio",
        "CTIA"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30960",
          "remediable": false,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This cannot be registered. Where the brand is an authorised partner using another company's marks legitimately, state the relationship in visible page content and expect the registration to be reviewed by a person.",
      "notes": "CTIA A65-03 extends the same prohibition to brand impersonation on any message landing page or download, and A65-04 to promotion of illegal activity. Both are discharged here.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-136",
      "slug": "web-136",
      "title": "No malware or insecure downloads served from the site",
      "statement": "The brand website must not host or promote malware, or application downloads served from non-secure locations.",
      "rationale": "A link in a text message that ends in a drive-by download is the highest-severity outcome in the whole framework, so the destination is screened for it directly. The common cause is not malice: an unmaintained plugin on a small business site gets compromised, the owner never sees the injected script, and the first they hear of it is a registration refusal that says nothing about their site being hacked.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA",
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Scan and clean the site, update the platform and plugins, and serve every download over https from your own domain. Done when a safe-browsing check on the domain comes back clear and no download link points at a plain-HTTP host.",
      "example": "App links point at https://apps.apple.com/... and https://play.google.com/... rather than at a self-hosted APK.",
      "pitfalls": [
        "Cleaning the site does not clear the blocklist entry. Request a review with the safe-browsing service as well, or the domain reputation rules keep failing after the malware is gone."
      ],
      "notes": "The landing-page malware screen is routed to WEBSITE by the catalog's layer-ownership rule, so it carries no MESSAGE_CONTENT alias: the message-side row was folded into this obligation rather than kept as a separate one.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-137",
      "slug": "web-137",
      "title": "No deceptive marketing claims on the site",
      "statement": "The brand website must not host or promote unsubstantiated health or product claims, fabricated urgency, unverifiable guarantees, unauthenticatable testimonials or false endorsements.",
      "rationale": "CTIA folds the FTC truth-in-advertising rules into the messaging framework, so the site is read against them and a claim that would draw an FTC letter draws a carrier rejection first. Almost every business trips this through ordinary conversion copywriting — a countdown that resets, a \"doctor recommended\" with no doctor, a testimonial with initials instead of a name — none of which was written to deceive anyone.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "Bandwidth",
        "AT&T",
        "CTIA",
        "FTC"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30962",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Qualify or remove each claim: name the source for a health or performance claim, make the deadline on any urgency real, and attribute testimonials to identifiable people. Done when every claim on the page could be defended with something you hold.",
      "example": "\"In a 2025 survey of 400 Acme Coffee subscribers, 82% said they brewed more often at home\" — rather than \"everyone brews better with Acme\".",
      "notes": "Distinct from WEB-024, which asks whether the site is real at all. A completely genuine business fails this rule on its marketing copy.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-139",
      "slug": "web-139",
      "title": "No counterfeit goods or falsified documents sold on the site",
      "statement": "The brand website must not host or promote counterfeit, replica or imitation designer goods, fake identification or falsified documentation.",
      "rationale": "AT&T bars the category outright because the messages promoting it are, by construction, promoting a crime — and fake identification carries a harm beyond the trade itself. The replica trade advertises openly enough that this is usually read straight off a product page rather than inferred.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This cannot be registered. A resale business that deals in authenticated genuine goods should say so on the product pages and in the campaign description, since the distinction is exactly what the screen is looking for.",
      "notes": "Severity divergence in the source: AT&T Schedule 1 grades counterfeit goods HIGH and fake identification BLOCKING. Strictest kept, and both limbs are one screen because they sit on the same catalog page in practice.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-140",
      "slug": "web-140",
      "title": "No law-evasion or questionable-legality products in the catalog",
      "statement": "The brand website must not host or promote law-evasion and protection-bypass products, or products of questionable legality.",
      "rationale": "AT&T names a specific old list — radar detectors, descramblers, copyright-bypass tools, miracle cures, witchcraft and good-luck merchandise — and it survives because those categories still attract the complaint patterns that put them there. A general retailer meets it through a single novelty line nobody thought about, which is why the fix is almost always the catalog rather than the business.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AT&T"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Remove the named product lines from the catalog, or drop the effectiveness claim where the item is a novelty. Done when nothing in the catalog is sold as a way around a law or as a remedy it cannot deliver.",
      "example": "List a \"lucky bean charm — novelty gift, no claims made\" rather than \"brings prosperity within 7 days\".",
      "notes": "Severity divergence inside the source: the questionable-legality clause is graded HIGH and the descrambler and radar-detector clauses MEDIUM. Graded MEDIUM overall because the enforcement in practice attaches to the product line rather than the brand, and the fix is a catalog edit.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-141",
      "slug": "web-141",
      "title": "No infringing content on the site",
      "statement": "The brand website must not host or promote content that infringes another party's intellectual property.",
      "rationale": "CTIA added this in SCMH v1.9, and it reaches messaging because a link in a text message is a distribution channel like any other — the rights holder's complaint arrives at the carrier. Small businesses trip it with stock imagery they did not license and fonts or music lifted from elsewhere, none of which they would describe as infringement.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "CTIA"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Replace unlicensed media with material you hold a licence for, and remove third-party marks you are not authorised to use. Done when every image, font and logo on the site traces to a licence or to your own work.",
      "example": "Swap an unlicensed press photo on the home page for your own photography of the Mission St roastery.",
      "effectiveFrom": "2025-01-01",
      "notes": "New in CTIA SCMH v1.9. `effectiveFrom` is set to the start of 2025 because the catalog records the version rather than a publication date, and dating it earlier would apply a requirement before it existed.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-142",
      "slug": "web-142",
      "title": "A storefront catalog must be screened for SHAFT merchandise before submitting through a strict platform",
      "statement": "The brand website must not host or promote SHAFT merchandise in the storefront catalog, where the destination platform refuses such merchants outright.",
      "rationale": "Some ISV platforms refuse SHAFT merchants entirely rather than age-gating them, which is stricter than the carrier baseline and invisible until a submission is refused. A homeware store with a single hip-flask-and-whiskey gift set is a SHAFT merchant to that screen, and the seller has no reason to think of themselves as one.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "TCR"
      ],
      "applicability": {
        "verticals": [
          "RETAIL"
        ]
      },
      "applicabilityText": "Applies when the vertical is RETAIL.",
      "universal": false,
      "remediation": "Search your own catalog for alcohol, tobacco, firearms and adult items — including bundles — before submitting, and confirm with your platform whether it refuses such merchants outright or age-gates them. Done when you can state which of the two applies to your account.",
      "example": "Catalog audit: 0 results for alcohol, tobacco, firearm and adult categories across all products and gift sets.",
      "notes": "The catalog conditions this on `provider=Postscript`, which is not in the Provider enum and would in any case be the wrong shape: a provider tag narrows when a rule fires, and this platform-strictness is a warning every retail merchant benefits from. Tagged to the retail vertical instead, with the platform condition carried in the criteria.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-143",
      "slug": "web-143",
      "title": "Affiliate marketing plus lending on the site is a harder rejection than either alone",
      "statement": "The brand website must not host or promote affiliate or lead-generation activity in the campaign combined with high-risk lending on the website.",
      "rationale": "Bandwidth escalates the two signals together rather than scoring them independently, because the combination is the shape of a payday-loan lead broker — the highest-complaint pattern on the channel. It matters to an honest business because remediating one limb leaves the escalation in place: taking the affiliate page down while the lending stays up does not return the brand to where it started.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "crawled website content",
      "severity": "BLOCKING",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "HARD_STOP",
      "authorities": [
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Bandwidth",
          "code": "3101",
          "remediable": false
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "This combination cannot be registered. Removing one limb does not restore the other to a clean score, so a business that genuinely does both needs to separate them into different entities before either can be registered.",
      "notes": "The applicability model has no \"both limbs present\" predicate, so the condition lives in the criteria: the judge passes immediately unless it finds affiliate or lead-sharing activity in the campaign AND lending content on the site. Recorded here rather than left implicit, so the rule does not read as universal.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-145",
      "slug": "web-145",
      "title": "A business social profile can stand in where no website exists",
      "statement": "Where the brand genuinely has no website, an established, active, public business profile is accepted as the online presence.",
      "rationale": "Plenty of real small businesses trade entirely through a Google Business Profile, a Facebook page or an Etsy shop, and refusing them outright would fail the registrations the framework least wants to lose. What providers actually reject is a private or dormant profile — the evidential work is being done by the profile being open and alive, not by it being a website.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "submitted social profile URL",
      "severity": "MEDIUM",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "Twilio",
        "Bandwidth",
        "Telnyx",
        "AWS",
        "Sinch"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30490",
          "remediable": true,
          "generation": "gen2"
        },
        {
          "provider": "Bandwidth",
          "code": "TFV 1202",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Submit a public profile on a platform the providers name — Facebook, Instagram, LinkedIn, Yelp, Google Business Profile or Etsy — that shows recent activity and is visible without logging in. Done when the profile opens in a private browser window and its most recent post is inside the last few months.",
      "notes": "Absorbs BRD-137. Bandwidth TFV 1202 rejects a private or inactive account, which is the failure mode this rule is really about — the substitution itself is permitted.",
      "catalogIds": [
        "BRD-137"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-146",
      "slug": "web-146",
      "title": "A substituted profile must be a business page, not a personal one",
      "statement": "A social profile standing in for a website must be a business page carrying the business name, a description of what it does, and contact information.",
      "rationale": "A personal timeline proves a person exists, which is not the question — the registration is asserting that a business exists and does what the campaign claims. The distinction matters most for the sole proprietors this route was built for, who often run the business from the account they already had, and who can fix it by converting the page rather than building a site.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "substituted social profile type and content",
      "severity": "HIGH",
      "detectability": [
        "CRAWL",
        "VISION"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "AWS",
        "Twilio",
        "Zoom"
      ],
      "codes": [
        {
          "provider": "Twilio",
          "code": "30490",
          "remediable": true,
          "generation": "gen2"
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Convert the profile to a business or page account and fill in the name, the category, a description of the products or services, and a contact method. Done when the profile shows the registered business name and a way to reach it without sending a direct message.",
      "notes": "Absorbs BRD-138. Readable either from the crawled profile text or from a screenshot, which is why it is dual CRAWL + VISION rather than vision-only.",
      "catalogIds": [
        "BRD-138"
      ],
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-147",
      "slug": "web-147",
      "title": "A social profile must not stand in for a website the brand has",
      "statement": "A social-media profile is accepted as the online presence only where the brand genuinely has no website of its own.",
      "rationale": "The substitute exists for businesses that never built a site, and it costs them extra scrutiny. Using it while a real site exists throws away the strongest evidence the registration has, and a reviewer who finds the website independently reads the substitution as an attempt to keep them off it.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website vs brand.social_profile_urls",
      "severity": "HIGH",
      "detectability": [
        "DETERMINISTIC"
      ],
      "failureClass": "RETRY_FIELD",
      "authorities": [
        "TCR",
        "Bandwidth"
      ],
      "codes": [
        {
          "provider": "Bandwidth",
          "code": "1100",
          "remediable": true
        }
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Put the business website in brand.website and leave the social profiles as supporting links. Done when brand.website holds the domain the business trades on rather than a profile page.",
      "example": "website: https://acmecoffee.com — with facebook.com/acmecoffee listed as a social profile, not as the website.",
      "notes": "Single secondary source in the catalog (alive5) with no carrier code behind it, so it is graded HIGH rather than BLOCKING and worded as a misuse of the substitute rather than a prohibition.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-148",
      "slug": "web-148",
      "title": "The profile substitute is for small businesses without an established site",
      "statement": "The social-profile route is available to small businesses and sole proprietors that have no established website, not to larger businesses choosing not to submit one.",
      "rationale": "Two providers restrict the substitution by business size while the others do not, so the same profile is accepted at one destination and rejected at another. A business large enough to be expected to have a site, submitting a profile instead, reads as evasive rather than small — and that judgement is made by a person, from facts about the business we do not hold.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "entity size vs the substitute path",
      "severity": "MEDIUM",
      "detectability": [
        "HUMAN"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "Sinch",
        "SignalWire"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Where the business has any web presence of its own, register it and keep the profile as a supporting link. Where it genuinely has none, expect the substitute to be questioned and be ready to say why no site exists.",
      "notes": "Nothing on the form carries employee count, revenue or trading history, so we cannot decide whether a brand is small enough for this route. The user has to make the call themselves: if the business would look odd to a stranger without a website, build one before registering. The catalog records this as a genuine divergence — Sinch and SignalWire restrict the substitution by size, Twilio and Bandwidth do not.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Would this business look odd to a stranger for having no website of its own?",
        "howToCheck": [
          "Judge it as a reviewer would, from size and trading history: the social-profile substitute is for small businesses and sole proprietors with no established site.",
          "Where the business has any web presence of its own, register that and keep the profile as a supporting link.",
          "Where it genuinely has none, be ready to say why."
        ],
        "failureLooksLike": "A substantial business submits a Facebook page instead of a site. Sinch and SignalWire restrict the substitution by size and Twilio and Bandwidth do not, so the same profile is accepted at one destination and read as evasive at another."
      }
    },
    {
      "id": "WEB-152",
      "slug": "web-152",
      "title": "A sole proprietor site must not present as a registered company",
      "statement": "Where the brand is registered as a sole proprietor, the website must not hold itself out as an LLC or incorporated entity.",
      "rationale": "A site displaying \"Acme Coffee LLC\" behind a sole proprietor registration tells the reviewer the tier is wrong — the business evidently is a registered entity and should have registered as one. The mismatch is caught on the website even when the brand form looks internally consistent.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand website + brand.entity_type",
      "severity": "HIGH",
      "detectability": [
        "CRAWL"
      ],
      "failureClass": "TERMINAL_WEBSITE",
      "authorities": [
        "TCR",
        "Twilio"
      ],
      "applicability": {
        "entityTypes": [
          "SOLE_PROPRIETOR"
        ]
      },
      "applicabilityText": "Applies when the brand is a sole proprietor.",
      "universal": false,
      "remediation": "Either register the brand as the company the website advertises, using its EIN, or remove the corporate designation from the site if it is not accurate.",
      "phase": "approval",
      "automated": true
    },
    {
      "id": "WEB-153",
      "slug": "web-153",
      "title": "A charity campaign must supply both its own site and an accreditation listing",
      "statement": "A Charity campaign must supply the charity's own website URL and a listing URL at an accreditation organisation, and both must resolve.",
      "rationale": "Donation messaging is the most impersonated category there is, so the carriers demand a second, independent source that the charity exists — a listing nobody can create for themselves. A real charity that has simply never registered with an accreditation body is stopped here, and finding that out at submission rather than after a rejection is worth weeks.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "charity website URL + accreditation listing URL",
      "severity": "BLOCKING",
      "detectability": [
        "EXTERNAL_DATA"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "T-Mobile",
        "Bandwidth",
        "Infobip"
      ],
      "codes": [
        {
          "provider": "T-Mobile",
          "code": "9002",
          "remediable": true
        },
        {
          "provider": "Bandwidth",
          "code": "TFV 1110",
          "remediable": true
        }
      ],
      "applicability": {
        "useCases": [
          "CHARITY"
        ]
      },
      "applicabilityText": "Applies when the use case is CHARITY.",
      "universal": false,
      "remediation": "Supply the charity's own website alongside a listing at an accreditation organisation — a GuideStar/Candid profile, a Charity Navigator entry, or the state charity register — and open both links yourself before submitting.",
      "notes": "We cannot verify an accreditation listing, and we do not hold the listing URL as a field. The user has to obtain it, confirm it resolves publicly, and supply it with the registration alongside the organisation name and EIN.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Do you have both URLs — the charity's own site and its accreditation listing — and do both open in a private window?",
        "howToCheck": [
          "Obtain the listing URL: a GuideStar/Candid profile, a Charity Navigator entry, or the state charity register.",
          "Open both links yourself, logged out, before submitting.",
          "Supply them with the organisation name and EIN."
        ],
        "failureLooksLike": "A real charity that never registered with an accreditation body is stopped here. Donation messaging is the most impersonated category there is, so a second, independent source that the charity exists is not negotiable."
      }
    },
    {
      "id": "WEB-154",
      "slug": "web-154",
      "title": "A political campaign must supply a resolving organisation website",
      "statement": "A Political campaign must supply the candidate's or organisation's website URL alongside the FEC Committee ID, and that URL must resolve.",
      "rationale": "The Committee ID proves a filing exists; the website is what ties the filing to the messages a voter is about to receive. Campaign sites are stood up and taken down on a schedule nobody else keeps, so a URL that worked when the registration was drafted is a common and entirely innocent way to fail a political vet.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "political organisation website URL",
      "severity": "BLOCKING",
      "detectability": [
        "EXTERNAL_DATA"
      ],
      "failureClass": "TERMINAL_EVIDENCE",
      "authorities": [
        "T-Mobile",
        "Bandwidth",
        "Infobip"
      ],
      "codes": [
        {
          "provider": "T-Mobile",
          "code": "9001",
          "remediable": true
        }
      ],
      "applicability": {
        "useCases": [
          "POLITICAL"
        ]
      },
      "applicabilityText": "Applies when the use case is POLITICAL.",
      "universal": false,
      "remediation": "Supply the campaign or organisation website beside the FEC Committee ID, and confirm it loads publicly on the day you submit and stays up through the review window.",
      "notes": "We hold neither the Committee ID nor a separate political-website field, and we cannot check a filing against the FEC. The user has to pair the two themselves and keep the site live until the campaign is approved.",
      "phase": "approval",
      "automated": false,
      "attestation": {
        "question": "Does the campaign or organisation website load publicly today, and will it stay up through the review window?",
        "howToCheck": [
          "Open it in a private window and confirm it loads for someone who is not logged in.",
          "Pair it with the FEC Committee ID in the submission.",
          "Keep it live until the campaign is approved — campaign sites are stood up and taken down on a schedule nobody else keeps."
        ],
        "failureLooksLike": "A URL that worked when the registration was drafted is down when the vet runs. The Committee ID proves a filing exists; the site is what ties the filing to the messages a voter is about to receive."
      }
    },
    {
      "id": "WEB-157",
      "slug": "web-157",
      "title": "A changed domain must be updated on the brand record",
      "statement": "When the business moves to a new domain, the registered brand website must be updated to match.",
      "rationale": "The brand record is re-checked long after approval, so a stale website field turns into a dead link on somebody else's schedule — and the consequence is not a request to update it but delivery problems and a re-vetting flag. Nobody thinks of the 10DLC record when a domain changes, because it is not part of any migration checklist.",
      "layer": "WEBSITE",
      "layerSlug": "website",
      "object": "brand.website currency",
      "severity": "MEDIUM",
      "detectability": [
        "UNDETECTABLE_PRE_SUBMISSION"
      ],
      "failureClass": "TERMINAL_EXTERNAL",
      "authorities": [
        "TCR",
        "EZ Texting"
      ],
      "applicabilityText": "Applies to every 10DLC registration.",
      "universal": true,
      "remediation": "Update brand.website on the brand record as part of any domain migration, and keep the old domain redirecting until the change has been through vetting. Done when the registered URL is the one customers are being sent to.",
      "notes": "Post-approval hygiene, invisible at submission. The user has to put the brand record on their own domain-migration checklist alongside DNS, email and analytics — nothing prompts them, and the failure surfaces as a delivery problem rather than as a registration one.",
      "phase": "post",
      "automated": false,
      "attestation": {
        "question": "Is the 10DLC brand record on your domain-migration checklist, alongside DNS, email and analytics?",
        "howToCheck": [
          "Add brand.website to the checklist now — nothing will prompt you at migration time.",
          "Update the brand record as part of the move, and keep the old domain redirecting until the change has been through vetting."
        ],
        "failureLooksLike": "The brand record is re-checked months later against a dead link. The consequence is a re-vetting flag and delivery problems, not a request to update the field."
      }
    }
  ]
}
