@primust/artifact-core 1.0.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.
Files changed (45) hide show
  1. package/dist/canonical.d.ts +24 -0
  2. package/dist/canonical.d.ts.map +1 -0
  3. package/dist/canonical.js +83 -0
  4. package/dist/canonical.js.map +1 -0
  5. package/dist/canonical.test.d.ts +2 -0
  6. package/dist/canonical.test.d.ts.map +1 -0
  7. package/dist/canonical.test.js +63 -0
  8. package/dist/canonical.test.js.map +1 -0
  9. package/dist/commitment.d.ts +56 -0
  10. package/dist/commitment.d.ts.map +1 -0
  11. package/dist/commitment.js +214 -0
  12. package/dist/commitment.js.map +1 -0
  13. package/dist/commitment.test.d.ts +7 -0
  14. package/dist/commitment.test.d.ts.map +1 -0
  15. package/dist/commitment.test.js +125 -0
  16. package/dist/commitment.test.js.map +1 -0
  17. package/dist/index.d.ts +9 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +6 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/signing.d.ts +80 -0
  22. package/dist/signing.d.ts.map +1 -0
  23. package/dist/signing.js +159 -0
  24. package/dist/signing.js.map +1 -0
  25. package/dist/signing.test.d.ts +2 -0
  26. package/dist/signing.test.d.ts.map +1 -0
  27. package/dist/signing.test.js +153 -0
  28. package/dist/signing.test.js.map +1 -0
  29. package/dist/types/artifact.d.ts +143 -0
  30. package/dist/types/artifact.d.ts.map +1 -0
  31. package/dist/types/artifact.js +18 -0
  32. package/dist/types/artifact.js.map +1 -0
  33. package/dist/types.d.ts +45 -0
  34. package/dist/types.d.ts.map +1 -0
  35. package/dist/types.js +7 -0
  36. package/dist/types.js.map +1 -0
  37. package/dist/validate-artifact.d.ts +23 -0
  38. package/dist/validate-artifact.d.ts.map +1 -0
  39. package/dist/validate-artifact.js +168 -0
  40. package/dist/validate-artifact.js.map +1 -0
  41. package/dist/validate-artifact.test.d.ts +2 -0
  42. package/dist/validate-artifact.test.d.ts.map +1 -0
  43. package/dist/validate-artifact.test.js +300 -0
  44. package/dist/validate-artifact.test.js.map +1 -0
  45. package/package.json +37 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Primust Canonical JSON Serialization
3
+ *
4
+ * Produces deterministic JSON output with recursively sorted keys
5
+ * and no whitespace. Two structurally identical objects always produce
6
+ * the same string regardless of key insertion order.
7
+ *
8
+ * Rules:
9
+ * - Object keys sorted lexicographically at every nesting depth
10
+ * - Array element order preserved (never sorted)
11
+ * - No whitespace (no spaces, no newlines, no indentation)
12
+ * - Only JSON-native types accepted: string, number, boolean, null, object, array
13
+ * - Non-JSON-native types (Date, Uint8Array, function, undefined, NaN, Infinity) → TypeError
14
+ *
15
+ * Reference: schemas/golden/canonical_vectors.json
16
+ * Quarantine: Q1 (top-level-only sort), Q6 (no-sort), Q8 (default=str coercion)
17
+ */
18
+ /**
19
+ * Recursively serialize a value to canonical JSON.
20
+ *
21
+ * @throws TypeError if the value contains non-JSON-native types
22
+ */
23
+ export declare function canonical(value: unknown): string;
24
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Primust Canonical JSON Serialization
3
+ *
4
+ * Produces deterministic JSON output with recursively sorted keys
5
+ * and no whitespace. Two structurally identical objects always produce
6
+ * the same string regardless of key insertion order.
7
+ *
8
+ * Rules:
9
+ * - Object keys sorted lexicographically at every nesting depth
10
+ * - Array element order preserved (never sorted)
11
+ * - No whitespace (no spaces, no newlines, no indentation)
12
+ * - Only JSON-native types accepted: string, number, boolean, null, object, array
13
+ * - Non-JSON-native types (Date, Uint8Array, function, undefined, NaN, Infinity) → TypeError
14
+ *
15
+ * Reference: schemas/golden/canonical_vectors.json
16
+ * Quarantine: Q1 (top-level-only sort), Q6 (no-sort), Q8 (default=str coercion)
17
+ */
18
+ /**
19
+ * Recursively serialize a value to canonical JSON.
20
+ *
21
+ * @throws TypeError if the value contains non-JSON-native types
22
+ */
23
+ export function canonical(value) {
24
+ return serializeValue(value);
25
+ }
26
+ function serializeValue(value) {
27
+ if (value === null) {
28
+ return 'null';
29
+ }
30
+ switch (typeof value) {
31
+ case 'string':
32
+ return JSON.stringify(value);
33
+ case 'number':
34
+ if (!Number.isFinite(value)) {
35
+ throw new TypeError(`canonical: cannot serialize ${value} (NaN/Infinity are not valid JSON)`);
36
+ }
37
+ return JSON.stringify(value);
38
+ case 'boolean':
39
+ return value ? 'true' : 'false';
40
+ case 'object':
41
+ if (Array.isArray(value)) {
42
+ return serializeArray(value);
43
+ }
44
+ if (value instanceof Date) {
45
+ throw new TypeError('canonical: Date objects must be converted to ISO 8601 strings before serialization');
46
+ }
47
+ if (value instanceof Uint8Array || (typeof Buffer !== 'undefined' && Buffer.isBuffer(value))) {
48
+ throw new TypeError('canonical: byte arrays must be base64url-encoded before serialization');
49
+ }
50
+ return serializeObject(value);
51
+ case 'undefined':
52
+ throw new TypeError('canonical: undefined is not valid JSON');
53
+ case 'function':
54
+ throw new TypeError('canonical: functions are not valid JSON');
55
+ case 'symbol':
56
+ throw new TypeError('canonical: symbols are not valid JSON');
57
+ case 'bigint':
58
+ throw new TypeError('canonical: BigInt must be converted to string or number before serialization');
59
+ default:
60
+ throw new TypeError(`canonical: unsupported type ${typeof value}`);
61
+ }
62
+ }
63
+ function serializeObject(obj) {
64
+ const keys = Object.keys(obj).sort();
65
+ const pairs = [];
66
+ for (const key of keys) {
67
+ const val = obj[key];
68
+ if (val === undefined) {
69
+ // Skip undefined values (matches JSON.stringify behavior)
70
+ continue;
71
+ }
72
+ pairs.push(`${JSON.stringify(key)}:${serializeValue(val)}`);
73
+ }
74
+ return `{${pairs.join(',')}}`;
75
+ }
76
+ function serializeArray(arr) {
77
+ const elements = [];
78
+ for (const item of arr) {
79
+ elements.push(serializeValue(item));
80
+ }
81
+ return `[${elements.join(',')}]`;
82
+ }
83
+ //# sourceMappingURL=canonical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,QAAQ;YACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,SAAS,CACjB,+BAA+B,KAAK,oCAAoC,CACzE,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAElC,KAAK,QAAQ;YACX,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;gBAC1B,MAAM,IAAI,SAAS,CACjB,oFAAoF,CACrF,CAAC;YACJ,CAAC;YACD,IAAI,KAAK,YAAY,UAAU,IAAI,CAAC,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC7F,MAAM,IAAI,SAAS,CACjB,uEAAuE,CACxE,CAAC;YACJ,CAAC;YACD,OAAO,eAAe,CAAC,KAAgC,CAAC,CAAC;QAE3D,KAAK,WAAW;YACd,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;QAEhE,KAAK,UAAU;YACb,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAEjE,KAAK,QAAQ;YACX,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAE/D,KAAK,QAAQ;YACX,MAAM,IAAI,SAAS,CAAC,8EAA8E,CAAC,CAAC;QAEtG;YACE,MAAM,IAAI,SAAS,CAAC,+BAA+B,OAAO,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAA4B;IACnD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,0DAA0D;YAC1D,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAChC,CAAC;AAED,SAAS,cAAc,CAAC,GAAc;IACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACnC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=canonical.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.test.d.ts","sourceRoot":"","sources":["../src/canonical.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { readFileSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { canonical } from './canonical.js';
5
+ // Load golden vectors
6
+ const vectorsPath = resolve(__dirname, '../../../schemas/golden/canonical_vectors.json');
7
+ const vectors = JSON.parse(readFileSync(vectorsPath, 'utf-8'));
8
+ describe('canonical', () => {
9
+ describe('golden vectors', () => {
10
+ for (const vec of vectors.vectors) {
11
+ it(`${vec.id}: ${vec.description}`, () => {
12
+ expect(canonical(vec.input)).toBe(vec.expected);
13
+ });
14
+ }
15
+ });
16
+ describe('hash vectors', () => {
17
+ it('produces correct canonical form for hash input', () => {
18
+ const vec = vectors.hash_vectors[0];
19
+ expect(canonical(vec.input)).toBe(vec.canonical);
20
+ });
21
+ });
22
+ describe('invalid vectors — non-JSON-native types must throw', () => {
23
+ it('reject-date-object: Date throws TypeError', () => {
24
+ expect(() => canonical({ ts: new Date() })).toThrow(TypeError);
25
+ });
26
+ it('reject-bytes: Uint8Array throws TypeError', () => {
27
+ expect(() => canonical({ data: new Uint8Array([1, 2, 3]) })).toThrow(TypeError);
28
+ });
29
+ it('reject-undefined-function: function throws TypeError', () => {
30
+ expect(() => canonical({ fn: () => { } })).toThrow(TypeError);
31
+ });
32
+ it('reject-nan: NaN throws TypeError', () => {
33
+ expect(() => canonical({ val: NaN })).toThrow(TypeError);
34
+ });
35
+ it('reject-infinity: Infinity throws TypeError', () => {
36
+ expect(() => canonical({ val: Infinity })).toThrow(TypeError);
37
+ });
38
+ it('reject-negative-infinity: -Infinity throws TypeError', () => {
39
+ expect(() => canonical({ val: -Infinity })).toThrow(TypeError);
40
+ });
41
+ it('reject-symbol: Symbol throws TypeError', () => {
42
+ expect(() => canonical({ val: Symbol('test') })).toThrow(TypeError);
43
+ });
44
+ it('reject-bigint: BigInt throws TypeError', () => {
45
+ expect(() => canonical({ val: BigInt(42) })).toThrow(TypeError);
46
+ });
47
+ });
48
+ describe('edge cases', () => {
49
+ it('undefined object properties are skipped', () => {
50
+ expect(canonical({ a: 1, b: undefined, c: 3 })).toBe('{"a":1,"c":3}');
51
+ });
52
+ it('recursive sorting is not top-level-only (Q1 quarantine)', () => {
53
+ // This is the exact pattern that Q1 quarantines:
54
+ // Object.keys().sort() only sorts top-level
55
+ const input = { outer: { z: 1, a: 2 } };
56
+ const result = canonical(input);
57
+ expect(result).toBe('{"outer":{"a":2,"z":1}}');
58
+ // Verify it's NOT the broken top-level-only version
59
+ expect(result).not.toBe('{"outer":{"z":1,"a":2}}');
60
+ });
61
+ });
62
+ });
63
+ //# sourceMappingURL=canonical.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.test.js","sourceRoot":"","sources":["../src/canonical.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Primust Artifact Core — Commitment Layer (P6-A)
3
+ *
4
+ * SHA-256 (default) and Poseidon2 (opt-in via PRIMUST_COMMITMENT_ALGORITHM=poseidon2) commitments.
5
+ * Poseidon2 uses a pure implementation — opt-in only until an audited reference
6
+ * (e.g. Barretenberg) is validated.
7
+ *
8
+ * PRIVACY INVARIANT: Raw content NEVER leaves the customer environment.
9
+ * Only the commitment hash transits to Primust API.
10
+ */
11
+ import type { CommitmentAlgorithm, ProofLevel } from './types/artifact.js';
12
+ /** ZK proof generation is always non-blocking. Non-negotiable. */
13
+ export declare const ZK_IS_BLOCKING: false;
14
+ export interface CommitmentResult {
15
+ hash: string;
16
+ algorithm: CommitmentAlgorithm;
17
+ }
18
+ /**
19
+ * Compute a commitment hash over input bytes.
20
+ *
21
+ * @param input - Raw content bytes (NEVER transmitted — only the hash leaves the environment)
22
+ * @param algorithm - 'sha256' (default) or 'poseidon2' (opt-in). If not specified, uses
23
+ * PRIMUST_COMMITMENT_ALGORITHM env var or defaults to 'sha256'.
24
+ */
25
+ export declare function commit(input: Uint8Array, algorithm?: CommitmentAlgorithm): CommitmentResult;
26
+ /**
27
+ * Compute a commitment hash for check output. Uses resolved algorithm.
28
+ */
29
+ export declare function commitOutput(output: Uint8Array): CommitmentResult;
30
+ /**
31
+ * Build a Merkle root over an array of commitment hashes.
32
+ * Uses the resolved algorithm (SHA-256 default, Poseidon2 opt-in) for intermediate nodes.
33
+ *
34
+ * @returns Merkle root, or null for empty array.
35
+ * Single hash → returns that hash unchanged.
36
+ */
37
+ export declare function buildCommitmentRoot(hashes: string[], algorithm?: CommitmentAlgorithm): string | null;
38
+ /** Stage types that map to proof levels. */
39
+ type StageType = 'deterministic_rule' | 'ml_model' | 'zkml_model' | 'statistical_test' | 'custom_code' | 'witnessed' | 'policy_engine';
40
+ /**
41
+ * Select the proof level for a given stage type.
42
+ *
43
+ * Mapping:
44
+ * deterministic_rule → mathematical
45
+ * zkml_model → verifiable_inference
46
+ * ml_model → execution
47
+ * statistical_test → execution (default; non-deterministic sampling/bootstrapping)
48
+ * custom_code → execution
49
+ * witnessed → witnessed
50
+ *
51
+ * Note: attestation is the weakest level and only applies from explicit manifest
52
+ * declaration, not from stage type mapping.
53
+ */
54
+ export declare function selectProofLevel(stageType: StageType): ProofLevel;
55
+ export {};
56
+ //# sourceMappingURL=commitment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitment.d.ts","sourceRoot":"","sources":["../src/commitment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAI3E,kEAAkE;AAClE,eAAO,MAAM,cAAc,EAAG,KAAc,CAAC;AAU7C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,mBAAmB,CAAC;CAChC;AA6ED;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,UAAU,EACjB,SAAS,CAAC,EAAE,mBAAmB,GAC9B,gBAAgB,CAMlB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,CAMjE;AA4BD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CASpG;AAuCD,4CAA4C;AAC5C,KAAK,SAAS,GACV,oBAAoB,GACpB,UAAU,GACV,YAAY,GACZ,kBAAkB,GAClB,aAAa,GACb,WAAW,GACX,eAAe,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CAiBjE"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Primust Artifact Core — Commitment Layer (P6-A)
3
+ *
4
+ * SHA-256 (default) and Poseidon2 (opt-in via PRIMUST_COMMITMENT_ALGORITHM=poseidon2) commitments.
5
+ * Poseidon2 uses a pure implementation — opt-in only until an audited reference
6
+ * (e.g. Barretenberg) is validated.
7
+ *
8
+ * PRIVACY INVARIANT: Raw content NEVER leaves the customer environment.
9
+ * Only the commitment hash transits to Primust API.
10
+ */
11
+ import { sha256 } from '@noble/hashes/sha256';
12
+ import { poseidon2Hash } from '@zkpassport/poseidon2';
13
+ // ── Constants ──
14
+ /** ZK proof generation is always non-blocking. Non-negotiable. */
15
+ export const ZK_IS_BLOCKING = false;
16
+ /**
17
+ * BN254 scalar field modulus.
18
+ * All Poseidon2 field arithmetic operates modulo this prime.
19
+ */
20
+ const BN254_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
21
+ // ── Helpers ──
22
+ /**
23
+ * Convert bytes to BN254 field elements.
24
+ * Each chunk of 31 bytes is interpreted as a big-endian unsigned integer
25
+ * to stay within the BN254 scalar field modulus.
26
+ */
27
+ function bytesToFieldElements(input) {
28
+ if (input.length === 0)
29
+ return [0n];
30
+ const elements = [];
31
+ const chunkSize = 31; // 31 bytes < 254 bits, always fits in BN254 field
32
+ for (let i = 0; i < input.length; i += chunkSize) {
33
+ const end = Math.min(i + chunkSize, input.length);
34
+ let value = 0n;
35
+ for (let j = i; j < end; j++) {
36
+ value = (value << 8n) | BigInt(input[j]);
37
+ }
38
+ elements.push(value % BN254_MODULUS);
39
+ }
40
+ return elements;
41
+ }
42
+ /**
43
+ * Poseidon2 hash over arbitrary bytes.
44
+ * Converts to field elements, then applies Poseidon2 sponge-style:
45
+ * absorb pairs of elements, squeeze final hash.
46
+ */
47
+ function poseidon2(input) {
48
+ const elements = bytesToFieldElements(input);
49
+ // Sponge: absorb pairs of field elements
50
+ let state = 0n;
51
+ for (let i = 0; i < elements.length; i += 2) {
52
+ const left = elements[i];
53
+ const right = i + 1 < elements.length ? elements[i + 1] : 0n;
54
+ state = poseidon2Hash([state + left, right]);
55
+ }
56
+ return 'poseidon2:' + state.toString(16).padStart(64, '0');
57
+ }
58
+ /**
59
+ * SHA-256 hash over arbitrary bytes.
60
+ */
61
+ function sha256Commit(input) {
62
+ const hash = sha256(input);
63
+ const hex = Array.from(hash)
64
+ .map((b) => b.toString(16).padStart(2, '0'))
65
+ .join('');
66
+ return 'sha256:' + hex;
67
+ }
68
+ /**
69
+ * Poseidon2 hash of two field elements (for Merkle tree internal nodes).
70
+ */
71
+ function poseidon2Pair(left, right) {
72
+ return poseidon2Hash([left, right]);
73
+ }
74
+ /**
75
+ * Parse a commitment hash string to extract the raw bigint value.
76
+ * Accepts both 'poseidon2:hex' and 'sha256:hex' formats.
77
+ */
78
+ function parseHashToField(hash) {
79
+ const colonIdx = hash.indexOf(':');
80
+ if (colonIdx === -1)
81
+ throw new Error(`Invalid hash format: ${hash}`);
82
+ const hex = hash.slice(colonIdx + 1);
83
+ return BigInt('0x' + hex) % BN254_MODULUS;
84
+ }
85
+ // ── Public API ──
86
+ /**
87
+ * Compute a commitment hash over input bytes.
88
+ *
89
+ * @param input - Raw content bytes (NEVER transmitted — only the hash leaves the environment)
90
+ * @param algorithm - 'sha256' (default) or 'poseidon2' (opt-in). If not specified, uses
91
+ * PRIMUST_COMMITMENT_ALGORITHM env var or defaults to 'sha256'.
92
+ */
93
+ export function commit(input, algorithm) {
94
+ const alg = algorithm ?? resolveAlgorithm();
95
+ if (alg === 'poseidon2') {
96
+ return { hash: poseidon2(input), algorithm: 'poseidon2' };
97
+ }
98
+ return { hash: sha256Commit(input), algorithm: 'sha256' };
99
+ }
100
+ /**
101
+ * Compute a commitment hash for check output. Uses resolved algorithm.
102
+ */
103
+ export function commitOutput(output) {
104
+ const alg = resolveAlgorithm();
105
+ if (alg === 'poseidon2') {
106
+ return { hash: poseidon2(output), algorithm: 'poseidon2' };
107
+ }
108
+ return { hash: sha256Commit(output), algorithm: 'sha256' };
109
+ }
110
+ /**
111
+ * Resolve the commitment algorithm.
112
+ * Default is "sha256". Poseidon2 is opt-in via PRIMUST_COMMITMENT_ALGORITHM=poseidon2
113
+ * until an audited implementation (e.g. Barretenberg) is validated.
114
+ */
115
+ function resolveAlgorithm() {
116
+ if (typeof process !== 'undefined' && process.env?.PRIMUST_COMMITMENT_ALGORITHM === 'poseidon2') {
117
+ return 'poseidon2';
118
+ }
119
+ return 'sha256';
120
+ }
121
+ /**
122
+ * Parse a commitment hash string to raw bytes.
123
+ */
124
+ function parseHashToRawBytes(hash) {
125
+ const colonIdx = hash.indexOf(':');
126
+ if (colonIdx === -1)
127
+ throw new Error(`Invalid hash format: ${hash}`);
128
+ const hex = hash.slice(colonIdx + 1);
129
+ const bytes = new Uint8Array(hex.length / 2);
130
+ for (let i = 0; i < bytes.length; i++) {
131
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
132
+ }
133
+ return bytes;
134
+ }
135
+ /**
136
+ * Build a Merkle root over an array of commitment hashes.
137
+ * Uses the resolved algorithm (SHA-256 default, Poseidon2 opt-in) for intermediate nodes.
138
+ *
139
+ * @returns Merkle root, or null for empty array.
140
+ * Single hash → returns that hash unchanged.
141
+ */
142
+ export function buildCommitmentRoot(hashes, algorithm) {
143
+ const alg = algorithm ?? resolveAlgorithm();
144
+ if (hashes.length === 0)
145
+ return null;
146
+ if (hashes.length === 1)
147
+ return hashes[0];
148
+ if (alg === 'poseidon2') {
149
+ return buildPoseidon2MerkleRoot(hashes);
150
+ }
151
+ return buildSha256MerkleRoot(hashes);
152
+ }
153
+ function buildPoseidon2MerkleRoot(hashes) {
154
+ let layer = hashes.map(parseHashToField);
155
+ while (layer.length > 1) {
156
+ const next = [];
157
+ for (let i = 0; i < layer.length; i += 2) {
158
+ const left = layer[i];
159
+ const right = i + 1 < layer.length ? layer[i + 1] : layer[i];
160
+ next.push(poseidon2Pair(left, right));
161
+ }
162
+ layer = next;
163
+ }
164
+ return 'poseidon2:' + layer[0].toString(16).padStart(64, '0');
165
+ }
166
+ function buildSha256MerkleRoot(hashes) {
167
+ let layer = hashes.map(parseHashToRawBytes);
168
+ while (layer.length > 1) {
169
+ const next = [];
170
+ for (let i = 0; i < layer.length; i += 2) {
171
+ const left = layer[i];
172
+ const right = i + 1 < layer.length ? layer[i + 1] : layer[i];
173
+ const combined = new Uint8Array(left.length + right.length);
174
+ combined.set(left);
175
+ combined.set(right, left.length);
176
+ next.push(sha256(combined));
177
+ }
178
+ layer = next;
179
+ }
180
+ return 'sha256:' + Array.from(layer[0]).map(b => b.toString(16).padStart(2, '0')).join('');
181
+ }
182
+ /**
183
+ * Select the proof level for a given stage type.
184
+ *
185
+ * Mapping:
186
+ * deterministic_rule → mathematical
187
+ * zkml_model → verifiable_inference
188
+ * ml_model → execution
189
+ * statistical_test → execution (default; non-deterministic sampling/bootstrapping)
190
+ * custom_code → execution
191
+ * witnessed → witnessed
192
+ *
193
+ * Note: attestation is the weakest level and only applies from explicit manifest
194
+ * declaration, not from stage type mapping.
195
+ */
196
+ export function selectProofLevel(stageType) {
197
+ switch (stageType) {
198
+ case 'deterministic_rule':
199
+ return 'mathematical';
200
+ case 'zkml_model':
201
+ return 'verifiable_inference';
202
+ case 'ml_model':
203
+ return 'execution';
204
+ case 'statistical_test':
205
+ return 'execution';
206
+ case 'custom_code':
207
+ return 'execution';
208
+ case 'witnessed':
209
+ return 'witnessed';
210
+ case 'policy_engine':
211
+ return 'mathematical';
212
+ }
213
+ }
214
+ //# sourceMappingURL=commitment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitment.js","sourceRoot":"","sources":["../src/commitment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tests for commitment layer — P6-A.
3
+ * 9 MUST PASS tests covering poseidon2/sha256 commitments, golden vectors,
4
+ * Merkle root, proof level selection, and privacy invariant.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=commitment.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitment.test.d.ts","sourceRoot":"","sources":["../src/commitment.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Tests for commitment layer — P6-A.
3
+ * 9 MUST PASS tests covering poseidon2/sha256 commitments, golden vectors,
4
+ * Merkle root, proof level selection, and privacy invariant.
5
+ */
6
+ import { readFileSync } from 'node:fs';
7
+ import { resolve } from 'node:path';
8
+ import { describe, expect, it, vi } from 'vitest';
9
+ import { ZK_IS_BLOCKING, buildCommitmentRoot, commit, commitOutput, selectProofLevel, } from './commitment.js';
10
+ // ── Helpers ──
11
+ function hexToBytes(hex) {
12
+ if (hex === '')
13
+ return new Uint8Array(0);
14
+ const bytes = new Uint8Array(hex.length / 2);
15
+ for (let i = 0; i < hex.length; i += 2) {
16
+ bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
17
+ }
18
+ return bytes;
19
+ }
20
+ const vectorsPath = resolve(__dirname, '../../../schemas/golden/commitment_vectors.json');
21
+ const vectorsFile = JSON.parse(readFileSync(vectorsPath, 'utf-8'));
22
+ // v2.0.0 structure: separate sha256_vectors, poseidon2_vectors, merkle_* sections
23
+ const sha256Vectors = vectorsFile.sha256_vectors ?? [];
24
+ const poseidon2Vectors = vectorsFile.poseidon2_vectors ?? [];
25
+ const merkleSha256Vectors = vectorsFile.merkle_sha256_vectors ?? [];
26
+ const merklePoseidon2Vectors = vectorsFile.merkle_poseidon2_vectors ?? [];
27
+ // Combined for backward-compatible iteration
28
+ const vectors = [
29
+ ...sha256Vectors.map(v => ({ ...v, type: 'commitment' })),
30
+ ...poseidon2Vectors.map(v => ({ ...v, type: 'commitment' })),
31
+ ...merkleSha256Vectors.map(v => ({ ...v, type: 'merkle_root' })),
32
+ ...merklePoseidon2Vectors.map(v => ({ ...v, type: 'merkle_root' })),
33
+ ];
34
+ // ── Tests ──
35
+ describe('commitment', () => {
36
+ it('MUST PASS: poseidon2 commitment is deterministic', () => {
37
+ const input = new TextEncoder().encode('deterministic test input');
38
+ const a = commit(input, 'poseidon2');
39
+ const b = commit(input, 'poseidon2');
40
+ expect(a.hash).toBe(b.hash);
41
+ expect(a.algorithm).toBe('poseidon2');
42
+ expect(a.hash).toMatch(/^poseidon2:[0-9a-f]{64}$/);
43
+ });
44
+ it('MUST PASS: sha256 commitment is deterministic', () => {
45
+ const input = new TextEncoder().encode('deterministic test input');
46
+ const a = commit(input, 'sha256');
47
+ const b = commit(input, 'sha256');
48
+ expect(a.hash).toBe(b.hash);
49
+ expect(a.algorithm).toBe('sha256');
50
+ expect(a.hash).toMatch(/^sha256:[0-9a-f]{64}$/);
51
+ });
52
+ it('MUST PASS: all golden vectors pass', () => {
53
+ for (const vec of vectors) {
54
+ if (vec.type === 'merkle_root') {
55
+ const root = buildCommitmentRoot(vec.input_hashes, vec.algorithm);
56
+ expect(root).toBe(vec.expected_root);
57
+ }
58
+ else {
59
+ const input = vec.input_hex !== undefined
60
+ ? hexToBytes(vec.input_hex)
61
+ : new TextEncoder().encode(vec.input_utf8);
62
+ const result = commit(input, vec.algorithm);
63
+ expect(result.hash).toBe(vec.expected_hash);
64
+ }
65
+ }
66
+ });
67
+ it('MUST PASS: commitOutput uses default algorithm (sha256)', () => {
68
+ const output = new TextEncoder().encode('some output content');
69
+ const result = commitOutput(output);
70
+ expect(result.algorithm).toBe('sha256');
71
+ expect(result.hash).toMatch(/^sha256:/);
72
+ });
73
+ it('MUST PASS: buildCommitmentRoot(empty array) returns null', () => {
74
+ expect(buildCommitmentRoot([])).toBeNull();
75
+ });
76
+ it('MUST PASS: ZK_IS_BLOCKING === false', () => {
77
+ expect(ZK_IS_BLOCKING).toBe(false);
78
+ });
79
+ it('MUST PASS: raw content not present in HTTP request body', () => {
80
+ const originalFetch = globalThis.fetch;
81
+ const mockFetch = vi.fn();
82
+ globalThis.fetch = mockFetch;
83
+ try {
84
+ const rawContent = new TextEncoder().encode('sensitive raw content');
85
+ commit(rawContent, 'poseidon2');
86
+ commit(rawContent, 'sha256');
87
+ commitOutput(rawContent);
88
+ // No HTTP calls should have been made — raw content stays local
89
+ expect(mockFetch).not.toHaveBeenCalled();
90
+ }
91
+ finally {
92
+ globalThis.fetch = originalFetch;
93
+ }
94
+ });
95
+ it('MUST PASS: all 5 proof levels present in proof level selection logic', () => {
96
+ const stageTypes = [
97
+ 'deterministic_rule',
98
+ 'ml_model',
99
+ 'zkml_model',
100
+ 'statistical_test',
101
+ 'custom_code',
102
+ 'witnessed',
103
+ ];
104
+ const proofLevels = new Set(stageTypes.map(selectProofLevel));
105
+ expect(proofLevels).toContain('mathematical');
106
+ expect(proofLevels).toContain('verifiable_inference');
107
+ expect(proofLevels).toContain('execution');
108
+ expect(proofLevels).toContain('witnessed');
109
+ });
110
+ it('MUST PASS: verifiable_inference proof level triggers only for zkml_model stage type', () => {
111
+ expect(selectProofLevel('zkml_model')).toBe('verifiable_inference');
112
+ // No other stage type should produce verifiable_inference
113
+ const others = [
114
+ 'deterministic_rule',
115
+ 'ml_model',
116
+ 'statistical_test',
117
+ 'custom_code',
118
+ 'witnessed',
119
+ ];
120
+ for (const st of others) {
121
+ expect(selectProofLevel(st)).not.toBe('verifiable_inference');
122
+ }
123
+ });
124
+ });
125
+ //# sourceMappingURL=commitment.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitment.test.js","sourceRoot":"","sources":["../src/commitment.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { canonical } from './canonical.js';
2
+ export { generateKeyPair, sign, verify, rotateKey, toBase64Url, fromBase64Url } from './signing.js';
3
+ export { commit, commitOutput, buildCommitmentRoot, selectProofLevel, ZK_IS_BLOCKING, } from './commitment.js';
4
+ export type { CommitmentResult } from './commitment.js';
5
+ export { validateArtifact } from './validate-artifact.js';
6
+ export type { ValidationError, ValidationResult } from './validate-artifact.js';
7
+ export type { SignerRecord, SignatureEnvelope, KeyStatus, RevocationReason, SignerType, } from './types.js';
8
+ export type { VPECArtifact, ProofLevel, SurfaceEntry, ProofDistribution, Coverage, GapEntry, ZkProof, ArtifactIssuer, ArtifactSignature, TimestampAnchor, TransparencyLog, PendingFlags, GapType, GapSeverity, SurfaceType, ObservationMode, ScopeType, PolicyBasis, ArtifactState, CommitmentAlgorithm, Prover, ProverSystem, TsaProvider, OrgRegion, } from './types/artifact.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACpG,OAAO,EACL,MAAM,EACN,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAChF,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAe,EACf,SAAS,EACT,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,MAAM,EACN,YAAY,EACZ,WAAW,EACX,SAAS,GACV,MAAM,qBAAqB,CAAC"}