One thesis: the driver's-license barcode is the one scheme in the registry where the governing text is not an identifier standard but criminal statute — so the correct product behavior is a refusal, enforced in the same machinery that enforces every other license class, and this post exists so your security review can verify the refusal instead of taking our word for it.
Every US and Canadian driver's license carries a PDF417 barcode whose payload follows the AAMVA DL/ID card design standard: a header, then tagged data elements — license number, name, date of birth, expiry, address, physical descriptors. Decoding it is trivial; every barcode SDK on Earth does it. Which is exactly the problem. The payload is a machine-readable dossier of personally identifiable information sitting on a card people hand to strangers, and an identifier platform has to decide — before the first scan — what it will refuse to do with it.
What the law actually says
The rule is not ours and it is not soft. California Civil Code §1798.90.1 permits swiping a driver's license only for enumerated purposes — verifying age or the authenticity of the license, and specified fraud-prevention uses — and prohibits retaining or using the information beyond them. Violation is a misdemeanor, punishable by up to one year and a $10,000 fine. California is one statute among a patchwork of state laws in the same shape, and the patchwork's common floor is the design constraint: check, then forget. A platform serving all fifty states builds to the strictest common reading, because "we store it, but only in the states where that's lawful" is not an architecture — it is a deposition waiting to happen.
The legitimate uses are real: age gating at delivery, license-authenticity checks at rental counters, form-fill with the holder present and consenting. All of them share one property — they need the parse now and the data never.
Policy as shipped data, not as policy document
The scheme registry row for AAMVA payloads carries the rule as an enforced flag, in the same pinned schemes/*.json file that carries its grammar:
{
"scheme": "dl-aamva",
"carrier": "pdf417",
"grammar": "aamva-dl-id",
"policy": {
"retention": "no_retention",
"enrich": "refused",
"basis": "state statutes incl. Cal. Civ. Code §1798.90.1"
}
}
This is the identical machinery that enforces license classes on every enrichment attribute — the mechanism that keeps a display-only attribute out of a storage-scoped response is the mechanism that keeps this scheme out of the answer layer entirely. no_retention is not a comment; it is an enum the verbs dispatch on.
Concretely:
$ barcoding resolve '@…ANSI 636014…DAQD1234562<…>' --json
{"scheme":"dl-aamva","parsed":{"jurisdiction":"…","expiry":"…","age_over_21":true, …},
"policy":"no_retention — output is local; nothing was transmitted or stored"}
$ barcoding enrich dl-aamva:…
{"error":{"code":"policy_refusal",
"message":"scheme dl-aamva carries no_retention; enrich is refused by design",
"hint":"resolve runs locally for parse/verify use only (age, authenticity)"}}
exit 1
resolve is pure and local — the payload is parsed in your process, on your machine, and goes nowhere, because resolve has no network path for any scheme. The refusal on enrich is typed, deterministic, and permanent. There is no flag to override it, no enterprise tier where it relaxes, and — unusually for this site — no onboarding path for this scheme. Nothing gated is coming later. The refusal is the finished feature.
Why "we could store it" is not a product question
A security reviewer has seen the alternative pitch: hash it, encrypt it, tokenize it, retain "only" derived fields. Each variant fails the same two tests. Legally, statutes in this family regulate the information from the license, not a storage format — a derived retention is a retention. Architecturally, data you hold is data you must defend, disclose, and eventually regret; data you structurally cannot hold is a questionnaire section that answers itself. The strongest security posture available to a barcode platform on this scheme is the boring one: be provably incapable of the harm. An open verb surface plus a published policy flag in a pinned registry file is that proof — you can read the row, run the refusal, and confirm the parse path has no transport.
The paragraph for your compliance team
Copy-paste, edit the bracketed part:
[Product] uses barcoding.dev's
resolveverb to parse AAMVA PDF417 driver's-license barcodes locally, for age and license-authenticity verification with the holder present. The parse executes on-device/in-process; barcoding.dev'sresolveverb performs no network transmission for any scheme. The AAMVA scheme row in barcoding.dev's pinned scheme registry carries a hardno_retentionpolicy flag: enrichment and storage verbs refuse driver's-license data by design, with a typed machine-readable error. Basis: state license-swiping statutes including Cal. Civ. Code §1798.90.1. No driver's-license data is transmitted to, stored by, or recoverable from barcoding.dev.
The registry row is /schemes/dl-aamva; the same policy-flag machinery, applied to enrichment licensing rather than statute, is how every attribute on this platform travels with its permissions attached — the provenance-envelope design that the rest of this site's answer layer is built on. Different rows, different rules, one enforcement engine. That uniformity is the actual answer to the questionnaire: this platform does not have a privacy feature bolted onto a data product; it has a license-and-policy engine that a data product happens to run inside.
Verify the refusal yourself: npx barcoding.dev resolve on your own license, watch the parse stay local, then run enrich on the result and read the exit code. A refusal you can reproduce is worth a stack of assurances you cannot.
Keys open the network half of the verb set. Get an API key — say what arrives at your door, and the provisioning order follows the list.
We answer in writing. We take at most five conversations a month, only when you ask for one, and only after you already have the written read.