@emilia-protocol/gate 0.11.0 → 0.14.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 +80 -0
- package/README.md +310 -0
- package/action-control-manifest.js +3 -268
- package/action-escrow-custodian.js +3 -394
- package/action-escrow-evidence.js +3 -858
- package/action-escrow-package.js +3 -1668
- package/action-escrow-postgres.js +3 -337
- package/action-escrow-state.js +3 -396
- package/action-escrow-verifiers.js +3 -331
- package/action-escrow.js +3 -2447
- 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 +1003 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1737 -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/proposal-to-effect.d.ts +146 -0
- package/dist/proposal-to-effect.d.ts.map +1 -0
- package/dist/proposal-to-effect.js +427 -0
- package/dist/proposal-to-effect.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 +35 -4
- package/proposal-to-effect.js +4 -0
- 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 +2127 -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/proposal-to-effect.ts +571 -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 -102
- 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
package/dist/metering.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* EMILIA Gate — usage metering (the value metric, EP-GATE-USAGE-v1).
|
|
5
|
+
*
|
|
6
|
+
* Pricing scales with what the gate actually protects: PROTECTED IRREVERSIBLE
|
|
7
|
+
* ACTIONS (guarded decisions — allows AND denies both consume enforcement) plus
|
|
8
|
+
* RECEIPT-YEARS under retention (one receipt kept one year = one receipt-year;
|
|
9
|
+
* horizons follow retention.js, default 6y = 2190 days). NEVER seats.
|
|
10
|
+
*
|
|
11
|
+
* Pure functions over evidence-log entries (`evidence.all()`); no clock, no
|
|
12
|
+
* network. The billing period is an explicit [periodStart, periodEnd) window —
|
|
13
|
+
* INCLUSIVE start, EXCLUSIVE end — so adjacent periods never double-count an
|
|
14
|
+
* entry sitting exactly on a boundary.
|
|
15
|
+
*
|
|
16
|
+
* Fail-closed posture for billing: an unbounded or reversed period is refused
|
|
17
|
+
* (thrown); malformed entries are surfaced in `integrity_warnings` rather than
|
|
18
|
+
* silently dropped; an entry whose allow flag is not literally `true` is
|
|
19
|
+
* counted as a deny; a statement over foreign or malformed usage is refused.
|
|
20
|
+
* `buildUsageStatement` output is deterministic (sorted keys + content hash)
|
|
21
|
+
* and UNSIGNED — the deployer signs it; the content hash binds that signature
|
|
22
|
+
* to exactly these numbers for billing reconciliation.
|
|
23
|
+
*/
|
|
24
|
+
import crypto from 'node:crypto';
|
|
25
|
+
export const USAGE_VERSION = 'EP-GATE-USAGE-v1';
|
|
26
|
+
const DAYS_PER_YEAR = 365;
|
|
27
|
+
// Mirrors retention.js's cold-horizon default (coldDays = 2190 = 6y): a receipt
|
|
28
|
+
// is presumed retained for the full audit horizon unless the entry states its own.
|
|
29
|
+
const DEFAULT_RETENTION_YEARS = 2190 / DAYS_PER_YEAR;
|
|
30
|
+
function sha256hex(s) {
|
|
31
|
+
return crypto.createHash('sha256').update(s).digest('hex');
|
|
32
|
+
}
|
|
33
|
+
/** Canonical JSON (recursive sorted keys) — matches evidence.js / @emilia-protocol/verify. */
|
|
34
|
+
function canonical(v) {
|
|
35
|
+
if (v === null || v === undefined)
|
|
36
|
+
return JSON.stringify(v);
|
|
37
|
+
if (Array.isArray(v))
|
|
38
|
+
return `[${v.map(canonical).join(',')}]`;
|
|
39
|
+
if (typeof v === 'object') {
|
|
40
|
+
return `{${Object.keys(v).sort().map((k) => JSON.stringify(k) + ':' + canonical(v[k])).join(',')}}`;
|
|
41
|
+
}
|
|
42
|
+
return JSON.stringify(v);
|
|
43
|
+
}
|
|
44
|
+
function toMs(t) {
|
|
45
|
+
if (t == null)
|
|
46
|
+
return null;
|
|
47
|
+
const ms = typeof t === 'number' ? t : Date.parse(t);
|
|
48
|
+
return Number.isFinite(ms) ? ms : null;
|
|
49
|
+
}
|
|
50
|
+
/** Key-sorted copy so output is byte-stable regardless of entry order. */
|
|
51
|
+
function sortedCounts(map) {
|
|
52
|
+
const out = {};
|
|
53
|
+
for (const k of Object.keys(map).sort())
|
|
54
|
+
out[k] = map[k];
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/** Entry-level day resolution (1/365y ≈ 0.00274) without float noise. */
|
|
58
|
+
function round6(x) {
|
|
59
|
+
return Math.round(x * 1e6) / 1e6;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The retention this entry STATES for itself, in years.
|
|
63
|
+
* @returns {number|null|NaN} years, `null` when unstated (default applies),
|
|
64
|
+
* `NaN` when stated but invalid (default applies + integrity warning — a
|
|
65
|
+
* malformed stated value must never silently shrink the metered total).
|
|
66
|
+
*/
|
|
67
|
+
function statedRetentionYears(e) {
|
|
68
|
+
if (e.retention_years != null) {
|
|
69
|
+
const y = Number(e.retention_years);
|
|
70
|
+
return Number.isFinite(y) && y >= 0 ? y : NaN;
|
|
71
|
+
}
|
|
72
|
+
if (e.retention_days != null) {
|
|
73
|
+
const d = Number(e.retention_days);
|
|
74
|
+
return Number.isFinite(d) && d >= 0 ? d / DAYS_PER_YEAR : NaN;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Meter a billing period over evidence entries.
|
|
80
|
+
*
|
|
81
|
+
* Billable = `kind: 'decision'` entries on GUARDED actions (`not_guarded`
|
|
82
|
+
* pass-throughs are free; execution records are provenance, not enforcement).
|
|
83
|
+
* Window is [periodStart, periodEnd): inclusive start, exclusive end.
|
|
84
|
+
*
|
|
85
|
+
* @param {Array<object>} entries evidence.all()
|
|
86
|
+
* @param {object} [o]
|
|
87
|
+
* @param {string|number} [o.periodStart] ISO or ms — required
|
|
88
|
+
* @param {string|number} [o.periodEnd] ISO or ms — required, >= periodStart
|
|
89
|
+
* @param {number} [o.retentionYearsDefault=6] applied when an entry states no retention
|
|
90
|
+
* @returns {{'@version':string, protected_actions:number, allows:number, denies:number,
|
|
91
|
+
* replays_blocked:number, by_action_type:object, by_tier:object,
|
|
92
|
+
* receipt_years:number, retention_years_default:number, period:object, integrity_warnings:object[]}}
|
|
93
|
+
*/
|
|
94
|
+
export function meterUsage(entries = [], { periodStart, periodEnd, retentionYearsDefault = DEFAULT_RETENTION_YEARS, } = {}) {
|
|
95
|
+
const startMs = toMs(periodStart);
|
|
96
|
+
const endMs = toMs(periodEnd);
|
|
97
|
+
// An unbounded or reversed period is not meterable — refuse rather than emit
|
|
98
|
+
// a statement whose window cannot be reconciled.
|
|
99
|
+
if (startMs == null || endMs == null) {
|
|
100
|
+
throw new Error('meterUsage: periodStart and periodEnd are required (ISO string or ms)');
|
|
101
|
+
}
|
|
102
|
+
if (endMs < startMs)
|
|
103
|
+
throw new Error('meterUsage: periodEnd must be >= periodStart');
|
|
104
|
+
if (!Number.isFinite(retentionYearsDefault) || retentionYearsDefault < 0) {
|
|
105
|
+
throw new Error('meterUsage: retentionYearsDefault must be a finite number >= 0');
|
|
106
|
+
}
|
|
107
|
+
const warnings = [];
|
|
108
|
+
const byAction = Object.create(null);
|
|
109
|
+
const byTier = Object.create(null);
|
|
110
|
+
let protectedActions = 0;
|
|
111
|
+
let allows = 0;
|
|
112
|
+
let denies = 0;
|
|
113
|
+
let replaysBlocked = 0;
|
|
114
|
+
let receiptYears = 0;
|
|
115
|
+
entries.forEach((e, index) => {
|
|
116
|
+
if (!e || typeof e !== 'object' || Array.isArray(e)) {
|
|
117
|
+
warnings.push({ index, reason: 'not_an_object' });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const t = toMs(e.at);
|
|
121
|
+
if (t == null) {
|
|
122
|
+
// Unplaceable in ANY period — surfaced, never silently dropped.
|
|
123
|
+
warnings.push({ index, reason: 'unparseable_at' });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (t < startMs || t >= endMs)
|
|
127
|
+
return; // outside [start, end)
|
|
128
|
+
if (typeof e.kind !== 'string' || e.kind.length === 0) {
|
|
129
|
+
warnings.push({ index, reason: 'missing_kind' });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (e.kind !== 'decision')
|
|
133
|
+
return; // execution/other records are not billable
|
|
134
|
+
if (e.reason === 'not_guarded')
|
|
135
|
+
return; // pass-throughs are free by design
|
|
136
|
+
protectedActions += 1;
|
|
137
|
+
// Fail closed: only a literal `true` counts as an allow.
|
|
138
|
+
if (e.allow === true)
|
|
139
|
+
allows += 1;
|
|
140
|
+
else
|
|
141
|
+
denies += 1;
|
|
142
|
+
if (e.reason === 'replay_refused')
|
|
143
|
+
replaysBlocked += 1;
|
|
144
|
+
const action = typeof e.action === 'string' && e.action ? e.action : 'unknown';
|
|
145
|
+
byAction[action] = (byAction[action] || 0) + 1;
|
|
146
|
+
const tier = typeof e.required_tier === 'string' && e.required_tier ? e.required_tier : 'unknown';
|
|
147
|
+
byTier[tier] = (byTier[tier] || 0) + 1;
|
|
148
|
+
const stated = statedRetentionYears(e);
|
|
149
|
+
if (Number.isNaN(stated)) {
|
|
150
|
+
warnings.push({ index, reason: 'invalid_stated_retention' });
|
|
151
|
+
receiptYears += retentionYearsDefault;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
receiptYears += stated ?? retentionYearsDefault;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
'@version': USAGE_VERSION,
|
|
159
|
+
period: {
|
|
160
|
+
start: new Date(startMs).toISOString(),
|
|
161
|
+
end: new Date(endMs).toISOString(),
|
|
162
|
+
bounds: 'inclusive_start_exclusive_end',
|
|
163
|
+
},
|
|
164
|
+
protected_actions: protectedActions,
|
|
165
|
+
allows,
|
|
166
|
+
denies,
|
|
167
|
+
replays_blocked: replaysBlocked,
|
|
168
|
+
by_action_type: sortedCounts(byAction),
|
|
169
|
+
by_tier: sortedCounts(byTier),
|
|
170
|
+
receipt_years: round6(receiptYears),
|
|
171
|
+
retention_years_default: retentionYearsDefault,
|
|
172
|
+
integrity_warnings: warnings,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Build the signed-ready usage statement handed to billing reconciliation.
|
|
177
|
+
* UNSIGNED — the deployer signs it; `content_hash` (sha256 over the canonical
|
|
178
|
+
* JSON of everything else) binds that signature to exactly these numbers.
|
|
179
|
+
* Deterministic: same usage + org → byte-identical statement, regardless of
|
|
180
|
+
* the entry order the usage was metered from.
|
|
181
|
+
* @param {object} usage a USAGE_VERSION object from meterUsage
|
|
182
|
+
* @param {{ org?: string }} [o]
|
|
183
|
+
*/
|
|
184
|
+
export function buildUsageStatement(usage, { org } = {}) {
|
|
185
|
+
// Never emit a statement over an artifact of a different or unknown format,
|
|
186
|
+
// and never one that fails to name who it bills.
|
|
187
|
+
if (!usage || usage['@version'] !== USAGE_VERSION) {
|
|
188
|
+
throw new Error(`buildUsageStatement: usage must be a ${USAGE_VERSION} object from meterUsage`);
|
|
189
|
+
}
|
|
190
|
+
if (!org || typeof org !== 'string') {
|
|
191
|
+
throw new Error('buildUsageStatement: org is required — a statement must name the billed party');
|
|
192
|
+
}
|
|
193
|
+
if (!usage.period || !usage.period.start || !usage.period.end) {
|
|
194
|
+
throw new Error('buildUsageStatement: usage.period is missing');
|
|
195
|
+
}
|
|
196
|
+
for (const k of ['protected_actions', 'allows', 'denies', 'replays_blocked', 'receipt_years']) {
|
|
197
|
+
if (!Number.isFinite(usage[k]) || usage[k] < 0) {
|
|
198
|
+
throw new Error(`buildUsageStatement: usage.${k} must be a finite number >= 0`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const warningCount = Array.isArray(usage.integrity_warnings) ? usage.integrity_warnings.length : 0;
|
|
202
|
+
const body = {
|
|
203
|
+
'@version': USAGE_VERSION,
|
|
204
|
+
kind: 'usage_statement',
|
|
205
|
+
org,
|
|
206
|
+
period: {
|
|
207
|
+
start: usage.period.start,
|
|
208
|
+
end: usage.period.end,
|
|
209
|
+
bounds: 'inclusive_start_exclusive_end',
|
|
210
|
+
},
|
|
211
|
+
protected_actions: usage.protected_actions,
|
|
212
|
+
allows: usage.allows,
|
|
213
|
+
denies: usage.denies,
|
|
214
|
+
replays_blocked: usage.replays_blocked,
|
|
215
|
+
by_action_type: sortedCounts(usage.by_action_type || {}),
|
|
216
|
+
by_tier: sortedCounts(usage.by_tier || {}),
|
|
217
|
+
receipt_years: usage.receipt_years,
|
|
218
|
+
retention_years_default: usage.retention_years_default ?? DEFAULT_RETENTION_YEARS,
|
|
219
|
+
// Data-quality signal for the reconciler: a statement metered over a log
|
|
220
|
+
// with integrity warnings is flagged incomplete, never silently clean.
|
|
221
|
+
integrity_warning_count: warningCount,
|
|
222
|
+
complete: warningCount === 0,
|
|
223
|
+
};
|
|
224
|
+
return { ...body, content_hash: sha256hex(canonical(body)) };
|
|
225
|
+
}
|
|
226
|
+
export default { meterUsage, buildUsageStatement, USAGE_VERSION };
|
|
227
|
+
//# sourceMappingURL=metering.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metering.js","sourceRoot":"","sources":["../src/metering.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EMILIA Gate — Prometheus metrics exposition (EP-GATE-METRICS-v1).
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency operational metrics over gate decisions, rendered in the
|
|
5
|
+
* Prometheus text exposition format 0.0.4 (HELP/TYPE lines, escaped label
|
|
6
|
+
* values, stable sorted output). Feed it the gate's decision entries — either
|
|
7
|
+
* the evidence-log entry ({ allow, action, reason, have_tier/required_tier,
|
|
8
|
+
* at }) or the `check()` output — via `onDecision`; scrape via `render()` or
|
|
9
|
+
* mount `handler()` on any framework.
|
|
10
|
+
*
|
|
11
|
+
* CONSTRAINT (enforced): metrics must NEVER throw into the enforcement path.
|
|
12
|
+
* `onDecision` sits on the gate's decision hot path; observability is never
|
|
13
|
+
* allowed to break enforcement. Any entry it cannot interpret — wrong type,
|
|
14
|
+
* underivable outcome, even a poisoned object whose property getters throw —
|
|
15
|
+
* increments ep_gate_metrics_malformed_total and returns. No exception
|
|
16
|
+
* escapes `onDecision`, ever.
|
|
17
|
+
*
|
|
18
|
+
* CARDINALITY GUARD: the action_type label is capped to a bounded set via the
|
|
19
|
+
* `maxSeries` option (default 64 distinct values). Once the cap is reached,
|
|
20
|
+
* new action types bucket to action_type="_other" so a hostile or buggy
|
|
21
|
+
* caller cannot blow up the time-series database. All label values are also
|
|
22
|
+
* length-capped. outcome and reason_class are bounded by construction.
|
|
23
|
+
*
|
|
24
|
+
* Deterministic and pure: time is injected (`now`), used only when an entry
|
|
25
|
+
* carries no usable timestamp. Same entries in, same exposition text out.
|
|
26
|
+
*/
|
|
27
|
+
export declare const METRICS_VERSION = "EP-GATE-METRICS-v1";
|
|
28
|
+
/** Prometheus text exposition format 0.0.4 content type. */
|
|
29
|
+
export declare const METRICS_CONTENT_TYPE = "text/plain; version=0.0.4; charset=utf-8";
|
|
30
|
+
/** Bounded denial reason classes — every gate refusal maps into exactly one. */
|
|
31
|
+
export declare const REASON_CLASSES: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Classify a gate denial reason string into one of REASON_CLASSES. Bounded by
|
|
34
|
+
* construction: unknown reasons land in 'other', never in a fresh label value.
|
|
35
|
+
* @param {string} reason e.g. 'replay_refused', 'receipt_rejected:bad_signature'
|
|
36
|
+
* @returns {string} one of REASON_CLASSES
|
|
37
|
+
*/
|
|
38
|
+
export declare function classifyDenialReason(reason: any): "replay" | "receipt_missing" | "receipt_invalid" | "assurance" | "execution_binding" | "infrastructure" | "other";
|
|
39
|
+
/**
|
|
40
|
+
* Create a metrics registry for one gate.
|
|
41
|
+
* @param {object} [o]
|
|
42
|
+
* @param {number} [o.maxSeries=64] cap on distinct action_type label values; overflow buckets to "_other"
|
|
43
|
+
* @param {number|function} [o.now=Date.now] injected clock (ms or () => ms) — used only when an entry has no usable timestamp
|
|
44
|
+
* @returns {{ onDecision: (entry: object) => void, render: () => string, handler: () => { status: number, headers: object, body: string } }}
|
|
45
|
+
*/
|
|
46
|
+
export declare function createMetrics({ maxSeries, now }?: {
|
|
47
|
+
maxSeries?: number | undefined;
|
|
48
|
+
now?: (() => number) | undefined;
|
|
49
|
+
}): {
|
|
50
|
+
onDecision: (entry: any) => void;
|
|
51
|
+
render: () => string;
|
|
52
|
+
handler: () => {
|
|
53
|
+
status: number;
|
|
54
|
+
headers: {
|
|
55
|
+
'content-type': string;
|
|
56
|
+
};
|
|
57
|
+
body: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
declare const _default: {
|
|
61
|
+
createMetrics: typeof createMetrics;
|
|
62
|
+
classifyDenialReason: typeof classifyDenialReason;
|
|
63
|
+
METRICS_VERSION: string;
|
|
64
|
+
METRICS_CONTENT_TYPE: string;
|
|
65
|
+
REASON_CLASSES: string[];
|
|
66
|
+
};
|
|
67
|
+
export default _default;
|
|
68
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,eAAO,MAAM,eAAe,uBAAuB,CAAC;AAEpD,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,6CAA6C,CAAC;AAE/E,gFAAgF;AAChF,eAAO,MAAM,cAAc,UAQ1B,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,KAAA,qHAS1C;AAoCD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,SAAc,EAAE,GAAc,EAAE;;;CAAK;;;;;;;;;;EAyHpE;;;;;;;;AAED,wBAA8G"}
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* EMILIA Gate — Prometheus metrics exposition (EP-GATE-METRICS-v1).
|
|
5
|
+
*
|
|
6
|
+
* Zero-dependency operational metrics over gate decisions, rendered in the
|
|
7
|
+
* Prometheus text exposition format 0.0.4 (HELP/TYPE lines, escaped label
|
|
8
|
+
* values, stable sorted output). Feed it the gate's decision entries — either
|
|
9
|
+
* the evidence-log entry ({ allow, action, reason, have_tier/required_tier,
|
|
10
|
+
* at }) or the `check()` output — via `onDecision`; scrape via `render()` or
|
|
11
|
+
* mount `handler()` on any framework.
|
|
12
|
+
*
|
|
13
|
+
* CONSTRAINT (enforced): metrics must NEVER throw into the enforcement path.
|
|
14
|
+
* `onDecision` sits on the gate's decision hot path; observability is never
|
|
15
|
+
* allowed to break enforcement. Any entry it cannot interpret — wrong type,
|
|
16
|
+
* underivable outcome, even a poisoned object whose property getters throw —
|
|
17
|
+
* increments ep_gate_metrics_malformed_total and returns. No exception
|
|
18
|
+
* escapes `onDecision`, ever.
|
|
19
|
+
*
|
|
20
|
+
* CARDINALITY GUARD: the action_type label is capped to a bounded set via the
|
|
21
|
+
* `maxSeries` option (default 64 distinct values). Once the cap is reached,
|
|
22
|
+
* new action types bucket to action_type="_other" so a hostile or buggy
|
|
23
|
+
* caller cannot blow up the time-series database. All label values are also
|
|
24
|
+
* length-capped. outcome and reason_class are bounded by construction.
|
|
25
|
+
*
|
|
26
|
+
* Deterministic and pure: time is injected (`now`), used only when an entry
|
|
27
|
+
* carries no usable timestamp. Same entries in, same exposition text out.
|
|
28
|
+
*/
|
|
29
|
+
export const METRICS_VERSION = 'EP-GATE-METRICS-v1';
|
|
30
|
+
/** Prometheus text exposition format 0.0.4 content type. */
|
|
31
|
+
export const METRICS_CONTENT_TYPE = 'text/plain; version=0.0.4; charset=utf-8';
|
|
32
|
+
/** Bounded denial reason classes — every gate refusal maps into exactly one. */
|
|
33
|
+
export const REASON_CLASSES = [
|
|
34
|
+
'replay', // replay_refused — one-time consumption caught a reuse
|
|
35
|
+
'receipt_missing', // receipt_required — guarded action arrived with no receipt
|
|
36
|
+
'receipt_invalid', // receipt_rejected:* — signature/freshness/scope/id failures
|
|
37
|
+
'assurance', // assurance_too_low | unknown_required_tier
|
|
38
|
+
'execution_binding', // execution_binding_failed — claim != observed mutation
|
|
39
|
+
'infrastructure', // evidence_log_failed | consumption_store_lacks_reserve
|
|
40
|
+
'other', // anything this version does not model
|
|
41
|
+
];
|
|
42
|
+
/** Longest label value we will expose; longer values are truncated (bounded exposition size). */
|
|
43
|
+
const MAX_LABEL_VALUE_LEN = 128;
|
|
44
|
+
/** Overflow bucket for the action_type cardinality guard. */
|
|
45
|
+
const OTHER_BUCKET = '_other';
|
|
46
|
+
/**
|
|
47
|
+
* Classify a gate denial reason string into one of REASON_CLASSES. Bounded by
|
|
48
|
+
* construction: unknown reasons land in 'other', never in a fresh label value.
|
|
49
|
+
* @param {string} reason e.g. 'replay_refused', 'receipt_rejected:bad_signature'
|
|
50
|
+
* @returns {string} one of REASON_CLASSES
|
|
51
|
+
*/
|
|
52
|
+
export function classifyDenialReason(reason) {
|
|
53
|
+
if (typeof reason !== 'string')
|
|
54
|
+
return 'other';
|
|
55
|
+
if (reason === 'replay_refused' || reason.includes('replay'))
|
|
56
|
+
return 'replay';
|
|
57
|
+
if (reason === 'receipt_required')
|
|
58
|
+
return 'receipt_missing';
|
|
59
|
+
if (reason.startsWith('receipt_rejected'))
|
|
60
|
+
return 'receipt_invalid';
|
|
61
|
+
if (reason === 'assurance_too_low' || reason === 'unknown_required_tier')
|
|
62
|
+
return 'assurance';
|
|
63
|
+
if (reason === 'execution_binding_failed')
|
|
64
|
+
return 'execution_binding';
|
|
65
|
+
if (reason === 'evidence_log_failed' || reason === 'consumption_store_lacks_reserve')
|
|
66
|
+
return 'infrastructure';
|
|
67
|
+
return 'other';
|
|
68
|
+
}
|
|
69
|
+
/** Escape a label value per the exposition format: backslash, quote, newline. */
|
|
70
|
+
function escapeLabelValue(v) {
|
|
71
|
+
return String(v)
|
|
72
|
+
.replace(/\\/g, '\\\\')
|
|
73
|
+
.replace(/"/g, '\\"')
|
|
74
|
+
.replace(/\n/g, '\\n');
|
|
75
|
+
}
|
|
76
|
+
/** Escape HELP text per the exposition format: backslash and newline only. */
|
|
77
|
+
function escapeHelp(v) {
|
|
78
|
+
return String(v).replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
|
|
79
|
+
}
|
|
80
|
+
/** Normalize a raw value into a safe, length-capped label value. */
|
|
81
|
+
function normLabel(raw, fallback) {
|
|
82
|
+
if (typeof raw !== 'string' || raw.length === 0)
|
|
83
|
+
return fallback;
|
|
84
|
+
return raw.length > MAX_LABEL_VALUE_LEN ? raw.slice(0, MAX_LABEL_VALUE_LEN) : raw;
|
|
85
|
+
}
|
|
86
|
+
/** Render a sorted, escaped label set: {a="x",b="y"} — stable key order. */
|
|
87
|
+
function renderLabels(obj) {
|
|
88
|
+
const keys = Object.keys(obj).sort();
|
|
89
|
+
return `{${keys.map((k) => `${k}="${escapeLabelValue(obj[k])}"`).join(',')}}`;
|
|
90
|
+
}
|
|
91
|
+
const METRICS = [
|
|
92
|
+
{ name: 'ep_gate_decisions_total', type: 'counter', help: 'Gate decisions by outcome, action type, and credited assurance tier.' },
|
|
93
|
+
{ name: 'ep_gate_denials_total', type: 'counter', help: 'Denied gate decisions by bounded denial reason class.' },
|
|
94
|
+
{ name: 'ep_gate_evidence_entries_total', type: 'counter', help: 'Evidence-log entries recorded for gate decisions.' },
|
|
95
|
+
{ name: 'ep_gate_last_decision_timestamp_seconds', type: 'gauge', help: 'Unix timestamp (seconds) of the most recent gate decision.' },
|
|
96
|
+
{ name: 'ep_gate_metrics_malformed_total', type: 'counter', help: 'Decision entries the metrics layer could not interpret (dropped, never thrown).' },
|
|
97
|
+
{ name: 'ep_gate_replays_blocked_total', type: 'counter', help: 'Receipt replays refused by one-time consumption.' },
|
|
98
|
+
];
|
|
99
|
+
/**
|
|
100
|
+
* Create a metrics registry for one gate.
|
|
101
|
+
* @param {object} [o]
|
|
102
|
+
* @param {number} [o.maxSeries=64] cap on distinct action_type label values; overflow buckets to "_other"
|
|
103
|
+
* @param {number|function} [o.now=Date.now] injected clock (ms or () => ms) — used only when an entry has no usable timestamp
|
|
104
|
+
* @returns {{ onDecision: (entry: object) => void, render: () => string, handler: () => { status: number, headers: object, body: string } }}
|
|
105
|
+
*/
|
|
106
|
+
export function createMetrics({ maxSeries = 64, now = Date.now } = {}) {
|
|
107
|
+
// Config is clamped, not thrown: a bad option must not brick metrics either.
|
|
108
|
+
const cap = (Number.isInteger(maxSeries) && maxSeries > 0) ? maxSeries : 64;
|
|
109
|
+
const decisions = new Map(); // rendered label set -> count
|
|
110
|
+
const denials = new Map(); // rendered label set -> count
|
|
111
|
+
let replaysBlocked = 0;
|
|
112
|
+
let evidenceEntries = 0;
|
|
113
|
+
let malformed = 0;
|
|
114
|
+
let lastDecisionSeconds = null; // gauge; no sample until the first decision
|
|
115
|
+
const actionTypes = new Set(); // cardinality guard for action_type
|
|
116
|
+
function boundedActionType(raw) {
|
|
117
|
+
const v = normLabel(raw, 'unknown');
|
|
118
|
+
if (actionTypes.has(v))
|
|
119
|
+
return v;
|
|
120
|
+
if (actionTypes.size < cap) {
|
|
121
|
+
actionTypes.add(v);
|
|
122
|
+
return v;
|
|
123
|
+
}
|
|
124
|
+
return OTHER_BUCKET;
|
|
125
|
+
}
|
|
126
|
+
function inc(map, key) {
|
|
127
|
+
map.set(key, (map.get(key) || 0) + 1);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Observe one gate decision. NEVER throws — see the module constraint. A
|
|
131
|
+
* malformed entry (non-object, underivable outcome, throwing getters, ...)
|
|
132
|
+
* increments ep_gate_metrics_malformed_total and returns.
|
|
133
|
+
*/
|
|
134
|
+
function onDecision(entry) {
|
|
135
|
+
try {
|
|
136
|
+
if (!entry || typeof entry !== 'object') {
|
|
137
|
+
malformed += 1;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Outcome: the authoritative field is the boolean `allow` (evidence
|
|
141
|
+
// entry and check() output both carry it). A string outcome is accepted
|
|
142
|
+
// only if it is exactly 'allow'/'deny'. Anything else is malformed.
|
|
143
|
+
let outcome;
|
|
144
|
+
if (entry.allow === true)
|
|
145
|
+
outcome = 'allow';
|
|
146
|
+
else if (entry.allow === false)
|
|
147
|
+
outcome = 'deny';
|
|
148
|
+
else if (entry.outcome === 'allow' || entry.outcome === 'deny')
|
|
149
|
+
outcome = entry.outcome;
|
|
150
|
+
else {
|
|
151
|
+
malformed += 1;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const actionType = boundedActionType(entry.action_type ?? entry.action);
|
|
155
|
+
const tier = normLabel(entry.tier ?? entry.have_tier ?? entry.required_tier, 'unknown');
|
|
156
|
+
inc(decisions, renderLabels({ outcome, action_type: actionType, tier }));
|
|
157
|
+
if (outcome === 'deny') {
|
|
158
|
+
const reasonClass = classifyDenialReason(entry.reason);
|
|
159
|
+
inc(denials, renderLabels({ reason_class: reasonClass }));
|
|
160
|
+
if (reasonClass === 'replay')
|
|
161
|
+
replaysBlocked += 1;
|
|
162
|
+
}
|
|
163
|
+
// Each decision appends one evidence record — unless the entry says the
|
|
164
|
+
// write failed outright (check() output carries evidence: null then).
|
|
165
|
+
if (entry.evidence !== null)
|
|
166
|
+
evidenceEntries += 1;
|
|
167
|
+
// Gauge: prefer the entry's own timestamp (`at` ISO/ms), else the
|
|
168
|
+
// injected clock. An unusable clock skips the gauge — never throws.
|
|
169
|
+
const at = entry.at ?? entry.created_at ?? null;
|
|
170
|
+
let ms = null;
|
|
171
|
+
if (typeof at === 'number' && Number.isFinite(at))
|
|
172
|
+
ms = at;
|
|
173
|
+
else if (typeof at === 'string') {
|
|
174
|
+
const p = Date.parse(at);
|
|
175
|
+
if (Number.isFinite(p))
|
|
176
|
+
ms = p;
|
|
177
|
+
}
|
|
178
|
+
if (ms == null) {
|
|
179
|
+
try {
|
|
180
|
+
const n = typeof now === 'function' ? now() : now;
|
|
181
|
+
if (typeof n === 'number' && Number.isFinite(n))
|
|
182
|
+
ms = n;
|
|
183
|
+
}
|
|
184
|
+
catch { /* unusable injected clock: skip the gauge update */ }
|
|
185
|
+
}
|
|
186
|
+
if (ms != null)
|
|
187
|
+
lastDecisionSeconds = ms / 1000;
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// The never-throw guarantee: a poisoned entry (throwing getter, hostile
|
|
191
|
+
// proxy) lands here. Count it, drop it, return. Enforcement continues.
|
|
192
|
+
malformed += 1;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** Render Prometheus text format 0.0.4. Deterministic: metrics in fixed order, series sorted. */
|
|
196
|
+
function render() {
|
|
197
|
+
const lines = [];
|
|
198
|
+
for (const m of METRICS) {
|
|
199
|
+
lines.push(`# HELP ${m.name} ${escapeHelp(m.help)}`);
|
|
200
|
+
lines.push(`# TYPE ${m.name} ${m.type}`);
|
|
201
|
+
switch (m.name) {
|
|
202
|
+
case 'ep_gate_decisions_total':
|
|
203
|
+
for (const k of [...decisions.keys()].sort())
|
|
204
|
+
lines.push(`${m.name}${k} ${decisions.get(k)}`);
|
|
205
|
+
break;
|
|
206
|
+
case 'ep_gate_denials_total':
|
|
207
|
+
for (const k of [...denials.keys()].sort())
|
|
208
|
+
lines.push(`${m.name}${k} ${denials.get(k)}`);
|
|
209
|
+
break;
|
|
210
|
+
case 'ep_gate_evidence_entries_total':
|
|
211
|
+
lines.push(`${m.name} ${evidenceEntries}`);
|
|
212
|
+
break;
|
|
213
|
+
case 'ep_gate_last_decision_timestamp_seconds':
|
|
214
|
+
// No sample until the first decision — a fabricated 0 would read as 1970.
|
|
215
|
+
if (lastDecisionSeconds != null)
|
|
216
|
+
lines.push(`${m.name} ${lastDecisionSeconds}`);
|
|
217
|
+
break;
|
|
218
|
+
case 'ep_gate_metrics_malformed_total':
|
|
219
|
+
lines.push(`${m.name} ${malformed}`);
|
|
220
|
+
break;
|
|
221
|
+
case 'ep_gate_replays_blocked_total':
|
|
222
|
+
lines.push(`${m.name} ${replaysBlocked}`);
|
|
223
|
+
break;
|
|
224
|
+
/* c8 ignore next 2 -- METRICS is a module constant; no other names exist */
|
|
225
|
+
default:
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return lines.join('\n') + '\n';
|
|
230
|
+
}
|
|
231
|
+
/** Framework-agnostic scrape response: mount on any router/handler. */
|
|
232
|
+
function handler() {
|
|
233
|
+
return {
|
|
234
|
+
status: 200,
|
|
235
|
+
headers: { 'content-type': METRICS_CONTENT_TYPE },
|
|
236
|
+
body: render(),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return { onDecision, render, handler };
|
|
240
|
+
}
|
|
241
|
+
export default { createMetrics, classifyDenialReason, METRICS_VERSION, METRICS_CONTENT_TYPE, REASON_CLASSES };
|
|
242
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|