@dsh-enhanced/plugin-control-plane 0.1.7 → 0.1.14

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 (67) hide show
  1. package/README.md +153 -32
  2. package/bin/dsh-local-release-adapter.js +1381 -0
  3. package/cordis.patch.yml +1 -0
  4. package/lib/approval.d.ts +13 -0
  5. package/lib/approval.d.ts.map +1 -0
  6. package/lib/approval.js +79 -0
  7. package/lib/approval.js.map +1 -0
  8. package/lib/attestation.d.ts +14 -0
  9. package/lib/attestation.d.ts.map +1 -0
  10. package/lib/attestation.js +222 -0
  11. package/lib/attestation.js.map +1 -0
  12. package/lib/catalog-interpreter.d.ts +12 -0
  13. package/lib/catalog-interpreter.d.ts.map +1 -0
  14. package/lib/catalog-interpreter.js +100 -0
  15. package/lib/catalog-interpreter.js.map +1 -0
  16. package/lib/catalog.d.ts +95 -10
  17. package/lib/catalog.d.ts.map +1 -1
  18. package/lib/catalog.js +1031 -18
  19. package/lib/catalog.js.map +1 -1
  20. package/lib/cli.d.ts +9 -0
  21. package/lib/cli.d.ts.map +1 -1
  22. package/lib/cli.js +1160 -162
  23. package/lib/cli.js.map +1 -1
  24. package/lib/host-attestor.d.ts +13 -0
  25. package/lib/host-attestor.d.ts.map +1 -0
  26. package/lib/host-attestor.js +139 -0
  27. package/lib/host-attestor.js.map +1 -0
  28. package/lib/index.d.ts +9 -0
  29. package/lib/index.d.ts.map +1 -1
  30. package/lib/index.js +9 -0
  31. package/lib/index.js.map +1 -1
  32. package/lib/lockfile.d.ts +7 -0
  33. package/lib/lockfile.d.ts.map +1 -0
  34. package/lib/lockfile.js +271 -0
  35. package/lib/lockfile.js.map +1 -0
  36. package/lib/release.d.ts +51 -0
  37. package/lib/release.d.ts.map +1 -0
  38. package/lib/release.js +1188 -0
  39. package/lib/release.js.map +1 -0
  40. package/lib/service.d.ts +9 -11
  41. package/lib/service.d.ts.map +1 -1
  42. package/lib/service.js +57 -29
  43. package/lib/service.js.map +1 -1
  44. package/lib/sqlite.d.ts +9 -0
  45. package/lib/sqlite.d.ts.map +1 -0
  46. package/lib/sqlite.js +709 -0
  47. package/lib/sqlite.js.map +1 -0
  48. package/lib/store.d.ts +258 -0
  49. package/lib/store.d.ts.map +1 -0
  50. package/lib/store.js +1848 -0
  51. package/lib/store.js.map +1 -0
  52. package/lib/tools.d.ts.map +1 -1
  53. package/lib/tools.js +23 -3
  54. package/lib/tools.js.map +1 -1
  55. package/lib/trust.d.ts +79 -0
  56. package/lib/trust.d.ts.map +1 -0
  57. package/lib/trust.js +477 -0
  58. package/lib/trust.js.map +1 -0
  59. package/lib/types.d.ts +740 -0
  60. package/lib/types.d.ts.map +1 -0
  61. package/lib/types.js +2 -0
  62. package/lib/types.js.map +1 -0
  63. package/lib/version.d.ts +1 -1
  64. package/lib/version.d.ts.map +1 -1
  65. package/lib/version.js +1 -1
  66. package/lib/version.js.map +1 -1
  67. package/package.json +2 -2
package/cordis.patch.yml CHANGED
@@ -4,4 +4,5 @@
4
4
  config:
5
5
  catalogPath: !!js dshHomePath('plugin-control/catalog.json')
6
6
  statePath: !!js dshHomePath('plugin-control/plans')
7
+ trustPath: !!js dshHomePath('plugin-control/trust.json')
7
8
  proposalTtlMs: 900000
@@ -0,0 +1,13 @@
1
+ import type { ApprovalAuthority, ApprovalReceipt, PluginActivationPlan, PluginSourcePlan, VerifiedApprovalReceipt } from './types.js';
2
+ export declare function parseApprovalReceipt(value: unknown): ApprovalReceipt;
3
+ export declare class Ed25519ApprovalAuthority implements ApprovalAuthority {
4
+ readonly publicKey: string | Buffer;
5
+ readonly expectedAuthority: string;
6
+ readonly expectedKeyId: string;
7
+ readonly now: () => number;
8
+ constructor(publicKey: string | Buffer, expectedAuthority: string, expectedKeyId: string, now?: () => number);
9
+ verify(receiptInput: ApprovalReceipt, plan: Pick<PluginActivationPlan | PluginSourcePlan, 'id' | 'digest' | 'createdAt' | 'expiresAt'>): Promise<VerifiedApprovalReceipt>;
10
+ }
11
+ export declare function loadPrivateApprovalInput(path: string, maximumBytes: number): Promise<string>;
12
+ export declare function approvalSigningPayload(receipt: Omit<ApprovalReceipt, 'signature'>): string;
13
+ //# sourceMappingURL=approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAqBrI,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAepE;AAED,qBAAa,wBAAyB,YAAW,iBAAiB;IAE9D,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IACnC,QAAQ,CAAC,iBAAiB,EAAE,MAAM;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM;gBAHjB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,MAAiB;IAGjC,MAAM,CAAC,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,CAAC,oBAAoB,GAAG,gBAAgB,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAiBhL;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlG;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,MAAM,CAE1F"}
@@ -0,0 +1,79 @@
1
+ import { createHash, createPublicKey, verify } from 'node:crypto';
2
+ import { lstat, readFile } from 'node:fs/promises';
3
+ import { ControlPlaneStoreError } from './store.js';
4
+ const ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/u;
5
+ const DIGEST = /^[a-f0-9]{64}$/u;
6
+ function canonicalReceipt(receipt) {
7
+ return JSON.stringify({
8
+ schemaVersion: receipt.schemaVersion,
9
+ approvalId: receipt.approvalId,
10
+ authority: receipt.authority,
11
+ keyId: receipt.keyId,
12
+ planId: receipt.planId,
13
+ planDigest: receipt.planDigest,
14
+ decision: receipt.decision,
15
+ principal: receipt.principal.normalize('NFC').trim(),
16
+ decidedAt: receipt.decidedAt,
17
+ expiresAt: receipt.expiresAt,
18
+ });
19
+ }
20
+ export function parseApprovalReceipt(value) {
21
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
22
+ throw new ControlPlaneStoreError('invalid-input', 'approval receipt must be an object');
23
+ const item = value;
24
+ if (item.schemaVersion !== 1 || typeof item.approvalId !== 'string' || typeof item.authority !== 'string'
25
+ || typeof item.keyId !== 'string' || typeof item.planId !== 'string' || typeof item.planDigest !== 'string'
26
+ || (item.decision !== 'approved' && item.decision !== 'rejected') || typeof item.principal !== 'string'
27
+ || !Number.isSafeInteger(item.decidedAt) || !Number.isSafeInteger(item.expiresAt) || typeof item.signature !== 'string') {
28
+ throw new ControlPlaneStoreError('invalid-input', 'approval receipt fields are invalid');
29
+ }
30
+ if (![item.approvalId, item.authority, item.keyId, item.planId].every(value => ID.test(value))
31
+ || !DIGEST.test(item.planDigest) || item.principal.trim() === '' || item.principal.length > 256
32
+ || item.expiresAt <= item.decidedAt || !/^[A-Za-z0-9+/]+={0,2}$/u.test(item.signature)) {
33
+ throw new ControlPlaneStoreError('invalid-input', 'approval receipt values are invalid');
34
+ }
35
+ return item;
36
+ }
37
+ export class Ed25519ApprovalAuthority {
38
+ publicKey;
39
+ expectedAuthority;
40
+ expectedKeyId;
41
+ now;
42
+ constructor(publicKey, expectedAuthority, expectedKeyId, now = Date.now) {
43
+ this.publicKey = publicKey;
44
+ this.expectedAuthority = expectedAuthority;
45
+ this.expectedKeyId = expectedKeyId;
46
+ this.now = now;
47
+ }
48
+ async verify(receiptInput, plan) {
49
+ const receipt = parseApprovalReceipt(receiptInput);
50
+ if (receipt.authority !== this.expectedAuthority || receipt.keyId !== this.expectedKeyId
51
+ || receipt.planId !== plan.id || receipt.planDigest !== plan.digest) {
52
+ throw new ControlPlaneStoreError('conflict', 'approval receipt is not bound to this exact authority, key, plan, and digest');
53
+ }
54
+ if (receipt.decidedAt < plan.createdAt || receipt.decidedAt > plan.expiresAt || this.now() > receipt.expiresAt) {
55
+ throw new ControlPlaneStoreError('expired', 'approval receipt is outside its valid plan-bound interval');
56
+ }
57
+ const body = Buffer.from(canonicalReceipt(receipt));
58
+ const signature = Buffer.from(receipt.signature, 'base64');
59
+ if (!verify(null, body, createPublicKey(this.publicKey), signature)) {
60
+ throw new ControlPlaneStoreError('invalid-input', 'approval receipt signature is invalid');
61
+ }
62
+ const { signature: _signature, ...fields } = receipt;
63
+ return { ...fields, principal: fields.principal.normalize('NFC').trim(), signatureDigest: createHash('sha256').update(signature).digest('hex') };
64
+ }
65
+ }
66
+ export async function loadPrivateApprovalInput(path, maximumBytes) {
67
+ const metadata = await lstat(path);
68
+ if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.nlink !== 1) {
69
+ throw new ControlPlaneStoreError('invalid-input', 'approval input must be a regular non-symlink file');
70
+ }
71
+ const value = await readFile(path, 'utf8');
72
+ if (Buffer.byteLength(value) > maximumBytes)
73
+ throw new ControlPlaneStoreError('invalid-input', 'approval input is too large');
74
+ return value;
75
+ }
76
+ export function approvalSigningPayload(receipt) {
77
+ return canonicalReceipt({ ...receipt, signature: '' });
78
+ }
79
+ //# sourceMappingURL=approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { HostAttestationAuthority, HostAttestationEvidence, HostAttestationReceipt, HostAttestationRequest, PluginActivationPlan, VerifiedHostAttestation } from './types.js';
2
+ export declare function hostAttestationRequestDigest(request: HostAttestationRequest): string;
3
+ export declare function hostAttestationEvidenceDigest(evidence: HostAttestationEvidence): string;
4
+ export declare function parseHostAttestationReceipt(value: unknown): HostAttestationReceipt;
5
+ export declare class Ed25519HostAttestationAuthority implements HostAttestationAuthority {
6
+ readonly publicKey: string | Buffer;
7
+ readonly expectedAuthority: string;
8
+ readonly expectedKeyId: string;
9
+ readonly now: () => number;
10
+ constructor(publicKey: string | Buffer, expectedAuthority: string, expectedKeyId: string, now?: () => number);
11
+ verify(receiptInput: HostAttestationReceipt, plan: PluginActivationPlan, request: HostAttestationRequest): Promise<VerifiedHostAttestation>;
12
+ }
13
+ export declare function hostAttestationSigningPayload(receipt: Omit<HostAttestationReceipt, 'signature'>): string;
14
+ //# sourceMappingURL=attestation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,YAAY,CAAA;AAwGnB,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAA2B;AAChH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,uBAAuB,GAAG,MAAM,CAA4B;AAEpH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAoBlF;AAkCD,qBAAa,+BAAgC,YAAW,wBAAwB;IAE5E,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IACnC,QAAQ,CAAC,iBAAiB,EAAE,MAAM;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM;gBAHjB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,MAAiB;IAGjC,MAAM,CAAC,YAAY,EAAE,sBAAsB,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAyBlJ;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,WAAW,CAAC,GAAG,MAAM,CAExG"}
@@ -0,0 +1,222 @@
1
+ import { createHash, createPublicKey, verify } from 'node:crypto';
2
+ import { ControlPlaneStoreError } from './store.js';
3
+ const ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/u;
4
+ const DIGEST = /^[a-f0-9]{64}$/u;
5
+ const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u;
6
+ const phases = new Set(['reload', 'readiness', 'effect-blocked-replay', 'shadow', 'canary', 'soak', 'health']);
7
+ function canonical(value) {
8
+ if (Array.isArray(value))
9
+ return `[${value.map(canonical).join(',')}]`;
10
+ if (typeof value === 'object' && value !== null) {
11
+ return `{${Object.entries(value).filter(([, item]) => item !== undefined)
12
+ .sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(',')}}`;
13
+ }
14
+ return JSON.stringify(value);
15
+ }
16
+ function digest(value) { return createHash('sha256').update(canonical(value)).digest('hex'); }
17
+ function record(value, label) {
18
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
19
+ throw new ControlPlaneStoreError('invalid-input', `${label} must be an object`);
20
+ return value;
21
+ }
22
+ function exact(value, fields, label) {
23
+ if (Object.keys(value).sort().join('\0') !== [...fields].sort().join('\0'))
24
+ throw new ControlPlaneStoreError('invalid-input', `${label} has unknown or missing fields`);
25
+ }
26
+ function integer(value, label, minimum = 0) {
27
+ if (!Number.isSafeInteger(value) || Number(value) < minimum)
28
+ throw new ControlPlaneStoreError('invalid-input', `${label} must be a bounded integer`);
29
+ return Number(value);
30
+ }
31
+ function text(value, label, pattern = ID) {
32
+ if (typeof value !== 'string' || !pattern.test(value))
33
+ throw new ControlPlaneStoreError('invalid-input', `${label} is invalid`);
34
+ return value;
35
+ }
36
+ function parseEvidence(value) {
37
+ const item = record(value, 'host attestation evidence');
38
+ const kind = item.kind;
39
+ if (kind === 'reload') {
40
+ exact(item, ['kind', 'reloaded', 'previousHostGeneration', 'currentHostGeneration', 'probeDigest'], 'reload evidence');
41
+ if (typeof item.reloaded !== 'boolean')
42
+ throw new ControlPlaneStoreError('invalid-input', 'reload evidence reloaded must be boolean');
43
+ return { kind, reloaded: item.reloaded, previousHostGeneration: integer(item.previousHostGeneration, 'previousHostGeneration'),
44
+ currentHostGeneration: integer(item.currentHostGeneration, 'currentHostGeneration', 1), probeDigest: text(item.probeDigest, 'probeDigest', DIGEST) };
45
+ }
46
+ if (kind === 'readiness') {
47
+ exact(item, ['kind', 'checks', 'failures', 'probeDigest'], 'readiness evidence');
48
+ const checks = integer(item.checks, 'checks');
49
+ const failures = integer(item.failures, 'failures');
50
+ if (failures > checks)
51
+ throw new ControlPlaneStoreError('invalid-input', 'readiness failures exceed checks');
52
+ return { kind, checks, failures, probeDigest: text(item.probeDigest, 'probeDigest', DIGEST) };
53
+ }
54
+ if (kind === 'effect-blocked-replay') {
55
+ exact(item, ['kind', 'deliveryAttempts', 'deliveryBlocked', 'toolExecutionAttempts', 'toolExecutionBlocked', 'externalEffects', 'replayDigest'], 'effect-blocked replay evidence');
56
+ const deliveryAttempts = integer(item.deliveryAttempts, 'deliveryAttempts');
57
+ const deliveryBlocked = integer(item.deliveryBlocked, 'deliveryBlocked');
58
+ const toolExecutionAttempts = integer(item.toolExecutionAttempts, 'toolExecutionAttempts');
59
+ const toolExecutionBlocked = integer(item.toolExecutionBlocked, 'toolExecutionBlocked');
60
+ if (deliveryBlocked > deliveryAttempts || toolExecutionBlocked > toolExecutionAttempts)
61
+ throw new ControlPlaneStoreError('invalid-input', 'blocked effects exceed attempted effects');
62
+ return { kind, deliveryAttempts, deliveryBlocked,
63
+ toolExecutionAttempts, toolExecutionBlocked,
64
+ externalEffects: integer(item.externalEffects, 'externalEffects'), replayDigest: text(item.replayDigest, 'replayDigest', DIGEST) };
65
+ }
66
+ if (kind === 'shadow') {
67
+ exact(item, ['kind', 'samples', 'mismatches', 'externalEffects', 'traceDigest'], 'shadow evidence');
68
+ const samples = integer(item.samples, 'samples');
69
+ const mismatches = integer(item.mismatches, 'mismatches');
70
+ if (mismatches > samples)
71
+ throw new ControlPlaneStoreError('invalid-input', 'shadow mismatches exceed samples');
72
+ return { kind, samples, mismatches,
73
+ externalEffects: integer(item.externalEffects, 'externalEffects'), traceDigest: text(item.traceDigest, 'traceDigest', DIGEST) };
74
+ }
75
+ if (kind === 'canary') {
76
+ exact(item, ['kind', 'exposureId', 'exposures', 'samples', 'failures', 'traceDigest'], 'canary evidence');
77
+ const samples = integer(item.samples, 'samples');
78
+ const failures = integer(item.failures, 'failures');
79
+ if (failures > samples)
80
+ throw new ControlPlaneStoreError('invalid-input', 'canary failures exceed samples');
81
+ return { kind, exposureId: text(item.exposureId, 'exposureId'), exposures: integer(item.exposures, 'exposures'),
82
+ samples, failures, traceDigest: text(item.traceDigest, 'traceDigest', DIGEST) };
83
+ }
84
+ if (kind === 'soak') {
85
+ exact(item, ['kind', 'windowStartedAt', 'windowEndedAt', 'samples', 'failures', 'traceDigest'], 'soak evidence');
86
+ const windowStartedAt = integer(item.windowStartedAt, 'windowStartedAt');
87
+ const windowEndedAt = integer(item.windowEndedAt, 'windowEndedAt');
88
+ if (windowEndedAt < windowStartedAt)
89
+ throw new ControlPlaneStoreError('invalid-input', 'soak evidence window is reversed');
90
+ const samples = integer(item.samples, 'samples');
91
+ const failures = integer(item.failures, 'failures');
92
+ if (failures > samples)
93
+ throw new ControlPlaneStoreError('invalid-input', 'soak failures exceed samples');
94
+ return { kind, windowStartedAt, windowEndedAt, samples,
95
+ failures, traceDigest: text(item.traceDigest, 'traceDigest', DIGEST) };
96
+ }
97
+ if (kind === 'health') {
98
+ exact(item, ['kind', 'checks', 'failures', 'probeDigest'], 'health evidence');
99
+ const checks = integer(item.checks, 'checks');
100
+ const failures = integer(item.failures, 'failures');
101
+ if (failures > checks)
102
+ throw new ControlPlaneStoreError('invalid-input', 'health failures exceed checks');
103
+ return { kind, checks, failures, probeDigest: text(item.probeDigest, 'probeDigest', DIGEST) };
104
+ }
105
+ throw new ControlPlaneStoreError('invalid-input', 'host attestation evidence kind is invalid');
106
+ }
107
+ function canonicalReceipt(receipt) {
108
+ return canonical({
109
+ schemaVersion: receipt.schemaVersion, receiptId: receipt.receiptId, authority: receipt.authority,
110
+ keyId: receipt.keyId, installationId: receipt.installationId, planId: receipt.planId,
111
+ planDigest: receipt.planDigest, activationId: receipt.activationId, fence: receipt.fence,
112
+ operationId: receipt.operationId, requestDigest: receipt.requestDigest, phase: receipt.phase,
113
+ outcome: receipt.outcome, hostGeneration: receipt.hostGeneration, evidence: receipt.evidence,
114
+ evidenceDigest: receipt.evidenceDigest, observedAt: receipt.observedAt, expiresAt: receipt.expiresAt,
115
+ });
116
+ }
117
+ export function hostAttestationRequestDigest(request) { return digest(request); }
118
+ export function hostAttestationEvidenceDigest(evidence) { return digest(evidence); }
119
+ export function parseHostAttestationReceipt(value) {
120
+ const item = record(value, 'host attestation');
121
+ exact(item, ['schemaVersion', 'receiptId', 'authority', 'keyId', 'installationId', 'planId', 'planDigest', 'activationId',
122
+ 'fence', 'operationId', 'requestDigest', 'phase', 'outcome', 'hostGeneration', 'evidence', 'evidenceDigest', 'observedAt', 'expiresAt', 'signature'], 'host attestation');
123
+ if (item.schemaVersion !== 2 || typeof item.phase !== 'string' || !phases.has(item.phase)
124
+ || (item.outcome !== 'passed' && item.outcome !== 'failed') || typeof item.signature !== 'string'
125
+ || !/^[A-Za-z0-9+/]+={0,2}$/u.test(item.signature))
126
+ throw new ControlPlaneStoreError('invalid-input', 'host attestation fields are invalid');
127
+ const receipt = {
128
+ schemaVersion: 2, receiptId: text(item.receiptId, 'receiptId'), authority: text(item.authority, 'authority'),
129
+ keyId: text(item.keyId, 'keyId'), installationId: text(item.installationId, 'installationId', UUID),
130
+ planId: text(item.planId, 'planId'), planDigest: text(item.planDigest, 'planDigest', DIGEST), activationId: text(item.activationId, 'activationId'),
131
+ fence: integer(item.fence, 'fence', 1), operationId: text(item.operationId, 'operationId'), requestDigest: text(item.requestDigest, 'requestDigest', DIGEST),
132
+ phase: item.phase, outcome: item.outcome, hostGeneration: integer(item.hostGeneration, 'hostGeneration', 1),
133
+ evidence: parseEvidence(item.evidence), evidenceDigest: text(item.evidenceDigest, 'evidenceDigest', DIGEST),
134
+ observedAt: integer(item.observedAt, 'observedAt'), expiresAt: integer(item.expiresAt, 'expiresAt'), signature: item.signature,
135
+ };
136
+ if (receipt.expiresAt <= receipt.observedAt || hostAttestationEvidenceDigest(receipt.evidence) !== receipt.evidenceDigest) {
137
+ throw new ControlPlaneStoreError('invalid-input', 'host attestation evidence digest or validity interval is invalid');
138
+ }
139
+ return receipt;
140
+ }
141
+ function assertPassedEvidence(receipt, request) {
142
+ const evidence = receipt.evidence;
143
+ const requirements = request.requirements;
144
+ if (evidence.kind !== request.phase || requirements.kind !== request.phase)
145
+ throw new ControlPlaneStoreError('conflict', 'host evidence is not for the requested phase');
146
+ if (receipt.outcome === 'failed')
147
+ return;
148
+ let passed = false;
149
+ if (evidence.kind === 'reload' && requirements.kind === 'reload') {
150
+ passed = evidence.reloaded && evidence.currentHostGeneration === receipt.hostGeneration
151
+ && evidence.previousHostGeneration === requirements.previousHostGeneration
152
+ && evidence.currentHostGeneration > requirements.previousHostGeneration;
153
+ }
154
+ else if (evidence.kind === 'readiness' && requirements.kind === 'readiness') {
155
+ passed = evidence.checks >= requirements.minimumChecks && evidence.failures === 0;
156
+ }
157
+ else if (evidence.kind === 'effect-blocked-replay' && requirements.kind === 'effect-blocked-replay') {
158
+ passed = evidence.deliveryAttempts >= requirements.minimumDeliveryAttempts && evidence.deliveryBlocked === evidence.deliveryAttempts
159
+ && evidence.toolExecutionAttempts >= requirements.minimumToolExecutionAttempts && evidence.toolExecutionBlocked === evidence.toolExecutionAttempts
160
+ && evidence.externalEffects <= requirements.maximumExternalEffects;
161
+ }
162
+ else if (evidence.kind === 'shadow' && requirements.kind === 'shadow') {
163
+ passed = evidence.samples >= requirements.minimumSamples && evidence.mismatches <= requirements.maximumMismatches
164
+ && evidence.externalEffects <= requirements.maximumExternalEffects;
165
+ }
166
+ else if (evidence.kind === 'canary' && requirements.kind === 'canary') {
167
+ passed = evidence.exposures === requirements.maximumExposures && evidence.samples >= requirements.minimumSamples
168
+ && evidence.failures <= requirements.maximumFailures;
169
+ }
170
+ else if (evidence.kind === 'soak' && requirements.kind === 'soak') {
171
+ const failureRate = evidence.samples === 0 ? Number.POSITIVE_INFINITY : evidence.failures / evidence.samples;
172
+ passed = evidence.windowEndedAt - evidence.windowStartedAt >= requirements.minimumWindowMs
173
+ && evidence.samples >= requirements.minimumSamples && failureRate <= requirements.maximumFailureRate
174
+ && evidence.windowStartedAt >= request.requestedAt && evidence.windowEndedAt <= receipt.observedAt;
175
+ }
176
+ else if (evidence.kind === 'health' && requirements.kind === 'health') {
177
+ passed = evidence.checks >= requirements.minimumChecks && evidence.failures <= requirements.maximumFailures;
178
+ }
179
+ if (!passed)
180
+ throw new ControlPlaneStoreError('invalid-input', `passed ${request.phase} receipt does not satisfy its signed evidence contract`);
181
+ }
182
+ export class Ed25519HostAttestationAuthority {
183
+ publicKey;
184
+ expectedAuthority;
185
+ expectedKeyId;
186
+ now;
187
+ constructor(publicKey, expectedAuthority, expectedKeyId, now = Date.now) {
188
+ this.publicKey = publicKey;
189
+ this.expectedAuthority = expectedAuthority;
190
+ this.expectedKeyId = expectedKeyId;
191
+ this.now = now;
192
+ }
193
+ async verify(receiptInput, plan, request) {
194
+ const receipt = parseHostAttestationReceipt(receiptInput);
195
+ const configuredIssuerMismatch = request.issuer.mode === 'configured-executable'
196
+ && (receipt.authority !== request.issuer.authority || receipt.keyId !== request.issuer.keyId);
197
+ if (receipt.authority !== this.expectedAuthority || receipt.keyId !== this.expectedKeyId
198
+ || configuredIssuerMismatch
199
+ || receipt.installationId !== plan.installationId || receipt.planId !== plan.id
200
+ || receipt.planDigest !== plan.digest || receipt.activationId !== plan.activation?.id
201
+ || receipt.fence !== plan.activation.fence || receipt.phase !== request.phase
202
+ || receipt.operationId !== request.operationId || receipt.requestDigest !== hostAttestationRequestDigest(request)) {
203
+ throw new ControlPlaneStoreError('conflict', 'host attestation is not bound to the exact request, installation, plan, activation fence, and phase');
204
+ }
205
+ const now = this.now();
206
+ if (receipt.observedAt < request.requestedAt || receipt.observedAt < plan.createdAt || receipt.observedAt > now || now > receipt.expiresAt
207
+ || receipt.expiresAt - receipt.observedAt > request.receiptTtlMs) {
208
+ throw new ControlPlaneStoreError('expired', 'host attestation is outside its validity interval');
209
+ }
210
+ const signature = Buffer.from(receipt.signature, 'base64');
211
+ if (!verify(null, Buffer.from(canonicalReceipt(receipt)), createPublicKey(this.publicKey), signature)) {
212
+ throw new ControlPlaneStoreError('invalid-input', 'host attestation signature is invalid');
213
+ }
214
+ assertPassedEvidence(receipt, request);
215
+ const { signature: _signature, ...fields } = receipt;
216
+ return Object.freeze({ ...fields, signatureDigest: createHash('sha256').update(signature).digest('hex') });
217
+ }
218
+ }
219
+ export function hostAttestationSigningPayload(receipt) {
220
+ return canonicalReceipt({ ...receipt, signature: '' });
221
+ }
222
+ //# sourceMappingURL=attestation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.js","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface TrustedCatalogCommitInterpreter {
2
+ canonicalPath: string;
3
+ descriptor: number;
4
+ }
5
+ /**
6
+ * Resolves one fixed system launcher without consulting PATH or process input,
7
+ * then opens only its canonical root-controlled target with O_NOFOLLOW. The
8
+ * caller owns the returned descriptor and must execute that descriptor rather
9
+ * than either pathname.
10
+ */
11
+ export declare function openTrustedCatalogCommitInterpreter(launcherPath: string): TrustedCatalogCommitInterpreter;
12
+ //# sourceMappingURL=catalog-interpreter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-interpreter.d.ts","sourceRoot":"","sources":["../src/catalog-interpreter.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,+BAA+B;IAC9C,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAiFD;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,YAAY,EAAE,MAAM,GAAG,+BAA+B,CAoBzG"}
@@ -0,0 +1,100 @@
1
+ import { closeSync, constants, fstatSync, lstatSync, openSync, readlinkSync, realpathSync } from 'node:fs';
2
+ import { dirname, isAbsolute, parse, resolve, sep } from 'node:path';
3
+ function invalid(message) {
4
+ return new Error(`catalog commit interpreter ${message}`);
5
+ }
6
+ function canonicalAbsolutePath(path, label) {
7
+ if (!isAbsolute(path) || path === parse(path).root || resolve(path) !== path || path.includes('\0')) {
8
+ throw invalid(`${label} is not an absolute normalized path`);
9
+ }
10
+ }
11
+ function trustedDirectory(path) {
12
+ const metadata = lstatSync(path, { bigint: true });
13
+ if (!metadata.isDirectory() || metadata.isSymbolicLink() || metadata.uid !== 0n || (metadata.mode & 18n) !== 0n) {
14
+ throw invalid('has an unsafe canonical directory');
15
+ }
16
+ }
17
+ function trustedDirectoryChain(path) {
18
+ canonicalAbsolutePath(path, 'directory');
19
+ if (realpathSync(path) !== path)
20
+ throw invalid('directory is not canonical');
21
+ const root = parse(path).root;
22
+ trustedDirectory(root);
23
+ let current = root;
24
+ for (const component of path.slice(root.length).split(sep).filter(Boolean)) {
25
+ current = resolve(current, component);
26
+ trustedDirectory(current);
27
+ }
28
+ }
29
+ function sameSnapshot(left, right) {
30
+ return left.dev === right.dev && left.ino === right.ino && left.size === right.size
31
+ && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
32
+ }
33
+ function trustedLauncher(metadata) {
34
+ if ((!metadata.isFile() && !metadata.isSymbolicLink()) || metadata.uid !== 0n || metadata.nlink !== 1n
35
+ || (metadata.isFile() && ((metadata.mode & 73n) === 0n || (metadata.mode & 18n) !== 0n))) {
36
+ throw invalid('launcher is not a trusted root-owned file or symbolic link');
37
+ }
38
+ }
39
+ function trustedTarget(metadata) {
40
+ if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.uid !== 0n || metadata.nlink !== 1n
41
+ || (metadata.mode & 73n) === 0n || (metadata.mode & 18n) !== 0n) {
42
+ throw invalid('target is not a trusted root-owned executable');
43
+ }
44
+ }
45
+ function resolveTrustedInterpreter(launcherPath) {
46
+ const chain = [];
47
+ let current = launcherPath;
48
+ for (let depth = 0; depth < 40; depth += 1) {
49
+ canonicalAbsolutePath(current, depth === 0 ? 'launcher' : 'link target');
50
+ trustedDirectoryChain(dirname(current));
51
+ const metadata = lstatSync(current, { bigint: true });
52
+ if (depth === 0)
53
+ trustedLauncher(metadata);
54
+ chain.push({ path: current, metadata });
55
+ if (!metadata.isSymbolicLink()) {
56
+ trustedTarget(metadata);
57
+ return { canonicalPath: current, chain };
58
+ }
59
+ if (metadata.uid !== 0n || metadata.nlink !== 1n) {
60
+ throw invalid('symbolic link is not root-owned with one canonical link');
61
+ }
62
+ current = resolve(dirname(current), readlinkSync(current));
63
+ }
64
+ throw invalid('symbolic link chain is too deep');
65
+ }
66
+ function samePathChain(left, right) {
67
+ return left.length === right.length && left.every((item, index) => {
68
+ const other = right[index];
69
+ return other !== undefined && item.path === other.path && sameSnapshot(item.metadata, other.metadata);
70
+ });
71
+ }
72
+ /**
73
+ * Resolves one fixed system launcher without consulting PATH or process input,
74
+ * then opens only its canonical root-controlled target with O_NOFOLLOW. The
75
+ * caller owns the returned descriptor and must execute that descriptor rather
76
+ * than either pathname.
77
+ */
78
+ export function openTrustedCatalogCommitInterpreter(launcherPath) {
79
+ const before = resolveTrustedInterpreter(launcherPath);
80
+ const targetBefore = before.chain.at(-1).metadata;
81
+ let descriptor;
82
+ try {
83
+ descriptor = openSync(before.canonicalPath, constants.O_RDONLY | constants.O_NOFOLLOW);
84
+ const opened = fstatSync(descriptor, { bigint: true });
85
+ const after = resolveTrustedInterpreter(launcherPath);
86
+ const targetAfter = after.chain.at(-1).metadata;
87
+ trustedTarget(opened);
88
+ if (!sameSnapshot(targetBefore, opened) || !sameSnapshot(opened, targetAfter)
89
+ || before.canonicalPath !== after.canonicalPath || !samePathChain(before.chain, after.chain)) {
90
+ throw invalid('mapping changed while its descriptor was opened');
91
+ }
92
+ return { canonicalPath: before.canonicalPath, descriptor };
93
+ }
94
+ catch (error) {
95
+ if (descriptor !== undefined)
96
+ closeSync(descriptor);
97
+ throw error;
98
+ }
99
+ }
100
+ //# sourceMappingURL=catalog-interpreter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-interpreter.js","sourceRoot":"","sources":["../src/catalog-interpreter.ts"],"names":[],"mappings":"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"}