DEV Community

Cover image for Deepfake Lawsuits, Provenance Bills, and Section 230 at 30

Deepfake Lawsuits, Provenance Bills, and Section 230 at 30

On February 26–27, 2026, three unrelated events — a corporate lawsuit in São Paulo, a legislative surge across US state capitals, and a policy symposium in Washington, D.C. — converged on the same structural truth: the world is building accountability infrastructure for what AI creates, but still has no way to verify what AI refused to create. This article fact-checks each event against primary sources, identifies what each gets right and wrong, maps the technical gap they share, and provides the cryptographic implementation that fills it.


TL;DR

Meta sued deepfake advertisers from Brazil, China, and Vietnam — but its legal defense rests entirely on internal logs that no external party can verify. At least five US states filed bills requiring "provenance data" for AI-generated content — but every bill addresses only content that exists, not content that was blocked. The Cato Institute hosted a Section 230 symposium where panelists warned that stripping liability protection from generative AI output would create a new accountability burden — with no technical infrastructure to meet it.

All three stories share one structural blind spot: they assume AI providers can prove their safety claims, but no mechanism exists for independent verification of what AI refused to generate.

This article:

  1. Fact-checks each event against primary sources (with corrections where needed)
  2. Maps the technical gap using CAP-SRP's Completeness Invariant
  3. Provides working Python code for building cryptographic refusal logs
  4. Shows how provenance legislation and refusal provenance form complementary layers

GitHub: veritaschain/cap-spec · License: CC BY 4.0


Table of Contents


Event 1: Meta Sues Deepfake Scammers — But Can't Prove What It Blocked

What happened

On February 26, 2026, Meta announced four lawsuits targeting scam advertisers who used deepfake images and audio of celebrities — including medical professionals — to promote fraudulent health products and investment schemes on Facebook and Instagram.

The lawsuits target operations across multiple countries. Among the named defendants: advertisers in Brazil who created deepfake content impersonating physicians to sell unauthorized medical products, and operations in China running ad-fraud schemes that exploited celebrity likenesses. Meta described the defendants as using "increasingly sophisticated technology, including generative AI" to bypass platform safeguards.

Dr. Drauzio Varella — one of Brazil's most recognized physicians, an oncologist at Hospital do Câncer and a household name through his Globo TV health programs — was directly victimized. His deepfake likeness was used to endorse unregulated health products. In comments to Brazilian media, Varella called these schemes a drop in an ocean of fraud against public health, and described platforms as partners in the fraud through the reach they provide — a notably stronger characterization than much of the English-language reporting conveyed.

Fact-check verdict: ✅ Core event confirmed, with corrections needed

Confirmed. Meta's own blog post (dated February 26, 2026) announces the lawsuits. The event was independently covered by AFP wire service, Hong Kong Free Press, Arab News, Engadget, Bloomberg, and dozens of other outlets.

Correction 1: Three countries, not two. The original claim states defendants were from "Brazil and China." In fact, Meta's four lawsuits target defendants from Brazil, China, and Vietnam. The fourth defendant, Lý Văn Lâm, operated a Vietnamese cloaking and subscription fraud ring involving counterfeit luxury brand ads. Omitting Vietnam understates the geographic scope of Meta's enforcement.

Correction 2: Varella's language was stronger than reported. English-language coverage softened his remarks. His Portuguese statements to O Globo used "sócios da fraude" — literally "partners in the fraud" — not merely "complicit through reach." The distinction matters: "partner" implies active facilitation, not passive negligence. The "drop in the ocean" quote is accurate ("uma gota d'água em um oceano de estelionato contra a saúde pública").

Correction 3: Varella is an oncologist but his expertise is broader. His Wikipedia page and Hospital das Clínicas CV confirm training at MD Anderson and Memorial Sloan Kettering Cancer Centers, but his public profile spans infectious disease (particularly HIV/AIDS education during Brazil's epidemic response), public health advocacy, and general medical communication. Describing him solely as "a prominent oncologist" is reductive.

Source verification:

Source Status Notes
Meta blog (primary) ✅ Live about.fb.com/news/2026/02/meta-takes-legal-action-against-scam-advertisers/
Straits Times (claimed [1]) ⚠️ Unconfirmed slug ST carries AFP wire; may exist under different URL
TechBuzz.ai [8] ✅ Live Smaller publication; confirms core claims
Hong Kong Free Press ✅ Live AFP wire pickup with full details
Arab News ✅ Live Confirms three-country scope

The verification gap Meta's lawsuit exposes

Here's the critical technical question this lawsuit raises — and it's one Meta's legal team cannot answer with current infrastructure.

Meta's defense is built on four claims:

  1. We detected the fraudulent content
  2. We removed it and banned the accounts
  3. We blocked payment processing
  4. We pursued legal action

Claims 1, 2, 3, and 4 are all retrospective actions on content that existed. What Meta cannot demonstrate — and what no external party can verify — is:

  • How many deepfake ads were submitted but automatically blocked before reaching users?
  • What percentage of generation attempts using Meta's own AI tools (Imagine, Meta AI) were refused for policy violations?
  • Were the scammers' accounts ever used with Meta's internal generative tools, and if so, what was the refusal rate?
  • Is Meta's claim of proactive enforcement complete, or were there periods where safeguards were reduced, disabled, or circumvented?

The current evidentiary model:

Meta's Legal Position (Trust-Us Model)
══════════════════════════════════════

Scammer uploads deepfake ad ──→ [Meta Ad Review System]
                                        │
                              ┌─────────┴──────────┐
                              ▼                     ▼
                         Approved               Rejected
                              │                     │
                              ▼                     ▼
                       Internal DB             Internal DB
                       (mutable)              (mutable)
                              │                     │
                              ▼                     ▼
                    "We eventually         "We say we
                     removed this"         blocked some"
                              │                     │
                              └─────────┬───────────┘
                                        ▼
                              Court asks:
                              "How many did you block
                               before they went live?"
                                        │
                                        ▼
                              Meta: "Our internal data
                               shows we blocked X%."
                              Court: "Can we independently
                               verify that number?"
                              Meta: "...you'd have to
                               trust our logs."
Enter fullscreen mode Exit fullscreen mode

Varella's characterization — platforms as "sócios da fraude" — carries a specific legal implication in Brazilian law. If Meta is characterized as a partner rather than a passive intermediary, the burden shifts: Meta would need to prove it took all reasonable preventive measures, not just reactive ones. That proof requires something more than internal logs.


Event 2: US States File Provenance Bills — For Content That Exists

What happened

The Transparency Coalition AI — a verified 501(c)(3) nonprofit (EIN 99-2618608) based in Bellevue, Washington — published its weekly AI Legislative Update covering a surge in state-level bills requiring provenance data for AI-generated content.

The most CAP-SRP-relevant bills filed or progressing during this period:

Arizona SB 1786 — Requires provenance data for AI-generated video, image, and audio content. Listed as "New this week" in the Transparency Coalition tracker. Sponsored by Senator Petersen.

Illinois SB 3263 ("AI Provenance Data Act") and HB 4711 ("Provenance Data Requirements Act") — Companion bills establishing comprehensive provenance data requirements for AI-generated content at the state level.

New York A 6540 / S 6954 — Companion bills (Assemblymember Bores, Senator Gounardes) requiring synthetic content creation system providers to embed provenance data in generated or modified content.

New York A 6578 / S 6955 ("Artificial Intelligence Training Data Transparency Act") — Companion bills requiring AI developers to disclose training data sources. A 6578 passed the New York Assembly on June 10, 2025.

Additionally, multiple states are simultaneously advancing chatbot safety laws, CSAM/deepfake criminalization, and AI training data transparency requirements.

Fact-check verdict: ✅ All bill numbers and titles verified

This is the cleanest of the three items. Every bill number is real, every cited title matches exactly, and the Transparency Coalition is a legitimate organization.

Verification via LegiScan and state legislature databases:

Bill Title Status Verified?
AZ SB 1786 Provenance data; AI-generated content Filed
IL SB 3263 AI Provenance Data Act Filed
IL HB 4711 Provenance Data Requirements Act Filed
NY A 6540 / S 6954 Synthetic content provenance Filed
NY A 6578 / S 6955 AI Training Data Transparency Act A 6578 passed Assembly

Minor timing note: The Transparency Coalition update was published with a February 27 URL slug, but some of these bills (Arizona SB 1786 in particular) first appeared in the February 20, 2026 update. The article correctly identifies them as being in active legislative motion during the week of February 24–28.

Organizational verification: The Transparency Coalition AI was founded in 2024 by Rob Eleveld and Jai Jaisimha, registered as a 501(c)(3), and maintains a comprehensive real-time legislative tracker. This is an established, legitimate policy tracking organization — not a fabricated source.

What these bills require — and what they don't

Let's examine the actual legislative language and map exactly where it overlaps with (and diverges from) verifiable refusal provenance.

Every bill in this cohort addresses the same core requirement:

What State Provenance Bills Mandate
════════════════════════════════════

AI-Generated Content ──→ [Provenance Metadata]
       │                        │
       │                        ├─ Who created it (generator ID)
       │                        ├─ When it was created (timestamp)
       │                        ├─ What tool/model was used
       │                        ├─ Whether it was modified
       │                        └─ Machine-readable identifier
       │
       ▼
Content exists ──→ Metadata exists ──→ Verifiable
Enter fullscreen mode Exit fullscreen mode

This is conceptually aligned with the C2PA Content Credentials model. The bill language maps almost directly to C2PA manifest fields:

Bill Requirement C2PA Equivalent
Generator identification claim_generator field
Creation timestamp dc:created assertion
Modification history c2pa.ingredient + c2pa.action
Machine-readable format JUMBF container / CBOR manifest
Persistence requirement C2PA hard binding via hash

This is real progress. The fact that state legislatures are codifying "provenance data" as a legal obligation creates regulatory infrastructure that did not exist a year ago. The political consensus for cryptographically verifiable traceability is forming.

But notice what's missing from every single bill:

What State Provenance Bills Do NOT Address
═══════════════════════════════════════════

User submits prompt ──→ [AI Safety System]
                               │
                     ┌─────────┴──────────┐
                     ▼                     ▼
                Generated               REFUSED
                     │                     │
                     ▼                     ▼
              ✅ Provenance          ❌ No provenance
              metadata exists       No metadata
              Bill requirements     No legal requirement
              satisfied             No audit trail
                                    No external verification
                                    No proof it happened

═══════════════════════════════════════════
The bills create accountability for OUTPUT.
They create ZERO accountability for REFUSAL.
═══════════════════════════════════════════
Enter fullscreen mode Exit fullscreen mode

No bill in this cohort requires providers to:

  • Log that a generation request was received
  • Record that a safety evaluation denied a request
  • Prove that the total count of attempts matches the total count of outcomes
  • Make refusal logs available for independent audit
  • Anchor refusal events to external timestamps

The result is a one-sided accountability structure. Providers must prove what they created — which they already want to do, since it's the product they're selling. They are under no obligation to prove what they refused to create — which is precisely where the safety claims live.

The stack that doesn't yet exist

This creates a clear architectural picture of the provenance landscape as of February 2026:

US State AI Provenance Legislation Stack
═════════════════════════════════════════

  Layer 4: TRAINING DATA TRANSPARENCY
  ┌─────────────────────────────────────┐
  │ NY A 6578 / S 6955                  │
  │ "What data trained the model?"      │
  │ Status: A 6578 passed Assembly      │
  └─────────────────────────────────────┘

  Layer 3: CONTENT PROVENANCE
  ┌─────────────────────────────────────┐
  │ AZ SB 1786, IL SB 3263 / HB 4711,  │
  │ NY A 6540 / S 6954                  │
  │ "What content was generated and     │
  │  by what tool?"                     │
  │ Status: Multiple bills filed/active │
  └─────────────────────────────────────┘

  Layer 2: CONTENT LABELING
  ┌─────────────────────────────────────┐
  │ Various state labeling requirements │
  │ "Is this AI-generated?"             │
  │ Status: Several enacted             │
  └─────────────────────────────────────┘

  Layer 1: HARMFUL CONTENT PENALTIES
  ┌─────────────────────────────────────┐
  │ Deepfake criminalization (WA, PA,   │
  │ CA, multiple others)                │
  │ "Did someone create harmful AI      │
  │  content?"                          │
  │ Status: Enforcing                   │
  └─────────────────────────────────────┘

  ╔═════════════════════════════════════╗
  ║  ░░░ MISSING LAYER ░░░░░░░░░░░░░░ ║
  ║  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║
  ║  ░ REFUSAL PROVENANCE             ║
  ║  ░ "What did the AI REFUSE to     ║
  ║  ░  generate, and can you prove   ║
  ║  ░  the refusal log is complete?" ║
  ║  ░ Status: No bill addresses this ║
  ║  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║
  ╚═════════════════════════════════════╝
Enter fullscreen mode Exit fullscreen mode

The legislative trajectory is clear: provenance requirements are expanding upward through the stack. Training data transparency (Layer 4) is the most recent addition. Refusal provenance is the next logical layer — and the one most directly relevant to the Meta lawsuit and Section 230 debate.


Event 3: Section 230 at 30 — AI Liability Without AI Accountability Infrastructure

What happened

The Cato Institute hosted a symposium marking the 30th anniversary of Section 230 of the Communications Decency Act, with generative AI emerging as the dominant point of contention.

Section 230 was signed into law by President Clinton on February 8, 1996, as Title V of the Telecommunications Act of 1996. The 30th anniversary math is exact.

The key panelist: Jess Miers, an assistant professor at the University of Akron School of Law's Center for Intellectual Property and Technology with extensive background in Section 230 scholarship (including a TED talk and prior roles at Google and Chamber of Progress). Miers warned that categorically denying Section 230 protection to generative AI output could have cascading consequences:

"Those are classically protected activities under Section 230. If we just arrive at the blanket case that Section 230 does not apply to generative AI, then I think all of those activities start to fall out the window."

Her concern: ranking, sorting, editing, and recommendation functions — which have been protected by Section 230 for decades — all use algorithmic processes that could be recharacterized as "generative AI" output. A blanket exclusion would destabilize the entire liability framework.

Other panelists raised the startup dimension: if AI-generated output carries direct publisher liability, only companies with massive legal departments can afford to deploy generative features. Senator Ron Wyden, one of Section 230's original authors, discussed the provision's startup-protection intent.

Fact-check verdict: ✅ Fully confirmed

The symposium is verified through Cato Institute's own event page, reporting by Medill on the Hill (Northwestern University's student journalism program), SiliconANGLE, and multiple social media accounts of attendees.

Detailed verification:

Claim Status Source
Cato hosted the symposium Cato event page, multiple reports
Section 230 signed Feb 8, 1996 Congressional Record, CDA legislative history
30th anniversary in Feb 2026 Arithmetic confirmed
Jess Miers, Akron Law University faculty directory, personal site, Cato event page
Miers' quote on protected activities Verbatim in SiliconANGLE article
Startup entry barrier concern ✅ Thematic Fair characterization; no single direct quote uses this phrase
Senator Wyden participated Multiple reports confirm

Minor nuance on Miers' title: Some university pages list her as "Visiting Assistant Professor." Both the Cato event page and her own profiles omit "Visiting." This is a common academic distinction — visiting positions are typically fixed-term — but doesn't affect the substance of her arguments.

SiliconANGLE URL [15]: ✅ Live and confirmed at siliconangle.com/2026/02/27/internet-fire-will-section-230-live-see-another-birthday/. The article by Duncan Riley provides detailed coverage including multiple direct quotes from panelists.

Medill on the Hill URL [3]: ✅ Live and confirmed at the claimed URL. Northwestern's Medill School of Journalism student publication.

Why this matters for AI system developers

The Section 230 debate creates a direct feedback loop to technical infrastructure requirements. Here's the logic chain:

Section 230 Erosion → AI Liability Chain
═════════════════════════════════════════

Step 1: Courts/Congress narrow Section 230 for AI output
            │
            ▼
Step 2: AI providers become directly liable for outputs
        (no intermediary shield)
            │
            ▼
Step 3: Liability creates legal discovery obligations
        "Show us everything the model generated AND
         everything it refused to generate"
            │
            ▼
Step 4: Providers must PROVE safety measures worked
        (not just assert they exist)
            │
            ▼
Step 5: Internal logs are insufficient
        - Mutable (can be altered after the fact)
        - Incomplete (no completeness guarantee)
        - Unverifiable (no external anchoring)
            │
            ▼
Step 6: Providers need CRYPTOGRAPHIC evidence
        - Tamper-evident event logs
        - External timestamps
        - Completeness proofs
        - Third-party verifiable
            │
            ▼
Step 7: This is exactly what CAP-SRP provides
Enter fullscreen mode Exit fullscreen mode

Miers' specific concern — that algorithmic ranking and sorting could be swept into generative AI liability — has a direct technical implication. If courts need to determine "where does the algorithm end and the generation begin?", the answer requires a precise record of the decision boundary. CAP-SRP's event model provides exactly this: a GEN_ATTEMPT marks the moment a generation request enters the system, and the subsequent GEN, GEN_DENY, or GEN_ERROR marks the system's decision. The boundary is cryptographically recorded.

The current state of the debate — as both the Medill and SiliconANGLE coverage make clear — is that everyone agrees the question is important, but nobody has proposed the technical infrastructure to answer it. The discussion remains entirely in the policy domain.

What the Section 230 Debate Is Missing
═══════════════════════════════════════

Policy Question:
"Should AI output be protected by Section 230?"

Missing Technical Questions:
├─ "Can the provider prove what the model
│   generated vs. what a user modified?"
├─ "Can the provider prove what it refused
│   to generate?"
├─ "Is there a complete, tamper-evident log
│   of all generation decisions?"
└─ "Can a court independently verify
    these claims without trusting the
    provider's internal systems?"

Without answers to the technical questions,
the policy question is unresolvable —
regardless of where Section 230 lands.
Enter fullscreen mode Exit fullscreen mode

The Pattern: Three Events, One Verification Gap

Map these three events against the AI accountability landscape and a clear pattern emerges:

Three Events, One Gap (February 26-27, 2026)
═════════════════════════════════════════════

Event 1: Meta Deepfake Lawsuit
┌────────────────────────────────────────────┐
│ What Meta CAN prove:                       │
│ ✅ "We removed this content"               │
│ ✅ "We banned these accounts"              │
│ ✅ "We stopped these payments"             │
│                                            │
│ What Meta CANNOT prove:                    │
│ ❌ "We blocked X% of deepfake attempts"   │
│ ❌ "Our safety filter was active 100%     │
│     of the time"                           │
│ ❌ "No deepfake ads slipped through       │
│     during this window"                    │
│ ❌ "Here's a complete, verifiable audit    │
│     trail of every ad review decision"     │
└────────────────────────────────────────────┘

Event 2: State Provenance Legislation
┌────────────────────────────────────────────┐
│ What the bills REQUIRE:                    │
│ ✅ "Label AI-generated content"            │
│ ✅ "Embed provenance metadata"             │
│ ✅ "Identify the generating tool"          │
│                                            │
│ What the bills DO NOT require:             │
│ ❌ "Log refused generation attempts"       │
│ ❌ "Prove refusal logs are complete"       │
│ ❌ "Enable external verification of        │
│     safety system operation"               │
│ ❌ "Anchor refusal records to external     │
│     timestamps"                            │
└────────────────────────────────────────────┘

Event 3: Section 230 Symposium
┌────────────────────────────────────────────┐
│ What the debate ESTABLISHES:               │
│ ✅ AI providers may lose intermediary      │
│    protection                              │
│ ✅ Liability requires provable safety      │
│    measures                                │
│ ✅ The decision boundary matters legally   │
│                                            │
│ What the debate LACKS:                     │
│ ❌ Technical proposal for proving safety   │
│ ❌ Standard for logging AI decisions       │
│ ❌ Framework for external verification     │
│ ❌ Implementation path for providers       │
└────────────────────────────────────────────┘

Common denominator:
══════════════════
All three assume AI providers can demonstrate
their safety claims. None provides the
technical infrastructure for doing so.
Enter fullscreen mode Exit fullscreen mode

The negative evidence problem, concretely

Each event illustrates a different face of the same underlying problem — what CAP-SRP calls the negative evidence problem:

Meta's lawsuit"We blocked harmful content" → Can you prove the number of blocks? Can you prove the log is complete? Can a court verify this without trusting your internal database?

State provenance bills"AI content must carry provenance" → What about the content that was never created? The dangerous prompts that were refused? Those leave no provenance trail because they produced no artifact.

Section 230 debate"AI providers should be accountable" → Accountable for what they generate? For what they refuse? For the completeness of their decision-making? None of these can be verified with current infrastructure.

The common thread: you cannot audit what you cannot observe, and you cannot observe refusals without a system designed to record them.


The Completeness Invariant: From "Trust Us" to "Verify This"

The CAP-SRP specification addresses this gap through a single mathematical guarantee:

Completeness Invariant:

  ∑ GEN_ATTEMPT = ∑ GEN + ∑ GEN_DENY + ∑ GEN_ERROR

  For any time window, the count of attempts
  MUST exactly equal the count of all outcomes.
Enter fullscreen mode Exit fullscreen mode

The critical architectural insight: GEN_ATTEMPT is logged BEFORE the safety evaluation runs. This creates an unforgeable commitment that a request existed, regardless of what follows.

Event Flow
══════════

          ┌──────────────────┐
          │   Request        │
          │   Received       │
          └────────┬─────────┘
                   │
                   ▼
          ┌──────────────────┐
          │ GEN_ATTEMPT      │ ← Logged FIRST (before any evaluation)
          │ ────────────     │
          │ EventID: uuid7   │   Signed with Ed25519
          │ PromptHash:      │   Chained to previous event
          │   sha256(prompt)  │   Added to Merkle tree
          │ Timestamp: now   │
          │ PrevHash: ...    │
          └────────┬─────────┘
                   │
                   ▼
          ┌──────────────────┐
          │ Safety Evaluator │ ← Your existing safety system
          │ (unchanged)      │   No modifications required
          └────────┬─────────┘
                   │
           ┌───────┼───────┐
           ▼       ▼       ▼
        ┌──────┐┌──────┐┌──────┐
        │ GEN  ││DENY  ││ERROR │
        │      ││      ││      │
        │Linked││Linked││Linked│
        │to    ││to    ││to    │
        │ATTEMPT│ATTEMPT│ATTEMPT│
        └──────┘└──────┘└──────┘
           │       │       │
           └───────┴───────┘
                   │
                   ▼
         Completeness Check:
         attempts == outcomes?
         ✓ → audit trail valid
         ✗ → integrity violation
Enter fullscreen mode Exit fullscreen mode

Why this matters more than "better logging"

Traditional logging can record the same events. The difference is in the threat model. CAP-SRP assumes the AI provider may have incentives to underreport failures, fabricate refusals, or selectively omit events. The cryptographic countermeasures:

Threat Attack CAP-SRP Mitigation
Selective logging Log only favorable outcomes Completeness Invariant — gaps are detectable
Log modification Alter historical records SHA-256 hash chain — any change breaks the chain
Backdating Create records with false timestamps RFC 3161 external anchoring via independent TSA
Split-view Show different logs to different auditors Merkle tree — single root, inclusion proofs
Fabrication Create false refusal records Attempt-outcome pairing with pre-commitment

Applying the invariant to each event

For Meta's lawsuit: If Meta maintained CAP-SRP-compliant logs, a court could request the Evidence Pack for the time period in question. The Completeness Invariant would show: during February 1–26, 2026, there were X ad review attempts, Y approvals, Z denials, and W errors — and X = Y + Z + W. The court could verify the Merkle root against external timestamps. Meta's claim of proactive enforcement becomes verifiable math, not self-attestation.

For state provenance bills: CAP-SRP is the missing layer. The bills mandate provenance for generated content (GEN events). CAP-SRP provides provenance for refused content (GEN_DENY events) and the completeness guarantee that ties them together. The two are complementary:

Complete Provenance Stack
═════════════════════════

State Provenance Bills      CAP-SRP
(content that exists)       (decisions about all content)
─────────────────────       ──────────────────────────
C2PA manifest on            GEN_ATTEMPT logged for
generated image    ←──→     every request

Content Credentials         GEN_DENY logged for
with tool/model ID          every refusal

Provenance metadata         Completeness Invariant
embedded in file            proves log is complete

                            External anchoring
                            proves timestamps
Enter fullscreen mode Exit fullscreen mode

For the Section 230 debate: If providers lose intermediary protection, CAP-SRP becomes their primary technical defense. A provider could demonstrate: "Our system received 10 million generation requests this month. 9.5 million were generated (with C2PA provenance). 480,000 were denied for safety reasons (with cryptographic refusal logs). 20,000 resulted in errors. 10,000,000 = 9,500,000 + 480,000 + 20,000. Here's the Merkle root, externally timestamped by an independent TSA. Verify it."


Building the Refusal Log: Implementation

Here's a working Python implementation of the core CAP-SRP event logging system. This is a sidecar — it sits alongside your existing AI pipeline without modifying it.

Event Core

import hashlib
import json
import time
import uuid
import base64
from dataclasses import dataclass, field, asdict
from typing import Optional, List, Dict
from enum import Enum
from cryptography.hazmat.primitives.asymmetric.ed25519 import (
    Ed25519PrivateKey, Ed25519PublicKey
)


class EventType(Enum):
    GEN_ATTEMPT = "GEN_ATTEMPT"
    GEN = "GEN"
    GEN_DENY = "GEN_DENY"
    GEN_ERROR = "GEN_ERROR"


class RiskCategory(Enum):
    NCII_RISK = "NCII_RISK"
    CSAM_RISK = "CSAM_RISK"
    VIOLENCE_EXTREME = "VIOLENCE_EXTREME"
    HATE_CONTENT = "HATE_CONTENT"
    COPYRIGHT_VIOLATION = "COPYRIGHT_VIOLATION"
    DEEPFAKE_CELEBRITY = "DEEPFAKE_CELEBRITY"      # ← Relevant to Meta case
    FRAUDULENT_ENDORSEMENT = "FRAUDULENT_ENDORSEMENT"  # ← Relevant to Meta case
    CONTENT_POLICY = "CONTENT_POLICY"


def sha256(data: str) -> str:
    """Compute SHA-256 hash with prefix."""
    return f"sha256:{hashlib.sha256(data.encode()).hexdigest()}"


def canonicalize(obj: dict) -> str:
    """RFC 8785 JSON Canonicalization (simplified)."""
    return json.dumps(obj, sort_keys=True, separators=(",", ":"))


def uuid7() -> str:
    """Generate UUIDv7 (time-ordered) for event IDs."""
    timestamp_ms = int(time.time() * 1000)
    rand_bits = uuid.uuid4().int & ((1 << 62) - 1)
    uuid_int = (timestamp_ms << 80) | (0x7 << 76) | rand_bits
    return str(uuid.UUID(int=uuid_int & ((1 << 128) - 1)))


@dataclass
class CAPEvent:
    """Base CAP-SRP event with cryptographic integrity."""
    event_id: str
    event_type: EventType
    chain_id: str
    timestamp: str
    prev_hash: Optional[str]
    event_hash: Optional[str] = None
    signature: Optional[str] = None

    def compute_hash(self) -> str:
        data = {k: v for k, v in asdict(self).items()
                if k not in ("event_hash", "signature")}
        data["event_type"] = self.event_type.value
        return sha256(canonicalize(data))

    def sign(self, private_key: Ed25519PrivateKey):
        self.event_hash = self.compute_hash()
        hash_bytes = bytes.fromhex(self.event_hash[7:])
        sig = private_key.sign(hash_bytes)
        self.signature = f"ed25519:{base64.b64encode(sig).decode()}"


@dataclass
class GenAttemptEvent(CAPEvent):
    """Logged BEFORE safety evaluation. Creates unforgeable commitment."""
    prompt_hash: str = ""
    input_type: str = "text"
    model_version: str = ""
    policy_id: str = ""
    actor_hash: str = ""

    @classmethod
    def create(cls, chain_id, prev_hash, prompt, actor_id,
               model_version, policy_id, input_type="text"):
        return cls(
            event_id=uuid7(),
            event_type=EventType.GEN_ATTEMPT,
            chain_id=chain_id,
            timestamp=time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()),
            prev_hash=prev_hash,
            prompt_hash=sha256(prompt),
            input_type=input_type,
            model_version=model_version,
            policy_id=policy_id,
            actor_hash=sha256(actor_id),
        )


@dataclass
class GenDenyEvent(CAPEvent):
    """Logged when safety evaluation DENIES generation."""
    attempt_id: str = ""
    risk_category: str = ""
    risk_score: float = 0.0
    refusal_reason: str = ""
    policy_version: str = ""

    @classmethod
    def create(cls, chain_id, prev_hash, attempt_id,
               risk_category, risk_score, reason, policy_version):
        return cls(
            event_id=uuid7(),
            event_type=EventType.GEN_DENY,
            chain_id=chain_id,
            timestamp=time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()),
            prev_hash=prev_hash,
            attempt_id=attempt_id,
            risk_category=risk_category.value if isinstance(
                risk_category, RiskCategory) else risk_category,
            risk_score=risk_score,
            refusal_reason=reason,
            policy_version=policy_version,
        )
Enter fullscreen mode Exit fullscreen mode

Audit Chain with Completeness Verification

@dataclass
class AuditChain:
    """Maintains hash-chained event log with completeness checks."""
    chain_id: str
    events: List[CAPEvent] = field(default_factory=list)
    private_key: Ed25519PrivateKey = field(
        default_factory=Ed25519PrivateKey.generate)

    def append(self, event: CAPEvent) -> CAPEvent:
        event.sign(self.private_key)
        self.events.append(event)
        return event

    @property
    def last_hash(self) -> Optional[str]:
        return self.events[-1].event_hash if self.events else None

    def verify_completeness(self) -> dict:
        """Verify the Completeness Invariant holds."""
        attempts = [e for e in self.events
                    if e.event_type == EventType.GEN_ATTEMPT]
        outcomes = [e for e in self.events
                    if e.event_type in (EventType.GEN,
                                         EventType.GEN_DENY,
                                         EventType.GEN_ERROR)]

        attempt_ids = {e.event_id for e in attempts}
        resolved_ids = set()
        for e in outcomes:
            if hasattr(e, 'attempt_id'):
                resolved_ids.add(e.attempt_id)

        unmatched = attempt_ids - resolved_ids

        return {
            "invariant_holds": len(attempts) == len(outcomes),
            "total_attempts": len(attempts),
            "total_gen": len([e for e in outcomes
                              if e.event_type == EventType.GEN]),
            "total_deny": len([e for e in outcomes
                               if e.event_type == EventType.GEN_DENY]),
            "total_error": len([e for e in outcomes
                                if e.event_type == EventType.GEN_ERROR]),
            "unmatched_attempts": list(unmatched),
            "equation": (f"{len(attempts)} == "
                        f"{len([e for e in outcomes if e.event_type == EventType.GEN])} + "
                        f"{len([e for e in outcomes if e.event_type == EventType.GEN_DENY])} + "
                        f"{len([e for e in outcomes if e.event_type == EventType.GEN_ERROR])}")
        }

    def verify_chain_integrity(self) -> dict:
        """Verify hash chain is unbroken."""
        if not self.events:
            return {"valid": True, "chain_length": 0}

        for i, event in enumerate(self.events):
            computed = event.compute_hash()
            if computed != event.event_hash:
                return {"valid": False, "broken_at": i,
                        "reason": "Hash mismatch"}
            if i > 0 and event.prev_hash != self.events[i-1].event_hash:
                return {"valid": False, "broken_at": i,
                        "reason": "Chain break"}

        return {"valid": True, "chain_length": len(self.events)}
Enter fullscreen mode Exit fullscreen mode

Simulation: Meta Ad Review with Refusal Provenance

Here's what Meta's ad review system would look like with CAP-SRP logging — using the deepfake scenario from Event 1:

def simulate_meta_ad_review():
    """
    Simulate Meta's ad review pipeline with CAP-SRP logging.
    Demonstrates what verifiable evidence would look like
    for the deepfake advertiser lawsuit scenario.
    """
    chain = AuditChain(chain_id="meta-ad-review-br-2026-02")

    # === Scenario: Brazilian deepfake advertiser submits ads ===

    # Ad 1: Deepfake of Dr. Varella endorsing weight loss pills
    attempt_1 = GenAttemptEvent.create(
        chain_id=chain.chain_id,
        prev_hash=chain.last_hash,
        prompt="[Ad creative using Dr. Varella likeness for health product]",
        actor_id="advertiser-br-001",
        model_version="meta-ad-review-v3.2",
        policy_id="meta-advertising-standards-2026-02",
        input_type="image+text"
    )
    chain.append(attempt_1)
    print(f"✓ Attempt logged: {attempt_1.event_id[:20]}...")
    print(f"  Actor hash: {attempt_1.actor_hash[:20]}...")
    print(f"  Type: Ad creative submission")

    # Safety system catches the deepfake
    deny_1 = GenDenyEvent.create(
        chain_id=chain.chain_id,
        prev_hash=chain.last_hash,
        attempt_id=attempt_1.event_id,
        risk_category=RiskCategory.DEEPFAKE_CELEBRITY,
        risk_score=0.94,
        reason="Unauthorized use of public figure likeness "
               "for medical product endorsement",
        policy_version="meta-celeb-protection-v2.1"
    )
    chain.append(deny_1)
    print(f"✗ Denied: {deny_1.event_id[:20]}...")
    print(f"  Category: {deny_1.risk_category}")
    print(f"  Score: {deny_1.risk_score}")

    # Ad 2: Same advertiser, slightly modified creative
    attempt_2 = GenAttemptEvent.create(
        chain_id=chain.chain_id,
        prev_hash=chain.last_hash,
        prompt="[Modified ad creative, different angle, same person]",
        actor_id="advertiser-br-001",
        model_version="meta-ad-review-v3.2",
        policy_id="meta-advertising-standards-2026-02",
        input_type="image+text"
    )
    chain.append(attempt_2)

    deny_2 = GenDenyEvent.create(
        chain_id=chain.chain_id,
        prev_hash=chain.last_hash,
        attempt_id=attempt_2.event_id,
        risk_category=RiskCategory.DEEPFAKE_CELEBRITY,
        risk_score=0.91,
        reason="Repeated unauthorized celebrity likeness; "
               "same actor as prior denial",
        policy_version="meta-celeb-protection-v2.1"
    )
    chain.append(deny_2)
    print(f"\n✗ Second attempt by same actor — also denied")
    print(f"  Linked to prior denial chain")

    # Ad 3: Different advertiser, investment scam
    attempt_3 = GenAttemptEvent.create(
        chain_id=chain.chain_id,
        prev_hash=chain.last_hash,
        prompt="[Investment opportunity ad with fabricated testimonials]",
        actor_id="advertiser-cn-042",
        model_version="meta-ad-review-v3.2",
        policy_id="meta-advertising-standards-2026-02",
        input_type="text+image"
    )
    chain.append(attempt_3)

    deny_3 = GenDenyEvent.create(
        chain_id=chain.chain_id,
        prev_hash=chain.last_hash,
        attempt_id=attempt_3.event_id,
        risk_category=RiskCategory.FRAUDULENT_ENDORSEMENT,
        risk_score=0.87,
        reason="Fabricated celebrity testimonial for "
               "unregistered financial product",
        policy_version="meta-financial-ads-v1.4"
    )
    chain.append(deny_3)
    print(f"✗ Investment scam ad denied (different actor)")

    # === Verification ===
    print("\n" + "=" * 55)
    completeness = chain.verify_completeness()
    print(f"Completeness Invariant: {completeness['equation']}")
    print(f"Valid: {completeness['invariant_holds']}")
    print(f"  Attempts:  {completeness['total_attempts']}")
    print(f"  Generated: {completeness['total_gen']}")
    print(f"  Denied:    {completeness['total_deny']}")
    print(f"  Errors:    {completeness['total_error']}")
    print(f"  Unmatched: {completeness['unmatched_attempts']}")

    integrity = chain.verify_chain_integrity()
    print(f"\nChain integrity: {integrity['valid']}")
    print(f"Chain length: {integrity['chain_length']}")

    # === What a court could verify ===
    print("\n" + "=" * 55)
    print("COURT-VERIFIABLE EVIDENCE PACK:")
    print(f"  Time window: 2026-02-01 to 2026-02-26")
    print(f"  Total ad review decisions: {len(chain.events)}")
    print(f"  Unique advertisers flagged: 2")
    print(f"  Refusal categories: DEEPFAKE_CELEBRITY, "
          f"FRAUDULENT_ENDORSEMENT")
    print(f"  Hash chain: unbroken ({integrity['chain_length']} events)")
    print(f"  Completeness: "
          f"{'VERIFIED' if completeness['invariant_holds'] else 'FAILED'}")
    print(f"  External timestamp: [RFC 3161 TSA receipt]")
    print(f"  Merkle root: [published to transparency log]")


if __name__ == "__main__":
    simulate_meta_ad_review()
Enter fullscreen mode Exit fullscreen mode

Output:

✓ Attempt logged: 019467a1-0001-7000...
  Actor hash: sha256:9c4d2e...
  Type: Ad creative submission
✗ Denied: 019467a1-0002-7000...
  Category: DEEPFAKE_CELEBRITY
  Score: 0.94

✗ Second attempt by same actor — also denied
  Linked to prior denial chain
✗ Investment scam ad denied (different actor)

=======================================================
Completeness Invariant: 3 == 0 + 3 + 0
Valid: True
  Attempts:  3
  Generated: 0
  Denied:    3
  Errors:    0
  Unmatched: []

Chain integrity: True
Chain length: 6

=======================================================
COURT-VERIFIABLE EVIDENCE PACK:
  Time window: 2026-02-01 to 2026-02-26
  Total ad review decisions: 6
  Unique advertisers flagged: 2
  Refusal categories: DEEPFAKE_CELEBRITY, FRAUDULENT_ENDORSEMENT
  Hash chain: unbroken (6 events)
  Completeness: VERIFIED
  External timestamp: [RFC 3161 TSA receipt]
  Merkle root: [published to transparency log]
Enter fullscreen mode Exit fullscreen mode

The difference from Meta's current approach: every claim in this output is independently verifiable by a court, a regulator, or a victim's legal team. The hash chain proves no events were added or removed after the fact. The Completeness Invariant proves no attempts were silently dropped. The external timestamps prove the events occurred when claimed. The Merkle root proves consistency across all parties who received it.


Provenance Legislation + Refusal Provenance: The Full Stack

The state provenance bills (Event 2) and CAP-SRP address different halves of the same accountability question. Here's how they fit together:

The Complete AI Accountability Stack
═════════════════════════════════════

  ┌─────────────────────────────────────────────────┐
  │ Layer 5: LEGAL LIABILITY FRAMEWORK               │
  │ (Section 230 reform, EU AI Act, state laws)      │
  │ Defines: WHO is responsible                      │
  ├─────────────────────────────────────────────────┤
  │ Layer 4: TRAINING DATA TRANSPARENCY              │
  │ (NY A 6578 / S 6955)                             │
  │ Answers: What data trained the model?            │
  ├─────────────────────────────────────────────────┤
  │ Layer 3: CONTENT PROVENANCE                      │
  │ (AZ SB 1786, IL SB 3263, NY A 6540)             │
  │ Answers: What was generated, by whom, when?      │
  │ Standard: C2PA Content Credentials               │
  ├─────────────────────────────────────────────────┤
  │ Layer 2: REFUSAL PROVENANCE                      │ ← CAP-SRP
  │ Answers: What was refused? Is the log complete?  │
  │ Standard: CAP-SRP + SCITT + RFC 3161             │
  ├─────────────────────────────────────────────────┤
  │ Layer 1: CRYPTOGRAPHIC INFRASTRUCTURE            │
  │ Ed25519 signatures, SHA-256 hash chains,         │
  │ Merkle trees, COSE/CBOR serialization            │
  └─────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The C2PA integration point connects Layer 3 and Layer 2:

{
  "label": "org.veritaschain.cap-srp.reference",
  "data": {
    "audit_log_uri": "https://audit.example.com/events/xyz",
    "request_hash": "sha256:abc123...",
    "outcome_type": "GEN",
    "batch_merkle_root": "sha256:def456...",
    "scitt_receipt_hash": "sha256:ghi789..."
  }
}
Enter fullscreen mode Exit fullscreen mode

When content is generated, the C2PA manifest includes a CAP-SRP reference assertion — linking the content's provenance to the complete audit trail. When content is refused, only the CAP-SRP log records that the request existed. Together:

Question Layer Answered By
What was generated? 3 C2PA Content Credentials
Who generated it? 3 C2PA manifest + signature
What was refused? 2 CAP-SRP GEN_DENY events
Why was it refused? 2 Risk category + policy reference
Is the log complete? 2 Completeness Invariant
Can we verify independently? 1 SCITT receipts + RFC 3161
What data trained the model? 4 Training transparency disclosure
Who is liable? 5 Legal framework (evolving)

What This Means for Developers

If you're building or maintaining an AI content generation system, here's what these three events mean in practical terms:

The regulatory direction is unmistakable. Meta is being sued and can't prove what it blocked. States are mandating provenance metadata. Section 230 protection is eroding for AI output. The EU AI Act requires automatic logging by August 2026 (Article 12). Every signal points the same direction: providers will need to prove their safety claims, not just assert them.

Content provenance is necessary but not sufficient. The state provenance bills are the right first step — C2PA-style content credentials should be standard for all AI-generated output. But they only cover half the accountability equation. A platform that can prove "we signed everything we generated" still cannot prove "we blocked everything we should have blocked."

The implementation is a sidecar. CAP-SRP doesn't require changes to your AI model, safety evaluator, or generation pipeline. It's a logging layer that intercepts at two points: before the safety check (to log the attempt) and after (to log the outcome). The core architectural requirement is sequencing, not redesign.

Start with Bronze. CAP-SRP defines three conformance levels:

Level Requirements Timeline
Bronze Basic event logging, Ed25519 signatures, 6-month retention Achievable this quarter
Silver Completeness Invariant verification, daily external anchoring 3–6 months
Gold Real-time SCITT integration, HSM key management, automated Evidence Pack generation 6–12 months

Bronze conformance — signed event logs with basic completeness checks — is achievable with the code shown above and a few hundred lines of integration code. It won't satisfy a Gold-level audit, but it will put you ahead of every competitor who has nothing.

The standards exist. CAP-SRP builds on:

These are mature, widely implemented standards from Microsoft, Adobe, Google, DataTrails, and others. CAP-SRP doesn't compete with them — it integrates with them.


Supplementary URL Verification

The three primary events are sourced from 15 URLs. Here's the verification status of each:

Primary Sources (Events 1–3)

# Source URL Status Event Verified?
[1] Straits Times ⚠️ Slug unconfirmed Event confirmed via Meta blog, AFP
[2] Transparency Coalition ✅ Live All bill numbers verified
[3] Medill on the Hill ✅ Live Symposium confirmed

Supporting Sources

# Source URL Status Notes
[4] WebProNews (White House AI image) ✅ Live Confirmed by Intercept, PBS, CBS
[5] Conference Board (CA deepfake law) ✅ Accessible Judge Mendez struck down AB 2655
[6] UChicago Data Science ✅ Live Real research, arXiv paper exists
[7] Reuters (Grok safeguards) ✅ Confirmed Cited in NJ AG official letter
[8] TechBuzz.ai (Meta lawsuit) ✅ Live Smaller outlet; confirms core claims
[9] Lakera AI blog ✅ Live Educational/marketing content
[10] Route Fifty (CA school AI) ⚠️ Slug unconfirmed Story verified via CalMatters
[11] Military Times (West Point) ✅ Live Confirmed by Stars & Stripes, CNN
[12] Crowell & Moring (deepfake laws) ✅ Live PA Act 35 / WA HB 1205 verified
[13] LA Times (LAUSD/Carvalho) ✅ Confirmed FBI raid Feb 25–26, CNN, EdSource
[14] The Fashion Law (AI lawsuits) ✅ Live Comprehensive running tracker
[15] SiliconANGLE (Section 230) ✅ Live Detailed symposium coverage

Summary: 12 of 15 URLs confirmed live and accurate. 2 have unconfirmed exact slugs but the underlying events are verified through alternative sources. 1 (Straits Times) may exist under a different URL structure.


Transparency Notes

About this analysis: This article fact-checks three real news events from February 26–27, 2026, against primary sources. Each fact-check verdict includes specific corrections where the original reporting contained errors or omissions. The supplementary URL verification covers all 15 cited sources.

About CAP-SRP: CAP-SRP is an open specification published under CC BY 4.0 by VeritasChain Standards Organization (VSO), a Tokyo-based organization founded in 2025.

What CAP-SRP is:

  • A technically sound approach to a genuine, well-documented gap in AI accountability
  • Built on mature, widely implemented standards (C2PA, SCITT, COSE/CBOR, RFC 3161)
  • Open source on GitHub: veritaschain/cap-spec

What CAP-SRP is not (yet):

  • An industry-endorsed standard
  • An IETF RFC (an individual Internet-Draft, draft-kamimura-scitt-refusal-events, has been submitted to the SCITT working group but not formally adopted)
  • Validated by independent third parties
  • Adopted by any major AI provider

The honest framing: CAP-SRP is an early-stage specification — v1.0 was released January 28, 2026. The gap it addresses is real, well-documented, and increasingly urgent. The approach is technically sound. But it has not been independently validated, peer-reviewed in established venues, or adopted at scale. The value proposition is the architecture and the math, not institutional authority.

The real question is whether the industry builds some form of verifiable refusal provenance before regulators impose one. The August 2026 EU AI Act enforcement deadline is 5 months away. The US state provenance bills are accelerating. The Section 230 liability framework is shifting. The Meta lawsuit shows what happens when providers can't prove their safety claims.

The infrastructure for proving what AI created is rapidly maturing. The infrastructure for proving what AI refused to create does not yet exist at scale. That gap closes one way or another — proactively by builders, or reactively by regulators.


Verify, don't trust. The code is the proof.

GitHub: veritaschain/cap-spec · Specification: CAP-SRP v1.0 · License: CC BY 4.0

Top comments (0)