← back to all posts
California· CCPA / CPRA· 5 min read

CCPA "do not sell": the evidence a database can provide

California's twelve-month sharing lookback is hard to evidence from current-state data. This post shows the queries that read it from recorded history.

The CCPA — as amended by the California Privacy Rights Act — gives California residents a small bundle of rights you have to honor on a forty-five-day clock. Most companies focus on the easy ones: right to know (§1798.110), right to delete (§1798.105). The hard ones are the two CPRA added in 2023 and the one that's existed since 2018 but nobody can actually prove.

The three hard ones

§1798.115 — twelve-month sharing lookback. Every sale or share of personal information over the prior year, with whom, and for what purpose. Your data warehouse, your ad networks, your service providers. Most companies can't produce this for one customer in less than a week.

§1798.121 — limit use of sensitive personal information. If a customer invokes this, you must prove that their location data, financial information, race/ethnic origin, sexual orientation, and so on, have only been used for the explicit purposes you disclosed. Not "we hope so" — proof.

§1798.135 — do not sell or share. This has been live since 2018. It's the right where most stacks silently break. The customer opts out, and your ad-network integration keeps firing because nobody wired the opt-out signal to the integration. You don't find out until the CPPA shows up.

What evidencing them requires

If you think about what these three rights actually demand of your engineering stack, it's:

  1. Every share is recorded with a recipient, a purpose, and a timestamp. Not a summary — every single share.
  2. Reads of sensitive PI are checked against a declared purpose. Field-level ACLs can require a purpose claim on the caller's JWT.
  3. Shares after an opt-out are stopped before they happen. Your sharing code has to check the opt-out; the engine does not provide an opt-out gate.

In InvariantDB, the first can be stored as graph data, the second can be enforced with field-level ACLs, and the third is application logic whose results you can store and query.

The §1798.135 opt-out

When a customer selects "Do Not Sell My Information," record the opt-out as a node with a timestamp. The engine does not provide an opt-out gate, so your sharing code has to check the opt-out before it shares data. If each share is also written to the graph, a query can compare share times with the opt-out time.

What the engine does record is each Cypher read that a field ACL denied and each search or node create it refused. If your ad-network integration uses its own credential, its refusals are one procedure call (the principal is fictional):

CALL db.aclEvents(0, 'apikey:ad-sync', 1000)
YIELD eventId, ts, principal, label, property, action, denied, reason
RETURN ts, principal, label, property, reason

The ACL event log lists denied accesses per principal, not per customer, and allowed reads are not logged. db.verifyAclChain() re-checks the log’s hash chain and reports the first event whose hash no longer matches.

The §1798.121 sensitive-PI purpose rules

Field-level ACLs can restrict each sensitive-PI field to callers whose JWT carries an allowed purpose. If a marketing system tries to read race or sexual orientation without an allowed purpose, a Cypher read returns null for that field and the denied read is recorded in the ACL event log. Allowed reads are not logged, so the log shows enforcement, not a full history of uses.

The ACL declarations in the schema history and the refusal log are the evidence you can show.

The numbers

CPPA fines start at $2,500 per unintentional violation and reach $7,500 per intentional violation. The catch is the "per resident" multiplier — if your integration leaked data on ten thousand customers, that's seventy-five million dollars. Once you add class-action liability on top, this becomes the single largest privacy-compliance risk a California consumer brand carries.

The walkthrough on the California tab shows the flow with illustrative data.

See the walkthrough

Step through the illustrative walkthrough.

The full illustrative flow, ending with the chain verification. It is pre-rendered, runs in any browser, and does not connect to an engine.

Open the California walkthrough →