eve-ai-governance 0.2.0 → 0.3.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/README.md +44 -39
- package/dist/cjs/attestation.d.ts +29 -0
- package/dist/cjs/attestation.d.ts.map +1 -0
- package/dist/cjs/attestation.js +42 -0
- package/dist/cjs/attestation.js.map +1 -0
- package/dist/cjs/canonical.d.ts +51 -0
- package/dist/cjs/canonical.d.ts.map +1 -0
- package/dist/cjs/canonical.js +168 -0
- package/dist/cjs/canonical.js.map +1 -0
- package/dist/cjs/decision-web.d.ts +29 -0
- package/dist/cjs/decision-web.d.ts.map +1 -0
- package/dist/cjs/decision-web.js +315 -0
- package/dist/cjs/decision-web.js.map +1 -0
- package/dist/cjs/decision.d.ts +62 -0
- package/dist/cjs/decision.d.ts.map +1 -0
- package/dist/cjs/decision.js +317 -0
- package/dist/cjs/decision.js.map +1 -0
- package/dist/cjs/index.d.ts +31 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +48 -15
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/iti.d.ts +33 -0
- package/dist/cjs/iti.d.ts.map +1 -0
- package/dist/cjs/iti.js +42 -0
- package/dist/cjs/iti.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/policy.d.ts +13 -0
- package/dist/cjs/policy.d.ts.map +1 -0
- package/dist/cjs/policy.js +18 -0
- package/dist/cjs/policy.js.map +1 -0
- package/dist/cjs/replay.d.ts +26 -0
- package/dist/cjs/replay.d.ts.map +1 -0
- package/dist/cjs/replay.js +39 -0
- package/dist/cjs/replay.js.map +1 -0
- package/dist/cjs/trust_root.d.ts +13 -0
- package/dist/cjs/trust_root.d.ts.map +1 -0
- package/dist/cjs/trust_root.js +18 -0
- package/dist/cjs/trust_root.js.map +1 -0
- package/dist/cjs/types.d.ts +195 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +9 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/verify.d.ts +191 -0
- package/dist/cjs/verify.d.ts.map +1 -0
- package/dist/cjs/verify.js +615 -0
- package/dist/cjs/verify.js.map +1 -0
- package/dist/esm/attestation.d.ts +29 -0
- package/dist/esm/attestation.d.ts.map +1 -0
- package/dist/esm/attestation.js +37 -0
- package/dist/esm/attestation.js.map +1 -0
- package/dist/esm/canonical.d.ts +51 -0
- package/dist/esm/canonical.d.ts.map +1 -0
- package/dist/esm/canonical.js +157 -0
- package/dist/esm/canonical.js.map +1 -0
- package/dist/esm/decision-web.d.ts +29 -0
- package/dist/esm/decision-web.d.ts.map +1 -0
- package/dist/esm/decision-web.js +312 -0
- package/dist/esm/decision-web.js.map +1 -0
- package/dist/esm/decision.d.ts +62 -0
- package/dist/esm/decision.d.ts.map +1 -0
- package/dist/esm/decision.js +314 -0
- package/dist/esm/decision.js.map +1 -0
- package/dist/esm/index.d.ts +31 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +31 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/iti.d.ts +33 -0
- package/dist/esm/iti.d.ts.map +1 -0
- package/dist/esm/iti.js +38 -0
- package/dist/esm/iti.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/policy.d.ts +13 -0
- package/dist/esm/policy.d.ts.map +1 -0
- package/dist/esm/policy.js +15 -0
- package/dist/esm/policy.js.map +1 -0
- package/dist/esm/replay.d.ts +26 -0
- package/dist/esm/replay.d.ts.map +1 -0
- package/dist/esm/replay.js +34 -0
- package/dist/esm/replay.js.map +1 -0
- package/dist/esm/trust_root.d.ts +13 -0
- package/dist/esm/trust_root.d.ts.map +1 -0
- package/dist/esm/trust_root.js +15 -0
- package/dist/esm/trust_root.js.map +1 -0
- package/dist/esm/types.d.ts +195 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +8 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/verify.d.ts +191 -0
- package/dist/esm/verify.d.ts.map +1 -0
- package/dist/esm/verify.js +575 -0
- package/dist/esm/verify.js.map +1 -0
- package/package.json +46 -30
- package/src/attestation.ts +50 -0
- package/src/canonical.ts +138 -0
- package/src/decision-web.ts +324 -0
- package/src/decision.ts +339 -0
- package/src/index.ts +54 -91
- package/src/iti.ts +44 -0
- package/src/policy.ts +20 -0
- package/src/replay.ts +44 -0
- package/src/trust_root.ts +20 -0
- package/src/types.ts +215 -0
- package/src/verify.ts +630 -0
- package/LICENSE +0 -18
- package/dist/cjs/client.d.ts +0 -175
- package/dist/cjs/client.d.ts.map +0 -1
- package/dist/cjs/client.js +0 -896
- package/dist/cjs/client.js.map +0 -1
- package/dist/cjs/errors.d.ts +0 -57
- package/dist/cjs/errors.d.ts.map +0 -1
- package/dist/cjs/errors.js +0 -95
- package/dist/cjs/errors.js.map +0 -1
- package/dist/cjs/models.d.ts +0 -499
- package/dist/cjs/models.d.ts.map +0 -1
- package/dist/cjs/models.js +0 -3
- package/dist/cjs/models.js.map +0 -1
- package/dist/esm/client.d.ts +0 -175
- package/dist/esm/client.d.ts.map +0 -1
- package/dist/esm/client.js +0 -891
- package/dist/esm/client.js.map +0 -1
- package/dist/esm/errors.d.ts +0 -57
- package/dist/esm/errors.d.ts.map +0 -1
- package/dist/esm/errors.js +0 -82
- package/dist/esm/errors.js.map +0 -1
- package/dist/esm/models.d.ts +0 -499
- package/dist/esm/models.d.ts.map +0 -1
- package/dist/esm/models.js +0 -2
- package/dist/esm/models.js.map +0 -1
- package/src/client.ts +0 -1061
- package/src/errors.ts +0 -81
- package/src/models.ts +0 -581
package/README.md
CHANGED
|
@@ -1,58 +1,63 @@
|
|
|
1
|
-
# eve-
|
|
1
|
+
# eve-governance (TypeScript)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
TypeScript SDK for offline cryptographic verification of EVE AI Core
|
|
4
|
+
governance artifacts.
|
|
5
|
+
|
|
6
|
+
> **Note:** This package provides the TypeScript API contract and type
|
|
7
|
+
> definitions. Implementation bodies are stubs; the Python SDK
|
|
8
|
+
> (`sdks/governance/`) contains the reference implementation.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
5
11
|
|
|
6
12
|
```bash
|
|
7
|
-
npm install eve-
|
|
13
|
+
npm install eve-governance
|
|
8
14
|
```
|
|
9
15
|
|
|
10
|
-
|
|
16
|
+
## Usage
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
```typescript
|
|
19
|
+
import {
|
|
20
|
+
verifyDecisionCertificate,
|
|
21
|
+
verifyChain,
|
|
22
|
+
verifyItiSnapshot,
|
|
23
|
+
healthBand,
|
|
24
|
+
} from "eve-governance";
|
|
13
25
|
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
// Verify a decision certificate
|
|
27
|
+
const result = await verifyDecisionCertificate(cert);
|
|
28
|
+
console.log(result.valid ? "✓ VERIFIED" : "✗ FAILED");
|
|
16
29
|
|
|
17
|
-
|
|
30
|
+
// Health band
|
|
31
|
+
console.log(healthBand(87.5)); // "GOOD"
|
|
32
|
+
```
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
request_id: 'req-001',
|
|
21
|
-
tenant_id: 'bank_001',
|
|
22
|
-
proposed_action: { type: 'loan_approval', amount: 250000 },
|
|
23
|
-
model_output: { decision: 'approve', confidence: 0.91 },
|
|
24
|
-
context: { credit_score: 580, debt_to_income: 0.52 },
|
|
25
|
-
policy_set: 'lending_v1',
|
|
26
|
-
});
|
|
27
|
-
// result.decision.status -> "ALLOWED" | "BLOCKED" | "MODIFIED"
|
|
34
|
+
## API
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
client.rateLimit; // { limit, remaining } | { limit: null, ... }
|
|
32
|
-
client.quotaWarning; // null | 'payment_past_due'
|
|
33
|
-
```
|
|
36
|
+
### `verifyHmac(payload, signature, key)`
|
|
37
|
+
Verify an HMAC-SHA256 signature.
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for the full status-code and accessor reference (`RateLimitError` on 429,
|
|
38
|
-
`PaymentRequiredError` on 402).
|
|
39
|
+
### `verifyDecisionCertificate(certDict, options?)`
|
|
40
|
+
Verify a single EVE CoreGuard decision certificate.
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
### `verifyBundle(bundlePath, options?)`
|
|
43
|
+
Verify a replay export bundle (ZIP or JSONL).
|
|
41
44
|
|
|
42
|
-
`
|
|
43
|
-
|
|
44
|
-
compatible with the Python SDKs (`json.dumps(sort_keys=True)`), so a proof signed
|
|
45
|
-
by EVE verifies here and vice-versa. Tampering any field (including nested ones)
|
|
46
|
-
fails; a wrong/empty signature returns `false` (never throws).
|
|
45
|
+
### `verifyChain(events)`
|
|
46
|
+
Verify hash-chain integrity of a list of audit events.
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
### `verifyItiSnapshot(snapshot, options?)`
|
|
49
|
+
Verify an ITI snapshot.
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
### `healthBand(compositeScore)`
|
|
52
|
+
Map a score (0–100) to a health band string.
|
|
53
|
+
|
|
54
|
+
### `analyzeReplayChain(events)`
|
|
55
|
+
Analyze a replay chain and return structured metrics.
|
|
56
|
+
|
|
57
|
+
## Types
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
See `src/types.ts` for all TypeScript interfaces.
|
|
55
60
|
|
|
56
61
|
## License
|
|
57
62
|
|
|
58
|
-
Proprietary
|
|
63
|
+
Proprietary — EVE NeuroSystems LLC
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EVE Governance SDK — Attestation verification stubs (TypeScript).
|
|
3
|
+
*/
|
|
4
|
+
import type { VerificationResult, VerifyOptions } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Verify a deployment attestation / build provenance artifact.
|
|
7
|
+
*
|
|
8
|
+
* @param attestation - The attestation dict.
|
|
9
|
+
* @param options - Optional signing key override.
|
|
10
|
+
* @returns - Resolves to a `VerificationResult`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifyDeploymentAttestation(attestation: Record<string, unknown>, options?: VerifyOptions): Promise<VerificationResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Verify a tenant trust certificate.
|
|
15
|
+
*
|
|
16
|
+
* @param cert - The trust certificate dict.
|
|
17
|
+
* @param options - Optional signing key override.
|
|
18
|
+
* @returns - Resolves to a `VerificationResult`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function verifyTrustCertificate(cert: Record<string, unknown>, options?: VerifyOptions): Promise<VerificationResult>;
|
|
21
|
+
/**
|
|
22
|
+
* Verify an enterprise onboarding bundle.
|
|
23
|
+
*
|
|
24
|
+
* @param bundle - The onboarding bundle dict.
|
|
25
|
+
* @param options - Optional signing key override.
|
|
26
|
+
* @returns - Resolves to a `VerificationResult`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function verifyOnboardingBundle(bundle: Record<string, unknown>, options?: VerifyOptions): Promise<VerificationResult>;
|
|
29
|
+
//# sourceMappingURL=attestation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../../src/attestation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAG7B;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAG7B;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAG7B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* EVE Governance SDK — Attestation verification stubs (TypeScript).
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.verifyDeploymentAttestation = verifyDeploymentAttestation;
|
|
7
|
+
exports.verifyTrustCertificate = verifyTrustCertificate;
|
|
8
|
+
exports.verifyOnboardingBundle = verifyOnboardingBundle;
|
|
9
|
+
/**
|
|
10
|
+
* Verify a deployment attestation / build provenance artifact.
|
|
11
|
+
*
|
|
12
|
+
* @param attestation - The attestation dict.
|
|
13
|
+
* @param options - Optional signing key override.
|
|
14
|
+
* @returns - Resolves to a `VerificationResult`.
|
|
15
|
+
*/
|
|
16
|
+
async function verifyDeploymentAttestation(attestation, options) {
|
|
17
|
+
// TODO: implement
|
|
18
|
+
throw new Error("Not implemented");
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Verify a tenant trust certificate.
|
|
22
|
+
*
|
|
23
|
+
* @param cert - The trust certificate dict.
|
|
24
|
+
* @param options - Optional signing key override.
|
|
25
|
+
* @returns - Resolves to a `VerificationResult`.
|
|
26
|
+
*/
|
|
27
|
+
async function verifyTrustCertificate(cert, options) {
|
|
28
|
+
// TODO: implement
|
|
29
|
+
throw new Error("Not implemented");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Verify an enterprise onboarding bundle.
|
|
33
|
+
*
|
|
34
|
+
* @param bundle - The onboarding bundle dict.
|
|
35
|
+
* @param options - Optional signing key override.
|
|
36
|
+
* @returns - Resolves to a `VerificationResult`.
|
|
37
|
+
*/
|
|
38
|
+
async function verifyOnboardingBundle(bundle, options) {
|
|
39
|
+
// TODO: implement
|
|
40
|
+
throw new Error("Not implemented");
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=attestation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../src/attestation.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAWH,kEAMC;AASD,wDAMC;AASD,wDAMC;AA3CD;;;;;;GAMG;AACI,KAAK,UAAU,2BAA2B,CAC/C,WAAoC,EACpC,OAAuB;IAEvB,kBAAkB;IAClB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,sBAAsB,CAC1C,IAA6B,EAC7B,OAAuB;IAEvB,kBAAkB;IAClB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,sBAAsB,CAC1C,MAA+B,EAC/B,OAAuB;IAEvB,kBAAkB;IAClB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EVE Governance SDK — pure canonicalization primitives.
|
|
3
|
+
*
|
|
4
|
+
* ZERO runtime dependencies and ZERO platform APIs (no `node:crypto`, no
|
|
5
|
+
* `Buffer`) — safe to run in Node **and** in the browser. This is the single
|
|
6
|
+
* source of truth for the serialization used by every verifier
|
|
7
|
+
* (`verify.ts` = Node, `decision.ts` = Node asymmetric, `decision-web.ts` =
|
|
8
|
+
* browser/WebCrypto), so their canonical bytes cannot drift apart.
|
|
9
|
+
*
|
|
10
|
+
* Two serializations, matching the Python backend byte-for-byte:
|
|
11
|
+
* - COMPACT json.dumps(obj, sort_keys=True, separators=(",",":"))
|
|
12
|
+
* -> eve-request-v1 / eve-response-v1 preimage digests + HMAC certs
|
|
13
|
+
* - DEFAULT-SEP json.dumps(payload, sort_keys=True) (", " / ": ")
|
|
14
|
+
* -> eve-jsonc-v1 decision-record content hash
|
|
15
|
+
*
|
|
16
|
+
* Both use ensure_ascii=True (non-ASCII -> \uXXXX) and recursive key sorting by
|
|
17
|
+
* Unicode code point.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Compare two strings by Unicode code point (matching Python `sort_keys=True`),
|
|
21
|
+
* NOT by UTF-16 code unit (JS default `Array.sort`), which diverges for
|
|
22
|
+
* astral-plane keys.
|
|
23
|
+
*/
|
|
24
|
+
export declare function compareCodePoints(a: string, b: string): number;
|
|
25
|
+
/** Deep-copy with all object keys recursively sorted; arrays keep order. */
|
|
26
|
+
export declare function sortKeys(obj: unknown): unknown;
|
|
27
|
+
/**
|
|
28
|
+
* Escape to match Python `json.dumps` default (`ensure_ascii=True`): standard
|
|
29
|
+
* short escapes, `\uXXXX` (lowercase hex) for every other control char and every
|
|
30
|
+
* non-ASCII UTF-16 code unit. `/` is not escaped. Iterating code units yields
|
|
31
|
+
* the surrogate halves Python emits for astral characters.
|
|
32
|
+
*/
|
|
33
|
+
export declare function escapeString(s: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Format a number to match Python `json.dumps`. Integers emit without a decimal
|
|
36
|
+
* point; non-integers use JS shortest repr (agrees with Python for the decimal
|
|
37
|
+
* values in EVE evidence). See the canonicalization registry for the
|
|
38
|
+
* integer-valued-float cross-language constraint.
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatNumber(n: number): string;
|
|
41
|
+
/** Compact serialization of an ALREADY key-sorted value (separators ",",":"). */
|
|
42
|
+
export declare function serializeCompact(value: unknown): string;
|
|
43
|
+
/** Default-separator serialization of an ALREADY key-sorted value (", " / ": "). */
|
|
44
|
+
export declare function serializeDefaultSep(value: unknown): string;
|
|
45
|
+
/** Canonical compact JSON bytes of a payload (sorts keys, then compact). */
|
|
46
|
+
export declare function canonicalizeCompact(payload: Record<string, unknown>): string;
|
|
47
|
+
/** Canonical default-separator JSON bytes of a payload (sorts keys, then ", "/": "). */
|
|
48
|
+
export declare function canonicalizeDefaultSep(payload: Record<string, unknown>): string;
|
|
49
|
+
/** Constant-time-ish equality for two strings (no platform crypto needed). */
|
|
50
|
+
export declare function constantTimeEqual(a: string, b: string): boolean;
|
|
51
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../src/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU9D;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAW9C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAqB9C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO9C;AAmBD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEvD;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE1D;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAE5E;AAED,wFAAwF;AACxF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAE/E;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAK/D"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* EVE Governance SDK — pure canonicalization primitives.
|
|
4
|
+
*
|
|
5
|
+
* ZERO runtime dependencies and ZERO platform APIs (no `node:crypto`, no
|
|
6
|
+
* `Buffer`) — safe to run in Node **and** in the browser. This is the single
|
|
7
|
+
* source of truth for the serialization used by every verifier
|
|
8
|
+
* (`verify.ts` = Node, `decision.ts` = Node asymmetric, `decision-web.ts` =
|
|
9
|
+
* browser/WebCrypto), so their canonical bytes cannot drift apart.
|
|
10
|
+
*
|
|
11
|
+
* Two serializations, matching the Python backend byte-for-byte:
|
|
12
|
+
* - COMPACT json.dumps(obj, sort_keys=True, separators=(",",":"))
|
|
13
|
+
* -> eve-request-v1 / eve-response-v1 preimage digests + HMAC certs
|
|
14
|
+
* - DEFAULT-SEP json.dumps(payload, sort_keys=True) (", " / ": ")
|
|
15
|
+
* -> eve-jsonc-v1 decision-record content hash
|
|
16
|
+
*
|
|
17
|
+
* Both use ensure_ascii=True (non-ASCII -> \uXXXX) and recursive key sorting by
|
|
18
|
+
* Unicode code point.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.compareCodePoints = compareCodePoints;
|
|
22
|
+
exports.sortKeys = sortKeys;
|
|
23
|
+
exports.escapeString = escapeString;
|
|
24
|
+
exports.formatNumber = formatNumber;
|
|
25
|
+
exports.serializeCompact = serializeCompact;
|
|
26
|
+
exports.serializeDefaultSep = serializeDefaultSep;
|
|
27
|
+
exports.canonicalizeCompact = canonicalizeCompact;
|
|
28
|
+
exports.canonicalizeDefaultSep = canonicalizeDefaultSep;
|
|
29
|
+
exports.constantTimeEqual = constantTimeEqual;
|
|
30
|
+
/**
|
|
31
|
+
* Compare two strings by Unicode code point (matching Python `sort_keys=True`),
|
|
32
|
+
* NOT by UTF-16 code unit (JS default `Array.sort`), which diverges for
|
|
33
|
+
* astral-plane keys.
|
|
34
|
+
*/
|
|
35
|
+
function compareCodePoints(a, b) {
|
|
36
|
+
const ia = Array.from(a);
|
|
37
|
+
const ib = Array.from(b);
|
|
38
|
+
const n = Math.min(ia.length, ib.length);
|
|
39
|
+
for (let i = 0; i < n; i += 1) {
|
|
40
|
+
const ca = ia[i].codePointAt(0);
|
|
41
|
+
const cb = ib[i].codePointAt(0);
|
|
42
|
+
if (ca !== cb)
|
|
43
|
+
return ca - cb;
|
|
44
|
+
}
|
|
45
|
+
return ia.length - ib.length;
|
|
46
|
+
}
|
|
47
|
+
/** Deep-copy with all object keys recursively sorted; arrays keep order. */
|
|
48
|
+
function sortKeys(obj) {
|
|
49
|
+
if (Array.isArray(obj))
|
|
50
|
+
return obj.map(sortKeys);
|
|
51
|
+
if (obj !== null && typeof obj === "object") {
|
|
52
|
+
const src = obj;
|
|
53
|
+
const sorted = {};
|
|
54
|
+
for (const key of Object.keys(src).sort(compareCodePoints)) {
|
|
55
|
+
sorted[key] = sortKeys(src[key]);
|
|
56
|
+
}
|
|
57
|
+
return sorted;
|
|
58
|
+
}
|
|
59
|
+
return obj;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Escape to match Python `json.dumps` default (`ensure_ascii=True`): standard
|
|
63
|
+
* short escapes, `\uXXXX` (lowercase hex) for every other control char and every
|
|
64
|
+
* non-ASCII UTF-16 code unit. `/` is not escaped. Iterating code units yields
|
|
65
|
+
* the surrogate halves Python emits for astral characters.
|
|
66
|
+
*/
|
|
67
|
+
function escapeString(s) {
|
|
68
|
+
let out = '"';
|
|
69
|
+
for (let i = 0; i < s.length; i += 1) {
|
|
70
|
+
const code = s.charCodeAt(i);
|
|
71
|
+
switch (code) {
|
|
72
|
+
case 0x22:
|
|
73
|
+
out += '\\"';
|
|
74
|
+
break;
|
|
75
|
+
case 0x5c:
|
|
76
|
+
out += "\\\\";
|
|
77
|
+
break;
|
|
78
|
+
case 0x08:
|
|
79
|
+
out += "\\b";
|
|
80
|
+
break;
|
|
81
|
+
case 0x09:
|
|
82
|
+
out += "\\t";
|
|
83
|
+
break;
|
|
84
|
+
case 0x0a:
|
|
85
|
+
out += "\\n";
|
|
86
|
+
break;
|
|
87
|
+
case 0x0c:
|
|
88
|
+
out += "\\f";
|
|
89
|
+
break;
|
|
90
|
+
case 0x0d:
|
|
91
|
+
out += "\\r";
|
|
92
|
+
break;
|
|
93
|
+
default:
|
|
94
|
+
if (code < 0x20 || code > 0x7e) {
|
|
95
|
+
out += "\\u" + code.toString(16).padStart(4, "0");
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
out += s[i];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return out + '"';
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Format a number to match Python `json.dumps`. Integers emit without a decimal
|
|
106
|
+
* point; non-integers use JS shortest repr (agrees with Python for the decimal
|
|
107
|
+
* values in EVE evidence). See the canonicalization registry for the
|
|
108
|
+
* integer-valued-float cross-language constraint.
|
|
109
|
+
*/
|
|
110
|
+
function formatNumber(n) {
|
|
111
|
+
if (!Number.isFinite(n)) {
|
|
112
|
+
if (Number.isNaN(n))
|
|
113
|
+
return "NaN";
|
|
114
|
+
return n > 0 ? "Infinity" : "-Infinity";
|
|
115
|
+
}
|
|
116
|
+
if (Number.isInteger(n))
|
|
117
|
+
return Object.is(n, -0) ? "0" : String(n);
|
|
118
|
+
return String(n);
|
|
119
|
+
}
|
|
120
|
+
function serializeWith(value, itemSep, kvSep) {
|
|
121
|
+
if (value === null || value === undefined)
|
|
122
|
+
return "null";
|
|
123
|
+
const t = typeof value;
|
|
124
|
+
if (t === "string")
|
|
125
|
+
return escapeString(value);
|
|
126
|
+
if (t === "number")
|
|
127
|
+
return formatNumber(value);
|
|
128
|
+
if (t === "boolean")
|
|
129
|
+
return value ? "true" : "false";
|
|
130
|
+
if (t === "bigint")
|
|
131
|
+
return value.toString();
|
|
132
|
+
if (Array.isArray(value))
|
|
133
|
+
return "[" + value.map((v) => serializeWith(v, itemSep, kvSep)).join(itemSep) + "]";
|
|
134
|
+
if (t === "object") {
|
|
135
|
+
const obj = value;
|
|
136
|
+
const parts = [];
|
|
137
|
+
for (const key of Object.keys(obj))
|
|
138
|
+
parts.push(escapeString(key) + kvSep + serializeWith(obj[key], itemSep, kvSep));
|
|
139
|
+
return "{" + parts.join(itemSep) + "}";
|
|
140
|
+
}
|
|
141
|
+
return "null";
|
|
142
|
+
}
|
|
143
|
+
/** Compact serialization of an ALREADY key-sorted value (separators ",",":"). */
|
|
144
|
+
function serializeCompact(value) {
|
|
145
|
+
return serializeWith(value, ",", ":");
|
|
146
|
+
}
|
|
147
|
+
/** Default-separator serialization of an ALREADY key-sorted value (", " / ": "). */
|
|
148
|
+
function serializeDefaultSep(value) {
|
|
149
|
+
return serializeWith(value, ", ", ": ");
|
|
150
|
+
}
|
|
151
|
+
/** Canonical compact JSON bytes of a payload (sorts keys, then compact). */
|
|
152
|
+
function canonicalizeCompact(payload) {
|
|
153
|
+
return serializeCompact(sortKeys(payload));
|
|
154
|
+
}
|
|
155
|
+
/** Canonical default-separator JSON bytes of a payload (sorts keys, then ", "/": "). */
|
|
156
|
+
function canonicalizeDefaultSep(payload) {
|
|
157
|
+
return serializeDefaultSep(sortKeys(payload));
|
|
158
|
+
}
|
|
159
|
+
/** Constant-time-ish equality for two strings (no platform crypto needed). */
|
|
160
|
+
function constantTimeEqual(a, b) {
|
|
161
|
+
if (a.length !== b.length)
|
|
162
|
+
return false;
|
|
163
|
+
let diff = 0;
|
|
164
|
+
for (let i = 0; i < a.length; i += 1)
|
|
165
|
+
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
166
|
+
return diff === 0;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/canonical.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EVE Governance SDK — BROWSER decision-record verifier (WebCrypto).
|
|
3
|
+
*
|
|
4
|
+
* The browser/isomorphic counterpart of `decision.ts`. It verifies the
|
|
5
|
+
* asymmetric, independently-verifiable `eve.decision.v3` decision certificate
|
|
6
|
+
* (`ed25519-` / `ecdsa-p256-`) using **WebCrypto (`crypto.subtle`)** and the
|
|
7
|
+
* shared pure canonicalization in `canonical.ts` — so its bytes match the Node
|
|
8
|
+
* and Python verifiers exactly. No `node:*` imports; runs in the browser and in
|
|
9
|
+
* Node (>=20). Public key only — no shared secret.
|
|
10
|
+
*
|
|
11
|
+
* `verifyDecisionRecordWeb` is **async** (WebCrypto is promise-based). HMAC
|
|
12
|
+
* records are reported not-independently-verifiable and are NOT verified here
|
|
13
|
+
* (symmetric verification belongs on a trusted server, not the browser).
|
|
14
|
+
*
|
|
15
|
+
* Browser support note: WebCrypto Ed25519 requires a recent browser
|
|
16
|
+
* (Chrome/Edge 137+, Firefox 129+, Safari 17+) or Node >=20. ECDSA-P256 is
|
|
17
|
+
* universally supported. If the runtime lacks Ed25519, verification returns a
|
|
18
|
+
* clear `valid:false` reason rather than throwing.
|
|
19
|
+
*/
|
|
20
|
+
import type { DecisionRecordVerificationResult } from "./types.js";
|
|
21
|
+
import type { VerifyDecisionRecordOptions } from "./decision.js";
|
|
22
|
+
/**
|
|
23
|
+
* Verify an EVE decision record (or `{decision_record, verification}` wrapper)
|
|
24
|
+
* in the browser with WebCrypto. Async; mirrors `verifyDecisionRecord` (Node).
|
|
25
|
+
* HMAC records are reported not-independently-verifiable (not verified here).
|
|
26
|
+
* Never throws — failures resolve to `{ valid: false, ... }`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function verifyDecisionRecordWeb(recordOrEvidence: Record<string, unknown>, options?: VerifyDecisionRecordOptions): Promise<DecisionRecordVerificationResult>;
|
|
29
|
+
//# sourceMappingURL=decision-web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-web.d.ts","sourceRoot":"","sources":["../../src/decision-web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AA8MjE;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzC,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,gCAAgC,CAAC,CAkF3C"}
|