@xemahq/xema 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +70 -37
  2. package/dist/assets/distribution-assets.manifest.json +1 -2
  3. package/dist/cli.js +2 -2
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/dev.js +1 -0
  6. package/dist/commands/dev.js.map +1 -1
  7. package/dist/commands/down.d.ts.map +1 -1
  8. package/dist/commands/down.js +7 -1
  9. package/dist/commands/down.js.map +1 -1
  10. package/dist/commands/edition.d.ts +3 -0
  11. package/dist/commands/edition.d.ts.map +1 -0
  12. package/dist/commands/edition.js +46 -0
  13. package/dist/commands/edition.js.map +1 -0
  14. package/dist/commands/init.js +2 -2
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/serve.js +1 -0
  17. package/dist/commands/serve.js.map +1 -1
  18. package/dist/commands/up.js +1 -0
  19. package/dist/commands/up.js.map +1 -1
  20. package/dist/dev/env-defaults.d.ts.map +1 -1
  21. package/dist/dev/env-defaults.js +5 -2
  22. package/dist/dev/env-defaults.js.map +1 -1
  23. package/dist/dev/infra-preflight.d.ts +3 -2
  24. package/dist/dev/infra-preflight.d.ts.map +1 -1
  25. package/dist/dev/infra-preflight.js +18 -8
  26. package/dist/dev/infra-preflight.js.map +1 -1
  27. package/dist/edition/verify-image-evidence.bundle.mjs +54283 -0
  28. package/dist/edition/verify-image-evidence.bundle.provenance.json +2877 -0
  29. package/dist/runtime/config/schema.d.ts +1 -0
  30. package/dist/runtime/config/schema.d.ts.map +1 -1
  31. package/dist/runtime/custody/local-custody.d.ts +12 -0
  32. package/dist/runtime/custody/local-custody.d.ts.map +1 -0
  33. package/dist/runtime/custody/local-custody.js +22 -0
  34. package/dist/runtime/custody/local-custody.js.map +1 -0
  35. package/dist/runtime/custody/openbao-custody-bootstrap.d.ts +18 -0
  36. package/dist/runtime/custody/openbao-custody-bootstrap.d.ts.map +1 -0
  37. package/dist/runtime/custody/openbao-custody-bootstrap.js +50 -0
  38. package/dist/runtime/custody/openbao-custody-bootstrap.js.map +1 -0
  39. package/dist/runtime/custody/openbao-custody-store.d.ts +18 -0
  40. package/dist/runtime/custody/openbao-custody-store.d.ts.map +1 -0
  41. package/dist/runtime/custody/openbao-custody-store.js +55 -0
  42. package/dist/runtime/custody/openbao-custody-store.js.map +1 -0
  43. package/dist/runtime/custody/openbao-http-client.d.ts +34 -0
  44. package/dist/runtime/custody/openbao-http-client.d.ts.map +1 -0
  45. package/dist/runtime/custody/openbao-http-client.js +154 -0
  46. package/dist/runtime/custody/openbao-http-client.js.map +1 -0
  47. package/dist/runtime/custody/openbao-local-constants.d.ts +22 -0
  48. package/dist/runtime/custody/openbao-local-constants.d.ts.map +1 -0
  49. package/dist/runtime/custody/openbao-local-constants.js +48 -0
  50. package/dist/runtime/custody/openbao-local-constants.js.map +1 -0
  51. package/dist/runtime/custody/openbao-local-runner.d.ts +16 -0
  52. package/dist/runtime/custody/openbao-local-runner.d.ts.map +1 -0
  53. package/dist/runtime/custody/openbao-local-runner.js +86 -0
  54. package/dist/runtime/custody/openbao-local-runner.js.map +1 -0
  55. package/dist/runtime/edition/run-entry.d.ts +9 -0
  56. package/dist/runtime/edition/run-entry.d.ts.map +1 -0
  57. package/dist/runtime/edition/run-entry.js +36 -0
  58. package/dist/runtime/edition/run-entry.js.map +1 -0
  59. package/dist/runtime/edition/verb-map.d.ts +60 -0
  60. package/dist/runtime/edition/verb-map.d.ts.map +1 -0
  61. package/dist/runtime/edition/verb-map.js +146 -0
  62. package/dist/runtime/edition/verb-map.js.map +1 -0
  63. package/dist/runtime/env-seeder.d.ts +2 -0
  64. package/dist/runtime/env-seeder.d.ts.map +1 -1
  65. package/dist/runtime/env-seeder.js +18 -3
  66. package/dist/runtime/env-seeder.js.map +1 -1
  67. package/dist/runtime/launch.d.ts +2 -1
  68. package/dist/runtime/launch.d.ts.map +1 -1
  69. package/dist/runtime/launch.js +31 -7
  70. package/dist/runtime/launch.js.map +1 -1
  71. package/dist/runtime/paths.d.ts +1 -2
  72. package/dist/runtime/paths.d.ts.map +1 -1
  73. package/dist/runtime/paths.js +0 -10
  74. package/dist/runtime/paths.js.map +1 -1
  75. package/dist/runtime/runner/chart-local-provenance.d.ts +20 -0
  76. package/dist/runtime/runner/chart-local-provenance.d.ts.map +1 -0
  77. package/dist/runtime/runner/chart-local-provenance.js +114 -0
  78. package/dist/runtime/runner/chart-local-provenance.js.map +1 -0
  79. package/dist/runtime/runner/chart-preflight.d.ts +8 -8
  80. package/dist/runtime/runner/chart-preflight.d.ts.map +1 -1
  81. package/dist/runtime/runner/chart-preflight.js +30 -69
  82. package/dist/runtime/runner/chart-preflight.js.map +1 -1
  83. package/dist/runtime/runner/chart-pull.d.ts +14 -0
  84. package/dist/runtime/runner/chart-pull.d.ts.map +1 -0
  85. package/dist/runtime/runner/chart-pull.js +96 -0
  86. package/dist/runtime/runner/chart-pull.js.map +1 -0
  87. package/dist/runtime/runner/chart-resolver.d.ts +4 -12
  88. package/dist/runtime/runner/chart-resolver.d.ts.map +1 -1
  89. package/dist/runtime/runner/chart-resolver.js +16 -62
  90. package/dist/runtime/runner/chart-resolver.js.map +1 -1
  91. package/dist/runtime/runner/chart-set-lock.d.ts +6 -20
  92. package/dist/runtime/runner/chart-set-lock.d.ts.map +1 -1
  93. package/dist/runtime/runner/chart-set-lock.js +55 -99
  94. package/dist/runtime/runner/chart-set-lock.js.map +1 -1
  95. package/dist/runtime/runner/helm-cli.d.ts +3 -1
  96. package/dist/runtime/runner/helm-cli.d.ts.map +1 -1
  97. package/dist/runtime/runner/helm-cli.js +9 -7
  98. package/dist/runtime/runner/helm-cli.js.map +1 -1
  99. package/dist/runtime/runner/helm-runner.d.ts +4 -4
  100. package/dist/runtime/runner/helm-runner.d.ts.map +1 -1
  101. package/dist/runtime/runner/helm-runner.js +18 -16
  102. package/dist/runtime/runner/helm-runner.js.map +1 -1
  103. package/dist/runtime/sources/kinds/git.d.ts +1 -2
  104. package/dist/runtime/sources/kinds/git.d.ts.map +1 -1
  105. package/dist/runtime/sources/kinds/git.js +8 -5
  106. package/dist/runtime/sources/kinds/git.js.map +1 -1
  107. package/dist/runtime/sources/manifest-walk.d.ts +3 -1
  108. package/dist/runtime/sources/manifest-walk.d.ts.map +1 -1
  109. package/dist/runtime/sources/manifest-walk.js +8 -3
  110. package/dist/runtime/sources/manifest-walk.js.map +1 -1
  111. package/dist/runtime/sources/schema.d.ts +3 -0
  112. package/dist/runtime/sources/schema.d.ts.map +1 -1
  113. package/dist/runtime/sources/schema.js +6 -1
  114. package/dist/runtime/sources/schema.js.map +1 -1
  115. package/dist/runtime/supervisor.d.ts +2 -0
  116. package/dist/runtime/supervisor.d.ts.map +1 -1
  117. package/dist/runtime/supervisor.js +1 -0
  118. package/dist/runtime/supervisor.js.map +1 -1
  119. package/edition/README.md +313 -0
  120. package/edition/assemble-producer-input.mjs +1251 -0
  121. package/edition/authorization-base.mjs +347 -0
  122. package/edition/biome-content.mjs +268 -0
  123. package/edition/build-biome-index.mjs +175 -0
  124. package/edition/build-platform-service-index.mjs +288 -0
  125. package/edition/build-runtime-image-source-index.mjs +821 -0
  126. package/edition/built-verifier.mjs +55 -0
  127. package/edition/catalogue-edition.mjs +49 -0
  128. package/edition/catalogue-fetch.mjs +64 -0
  129. package/edition/catalogue.mjs +135 -0
  130. package/edition/chart-set-source-commit.mjs +92 -0
  131. package/edition/check-committed-image-evidence.mjs +383 -0
  132. package/edition/checkout-indexed-source-repositories.mjs +105 -0
  133. package/edition/comment-blanker.mjs +75 -0
  134. package/edition/connector-source-authority.mjs +60 -0
  135. package/edition/customer-definition.mjs +183 -0
  136. package/edition/customer-flags.mjs +7 -0
  137. package/edition/develop-customer-edition.mjs +99 -0
  138. package/edition/develop-edition-resolve.mjs +65 -0
  139. package/edition/develop-edition.mjs +274 -0
  140. package/edition/develop-freeze.mjs +173 -0
  141. package/edition/develop-image-coordinate.mjs +54 -0
  142. package/edition/develop-seal.mjs +77 -0
  143. package/edition/develop-snapshot-inputs.mjs +104 -0
  144. package/edition/dist-check.mjs +986 -0
  145. package/edition/distribution-evidence-set.mjs +987 -0
  146. package/edition/distribution-paths.mjs +191 -0
  147. package/edition/edition-artifact.mjs +284 -0
  148. package/edition/edition-biome-manifests.mjs +85 -0
  149. package/edition/edition-channel.mjs +6 -0
  150. package/edition/edition-chart-set.mjs +93 -0
  151. package/edition/edition-config.mjs +205 -0
  152. package/edition/edition-constants.mjs +57 -0
  153. package/edition/edition-contract.json +30 -0
  154. package/edition/edition-list.mjs +35 -0
  155. package/edition/edition-locks.mjs +69 -0
  156. package/edition/edition-protocol.mjs +228 -0
  157. package/edition/edition-workspace.mjs +187 -0
  158. package/edition/evidence-checkout.mjs +439 -0
  159. package/edition/evidence-grammars.mjs +16 -0
  160. package/edition/evidence-trust-pin.mjs +304 -0
  161. package/edition/evidence-trust-policy.mjs +294 -0
  162. package/edition/external-source-walk.mjs +463 -0
  163. package/edition/first-party-source-ids.mjs +59 -0
  164. package/edition/fleet-coordinate-finality.mjs +350 -0
  165. package/edition/git-source-auth.mjs +52 -0
  166. package/edition/image-delivery-entitlement-descriptor.mjs +106 -0
  167. package/edition/image-evidence-replay-state.mjs +242 -0
  168. package/edition/image-evidence.mjs +1233 -0
  169. package/edition/kernel-contract-authority.mjs +443 -0
  170. package/edition/lib.mjs +3021 -0
  171. package/edition/no-follow-file.mjs +94 -0
  172. package/edition/oci-evidence-verbs.mjs +392 -0
  173. package/edition/oci-image-source-evidence.mjs +239 -0
  174. package/edition/oras.mjs +648 -0
  175. package/edition/pin-source.mjs +227 -0
  176. package/edition/plan-image-evidence-refresh.mjs +408 -0
  177. package/edition/platform-lock-readability.mjs +892 -0
  178. package/edition/platform-service-class.mjs +18 -0
  179. package/edition/platform-service-source-authority.mjs +105 -0
  180. package/edition/positive-closure.mjs +162 -0
  181. package/edition/produce-distribution-completeness-evidence.mjs +311 -0
  182. package/edition/produce-image-delivery-entitlement-evidence.mjs +294 -0
  183. package/edition/produce-image-source-evidence.mjs +765 -0
  184. package/edition/producer-evidence-bundle.mjs +157 -0
  185. package/edition/registry-credentials.mjs +193 -0
  186. package/edition/release-catalogue.mjs +39 -0
  187. package/edition/release-channel-guard.mjs +109 -0
  188. package/edition/release-edition-artifact.mjs +157 -0
  189. package/edition/remedy-command.mjs +89 -0
  190. package/edition/repin-evidence-trust.mjs +101 -0
  191. package/edition/required-resource-provider.mjs +58 -0
  192. package/edition/resolve-chart-set.mjs +415 -0
  193. package/edition/resolve-customer-edition.mjs +288 -0
  194. package/edition/resolve-distribution.mjs +2318 -0
  195. package/edition/resolve-edition.mjs +186 -0
  196. package/edition/resolve-images.mjs +1606 -0
  197. package/edition/seal-image-digests.mjs +855 -0
  198. package/edition/sealed-evidence-accept.mjs +82 -0
  199. package/edition/source-authority.mjs +725 -0
  200. package/edition/source-closure.mjs +116 -0
  201. package/edition/strict-json.mjs +121 -0
  202. package/edition/string-order.mjs +5 -0
  203. package/edition/trust-policy-arming.mjs +120 -0
  204. package/edition/trusted-executable.mjs +166 -0
  205. package/edition/verifier-binding.mjs +45 -0
  206. package/edition/verifier-files.mjs +8 -0
  207. package/edition/verifier-kernel-schemas.mjs +22 -0
  208. package/edition/verifier-provenance.mjs +64 -0
  209. package/edition/verify-image-evidence.mjs +458 -0
  210. package/edition/verify-image-platforms.mjs +495 -0
  211. package/edition/why.mjs +56 -0
  212. package/edition/workspace-sections.mjs +195 -0
  213. package/examples/06-biome-sources.yaml +1 -0
  214. package/package.json +14 -6
  215. package/dist/commands/dist.d.ts +0 -16
  216. package/dist/commands/dist.d.ts.map +0 -1
  217. package/dist/commands/dist.js +0 -182
  218. package/dist/commands/dist.js.map +0 -1
  219. package/dist/runtime/distribution/available-biome.d.ts +0 -10
  220. package/dist/runtime/distribution/available-biome.d.ts.map +0 -1
  221. package/dist/runtime/distribution/available-biome.js +0 -156
  222. package/dist/runtime/distribution/available-biome.js.map +0 -1
  223. package/dist/runtime/distribution/compose.d.ts +0 -23
  224. package/dist/runtime/distribution/compose.d.ts.map +0 -1
  225. package/dist/runtime/distribution/compose.js +0 -48
  226. package/dist/runtime/distribution/compose.js.map +0 -1
  227. package/dist/runtime/runner/chart-trust.d.ts +0 -57
  228. package/dist/runtime/runner/chart-trust.d.ts.map +0 -1
  229. package/dist/runtime/runner/chart-trust.js +0 -270
  230. package/dist/runtime/runner/chart-trust.js.map +0 -1
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env node
2
+ // The image delivery entitlement statement: one customer's entitlement to one
3
+ // sealed evidence set.
4
+ //
5
+ // xema edition evidence statement entitlement stage|accept …
6
+ //
7
+ // `stage` writes the canonical statement into a NEW staging directory and
8
+ // prints the signing plan; the caller signs it (`cosign attest-blob`);
9
+ // `accept` re-derives the statement from the same flags, refuses staged bytes
10
+ // that differ, verifies the signed bundle with cosign against the declared
11
+ // signer, writes `entitlement.json` and seals the output (built from the
12
+ // re-derived files, never renamed from the staging). This module never signs and never requests an OIDC token.
13
+
14
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
15
+ import { isAbsolute, join, resolve } from 'node:path';
16
+
17
+ import {
18
+ acceptSignedEvidenceStatement,
19
+ assertPinnedCosignVersion,
20
+ buildImageDeliveryEntitlementStatement,
21
+ loadPinnedTrustPolicy,
22
+ parseEvidenceCliFlags,
23
+ stageEvidenceStatement,
24
+ } from './distribution-evidence-set.mjs';
25
+ import {
26
+ WorkspaceRoot,
27
+ configureEditionWorkspaceFromArgv,
28
+ dataRoot,
29
+ isEntryModule,
30
+ } from './edition-workspace.mjs';
31
+ import { ENTITLEMENT_DESCRIPTOR_FILE, entitlementDescriptorDocument } from './image-delivery-entitlement-descriptor.mjs';
32
+ import { canonicalJsonBytes, readCanonicalJsonFromRoot } from './image-evidence.mjs';
33
+ import { serializeJson } from './lib.mjs';
34
+ import { githubWorkflowSigner } from './produce-distribution-completeness-evidence.mjs';
35
+ import {
36
+ assertGitHubProducerContext,
37
+ createCosignVerifier,
38
+ loadProducerKernelSchemas,
39
+ } from './produce-image-source-evidence.mjs';
40
+ import { assertStagedExactly, reserveSealing, sealAccepted } from './sealed-evidence-accept.mjs';
41
+
42
+ const ENTITLEMENT_STATEMENT_PATH = 'entitlement/statement.json';
43
+ const ENTITLEMENT_BUNDLE_PATH = 'entitlement/bundle.sigstore.json';
44
+
45
+ /**
46
+ * Read the completeness statement digest of an ASSEMBLED evidence set.
47
+ *
48
+ * The set is parsed through the kernel schema first: an entitlement must never
49
+ * be issued against a document that the verifier would not accept as an
50
+ * evidence set in the first place.
51
+ */
52
+ export function readCompletenessStatementDigest({
53
+ evidenceRoot,
54
+ distributionId,
55
+ schemas,
56
+ evidenceSetPath = 'evidence-set.json',
57
+ }) {
58
+ const evidenceSet = schemas.parseDistributionImageEvidenceSet(
59
+ readCanonicalJsonFromRoot(
60
+ evidenceRoot,
61
+ evidenceSetPath,
62
+ 'distribution image evidence set',
63
+ ),
64
+ );
65
+ if (evidenceSet.distributionId !== distributionId) {
66
+ throw new Error(
67
+ `evidence set "${evidenceSet.distributionId}" does not match requested distribution "${distributionId}"`,
68
+ );
69
+ }
70
+ return {
71
+ evidenceSet,
72
+ completenessStatementDigest: evidenceSet.completeness.statementDigest,
73
+ };
74
+ }
75
+
76
+
77
+ function deriveEntitlement(options) {
78
+ const { completenessStatementDigest } = readCompletenessStatementDigest({
79
+ evidenceRoot: options.evidenceRoot,
80
+ distributionId: options.distributionId,
81
+ schemas: options.schemas,
82
+ });
83
+ const statement = buildImageDeliveryEntitlementStatement({
84
+ distributionId: options.distributionId,
85
+ completenessStatementDigest,
86
+ customerId: options.customerId,
87
+ mode: options.mode,
88
+ targetRegistry: options.targetRegistry,
89
+ idempotencyKey: options.idempotencyKey,
90
+ runId: options.runId,
91
+ runAttempt: options.runAttempt,
92
+ issuedAt: options.issuedAt,
93
+ expiresAt: options.expiresAt,
94
+ maxTtlSeconds: options.policy.maxEntitlementTtlSeconds,
95
+ schemas: options.schemas,
96
+ });
97
+ return {
98
+ completenessStatementDigest,
99
+ statement,
100
+ signing: {
101
+ statement,
102
+ root: options.stagingDirectory,
103
+ statementPath: ENTITLEMENT_STATEMENT_PATH,
104
+ bundlePath: ENTITLEMENT_BUNDLE_PATH,
105
+ signer: options.signer,
106
+ certificateWorkflowSha: options.signingWorkflowSha,
107
+ predicateType: options.schemas.IMAGE_DELIVERY_ENTITLEMENT_PREDICATE_TYPE,
108
+ },
109
+ };
110
+ }
111
+
112
+ /** Stage one customer's entitlement statement for signing. Returns the signing plan and the statement. */
113
+ export function stageImageDeliveryEntitlementEvidence(options) {
114
+ const { stagingDirectory } = options;
115
+ if (typeof stagingDirectory !== 'string' || !isAbsolute(stagingDirectory)) {
116
+ throw new Error('the entitlement staging directory must be absolute');
117
+ }
118
+ if (existsSync(stagingDirectory)) {
119
+ throw new Error(`entitlement staging directory already exists: ${stagingDirectory}`);
120
+ }
121
+ assertGitHubProducerContext(
122
+ { signer: options.signer, producerWorkflowSha: options.signingWorkflowSha },
123
+ options.githubContext,
124
+ );
125
+ const { statement, signing } = deriveEntitlement(options);
126
+ mkdirSync(stagingDirectory, { recursive: true, mode: 0o700 });
127
+ try {
128
+ const plan = stageEvidenceStatement(signing);
129
+ return {
130
+ plan: {
131
+ ...plan,
132
+ kind: 'entitlement',
133
+ distributionId: options.distributionId,
134
+ customerId: options.customerId,
135
+ },
136
+ statement,
137
+ };
138
+ } catch (error) {
139
+ rmSync(stagingDirectory, { recursive: true, force: true });
140
+ throw error;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Accept the signed entitlement bundle, write `entitlement.json` and seal
146
+ * `outputDirectory`. The output is BUILT from the re-derived statement and the
147
+ * canonicalized bundle, never renamed from the staging, which must hold exactly
148
+ * what stage recorded and does not outlive the accept.
149
+ */
150
+ export function acceptImageDeliveryEntitlementEvidence(options) {
151
+ const { outputDirectory, stagingDirectory, readCosignVersion, runCosign } = options;
152
+ if (
153
+ typeof outputDirectory !== 'string' ||
154
+ !isAbsolute(outputDirectory) ||
155
+ typeof stagingDirectory !== 'string' ||
156
+ !isAbsolute(stagingDirectory)
157
+ ) {
158
+ throw new Error('the entitlement output and staging directories must be absolute');
159
+ }
160
+ if (typeof readCosignVersion !== 'function' || typeof runCosign !== 'function') {
161
+ throw new Error('cosign seams are required');
162
+ }
163
+ const sealing = reserveSealing(outputDirectory, 'entitlement');
164
+ return sealAccepted({
165
+ stagingDirectory,
166
+ sealing,
167
+ outputDirectory,
168
+ build: () => {
169
+ assertGitHubProducerContext(
170
+ { signer: options.signer, producerWorkflowSha: options.signingWorkflowSha },
171
+ options.githubContext,
172
+ );
173
+ assertPinnedCosignVersion(readCosignVersion(), options.policy?.cosignVersion);
174
+ const { completenessStatementDigest, statement, signing } = deriveEntitlement(options);
175
+ assertStagedExactly(stagingDirectory, [ENTITLEMENT_STATEMENT_PATH, ENTITLEMENT_BUNDLE_PATH]);
176
+ const descriptor = acceptSignedEvidenceStatement({ ...signing, sealingRoot: sealing, runCosign });
177
+ writeFileSync(
178
+ join(sealing, ENTITLEMENT_DESCRIPTOR_FILE),
179
+ canonicalJsonBytes(
180
+ entitlementDescriptorDocument({
181
+ distributionId: options.distributionId,
182
+ customerId: options.customerId,
183
+ mode: options.mode,
184
+ targetRegistry: options.targetRegistry,
185
+ idempotencyKey: options.idempotencyKey,
186
+ distributionStatementDigest: completenessStatementDigest,
187
+ evidence: descriptor,
188
+ }),
189
+ ),
190
+ { flag: 'wx', mode: 0o644 },
191
+ );
192
+ return { outputDirectory, statement, descriptor, completenessStatementDigest };
193
+ },
194
+ });
195
+ }
196
+
197
+ function requireInteger(raw, label, { positive }) {
198
+ const value = Number(raw);
199
+ if (!/^\d+$/.test(String(raw)) || !Number.isSafeInteger(value) || (positive && value <= 0)) {
200
+ throw new Error(`--${label} must be a ${positive ? 'positive' : 'non-negative'} integer`);
201
+ }
202
+ return value;
203
+ }
204
+
205
+ const SHARED_FLAGS = Object.freeze([
206
+ 'distribution',
207
+ 'evidence-root',
208
+ 'staging',
209
+ 'customer',
210
+ 'mode',
211
+ 'target-registry',
212
+ 'idempotency-key',
213
+ 'run-id',
214
+ 'run-attempt',
215
+ 'issued-at',
216
+ 'expires-at',
217
+ 'signer-repository',
218
+ 'signer-ref',
219
+ 'signer-workflow-path',
220
+ 'github-repository',
221
+ 'github-ref',
222
+ 'github-sha',
223
+ 'github-workflow-ref',
224
+ ]);
225
+
226
+ async function main() {
227
+ const [phase, ...args] = configureEditionWorkspaceFromArgv(process.argv.slice(2), [
228
+ WorkspaceRoot.Data,
229
+ WorkspaceRoot.Kernel,
230
+ ]);
231
+ if (phase !== 'stage' && phase !== 'accept') {
232
+ throw new Error('usage: xema edition evidence statement entitlement <stage|accept> …');
233
+ }
234
+ const flags = parseEvidenceCliFlags(args, {
235
+ single: phase === 'stage' ? SHARED_FLAGS : [...SHARED_FLAGS, 'output', 'cosign'],
236
+ repeated: [],
237
+ });
238
+ const { schemas } = await loadProducerKernelSchemas({ dataRoot: dataRoot() });
239
+ const githubSha = flags.require('github-sha');
240
+ const options = {
241
+ distributionId: flags.require('distribution'),
242
+ evidenceRoot: resolve(flags.require('evidence-root')),
243
+ stagingDirectory: resolve(flags.require('staging')),
244
+ schemas,
245
+ policy: loadPinnedTrustPolicy({ dataRoot: dataRoot(), schemas }),
246
+ signer: githubWorkflowSigner({
247
+ repository: flags.require('signer-repository'),
248
+ ref: flags.require('signer-ref'),
249
+ path: flags.require('signer-workflow-path'),
250
+ }),
251
+ githubContext: {
252
+ repository: flags.require('github-repository'),
253
+ ref: flags.require('github-ref'),
254
+ sha: githubSha,
255
+ workflowRef: flags.require('github-workflow-ref'),
256
+ },
257
+ signingWorkflowSha: githubSha,
258
+ customerId: flags.require('customer'),
259
+ mode: flags.require('mode'),
260
+ targetRegistry: flags.optional('target-registry') ?? null,
261
+ idempotencyKey: flags.require('idempotency-key'),
262
+ runId: flags.require('run-id'),
263
+ runAttempt: requireInteger(flags.require('run-attempt'), 'run-attempt', { positive: true }),
264
+ issuedAt: flags.require('issued-at'),
265
+ expiresAt: flags.require('expires-at'),
266
+ };
267
+ if (phase === 'stage') {
268
+ process.stdout.write(serializeJson(stageImageDeliveryEntitlementEvidence(options).plan));
269
+ return;
270
+ }
271
+ const result = acceptImageDeliveryEntitlementEvidence({
272
+ ...options,
273
+ outputDirectory: resolve(flags.require('output')),
274
+ ...createCosignVerifier(resolve(flags.require('cosign'))),
275
+ });
276
+ process.stdout.write(
277
+ serializeJson({
278
+ schemaVersion: 1,
279
+ kind: 'entitlement',
280
+ distributionId: options.distributionId,
281
+ customerId: options.customerId,
282
+ outputDirectory: result.outputDirectory,
283
+ completenessStatementDigest: result.completenessStatementDigest,
284
+ evidence: result.descriptor,
285
+ }),
286
+ );
287
+ }
288
+
289
+ if (isEntryModule(import.meta.url)) {
290
+ main().catch((error) => {
291
+ console.error(`[image-delivery-entitlement] ${error.message}`);
292
+ process.exitCode = 1;
293
+ });
294
+ }