@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
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // @primust/artifact-core — Canonical JSON, hashing, signing, commitments, artifact types
2
+ export { canonical } from './canonical.js';
3
+ export { generateKeyPair, sign, verify, rotateKey, toBase64Url, fromBase64Url } from './signing.js';
4
+ export { commit, commitOutput, buildCommitmentRoot, selectProofLevel, ZK_IS_BLOCKING, } from './commitment.js';
5
+ export { validateArtifact } from './validate-artifact.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,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;AAEzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Primust Signing — Ed25519 key generation, signing, verification, rotation
3
+ *
4
+ * Signing process (spec):
5
+ * 1. canonical(document) → string
6
+ * 2. SHA-256(canonical_string) → bytes
7
+ * 3. Ed25519.sign(hash_bytes, private_key) → signature_bytes
8
+ * 4. base64url(signature_bytes) → signature field
9
+ *
10
+ * Key identity invariants (SIGNER_TRUST_POLICY.md):
11
+ * - signer_id: stable logical identifier, survives rotation
12
+ * - kid: specific key version, unique per generation
13
+ * - Both required in every SignatureEnvelope
14
+ * - Rotation creates new kid, same signer_id
15
+ * - Rotation does NOT invalidate prior signatures (Q2 quarantine)
16
+ *
17
+ * Libraries: @noble/ed25519 + @noble/hashes
18
+ */
19
+ import type { SignerRecord, SignatureEnvelope, SignerType } from './types.js';
20
+ /** Encode bytes to base64url (no padding) */
21
+ declare function toBase64Url(bytes: Uint8Array): string;
22
+ /** Decode base64url to bytes */
23
+ declare function fromBase64Url(b64url: string): Uint8Array;
24
+ /**
25
+ * Generate a new Ed25519 key pair and produce a SignerRecord.
26
+ *
27
+ * Each call produces a distinct kid. No silent auto-generation (Q4 quarantine).
28
+ */
29
+ export declare function generateKeyPair(signerId: string, orgId: string, signerType: SignerType): {
30
+ signerRecord: SignerRecord;
31
+ privateKey: Uint8Array;
32
+ };
33
+ /**
34
+ * Sign a document.
35
+ *
36
+ * Process:
37
+ * 1. canonical(document) → deterministic JSON string
38
+ * 2. SHA-256(canonical_string) → 32-byte hash
39
+ * 3. Ed25519.sign(hash, privateKey) → 64-byte signature
40
+ * 4. base64url(signature) → string
41
+ *
42
+ * @param document - The document to sign (must contain only JSON-native types)
43
+ * @param privateKey - Ed25519 private key bytes
44
+ * @param signerRecord - The signer's active record (must have status 'active')
45
+ * @returns The original document and its signature envelope
46
+ */
47
+ export declare function sign(document: Record<string, unknown>, privateKey: Uint8Array, signerRecord: SignerRecord): {
48
+ document: Record<string, unknown>;
49
+ signatureEnvelope: SignatureEnvelope;
50
+ };
51
+ /**
52
+ * Verify a document's signature.
53
+ *
54
+ * Recomputes canonical(document) → SHA-256 → verifies Ed25519 signature.
55
+ * Does NOT evaluate key status — that is the verifier's responsibility
56
+ * (SIGNER_TRUST_POLICY.md §3–4).
57
+ *
58
+ * @param document - The document that was signed
59
+ * @param signatureEnvelope - The signature envelope
60
+ * @param publicKeyB64Url - Base64url-encoded Ed25519 public key
61
+ * @returns true if the cryptographic signature is valid
62
+ */
63
+ export declare function verify(document: Record<string, unknown>, signatureEnvelope: SignatureEnvelope, publicKeyB64Url: string): boolean;
64
+ /**
65
+ * Rotate a key: create a new kid under the same signer_id.
66
+ *
67
+ * The existing record transitions to 'rotated'. A new record is created
68
+ * with status 'active'. Prior signatures remain valid against the old kid
69
+ * (SIGNER_TRUST_POLICY.md §2, Q2 quarantine).
70
+ *
71
+ * @param existingRecord - The current active SignerRecord
72
+ * @returns Updated old record (rotated) and new active record + private key
73
+ */
74
+ export declare function rotateKey(existingRecord: SignerRecord): {
75
+ updatedRecord: SignerRecord;
76
+ newRecord: SignerRecord;
77
+ newPrivateKey: Uint8Array;
78
+ };
79
+ export { toBase64Url, fromBase64Url };
80
+ //# sourceMappingURL=signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAa9E,6CAA6C;AAC7C,iBAAS,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAM9C;AAED,gCAAgC;AAChC,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CASjD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,UAAU,GACrB;IAAE,YAAY,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAsBxD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,IAAI,CAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,GACzB;IAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAA;CAAE,CAkB7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,MAAM,GACtB,OAAO,CAWT;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,cAAc,EAAE,YAAY,GAAG;IACvD,aAAa,EAAE,YAAY,CAAC;IAC5B,SAAS,EAAE,YAAY,CAAC;IACxB,aAAa,EAAE,UAAU,CAAC;CAC3B,CAyBA;AAGD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Primust Signing — Ed25519 key generation, signing, verification, rotation
3
+ *
4
+ * Signing process (spec):
5
+ * 1. canonical(document) → string
6
+ * 2. SHA-256(canonical_string) → bytes
7
+ * 3. Ed25519.sign(hash_bytes, private_key) → signature_bytes
8
+ * 4. base64url(signature_bytes) → signature field
9
+ *
10
+ * Key identity invariants (SIGNER_TRUST_POLICY.md):
11
+ * - signer_id: stable logical identifier, survives rotation
12
+ * - kid: specific key version, unique per generation
13
+ * - Both required in every SignatureEnvelope
14
+ * - Rotation creates new kid, same signer_id
15
+ * - Rotation does NOT invalidate prior signatures (Q2 quarantine)
16
+ *
17
+ * Libraries: @noble/ed25519 + @noble/hashes
18
+ */
19
+ import * as ed from '@noble/ed25519';
20
+ import { sha512 } from '@noble/hashes/sha512';
21
+ import { sha256 } from '@noble/hashes/sha256';
22
+ import { canonical } from './canonical.js';
23
+ // Configure ed25519 to use sha512
24
+ ed.etc.sha512Sync = (...m) => sha512(ed.etc.concatBytes(...m));
25
+ /** Generate a cryptographically random hex string */
26
+ function randomHex(bytes) {
27
+ const buf = ed.utils.randomPrivateKey().slice(0, bytes);
28
+ return Array.from(buf)
29
+ .map((b) => b.toString(16).padStart(2, '0'))
30
+ .join('');
31
+ }
32
+ /** Encode bytes to base64url (no padding) */
33
+ function toBase64Url(bytes) {
34
+ let binary = '';
35
+ for (const byte of bytes) {
36
+ binary += String.fromCharCode(byte);
37
+ }
38
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
39
+ }
40
+ /** Decode base64url to bytes */
41
+ function fromBase64Url(b64url) {
42
+ const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
43
+ const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);
44
+ const binary = atob(padded);
45
+ const bytes = new Uint8Array(binary.length);
46
+ for (let i = 0; i < binary.length; i++) {
47
+ bytes[i] = binary.charCodeAt(i);
48
+ }
49
+ return bytes;
50
+ }
51
+ /**
52
+ * Generate a new Ed25519 key pair and produce a SignerRecord.
53
+ *
54
+ * Each call produces a distinct kid. No silent auto-generation (Q4 quarantine).
55
+ */
56
+ export function generateKeyPair(signerId, orgId, signerType) {
57
+ const privateKey = ed.utils.randomPrivateKey();
58
+ const publicKey = ed.getPublicKey(privateKey);
59
+ const kid = `kid_${randomHex(8)}`;
60
+ const now = new Date().toISOString();
61
+ const signerRecord = {
62
+ signer_id: signerId,
63
+ kid,
64
+ public_key_b64url: toBase64Url(publicKey),
65
+ algorithm: 'Ed25519',
66
+ status: 'active',
67
+ revocation_reason: null,
68
+ revoked_at: null,
69
+ superseded_by_kid: null,
70
+ activated_at: now,
71
+ deactivated_at: null,
72
+ org_id: orgId,
73
+ signer_type: signerType,
74
+ };
75
+ return { signerRecord, privateKey };
76
+ }
77
+ /**
78
+ * Sign a document.
79
+ *
80
+ * Process:
81
+ * 1. canonical(document) → deterministic JSON string
82
+ * 2. SHA-256(canonical_string) → 32-byte hash
83
+ * 3. Ed25519.sign(hash, privateKey) → 64-byte signature
84
+ * 4. base64url(signature) → string
85
+ *
86
+ * @param document - The document to sign (must contain only JSON-native types)
87
+ * @param privateKey - Ed25519 private key bytes
88
+ * @param signerRecord - The signer's active record (must have status 'active')
89
+ * @returns The original document and its signature envelope
90
+ */
91
+ export function sign(document, privateKey, signerRecord) {
92
+ if (signerRecord.status !== 'active') {
93
+ throw new Error(`Cannot sign with ${signerRecord.status} key (kid: ${signerRecord.kid})`);
94
+ }
95
+ const canonicalStr = canonical(document);
96
+ const hashBytes = sha256(new TextEncoder().encode(canonicalStr));
97
+ const signatureBytes = ed.sign(hashBytes, privateKey);
98
+ const signatureEnvelope = {
99
+ signer_id: signerRecord.signer_id,
100
+ kid: signerRecord.kid,
101
+ algorithm: 'Ed25519',
102
+ signature: toBase64Url(signatureBytes),
103
+ signed_at: new Date().toISOString(),
104
+ };
105
+ return { document, signatureEnvelope };
106
+ }
107
+ /**
108
+ * Verify a document's signature.
109
+ *
110
+ * Recomputes canonical(document) → SHA-256 → verifies Ed25519 signature.
111
+ * Does NOT evaluate key status — that is the verifier's responsibility
112
+ * (SIGNER_TRUST_POLICY.md §3–4).
113
+ *
114
+ * @param document - The document that was signed
115
+ * @param signatureEnvelope - The signature envelope
116
+ * @param publicKeyB64Url - Base64url-encoded Ed25519 public key
117
+ * @returns true if the cryptographic signature is valid
118
+ */
119
+ export function verify(document, signatureEnvelope, publicKeyB64Url) {
120
+ try {
121
+ const canonicalStr = canonical(document);
122
+ const hashBytes = sha256(new TextEncoder().encode(canonicalStr));
123
+ const signatureBytes = fromBase64Url(signatureEnvelope.signature);
124
+ const publicKeyBytes = fromBase64Url(publicKeyB64Url);
125
+ return ed.verify(signatureBytes, hashBytes, publicKeyBytes);
126
+ }
127
+ catch {
128
+ return false;
129
+ }
130
+ }
131
+ /**
132
+ * Rotate a key: create a new kid under the same signer_id.
133
+ *
134
+ * The existing record transitions to 'rotated'. A new record is created
135
+ * with status 'active'. Prior signatures remain valid against the old kid
136
+ * (SIGNER_TRUST_POLICY.md §2, Q2 quarantine).
137
+ *
138
+ * @param existingRecord - The current active SignerRecord
139
+ * @returns Updated old record (rotated) and new active record + private key
140
+ */
141
+ export function rotateKey(existingRecord) {
142
+ if (existingRecord.status !== 'active') {
143
+ throw new Error(`Cannot rotate ${existingRecord.status} key (kid: ${existingRecord.kid}). Only active keys can be rotated.`);
144
+ }
145
+ // Generate new key pair under the same signer_id
146
+ const { signerRecord: newRecord, privateKey: newPrivateKey } = generateKeyPair(existingRecord.signer_id, existingRecord.org_id, existingRecord.signer_type);
147
+ const now = new Date().toISOString();
148
+ // Transition old record to rotated
149
+ const updatedRecord = {
150
+ ...existingRecord,
151
+ status: 'rotated',
152
+ superseded_by_kid: newRecord.kid,
153
+ deactivated_at: now,
154
+ };
155
+ return { updatedRecord, newRecord, newPrivateKey };
156
+ }
157
+ // Re-export utilities for consumer use
158
+ export { toBase64Url, fromBase64Url };
159
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.test.d.ts","sourceRoot":"","sources":["../src/signing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { generateKeyPair, sign, verify, rotateKey } from './signing.js';
3
+ describe('signing', () => {
4
+ const SIGNER_ID = 'signer_test_001';
5
+ const ORG_ID = 'org_test_001';
6
+ const SIGNER_TYPE = 'artifact_signer';
7
+ describe('generateKeyPair', () => {
8
+ it('produces a valid SignerRecord with distinct kid', () => {
9
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
10
+ expect(signerRecord.signer_id).toBe(SIGNER_ID);
11
+ expect(signerRecord.kid).toMatch(/^kid_[0-9a-f]{16}$/);
12
+ expect(signerRecord.algorithm).toBe('Ed25519');
13
+ expect(signerRecord.status).toBe('active');
14
+ expect(signerRecord.revocation_reason).toBeNull();
15
+ expect(signerRecord.revoked_at).toBeNull();
16
+ expect(signerRecord.superseded_by_kid).toBeNull();
17
+ expect(signerRecord.org_id).toBe(ORG_ID);
18
+ expect(signerRecord.signer_type).toBe(SIGNER_TYPE);
19
+ expect(signerRecord.public_key_b64url).toBeTypeOf('string');
20
+ expect(signerRecord.public_key_b64url.length).toBeGreaterThan(0);
21
+ expect(privateKey).toBeInstanceOf(Uint8Array);
22
+ expect(privateKey.length).toBe(32);
23
+ });
24
+ it('generates distinct kid on each call (signer_id ≠ kid)', () => {
25
+ const a = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
26
+ const b = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
27
+ // Same signer_id
28
+ expect(a.signerRecord.signer_id).toBe(b.signerRecord.signer_id);
29
+ // Different kid
30
+ expect(a.signerRecord.kid).not.toBe(b.signerRecord.kid);
31
+ // Different key material
32
+ expect(a.signerRecord.public_key_b64url).not.toBe(b.signerRecord.public_key_b64url);
33
+ });
34
+ });
35
+ describe('sign → verify roundtrip', () => {
36
+ it('MUST PASS: sign → verify roundtrip', () => {
37
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
38
+ const doc = { action: 'create', target: 'resource_42', ts: '2026-03-10T00:00:00Z' };
39
+ const { document, signatureEnvelope } = sign(doc, privateKey, signerRecord);
40
+ expect(signatureEnvelope.signer_id).toBe(SIGNER_ID);
41
+ expect(signatureEnvelope.kid).toBe(signerRecord.kid);
42
+ expect(signatureEnvelope.algorithm).toBe('Ed25519');
43
+ expect(signatureEnvelope.signature).toBeTypeOf('string');
44
+ expect(signatureEnvelope.signed_at).toMatch(/^\d{4}-/);
45
+ const valid = verify(document, signatureEnvelope, signerRecord.public_key_b64url);
46
+ expect(valid).toBe(true);
47
+ });
48
+ it('MUST PASS: tampered document fails verify', () => {
49
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
50
+ const doc = { action: 'create', target: 'resource_42' };
51
+ const { signatureEnvelope } = sign(doc, privateKey, signerRecord);
52
+ // Tamper with the document
53
+ const tampered = { action: 'delete', target: 'resource_42' };
54
+ const valid = verify(tampered, signatureEnvelope, signerRecord.public_key_b64url);
55
+ expect(valid).toBe(false);
56
+ });
57
+ it('wrong public key fails verify', () => {
58
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
59
+ const other = generateKeyPair('signer_other', ORG_ID, SIGNER_TYPE);
60
+ const doc = { msg: 'hello' };
61
+ const { document, signatureEnvelope } = sign(doc, privateKey, signerRecord);
62
+ const valid = verify(document, signatureEnvelope, other.signerRecord.public_key_b64url);
63
+ expect(valid).toBe(false);
64
+ });
65
+ it('corrupted signature fails verify', () => {
66
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
67
+ const doc = { data: 'test' };
68
+ const { document, signatureEnvelope } = sign(doc, privateKey, signerRecord);
69
+ const corrupted = { ...signatureEnvelope, signature: 'AAAA_bad_signature' };
70
+ const valid = verify(document, corrupted, signerRecord.public_key_b64url);
71
+ expect(valid).toBe(false);
72
+ });
73
+ });
74
+ describe('sign guards', () => {
75
+ it('refuses to sign with a rotated key', () => {
76
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
77
+ const rotatedRecord = { ...signerRecord, status: 'rotated' };
78
+ expect(() => sign({ data: 'test' }, privateKey, rotatedRecord)).toThrow(/rotated/);
79
+ });
80
+ it('refuses to sign with a revoked key', () => {
81
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
82
+ const revokedRecord = { ...signerRecord, status: 'revoked' };
83
+ expect(() => sign({ data: 'test' }, privateKey, revokedRecord)).toThrow(/revoked/);
84
+ });
85
+ });
86
+ describe('rotateKey', () => {
87
+ it('MUST PASS: rotated kid still verifies historical document', () => {
88
+ const { signerRecord: original, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
89
+ const doc = { historical: true, version: 1 };
90
+ // Sign with original key
91
+ const { document, signatureEnvelope } = sign(doc, privateKey, original);
92
+ // Rotate the key
93
+ const { updatedRecord, newRecord } = rotateKey(original);
94
+ // Original record is now rotated
95
+ expect(updatedRecord.status).toBe('rotated');
96
+ expect(updatedRecord.kid).toBe(original.kid);
97
+ expect(updatedRecord.signer_id).toBe(SIGNER_ID);
98
+ // New record is active under the same signer_id
99
+ expect(newRecord.status).toBe('active');
100
+ expect(newRecord.signer_id).toBe(SIGNER_ID);
101
+ expect(newRecord.kid).not.toBe(original.kid);
102
+ // Historical document STILL verifies against the original public key
103
+ const valid = verify(document, signatureEnvelope, updatedRecord.public_key_b64url);
104
+ expect(valid).toBe(true);
105
+ });
106
+ it('MUST PASS: rotateKey sets superseded_by_kid on old record', () => {
107
+ const { signerRecord } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
108
+ const { updatedRecord, newRecord } = rotateKey(signerRecord);
109
+ expect(updatedRecord.superseded_by_kid).toBe(newRecord.kid);
110
+ expect(updatedRecord.deactivated_at).toMatch(/^\d{4}-/);
111
+ });
112
+ it('rotateKey preserves signer_id across rotation', () => {
113
+ const { signerRecord } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
114
+ const { updatedRecord, newRecord } = rotateKey(signerRecord);
115
+ expect(updatedRecord.signer_id).toBe(SIGNER_ID);
116
+ expect(newRecord.signer_id).toBe(SIGNER_ID);
117
+ });
118
+ it('cannot rotate an already-rotated key', () => {
119
+ const { signerRecord } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
120
+ const { updatedRecord } = rotateKey(signerRecord);
121
+ expect(() => rotateKey(updatedRecord)).toThrow(/rotated/);
122
+ });
123
+ });
124
+ describe('quarantine compliance', () => {
125
+ it('MUST PASS: no hardcoded keys anywhere', () => {
126
+ // Generate multiple keypairs and verify they are all unique
127
+ const keys = Array.from({ length: 5 }, () => generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE));
128
+ const publicKeys = new Set(keys.map((k) => k.signerRecord.public_key_b64url));
129
+ const kids = new Set(keys.map((k) => k.signerRecord.kid));
130
+ expect(publicKeys.size).toBe(5);
131
+ expect(kids.size).toBe(5);
132
+ });
133
+ it('signature envelope always contains both signer_id and kid', () => {
134
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
135
+ const doc = { test: true };
136
+ const { signatureEnvelope } = sign(doc, privateKey, signerRecord);
137
+ expect(signatureEnvelope.signer_id).toBe(SIGNER_ID);
138
+ expect(signatureEnvelope.kid).toBe(signerRecord.kid);
139
+ expect(signatureEnvelope.signer_id).not.toBe(signatureEnvelope.kid);
140
+ });
141
+ it('canonical serialization is recursive (Q1 enforcement)', () => {
142
+ const { signerRecord, privateKey } = generateKeyPair(SIGNER_ID, ORG_ID, SIGNER_TYPE);
143
+ // Two documents with same data but different nested key order
144
+ const doc1 = { outer: { z: 1, a: 2 }, id: 'test' };
145
+ const doc2 = { id: 'test', outer: { a: 2, z: 1 } };
146
+ const { signatureEnvelope: sig1 } = sign(doc1, privateKey, signerRecord);
147
+ // doc2 should verify against sig1 because canonical form is identical
148
+ const valid = verify(doc2, sig1, signerRecord.public_key_b64url);
149
+ expect(valid).toBe(true);
150
+ });
151
+ });
152
+ });
153
+ //# sourceMappingURL=signing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.test.js","sourceRoot":"","sources":["../src/signing.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Primust VPEC Artifact Schema — TypeScript types
3
+ *
4
+ * Provisional-frozen at schema_version 4.0.0
5
+ * Canonical source: schemas/json/artifact.schema.json
6
+ *
7
+ * INVARIANTS (enforced in validateArtifact):
8
+ * 1. proof_level MUST equal proof_distribution.weakest_link
9
+ * 2. reliance_mode field ANYWHERE → validation error
10
+ * 3. manifest_hashes MUST be object (map), not array
11
+ * 4. gaps[] entries MUST have gap_type + severity (not bare strings)
12
+ * 5. partial: true → policy_coverage_pct must be 0
13
+ * 6. instrumentation_surface_pct and policy_coverage_pct never collapsed
14
+ * 7. issuer.public_key_url must match primust.com/.well-known/ pattern
15
+ * 8. test_mode: true rejected by primust-verify in --production mode
16
+ */
17
+ export type ProofLevel = 'mathematical' | 'verifiable_inference' | 'execution' | 'witnessed' | 'attestation';
18
+ export type SurfaceType = 'in_process_adapter' | 'middleware_interceptor' | 'platform_event_feed' | 'audit_log_ingest' | 'manual_assertion';
19
+ export type ObservationMode = 'pre_action' | 'in_flight' | 'post_action_realtime' | 'post_action_batch';
20
+ export type ScopeType = 'full_workflow' | 'orchestration_boundary' | 'platform_logged_events' | 'component_scope' | 'partial_unknown';
21
+ export type PolicyBasis = 'P1_self_declared' | 'P2_baseline_aligned' | 'P3_baseline_plus_deviations';
22
+ export type ArtifactState = 'provisional' | 'signed' | 'final';
23
+ export type CommitmentAlgorithm = 'poseidon2' | 'sha256';
24
+ export type Prover = 'local' | 'modal_cpu' | 'modal_gpu';
25
+ export type ProverSystem = 'ultrahonk' | 'ezkl' | 'groth16_bionetta';
26
+ export type TsaProvider = 'digicert_us' | 'digicert_eu' | 'none';
27
+ export type OrgRegion = 'us' | 'eu';
28
+ export type GapSeverity = 'Critical' | 'High' | 'Medium' | 'Low' | 'Informational';
29
+ export type GapType = 'check_not_executed' | 'enforcement_override' | 'engine_error' | 'check_degraded' | 'external_boundary_traversal' | 'lineage_token_missing' | 'admission_gate_override' | 'check_timing_suspect' | 'reviewer_credential_invalid' | 'witnessed_display_missing' | 'witnessed_rationale_missing' | 'deterministic_consistency_violation' | 'skip_rationale_missing' | 'policy_config_drift' | 'zkml_proof_pending_timeout' | 'zkml_proof_failed' | 'explanation_missing' | 'bias_audit_missing';
30
+ export interface SurfaceEntry {
31
+ surface_id: string;
32
+ surface_type: SurfaceType;
33
+ observation_mode: ObservationMode;
34
+ proof_ceiling: ProofLevel;
35
+ scope_type: ScopeType;
36
+ scope_description: string;
37
+ surface_coverage_statement: string;
38
+ }
39
+ export interface ProofDistribution {
40
+ mathematical: number;
41
+ verifiable_inference: number;
42
+ execution: number;
43
+ witnessed: number;
44
+ attestation: number;
45
+ weakest_link: ProofLevel;
46
+ weakest_link_explanation: string;
47
+ }
48
+ export interface Coverage {
49
+ records_total: number;
50
+ records_pass: number;
51
+ records_fail: number;
52
+ records_degraded: number;
53
+ records_not_applicable: number;
54
+ /** DENOMINATOR 1: % of required checks (per PolicySnapshot) that ran. */
55
+ policy_coverage_pct: number;
56
+ /** DENOMINATOR 2: % of total workflow universe in instrumentation scope. null when partial_unknown. NEVER collapse with policy_coverage_pct. */
57
+ instrumentation_surface_pct: number | null;
58
+ /** Plain-English statement of what the surface denominator represents. */
59
+ instrumentation_surface_basis: string;
60
+ }
61
+ export interface GapEntry {
62
+ gap_id: string;
63
+ gap_type: GapType;
64
+ severity: GapSeverity;
65
+ }
66
+ export interface ZkProof {
67
+ circuit: string;
68
+ proof_bytes: string;
69
+ public_inputs: string[];
70
+ verified_at: string;
71
+ prover: Prover;
72
+ prover_system: ProverSystem;
73
+ nargo_version: string | null;
74
+ }
75
+ export interface ArtifactIssuer {
76
+ signer_id: string;
77
+ kid: string;
78
+ algorithm: 'Ed25519';
79
+ public_key_url: string;
80
+ org_region: OrgRegion;
81
+ }
82
+ export interface ArtifactSignature {
83
+ signer_id: string;
84
+ kid: string;
85
+ algorithm: 'Ed25519';
86
+ signature: string;
87
+ signed_at: string;
88
+ }
89
+ export interface TimestampAnchor {
90
+ type: 'rfc3161' | 'none';
91
+ tsa: TsaProvider;
92
+ value: string | null;
93
+ }
94
+ export interface TransparencyLog {
95
+ rekor_log_id: string | null;
96
+ rekor_entry_url: string | null;
97
+ published_at: string | null;
98
+ }
99
+ export interface PendingFlags {
100
+ signature_pending: boolean;
101
+ /** true when Noir/UltraHonk proof in-flight */
102
+ proof_pending: boolean;
103
+ /** true when EZKL/Bionetta proof in-flight (Tier 2) */
104
+ zkml_proof_pending: boolean;
105
+ submission_pending: boolean;
106
+ /** true until transparency_log.rekor_log_id populated */
107
+ rekor_pending: boolean;
108
+ }
109
+ export interface VPECArtifact {
110
+ vpec_id: string;
111
+ schema_version: '4.0.0';
112
+ org_id: string;
113
+ run_id: string;
114
+ workflow_id: string;
115
+ /** Customer-computed config epoch hash. null when not provided. */
116
+ process_context_hash: string | null;
117
+ policy_snapshot_hash: string;
118
+ policy_basis: PolicyBasis;
119
+ /** true when issued via p.close(partial=True). Coverage credit NOT awarded. */
120
+ partial: boolean;
121
+ surface_summary: SurfaceEntry[];
122
+ /** MUST equal proof_distribution.weakest_link. Computed — never set manually. */
123
+ proof_level: ProofLevel;
124
+ proof_distribution: ProofDistribution;
125
+ state: ArtifactState;
126
+ coverage: Coverage;
127
+ gaps: GapEntry[];
128
+ /** Map of manifest_id → sha256:hex. Object, not array. */
129
+ manifest_hashes: Record<string, string>;
130
+ /** Merkle root over all CheckExecutionRecord commitment_hashes. null when zero records. */
131
+ commitment_root: string | null;
132
+ commitment_algorithm: CommitmentAlgorithm;
133
+ zk_proof: ZkProof | null;
134
+ issuer: ArtifactIssuer;
135
+ signature: ArtifactSignature;
136
+ timestamp_anchor: TimestampAnchor;
137
+ transparency_log: TransparencyLog;
138
+ issued_at: string;
139
+ pending_flags: PendingFlags;
140
+ /** true when issued with pk_test_xxx key. Rejected by primust-verify in --production. */
141
+ test_mode: boolean;
142
+ }
143
+ //# sourceMappingURL=artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../../src/types/artifact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Primust VPEC Artifact Schema — TypeScript types
3
+ *
4
+ * Provisional-frozen at schema_version 4.0.0
5
+ * Canonical source: schemas/json/artifact.schema.json
6
+ *
7
+ * INVARIANTS (enforced in validateArtifact):
8
+ * 1. proof_level MUST equal proof_distribution.weakest_link
9
+ * 2. reliance_mode field ANYWHERE → validation error
10
+ * 3. manifest_hashes MUST be object (map), not array
11
+ * 4. gaps[] entries MUST have gap_type + severity (not bare strings)
12
+ * 5. partial: true → policy_coverage_pct must be 0
13
+ * 6. instrumentation_surface_pct and policy_coverage_pct never collapsed
14
+ * 7. issuer.public_key_url must match primust.com/.well-known/ pattern
15
+ * 8. test_mode: true rejected by primust-verify in --production mode
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../src/types/artifact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}