Files
agentic-dev-template/docs/compliance
Danijel Martinek a74b7360e1 docs(compliance): document policy template convention in README and glossary
Add a "Policy templates" section to docs/compliance/README.md explaining
the docs/compliance/templates/ directory, the copy-to-compliance/ workflow,
the [FILL IN:] placeholder convention, and the verification one-liner.

Add four glossary entries: fill-in template, [FILL IN:] marker,
pre-launch compliance checklist, and compliance overview.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:49:50 +00:00
..

docs/compliance — reference examples for the compliance module

This folder contains annotated example files that document the schema used by the compliance generators. It is not the live compliance artifact directory.

Location Contents Edit manually?
docs/compliance/ (this folder) Schema examples and this README Yes — static reference
compliance/ (repo root) Live generated artifacts No — run the generators

What each file in compliance/ contains

compliance/data-map.yml

A field-level PII inventory derived from every Payload collection in the workspace.

For each collection the generator records:

  • auth — whether the collection has Payload authentication enabled
  • piiFields — every field carrying a custom.pii tag, plus Payload auth defaults (email, etc.) for auth collections

Each PII field entry captures the category (e.g. contact-email, identification-username), one or more purposes (e.g. account-authentication, service-delivery), whether the field is exportable (GDPR Art. 15) and restrictable (GDPR Art. 18), the source (field-tag, auth-default, or auth-override), and an optional per-field retention override.

See docs/compliance/data-map.example.yml for every field with annotations.

compliance/retention-policy.yml

A collection-level retention schedule derived from custom.retention blocks in Payload collection configs.

For each collection the generator records:

  • purgeSchedule — cadence for the background purge job (daily | weekly | monthly); required on every collection
  • activeRetention (optional) — how long to keep a live record before triggering deletion
  • coldArchive (optional) — long-term archive window for regulatory fixed-term obligations
  • postDeletion — what happens after a DSR erasure or account-closure request (hard-delete or pseudonymize with an ISO 8601 grace period)

See docs/compliance/retention-policy.example.yml for every field with annotations.

compliance/sub-processors.yml

An inventory of every third-party processor that receives personal data from this application. Entries come from two sources and are merged at emit time:

  1. Library decision traces (docs/library-decisions/*.md) — npm packages where is-sub-processor: true in the frontmatter.
  2. Manual entries (compliance/sub-processors.manual.yml) — non-npm vendors (REST APIs, SaaS integrations, infrastructure providers).

Each entry records the package name (sort key), data-sent description, region, dpa-signed and sccs-required booleans, a contact URL, the decision status, and a source discriminator (library-trace or manual).

See docs/compliance/sub-processors.example.yml for both entry kinds with annotations.


How the files are generated

All three artifacts are regenerated together:

pnpm compliance:emit-all

Or individually:

pnpm compliance:data-map          # writes compliance/data-map.yml
pnpm compliance:retention-policy  # writes compliance/retention-policy.yml
pnpm compliance:sub-processors    # writes compliance/sub-processors.yml

Each script also supports two diagnostic modes:

pnpm compliance:data-map -- --print   # write YAML to stdout (no file written)
pnpm compliance:data-map -- --check   # diff vs committed file; exit 1 on mismatch

--check mode is used by the pre-commit hook and CI drift gate to detect uncommitted changes to collection configs that would cause compliance/*.yml to drift from the source of truth.


Keeping compliance/*.yml up to date

Regenerate and commit the artifacts whenever you:

  • Add or modify a Payload collection in any feature package
  • Change custom.pii tags on collection fields
  • Change custom.retention blocks on collection configs
  • Add a library decision trace with is-sub-processor: true
  • Add or update entries in compliance/sub-processors.manual.yml

The pre-commit hook and CI gate run emit-all --check and will reject the commit or PR if the committed YAML is stale.


Annotating PII fields in a collection

Add custom.pii to any field in a Payload collection config:

{
  name: "phone",
  type: "text",
  custom: {
    pii: {
      category: "contact-phone",               // PiiCategory
      purpose: ["transactional-notifications"], // DataProcessingPurpose[]
      exportable: true,
      restrictable: true,
      // Optional per-field retention override:
      retention: {
        duration: "P1Y",                        // ISO 8601
        trigger: "from-last-access",            // "from-creation" | "from-last-access" | "after-deletion"
        action:  "hard-delete",                 // "hard-delete" | "pseudonymize"
      },
    },
  },
},

For auth collections, email is automatically classified via PAYLOAD_AUTH_PII_DEFAULTS. Override per-collection via custom.authPii:

{
  slug: "members",
  auth: true,
  custom: {
    authPii: {
      // Extend or replace the email default for this collection only:
      email: {
        category: "contact-email",
        purpose: ["account-authentication", "marketing-communications"],
        exportable: true,
        restrictable: true,
      },
    },
  },
}

See packages/core-shared/src/payload/pii-types.ts for the full list of allowed PiiCategory and DataProcessingPurpose values.


Annotating retention policy in a collection

Add custom.retention to the collection config. purgeSchedule is required on every collection; the other fields are optional:

{
  slug: "profiles",
  custom: {
    retention: {
      purgeSchedule: "daily",               // Required: "daily" | "weekly" | "monthly"
      activeRetention: {                    // Optional: expire live records
        duration: "P2Y",
        trigger: "from-last-access",
      },
      coldArchive: {                        // Optional: regulatory fixed-term archive
        duration: "P7Y",
        trigger: "from-creation",
      },
      postDeletion: {                       // Optional: override the default post-deletion behaviour
        action:   "pseudonymize",           // "hard-delete" | "pseudonymize"
        duration: "P30D",
        trigger:  "after-deletion",
      },
    },
  },
}

Registering a sub-processor

From an npm library (preferred)

Add sub-processor fields to the library's decision trace in docs/library-decisions/:

---
package: "@acme/notifications-sdk"
version: "^2.3.0"
decision: approved
is-sub-processor: true
data-sent: "user email address and display name for transactional notification delivery"
region: EU
dpa-signed: true
sccs-required: false
contact: https://acme-sdk.example/privacy/dpa
---

Run pnpm compliance:sub-processors to regenerate.

Non-npm vendors (REST APIs, SaaS, infrastructure)

Create compliance/sub-processors.manual.yml if it doesn't already exist and add an entry:

- package: acme-email-service # slug-style identifier (no @ prefix)
  version: "REST API v3"
  data-sent: "user email address and message body for transactional email delivery"
  region: EU
  dpa-signed: true
  sccs-required: false
  contact: https://acme-email.example/legal/dpa
  decision: approved

compliance/sub-processors.manual.yml is a hand-authored file committed to the repository alongside the generated compliance/sub-processors.yml. The generator merges manual entries at emit time and injects source: "manual" automatically. Do not add source: manually — it will be overwritten.

Run pnpm compliance:sub-processors after any change to regenerate compliance/sub-processors.yml.


Policy templates

The docs/compliance/templates/ directory contains fill-in-the-blank runbooks for the operational policies required before a GDPR-covered launch. These are template originals — do not edit them in place.

Copy-to-compliance/ workflow

  1. Copy the desired template from docs/compliance/templates/ to compliance/ (repo root):
    cp docs/compliance/templates/dsr-procedure.template.md compliance/dsr-procedure.md
    
  2. Open the copied file and replace every [FILL IN:] marker with the project-specific value.
  3. Commit the filled file to the repo as a live compliance artifact (same cadence as compliance/*.yml).

[FILL IN:] convention

Every placeholder that requires a project-specific value is marked with the literal string [FILL IN:] followed by a short description of what is expected. This makes placeholders machine-detectable and easy to audit.

To verify that all placeholders in your live artifacts have been resolved, run:

grep -rn '\[FILL IN:' compliance/

A zero-line result means all templates have been fully filled in. Any output identifies the file and line that still needs attention.


sccs-required guidance

Set sccs-required: true when:

  • The vendor's primary data-residency region is outside the EEA and
  • There is no EU adequacy decision covering that country (e.g. US before Privacy Shield replacement, India, most of Asia-Pacific)

Set sccs-required: false when:

  • The vendor is EU/EEA-resident, or
  • The vendor's country has a current EU adequacy decision, or
  • The data transfer is covered by Binding Corporate Rules

When sccs-required: true, ensure SCCs are incorporated in the DPA before marking dpa-signed: true.