@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.
- package/dist/canonical.d.ts +24 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +83 -0
- package/dist/canonical.js.map +1 -0
- package/dist/canonical.test.d.ts +2 -0
- package/dist/canonical.test.d.ts.map +1 -0
- package/dist/canonical.test.js +63 -0
- package/dist/canonical.test.js.map +1 -0
- package/dist/commitment.d.ts +56 -0
- package/dist/commitment.d.ts.map +1 -0
- package/dist/commitment.js +214 -0
- package/dist/commitment.js.map +1 -0
- package/dist/commitment.test.d.ts +7 -0
- package/dist/commitment.test.d.ts.map +1 -0
- package/dist/commitment.test.js +125 -0
- package/dist/commitment.test.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/signing.d.ts +80 -0
- package/dist/signing.d.ts.map +1 -0
- package/dist/signing.js +159 -0
- package/dist/signing.js.map +1 -0
- package/dist/signing.test.d.ts +2 -0
- package/dist/signing.test.d.ts.map +1 -0
- package/dist/signing.test.js +153 -0
- package/dist/signing.test.js.map +1 -0
- package/dist/types/artifact.d.ts +143 -0
- package/dist/types/artifact.d.ts.map +1 -0
- package/dist/types/artifact.js +18 -0
- package/dist/types/artifact.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-artifact.d.ts +23 -0
- package/dist/validate-artifact.d.ts.map +1 -0
- package/dist/validate-artifact.js +168 -0
- package/dist/validate-artifact.js.map +1 -0
- package/dist/validate-artifact.test.d.ts +2 -0
- package/dist/validate-artifact.test.d.ts.map +1 -0
- package/dist/validate-artifact.test.js +300 -0
- package/dist/validate-artifact.test.js.map +1 -0
- 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"}
|
package/dist/signing.js
ADDED
|
@@ -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":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,kCAAkC;AAClC,EAAE,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,GAAG,CAAe,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAE7E,qDAAqD;AACrD,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;SACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,6CAA6C;AAC7C,SAAS,WAAW,CAAC,KAAiB;IACpC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACjF,CAAC;AAED,gCAAgC;AAChC,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,KAAa,EACb,UAAsB;IAEtB,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,MAAM,YAAY,GAAiB;QACjC,SAAS,EAAE,QAAQ;QACnB,GAAG;QACH,iBAAiB,EAAE,WAAW,CAAC,SAAS,CAAC;QACzC,SAAS,EAAE,SAAS;QACpB,MAAM,EAAE,QAAQ;QAChB,iBAAiB,EAAE,IAAI;QACvB,UAAU,EAAE,IAAI;QAChB,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,GAAG;QACjB,cAAc,EAAE,IAAI;QACpB,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,UAAU;KACxB,CAAC;IAEF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,IAAI,CAClB,QAAiC,EACjC,UAAsB,EACtB,YAA0B;IAE1B,IAAI,YAAY,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,oBAAoB,YAAY,CAAC,MAAM,cAAc,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC;IAC5F,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACjE,MAAM,cAAc,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAEtD,MAAM,iBAAiB,GAAsB;QAC3C,SAAS,EAAE,YAAY,CAAC,SAAS;QACjC,GAAG,EAAE,YAAY,CAAC,GAAG;QACrB,SAAS,EAAE,SAAS;QACpB,SAAS,EAAE,WAAW,CAAC,cAAc,CAAC;QACtC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CACpB,QAAiC,EACjC,iBAAoC,EACpC,eAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACjE,MAAM,cAAc,GAAG,aAAa,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAClE,MAAM,cAAc,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;QAEtD,OAAO,EAAE,CAAC,MAAM,CAAC,cAAc,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,cAA4B;IAKpD,IAAI,cAAc,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CACb,iBAAiB,cAAc,CAAC,MAAM,cAAc,cAAc,CAAC,GAAG,qCAAqC,CAC5G,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,eAAe,CAC5E,cAAc,CAAC,SAAS,EACxB,cAAc,CAAC,MAAM,EACrB,cAAc,CAAC,WAAW,CAC3B,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,mCAAmC;IACnC,MAAM,aAAa,GAAiB;QAClC,GAAG,cAAc;QACjB,MAAM,EAAE,SAAS;QACjB,iBAAiB,EAAE,SAAS,CAAC,GAAG;QAChC,cAAc,EAAE,GAAG;KACpB,CAAC;IAEF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AACrD,CAAC;AAED,uCAAuC;AACvC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -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"}
|