GuidesCompliance gates

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

  1. ADA / accessibility — a Biome preset (@dscodotco/compliance-gates/biome) that enables the full a11y rule group at error level. Extend it from your biome.json, and a11y violations fail biome check.
  2. 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

CheckLaw it maps to
arlAutoRenewCA ARL / ROSCA / FTC Click-to-Cancel
ccpaPrivacyChoicesCCPA / CPRA
prop65CA Prop 65
canSpamFooterCAN-SPAM
ruoNoticeFDA RUO labeling / FTC
accessibilityStatementADA Title III / CA Unruh
noPreCheckedConsentROSCA / FTC negative-option
Biome presetADA / 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-check

It 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.