@clawbureau/clawverify-core 0.1.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/LICENSE +21 -0
- package/README.md +40 -0
- package/dist/crypto.d.ts +27 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +124 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/jcs.d.ts +13 -0
- package/dist/jcs.d.ts.map +1 -0
- package/dist/jcs.js +43 -0
- package/dist/jcs.js.map +1 -0
- package/dist/model-identity.d.ts +46 -0
- package/dist/model-identity.d.ts.map +1 -0
- package/dist/model-identity.js +233 -0
- package/dist/model-identity.js.map +1 -0
- package/dist/schema-registry.d.ts +99 -0
- package/dist/schema-registry.d.ts.map +1 -0
- package/dist/schema-registry.js +259 -0
- package/dist/schema-registry.js.map +1 -0
- package/dist/schema-validation.d.ts +35 -0
- package/dist/schema-validation.d.ts.map +1 -0
- package/dist/schema-validation.js +156 -0
- package/dist/schema-validation.js.map +1 -0
- package/dist/schema-validators.generated.d.ts +158 -0
- package/dist/schema-validators.generated.d.ts.map +1 -0
- package/dist/schema-validators.generated.js +19186 -0
- package/dist/schema-validators.generated.js.map +1 -0
- package/dist/types.d.ts +910 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +33 -0
- package/dist/types.js.map +1 -0
- package/dist/verify-audit-result-attestation.d.ts +32 -0
- package/dist/verify-audit-result-attestation.d.ts.map +1 -0
- package/dist/verify-audit-result-attestation.js +396 -0
- package/dist/verify-audit-result-attestation.js.map +1 -0
- package/dist/verify-derivation-attestation.d.ts +30 -0
- package/dist/verify-derivation-attestation.d.ts.map +1 -0
- package/dist/verify-derivation-attestation.js +371 -0
- package/dist/verify-derivation-attestation.js.map +1 -0
- package/dist/verify-execution-attestation.d.ts +32 -0
- package/dist/verify-execution-attestation.d.ts.map +1 -0
- package/dist/verify-execution-attestation.js +578 -0
- package/dist/verify-execution-attestation.js.map +1 -0
- package/dist/verify-export-bundle.d.ts +14 -0
- package/dist/verify-export-bundle.d.ts.map +1 -0
- package/dist/verify-export-bundle.js +307 -0
- package/dist/verify-export-bundle.js.map +1 -0
- package/dist/verify-log-inclusion-proof.d.ts +16 -0
- package/dist/verify-log-inclusion-proof.d.ts.map +1 -0
- package/dist/verify-log-inclusion-proof.js +216 -0
- package/dist/verify-log-inclusion-proof.js.map +1 -0
- package/dist/verify-proof-bundle.d.ts +48 -0
- package/dist/verify-proof-bundle.d.ts.map +1 -0
- package/dist/verify-proof-bundle.js +1708 -0
- package/dist/verify-proof-bundle.js.map +1 -0
- package/dist/verify-receipt.d.ts +30 -0
- package/dist/verify-receipt.d.ts.map +1 -0
- package/dist/verify-receipt.js +408 -0
- package/dist/verify-receipt.js.map +1 -0
- package/dist/verify-web-receipt.d.ts +21 -0
- package/dist/verify-web-receipt.d.ts.map +1 -0
- package/dist/verify-web-receipt.js +341 -0
- package/dist/verify-web-receipt.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Clawbureau
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# @clawbureau/clawverify-core
|
|
2
|
+
|
|
3
|
+
Pure, offline-capable verification primitives for the **Clawsig Protocol**. Zero network dependencies — just cryptographic verification.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @clawbureau/clawverify-core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { verifyProofBundle } from '@clawbureau/clawverify-core';
|
|
15
|
+
|
|
16
|
+
const bundle = JSON.parse(fs.readFileSync('run_xxx-bundle.json', 'utf-8'));
|
|
17
|
+
const result = verifyProofBundle(bundle);
|
|
18
|
+
|
|
19
|
+
console.log(result.status); // 'PASS' or 'FAIL'
|
|
20
|
+
console.log(result.reason_code); // 'OK', 'SIGNATURE_INVALID', etc.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What it verifies
|
|
24
|
+
|
|
25
|
+
- JSON schema validation (fail-closed on unknown versions)
|
|
26
|
+
- Ed25519 signature verification (did:key extraction)
|
|
27
|
+
- Event chain hash integrity (SHA-256)
|
|
28
|
+
- Tool receipt validation (version, algorithm, agent DID, required fields)
|
|
29
|
+
- Side-effect receipt validation (effect class, version, required fields)
|
|
30
|
+
- Human approval receipt validation (approval type, agent DID, required fields)
|
|
31
|
+
- Signer DID allowlist enforcement (optional, via config)
|
|
32
|
+
- Export bundle and log inclusion proof verification
|
|
33
|
+
|
|
34
|
+
## Fail-closed by design
|
|
35
|
+
|
|
36
|
+
Unknown schema versions, hash algorithms, or envelope formats produce `FAIL` — never silently pass.
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
MIT
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic utilities for signature verification
|
|
3
|
+
*/
|
|
4
|
+
import type { HashAlgorithm, Algorithm } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Decode base64url to Uint8Array
|
|
7
|
+
*/
|
|
8
|
+
export declare function base64UrlDecode(str: string): Uint8Array;
|
|
9
|
+
/**
|
|
10
|
+
* Encode Uint8Array to base64url
|
|
11
|
+
*/
|
|
12
|
+
export declare function base64UrlEncode(bytes: Uint8Array): string;
|
|
13
|
+
/**
|
|
14
|
+
* Compute hash of payload using specified algorithm
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeHash(payload: unknown, algorithm: HashAlgorithm): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Extract public key bytes from did:key
|
|
19
|
+
* Format: did:key:z<multibase-encoded-public-key>
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractPublicKeyFromDidKey(did: string): Uint8Array | null;
|
|
22
|
+
export declare function base58Decode(str: string): Uint8Array;
|
|
23
|
+
/**
|
|
24
|
+
* Verify Ed25519 signature using Web Crypto API
|
|
25
|
+
*/
|
|
26
|
+
export declare function verifySignature(algorithm: Algorithm, publicKeyBytes: Uint8Array, signature: Uint8Array, message: Uint8Array): Promise<boolean>;
|
|
27
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAWvD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIzD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,aAAa,GACvB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAmBzE;AAQD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAkCpD;AAeD;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,UAAU,EAC1B,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,OAAO,CAAC,CAyBlB"}
|
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic utilities for signature verification
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Decode base64url to Uint8Array
|
|
6
|
+
*/
|
|
7
|
+
export function base64UrlDecode(str) {
|
|
8
|
+
// Replace base64url chars with base64
|
|
9
|
+
const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
10
|
+
// Pad with = if needed
|
|
11
|
+
const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);
|
|
12
|
+
const binary = atob(padded);
|
|
13
|
+
const bytes = new Uint8Array(binary.length);
|
|
14
|
+
for (let i = 0; i < binary.length; i++) {
|
|
15
|
+
bytes[i] = binary.charCodeAt(i);
|
|
16
|
+
}
|
|
17
|
+
return bytes;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Encode Uint8Array to base64url
|
|
21
|
+
*/
|
|
22
|
+
export function base64UrlEncode(bytes) {
|
|
23
|
+
const binary = String.fromCharCode(...bytes);
|
|
24
|
+
const base64 = btoa(binary);
|
|
25
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compute hash of payload using specified algorithm
|
|
29
|
+
*/
|
|
30
|
+
export async function computeHash(payload, algorithm) {
|
|
31
|
+
const encoder = new TextEncoder();
|
|
32
|
+
const data = encoder.encode(JSON.stringify(payload));
|
|
33
|
+
if (algorithm === 'SHA-256') {
|
|
34
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
35
|
+
return base64UrlEncode(new Uint8Array(hashBuffer));
|
|
36
|
+
}
|
|
37
|
+
// BLAKE3 would require a library - for now SHA-256 is primary
|
|
38
|
+
throw new Error(`Hash algorithm not implemented: ${algorithm}`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract public key bytes from did:key
|
|
42
|
+
* Format: did:key:z<multibase-encoded-public-key>
|
|
43
|
+
*/
|
|
44
|
+
export function extractPublicKeyFromDidKey(did) {
|
|
45
|
+
if (!did.startsWith('did:key:z')) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
// Remove did:key:z prefix and decode multibase (z = base58btc)
|
|
50
|
+
const multibase = did.slice(9);
|
|
51
|
+
const decoded = base58Decode(multibase);
|
|
52
|
+
// Ed25519 multicodec prefix is 0xed01
|
|
53
|
+
if (decoded[0] === 0xed && decoded[1] === 0x01) {
|
|
54
|
+
return decoded.slice(2);
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Base58 Bitcoin alphabet decoder
|
|
64
|
+
*/
|
|
65
|
+
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
66
|
+
export function base58Decode(str) {
|
|
67
|
+
const bytes = [0];
|
|
68
|
+
for (const char of str) {
|
|
69
|
+
const value = BASE58_ALPHABET.indexOf(char);
|
|
70
|
+
if (value === -1) {
|
|
71
|
+
throw new Error(`Invalid base58 character: ${char}`);
|
|
72
|
+
}
|
|
73
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
74
|
+
bytes[i] *= 58;
|
|
75
|
+
}
|
|
76
|
+
bytes[0] += value;
|
|
77
|
+
let carry = 0;
|
|
78
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
79
|
+
bytes[i] += carry;
|
|
80
|
+
carry = bytes[i] >> 8;
|
|
81
|
+
bytes[i] &= 0xff;
|
|
82
|
+
}
|
|
83
|
+
while (carry) {
|
|
84
|
+
bytes.push(carry & 0xff);
|
|
85
|
+
carry >>= 8;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Handle leading zeros
|
|
89
|
+
for (const char of str) {
|
|
90
|
+
if (char !== '1')
|
|
91
|
+
break;
|
|
92
|
+
bytes.push(0);
|
|
93
|
+
}
|
|
94
|
+
return new Uint8Array(bytes.reverse());
|
|
95
|
+
}
|
|
96
|
+
function toArrayBuffer(bytes) {
|
|
97
|
+
// DOM SubtleCrypto typings reject SharedArrayBuffer-backed views.
|
|
98
|
+
// Our inputs are expected to be regular ArrayBuffers, but we normalize anyway.
|
|
99
|
+
const buf = bytes.buffer;
|
|
100
|
+
if (buf instanceof ArrayBuffer) {
|
|
101
|
+
return buf.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
102
|
+
}
|
|
103
|
+
const copy = new Uint8Array(bytes.byteLength);
|
|
104
|
+
copy.set(bytes);
|
|
105
|
+
return copy.buffer;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Verify Ed25519 signature using Web Crypto API
|
|
109
|
+
*/
|
|
110
|
+
export async function verifySignature(algorithm, publicKeyBytes, signature, message) {
|
|
111
|
+
if (algorithm !== 'Ed25519') {
|
|
112
|
+
throw new Error(`Algorithm not supported: ${algorithm}`);
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
// Import the public key
|
|
116
|
+
const publicKey = await crypto.subtle.importKey('raw', toArrayBuffer(publicKeyBytes), { name: 'Ed25519' }, false, ['verify']);
|
|
117
|
+
// Verify the signature
|
|
118
|
+
return await crypto.subtle.verify('Ed25519', publicKey, toArrayBuffer(signature), toArrayBuffer(message));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clawbureau/clawverify-core
|
|
3
|
+
*
|
|
4
|
+
* Pure, offline-capable verification primitives shared by:
|
|
5
|
+
* - packages/clawverify-cli (offline verifier)
|
|
6
|
+
* - (optional) hosted verifiers / services
|
|
7
|
+
*
|
|
8
|
+
* Hard constraints:
|
|
9
|
+
* - fail-closed for unknown schema/version/algorithm
|
|
10
|
+
* - deterministic error codes
|
|
11
|
+
* - no network fetches
|
|
12
|
+
*/
|
|
13
|
+
export * from './types.js';
|
|
14
|
+
export { verifyProofBundle } from './verify-proof-bundle.js';
|
|
15
|
+
export type { ProofBundleVerifierOptions } from './verify-proof-bundle.js';
|
|
16
|
+
export { verifyExportBundle } from './verify-export-bundle.js';
|
|
17
|
+
export type { VerifyExportBundleOptions } from './verify-export-bundle.js';
|
|
18
|
+
export { verifyReceipt } from './verify-receipt.js';
|
|
19
|
+
export type { ReceiptVerifierOptions } from './verify-receipt.js';
|
|
20
|
+
export { verifyWebReceipt } from './verify-web-receipt.js';
|
|
21
|
+
export { verifyExecutionAttestation } from './verify-execution-attestation.js';
|
|
22
|
+
export { verifyDerivationAttestation } from './verify-derivation-attestation.js';
|
|
23
|
+
export { verifyAuditResultAttestation } from './verify-audit-result-attestation.js';
|
|
24
|
+
export { verifyLogInclusionProof } from './verify-log-inclusion-proof.js';
|
|
25
|
+
export { base64UrlDecode, base64UrlEncode, computeHash, extractPublicKeyFromDidKey, verifySignature, } from './crypto.js';
|
|
26
|
+
export { jcsCanonicalize } from './jcs.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAE3E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,EACL,eAAe,EACf,eAAe,EACf,WAAW,EACX,0BAA0B,EAC1B,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clawbureau/clawverify-core
|
|
3
|
+
*
|
|
4
|
+
* Pure, offline-capable verification primitives shared by:
|
|
5
|
+
* - packages/clawverify-cli (offline verifier)
|
|
6
|
+
* - (optional) hosted verifiers / services
|
|
7
|
+
*
|
|
8
|
+
* Hard constraints:
|
|
9
|
+
* - fail-closed for unknown schema/version/algorithm
|
|
10
|
+
* - deterministic error codes
|
|
11
|
+
* - no network fetches
|
|
12
|
+
*/
|
|
13
|
+
export * from './types.js';
|
|
14
|
+
export { verifyProofBundle } from './verify-proof-bundle.js';
|
|
15
|
+
export { verifyExportBundle } from './verify-export-bundle.js';
|
|
16
|
+
export { verifyReceipt } from './verify-receipt.js';
|
|
17
|
+
export { verifyWebReceipt } from './verify-web-receipt.js';
|
|
18
|
+
export { verifyExecutionAttestation } from './verify-execution-attestation.js';
|
|
19
|
+
export { verifyDerivationAttestation } from './verify-derivation-attestation.js';
|
|
20
|
+
export { verifyAuditResultAttestation } from './verify-audit-result-attestation.js';
|
|
21
|
+
export { verifyLogInclusionProof } from './verify-log-inclusion-proof.js';
|
|
22
|
+
export { base64UrlDecode, base64UrlEncode, computeHash, extractPublicKeyFromDidKey, verifySignature, } from './crypto.js';
|
|
23
|
+
export { jcsCanonicalize } from './jcs.js';
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,EACL,eAAe,EACf,eAAe,EACf,WAAW,EACX,0BAA0B,EAC1B,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/jcs.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 8785 — JSON Canonicalization Scheme (JCS)
|
|
3
|
+
*
|
|
4
|
+
* Produces a deterministic JSON string suitable for signing/verifying.
|
|
5
|
+
*
|
|
6
|
+
* Notes:
|
|
7
|
+
* - Only valid JSON data is supported (no undefined/functions/symbols).
|
|
8
|
+
* - Object keys are sorted lexicographically.
|
|
9
|
+
* - Numbers must be finite.
|
|
10
|
+
* - Output contains no whitespace.
|
|
11
|
+
*/
|
|
12
|
+
export declare function jcsCanonicalize(value: unknown): string;
|
|
13
|
+
//# sourceMappingURL=jcs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jcs.d.ts","sourceRoot":"","sources":["../src/jcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAqCtD"}
|
package/dist/jcs.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 8785 — JSON Canonicalization Scheme (JCS)
|
|
3
|
+
*
|
|
4
|
+
* Produces a deterministic JSON string suitable for signing/verifying.
|
|
5
|
+
*
|
|
6
|
+
* Notes:
|
|
7
|
+
* - Only valid JSON data is supported (no undefined/functions/symbols).
|
|
8
|
+
* - Object keys are sorted lexicographically.
|
|
9
|
+
* - Numbers must be finite.
|
|
10
|
+
* - Output contains no whitespace.
|
|
11
|
+
*/
|
|
12
|
+
export function jcsCanonicalize(value) {
|
|
13
|
+
if (value === null)
|
|
14
|
+
return 'null';
|
|
15
|
+
switch (typeof value) {
|
|
16
|
+
case 'boolean':
|
|
17
|
+
return value ? 'true' : 'false';
|
|
18
|
+
case 'number':
|
|
19
|
+
if (!Number.isFinite(value)) {
|
|
20
|
+
throw new Error('Non-finite number not allowed in JCS');
|
|
21
|
+
}
|
|
22
|
+
// JSON.stringify() uses the ECMAScript number to string algorithm.
|
|
23
|
+
return JSON.stringify(value);
|
|
24
|
+
case 'string':
|
|
25
|
+
return JSON.stringify(value);
|
|
26
|
+
case 'object': {
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return `[${value.map(jcsCanonicalize).join(',')}]`;
|
|
29
|
+
}
|
|
30
|
+
const obj = value;
|
|
31
|
+
const keys = Object.keys(obj).sort();
|
|
32
|
+
const parts = [];
|
|
33
|
+
for (const k of keys) {
|
|
34
|
+
parts.push(`${JSON.stringify(k)}:${jcsCanonicalize(obj[k])}`);
|
|
35
|
+
}
|
|
36
|
+
return `{${parts.join(',')}}`;
|
|
37
|
+
}
|
|
38
|
+
default:
|
|
39
|
+
// undefined | function | symbol | bigint
|
|
40
|
+
throw new Error(`Unsupported value type for JCS: ${typeof value}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=jcs.js.map
|
package/dist/jcs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jcs.js","sourceRoot":"","sources":["../src/jcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAElC,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAElC,KAAK,QAAQ;YACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;YACD,mEAAmE;YACnE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YACrD,CAAC;YAED,MAAM,GAAG,GAAG,KAAgC,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,MAAM,KAAK,GAAa,EAAE,CAAC;YAE3B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChE,CAAC;YAED,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAChC,CAAC;QAED;YACE,yCAAyC;YACzC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CVF-US-016 — Model identity extraction + verification.
|
|
3
|
+
*
|
|
4
|
+
* Model identity is an orthogonal axis to PoH tiers:
|
|
5
|
+
* - PoH (`proof_tier` / `poh_tier`) describes execution provenance.
|
|
6
|
+
* - `model_identity_tier` describes what we can honestly claim about the model identity.
|
|
7
|
+
*
|
|
8
|
+
* This module intentionally fail-closes *only* the model identity axis.
|
|
9
|
+
* Receipt signature/binding validity is handled elsewhere.
|
|
10
|
+
*/
|
|
11
|
+
import type { GatewayReceiptPayload, ModelIdentityTier, SignedEnvelope } from './types.js';
|
|
12
|
+
export declare function computeModelIdentityHashB64u(identity: unknown): Promise<string>;
|
|
13
|
+
export interface ModelIdentityVerificationResult {
|
|
14
|
+
/** Whether the model identity claim itself verified (schema + hash + consistency). */
|
|
15
|
+
valid: boolean;
|
|
16
|
+
tier: ModelIdentityTier;
|
|
17
|
+
/** Deterministic risk flags (non-normative). */
|
|
18
|
+
risk_flags: string[];
|
|
19
|
+
computed_hash_b64u?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Verify model identity for a single receipt payload.
|
|
23
|
+
*
|
|
24
|
+
* Returns:
|
|
25
|
+
* - `valid=false` only means model identity cannot be trusted. Receipt may still be cryptographically valid.
|
|
26
|
+
*/
|
|
27
|
+
export declare function verifyModelIdentityFromReceiptPayload(payload: GatewayReceiptPayload): Promise<ModelIdentityVerificationResult>;
|
|
28
|
+
export interface ReceiptVerificationForModelIdentity {
|
|
29
|
+
signature_valid?: boolean;
|
|
30
|
+
binding_valid?: boolean;
|
|
31
|
+
valid?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compute a single model_identity_tier for a set of receipts.
|
|
35
|
+
*
|
|
36
|
+
* Policy/gating-friendly semantics: the overall tier is the *minimum* tier
|
|
37
|
+
* across all receipts that have signature-valid envelopes.
|
|
38
|
+
*/
|
|
39
|
+
export declare function computeModelIdentityTierFromReceipts(input: {
|
|
40
|
+
receipts: SignedEnvelope<GatewayReceiptPayload>[];
|
|
41
|
+
receiptResults?: ReceiptVerificationForModelIdentity[] | null;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
model_identity_tier: ModelIdentityTier;
|
|
44
|
+
risk_flags: string[];
|
|
45
|
+
}>;
|
|
46
|
+
//# sourceMappingURL=model-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-identity.d.ts","sourceRoot":"","sources":["../src/model-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAgB3F,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAErF;AA0DD,MAAM,WAAW,+BAA+B;IAC9C,sFAAsF;IACtF,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,iBAAiB,CAAC;IACxB,gDAAgD;IAChD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,qCAAqC,CACzD,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,+BAA+B,CAAC,CAkH1C;AAED,MAAM,WAAW,mCAAmC;IAClD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,oCAAoC,CAAC,KAAK,EAAE;IAChE,QAAQ,EAAE,cAAc,CAAC,qBAAqB,CAAC,EAAE,CAAC;IAClD,cAAc,CAAC,EAAE,mCAAmC,EAAE,GAAG,IAAI,CAAC;CAC/D,GAAG,OAAO,CAAC;IAAE,mBAAmB,EAAE,iBAAiB,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAoC5E"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CVF-US-016 — Model identity extraction + verification.
|
|
3
|
+
*
|
|
4
|
+
* Model identity is an orthogonal axis to PoH tiers:
|
|
5
|
+
* - PoH (`proof_tier` / `poh_tier`) describes execution provenance.
|
|
6
|
+
* - `model_identity_tier` describes what we can honestly claim about the model identity.
|
|
7
|
+
*
|
|
8
|
+
* This module intentionally fail-closes *only* the model identity axis.
|
|
9
|
+
* Receipt signature/binding validity is handled elsewhere.
|
|
10
|
+
*/
|
|
11
|
+
import { base64UrlEncode } from './crypto.js';
|
|
12
|
+
import { jcsCanonicalize } from './jcs.js';
|
|
13
|
+
import { isValidBase64Url } from './schema-registry.js';
|
|
14
|
+
import { validateModelIdentityV1 } from './schema-validation.js';
|
|
15
|
+
function isRecord(x) {
|
|
16
|
+
return typeof x === 'object' && x !== null && !Array.isArray(x);
|
|
17
|
+
}
|
|
18
|
+
async function sha256B64uUtf8(s) {
|
|
19
|
+
const bytes = new TextEncoder().encode(s);
|
|
20
|
+
const digest = await crypto.subtle.digest('SHA-256', bytes);
|
|
21
|
+
return base64UrlEncode(new Uint8Array(digest));
|
|
22
|
+
}
|
|
23
|
+
export async function computeModelIdentityHashB64u(identity) {
|
|
24
|
+
return sha256B64uUtf8(jcsCanonicalize(identity));
|
|
25
|
+
}
|
|
26
|
+
const TIER_STRENGTH = {
|
|
27
|
+
unknown: 0,
|
|
28
|
+
closed_opaque: 1,
|
|
29
|
+
closed_provider_manifest: 2,
|
|
30
|
+
openweights_hashable: 3,
|
|
31
|
+
tee_measured: 4,
|
|
32
|
+
};
|
|
33
|
+
function normalizeTier(tier) {
|
|
34
|
+
if (tier === 'closed_opaque')
|
|
35
|
+
return 'closed_opaque';
|
|
36
|
+
if (tier === 'closed_provider_manifest')
|
|
37
|
+
return 'closed_provider_manifest';
|
|
38
|
+
if (tier === 'openweights_hashable')
|
|
39
|
+
return 'openweights_hashable';
|
|
40
|
+
if (tier === 'tee_measured')
|
|
41
|
+
return 'tee_measured';
|
|
42
|
+
return 'unknown';
|
|
43
|
+
}
|
|
44
|
+
function requireString(obj, key) {
|
|
45
|
+
const v = obj[key];
|
|
46
|
+
return typeof v === 'string' && v.trim().length > 0 ? v : null;
|
|
47
|
+
}
|
|
48
|
+
function hasProviderManifestEvidence(identity) {
|
|
49
|
+
const artifacts = identity.artifacts;
|
|
50
|
+
if (!isRecord(artifacts))
|
|
51
|
+
return false;
|
|
52
|
+
const pm = artifacts.provider_manifest;
|
|
53
|
+
if (!isRecord(pm))
|
|
54
|
+
return false;
|
|
55
|
+
const h = pm.hash_b64u;
|
|
56
|
+
return typeof h === 'string' && isValidBase64Url(h) && h.length >= 8;
|
|
57
|
+
}
|
|
58
|
+
function hasOpenweightsEvidence(identity) {
|
|
59
|
+
const artifacts = identity.artifacts;
|
|
60
|
+
if (!isRecord(artifacts))
|
|
61
|
+
return false;
|
|
62
|
+
const ow = artifacts.openweights;
|
|
63
|
+
if (!isRecord(ow))
|
|
64
|
+
return false;
|
|
65
|
+
const weights = ow.weights;
|
|
66
|
+
if (!Array.isArray(weights) || weights.length === 0)
|
|
67
|
+
return false;
|
|
68
|
+
for (const w of weights) {
|
|
69
|
+
if (!isRecord(w))
|
|
70
|
+
return false;
|
|
71
|
+
const h = w.hash_b64u;
|
|
72
|
+
if (typeof h !== 'string' || !isValidBase64Url(h) || h.length < 8)
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
function hasTeeEvidence(identity) {
|
|
78
|
+
const artifacts = identity.artifacts;
|
|
79
|
+
if (!isRecord(artifacts))
|
|
80
|
+
return false;
|
|
81
|
+
const tm = artifacts.tee_measurement;
|
|
82
|
+
if (!isRecord(tm))
|
|
83
|
+
return false;
|
|
84
|
+
const ref = tm.attestation_report_ref;
|
|
85
|
+
if (!isRecord(ref))
|
|
86
|
+
return false;
|
|
87
|
+
const h = ref.resource_hash_b64u;
|
|
88
|
+
return typeof h === 'string' && isValidBase64Url(h) && h.length >= 8;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Verify model identity for a single receipt payload.
|
|
92
|
+
*
|
|
93
|
+
* Returns:
|
|
94
|
+
* - `valid=false` only means model identity cannot be trusted. Receipt may still be cryptographically valid.
|
|
95
|
+
*/
|
|
96
|
+
export async function verifyModelIdentityFromReceiptPayload(payload) {
|
|
97
|
+
const risk = new Set();
|
|
98
|
+
const metadata = isRecord(payload.metadata) ? payload.metadata : null;
|
|
99
|
+
const providedIdentity = metadata?.model_identity;
|
|
100
|
+
const providedHash = typeof metadata?.model_identity_hash_b64u === 'string' ? metadata.model_identity_hash_b64u : null;
|
|
101
|
+
let identity;
|
|
102
|
+
if (providedIdentity === undefined) {
|
|
103
|
+
// Back-compat: older receipts may not include model identity metadata.
|
|
104
|
+
// Default is still "closed_opaque" for closed providers.
|
|
105
|
+
risk.add('MODEL_IDENTITY_MISSING_DEFAULTED');
|
|
106
|
+
identity = {
|
|
107
|
+
model_identity_version: '1',
|
|
108
|
+
tier: 'closed_opaque',
|
|
109
|
+
model: {
|
|
110
|
+
provider: payload.provider,
|
|
111
|
+
name: payload.model,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Strict schema validate when present.
|
|
117
|
+
const v = validateModelIdentityV1(providedIdentity);
|
|
118
|
+
if (!v.valid) {
|
|
119
|
+
risk.add('MODEL_IDENTITY_SCHEMA_INVALID');
|
|
120
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort() };
|
|
121
|
+
}
|
|
122
|
+
identity = providedIdentity;
|
|
123
|
+
}
|
|
124
|
+
// Ensure the identity model label matches the receipt payload model label.
|
|
125
|
+
if (!isRecord(identity)) {
|
|
126
|
+
risk.add('MODEL_IDENTITY_SCHEMA_INVALID');
|
|
127
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort() };
|
|
128
|
+
}
|
|
129
|
+
const model = identity.model;
|
|
130
|
+
if (!isRecord(model)) {
|
|
131
|
+
risk.add('MODEL_IDENTITY_SCHEMA_INVALID');
|
|
132
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort() };
|
|
133
|
+
}
|
|
134
|
+
const identityProvider = requireString(model, 'provider');
|
|
135
|
+
const identityName = requireString(model, 'name');
|
|
136
|
+
if (!identityProvider || !identityName) {
|
|
137
|
+
risk.add('MODEL_IDENTITY_SCHEMA_INVALID');
|
|
138
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort() };
|
|
139
|
+
}
|
|
140
|
+
if (identityProvider !== payload.provider || identityName !== payload.model) {
|
|
141
|
+
risk.add('MODEL_IDENTITY_MODEL_MISMATCH');
|
|
142
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort() };
|
|
143
|
+
}
|
|
144
|
+
// Validate hash (if present) against sha256_b64u(JCS(model_identity)).
|
|
145
|
+
let computedHash;
|
|
146
|
+
try {
|
|
147
|
+
computedHash = await computeModelIdentityHashB64u(identity);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
risk.add('MODEL_IDENTITY_HASH_COMPUTE_FAILED');
|
|
151
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort() };
|
|
152
|
+
}
|
|
153
|
+
if (providedHash) {
|
|
154
|
+
if (!isValidBase64Url(providedHash)) {
|
|
155
|
+
risk.add('MODEL_IDENTITY_HASH_INVALID');
|
|
156
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort(), computed_hash_b64u: computedHash };
|
|
157
|
+
}
|
|
158
|
+
if (providedHash !== computedHash) {
|
|
159
|
+
risk.add('MODEL_IDENTITY_HASH_MISMATCH');
|
|
160
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort(), computed_hash_b64u: computedHash };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
risk.add('MODEL_IDENTITY_HASH_MISSING');
|
|
165
|
+
}
|
|
166
|
+
// Validate tier semantics (fail-closed on stronger tiers without evidence).
|
|
167
|
+
const tier = normalizeTier(identity.tier);
|
|
168
|
+
if (tier === 'unknown') {
|
|
169
|
+
risk.add('MODEL_IDENTITY_TIER_INVALID');
|
|
170
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort(), computed_hash_b64u: computedHash };
|
|
171
|
+
}
|
|
172
|
+
if (tier === 'closed_provider_manifest' && !hasProviderManifestEvidence(identity)) {
|
|
173
|
+
risk.add('MODEL_IDENTITY_EVIDENCE_MISSING');
|
|
174
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort(), computed_hash_b64u: computedHash };
|
|
175
|
+
}
|
|
176
|
+
if (tier === 'openweights_hashable' && !hasOpenweightsEvidence(identity)) {
|
|
177
|
+
risk.add('MODEL_IDENTITY_EVIDENCE_MISSING');
|
|
178
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort(), computed_hash_b64u: computedHash };
|
|
179
|
+
}
|
|
180
|
+
if (tier === 'tee_measured' && !hasTeeEvidence(identity)) {
|
|
181
|
+
risk.add('MODEL_IDENTITY_EVIDENCE_MISSING');
|
|
182
|
+
return { valid: false, tier: 'unknown', risk_flags: [...risk].sort(), computed_hash_b64u: computedHash };
|
|
183
|
+
}
|
|
184
|
+
if (tier === 'closed_opaque') {
|
|
185
|
+
// Not an error: this is the expected posture for closed providers.
|
|
186
|
+
risk.add('MODEL_IDENTITY_OPAQUE');
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
valid: true,
|
|
190
|
+
tier,
|
|
191
|
+
risk_flags: [...risk].sort(),
|
|
192
|
+
computed_hash_b64u: computedHash,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Compute a single model_identity_tier for a set of receipts.
|
|
197
|
+
*
|
|
198
|
+
* Policy/gating-friendly semantics: the overall tier is the *minimum* tier
|
|
199
|
+
* across all receipts that have signature-valid envelopes.
|
|
200
|
+
*/
|
|
201
|
+
export async function computeModelIdentityTierFromReceipts(input) {
|
|
202
|
+
const risk = new Set();
|
|
203
|
+
const tiers = [];
|
|
204
|
+
for (let i = 0; i < input.receipts.length; i++) {
|
|
205
|
+
const r = input.receipts[i];
|
|
206
|
+
const vr = input.receiptResults?.[i];
|
|
207
|
+
// Only consider receipts whose envelope signature+payload hash were verified.
|
|
208
|
+
// If we have no per-receipt verification results, assume caller already filtered.
|
|
209
|
+
if (vr && vr.signature_valid === false)
|
|
210
|
+
continue;
|
|
211
|
+
const out = await verifyModelIdentityFromReceiptPayload(r.payload);
|
|
212
|
+
for (const f of out.risk_flags)
|
|
213
|
+
risk.add(f);
|
|
214
|
+
tiers.push(out.tier);
|
|
215
|
+
}
|
|
216
|
+
if (tiers.length === 0) {
|
|
217
|
+
risk.add('MODEL_IDENTITY_NO_SIGNATURE_VERIFIED_RECEIPTS');
|
|
218
|
+
return { model_identity_tier: 'unknown', risk_flags: [...risk].sort() };
|
|
219
|
+
}
|
|
220
|
+
let minTier = tiers[0];
|
|
221
|
+
for (const t of tiers) {
|
|
222
|
+
if (TIER_STRENGTH[t] < TIER_STRENGTH[minTier])
|
|
223
|
+
minTier = t;
|
|
224
|
+
}
|
|
225
|
+
const distinct = new Set(tiers);
|
|
226
|
+
if (distinct.size > 1)
|
|
227
|
+
risk.add('MODEL_IDENTITY_HETEROGENEOUS');
|
|
228
|
+
return {
|
|
229
|
+
model_identity_tier: minTier,
|
|
230
|
+
risk_flags: [...risk].sort(),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=model-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-identity.js","sourceRoot":"","sources":["../src/model-identity.ts"],"names":[],"mappings":"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"}
|