hachure 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,332 @@
1
+ {
2
+ "now": "2026-06-10T00:00:00.000Z",
3
+ "input": {
4
+ "schemaVersion": 3,
5
+ "source": "kontour-surface-validation-fixtures",
6
+ "identityLinks": [
7
+ {
8
+ "subjects": [
9
+ {
10
+ "subjectType": "repo-surface",
11
+ "subjectId": "example/repo:src/api"
12
+ },
13
+ {
14
+ "subjectType": "release-channel",
15
+ "subjectId": "repo-governance:api"
16
+ }
17
+ ],
18
+ "reason": "API source and the named release channel describe the same surface."
19
+ }
20
+ ],
21
+ "claims": [
22
+ {
23
+ "id": "claim.repo-governance.api-proof",
24
+ "subjectType": "repo-surface",
25
+ "subjectId": "example/repo:src/api",
26
+ "surface": "repo-governance.developer-evidence",
27
+ "claimType": "software-evidence",
28
+ "fieldOrBehavior": "acceptanceCriteriaLane",
29
+ "value": "npm test passed for API surface change",
30
+ "createdAt": "2026-04-25T00:00:00.000Z",
31
+ "updatedAt": "2026-04-25T00:05:00.000Z",
32
+ "impactLevel": "high",
33
+ "currentIntegrityRef": "commit-or-run-id-placeholder",
34
+ "verificationPolicyId": "policy.software-evidence.commit",
35
+ "subjectAliases": [
36
+ {
37
+ "subjectType": "release-channel",
38
+ "subjectId": "repo-governance:api"
39
+ }
40
+ ],
41
+ "confidenceBasis": {
42
+ "sourceQuality": "strong",
43
+ "reviewerAuthority": "system",
44
+ "evidenceStrength": "strong",
45
+ "impactLevel": "high"
46
+ }
47
+ },
48
+ {
49
+ "id": "claim.field-attested-records.registration-status",
50
+ "subjectType": "attested-record",
51
+ "subjectId": "field-attested-records:denver-example-record",
52
+ "surface": "field-attested-records.public-data",
53
+ "claimType": "public-data-field",
54
+ "fieldOrBehavior": "registrationStatus",
55
+ "value": "OPEN",
56
+ "createdAt": "2026-04-01T00:00:00.000Z",
57
+ "updatedAt": "2026-04-01T00:00:00.000Z",
58
+ "impactLevel": "high",
59
+ "verificationPolicyId": "policy.public-data-field.short-lived",
60
+ "confidenceBasis": {
61
+ "sourceQuality": "strong",
62
+ "extractionConfidence": 0.92,
63
+ "corroborationCount": 1,
64
+ "reviewerAuthority": "operator",
65
+ "evidenceStrength": "moderate",
66
+ "impactLevel": "high"
67
+ }
68
+ },
69
+ {
70
+ "id": "claim.fact-resolution.w2-wages",
71
+ "subjectType": "fact",
72
+ "subjectId": "fact-resolution:demo-case-2025:w2.wages",
73
+ "surface": "fact-resolution.financial-facts",
74
+ "claimType": "verified-financial-fact",
75
+ "fieldOrBehavior": "w2.wages",
76
+ "value": 123456,
77
+ "createdAt": "2026-04-20T00:00:00.000Z",
78
+ "updatedAt": "2026-04-20T00:00:00.000Z",
79
+ "impactLevel": "critical",
80
+ "verificationPolicyId": "policy.financial-fact.historical",
81
+ "confidenceBasis": {
82
+ "sourceQuality": "strong",
83
+ "corroborationCount": 2,
84
+ "reviewerAuthority": "domain_expert",
85
+ "evidenceStrength": "strong",
86
+ "impactLevel": "critical"
87
+ }
88
+ },
89
+ {
90
+ "id": "claim.surface.future-console",
91
+ "subjectType": "roadmap-item",
92
+ "subjectId": "kontour-surface:hosted-console",
93
+ "surface": "surface.roadmap",
94
+ "claimType": "roadmap-capability",
95
+ "fieldOrBehavior": "implementationStatus",
96
+ "value": "planned",
97
+ "createdAt": "2026-04-25T00:00:00.000Z",
98
+ "updatedAt": "2026-04-25T00:00:00.000Z",
99
+ "impactLevel": "medium",
100
+ "verificationPolicyId": "policy.roadmap.manual"
101
+ }
102
+ ],
103
+ "evidence": [
104
+ {
105
+ "id": "evidence.repo-governance.test-output",
106
+ "claimId": "claim.repo-governance.api-proof",
107
+ "evidenceType": "test_output",
108
+ "method": "validation",
109
+ "sourceRef": "repo governance evidence check",
110
+ "sourceLocator": "npm test",
111
+ "excerptOrSummary": "84 tests passed for the verified repo state.",
112
+ "observedAt": "2026-04-25T00:05:00.000Z",
113
+ "collectedBy": "repo-governance",
114
+ "integrityRef": "commit-or-run-id-placeholder"
115
+ },
116
+ {
117
+ "id": "evidence.field-attested-records.source-excerpt",
118
+ "claimId": "claim.field-attested-records.registration-status",
119
+ "evidenceType": "source_excerpt",
120
+ "method": "observation",
121
+ "sourceRef": "https://example.org/camps/register",
122
+ "sourceLocator": "registration section",
123
+ "excerptOrSummary": "Registration is open now for summer sessions.",
124
+ "observedAt": "2026-04-01T00:00:00.000Z",
125
+ "collectedBy": "field-data-crawler"
126
+ },
127
+ {
128
+ "id": "evidence.field-attested-records.admin-attestation",
129
+ "claimId": "claim.field-attested-records.registration-status",
130
+ "evidenceType": "human_attestation",
131
+ "method": "attestation",
132
+ "sourceRef": "record steward review",
133
+ "sourceLocator": "FieldAttestation.registrationStatus",
134
+ "excerptOrSummary": "Admin approved the registration status from the source excerpt.",
135
+ "observedAt": "2026-04-01T00:10:00.000Z",
136
+ "collectedBy": "record-steward"
137
+ },
138
+ {
139
+ "id": "evidence.fact-resolution.document-citation",
140
+ "claimId": "claim.fact-resolution.w2-wages",
141
+ "evidenceType": "document_citation",
142
+ "method": "corroboration",
143
+ "sourceRef": "W-2 imported document",
144
+ "sourceLocator": "Box 1",
145
+ "excerptOrSummary": "W-2 Box 1 wages matched the verified fact value.",
146
+ "observedAt": "2026-04-20T00:00:00.000Z",
147
+ "collectedBy": "fact-importer",
148
+ "integrityRef": "document-hash-placeholder"
149
+ },
150
+ {
151
+ "id": "evidence.fact-resolution.calculation-trace",
152
+ "claimId": "claim.fact-resolution.w2-wages",
153
+ "evidenceType": "calculation_trace",
154
+ "method": "validation",
155
+ "sourceRef": "fact resolution package",
156
+ "sourceLocator": "verified_facts.w2.wages",
157
+ "excerptOrSummary": "Resolved fact was promoted to verified_facts before downstream analysis.",
158
+ "observedAt": "2026-04-20T00:15:00.000Z",
159
+ "collectedBy": "fact-resolution-service"
160
+ }
161
+ ],
162
+ "policies": [
163
+ {
164
+ "id": "policy.software-evidence.commit",
165
+ "claimType": "software-evidence",
166
+ "parentType": "developer-claim",
167
+ "requiredEvidence": [
168
+ "test_output"
169
+ ],
170
+ "requiredMethods": [
171
+ "validation"
172
+ ],
173
+ "requiresCorroboration": false,
174
+ "acceptanceCriteria": [
175
+ "evidence check passes for the affected commit or diff"
176
+ ],
177
+ "reviewAuthority": "repo policy",
178
+ "validityRule": {
179
+ "kind": "commit"
180
+ },
181
+ "stalenessTriggers": [
182
+ "new commit touches the same surface",
183
+ "evidence check changes"
184
+ ],
185
+ "conflictRules": [
186
+ "failed evidence check supersedes prior passing evidence"
187
+ ],
188
+ "impactLevel": "high",
189
+ "incompatibleStatuses": [
190
+ {
191
+ "statuses": [
192
+ "verified",
193
+ "rejected"
194
+ ],
195
+ "message": "A surface cannot be simultaneously verified and rejected at the same commit."
196
+ }
197
+ ]
198
+ },
199
+ {
200
+ "id": "policy.public-data-field.short-lived",
201
+ "claimType": "public-data-field",
202
+ "requiredEvidence": [
203
+ "source_excerpt",
204
+ "human_attestation"
205
+ ],
206
+ "requiredMethods": [
207
+ "observation",
208
+ "attestation"
209
+ ],
210
+ "requiresCorroboration": true,
211
+ "acceptanceCriteria": [
212
+ "field-level review or crawl approval"
213
+ ],
214
+ "reviewAuthority": "operator",
215
+ "validityRule": {
216
+ "kind": "duration",
217
+ "durationDays": 14
218
+ },
219
+ "stalenessTriggers": [
220
+ "source page changes",
221
+ "validity window expires",
222
+ "user report conflicts"
223
+ ],
224
+ "conflictRules": [
225
+ "new source excerpt conflicts with approved value"
226
+ ],
227
+ "impactLevel": "high"
228
+ },
229
+ {
230
+ "id": "policy.financial-fact.historical",
231
+ "claimType": "verified-financial-fact",
232
+ "requiredEvidence": [
233
+ "document_citation",
234
+ "calculation_trace"
235
+ ],
236
+ "requiredMethods": [
237
+ "corroboration",
238
+ "validation"
239
+ ],
240
+ "requiresCorroboration": true,
241
+ "acceptanceCriteria": [
242
+ "resolved fact promoted to verified fact"
243
+ ],
244
+ "reviewAuthority": "domain expert",
245
+ "validityRule": {
246
+ "kind": "historical"
247
+ },
248
+ "stalenessTriggers": [
249
+ "new source document imported",
250
+ "conflicting candidate appears"
251
+ ],
252
+ "conflictRules": [
253
+ "multi-candidate facts require manual resolution"
254
+ ],
255
+ "impactLevel": "critical"
256
+ },
257
+ {
258
+ "id": "policy.roadmap.manual",
259
+ "claimType": "roadmap-capability",
260
+ "requiredEvidence": [
261
+ "human_attestation"
262
+ ],
263
+ "requiredMethods": [
264
+ "attestation"
265
+ ],
266
+ "requiresCorroboration": false,
267
+ "acceptanceCriteria": [
268
+ "explicit roadmap acceptance"
269
+ ],
270
+ "reviewAuthority": "product owner",
271
+ "validityRule": {
272
+ "kind": "manual"
273
+ },
274
+ "stalenessTriggers": [
275
+ "roadmap changed"
276
+ ],
277
+ "conflictRules": [
278
+ "implementation claim without shipped evidence is unsupported"
279
+ ],
280
+ "impactLevel": "medium"
281
+ }
282
+ ],
283
+ "events": [
284
+ {
285
+ "id": "event.repo-governance.verified",
286
+ "claimId": "claim.repo-governance.api-proof",
287
+ "status": "verified",
288
+ "actor": "repo-governance",
289
+ "method": "evidence-check",
290
+ "evidenceIds": [
291
+ "evidence.repo-governance.test-output"
292
+ ],
293
+ "createdAt": "2026-04-25T00:05:00.000Z",
294
+ "verifiedAt": "2026-04-25T00:05:00.000Z"
295
+ },
296
+ {
297
+ "id": "event.field-attested-records.verified",
298
+ "claimId": "claim.field-attested-records.registration-status",
299
+ "status": "verified",
300
+ "actor": "record-steward",
301
+ "method": "field-attestation",
302
+ "evidenceIds": [
303
+ "evidence.field-attested-records.source-excerpt",
304
+ "evidence.field-attested-records.admin-attestation"
305
+ ],
306
+ "createdAt": "2026-04-01T00:10:00.000Z",
307
+ "verifiedAt": "2026-04-01T00:10:00.000Z"
308
+ },
309
+ {
310
+ "id": "event.fact-resolution.verified",
311
+ "claimId": "claim.fact-resolution.w2-wages",
312
+ "status": "verified",
313
+ "actor": "fact-resolution-service",
314
+ "method": "verified-fact-promotion",
315
+ "evidenceIds": [
316
+ "evidence.fact-resolution.document-citation",
317
+ "evidence.fact-resolution.calculation-trace"
318
+ ],
319
+ "createdAt": "2026-04-20T00:15:00.000Z",
320
+ "verifiedAt": "2026-04-20T00:15:00.000Z"
321
+ }
322
+ ]
323
+ },
324
+ "expect": {
325
+ "statusByClaimId": {
326
+ "claim.repo-governance.api-proof": "verified",
327
+ "claim.field-attested-records.registration-status": "stale",
328
+ "claim.fact-resolution.w2-wages": "verified",
329
+ "claim.surface.future-console": "unknown"
330
+ }
331
+ }
332
+ }
@@ -0,0 +1,76 @@
1
+ {
2
+ "now": "2026-06-10T00:00:00.000Z",
3
+ "input": {
4
+ "schemaVersion": 3,
5
+ "source": "spec-conformance:stale-duration",
6
+ "claims": [
7
+ {
8
+ "id": "claim.public.field",
9
+ "subjectType": "data-field",
10
+ "subjectId": "dataset:registration-status",
11
+ "surface": "public-data.status",
12
+ "claimType": "public-data-field",
13
+ "fieldOrBehavior": "registrationStatus",
14
+ "value": "OPEN",
15
+ "createdAt": "2026-04-01T00:00:00.000Z",
16
+ "updatedAt": "2026-04-01T00:00:00.000Z",
17
+ "impactLevel": "high",
18
+ "verificationPolicyId": "policy.public-data-field.short-lived"
19
+ }
20
+ ],
21
+ "evidence": [
22
+ {
23
+ "id": "evidence.public.source-excerpt",
24
+ "claimId": "claim.public.field",
25
+ "evidenceType": "source_excerpt",
26
+ "method": "observation",
27
+ "sourceRef": "https://example.org/register",
28
+ "excerptOrSummary": "Registration is open for summer sessions.",
29
+ "observedAt": "2026-04-01T00:00:00.000Z",
30
+ "collectedBy": "crawler"
31
+ },
32
+ {
33
+ "id": "evidence.public.human-attestation",
34
+ "claimId": "claim.public.field",
35
+ "evidenceType": "human_attestation",
36
+ "method": "attestation",
37
+ "sourceRef": "record-steward review",
38
+ "excerptOrSummary": "Admin approved registration status from source excerpt.",
39
+ "observedAt": "2026-04-01T00:10:00.000Z",
40
+ "collectedBy": "record-steward"
41
+ }
42
+ ],
43
+ "policies": [
44
+ {
45
+ "id": "policy.public-data-field.short-lived",
46
+ "claimType": "public-data-field",
47
+ "requiredEvidence": ["source_excerpt", "human_attestation"],
48
+ "requiredMethods": ["observation", "attestation"],
49
+ "requiresCorroboration": true,
50
+ "acceptanceCriteria": ["field-level review or crawl approval"],
51
+ "reviewAuthority": "operator",
52
+ "validityRule": { "kind": "duration", "durationDays": 14 },
53
+ "stalenessTriggers": ["validity window expires"],
54
+ "conflictRules": [],
55
+ "impactLevel": "high"
56
+ }
57
+ ],
58
+ "events": [
59
+ {
60
+ "id": "event.public.verified",
61
+ "claimId": "claim.public.field",
62
+ "status": "verified",
63
+ "actor": "record-steward",
64
+ "method": "field-attestation",
65
+ "evidenceIds": ["evidence.public.source-excerpt", "evidence.public.human-attestation"],
66
+ "createdAt": "2026-04-01T00:10:00.000Z",
67
+ "verifiedAt": "2026-04-01T00:10:00.000Z"
68
+ }
69
+ ]
70
+ },
71
+ "expect": {
72
+ "statusByClaimId": {
73
+ "claim.public.field": "stale"
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "now": "2026-06-10T00:00:00.000Z",
3
+ "input": {
4
+ "schemaVersion": 3,
5
+ "source": "spec-conformance:verified-commit",
6
+ "claims": [
7
+ {
8
+ "id": "claim.api.rate-limit",
9
+ "subjectType": "api",
10
+ "subjectId": "public-api",
11
+ "surface": "api.guarantees",
12
+ "claimType": "software-evidence",
13
+ "fieldOrBehavior": "rate limit is enforced",
14
+ "value": "100 requests/minute",
15
+ "createdAt": "2026-04-25T00:00:00.000Z",
16
+ "updatedAt": "2026-04-25T00:05:00.000Z",
17
+ "impactLevel": "high",
18
+ "currentIntegrityRef": "commit:abc123",
19
+ "verificationPolicyId": "policy.software-evidence.commit"
20
+ }
21
+ ],
22
+ "evidence": [
23
+ {
24
+ "id": "evidence.api.rate-limit.test",
25
+ "claimId": "claim.api.rate-limit",
26
+ "evidenceType": "test_output",
27
+ "method": "validation",
28
+ "sourceRef": "ci:1847",
29
+ "excerptOrSummary": "Rate-limit tests passed.",
30
+ "observedAt": "2026-04-25T00:05:00.000Z",
31
+ "collectedBy": "ci",
32
+ "integrityRef": "commit:abc123"
33
+ }
34
+ ],
35
+ "policies": [
36
+ {
37
+ "id": "policy.software-evidence.commit",
38
+ "claimType": "software-evidence",
39
+ "requiredEvidence": ["test_output"],
40
+ "requiredMethods": ["validation"],
41
+ "requiresCorroboration": false,
42
+ "acceptanceCriteria": ["evidence check passes for the affected commit"],
43
+ "reviewAuthority": "repo policy",
44
+ "validityRule": { "kind": "commit" },
45
+ "stalenessTriggers": ["new commit touches the same surface"],
46
+ "conflictRules": [],
47
+ "impactLevel": "high"
48
+ }
49
+ ],
50
+ "events": [
51
+ {
52
+ "id": "event.api.rate-limit.verified",
53
+ "claimId": "claim.api.rate-limit",
54
+ "status": "verified",
55
+ "actor": "ci",
56
+ "method": "npm test",
57
+ "evidenceIds": ["evidence.api.rate-limit.test"],
58
+ "createdAt": "2026-04-25T00:05:00.000Z",
59
+ "verifiedAt": "2026-04-25T00:05:00.000Z"
60
+ }
61
+ ]
62
+ },
63
+ "expect": {
64
+ "statusByClaimId": {
65
+ "claim.api.rate-limit": "verified"
66
+ }
67
+ }
68
+ }
package/index.mjs ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * hachure — canonical npm distribution of the Hachure trust format spec.
3
+ *
4
+ * Exports:
5
+ * STATUS_FUNCTION_VERSION — spec-side declaration of the current status
6
+ * derivation algorithm version. Reference
7
+ * implementations must export a matching value.
8
+ * schemas — Map<recordName, parsedSchemaObject> for every
9
+ * normative schema shipped with this package.
10
+ * testVectors — Array<{name, vector}> of all conformance test
11
+ * vectors. Each vector has `input`, `expect`, and
12
+ * `now` fields; run them against your implementation
13
+ * to claim conformance.
14
+ */
15
+
16
+ import { readFileSync, readdirSync } from 'node:fs';
17
+ import { fileURLToPath } from 'node:url';
18
+ import { join, dirname, basename } from 'node:path';
19
+
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Spec-side declaration of the status function version.
24
+ // Any implementation claiming conformance at this version must produce the
25
+ // same status outputs as the test vectors for all cases in conformance/.
26
+ // ---------------------------------------------------------------------------
27
+ export const STATUS_FUNCTION_VERSION = '1';
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Schemas — Map of record name (filename without .schema.json) → parsed JSON.
31
+ // ---------------------------------------------------------------------------
32
+ function loadSchemas() {
33
+ const schemasDir = join(__dirname, 'schemas');
34
+ const map = new Map();
35
+ for (const file of readdirSync(schemasDir).sort()) {
36
+ if (!file.endsWith('.schema.json')) continue;
37
+ const name = file.replace(/\.schema\.json$/, '');
38
+ map.set(name, JSON.parse(readFileSync(join(schemasDir, file), 'utf8')));
39
+ }
40
+ return map;
41
+ }
42
+
43
+ export const schemas = loadSchemas();
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Test vectors — Array of { name, vector } loaded from conformance/*.json.
47
+ // Each vector: { now, input, expect: { statusByClaimId } }
48
+ // ---------------------------------------------------------------------------
49
+ function loadTestVectors() {
50
+ const conformanceDir = join(__dirname, 'conformance');
51
+ const vectors = [];
52
+ for (const file of readdirSync(conformanceDir).sort()) {
53
+ if (!file.endsWith('.json')) continue;
54
+ const name = basename(file, '.json');
55
+ const vector = JSON.parse(readFileSync(join(conformanceDir, file), 'utf8'));
56
+ vectors.push({ name, vector });
57
+ }
58
+ return vectors;
59
+ }
60
+
61
+ export const testVectors = loadTestVectors();
@@ -0,0 +1,133 @@
1
+ # in-toto Interop: TrustBundle as an in-toto Statement v1
2
+
3
+ **Module:** `@kontourai/surface` — `src/interop/in-toto.ts`
4
+ **Public exports:** `toInTotoStatement`, `toDsseEnvelope`, `buildPaeBytes`, `parseDssePayload`
5
+
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ This module lets a producer publish a TrustBundle as a signed software-supply-chain
11
+ attestation by wrapping it in the in-toto Statement v1 format and optionally enveloping
12
+ it in DSSE (Dead Simple Signing Envelope). It adds no new crypto dependency: all
13
+ cryptographic operations are injected via a caller-supplied `Signer`.
14
+
15
+ ---
16
+
17
+ ## Statement shape
18
+
19
+ `toInTotoStatement(bundle, { subjects })` produces an in-toto Statement v1:
20
+
21
+ ```jsonc
22
+ {
23
+ "_type": "https://in-toto.io/Statement/v1",
24
+ "subject": [
25
+ {
26
+ "name": "<producer-chosen artifact reference>",
27
+ "digest": { "sha256": "<hex>" }
28
+ }
29
+ ],
30
+ "predicateType": "https://hachure.org/v1/bundle",
31
+ "predicate": { /* the TrustBundle verbatim */ }
32
+ }
33
+ ```
34
+
35
+ | Field | Value | Note |
36
+ |---|---|---|
37
+ | `_type` | `https://in-toto.io/Statement/v1` | Fixed; identifies the in-toto spec version. |
38
+ | `subject` | caller-supplied `[{ name, digest }]` | At least one required. The producer knows which artifact digests are relevant; Surface does not infer them. |
39
+ | `predicateType` | `https://hachure.org/v1/bundle` | Stable URI identifying Kontour trust bundles. |
40
+ | `predicate` | the TrustBundle | The full bundle becomes the predicate; no fields are stripped or remapped. |
41
+
42
+ The `predicateType` URI is stable for the lifetime of `hachure.org/v1`. If the
43
+ TrustBundle schema is broken (a new `apiVersion`), a new predicate type URI will be
44
+ registered rather than reusing this one.
45
+
46
+ ---
47
+
48
+ ## DSSE envelope and PAE
49
+
50
+ `toDsseEnvelope(statement, signer)` returns a DSSE envelope:
51
+
52
+ ```jsonc
53
+ {
54
+ "payloadType": "application/vnd.in-toto+json",
55
+ "payload": "<base64-standard>",
56
+ "signatures": [
57
+ { "keyid": "<from signer>", "sig": "<base64 signature over PAE>" }
58
+ ]
59
+ }
60
+ ```
61
+
62
+ The payload is the base64-standard-encoded UTF-8 JSON serialisation of the Statement.
63
+
64
+ **Pre-Authentication Encoding (PAE)** — the bytes handed to `signer.sign()`:
65
+
66
+ ```
67
+ PAE(type, body) = "DSSEv1" SP DEC(byte_len(type)) SP type SP DEC(byte_len(body)) SP body
68
+ ```
69
+
70
+ `buildPaeBytes(payloadType, bodyString): Uint8Array` is exported so callers can
71
+ verify the pre-image independently or pass it directly to a WebCrypto
72
+ `SubtleCrypto.sign()` call.
73
+
74
+ ### Injecting a signer
75
+
76
+ ```ts
77
+ import { toInTotoStatement, toDsseEnvelope } from "@kontourai/surface/interop/in-toto";
78
+
79
+ const signer = {
80
+ keyid: "my-key-id",
81
+ async sign(paeBytes: Uint8Array): Promise<string> {
82
+ // e.g. WebCrypto:
83
+ const raw = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, paeBytes);
84
+ return Buffer.from(raw).toString("base64");
85
+ },
86
+ };
87
+
88
+ const statement = toInTotoStatement(bundle, { subjects });
89
+ const envelope = await toDsseEnvelope(statement, signer);
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Sigstore / Rekor anchoring guidance
95
+
96
+ The DSSE envelope produced by this module is structurally compatible with
97
+ [Sigstore](https://sigstore.dev) tooling:
98
+
99
+ 1. **Sign with Sigstore Cosign** — Cosign's `attest` command accepts DSSE envelopes.
100
+ Pass `--type custom` and `--predicate <bundle.json>` together with the
101
+ `predicateType` URI to have Cosign wrap the bundle and upload the signed envelope
102
+ to the [Rekor](https://docs.sigstore.dev/logging/overview/) transparency log.
103
+
104
+ 2. **Upload to Rekor directly** — Use the Rekor `hashedrekord` or `dsse` entry type
105
+ with the DSSE envelope JSON. Once uploaded, Rekor returns a `LogEntry` UUID that
106
+ can be stored in a `TrustBundle.proof` field (Kontour Resource Shape) as an
107
+ `IntegrityAnchor` of kind `transparency_log`.
108
+
109
+ 3. **Verify** — Retrieve the envelope from Rekor, decode `payload` from base64,
110
+ reconstruct PAE via `buildPaeBytes`, verify the signature against the signer's
111
+ public key, and check the `predicate` against the live `TrustBundle`.
112
+
113
+ ---
114
+
115
+ ## What Kontour adds on top of a frozen attestation
116
+
117
+ An in-toto Statement is a **frozen attestation**: it captures a point-in-time
118
+ assertion and anchors it cryptographically. That is exactly what the DSSE envelope
119
+ provides.
120
+
121
+ A Kontour `TrustBundle` adds **living status** on top:
122
+
123
+ | Frozen attestation (in-toto envelope) | Living bundle (Surface) |
124
+ |---|---|
125
+ | Status is sealed at signing time. | Status is recomputed from events at query time: `f(claim, events, policy, now)`. |
126
+ | Tamper-evident; content cannot change. | Append-only; new events and evidence accumulate. |
127
+ | Verifier trusts the signer's identity. | Verifier trusts the derivation algorithm (`STATUS_FUNCTION_VERSION`). |
128
+ | Useful for supply-chain audits and legal holds. | Useful for operational dashboards, gates, and consumer inquiries. |
129
+
130
+ The two are complementary: embed the bundle in an in-toto envelope to
131
+ *anchor what was known at release time*; continue querying the live bundle to track
132
+ *what is true now*. An `InquiryRecord` (ADR 0003 §6) records the live status at
133
+ inquiry time, linking the frozen and living views.