@zanii/compliance 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,42 +1,44 @@
1
- # @zanii/compliance
2
-
3
- Turn a Zanii **audit bundle** into an auditor-ready compliance report — verified
4
- offline, no network, no trust in Zanii's servers. Action breakdown by control,
5
- on-chain anchoring coverage, and a Markdown renderer you can hand straight to an
6
- auditor.
7
-
8
- ```sh
9
- npm install @zanii/compliance
10
- ```
11
-
12
- ## Usage
13
-
14
- ```ts
15
- import { buildComplianceReport, renderComplianceMarkdown } from '@zanii/compliance';
16
-
17
- // bundle = the JSON from `zanii export <did>` (or GET /v1/export/<did>)
18
- const report = buildComplianceReport(bundle, {
19
- controls: {
20
- crm: 'AC-2 Account Management',
21
- email: 'AU-2 Audit Events',
22
- pay: 'SC-13 Cryptographic Protection',
23
- },
24
- });
25
-
26
- console.log(report.verified, report.flags); // false-verified bundles still summarize, with a flag
27
- console.log(renderComplianceMarkdown(report)); // → hand to the auditor
28
- ```
29
-
30
- `buildComplianceReport` verifies the bundle with `@zanii/core` first; every figure
31
- is derived from the receipts, and anything an auditor should notice (failed
32
- verification, unanchored receipts, revoked delegations, unmapped namespaces)
33
- lands in `report.flags`.
34
-
35
- ## Changelog
36
-
37
- - **0.2.0** — added `reconcile` (provider-vs-ledger omission catcher).
38
- - **0.1.0** — initial release: `buildComplianceReport`, `renderComplianceMarkdown`, `ControlMap`.
39
-
40
- ## License
41
-
42
- Apache-2.0.
1
+ # @zanii/compliance
2
+
3
+ Turn a Zanii **audit bundle** into an auditor-ready compliance report — verified
4
+ offline, no network, no trust in Zanii's servers. Action breakdown by control,
5
+ on-chain anchoring coverage, and a Markdown renderer you can hand straight to an
6
+ auditor.
7
+
8
+ ```sh
9
+ npm install @zanii/compliance
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import { buildComplianceReport, renderComplianceMarkdown } from '@zanii/compliance';
16
+
17
+ // bundle = the JSON from `zanii export <did>` (or GET /v1/export/<did>)
18
+ const report = buildComplianceReport(bundle, {
19
+ controls: {
20
+ crm: 'AC-2 Account Management',
21
+ email: 'AU-2 Audit Events',
22
+ pay: 'SC-13 Cryptographic Protection',
23
+ },
24
+ });
25
+
26
+ console.log(report.verified, report.flags); // false-verified bundles still summarize, with a flag
27
+ console.log(renderComplianceMarkdown(report)); // → hand to the auditor
28
+ ```
29
+
30
+ `buildComplianceReport` verifies the bundle with `@zanii/core` first; every figure
31
+ is derived from the receipts, and anything an auditor should notice (failed
32
+ verification, unanchored receipts, revoked delegations, unmapped namespaces)
33
+ lands in `report.flags`.
34
+
35
+ ## Changelog
36
+
37
+ - **0.2.3** — Framework mappings (`mapToFramework`: EU AI Act, ISO/IEC 42001, NIST AI RMF, SOC 2, DORA, NIS2, HIPAA, PCI DSS 4.0, GDPR), each control met / partial / not-evidenced with the evidence stated; `controlTimeline`, provably random `sampleSelector`, `exceptionRegister` with remediations, an AI Act Annex IV `aiActTechnicalFile` draft, `incidentReport` with deadlines, `postMarketMonitoring`, signed control-owner attestations, JSON-LD `regulatorExport` and an offline `renderAuditorPortal`.
38
+ - **0.2.2** — now depends on `@zanii/core` 0.5 (protocol 1.2), so it shares one core with `@zanii/sdk` 0.5 instead of pulling in a second, older copy. No API change.
39
+ - **0.2.0** — added `reconcile` (provider-vs-ledger omission catcher).
40
+ - **0.1.0** — initial release: `buildComplianceReport`, `renderComplianceMarkdown`, `ControlMap`.
41
+
42
+ ## License
43
+
44
+ Apache-2.0.
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Control-by-control evidence for the frameworks auditors ask about, computed from a
3
+ * verified audit bundle. "met" means the log carries evidence for the control; it is
4
+ * evidence for an auditor, never a certification. Controls the log cannot evidence are
5
+ * reported as `not-evidenced`, not as failed or passed.
6
+ */
7
+ import { type AuditBundle, type SignedObject } from '@zanii/core';
8
+ import { type Regime } from '@zanii/regulator';
9
+ export type Framework = 'eu-ai-act' | 'iso42001' | 'nist-ai-rmf' | 'soc2' | 'dora' | 'nis2' | 'hipaa' | 'pci4' | 'gdpr';
10
+ export type ControlStatus = 'met' | 'partial' | 'not-evidenced';
11
+ export interface ControlResult {
12
+ id: string;
13
+ title: string;
14
+ status: ControlStatus;
15
+ evidence: string;
16
+ }
17
+ /** Evidence per control for one framework. */
18
+ export declare function mapToFramework(bundle: AuditBundle, framework: Framework): {
19
+ framework: Framework;
20
+ verified: boolean;
21
+ controls: ControlResult[];
22
+ };
23
+ /** Re-evaluate the framework window by window: a control that slips shows up when it slipped. */
24
+ export declare function controlTimeline(bundles: Array<{
25
+ period: string;
26
+ bundle: AuditBundle;
27
+ }>, framework: Framework): {
28
+ period: string;
29
+ verified: boolean;
30
+ met: number;
31
+ total: number;
32
+ gaps: string[];
33
+ }[];
34
+ /**
35
+ * A provably random audit sample: commit the seed before seeing the population, then
36
+ * draw. The auditor can redo the draw from the seed.
37
+ */
38
+ export declare function sampleSelector(bundle: AuditBundle, n: number, seed?: string): {
39
+ seed: string;
40
+ commitment: string | undefined;
41
+ sample: {
42
+ hash: string;
43
+ index: number;
44
+ }[];
45
+ };
46
+ /** Every exception an auditor should see, with any remediation recorded against it. */
47
+ export declare function exceptionRegister(bundle: AuditBundle, remediations?: Array<{
48
+ exception: string;
49
+ action: string;
50
+ by: string;
51
+ ts: string;
52
+ }>): {
53
+ open: number;
54
+ exceptions: {
55
+ id: string;
56
+ description: string;
57
+ remediation: (typeof remediations)[number] | null;
58
+ }[];
59
+ };
60
+ /** EU AI Act Annex IV technical documentation, drafted from what you supply plus what the log proves. */
61
+ export declare function aiActTechnicalFile(system: {
62
+ name: string;
63
+ provider: string;
64
+ intendedPurpose: string;
65
+ version: string;
66
+ humanOversight: string;
67
+ accuracyMetrics?: Record<string, string>;
68
+ }, bundle: AuditBundle): string;
69
+ /** An incident report skeleton with the regime's deadlines and the receipts it concerns. */
70
+ export declare function incidentReport(incident: {
71
+ id: string;
72
+ summary: string;
73
+ awareAt: string;
74
+ receipts: string[];
75
+ }, regime: Regime): {
76
+ deadlines: import("@zanii/regulator").Deadline[];
77
+ evidence: string[];
78
+ id: string;
79
+ summary: string;
80
+ awareAt: string;
81
+ receipts: string[];
82
+ regime: Regime;
83
+ };
84
+ /** Trend across monitoring periods: activity, share of high-risk actions, guard decisions, failures. */
85
+ export declare function postMarketMonitoring(periods: Array<{
86
+ period: string;
87
+ bundle: AuditBundle;
88
+ }>): {
89
+ period: string;
90
+ verified: boolean;
91
+ actions: number;
92
+ highRiskShare: number;
93
+ guardDecisions: number;
94
+ incidents: number;
95
+ }[];
96
+ export type ControlAttestation = SignedObject<{
97
+ v: 1;
98
+ type: 'compliance.attestation';
99
+ control: string;
100
+ period: string;
101
+ statement: string;
102
+ ts: string;
103
+ }>;
104
+ /** A control owner's signed quarterly attestation. */
105
+ export declare function attestControl(input: {
106
+ control: string;
107
+ period: string;
108
+ statement: string;
109
+ ts?: string;
110
+ }, ownerPrivateKey: Uint8Array): ControlAttestation;
111
+ export declare function verifyControlAttestation(a: ControlAttestation, ownerDid?: string): boolean;
112
+ /** A framework mapping as JSON-LD for machine submission. */
113
+ export declare function regulatorExport(mapping: ReturnType<typeof mapToFramework>, agent: string): {
114
+ '@context': {
115
+ '@vocab': string;
116
+ schema: string;
117
+ };
118
+ '@type': string;
119
+ agent: string;
120
+ framework: Framework;
121
+ verified: boolean;
122
+ controls: {
123
+ '@type': string;
124
+ identifier: string;
125
+ name: string;
126
+ status: ControlStatus;
127
+ evidence: string;
128
+ }[];
129
+ };
130
+ /**
131
+ * A single offline HTML file for an auditor: the framework mapping plus the full bundle
132
+ * embedded, so they can re-verify it with any Zanii verifier (or the /verify-bundle page).
133
+ */
134
+ export declare function renderAuditorPortal(bundle: AuditBundle, frameworks: Framework[]): string;
135
+ //# sourceMappingURL=frameworks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks.d.ts","sourceRoot":"","sources":["../src/frameworks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Control-by-control evidence for the frameworks auditors ask about, computed from a
3
+ * verified audit bundle. "met" means the log carries evidence for the control; it is
4
+ * evidence for an auditor, never a certification. Controls the log cannot evidence are
5
+ * reported as `not-evidenced`, not as failed or passed.
6
+ */
7
+ import { jcsHash, signObject, verifyAuditBundle, verifySignedObject } from '@zanii/core';
8
+ import { commitSeed, drawSample, incidentClock } from '@zanii/regulator';
9
+ const targetOf = (r) => r.target ?? r.body?.target ?? '';
10
+ function facts(bundle) {
11
+ const report = verifyAuditBundle(bundle);
12
+ const targets = bundle.receipts.map((b) => targetOf(b.receipt));
13
+ const s = report.stats;
14
+ const days = s.first_ts && s.last_ts ? (Date.parse(s.last_ts) - Date.parse(s.first_ts)) / 86_400_000 : 0;
15
+ return {
16
+ report, verified: report.ok,
17
+ chainOk: !!report.checks.find((c) => /chain/i.test(c.label))?.ok,
18
+ anchoredAll: s.anchored_through !== null && s.anchored_through >= Math.max(...bundle.receipts.map((r) => r.index), 0),
19
+ receipts: targets.length, days, targets,
20
+ oversight: targets.filter((t) => /confirm|approv|takeover|handback|review/i.test(t)).length,
21
+ guard: targets.filter((t) => t.startsWith('zanii.guard.')).length,
22
+ incidents: targets.filter((t) => /incident|estop|break-glass/i.test(t)).length,
23
+ revocations: s.revoked_certs,
24
+ highRisk: bundle.receipts.filter((b) => ['high', 'critical'].includes(b.receipt.risk)).length,
25
+ };
26
+ }
27
+ const c = (id, title, status, evidence) => ({ id, title, status, evidence });
28
+ const logs = (f) => f.verified && f.chainOk ? (f.anchoredAll ? 'met' : 'partial') : 'not-evidenced';
29
+ const logsText = (f) => `${f.receipts} signed, hash-chained records; offline verification ${f.verified ? 'passed' : 'FAILED'}; ${f.anchoredAll ? 'all anchored on-chain' : 'not all anchored yet'}`;
30
+ const oversight = (f) => (f.oversight > 0 ? 'met' : f.highRisk === 0 ? 'partial' : 'not-evidenced');
31
+ const oversightText = (f) => `${f.oversight} human confirmation / review records for ${f.highRisk} high-risk actions`;
32
+ const FRAMEWORKS = {
33
+ 'eu-ai-act': (f) => [
34
+ c('Art. 12', 'Record-keeping: automatic logging over the lifetime of the system', logs(f), logsText(f)),
35
+ c('Art. 14', 'Human oversight', oversight(f), oversightText(f)),
36
+ c('Art. 19 / 26(6)', 'Keep automatically generated logs for at least six months', f.days >= 182 ? 'met' : 'partial', `records span ${Math.round(f.days)} days`),
37
+ c('Art. 72', 'Post-market monitoring', f.guard > 0 ? 'met' : 'partial', `${f.guard} runtime security decisions recorded`),
38
+ c('Art. 73', 'Reporting of serious incidents', f.incidents > 0 ? 'partial' : 'not-evidenced', `${f.incidents} incident-type records; reporting itself happens outside the log`),
39
+ ],
40
+ iso42001: (f) => [
41
+ c('Clause 8.1', 'Operational planning and control', f.revocations >= 0 && f.verified ? 'met' : 'not-evidenced', 'every action carries the owner-signed delegation it ran under'),
42
+ c('Clause 9.1', 'Monitoring, measurement, analysis and evaluation', logs(f), logsText(f)),
43
+ c('Clause 10.2', 'Nonconformity and corrective action', f.incidents > 0 ? 'partial' : 'not-evidenced', `${f.incidents} incident records`),
44
+ ],
45
+ 'nist-ai-rmf': (f) => [
46
+ c('GOVERN', 'Accountability structures are in place', f.verified ? 'met' : 'not-evidenced', 'actions are attributable to agents and owners through signed delegations'),
47
+ c('MEASURE', 'AI risks are tracked', f.highRisk > 0 || f.guard > 0 ? 'met' : 'partial', `${f.highRisk} risk-labelled high/critical actions, ${f.guard} guard decisions`),
48
+ c('MANAGE', 'Risks are responded to', f.revocations > 0 || f.incidents > 0 ? 'met' : 'partial', `${f.revocations} revocations, ${f.incidents} incident records`),
49
+ ],
50
+ soc2: (f) => [
51
+ c('CC6.1', 'Logical access controls', f.verified ? 'met' : 'not-evidenced', 'scoped, expiring delegations; revocation recorded'),
52
+ c('CC7.2', 'Monitoring of system components for anomalies', f.guard > 0 ? 'met' : 'partial', `${f.guard} guard decisions; complete activity log`),
53
+ c('CC8.1', 'Change management', f.targets.some((t) => t.includes('evolution') || t.includes('succession')) ? 'met' : 'not-evidenced', 'agent changes and key rotations as signed records'),
54
+ ],
55
+ dora: (f) => [
56
+ c('Art. 17', 'ICT-related incident management process', f.incidents > 0 ? 'partial' : 'not-evidenced', `${f.incidents} incident records`),
57
+ c('Art. 19', 'Reporting of major ICT-related incidents', 'not-evidenced', 'use @zanii/regulator incidentClock for the deadlines; filings happen outside the log'),
58
+ c('Art. 28', 'ICT third-party risk', f.targets.some((t) => t.startsWith('subprocessor') || t.startsWith('broker.')) ? 'partial' : 'not-evidenced', 'third-party calls through the broker / subprocessor records'),
59
+ ],
60
+ nis2: (f) => [
61
+ c('Art. 21', 'Cybersecurity risk-management measures', f.guard > 0 || f.revocations > 0 ? 'partial' : 'not-evidenced', `${f.guard} guard decisions, ${f.revocations} revocations`),
62
+ c('Art. 23', 'Reporting obligations', f.incidents > 0 ? 'partial' : 'not-evidenced', 'incident records; use incidentReport for the 24h / 72h / one-month clock'),
63
+ ],
64
+ hipaa: (f) => [c('164.312(b)', 'Audit controls: record and examine activity', logs(f), logsText(f))],
65
+ pci4: (f) => [c('Req. 10', 'Log and monitor all access to system components and data', logs(f), logsText(f))],
66
+ gdpr: (f) => [
67
+ c('Art. 5(2)', 'Accountability', f.verified ? 'met' : 'not-evidenced', 'processing actions are signed and attributable'),
68
+ c('Art. 30', 'Records of processing activities', f.receipts > 0 ? 'partial' : 'not-evidenced', 'activity records exist; the Art. 30 register itself is a separate document'),
69
+ ],
70
+ };
71
+ /** Evidence per control for one framework. */
72
+ export function mapToFramework(bundle, framework) {
73
+ const f = facts(bundle);
74
+ return { framework, verified: f.verified, controls: FRAMEWORKS[framework](f) };
75
+ }
76
+ /** Re-evaluate the framework window by window: a control that slips shows up when it slipped. */
77
+ export function controlTimeline(bundles, framework) {
78
+ return bundles.map(({ period, bundle }) => {
79
+ const m = mapToFramework(bundle, framework);
80
+ return { period, verified: m.verified, met: m.controls.filter((x) => x.status === 'met').length, total: m.controls.length, gaps: m.controls.filter((x) => x.status !== 'met').map((x) => x.id) };
81
+ });
82
+ }
83
+ /**
84
+ * A provably random audit sample: commit the seed before seeing the population, then
85
+ * draw. The auditor can redo the draw from the seed.
86
+ */
87
+ export function sampleSelector(bundle, n, seed) {
88
+ const s = seed ? { seed, commitment: undefined } : commitSeed();
89
+ return { seed: s.seed, commitment: s.commitment, sample: drawSample(bundle.receipts.map((r) => ({ hash: r.hash, index: r.index })), n, s.seed) };
90
+ }
91
+ /** Every exception an auditor should see, with any remediation recorded against it. */
92
+ export function exceptionRegister(bundle, remediations = []) {
93
+ const f = facts(bundle);
94
+ const exceptions = [];
95
+ f.report.checks.filter((x) => !x.ok).forEach((x) => exceptions.push({ id: jcsHash({ check: x.label }), description: `verification check failed: ${x.label}`, remediation: null }));
96
+ if (!f.anchoredAll)
97
+ exceptions.push({ id: jcsHash({ e: 'anchoring', agent: bundle.agent_id }), description: 'not all records are anchored on-chain', remediation: null });
98
+ if (f.highRisk > 0 && f.oversight === 0)
99
+ exceptions.push({ id: jcsHash({ e: 'oversight', agent: bundle.agent_id }), description: `${f.highRisk} high-risk actions with no human confirmation on record`, remediation: null });
100
+ for (const e of exceptions)
101
+ e.remediation = remediations.find((r) => r.exception === e.id) ?? null;
102
+ return { open: exceptions.filter((e) => !e.remediation).length, exceptions };
103
+ }
104
+ /** EU AI Act Annex IV technical documentation, drafted from what you supply plus what the log proves. */
105
+ export function aiActTechnicalFile(system, bundle) {
106
+ const m = mapToFramework(bundle, 'eu-ai-act');
107
+ const metrics = Object.entries(system.accuracyMetrics ?? {}).map(([k, v]) => `- ${k}: ${v}`).join('\n') || '- (to be supplied by the provider)';
108
+ return `# Technical documentation: ${system.name} ${system.version}
109
+
110
+ ## 1. General description
111
+ - Provider: ${system.provider}
112
+ - Intended purpose: ${system.intendedPurpose}
113
+
114
+ ## 2. Human oversight measures
115
+ ${system.humanOversight}
116
+
117
+ ## 3. Performance
118
+ ${metrics}
119
+
120
+ ## 4. Record-keeping and monitoring (from the transparency log)
121
+ ${m.controls.map((x) => `- **${x.id}** ${x.title}: ${x.status}. ${x.evidence}`).join('\n')}
122
+
123
+ Log evidence for agent \`${bundle.agent_id}\`, verified offline: ${m.verified ? 'yes' : 'NO'}.
124
+ `;
125
+ }
126
+ /** An incident report skeleton with the regime's deadlines and the receipts it concerns. */
127
+ export function incidentReport(incident, regime) {
128
+ return { regime, ...incident, deadlines: incidentClock(regime, incident.awareAt), evidence: incident.receipts };
129
+ }
130
+ /** Trend across monitoring periods: activity, share of high-risk actions, guard decisions, failures. */
131
+ export function postMarketMonitoring(periods) {
132
+ return periods.map(({ period, bundle }) => {
133
+ const f = facts(bundle);
134
+ return { period, verified: f.verified, actions: f.receipts, highRiskShare: f.receipts ? f.highRisk / f.receipts : 0, guardDecisions: f.guard, incidents: f.incidents };
135
+ });
136
+ }
137
+ /** A control owner's signed quarterly attestation. */
138
+ export function attestControl(input, ownerPrivateKey) {
139
+ return signObject({ v: 1, type: 'compliance.attestation', ...input, ts: input.ts ?? new Date().toISOString() }, ownerPrivateKey);
140
+ }
141
+ export function verifyControlAttestation(a, ownerDid) {
142
+ return verifySignedObject(a) && a.type === 'compliance.attestation' && (!ownerDid || a.signer === ownerDid);
143
+ }
144
+ /** A framework mapping as JSON-LD for machine submission. */
145
+ export function regulatorExport(mapping, agent) {
146
+ return {
147
+ '@context': { '@vocab': 'https://ledger.zanii.agency/vocab#', schema: 'https://schema.org/' },
148
+ '@type': 'ComplianceEvidence',
149
+ agent, framework: mapping.framework, verified: mapping.verified,
150
+ controls: mapping.controls.map((x) => ({ '@type': 'Control', identifier: x.id, name: x.title, status: x.status, evidence: x.evidence })),
151
+ };
152
+ }
153
+ const esc = (s) => s.replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[ch]);
154
+ /**
155
+ * A single offline HTML file for an auditor: the framework mapping plus the full bundle
156
+ * embedded, so they can re-verify it with any Zanii verifier (or the /verify-bundle page).
157
+ */
158
+ export function renderAuditorPortal(bundle, frameworks) {
159
+ const sections = frameworks.map((fw) => {
160
+ const m = mapToFramework(bundle, fw);
161
+ return `<h2>${esc(fw)}</h2><table><tr><th>Control</th><th>Status</th><th>Evidence</th></tr>${m.controls.map((x) => `<tr><td>${esc(x.id)} ${esc(x.title)}</td><td>${x.status}</td><td>${esc(x.evidence)}</td></tr>`).join('')}</table>`;
162
+ }).join('');
163
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Audit evidence</title><style>body{font:14px/1.5 system-ui,sans-serif;max-width:960px;margin:2rem auto;padding:0 1rem}table{border-collapse:collapse;width:100%}td,th{border:1px solid #ccc;padding:4px 8px;text-align:left;vertical-align:top}</style></head><body>
164
+ <h1>Audit evidence for <code>${esc(bundle.agent_id)}</code></h1>
165
+ <p>Bundle hash <code>${esc(jcsHash(bundle))}</code>. Re-verify the embedded bundle with <code>zanii offline-verify</code> or the offline page at /verify-bundle.</p>
166
+ ${sections}
167
+ <script type="application/json" id="bundle">${JSON.stringify(bundle).replace(/</g, '\\u003c')}</script></body></html>`;
168
+ }
169
+ //# sourceMappingURL=frameworks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks.js","sourceRoot":"","sources":["../src/frameworks.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -65,4 +65,5 @@ export interface ReconcileReport {
65
65
  }
66
66
  /** Reconcile provider settlement references against the ledger's. */
67
67
  export declare function reconcile(ledgerRefs: Iterable<string>, providerRefs: Iterable<string>): ReconcileReport;
68
+ export * from './frameworks.js';
68
69
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAErF,mFAAmF;AACnF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,2DAA2D;IAC3D,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9D,sEAAsE;IACtE,QAAQ,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,wDAAwD;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,UAAU,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,gBAAgB,CAyClB;AAED,iDAAiD;AACjD,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAwBpE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oFAAoF;IACpF,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,eAAe,CASvG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAErF,mFAAmF;AACnF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,2DAA2D;IAC3D,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9D,sEAAsE;IACtE,QAAQ,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,wDAAwD;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,UAAU,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,gBAAgB,CAyClB;AAED,iDAAiD;AACjD,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAwBpE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oFAAoF;IACpF,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,eAAe,CASvG;AACD,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -94,4 +94,5 @@ export function reconcile(ledgerRefs, providerRefs) {
94
94
  missing_from_provider.push(ref);
95
95
  return { ok: missing_from_ledger.length === 0, matched, missing_from_ledger, missing_from_provider };
96
96
  }
97
+ export * from './frameworks.js';
97
98
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zanii/compliance",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Turn a Zanii audit bundle into an auditor-ready compliance report - offline verification, action breakdown, anchoring coverage, and control mapping, rendered to Markdown.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ledger.zanii.agency",
@@ -29,10 +29,11 @@
29
29
  "@types/node": "^26.1.0",
30
30
  "typescript": "^5.8.2",
31
31
  "vitest": "^3.0.9",
32
- "@zanii/testing": "0.1.1"
32
+ "@zanii/testing": "0.1.2"
33
33
  },
34
34
  "dependencies": {
35
- "@zanii/core": "^0.4.0"
35
+ "@zanii/core": "^0.5.4",
36
+ "@zanii/regulator": "^0.1.0"
36
37
  },
37
38
  "scripts": {
38
39
  "build": "tsc -p tsconfig.build.json",
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Control-by-control evidence for the frameworks auditors ask about, computed from a
3
+ * verified audit bundle. "met" means the log carries evidence for the control; it is
4
+ * evidence for an auditor, never a certification. Controls the log cannot evidence are
5
+ * reported as `not-evidenced`, not as failed or passed.
6
+ */
7
+ import { jcsHash, signObject, verifyAuditBundle, verifySignedObject, type AuditBundle, type BundleReport, type SignedObject } from '@zanii/core';
8
+ import { commitSeed, drawSample, incidentClock, type Regime } from '@zanii/regulator';
9
+
10
+ export type Framework = 'eu-ai-act' | 'iso42001' | 'nist-ai-rmf' | 'soc2' | 'dora' | 'nis2' | 'hipaa' | 'pci4' | 'gdpr';
11
+ export type ControlStatus = 'met' | 'partial' | 'not-evidenced';
12
+
13
+ export interface ControlResult {
14
+ id: string;
15
+ title: string;
16
+ status: ControlStatus;
17
+ evidence: string;
18
+ }
19
+
20
+ interface Facts {
21
+ report: BundleReport;
22
+ verified: boolean;
23
+ chainOk: boolean;
24
+ anchoredAll: boolean;
25
+ receipts: number;
26
+ days: number;
27
+ targets: string[];
28
+ oversight: number;
29
+ guard: number;
30
+ incidents: number;
31
+ revocations: number;
32
+ highRisk: number;
33
+ }
34
+
35
+ const targetOf = (r: any): string => r.target ?? r.body?.target ?? '';
36
+
37
+ function facts(bundle: AuditBundle): Facts {
38
+ const report = verifyAuditBundle(bundle);
39
+ const targets = bundle.receipts.map((b) => targetOf(b.receipt));
40
+ const s = report.stats;
41
+ const days = s.first_ts && s.last_ts ? (Date.parse(s.last_ts) - Date.parse(s.first_ts)) / 86_400_000 : 0;
42
+ return {
43
+ report, verified: report.ok,
44
+ chainOk: !!report.checks.find((c) => /chain/i.test(c.label))?.ok,
45
+ anchoredAll: s.anchored_through !== null && s.anchored_through >= Math.max(...bundle.receipts.map((r) => r.index), 0),
46
+ receipts: targets.length, days, targets,
47
+ oversight: targets.filter((t) => /confirm|approv|takeover|handback|review/i.test(t)).length,
48
+ guard: targets.filter((t) => t.startsWith('zanii.guard.')).length,
49
+ incidents: targets.filter((t) => /incident|estop|break-glass/i.test(t)).length,
50
+ revocations: s.revoked_certs,
51
+ highRisk: bundle.receipts.filter((b) => ['high', 'critical'].includes((b.receipt as any).risk)).length,
52
+ };
53
+ }
54
+
55
+ const c = (id: string, title: string, status: ControlStatus, evidence: string): ControlResult => ({ id, title, status, evidence });
56
+ const logs = (f: Facts) => f.verified && f.chainOk ? (f.anchoredAll ? 'met' : 'partial') : 'not-evidenced';
57
+ const logsText = (f: Facts) => `${f.receipts} signed, hash-chained records; offline verification ${f.verified ? 'passed' : 'FAILED'}; ${f.anchoredAll ? 'all anchored on-chain' : 'not all anchored yet'}`;
58
+ const oversight = (f: Facts): ControlStatus => (f.oversight > 0 ? 'met' : f.highRisk === 0 ? 'partial' : 'not-evidenced');
59
+ const oversightText = (f: Facts) => `${f.oversight} human confirmation / review records for ${f.highRisk} high-risk actions`;
60
+
61
+ const FRAMEWORKS: Record<Framework, (f: Facts) => ControlResult[]> = {
62
+ 'eu-ai-act': (f) => [
63
+ c('Art. 12', 'Record-keeping: automatic logging over the lifetime of the system', logs(f), logsText(f)),
64
+ c('Art. 14', 'Human oversight', oversight(f), oversightText(f)),
65
+ c('Art. 19 / 26(6)', 'Keep automatically generated logs for at least six months', f.days >= 182 ? 'met' : 'partial', `records span ${Math.round(f.days)} days`),
66
+ c('Art. 72', 'Post-market monitoring', f.guard > 0 ? 'met' : 'partial', `${f.guard} runtime security decisions recorded`),
67
+ c('Art. 73', 'Reporting of serious incidents', f.incidents > 0 ? 'partial' : 'not-evidenced', `${f.incidents} incident-type records; reporting itself happens outside the log`),
68
+ ],
69
+ iso42001: (f) => [
70
+ c('Clause 8.1', 'Operational planning and control', f.revocations >= 0 && f.verified ? 'met' : 'not-evidenced', 'every action carries the owner-signed delegation it ran under'),
71
+ c('Clause 9.1', 'Monitoring, measurement, analysis and evaluation', logs(f), logsText(f)),
72
+ c('Clause 10.2', 'Nonconformity and corrective action', f.incidents > 0 ? 'partial' : 'not-evidenced', `${f.incidents} incident records`),
73
+ ],
74
+ 'nist-ai-rmf': (f) => [
75
+ c('GOVERN', 'Accountability structures are in place', f.verified ? 'met' : 'not-evidenced', 'actions are attributable to agents and owners through signed delegations'),
76
+ c('MEASURE', 'AI risks are tracked', f.highRisk > 0 || f.guard > 0 ? 'met' : 'partial', `${f.highRisk} risk-labelled high/critical actions, ${f.guard} guard decisions`),
77
+ c('MANAGE', 'Risks are responded to', f.revocations > 0 || f.incidents > 0 ? 'met' : 'partial', `${f.revocations} revocations, ${f.incidents} incident records`),
78
+ ],
79
+ soc2: (f) => [
80
+ c('CC6.1', 'Logical access controls', f.verified ? 'met' : 'not-evidenced', 'scoped, expiring delegations; revocation recorded'),
81
+ c('CC7.2', 'Monitoring of system components for anomalies', f.guard > 0 ? 'met' : 'partial', `${f.guard} guard decisions; complete activity log`),
82
+ c('CC8.1', 'Change management', f.targets.some((t) => t.includes('evolution') || t.includes('succession')) ? 'met' : 'not-evidenced', 'agent changes and key rotations as signed records'),
83
+ ],
84
+ dora: (f) => [
85
+ c('Art. 17', 'ICT-related incident management process', f.incidents > 0 ? 'partial' : 'not-evidenced', `${f.incidents} incident records`),
86
+ c('Art. 19', 'Reporting of major ICT-related incidents', 'not-evidenced', 'use @zanii/regulator incidentClock for the deadlines; filings happen outside the log'),
87
+ c('Art. 28', 'ICT third-party risk', f.targets.some((t) => t.startsWith('subprocessor') || t.startsWith('broker.')) ? 'partial' : 'not-evidenced', 'third-party calls through the broker / subprocessor records'),
88
+ ],
89
+ nis2: (f) => [
90
+ c('Art. 21', 'Cybersecurity risk-management measures', f.guard > 0 || f.revocations > 0 ? 'partial' : 'not-evidenced', `${f.guard} guard decisions, ${f.revocations} revocations`),
91
+ c('Art. 23', 'Reporting obligations', f.incidents > 0 ? 'partial' : 'not-evidenced', 'incident records; use incidentReport for the 24h / 72h / one-month clock'),
92
+ ],
93
+ hipaa: (f) => [c('164.312(b)', 'Audit controls: record and examine activity', logs(f), logsText(f))],
94
+ pci4: (f) => [c('Req. 10', 'Log and monitor all access to system components and data', logs(f), logsText(f))],
95
+ gdpr: (f) => [
96
+ c('Art. 5(2)', 'Accountability', f.verified ? 'met' : 'not-evidenced', 'processing actions are signed and attributable'),
97
+ c('Art. 30', 'Records of processing activities', f.receipts > 0 ? 'partial' : 'not-evidenced', 'activity records exist; the Art. 30 register itself is a separate document'),
98
+ ],
99
+ };
100
+
101
+ /** Evidence per control for one framework. */
102
+ export function mapToFramework(bundle: AuditBundle, framework: Framework): { framework: Framework; verified: boolean; controls: ControlResult[] } {
103
+ const f = facts(bundle);
104
+ return { framework, verified: f.verified, controls: FRAMEWORKS[framework](f) };
105
+ }
106
+
107
+ /** Re-evaluate the framework window by window: a control that slips shows up when it slipped. */
108
+ export function controlTimeline(bundles: Array<{ period: string; bundle: AuditBundle }>, framework: Framework) {
109
+ return bundles.map(({ period, bundle }) => {
110
+ const m = mapToFramework(bundle, framework);
111
+ return { period, verified: m.verified, met: m.controls.filter((x) => x.status === 'met').length, total: m.controls.length, gaps: m.controls.filter((x) => x.status !== 'met').map((x) => x.id) };
112
+ });
113
+ }
114
+
115
+ /**
116
+ * A provably random audit sample: commit the seed before seeing the population, then
117
+ * draw. The auditor can redo the draw from the seed.
118
+ */
119
+ export function sampleSelector(bundle: AuditBundle, n: number, seed?: string) {
120
+ const s = seed ? { seed, commitment: undefined } : commitSeed();
121
+ return { seed: s.seed, commitment: s.commitment, sample: drawSample(bundle.receipts.map((r) => ({ hash: r.hash, index: r.index })), n, s.seed) };
122
+ }
123
+
124
+ /** Every exception an auditor should see, with any remediation recorded against it. */
125
+ export function exceptionRegister(bundle: AuditBundle, remediations: Array<{ exception: string; action: string; by: string; ts: string }> = []) {
126
+ const f = facts(bundle);
127
+ const exceptions: Array<{ id: string; description: string; remediation: (typeof remediations)[number] | null }> = [];
128
+ f.report.checks.filter((x) => !x.ok).forEach((x) => exceptions.push({ id: jcsHash({ check: x.label }), description: `verification check failed: ${x.label}`, remediation: null }));
129
+ if (!f.anchoredAll) exceptions.push({ id: jcsHash({ e: 'anchoring', agent: bundle.agent_id }), description: 'not all records are anchored on-chain', remediation: null });
130
+ if (f.highRisk > 0 && f.oversight === 0) exceptions.push({ id: jcsHash({ e: 'oversight', agent: bundle.agent_id }), description: `${f.highRisk} high-risk actions with no human confirmation on record`, remediation: null });
131
+ for (const e of exceptions) e.remediation = remediations.find((r) => r.exception === e.id) ?? null;
132
+ return { open: exceptions.filter((e) => !e.remediation).length, exceptions };
133
+ }
134
+
135
+ /** EU AI Act Annex IV technical documentation, drafted from what you supply plus what the log proves. */
136
+ export function aiActTechnicalFile(system: { name: string; provider: string; intendedPurpose: string; version: string; humanOversight: string; accuracyMetrics?: Record<string, string> }, bundle: AuditBundle): string {
137
+ const m = mapToFramework(bundle, 'eu-ai-act');
138
+ const metrics = Object.entries(system.accuracyMetrics ?? {}).map(([k, v]) => `- ${k}: ${v}`).join('\n') || '- (to be supplied by the provider)';
139
+ return `# Technical documentation: ${system.name} ${system.version}
140
+
141
+ ## 1. General description
142
+ - Provider: ${system.provider}
143
+ - Intended purpose: ${system.intendedPurpose}
144
+
145
+ ## 2. Human oversight measures
146
+ ${system.humanOversight}
147
+
148
+ ## 3. Performance
149
+ ${metrics}
150
+
151
+ ## 4. Record-keeping and monitoring (from the transparency log)
152
+ ${m.controls.map((x) => `- **${x.id}** ${x.title}: ${x.status}. ${x.evidence}`).join('\n')}
153
+
154
+ Log evidence for agent \`${bundle.agent_id}\`, verified offline: ${m.verified ? 'yes' : 'NO'}.
155
+ `;
156
+ }
157
+
158
+ /** An incident report skeleton with the regime's deadlines and the receipts it concerns. */
159
+ export function incidentReport(incident: { id: string; summary: string; awareAt: string; receipts: string[] }, regime: Regime) {
160
+ return { regime, ...incident, deadlines: incidentClock(regime, incident.awareAt), evidence: incident.receipts };
161
+ }
162
+
163
+ /** Trend across monitoring periods: activity, share of high-risk actions, guard decisions, failures. */
164
+ export function postMarketMonitoring(periods: Array<{ period: string; bundle: AuditBundle }>) {
165
+ return periods.map(({ period, bundle }) => {
166
+ const f = facts(bundle);
167
+ return { period, verified: f.verified, actions: f.receipts, highRiskShare: f.receipts ? f.highRisk / f.receipts : 0, guardDecisions: f.guard, incidents: f.incidents };
168
+ });
169
+ }
170
+
171
+ export type ControlAttestation = SignedObject<{ v: 1; type: 'compliance.attestation'; control: string; period: string; statement: string; ts: string }>;
172
+
173
+ /** A control owner's signed quarterly attestation. */
174
+ export function attestControl(input: { control: string; period: string; statement: string; ts?: string }, ownerPrivateKey: Uint8Array): ControlAttestation {
175
+ return signObject({ v: 1 as const, type: 'compliance.attestation' as const, ...input, ts: input.ts ?? new Date().toISOString() }, ownerPrivateKey);
176
+ }
177
+
178
+ export function verifyControlAttestation(a: ControlAttestation, ownerDid?: string): boolean {
179
+ return verifySignedObject(a) && a.type === 'compliance.attestation' && (!ownerDid || a.signer === ownerDid);
180
+ }
181
+
182
+ /** A framework mapping as JSON-LD for machine submission. */
183
+ export function regulatorExport(mapping: ReturnType<typeof mapToFramework>, agent: string) {
184
+ return {
185
+ '@context': { '@vocab': 'https://ledger.zanii.agency/vocab#', schema: 'https://schema.org/' },
186
+ '@type': 'ComplianceEvidence',
187
+ agent, framework: mapping.framework, verified: mapping.verified,
188
+ controls: mapping.controls.map((x) => ({ '@type': 'Control', identifier: x.id, name: x.title, status: x.status, evidence: x.evidence })),
189
+ };
190
+ }
191
+
192
+ const esc = (s: string) => s.replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[ch]!);
193
+
194
+ /**
195
+ * A single offline HTML file for an auditor: the framework mapping plus the full bundle
196
+ * embedded, so they can re-verify it with any Zanii verifier (or the /verify-bundle page).
197
+ */
198
+ export function renderAuditorPortal(bundle: AuditBundle, frameworks: Framework[]): string {
199
+ const sections = frameworks.map((fw) => {
200
+ const m = mapToFramework(bundle, fw);
201
+ return `<h2>${esc(fw)}</h2><table><tr><th>Control</th><th>Status</th><th>Evidence</th></tr>${m.controls.map((x) => `<tr><td>${esc(x.id)} ${esc(x.title)}</td><td>${x.status}</td><td>${esc(x.evidence)}</td></tr>`).join('')}</table>`;
202
+ }).join('');
203
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Audit evidence</title><style>body{font:14px/1.5 system-ui,sans-serif;max-width:960px;margin:2rem auto;padding:0 1rem}table{border-collapse:collapse;width:100%}td,th{border:1px solid #ccc;padding:4px 8px;text-align:left;vertical-align:top}</style></head><body>
204
+ <h1>Audit evidence for <code>${esc(bundle.agent_id)}</code></h1>
205
+ <p>Bundle hash <code>${esc(jcsHash(bundle as never))}</code>. Re-verify the embedded bundle with <code>zanii offline-verify</code> or the offline page at /verify-bundle.</p>
206
+ ${sections}
207
+ <script type="application/json" id="bundle">${JSON.stringify(bundle).replace(/</g, '\\u003c')}</script></body></html>`;
208
+ }
package/src/index.ts CHANGED
@@ -136,3 +136,4 @@ export function reconcile(ledgerRefs: Iterable<string>, providerRefs: Iterable<s
136
136
  for (const ref of ledger) if (!provider.has(ref)) missing_from_provider.push(ref);
137
137
  return { ok: missing_from_ledger.length === 0, matched, missing_from_ledger, missing_from_provider };
138
138
  }
139
+ export * from './frameworks.js';