II.
Page JSON
Structured · livepage:library-data-privacy-compliance
Data Privacy Compliance (Library) json
Inspect the normalized record payload exactly as the atlas UI reads it.
{
"id": "page:library-data-privacy-compliance",
"_kind": "Page",
"_file": "wiki/library/data-privacy-compliance.md",
"_cluster": "wiki",
"attributes": {
"nodeKind": "Page",
"title": "Data Privacy Compliance (Library)",
"displayName": "Data Privacy Compliance (Library)",
"slug": "library/data-privacy-compliance",
"articlePath": "wiki/library/data-privacy-compliance.md",
"article": "\n# Data Privacy Compliance\n\nPrivacy operations lifecycle for DSAR (data-subject access request), erasure, and DPIA work: intake and identity verification, kip-reconciled data mapping, parallel multi-system retrieval, exemption analysis with mandatory legal bases, policy-gated deletion and disclosure, and deadline-audited closure — all inside statutory clocks. This specialization **complements** `security-compliance` and supersedes nothing.\n\nUse it when a data-subject request arrives (access, erasure, rectification, portability), when an erasure demands verified deletion across systems, or when a request surfaces new high-risk processing that needs a DPIA signed off.\n\n## Statutory clocks\n\nClocks are **frozen consts, not inputs** — there is deliberately no override knob. A statute is not configurable.\n\n| Clock | Duration | Legal basis | Starts from |\n|---|---|---|---|\n| `dsar` | 30 days | GDPR Art 12(3) / CCPA 1798.130 | **RECEIPT** (`request.receivedAt`), not verification |\n| `breach` | 72 hours | GDPR Art 33(1) | breach-indicator detection at intake |\n\nThe DSAR clock is started by the **orchestrator** the moment the process runs — before classification finishes, because the statute does not wait. If intake reports non-empty `breachIndicators`, a second 72-hour ledger clock opens and the run records a composition directive to run `specializations/domains/business/legal/data-breach-response` **by name** — this process never absorbs regulator notification.\n\n## Deadline-escalation map\n\nZone computed by `deadlineZone(nowMs, clockStartMs, deadlineMs)` from the remaining/total ratio: **comfortable** > 0.5, **warning** > 0.25, **critical** > 0, **breached** <= 0. Throws on non-finite inputs or a deadline at/before the clock start — no fallback zone.\n\n`DEADLINE_ESCALATION` (verbatim — the frozen const is the implementation):\n\n| Action | comfortable | warning | critical | breached |\n|---|---|---|---|---|\n| `data-deletion` | dpo | dpo | privacy-counsel | privacy-counsel |\n| `disclosure-response` | dpo | dpo | privacy-counsel | privacy-counsel |\n| `dpia-signoff` | privacy-counsel | privacy-counsel | privacy-counsel | privacy-counsel |\n\n`dpia-signoff` is not clock-driven; its row is kept total so lookups never miss. Lookups go through `deadlineExpert(actionId, zone)`, which **throws** on unknown actions and unknown zones — the exact analog of incident-lifecycle `routingExpert()`; no default expert exists.\n\n## Policy-gated actions\n\nConvention: **`breakpointId` = actionId**, expert from `deadlineExpert(actionId, currentZone())`, tags `['policy-gated','privacy','dsar'|'dpia', <zone>]`, strategy `single`, **never auto-approved** (no `autoApproveAfterN`, no `presentAlwaysApprove`). Any harness-level auto-approval is surfaced by `recordGate()` into the always-present `autoApprovals[]` output — fail-closed provenance, nothing auto-approves silently.\n\n| actionId | What it gates | Raised in |\n|---|---|---|\n| `data-deletion` | Irreversible deletion of personal data | P6, erasure branch only; one bounded re-plan round; second rejection halts with nothing deleted |\n| `disclosure-response` | Sending the disclosure package **or denial letter** to the data subject | P10, both outcomes; one bounded revise-and-re-gate round; unapproved -> withheld, fail closed |\n| `dpia-signoff` | Approving the privacy impact assessment | P9, only when `dpiaRequired` or `inputs.dpiaContext` |\n\nNon-policy breakpoints: `dpc.identity-verification.unverified` (P2, only on failed verification — genuinely blocking) and the combinator-owned `dpc.dsar-completeness.gate-escalation` (only on gate exhaustion).\n\n## Lifecycle walkthrough (P0–P11)\n\n- **P0 — kip recall** (kind `data-privacy`): data-map/system-of-record facts and DSAR precedents for the subject + jurisdiction, threaded into intake and the data-map refresh.\n- **P1 — DSAR intake + clock start**: orchestrator starts the 30-day clock from `request.receivedAt`; `assertRequestType` validates the classification; `non-dsar` exits early before verification or any gate; breach indicators open the 72-hour clock + composition directive.\n- **P2 — identity verification (fail-closed)**: failed verification raises the unverified breakpoint; rejected -> run refused with **closure audit still executed** (a refusal is still deadline-audited); approved -> recorded as an identity bypass that forces `success:false`.\n- **P3 — data-map refresh**: kip-recalled map reconciled against the live inventory (seeded from `data-mapping-inventory.js` discovery/classification/system-inventory slices). **Zero mapped systems throws** — there is no fallback system list.\n- **P4 — parallel multi-system retrieval**: one `dpc.system-retrieval` task per mapped system via `ctx.parallel.all`; the orchestrator diffs results against the map to compute `allSystemsSearched` (ground truth for the coverage critic).\n- **P5 — exemption analysis + branch assembly**: every withheld item must cite instrument + article + rationale (uncited withholding is schema-invalid). Access/rectification/portability -> disclosure package compiled (an all-withheld outcome compiles a **denial letter** riding the same schema and gates); erasure -> deletion plan whose every action carries the exact `verificationQuery` the gate later executes.\n- **P6 — data-deletion gate** (erasure only): never auto-approves; one re-plan round; second rejection returns with **nothing deleted** — the executor has no other invocation site.\n- **P7 — deletion execution**: only inside the `approved === true` branch; per-system outcomes reported honestly, ledgered by the orchestrator.\n- **P8 — adversarial completeness-and-exemption gate** (`dpc.dsar-completeness`): coverage-critic + exemption-critic, plus deletion-verification-critic on erasure, which **executes every verificationQuery** and requires zero records back. Nothing leaves until this gate passes (or the owner accepts via escalation).\n- **P9 — dpia-signoff gate** (conditional): DPIA drafted to `artifactsDir`, signed off by privacy-counsel at every zone; rejection blocks closure success only when the DPIA need came from the request's own processing.\n- **P10 — disclosure-response gate -> delivery**: both disclosure and denial ride the same gate; approved -> the package is delivered **verbatim** with a concrete `messageRef`; unapproved after one revise round -> withheld, recorded, fail closed.\n- **P11 — deadline-audited closure + kip assert**: `dpc.closure-audit` executes the deadline arithmetic against the orchestrator ledger; kip assert writes updated data-map facts, the DSAR precedent, and deletion outcomes.\n\n## Composition seeds\n\n- [`domains/business/legal/data-mapping-inventory.js`](../domains/business/legal/data-mapping-inventory.js) — **folded slice** (composition, NOT supersedes): discovery/classification/system-inventory folded into `dpc.data-map-refresh`.\n- [`domains/business/legal/data-breach-response.js`](../domains/business/legal/data-breach-response.js) — **composed by name** when `breachIndicators` fire the 72-hour clock; regulator notification stays in that process.\n\n## Module table — `dsar-lifecycle.js` exports\n\n| Export | Kind | Purpose |\n|---|---|---|\n| `process(inputs, ctx)` | orchestrator | The DSAR lifecycle, phases P0–P11 |\n| `STATUTORY_CLOCKS` | frozen const | 30-day DSAR / 72-hour breach clocks with legal bases |\n| `REQUEST_TYPES` | frozen const | `['access','erasure','rectification','portability']` |\n| `IDENTITY_VERIFICATION_METHODS` | frozen const | Allowed verification methods |\n| `DEADLINE_ZONES` | frozen const | `['comfortable','warning','critical','breached']` |\n| `DEADLINE_ESCALATION` | frozen const | Per-zone expert routing (lookup via `deadlineExpert`) |\n| `deadlineExpert(actionId, zone)` | helper | Escalation lookup — **throws** on unknown action/zone (no fallback expert) |\n| `deadlineZone(nowMs, clockStartMs, deadlineMs)` | helper | Zone computation — **throws** on non-finite inputs or deadline <= start |\n| `assertRequestType(value, source)` | helper | **Throws** on unknown request types; `'non-dsar'` passes as a classification outcome |\n| `dsarIntakeTask` | agent task | `dpc.dsar-intake` — classification, dsarId mint, breach indicators |\n| `identityVerificationTask` | agent task | `dpc.identity-verification` — executed checks, fail-closed |\n| `dataMapRefreshTask` | agent task | `dpc.data-map-refresh` — kip-reconciled inventory |\n| `systemRetrievalTask` | agent task | `dpc.system-retrieval` — per-system fan-out unit |\n| `exemptionAnalysisTask` | agent task | `dpc.exemption-analysis` — per-item legal bases |\n| `responseCompilationTask` | agent task | `dpc.response-compilation` — draft only, denial included |\n| `deletionPlanTask` | agent task | `dpc.deletion-plan` — plan only, verificationQuery per action |\n| `deletionExecutionTask` | agent task | `dpc.deletion-execution` — only after its gate approves |\n| `dpiaDraftTask` | agent task | `dpc.dpia-draft` — DPIA markdown |\n| `responseDeliveryTask` | agent task | `dpc.response-delivery` — only after its gate approves |\n| `closureAuditTask` | agent task | `dpc.closure-audit` — executed deadline arithmetic |\n\nGate combinators (`routedBreakpoint`, `adversarialGate`, `kipRecall`, `kipAssert`) are imported from [`../common-utilities/routed-gate-combinators.js`](../common-utilities/routed-gate-combinators.js), not redefined.\n\n## Inputs / outputs reference\n\n**Inputs**: `request { receivedAt (ISO, REQUIRED — starts the statutory clock), channel, subject { name, email, identifiers? }, rawText }`, `requestTypeOverride?`, `jurisdiction` (`'gdpr'|'ccpa'|string`, REQUIRED), `dpiaContext?`, `maxFixAttempts?` (default 2), `kipEnabled?` (default true), `kipDir?` (default `.a5c/kip`), `kipModel?` (default `sonnet`), `artifactsDir?`. Missing `request.receivedAt`/`subject` **throws** — the process refuses to guess when a statutory clock started.\n\n**Outputs**: `success`, `dsarId`, `requestType`, `identityVerified`, `clock { startedAt, deadlineAt, zoneAtClosure, breached, ledger[] }`, `dataMap { systems, discrepancies, dpiaRequired }`, `retrieval { perSystem[], allSystemsSearched }`, `withheld[]`, `deletion { plan, executed, verified } | null`, `disclosure { sent, deliveredAt, messageRef } | null`, `dpia { required, path, signedOff } | null`, `completenessGate { passed, attempts, escalated, issues }`, `autoApprovals[]` (ALWAYS present — fail-closed provenance), `kipFactsAsserted`, `slaBreaches[]`, `artifacts[]`, `metadata { processId, runId, clockLedger, breakpointsHit }`.\n\n## Hard rules\n\n- **No fallbacks**: `assertRequestType`, `deadlineZone`, and `deadlineExpert` all throw on unknown values; an empty data map throws; missing `request.receivedAt` throws. There is no default expert, zone, request type, or system list anywhere.\n- **Fail-closed gates**: deletion and disclosure never execute via any ungated path. `dpc.deletion-execution` and `dpc.response-delivery` are invoked only inside the `approved === true` branches of their gates; no retry, recovery, or closure path calls them otherwise.\n- **Style-A agent-only**: every task is `kind: 'agent'` (zero `kind: 'shell'`), with per-effect `io` paths and `labels`, and every evidence-carrying output schema declares `evidence { type: 'array', minItems: 1 }`.\n- **Orchestrator-owned clock ledger**: the ledger is accumulated in the orchestrator, never inside agents, so the deadline auditor and gate critics diff against ground truth the agents cannot rewrite.\n\n## Validation\n\nESM import check from the repo root (resolves the `../common-utilities` import and `@a5c-ai/babysitter-sdk`):\n\n```bash\nnode --input-type=module -e \"await import('./library/specializations/data-privacy-compliance/dsar-lifecycle.js')\"\n```\n\nThen confirm the exported consts are frozen and the lookups throw:\n\n```bash\nnode --input-type=module -e \"\nconst m = await import('./library/specializations/data-privacy-compliance/dsar-lifecycle.js');\nif (!Object.isFrozen(m.STATUTORY_CLOCKS) || !Object.isFrozen(m.DEADLINE_ESCALATION)) throw new Error('consts not frozen');\ntry { m.deadlineExpert('data-deletion', 'nope'); throw new Error('should have thrown'); } catch (e) { if (!/unknown deadline zone/.test(e.message)) throw e; }\ntry { m.assertRequestType('bogus', 'test'); throw new Error('should have thrown'); } catch (e) { if (!/Unknown requestType/.test(e.message)) throw e; }\nconsole.log('ok');\n\"\n```\n",
"documents": [
"specialization:data-privacy-compliance"
]
},
"outgoingEdges": [
{
"from": "page:library-data-privacy-compliance",
"to": "specialization:data-privacy-compliance",
"kind": "documents"
}
],
"incomingEdges": [
{
"from": "page:index",
"to": "page:library-data-privacy-compliance",
"kind": "contains_page"
}
]
}