{
  "id": "OPS-208",
  "slug": "ops-208",
  "title": "The consent record should carry the browser user agent",
  "statement": "Every consent record must carry the device or browser user agent behind the submission.",
  "rationale": "When a consumer says they never filled in the form, the IP and timestamp establish that something was submitted and nothing more. The user agent is the one field on the record that speaks to how it was submitted — a real browser on a phone reads differently from a scripted post — and it is free to capture, since the header arrives with every request.",
  "layer": "OPERATIONAL",
  "layerSlug": "operational",
  "object": "campaign.message_flow + privacy policy",
  "severity": "LOW",
  "detectability": [
    "AI_FORM"
  ],
  "failureClass": "RETRY_FIELD",
  "authorities": [
    "CTIA",
    "mytcrplus"
  ],
  "applicability": {
    "consentMethods": [
      "web_form",
      "checkout",
      "account_settings",
      "third_party",
      "chat",
      "social",
      "email",
      "qr"
    ]
  },
  "applicabilityText": "Applies when consent was collected by web form, checkout, account settings, third party, chat, social, email and QR code.",
  "universal": false,
  "remediation": "Capture the User-Agent header alongside the IP address at submission and store it on the consent record. Done when a record shows the browser and device as well as the address it came from.",
  "example": "Each web opt-in stores user_agent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_2 like Mac OS X) …\" beside the IP.",
  "notes": "Registration-side twin: we judge whether the programme describes storing the field, never whether the stored record exists.",
  "phase": "approval",
  "automated": true,
  "url": "https://ekas.io/rules/10dlc/operational/ops-208/",
  "markdown": "https://ekas.io/rules/10dlc/operational/ops-208.md",
  "registry": "https://ekas.io/rules/10dlc/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/"
}
