@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,242 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import {
3
+ closeSync,
4
+ constants as fsConstants,
5
+ fstatSync,
6
+ fsyncSync,
7
+ openSync,
8
+ readSync,
9
+ realpathSync,
10
+ renameSync,
11
+ unlinkSync,
12
+ writeFileSync,
13
+ } from 'node:fs';
14
+ import { basename, dirname, isAbsolute, join } from 'node:path';
15
+
16
+ import {
17
+ canonicalJsonBytes,
18
+ parseCanonicalJsonBytes,
19
+ } from './image-evidence.mjs';
20
+
21
+ const MAX_REPLAY_STATE_BYTES = 64 * 1024;
22
+
23
+ function openRegularFileNoFollow(path) {
24
+ const descriptor = openSync(
25
+ path,
26
+ fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW,
27
+ );
28
+ const metadata = fstatSync(descriptor);
29
+ if (!metadata.isFile()) {
30
+ closeSync(descriptor);
31
+ throw new Error(`replay state "${path}" is not a regular file`);
32
+ }
33
+ if ((metadata.mode & 0o777) !== 0o600) {
34
+ closeSync(descriptor);
35
+ throw new Error(`replay state "${path}" must have exact mode 0600`);
36
+ }
37
+ if (
38
+ typeof process.getuid === 'function' &&
39
+ metadata.uid !== process.getuid()
40
+ ) {
41
+ closeSync(descriptor);
42
+ throw new Error(`replay state "${path}" must be owned by the verifier`);
43
+ }
44
+ return descriptor;
45
+ }
46
+
47
+ function assertTrustedStateDirectory(path) {
48
+ const descriptor = openSync(
49
+ path,
50
+ fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW,
51
+ );
52
+ try {
53
+ const metadata = fstatSync(descriptor);
54
+ if (!metadata.isDirectory()) {
55
+ throw new Error(`replay state parent "${path}" is not a directory`);
56
+ }
57
+ if ((metadata.mode & 0o777) !== 0o700) {
58
+ throw new Error(
59
+ `replay state parent "${path}" must have exact mode 0700`,
60
+ );
61
+ }
62
+ if (
63
+ typeof process.getuid === 'function' &&
64
+ metadata.uid !== process.getuid()
65
+ ) {
66
+ throw new Error(
67
+ `replay state parent "${path}" must be owned by the verifier`,
68
+ );
69
+ }
70
+ } finally {
71
+ closeSync(descriptor);
72
+ }
73
+ }
74
+
75
+ function writeDurableReplacement(path, value) {
76
+ const directory = realpathSync(dirname(path));
77
+ const temporaryPath = join(
78
+ directory,
79
+ `.${basename(path)}.${randomUUID()}.tmp`,
80
+ );
81
+ let descriptor;
82
+ try {
83
+ descriptor = openSync(
84
+ temporaryPath,
85
+ fsConstants.O_CREAT |
86
+ fsConstants.O_EXCL |
87
+ fsConstants.O_WRONLY |
88
+ fsConstants.O_NOFOLLOW,
89
+ 0o600,
90
+ );
91
+ writeFileSync(descriptor, canonicalJsonBytes(value));
92
+ fsyncSync(descriptor);
93
+ closeSync(descriptor);
94
+ descriptor = undefined;
95
+ renameSync(temporaryPath, path);
96
+ const directoryDescriptor = openSync(directory, fsConstants.O_RDONLY);
97
+ try {
98
+ fsyncSync(directoryDescriptor);
99
+ } finally {
100
+ closeSync(directoryDescriptor);
101
+ }
102
+ } finally {
103
+ if (descriptor !== undefined) {closeSync(descriptor);}
104
+ removeIfPresent(temporaryPath);
105
+ }
106
+ }
107
+
108
+ /** Remove `path`; only its absence is tolerated. */
109
+ function removeIfPresent(path) {
110
+ try {
111
+ unlinkSync(path);
112
+ } catch (error) {
113
+ if (error?.code !== 'ENOENT') {throw error;}
114
+ }
115
+ }
116
+
117
+ export async function verifyAndAdvanceReplayState({
118
+ statePath,
119
+ distributionId,
120
+ trustPolicyDigest,
121
+ parseReplayState,
122
+ verify,
123
+ }) {
124
+ if (!isAbsolute(statePath)) {
125
+ throw new Error('replay state path must be absolute');
126
+ }
127
+ const stateDirectory = realpathSync(dirname(statePath));
128
+ if (stateDirectory !== dirname(statePath)) {
129
+ throw new Error('replay state parent path must be canonical');
130
+ }
131
+ assertTrustedStateDirectory(stateDirectory);
132
+ const canonicalStatePath = join(stateDirectory, basename(statePath));
133
+ const lockPath = `${canonicalStatePath}.lock`;
134
+ let lockDescriptor;
135
+ try {
136
+ lockDescriptor = openSync(
137
+ lockPath,
138
+ fsConstants.O_CREAT |
139
+ fsConstants.O_EXCL |
140
+ fsConstants.O_WRONLY |
141
+ fsConstants.O_NOFOLLOW,
142
+ 0o600,
143
+ );
144
+ } catch (error) {
145
+ if (error?.code === 'EEXIST') {
146
+ throw new Error(
147
+ `replay state "${canonicalStatePath}" is locked by another verifier; explicit operator reconciliation is required for a stale lock`,
148
+ );
149
+ }
150
+ throw error;
151
+ }
152
+
153
+ try {
154
+ writeFileSync(
155
+ lockDescriptor,
156
+ `${process.pid} ${new Date().toISOString()}\n`,
157
+ );
158
+ fsyncSync(lockDescriptor);
159
+ const stateDescriptor = openRegularFileNoFollow(canonicalStatePath);
160
+ let state;
161
+ try {
162
+ const before = fstatSync(stateDescriptor);
163
+ if (before.size > MAX_REPLAY_STATE_BYTES) {
164
+ throw new Error(`replay state exceeds ${MAX_REPLAY_STATE_BYTES} bytes`);
165
+ }
166
+ const stateBytes = Buffer.alloc(before.size);
167
+ let offset = 0;
168
+ while (offset < stateBytes.length) {
169
+ const count = readSync(
170
+ stateDescriptor,
171
+ stateBytes,
172
+ offset,
173
+ stateBytes.length - offset,
174
+ offset,
175
+ );
176
+ if (count === 0) {
177
+ throw new Error('replay state was truncated while reading');
178
+ }
179
+ offset += count;
180
+ }
181
+ if (readSync(stateDescriptor, Buffer.alloc(1), 0, 1, offset) !== 0) {
182
+ throw new Error('replay state grew while reading');
183
+ }
184
+ const after = fstatSync(stateDescriptor);
185
+ for (const field of ['dev', 'ino', 'size', 'mtimeMs', 'ctimeMs']) {
186
+ if (after[field] !== before[field]) {
187
+ throw new Error('replay state changed while reading');
188
+ }
189
+ }
190
+ state = parseReplayState(
191
+ parseCanonicalJsonBytes(stateBytes, 'distribution image replay state'),
192
+ );
193
+ } finally {
194
+ closeSync(stateDescriptor);
195
+ }
196
+ if (
197
+ state.distributionId !== distributionId ||
198
+ state.trustPolicyDigest !== trustPolicyDigest
199
+ ) {
200
+ throw new Error(
201
+ 'replay state does not match the selected distribution and committed trust policy',
202
+ );
203
+ }
204
+
205
+ const verified = await verify(state);
206
+ const completeness = verified.completenessStatement.predicate;
207
+ if (completeness.releaseSequence <= state.lastReleaseSequence) {
208
+ throw new Error(
209
+ 'verified completeness evidence does not advance releaseSequence',
210
+ );
211
+ }
212
+ if (completeness.nonce === state.lastCompletenessNonce) {
213
+ throw new Error(
214
+ 'verified completeness evidence reuses the last accepted nonce',
215
+ );
216
+ }
217
+ if (
218
+ verified.completenessStatementDigest ===
219
+ state.lastCompletenessStatementDigest
220
+ ) {
221
+ throw new Error(
222
+ 'verified completeness evidence reuses the last accepted statement',
223
+ );
224
+ }
225
+ const nextState = parseReplayState({
226
+ schemaVersion: 1,
227
+ distributionId,
228
+ trustPolicyDigest,
229
+ lastReleaseSequence: completeness.releaseSequence,
230
+ lastCompletenessStatementDigest: verified.completenessStatementDigest,
231
+ lastCompletenessNonce: completeness.nonce,
232
+ });
233
+ writeDurableReplacement(canonicalStatePath, nextState);
234
+ return { verified, replayState: nextState };
235
+ } finally {
236
+ try {
237
+ closeSync(lockDescriptor);
238
+ } finally {
239
+ unlinkSync(lockPath);
240
+ }
241
+ }
242
+ }