@emilia-protocol/gate 0.10.0 → 0.13.0
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/CHANGELOG.md +91 -0
- package/README.md +272 -0
- package/action-control-manifest.js +3 -268
- package/action-escrow-custodian.js +4 -0
- package/action-escrow-evidence.js +4 -0
- package/action-escrow-package.js +4 -0
- package/action-escrow-postgres.js +4 -0
- package/action-escrow-state.js +4 -0
- package/action-escrow-verifiers.js +4 -0
- package/action-escrow.js +4 -0
- package/action-packs.js +3 -140
- package/adapters/_kit.js +3 -104
- package/adapters/aws.js +3 -108
- package/adapters/cloudflare.js +3 -54
- package/adapters/gcp.js +3 -70
- package/adapters/github.js +3 -109
- package/adapters/jira.js +3 -55
- package/adapters/k8s.js +3 -70
- package/adapters/linear.js +3 -55
- package/adapters/salesforce.js +3 -55
- package/adapters/stripe.js +3 -81
- package/adapters/supabase.js +3 -121
- package/adapters/terraform.js +3 -59
- package/adapters/vercel.js +3 -84
- package/aec-execution.js +3 -312
- package/breakglass.js +3 -582
- package/capability-receipt.js +4 -0
- package/cf1-conformance.js +3 -106
- package/challenge-store.js +3 -69
- package/control-plane.js +3 -340
- package/coverage.js +3 -721
- package/demo.mjs +1 -1
- package/deployment-attestation.js +3 -247
- package/dist/action-control-manifest.d.ts +82 -0
- package/dist/action-control-manifest.d.ts.map +1 -0
- package/dist/action-control-manifest.js +422 -0
- package/dist/action-control-manifest.js.map +1 -0
- package/dist/action-escrow-custodian.d.ts +74 -0
- package/dist/action-escrow-custodian.d.ts.map +1 -0
- package/dist/action-escrow-custodian.js +363 -0
- package/dist/action-escrow-custodian.js.map +1 -0
- package/dist/action-escrow-evidence.d.ts +130 -0
- package/dist/action-escrow-evidence.d.ts.map +1 -0
- package/dist/action-escrow-evidence.js +1012 -0
- package/dist/action-escrow-evidence.js.map +1 -0
- package/dist/action-escrow-package.d.ts +10 -0
- package/dist/action-escrow-package.d.ts.map +1 -0
- package/dist/action-escrow-package.js +1583 -0
- package/dist/action-escrow-package.js.map +1 -0
- package/dist/action-escrow-postgres.d.ts +62 -0
- package/dist/action-escrow-postgres.d.ts.map +1 -0
- package/dist/action-escrow-postgres.js +339 -0
- package/dist/action-escrow-postgres.js.map +1 -0
- package/dist/action-escrow-state.d.ts +141 -0
- package/dist/action-escrow-state.d.ts.map +1 -0
- package/dist/action-escrow-state.js +413 -0
- package/dist/action-escrow-state.js.map +1 -0
- package/dist/action-escrow-verifiers.d.ts +65 -0
- package/dist/action-escrow-verifiers.d.ts.map +1 -0
- package/dist/action-escrow-verifiers.js +421 -0
- package/dist/action-escrow-verifiers.js.map +1 -0
- package/dist/action-escrow.d.ts +112 -0
- package/dist/action-escrow.d.ts.map +1 -0
- package/dist/action-escrow.js +2661 -0
- package/dist/action-escrow.js.map +1 -0
- package/dist/action-packs.d.ts +54 -0
- package/dist/action-packs.d.ts.map +1 -0
- package/dist/action-packs.js +143 -0
- package/dist/action-packs.js.map +1 -0
- package/dist/adapters/_kit.d.ts +50 -0
- package/dist/adapters/_kit.d.ts.map +1 -0
- package/dist/adapters/_kit.js +98 -0
- package/dist/adapters/_kit.js.map +1 -0
- package/dist/adapters/aws.d.ts +158 -0
- package/dist/adapters/aws.d.ts.map +1 -0
- package/dist/adapters/aws.js +136 -0
- package/dist/adapters/aws.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +116 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -0
- package/dist/adapters/cloudflare.js +75 -0
- package/dist/adapters/cloudflare.js.map +1 -0
- package/dist/adapters/gcp.d.ts +139 -0
- package/dist/adapters/gcp.d.ts.map +1 -0
- package/dist/adapters/gcp.js +69 -0
- package/dist/adapters/gcp.js.map +1 -0
- package/dist/adapters/github.d.ts +123 -0
- package/dist/adapters/github.d.ts.map +1 -0
- package/dist/adapters/github.js +105 -0
- package/dist/adapters/github.js.map +1 -0
- package/dist/adapters/jira.d.ts +109 -0
- package/dist/adapters/jira.d.ts.map +1 -0
- package/dist/adapters/jira.js +54 -0
- package/dist/adapters/jira.js.map +1 -0
- package/dist/adapters/k8s.d.ts +139 -0
- package/dist/adapters/k8s.d.ts.map +1 -0
- package/dist/adapters/k8s.js +69 -0
- package/dist/adapters/k8s.js.map +1 -0
- package/dist/adapters/linear.d.ts +109 -0
- package/dist/adapters/linear.d.ts.map +1 -0
- package/dist/adapters/linear.js +54 -0
- package/dist/adapters/linear.js.map +1 -0
- package/dist/adapters/salesforce.d.ts +109 -0
- package/dist/adapters/salesforce.d.ts.map +1 -0
- package/dist/adapters/salesforce.js +54 -0
- package/dist/adapters/salesforce.js.map +1 -0
- package/dist/adapters/stripe.d.ts +116 -0
- package/dist/adapters/stripe.d.ts.map +1 -0
- package/dist/adapters/stripe.js +77 -0
- package/dist/adapters/stripe.js.map +1 -0
- package/dist/adapters/supabase.d.ts +127 -0
- package/dist/adapters/supabase.d.ts.map +1 -0
- package/dist/adapters/supabase.js +112 -0
- package/dist/adapters/supabase.js.map +1 -0
- package/dist/adapters/terraform.d.ts +109 -0
- package/dist/adapters/terraform.d.ts.map +1 -0
- package/dist/adapters/terraform.js +58 -0
- package/dist/adapters/terraform.js.map +1 -0
- package/dist/adapters/vercel.d.ts +114 -0
- package/dist/adapters/vercel.d.ts.map +1 -0
- package/dist/adapters/vercel.js +81 -0
- package/dist/adapters/vercel.js.map +1 -0
- package/dist/aec-execution.d.ts +107 -0
- package/dist/aec-execution.d.ts.map +1 -0
- package/dist/aec-execution.js +334 -0
- package/dist/aec-execution.js.map +1 -0
- package/dist/breakglass.d.ts +205 -0
- package/dist/breakglass.d.ts.map +1 -0
- package/dist/breakglass.js +627 -0
- package/dist/breakglass.js.map +1 -0
- package/dist/capability-receipt.d.ts +601 -0
- package/dist/capability-receipt.d.ts.map +1 -0
- package/dist/capability-receipt.js +1177 -0
- package/dist/capability-receipt.js.map +1 -0
- package/dist/cf1-conformance.d.ts +83 -0
- package/dist/cf1-conformance.d.ts.map +1 -0
- package/dist/cf1-conformance.js +94 -0
- package/dist/cf1-conformance.js.map +1 -0
- package/dist/challenge-store.d.ts +20 -0
- package/dist/challenge-store.d.ts.map +1 -0
- package/dist/challenge-store.js +62 -0
- package/dist/challenge-store.js.map +1 -0
- package/dist/control-plane.d.ts +136 -0
- package/dist/control-plane.d.ts.map +1 -0
- package/dist/control-plane.js +349 -0
- package/dist/control-plane.js.map +1 -0
- package/dist/coverage.d.ts +156 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +768 -0
- package/dist/coverage.js.map +1 -0
- package/dist/deployment-attestation.d.ts +93 -0
- package/dist/deployment-attestation.d.ts.map +1 -0
- package/dist/deployment-attestation.js +262 -0
- package/dist/deployment-attestation.js.map +1 -0
- package/dist/eg1-conformance.d.ts +286 -0
- package/dist/eg1-conformance.d.ts.map +1 -0
- package/dist/eg1-conformance.js +379 -0
- package/dist/eg1-conformance.js.map +1 -0
- package/dist/enterprise.d.ts +88 -0
- package/dist/enterprise.d.ts.map +1 -0
- package/dist/enterprise.js +194 -0
- package/dist/enterprise.js.map +1 -0
- package/dist/evidence-postgres.d.ts +123 -0
- package/dist/evidence-postgres.d.ts.map +1 -0
- package/dist/evidence-postgres.js +343 -0
- package/dist/evidence-postgres.js.map +1 -0
- package/dist/evidence.d.ts +113 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +369 -0
- package/dist/evidence.js.map +1 -0
- package/dist/execution-binding.d.ts +49 -0
- package/dist/execution-binding.d.ts.map +1 -0
- package/dist/execution-binding.js +243 -0
- package/dist/execution-binding.js.map +1 -0
- package/dist/formal-runtime-map.d.ts +42 -0
- package/dist/formal-runtime-map.d.ts.map +1 -0
- package/dist/formal-runtime-map.js +23 -0
- package/dist/formal-runtime-map.js.map +1 -0
- package/dist/index.d.ts +1002 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1736 -0
- package/dist/index.js.map +1 -0
- package/dist/key-registry.d.ts +60 -0
- package/dist/key-registry.d.ts.map +1 -0
- package/dist/key-registry.js +144 -0
- package/dist/key-registry.js.map +1 -0
- package/dist/mcp.d.ts +53 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +112 -0
- package/dist/mcp.js.map +1 -0
- package/dist/metering.d.ts +80 -0
- package/dist/metering.d.ts.map +1 -0
- package/dist/metering.js +227 -0
- package/dist/metering.js.map +1 -0
- package/dist/metrics.d.ts +68 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +242 -0
- package/dist/metrics.js.map +1 -0
- package/dist/network-witness.d.ts +167 -0
- package/dist/network-witness.d.ts.map +1 -0
- package/dist/network-witness.js +520 -0
- package/dist/network-witness.js.map +1 -0
- package/dist/protocol-state.d.ts +141 -0
- package/dist/protocol-state.d.ts.map +1 -0
- package/dist/protocol-state.js +106 -0
- package/dist/protocol-state.js.map +1 -0
- package/dist/receipt-program.d.ts +59 -0
- package/dist/receipt-program.d.ts.map +1 -0
- package/dist/receipt-program.js +1053 -0
- package/dist/receipt-program.js.map +1 -0
- package/dist/reliance-kernel.d.ts +66 -0
- package/dist/reliance-kernel.d.ts.map +1 -0
- package/dist/reliance-kernel.js +103 -0
- package/dist/reliance-kernel.js.map +1 -0
- package/dist/reliance-packet.d.ts +67 -0
- package/dist/reliance-packet.d.ts.map +1 -0
- package/dist/reliance-packet.js +176 -0
- package/dist/reliance-packet.js.map +1 -0
- package/dist/remedy-program-postgres.d.ts +37 -0
- package/dist/remedy-program-postgres.d.ts.map +1 -0
- package/dist/remedy-program-postgres.js +291 -0
- package/dist/remedy-program-postgres.js.map +1 -0
- package/dist/remedy-program-receipt.d.ts +97 -0
- package/dist/remedy-program-receipt.d.ts.map +1 -0
- package/dist/remedy-program-receipt.js +817 -0
- package/dist/remedy-program-receipt.js.map +1 -0
- package/dist/remedy-program.d.ts +76 -0
- package/dist/remedy-program.d.ts.map +1 -0
- package/dist/remedy-program.js +1346 -0
- package/dist/remedy-program.js.map +1 -0
- package/dist/reports/art14.d.ts +101 -0
- package/dist/reports/art14.d.ts.map +1 -0
- package/dist/reports/art14.js +340 -0
- package/dist/reports/art14.js.map +1 -0
- package/dist/reports/assurance-package.d.ts +197 -0
- package/dist/reports/assurance-package.d.ts.map +1 -0
- package/dist/reports/assurance-package.js +313 -0
- package/dist/reports/assurance-package.js.map +1 -0
- package/dist/reports/auditor-workpaper.d.ts +194 -0
- package/dist/reports/auditor-workpaper.d.ts.map +1 -0
- package/dist/reports/auditor-workpaper.js +545 -0
- package/dist/reports/auditor-workpaper.js.map +1 -0
- package/dist/reports/external-verification.d.ts +76 -0
- package/dist/reports/external-verification.d.ts.map +1 -0
- package/dist/reports/external-verification.js +209 -0
- package/dist/reports/external-verification.js.map +1 -0
- package/dist/reports/reperform.d.ts +122 -0
- package/dist/reports/reperform.d.ts.map +1 -0
- package/dist/reports/reperform.js +432 -0
- package/dist/reports/reperform.js.map +1 -0
- package/dist/reports/underwriter.d.ts +127 -0
- package/dist/reports/underwriter.d.ts.map +1 -0
- package/dist/reports/underwriter.js +348 -0
- package/dist/reports/underwriter.js.map +1 -0
- package/dist/retention.d.ts +88 -0
- package/dist/retention.d.ts.map +1 -0
- package/dist/retention.js +90 -0
- package/dist/retention.js.map +1 -0
- package/dist/roster.d.ts +113 -0
- package/dist/roster.d.ts.map +1 -0
- package/dist/roster.js +261 -0
- package/dist/roster.js.map +1 -0
- package/dist/runtime-monitor.d.ts +132 -0
- package/dist/runtime-monitor.d.ts.map +1 -0
- package/dist/runtime-monitor.js +197 -0
- package/dist/runtime-monitor.js.map +1 -0
- package/dist/settlement.d.ts +68 -0
- package/dist/settlement.d.ts.map +1 -0
- package/dist/settlement.js +306 -0
- package/dist/settlement.js.map +1 -0
- package/dist/siem.d.ts +261 -0
- package/dist/siem.d.ts.map +1 -0
- package/dist/siem.js +247 -0
- package/dist/siem.js.map +1 -0
- package/dist/store-postgres.d.ts +107 -0
- package/dist/store-postgres.d.ts.map +1 -0
- package/dist/store-postgres.js +152 -0
- package/dist/store-postgres.js.map +1 -0
- package/dist/store.d.ts +95 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +202 -0
- package/dist/store.js.map +1 -0
- package/dist/strict-json.d.ts +14 -0
- package/dist/strict-json.d.ts.map +1 -0
- package/dist/strict-json.js +132 -0
- package/dist/strict-json.js.map +1 -0
- package/dist/trust-program-adapters.d.ts +122 -0
- package/dist/trust-program-adapters.d.ts.map +1 -0
- package/dist/trust-program-adapters.js +802 -0
- package/dist/trust-program-adapters.js.map +1 -0
- package/dist/trust-program-postgres.d.ts +41 -0
- package/dist/trust-program-postgres.d.ts.map +1 -0
- package/dist/trust-program-postgres.js +346 -0
- package/dist/trust-program-postgres.js.map +1 -0
- package/dist/trust-program-revocation.d.ts +206 -0
- package/dist/trust-program-revocation.d.ts.map +1 -0
- package/dist/trust-program-revocation.js +600 -0
- package/dist/trust-program-revocation.js.map +1 -0
- package/dist/trust-program.d.ts +197 -0
- package/dist/trust-program.d.ts.map +1 -0
- package/dist/trust-program.js +1351 -0
- package/dist/trust-program.js.map +1 -0
- package/dist/witness-postgres.d.ts +43 -0
- package/dist/witness-postgres.d.ts.map +1 -0
- package/dist/witness-postgres.js +92 -0
- package/dist/witness-postgres.js.map +1 -0
- package/dist/zk-range-proof.d.ts +78 -0
- package/dist/zk-range-proof.d.ts.map +1 -0
- package/dist/zk-range-proof.js +228 -0
- package/dist/zk-range-proof.js.map +1 -0
- package/eg1-conformance.js +3 -404
- package/enterprise.js +3 -180
- package/ep-assure.mjs +1 -0
- package/evidence-postgres.js +3 -356
- package/evidence.js +4 -360
- package/execution-binding.js +3 -212
- package/formal-runtime-map.js +4 -0
- package/index.js +4 -1249
- package/key-registry.js +3 -134
- package/mcp.js +3 -109
- package/metering.js +3 -226
- package/metrics.js +3 -231
- package/network-witness.js +3 -499
- package/package.json +47 -4
- package/receipt-program.js +4 -0
- package/reliance-kernel.js +3 -112
- package/reliance-packet.js +3 -175
- package/remedy-program-postgres.js +4 -0
- package/remedy-program-receipt.js +4 -0
- package/remedy-program.js +4 -0
- package/reports/art14.js +0 -0
- package/reports/assurance-package.js +2 -312
- package/reports/auditor-workpaper.js +3 -537
- package/reports/external-verification.js +3 -222
- package/reports/reperform.js +3 -424
- package/reports/underwriter.js +3 -339
- package/retention.js +3 -84
- package/roster.js +3 -264
- package/runtime-monitor.js +4 -0
- package/settlement.js +3 -299
- package/siem.js +3 -235
- package/src/action-control-manifest.ts +424 -0
- package/src/action-escrow-custodian.ts +427 -0
- package/src/action-escrow-evidence.ts +1178 -0
- package/src/action-escrow-package.ts +1821 -0
- package/src/action-escrow-postgres.ts +366 -0
- package/src/action-escrow-state.ts +498 -0
- package/src/action-escrow-verifiers.ts +484 -0
- package/src/action-escrow.ts +3039 -0
- package/src/action-packs.ts +170 -0
- package/src/adapters/_kit.ts +117 -0
- package/src/adapters/aws.ts +142 -0
- package/src/adapters/cloudflare.ts +78 -0
- package/src/adapters/gcp.ts +71 -0
- package/src/adapters/github.ts +110 -0
- package/src/adapters/jira.ts +56 -0
- package/src/adapters/k8s.ts +71 -0
- package/src/adapters/linear.ts +56 -0
- package/src/adapters/salesforce.ts +56 -0
- package/src/adapters/stripe.ts +82 -0
- package/src/adapters/supabase.ts +122 -0
- package/src/adapters/terraform.ts +60 -0
- package/src/adapters/vercel.ts +85 -0
- package/src/aec-execution.ts +354 -0
- package/src/breakglass.ts +647 -0
- package/src/capability-receipt.ts +1258 -0
- package/src/cf1-conformance.ts +120 -0
- package/src/challenge-store.ts +70 -0
- package/src/control-plane.ts +374 -0
- package/src/coverage.ts +832 -0
- package/src/deployment-attestation.ts +259 -0
- package/src/eg1-conformance.ts +471 -0
- package/src/enterprise.ts +195 -0
- package/src/evidence-postgres.ts +374 -0
- package/src/evidence.ts +367 -0
- package/src/execution-binding.ts +236 -0
- package/src/formal-runtime-map.ts +24 -0
- package/src/index.ts +2122 -0
- package/src/key-registry.ts +150 -0
- package/src/mcp.ts +120 -0
- package/src/metering.ts +237 -0
- package/src/metrics.ts +232 -0
- package/src/network-witness.ts +585 -0
- package/src/protocol-state.ts +143 -0
- package/src/protocol-state.typecheck.ts +94 -0
- package/src/receipt-program.ts +1105 -0
- package/src/reliance-kernel.ts +119 -0
- package/src/reliance-packet.ts +206 -0
- package/src/remedy-program-postgres.ts +367 -0
- package/src/remedy-program-receipt.ts +891 -0
- package/src/remedy-program.ts +1388 -0
- package/src/reports/art14.ts +361 -0
- package/src/reports/assurance-package.ts +330 -0
- package/src/reports/auditor-workpaper.ts +558 -0
- package/src/reports/external-verification.ts +232 -0
- package/src/reports/reperform.ts +441 -0
- package/src/reports/underwriter.ts +356 -0
- package/src/retention.ts +100 -0
- package/src/roster.ts +273 -0
- package/src/runtime-monitor.ts +217 -0
- package/src/settlement.ts +313 -0
- package/src/siem.ts +247 -0
- package/src/store-postgres.ts +167 -0
- package/src/store.ts +214 -0
- package/src/strict-json.ts +115 -0
- package/src/trust-program-adapters.ts +847 -0
- package/src/trust-program-postgres.ts +429 -0
- package/src/trust-program-revocation.ts +751 -0
- package/src/trust-program.ts +1460 -0
- package/src/witness-postgres.ts +106 -0
- package/src/zk-range-proof.ts +250 -0
- package/store-postgres.js +3 -161
- package/store.js +4 -198
- package/strict-json.js +3 -85
- package/trust-program-adapters.js +4 -0
- package/trust-program-postgres.js +4 -0
- package/trust-program-revocation.js +4 -0
- package/trust-program.js +4 -0
- package/witness-postgres.js +3 -96
- package/zk-range-proof.js +4 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* EMILIA Gate — EU AI Act Article 14 human-oversight evidence pack.
|
|
4
|
+
*
|
|
5
|
+
* Distills a period of the gate's tamper-evident evidence log into the artifact
|
|
6
|
+
* an Article 14 assessment consumes: which named principal authorized which
|
|
7
|
+
* action_type at which verified assurance tier (oversight exercised), which
|
|
8
|
+
* refusals fired and on which failing predicate (interventions), which replay /
|
|
9
|
+
* tamper attempts were blocked, which actions passed OUTSIDE the manifest
|
|
10
|
+
* (uncontrolled-action exceptions), and the coverage ratio of guarded decisions.
|
|
11
|
+
*
|
|
12
|
+
* Pure over the entries (evidence.all() in, pack out); time enters only through
|
|
13
|
+
* the period bounds and the optional `now` (generated_at). Malformed entries are
|
|
14
|
+
* NEVER silently dropped — they are excluded from the tables and surfaced in
|
|
15
|
+
* `integrity_warnings`, so the pack cannot quietly understate what the log holds.
|
|
16
|
+
* The honesty notice is a structural part of the format: renderMarkdown refuses
|
|
17
|
+
* a pack whose notice was altered or removed.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export const ART14_PACK_VERSION = 'EP-GATE-ART14-PACK-v1';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Mandatory honesty header. Present verbatim in every pack and every rendered
|
|
24
|
+
* view; a pack without it is not an EP-GATE-ART14-PACK-v1.
|
|
25
|
+
*/
|
|
26
|
+
export const ART14_HONESTY_NOTICE =
|
|
27
|
+
'This evidence pack SUPPORTS an EU AI Act Article 14 human-oversight assessment. '
|
|
28
|
+
+ 'It does not itself constitute, and must not be represented as, Article 14 compliance '
|
|
29
|
+
+ 'or a certification of compliance. Counts are derived from the gate\'s tamper-evident '
|
|
30
|
+
+ 'evidence log; the identity of principals is as pinned by the deployer, not '
|
|
31
|
+
+ 'independently verified by this report.';
|
|
32
|
+
|
|
33
|
+
// Gate refusal reason -> the named oversight predicate that failed. An unmapped
|
|
34
|
+
// reason is surfaced as `unmapped:<reason>` — visible, never genericized away.
|
|
35
|
+
const FAILING_PREDICATE_BY_REASON = {
|
|
36
|
+
receipt_required: 'authorization_receipt_present',
|
|
37
|
+
replay_refused: 'one_time_consumption',
|
|
38
|
+
consumption_store_lacks_reserve: 'one_time_consumption',
|
|
39
|
+
assurance_too_low: 'assurance_tier_sufficient',
|
|
40
|
+
unknown_required_tier: 'assurance_tier_sufficient',
|
|
41
|
+
execution_binding_failed: 'execution_binding_intact',
|
|
42
|
+
evidence_log_failed: 'evidence_durably_recorded',
|
|
43
|
+
};
|
|
44
|
+
const RECEIPT_REJECTED_PREFIX = 'receipt_rejected:';
|
|
45
|
+
|
|
46
|
+
function oversightKey(principal, action, tier) {
|
|
47
|
+
return JSON.stringify([principal, action, tier]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function failingPredicate(reason) {
|
|
51
|
+
if (FAILING_PREDICATE_BY_REASON[reason]) return FAILING_PREDICATE_BY_REASON[reason];
|
|
52
|
+
if (reason.startsWith(RECEIPT_REJECTED_PREFIX)) {
|
|
53
|
+
return `receipt_valid:${reason.slice(RECEIPT_REJECTED_PREFIX.length)}`;
|
|
54
|
+
}
|
|
55
|
+
return `unmapped:${reason}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const TIER_ORDER = { software: 0, class_a: 1, quorum: 2 };
|
|
59
|
+
|
|
60
|
+
type Art14Options = {
|
|
61
|
+
organization?: string;
|
|
62
|
+
system?: string;
|
|
63
|
+
periodStart?: string | number;
|
|
64
|
+
periodEnd?: string | number;
|
|
65
|
+
now?: number | (() => number);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
function toMs(t) {
|
|
69
|
+
if (t == null) return null;
|
|
70
|
+
const ms = typeof t === 'number' ? t : Date.parse(t);
|
|
71
|
+
return Number.isFinite(ms) ? ms : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Build the Article 14 evidence pack for a reporting period.
|
|
76
|
+
*
|
|
77
|
+
* Window is half-open [periodStart, periodEnd): an entry stamped exactly at
|
|
78
|
+
* periodEnd belongs to the NEXT period, so adjacent packs never double-count.
|
|
79
|
+
* An empty or inverted period is refused, not rendered as a vacuous pack.
|
|
80
|
+
*
|
|
81
|
+
* @param {Array<object>} entries evidence.all() — decision/execution records
|
|
82
|
+
* @param {object} [o]
|
|
83
|
+
* @param {string} [o.organization] deployer legal/organizational name
|
|
84
|
+
* @param {string} [o.system] the AI system this gate guards
|
|
85
|
+
* @param {string|number} [o.periodStart] inclusive (ISO or epoch ms)
|
|
86
|
+
* @param {string|number} [o.periodEnd] exclusive (ISO or epoch ms)
|
|
87
|
+
* @param {Function|number} [o.now=Date.now] clock for generated_at
|
|
88
|
+
* @returns {object} EP-GATE-ART14-PACK-v1
|
|
89
|
+
*/
|
|
90
|
+
export function buildArt14EvidencePack(entries: Array<Record<string, any>> = [], {
|
|
91
|
+
organization, system, periodStart, periodEnd, now = Date.now,
|
|
92
|
+
}: Art14Options = {}) {
|
|
93
|
+
if (!Array.isArray(entries)) throw new Error('art14: entries must be an array (evidence.all())');
|
|
94
|
+
if (!organization || typeof organization !== 'string') throw new Error('art14: organization is required');
|
|
95
|
+
if (!system || typeof system !== 'string') throw new Error('art14: system is required');
|
|
96
|
+
const startMs = toMs(periodStart);
|
|
97
|
+
const endMs = toMs(periodEnd);
|
|
98
|
+
if (startMs == null || endMs == null) {
|
|
99
|
+
throw new Error('art14: periodStart and periodEnd must be ISO timestamps or epoch ms');
|
|
100
|
+
}
|
|
101
|
+
if (endMs <= startMs) throw new Error('art14: empty or inverted period (periodEnd must be after periodStart)');
|
|
102
|
+
|
|
103
|
+
const warnings: Array<Record<string, any>> = [];
|
|
104
|
+
const oversight = new Map(); // principal\0action\0tier -> row
|
|
105
|
+
const interventions: Array<Record<string, any>> = [];
|
|
106
|
+
const replayBlocked: Array<Record<string, any>> = [];
|
|
107
|
+
const tamperBlocked: Array<Record<string, any>> = [];
|
|
108
|
+
const exceptions: Array<Record<string, any>> = [];
|
|
109
|
+
let decisionsTotal = 0;
|
|
110
|
+
let decisionsGuarded = 0;
|
|
111
|
+
let executionsInWindow = 0;
|
|
112
|
+
let inWindow = 0;
|
|
113
|
+
let outsideWindow = 0;
|
|
114
|
+
let head: string | null = null;
|
|
115
|
+
|
|
116
|
+
entries.forEach((e, index) => {
|
|
117
|
+
const ref = {
|
|
118
|
+
index,
|
|
119
|
+
seq: e && typeof e === 'object' && Number.isInteger(e.seq) ? e.seq : null,
|
|
120
|
+
hash: e && typeof e === 'object' && typeof e.hash === 'string' ? e.hash : null,
|
|
121
|
+
};
|
|
122
|
+
if (!e || typeof e !== 'object' || Array.isArray(e)) {
|
|
123
|
+
warnings.push({ ...ref, problem: 'not_an_object' });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// An entry whose timestamp cannot be parsed cannot be placed in ANY period;
|
|
127
|
+
// it is warned, never silently assigned in or out of the window.
|
|
128
|
+
const atMs = toMs(e.at);
|
|
129
|
+
if (atMs == null) {
|
|
130
|
+
warnings.push({ ...ref, problem: 'missing_or_unparseable_at' });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (atMs < startMs || atMs >= endMs) {
|
|
134
|
+
outsideWindow += 1;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (e.kind !== 'decision' && e.kind !== 'execution') {
|
|
138
|
+
warnings.push({ ...ref, problem: 'unknown_kind', kind: e.kind ?? null });
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (e.kind === 'execution') {
|
|
142
|
+
inWindow += 1;
|
|
143
|
+
head = ref.hash ?? head;
|
|
144
|
+
executionsInWindow += 1;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// A decision record must carry a boolean verdict and a reason; anything
|
|
148
|
+
// else is counted as an integrity warning, not folded into the tables.
|
|
149
|
+
if (typeof e.allow !== 'boolean' || typeof e.reason !== 'string' || e.reason.length === 0) {
|
|
150
|
+
warnings.push({ ...ref, problem: 'malformed_decision' });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
inWindow += 1;
|
|
154
|
+
head = ref.hash ?? head;
|
|
155
|
+
decisionsTotal += 1;
|
|
156
|
+
const principal = typeof e.subject === 'string' && e.subject ? e.subject : '(unattributed)';
|
|
157
|
+
const action = typeof e.action === 'string' && e.action ? e.action : '(unspecified)';
|
|
158
|
+
|
|
159
|
+
if (e.allow) {
|
|
160
|
+
if (e.reason === 'not_guarded') {
|
|
161
|
+
// Passed through OUTSIDE the manifest: no receipt, no human oversight —
|
|
162
|
+
// an exception the assessor must see, not a covered decision.
|
|
163
|
+
exceptions.push({ at: e.at, action, selector: e.selector ?? null, hash: ref.hash });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
decisionsGuarded += 1;
|
|
167
|
+
const tier = e.have_tier || e.required_tier || 'unknown';
|
|
168
|
+
const key = oversightKey(principal, action, tier);
|
|
169
|
+
const row = oversight.get(key)
|
|
170
|
+
|| { principal, action_type: action, assurance_tier: tier, count: 0 };
|
|
171
|
+
row.count += 1;
|
|
172
|
+
oversight.set(key, row);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
decisionsGuarded += 1;
|
|
177
|
+
const row = {
|
|
178
|
+
at: e.at,
|
|
179
|
+
action,
|
|
180
|
+
principal,
|
|
181
|
+
reason: e.reason,
|
|
182
|
+
failing_predicate: failingPredicate(e.reason),
|
|
183
|
+
receipt_id: e.receipt_id ?? null,
|
|
184
|
+
hash: ref.hash,
|
|
185
|
+
};
|
|
186
|
+
interventions.push(row);
|
|
187
|
+
if (e.reason === 'replay_refused') replayBlocked.push(row);
|
|
188
|
+
if (e.reason.startsWith(RECEIPT_REJECTED_PREFIX) || e.reason === 'execution_binding_failed') {
|
|
189
|
+
tamperBlocked.push(row);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Deterministic ordering: principal, then action, then tier strength.
|
|
194
|
+
const oversightRows = [...oversight.values()].sort((a, b) =>
|
|
195
|
+
a.principal.localeCompare(b.principal)
|
|
196
|
+
|| a.action_type.localeCompare(b.action_type)
|
|
197
|
+
|| ((TIER_ORDER[a.assurance_tier] ?? 99) - (TIER_ORDER[b.assurance_tier] ?? 99))
|
|
198
|
+
|| a.assurance_tier.localeCompare(b.assurance_tier));
|
|
199
|
+
|
|
200
|
+
const byPredicate: Record<string, number> = {};
|
|
201
|
+
for (const i of interventions) byPredicate[i.failing_predicate] = (byPredicate[i.failing_predicate] || 0) + 1;
|
|
202
|
+
const byPredicateSorted: Record<string, number> = {};
|
|
203
|
+
for (const k of Object.keys(byPredicate).sort()) byPredicateSorted[k] = byPredicate[k];
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
'@version': ART14_PACK_VERSION,
|
|
207
|
+
notice: ART14_HONESTY_NOTICE,
|
|
208
|
+
organization,
|
|
209
|
+
system,
|
|
210
|
+
period: { start: new Date(startMs).toISOString(), end: new Date(endMs).toISOString() },
|
|
211
|
+
generated_at: new Date(typeof now === 'function' ? now() : now).toISOString(),
|
|
212
|
+
evidence: {
|
|
213
|
+
head, // hash of the last in-window record — ties the pack to a chain state
|
|
214
|
+
entries_total: entries.length,
|
|
215
|
+
entries_in_window: inWindow,
|
|
216
|
+
excluded_outside_window: outsideWindow,
|
|
217
|
+
executions: executionsInWindow,
|
|
218
|
+
},
|
|
219
|
+
oversight_exercised: oversightRows,
|
|
220
|
+
interventions: {
|
|
221
|
+
total: interventions.length,
|
|
222
|
+
by_predicate: byPredicateSorted,
|
|
223
|
+
entries: interventions,
|
|
224
|
+
},
|
|
225
|
+
replay_tamper: {
|
|
226
|
+
replay_blocked: replayBlocked.length,
|
|
227
|
+
tamper_blocked: tamperBlocked.length,
|
|
228
|
+
entries: [...replayBlocked, ...tamperBlocked.filter((t) => t.reason !== 'replay_refused')],
|
|
229
|
+
},
|
|
230
|
+
uncontrolled_action_exceptions: {
|
|
231
|
+
total: exceptions.length,
|
|
232
|
+
entries: exceptions,
|
|
233
|
+
},
|
|
234
|
+
coverage: {
|
|
235
|
+
decisions_total: decisionsTotal,
|
|
236
|
+
decisions_guarded: decisionsGuarded,
|
|
237
|
+
// null (not 0, not 1) when the period holds no decisions: an empty period
|
|
238
|
+
// proves nothing and must not read as either perfect or absent coverage.
|
|
239
|
+
ratio: decisionsTotal > 0 ? decisionsGuarded / decisionsTotal : null,
|
|
240
|
+
},
|
|
241
|
+
integrity_warnings: warnings,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Table cells must not break the table; the source strings are log-derived.
|
|
247
|
+
* Backslash is escaped FIRST: escaping only the pipe turns a log-derived
|
|
248
|
+
* `a\|b` into `a\\|b`, where the `\\` renders as a literal backslash and
|
|
249
|
+
* leaves the pipe live as a cell delimiter, letting an action or refusal
|
|
250
|
+
* reason split its cell and shift every column after it.
|
|
251
|
+
*/
|
|
252
|
+
function md(v) {
|
|
253
|
+
return String(v ?? '—')
|
|
254
|
+
.replace(/\\/g, '\\\\')
|
|
255
|
+
.replace(/\|/g, '\\|')
|
|
256
|
+
.replace(/\r?\n/g, ' ');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Render the pack as the human-readable Markdown view. Refuses any document
|
|
261
|
+
* that is not a verbatim EP-GATE-ART14-PACK-v1 — a missing or edited honesty
|
|
262
|
+
* notice must never render as an apparently-complete report.
|
|
263
|
+
*/
|
|
264
|
+
export function renderMarkdown(pack) {
|
|
265
|
+
if (!pack || pack['@version'] !== ART14_PACK_VERSION) {
|
|
266
|
+
throw new Error(`art14: renderMarkdown requires an ${ART14_PACK_VERSION} pack`);
|
|
267
|
+
}
|
|
268
|
+
if (pack.notice !== ART14_HONESTY_NOTICE) {
|
|
269
|
+
throw new Error('art14: refusing to render a pack whose honesty notice was altered or removed');
|
|
270
|
+
}
|
|
271
|
+
const L: string[] = [];
|
|
272
|
+
L.push('# Article 14 Human-Oversight Evidence Pack');
|
|
273
|
+
L.push('');
|
|
274
|
+
L.push(`> ${pack.notice}`);
|
|
275
|
+
L.push('');
|
|
276
|
+
L.push(`- **Format:** ${ART14_PACK_VERSION}`);
|
|
277
|
+
L.push(`- **Organization:** ${md(pack.organization)}`);
|
|
278
|
+
L.push(`- **System:** ${md(pack.system)}`);
|
|
279
|
+
L.push(`- **Period:** ${pack.period.start} — ${pack.period.end} (end exclusive)`);
|
|
280
|
+
L.push(`- **Generated:** ${pack.generated_at}`);
|
|
281
|
+
L.push(`- **Evidence head:** ${md(pack.evidence.head)} (${pack.evidence.entries_in_window} record(s) in window, ${pack.evidence.excluded_outside_window} outside)`);
|
|
282
|
+
L.push('');
|
|
283
|
+
|
|
284
|
+
L.push('## Oversight exercised');
|
|
285
|
+
if (pack.oversight_exercised.length === 0) {
|
|
286
|
+
L.push('');
|
|
287
|
+
L.push('No authorized guarded actions in this period.');
|
|
288
|
+
} else {
|
|
289
|
+
L.push('');
|
|
290
|
+
L.push('| Principal | Action type | Assurance tier | Authorizations |');
|
|
291
|
+
L.push('| --- | --- | --- | ---: |');
|
|
292
|
+
for (const r of pack.oversight_exercised) {
|
|
293
|
+
L.push(`| ${md(r.principal)} | ${md(r.action_type)} | ${md(r.assurance_tier)} | ${r.count} |`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
L.push('');
|
|
297
|
+
|
|
298
|
+
L.push('## Interventions (refusals)');
|
|
299
|
+
if (pack.interventions.total === 0) {
|
|
300
|
+
L.push('');
|
|
301
|
+
L.push('No refusals in this period.');
|
|
302
|
+
} else {
|
|
303
|
+
L.push('');
|
|
304
|
+
L.push('| At | Action | Principal | Failing predicate | Reason |');
|
|
305
|
+
L.push('| --- | --- | --- | --- | --- |');
|
|
306
|
+
for (const r of pack.interventions.entries) {
|
|
307
|
+
L.push(`| ${md(r.at)} | ${md(r.action)} | ${md(r.principal)} | ${md(r.failing_predicate)} | ${md(r.reason)} |`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
L.push('');
|
|
311
|
+
|
|
312
|
+
L.push('## Replay / tamper attempts blocked');
|
|
313
|
+
L.push('');
|
|
314
|
+
L.push(`- Replay attempts blocked: **${pack.replay_tamper.replay_blocked}**`);
|
|
315
|
+
L.push(`- Tamper attempts blocked: **${pack.replay_tamper.tamper_blocked}**`);
|
|
316
|
+
L.push('');
|
|
317
|
+
|
|
318
|
+
L.push('## Uncontrolled-action exceptions');
|
|
319
|
+
if (pack.uncontrolled_action_exceptions.total === 0) {
|
|
320
|
+
L.push('');
|
|
321
|
+
L.push('None — every decision in this period was for a manifest-guarded action.');
|
|
322
|
+
} else {
|
|
323
|
+
L.push('');
|
|
324
|
+
L.push(`${pack.uncontrolled_action_exceptions.total} action(s) passed through OUTSIDE the manifest (no receipt required, no oversight exercised):`);
|
|
325
|
+
L.push('');
|
|
326
|
+
L.push('| At | Action |');
|
|
327
|
+
L.push('| --- | --- |');
|
|
328
|
+
for (const r of pack.uncontrolled_action_exceptions.entries) {
|
|
329
|
+
L.push(`| ${md(r.at)} | ${md(r.action)} |`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
L.push('');
|
|
333
|
+
|
|
334
|
+
L.push('## Coverage');
|
|
335
|
+
L.push('');
|
|
336
|
+
if (pack.coverage.ratio === null) {
|
|
337
|
+
L.push('No decisions recorded in this period — coverage is indeterminate, not 100%.');
|
|
338
|
+
} else {
|
|
339
|
+
L.push(`${pack.coverage.decisions_guarded} of ${pack.coverage.decisions_total} decision(s) were manifest-guarded — coverage ratio **${pack.coverage.ratio.toFixed(4)}**.`);
|
|
340
|
+
}
|
|
341
|
+
L.push('');
|
|
342
|
+
|
|
343
|
+
L.push('## Integrity warnings');
|
|
344
|
+
if (pack.integrity_warnings.length === 0) {
|
|
345
|
+
L.push('');
|
|
346
|
+
L.push('None.');
|
|
347
|
+
} else {
|
|
348
|
+
L.push('');
|
|
349
|
+
L.push(`${pack.integrity_warnings.length} log entr(ies) could not be classified and are EXCLUDED from the tables above:`);
|
|
350
|
+
L.push('');
|
|
351
|
+
L.push('| Index | Seq | Problem |');
|
|
352
|
+
L.push('| ---: | ---: | --- |');
|
|
353
|
+
for (const w of pack.integrity_warnings) {
|
|
354
|
+
L.push(`| ${w.index} | ${md(w.seq)} | ${md(w.problem)} |`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
L.push('');
|
|
358
|
+
return L.join('\n');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export default { ART14_PACK_VERSION, ART14_HONESTY_NOTICE, buildArt14EvidencePack, renderMarkdown, failingPredicate };
|