Satisfy the compliance gates
The compliance gates turn well-known consumer-protection requirements — the
disclosures, links, and warnings that draw lawsuits when they go missing — into
build gates. They run in the pre-commit hook and in the CI verify job, so a
required disclosure cannot silently disappear from a surface you ship.
This is developer and CI tooling, not a runtime API and not a per-store setting.
There is no fdk_ credential involved. If you build a storefront or portal
surface on the platform, these gates are how you prove the required elements are
present in your code. They enforce presence, not legal sufficiency — counsel
still signs off on the actual wording.
The two halves
- ADA / accessibility — a Biome preset
(
@dscodotco/compliance-gates/biome) that enables the fulla11yrule group at error level. Extend it from yourbiome.json, and a11y violations failbiome check. - Content gates — a config-driven CLI (
compliance-check) that scans your source for the required elements and exits non-zero on any violation.
What each gate checks
| Check | Law it maps to |
|---|---|
arlAutoRenew | CA ARL / ROSCA / FTC Click-to-Cancel |
ccpaPrivacyChoices | CCPA / CPRA |
prop65 | CA Prop 65 |
canSpamFooter | CAN-SPAM |
ruoNotice | FDA RUO labeling / FTC |
accessibilityStatement | ADA Title III / CA Unruh |
noPreCheckedConsent | ROSCA / FTC negative-option |
| Biome preset | ADA / a11y |
Each content check is one of three kinds:
- required-somewhere — at least one file in the globs contains one of the accepted patterns.
- conditional — any file matching a trigger must also contain a required element.
- forbidden — no file may contain a banned pattern.
A required-somewhere or conditional check whose globs match zero files
fails (“gate scoped to nothing”). A gate pointed at a path that does not
exist, or whose target file was deleted, must never read as green.
Configure and run
Declare your checks
Create a compliance.config.ts and list the checks that apply to the surfaces
in your package, each scoped to the globs it must scan.
// compliance.config.ts
import {
arlAutoRenew, ccpaPrivacyChoices, prop65, canSpamFooter, ruoNotice,
accessibilityStatement, noPreCheckedConsent, type ComplianceConfig,
} from "@dscodotco/compliance-gates";
export const config: ComplianceConfig = {
checks: [
ccpaPrivacyChoices(["surfaces/**/footer*.tsx", "surfaces/**/layout*.tsx"]),
arlAutoRenew(["surfaces/**/checkout/**"]),
prop65(["surfaces/**/product/**"]),
canSpamFooter(["modules/comms/src/**", "modules/marketing/src/index.ts"]),
ruoNotice(["surfaces/storefront/**"]),
noPreCheckedConsent(["surfaces/**"]),
],
};Enable the a11y preset
Extend the Biome preset from your biome.json so accessibility violations fail
biome check:
{ "extends": ["@dscodotco/compliance-gates/biome"] }Run the check
compliance-checkIt exits 1 on any violation and names what is missing and where. The same
command runs in CI as pnpm check:compliance, and the checks are gating — there
is no admin bypass.
What a surface must satisfy
For a storefront that sells subscriptions, sends marketing email, and lists RUO products, the practical checklist is: a CCPA privacy-choices link in the footer, ARL auto-renewal disclosure in the checkout flow, a Prop 65 warning on product pages, a CAN-SPAM footer on outbound mail, the RUO research-use notice, no pre-checked consent boxes, and an accessibility statement. Wire the matching checks to the globs where those elements live, and keep them pointed at real files — a deleted target is a failing gate, by design.
The gates documented here are the mechanically enforced subset of a broader, internally maintained compliance program.
Related
- Compliance reference — the check kinds and covered categories in full.