Adopting the GDPR and HIPAA compliance packs
Add structured linting for GDPR Art. 28/30/35 documentary artifacts and the HIPAA Security Rule BAA register to a ctxgrd-enabled repository.
What ctxgrd checks – and what it does not
ctxgrd checks the existence, required metadata, freshness, and cross-references of your compliance paper artifacts. It does not evaluate legal adequacy, determine whether processing was lawful, or verify that a safeguard actually operated. Substantive compliance is counsel’s domain.
Prerequisites
ctxgrd0.41.0 or later.- A
ctxgrd.tomlin the repository root. If none exists, runctxgrd pack add project-docsto create a baseline.
Adopt the GDPR pack
1. Add the pack
ctxgrd pack add gdpr
pack add gdpr automatically resolves the security base pack (which defines
the POLICY, RISK, and VULN namespaces reused across compliance programs)
and writes both packs’ namespace blocks into ctxgrd.toml in dependency order.
You do not need a separate pack add security step.
Each block carries a provenance comment so pack outdated and pack migrate
can track it:
# pack: [email protected] sha:…
[POLICY]
…
# pack: [email protected] sha:…
[ROPA]
…
To preview what would be written without touching ctxgrd.toml:
ctxgrd pack add gdpr --dry-run
2. Understand the namespaces
The gdpr pack defines three namespaces, all path-claimed under
docs/compliance/gdpr/.
| Namespace | Path glob | Regulation article |
|---|---|---|
ROPA |
docs/compliance/gdpr/ropa/** |
Art. 30 – records of processing activities |
DPIA |
docs/compliance/gdpr/dpia/** |
Art. 35 – data protection impact assessments |
DPA |
docs/compliance/gdpr/dpa/** |
Art. 28 – processor / subprocessor agreement register |
3. Author a ROPA record
A ROPA entry requires id, title, status, controller_or_processor,
lawful_basis, data_categories, and retention. The closed vocabulary for
controller_or_processor is controller, processor, or joint-controller.
The closed vocabulary for lawful_basis matches the six Art. 6(1) bases:
consent, contract, legal_obligation, vital_interests, public_task, or
legitimate_interests.
Create a file at docs/compliance/gdpr/ropa/customer-crm.md:
---
id: ROPA-001
title: Customer CRM data processing
status: active
controller_or_processor: controller
lawful_basis: contract
data_categories: name, email, phone
retention: 7 years post-contract
---
# Customer CRM data processing
Processing activities for customer relationship management data.
Run the linter:
ctxgrd
A missing or invalid lawful_basis is caught by core.allowed-values at the
ROPA namespace. An absent required field is caught by core.required-metadata.
4. The processor – DPA cross-reference rule
When controller_or_processor is processor, the gdpr.processor-dpa rule
requires the ROPA entry to cross-reference the governing DPA record. The
cross-reference may appear in depends_on frontmatter or as a body reference to
a DPA-<number> ID.
First, create the DPA record at docs/compliance/gdpr/dpa/hosting-provider.md:
---
id: DPA-001
title: Hosting provider data processing agreement
status: executed
party: Acme Hosting Ltd
executed_date: 2025-01-15
---
Then reference it from the processor ROPA:
---
id: ROPA-002
title: Analytics processing on behalf of client
status: active
controller_or_processor: processor
lawful_basis: contract
data_categories: usage events
retention: 90 days
depends_on: [DPA-001]
---
5. Author a DPIA
A DPIA requires id, title, status, and reviewed_date. The
core.calendar-freshness rule flags a DPIA whose reviewed_date is more than
365 days in the past.
---
id: DPIA-001
title: High-risk analytics pipeline assessment
status: active
reviewed_date: 2026-01-10
depends_on: [ROPA-002]
---
The depends_on cross-reference to the ROPA activity it assesses is checked by
core.cross-ref. A DPIA with a stale reviewed_date produces a
core.calendar-freshness diagnostic.
6. Lint and iterate
ctxgrd
ctxgrd --format json | jq '.[] | select(.code | startswith("gdpr"))'
Adopt the HIPAA pack
1. Add the pack
ctxgrd pack add hipaa
As with gdpr, pack add hipaa automatically pulls in the security base pack
first.
2. Understand the namespaces
The hipaa pack defines two namespaces under docs/compliance/hipaa/.
| Namespace | Path glob | Regulation section |
|---|---|---|
SAFEGUARD |
docs/compliance/hipaa/safeguards/** |
45 CFR 164.308/310/312 – Security Rule safeguard register |
BAA |
docs/compliance/hipaa/baa/** |
45 CFR 164.308(b)(1) / 164.314 – Business Associate Agreement register |
3. Author a BAA record
A BAA entry requires id, title, status, party, executed_date, and
reviewed_date. The core.calendar-freshness rule flags a BAA whose
reviewed_date is more than 365 days in the past.
Create docs/compliance/hipaa/baa/lab-results-vendor.md:
---
id: BAA-001
title: Lab results processing vendor BAA
status: executed
party: MedData Systems Inc
executed_date: 2025-03-01
reviewed_date: 2026-03-01
---
# Lab results processing vendor BAA
Business Associate Agreement with MedData Systems Inc for processing lab
result data.
A BAA whose reviewed_date is stale produces a core.calendar-freshness
diagnostic pointing to that field.
4. Map a safeguard to its evidence
The SAFEGUARD namespace carries the Security Rule safeguard-to-evidence register
(45 CFR 164.308/310/312). A mapping requires id, title, status, and
safeguard, where safeguard is drawn from the closed catalog of 42 Security
Rule implementation specifications (e.g. 164.308.risk_analysis,
164.312.encryption_decryption) – core.allowed-values flags a mistyped or
non-existent safeguard id.
The hipaa.safeguard-evidence rule then checks that the mapping points at
implementing evidence:
- Every in-scope safeguard must cross-reference a
POLICYor an ADR (viadepends_onor a body reference to its id). - A Required safeguard must have that evidence – no exceptions.
- An Addressable safeguard may instead carry a
justificationfield recording why an equivalent (or no) control is reasonable. The rule knows which safeguards are Addressable from the catalog: the generator projects the Required/Addressable flag from the regulation extract into the rule’s configuration.
A Required safeguard backed by a policy – create
docs/compliance/hipaa/safeguards/risk-analysis.md:
---
id: SAFEGUARD-001
title: Risk analysis safeguard mapping
status: active
safeguard: 164.308.risk_analysis
depends_on: [POLICY-004]
---
# Risk analysis safeguard mapping
Implemented by our information-security risk-analysis policy.
An Addressable safeguard documented as not implemented – create
docs/compliance/hipaa/safeguards/automatic-logoff.md:
---
id: SAFEGUARD-002
title: Automatic logoff safeguard mapping
status: active
safeguard: 164.312.automatic_logoff
justification: Workstations are single-tenant kiosks in a locked facility; session timeout is enforced at the OS image layer instead.
---
The same justification on a Required safeguard would still be flagged –
hipaa.safeguard-evidence only accepts it for Addressable specifications.
Regenerating a pack from a regulation change
Each compliance pack’s pack.toml is generated from a canonical structured
extract at packs/<regulation>/regulation.json. If the regulation changes – for
example, the HIPAA catalog is updated or a new Art. 6 lawful basis is added –
update the extract and regenerate:
cargo run --example gen_compliance_pack -- gdpr
cargo run --example gen_compliance_pack -- hipaa
Review the diff to confirm only the expected vocabulary or metadata changed, then apply the updated pack to your config:
ctxgrd pack migrate
Verify the config is clean
After adding either pack, run ctxgrd from the repo root to confirm no configuration errors:
ctxgrd
A cfg.rule-unknown diagnostic means the installed binary predates a rule in
ctxgrd.toml. Reinstall the binary to match the config version.
Next steps
- Rule packs – the full built-in pack catalog.
- Configuring namespaces – path claims and claim precedence.
- Keeping adopted packs current – migrating pack definitions after a ctxgrd upgrade.