@wavehouse/chtypes 0.5.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +34 -38
  3. package/dist/abi1/buildinfo.d.ts +40 -0
  4. package/dist/abi1/buildinfo.d.ts.map +1 -0
  5. package/dist/abi1/buildinfo.js +83 -0
  6. package/dist/abi1/buildinfo.js.map +1 -0
  7. package/dist/abi1/calls.gen.d.ts +55 -0
  8. package/dist/abi1/calls.gen.d.ts.map +1 -0
  9. package/dist/abi1/calls.gen.js +110 -0
  10. package/dist/abi1/calls.gen.js.map +1 -0
  11. package/dist/abi1/decls.gen.d.ts +115 -0
  12. package/dist/abi1/decls.gen.d.ts.map +1 -0
  13. package/dist/abi1/decls.gen.js +1613 -0
  14. package/dist/abi1/decls.gen.js.map +1 -0
  15. package/dist/abi1/errmap.gen.d.ts +18 -0
  16. package/dist/abi1/errmap.gen.d.ts.map +1 -0
  17. package/dist/abi1/errmap.gen.js +66 -0
  18. package/dist/abi1/errmap.gen.js.map +1 -0
  19. package/dist/abi1/errors.d.ts +107 -0
  20. package/dist/abi1/errors.d.ts.map +1 -0
  21. package/dist/abi1/errors.js +134 -0
  22. package/dist/abi1/errors.js.map +1 -0
  23. package/dist/abi1/handles.d.ts +31 -0
  24. package/dist/abi1/handles.d.ts.map +1 -0
  25. package/dist/abi1/handles.js +76 -0
  26. package/dist/abi1/handles.js.map +1 -0
  27. package/dist/abi1/index.d.ts +17 -0
  28. package/dist/abi1/index.d.ts.map +1 -0
  29. package/dist/abi1/index.js +17 -0
  30. package/dist/abi1/index.js.map +1 -0
  31. package/dist/abi1/libc.d.ts +54 -0
  32. package/dist/abi1/libc.d.ts.map +1 -0
  33. package/dist/abi1/libc.gen.d.ts +12 -0
  34. package/dist/abi1/libc.gen.d.ts.map +1 -0
  35. package/dist/abi1/libc.gen.js +75 -0
  36. package/dist/abi1/libc.gen.js.map +1 -0
  37. package/dist/abi1/libc.js +109 -0
  38. package/dist/abi1/libc.js.map +1 -0
  39. package/dist/abi1/loader.d.ts +99 -0
  40. package/dist/abi1/loader.d.ts.map +1 -0
  41. package/dist/abi1/loader.js +261 -0
  42. package/dist/abi1/loader.js.map +1 -0
  43. package/dist/abi1/raw.d.ts +104 -0
  44. package/dist/abi1/raw.d.ts.map +1 -0
  45. package/dist/abi1/raw.js +296 -0
  46. package/dist/abi1/raw.js.map +1 -0
  47. package/dist/abi1/strictjson.d.ts +19 -0
  48. package/dist/abi1/strictjson.d.ts.map +1 -0
  49. package/dist/abi1/strictjson.js +78 -0
  50. package/dist/abi1/strictjson.js.map +1 -0
  51. package/dist/abi1/vocab.gen.d.ts +169 -0
  52. package/dist/abi1/vocab.gen.d.ts.map +1 -0
  53. package/dist/abi1/vocab.gen.js +306 -0
  54. package/dist/abi1/vocab.gen.js.map +1 -0
  55. package/dist/cli.d.ts +25 -26
  56. package/dist/cli.d.ts.map +1 -1
  57. package/dist/cli.js +206 -218
  58. package/dist/cli.js.map +1 -1
  59. package/dist/documents.d.ts +195 -0
  60. package/dist/documents.d.ts.map +1 -0
  61. package/dist/documents.js +389 -0
  62. package/dist/documents.js.map +1 -0
  63. package/dist/env.d.ts +16 -0
  64. package/dist/env.d.ts.map +1 -0
  65. package/dist/env.js +57 -0
  66. package/dist/env.js.map +1 -0
  67. package/dist/index.d.ts +19 -24
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +17 -23
  70. package/dist/index.js.map +1 -1
  71. package/dist/json.d.ts +11 -89
  72. package/dist/json.d.ts.map +1 -1
  73. package/dist/json.js +16 -180
  74. package/dist/json.js.map +1 -1
  75. package/dist/library.d.ts +53 -309
  76. package/dist/library.d.ts.map +1 -1
  77. package/dist/library.js +77 -315
  78. package/dist/library.js.map +1 -1
  79. package/dist/ocifetch/constants.gen.d.ts +84 -0
  80. package/dist/ocifetch/constants.gen.d.ts.map +1 -0
  81. package/dist/ocifetch/constants.gen.js +92 -0
  82. package/dist/ocifetch/constants.gen.js.map +1 -0
  83. package/dist/ocifetch/dsse.d.ts +114 -0
  84. package/dist/ocifetch/dsse.d.ts.map +1 -0
  85. package/dist/ocifetch/dsse.js +331 -0
  86. package/dist/ocifetch/dsse.js.map +1 -0
  87. package/dist/ocifetch/ensure.d.ts +65 -0
  88. package/dist/ocifetch/ensure.d.ts.map +1 -0
  89. package/dist/ocifetch/ensure.js +775 -0
  90. package/dist/ocifetch/ensure.js.map +1 -0
  91. package/dist/ocifetch/errors.d.ts +92 -0
  92. package/dist/ocifetch/errors.d.ts.map +1 -0
  93. package/dist/ocifetch/errors.js +101 -0
  94. package/dist/ocifetch/errors.js.map +1 -0
  95. package/dist/ocifetch/goldens.d.ts +44 -0
  96. package/dist/ocifetch/goldens.d.ts.map +1 -0
  97. package/dist/ocifetch/goldens.js +62 -0
  98. package/dist/ocifetch/goldens.js.map +1 -0
  99. package/dist/ocifetch/http.d.ts +124 -0
  100. package/dist/ocifetch/http.d.ts.map +1 -0
  101. package/dist/ocifetch/http.js +549 -0
  102. package/dist/ocifetch/http.js.map +1 -0
  103. package/dist/ocifetch/index.d.ts +17 -0
  104. package/dist/ocifetch/index.d.ts.map +1 -0
  105. package/dist/ocifetch/index.js +14 -0
  106. package/dist/ocifetch/index.js.map +1 -0
  107. package/dist/ocifetch/layout.d.ts +126 -0
  108. package/dist/ocifetch/layout.d.ts.map +1 -0
  109. package/dist/ocifetch/layout.js +375 -0
  110. package/dist/ocifetch/layout.js.map +1 -0
  111. package/dist/ocifetch/localverify.d.ts +43 -0
  112. package/dist/ocifetch/localverify.d.ts.map +1 -0
  113. package/dist/ocifetch/localverify.js +164 -0
  114. package/dist/ocifetch/localverify.js.map +1 -0
  115. package/dist/ocifetch/lock.d.ts +39 -0
  116. package/dist/ocifetch/lock.d.ts.map +1 -0
  117. package/dist/ocifetch/lock.js +140 -0
  118. package/dist/ocifetch/lock.js.map +1 -0
  119. package/dist/ocifetch/oci.d.ts +100 -0
  120. package/dist/ocifetch/oci.d.ts.map +1 -0
  121. package/dist/ocifetch/oci.js +323 -0
  122. package/dist/ocifetch/oci.js.map +1 -0
  123. package/dist/ocifetch/referrers.d.ts +55 -0
  124. package/dist/ocifetch/referrers.d.ts.map +1 -0
  125. package/dist/ocifetch/referrers.js +132 -0
  126. package/dist/ocifetch/referrers.js.map +1 -0
  127. package/dist/ocifetch/types.d.ts +167 -0
  128. package/dist/ocifetch/types.d.ts.map +1 -0
  129. package/dist/ocifetch/types.js +88 -0
  130. package/dist/ocifetch/types.js.map +1 -0
  131. package/dist/ocifetch/unpack.d.ts +55 -0
  132. package/dist/ocifetch/unpack.d.ts.map +1 -0
  133. package/dist/ocifetch/unpack.js +205 -0
  134. package/dist/ocifetch/unpack.js.map +1 -0
  135. package/dist/registry.d.ts +38 -387
  136. package/dist/registry.d.ts.map +1 -1
  137. package/dist/registry.js +94 -819
  138. package/dist/registry.js.map +1 -1
  139. package/dist/schema.d.ts +77 -588
  140. package/dist/schema.d.ts.map +1 -1
  141. package/dist/schema.js +87 -549
  142. package/dist/schema.js.map +1 -1
  143. package/dist/settings.d.ts +27 -36
  144. package/dist/settings.d.ts.map +1 -1
  145. package/dist/settings.js +75 -25
  146. package/dist/settings.js.map +1 -1
  147. package/dist/setup.d.ts +37 -0
  148. package/dist/setup.d.ts.map +1 -0
  149. package/dist/setup.js +60 -0
  150. package/dist/setup.js.map +1 -0
  151. package/dist/tar.d.ts +27 -11
  152. package/dist/tar.d.ts.map +1 -1
  153. package/dist/tar.js +54 -32
  154. package/dist/tar.js.map +1 -1
  155. package/package.json +2 -2
  156. package/dist/discover.d.ts +0 -142
  157. package/dist/discover.d.ts.map +0 -1
  158. package/dist/discover.js +0 -288
  159. package/dist/discover.js.map +0 -1
  160. package/dist/error-codes.d.ts +0 -80
  161. package/dist/error-codes.d.ts.map +0 -1
  162. package/dist/error-codes.js +0 -139
  163. package/dist/error-codes.js.map +0 -1
  164. package/dist/errors.d.ts +0 -284
  165. package/dist/errors.d.ts.map +0 -1
  166. package/dist/errors.js +0 -321
  167. package/dist/errors.js.map +0 -1
  168. package/dist/fetch.d.ts +0 -382
  169. package/dist/fetch.d.ts.map +0 -1
  170. package/dist/fetch.js +0 -1498
  171. package/dist/fetch.js.map +0 -1
  172. package/dist/ffi.d.ts +0 -410
  173. package/dist/ffi.d.ts.map +0 -1
  174. package/dist/ffi.js +0 -1154
  175. package/dist/ffi.js.map +0 -1
  176. package/dist/format.d.ts +0 -128
  177. package/dist/format.d.ts.map +0 -1
  178. package/dist/format.js +0 -132
  179. package/dist/format.js.map +0 -1
  180. package/dist/numeric.d.ts +0 -20
  181. package/dist/numeric.d.ts.map +0 -1
  182. package/dist/numeric.js +0 -107
  183. package/dist/numeric.js.map +0 -1
  184. package/dist/paths.d.ts +0 -55
  185. package/dist/paths.d.ts.map +0 -1
  186. package/dist/paths.js +0 -87
  187. package/dist/paths.js.map +0 -1
  188. package/dist/results.d.ts +0 -495
  189. package/dist/results.d.ts.map +0 -1
  190. package/dist/results.js +0 -406
  191. package/dist/results.js.map +0 -1
  192. package/dist/transform.d.ts +0 -73
  193. package/dist/transform.d.ts.map +0 -1
  194. package/dist/transform.js +0 -533
  195. package/dist/transform.js.map +0 -1
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Verifying a pre-seeded cache entry from local blobs alone, zero network
3
+ * (`docs/guides/fetch-v1.md` §1, §6): "a pre-seeded layout has entries in
4
+ * `index.json` with no corresponding `unpacked/` directory yet; the first
5
+ * request for one verifies it against its signature exactly as a freshly
6
+ * downloaded layer would, then unpacks it." `--offline`/`resolve_installed`
7
+ * are the only callers — never `ensure`'s normal online path, which always
8
+ * has a live referrers API to ask.
9
+ *
10
+ * There is no referrers API to query here, so trust discovery is a local
11
+ * scan: every blob under `blobs/sha256/` that parses as an OCI manifest
12
+ * with the signature bundle's own `artifactType` is a *candidate* referrer
13
+ * of the platform manifest, tried the same way `dsse.ts`'s
14
+ * `verifyAnyReferrerBundle` tries referrers fetched over the network —
15
+ * stopping at the first whose signature verifies AND whose statement names
16
+ * this exact platform manifest's layer as its subject. `oras copy -r
17
+ * --to-oci-layout` is what populates these blobs when pulling from a real
18
+ * registry (guide §1); `index.json` itself carries no referrers listing (no
19
+ * such thing exists in the OCI image-layout spec), which is exactly why
20
+ * this is a scan rather than a lookup.
21
+ */
22
+ import { rm } from 'node:fs/promises';
23
+ import path from 'node:path';
24
+ import { MEDIA_TYPE_BUNDLE, PREDICATE_TYPE_ARTIFACT } from './constants.gen.js';
25
+ import { checkArtifactStatement, parseStatement, verifyBundleSignature } from './dsse.js';
26
+ import { ArtifactCorruptError } from './errors.js';
27
+ import { buildRecord, commitStaging, freshStagingDir, listLocalBlobHexes, readLocalBlob, readVerifiedRecord, unpackedDir, writeVerifiedRecord, } from './layout.js';
28
+ import { parseManifest, verifyDescriptor } from './oci.js';
29
+ import { digestOfHex, hexOfDigest, platformInfo } from './types.js';
30
+ import { measureLibrary, verifyAndUnpackLayerBytes, verifyInstalledLibrary } from './unpack.js';
31
+ /**
32
+ * Verifies and installs the platform manifest named by `manifestDigest`,
33
+ * reading every blob it needs from `blobsSourceDir`'s `blobs/sha256/` but
34
+ * always **writing** the result (the unpacked library and its
35
+ * `verified.json`) under `writeRoot` — the two differ for a read-only
36
+ * system directory (guide §1: "never written to"), where `blobsSourceDir`
37
+ * is that system dir and `writeRoot` is the user's own cache.
38
+ *
39
+ * Idempotent and cheap on a repeat call: if `writeRoot` already has a
40
+ * `verified.json` for this digest, returns it without touching
41
+ * `blobsSourceDir` again. Returns `undefined` (never throws) when this
42
+ * specific entry cannot be locally verified — a bad or incomplete
43
+ * pre-seeded blob is "not usable", not a hard failure for whatever broader
44
+ * scan is trying several candidates. The caller decides whether the
45
+ * resulting predicate's own `clickhouse_version` fits whatever request
46
+ * prompted the scan — this function verifies the entry on its own terms,
47
+ * not against any one request.
48
+ */
49
+ export async function verifyAndInstallFromLocalBlobs(blobsSourceDir, writeRoot, manifestDigest, platform, trustedKeys) {
50
+ const manifestHex = hexOfDigest(manifestDigest);
51
+ const existing = await readVerifiedRecord(unpackedDir(writeRoot, manifestHex));
52
+ if (existing !== undefined)
53
+ return existing;
54
+ try {
55
+ const manifestBytes = await readLocalBlob(blobsSourceDir, manifestHex);
56
+ if (manifestBytes === undefined)
57
+ return undefined;
58
+ verifyDescriptor({ mediaType: '', digest: manifestDigest }, manifestBytes, `manifest ${manifestDigest}`);
59
+ const manifest = parseManifest(manifestDigest, manifestBytes);
60
+ const info = platformInfo(platform);
61
+ const found = await findLocalSignature(blobsSourceDir, manifest.layer, trustedKeys);
62
+ if (found === undefined)
63
+ return undefined;
64
+ const predicate = checkArtifactStatement(found.statement, PREDICATE_TYPE_ARTIFACT, manifest.layer.digest, {
65
+ os: info.os,
66
+ arch: info.architecture,
67
+ // No `requestedSpelling`: this entry is verified on its own terms,
68
+ // not against one request — see this function's own doc comment.
69
+ });
70
+ const layerBytes = await readLocalBlob(blobsSourceDir, hexOfDigest(manifest.layer.digest));
71
+ if (layerBytes === undefined)
72
+ return undefined;
73
+ const staging = await freshStagingDir(writeRoot);
74
+ try {
75
+ const entries = await verifyAndUnpackLayerBytes(layerBytes, manifest.layer, staging);
76
+ if (!entries.some((e) => e.name === predicate.library)) {
77
+ throw new ArtifactCorruptError(`chtypes: the local layer does not contain its own predicate's library ${JSON.stringify(predicate.library)}`);
78
+ }
79
+ await verifyInstalledLibrary(path.join(staging, predicate.library), predicate.library_sha256, predicate.library_bytes);
80
+ const record = buildRecord({
81
+ platform,
82
+ predicate,
83
+ library: await measureLibrary(path.join(staging, predicate.library)),
84
+ indexDigest: null,
85
+ manifestDigest,
86
+ layerDigest: manifest.layer.digest,
87
+ bundleDigest: found.bundleDigest,
88
+ bundleManifestDigest: found.bundleManifestDigest,
89
+ signedBy: found.signedBy,
90
+ });
91
+ await writeVerifiedRecord(staging, record);
92
+ await commitStaging(staging, unpackedDir(writeRoot, manifestHex));
93
+ return record;
94
+ }
95
+ catch {
96
+ await rm(staging, { recursive: true, force: true }).catch(() => { });
97
+ return undefined;
98
+ }
99
+ }
100
+ catch {
101
+ // Any failure anywhere in this local-only verification (malformed
102
+ // blob, bad signature, wrong subject) just means this candidate is not
103
+ // usable — never a hard error, since a scan may have other candidates
104
+ // to try, and `--offline` would otherwise crash on one bad bystander
105
+ // entry in an otherwise-healthy cache.
106
+ return undefined;
107
+ }
108
+ }
109
+ /**
110
+ * Scans every local blob for one that is an OCI manifest of the signature
111
+ * bundle's `artifactType`, tries its own layer (the bundle JSON) against
112
+ * `trustedKeys`, and accepts the first whose verified statement names
113
+ * `layer`'s digest as its subject. Order is the filesystem's own
114
+ * `readdir` order — deterministic per run, immaterial to correctness since
115
+ * every candidate is checked.
116
+ */
117
+ async function findLocalSignature(blobsSourceDir, layer, trustedKeys) {
118
+ const hexes = await listLocalBlobHexes(blobsSourceDir);
119
+ for (const hex of hexes) {
120
+ const bytes = await readLocalBlob(blobsSourceDir, hex);
121
+ if (bytes === undefined)
122
+ continue;
123
+ const artifactType = readArtifactType(bytes);
124
+ if (artifactType !== MEDIA_TYPE_BUNDLE)
125
+ continue;
126
+ let candidateManifest;
127
+ try {
128
+ candidateManifest = parseManifest(digestOfHex(hex), bytes);
129
+ }
130
+ catch {
131
+ continue; // Names the bundle artifactType but is not a readable manifest — not a candidate.
132
+ }
133
+ const bundleBytes = await readLocalBlob(blobsSourceDir, hexOfDigest(candidateManifest.layer.digest));
134
+ if (bundleBytes === undefined)
135
+ continue;
136
+ const verified = verifyBundleSignature(bundleBytes, trustedKeys);
137
+ if (verified === undefined)
138
+ continue;
139
+ let statement;
140
+ try {
141
+ statement = parseStatement(verified.payload);
142
+ }
143
+ catch {
144
+ continue;
145
+ }
146
+ if (statement.subject[0]?.digest.sha256 !== hexOfDigest(layer.digest))
147
+ continue;
148
+ return { statement, signedBy: verified.signedBy, bundleDigest: candidateManifest.layer.digest, bundleManifestDigest: digestOfHex(hex) };
149
+ }
150
+ return undefined;
151
+ }
152
+ function readArtifactType(manifestBytes) {
153
+ try {
154
+ const parsed = JSON.parse(manifestBytes.toString('utf8'));
155
+ if (parsed === null || typeof parsed !== 'object')
156
+ return undefined;
157
+ const v = parsed['artifactType'];
158
+ return typeof v === 'string' ? v : undefined;
159
+ }
160
+ catch {
161
+ return undefined;
162
+ }
163
+ }
164
+ //# sourceMappingURL=localverify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localverify.js","sourceRoot":"","sources":["../../src/ocifetch/localverify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Lock schema 3 (`docs/guides/fetch-v1.md` §6, `spec/fetch-v1/schema/lock3.schema.json`):
3
+ * per declared platform, the request, the exact version and build, and the
4
+ * platform manifest/layer/bundle digests — never a hostname. Schema 1 and 2
5
+ * (v0) are refused outright, never silently reinterpreted, exactly as v0
6
+ * refuses a lock newer than it understands.
7
+ */
8
+ import { type PlatformKey } from './types.js';
9
+ export interface LockPin {
10
+ readonly version: string;
11
+ readonly build: string;
12
+ readonly manifest: string;
13
+ readonly layer: string;
14
+ readonly bundle: string;
15
+ readonly index?: string;
16
+ }
17
+ export interface LockFile {
18
+ readonly schema: 3;
19
+ readonly abi: 1;
20
+ readonly platforms: readonly PlatformKey[];
21
+ /** Keyed by the originally-requested spelling, then by platform key. */
22
+ readonly requests: Readonly<Record<string, Readonly<Record<string, LockPin>>>>;
23
+ }
24
+ export declare function emptyLock(): LockFile;
25
+ export declare function defaultLockPath(cwd?: string): string;
26
+ /**
27
+ * Validates and narrows a parsed JSON value into a `LockFile`. Any v0 lock
28
+ * (`schema: 1` or `schema: 2` in v0's own numbering) and any other
29
+ * malformed shape is `ArtifactPinnedError`, naming re-lock — `--frozen`
30
+ * reads this the same way a missing pin does (guide §6).
31
+ */
32
+ export declare function validateLock(parsed: unknown, path_: string): LockFile;
33
+ /** `undefined` when no lock file exists at `lockPath`. */
34
+ export declare function readLock(lockPath: string): Promise<LockFile | undefined>;
35
+ export declare function writeLock(lockPath: string, lock: LockFile): Promise<void>;
36
+ export declare function getPin(lock: LockFile, spelling: string, platform: PlatformKey): LockPin | undefined;
37
+ /** Returns a new lock with `pin` set for `spelling`/`platform`, adding `platform` to the declared list if new. */
38
+ export declare function withPin(lock: LockFile, spelling: string, platform: PlatformKey, pin: LockPin): LockFile;
39
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/ocifetch/lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;IAChB,QAAQ,CAAC,SAAS,EAAE,SAAS,WAAW,EAAE,CAAC;IAC3C,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;CAChF;AAID,wBAAgB,SAAS,IAAI,QAAQ,CAEpC;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAEnE;AAQD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAqErE;AAED,0DAA0D;AAC1D,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAe9E;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,GAAG,SAAS,CAEnG;AAED,kHAAkH;AAClH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,GAAG,QAAQ,CAOvG"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Lock schema 3 (`docs/guides/fetch-v1.md` §6, `spec/fetch-v1/schema/lock3.schema.json`):
3
+ * per declared platform, the request, the exact version and build, and the
4
+ * platform manifest/layer/bundle digests — never a hostname. Schema 1 and 2
5
+ * (v0) are refused outright, never silently reinterpreted, exactly as v0
6
+ * refuses a lock newer than it understands.
7
+ */
8
+ import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
9
+ import path from 'node:path';
10
+ import { randomBytes } from 'node:crypto';
11
+ import { LOCK_DEFAULT_FILE, LOCK_SCHEMA, PLATFORMS } from './constants.gen.js';
12
+ import { ArtifactPinnedError } from './errors.js';
13
+ import { isPlatformKey } from './types.js';
14
+ const DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
15
+ export function emptyLock() {
16
+ return { schema: LOCK_SCHEMA, abi: 1, platforms: [], requests: {} };
17
+ }
18
+ export function defaultLockPath(cwd = process.cwd()) {
19
+ return path.join(cwd, LOCK_DEFAULT_FILE);
20
+ }
21
+ function pinName(digest, field) {
22
+ if (!DIGEST_RE.test(digest)) {
23
+ throw new ArtifactPinnedError(`chtypes: lock pin's ${field} ${JSON.stringify(digest)} is not a sha256 digest`);
24
+ }
25
+ }
26
+ /**
27
+ * Validates and narrows a parsed JSON value into a `LockFile`. Any v0 lock
28
+ * (`schema: 1` or `schema: 2` in v0's own numbering) and any other
29
+ * malformed shape is `ArtifactPinnedError`, naming re-lock — `--frozen`
30
+ * reads this the same way a missing pin does (guide §6).
31
+ */
32
+ export function validateLock(parsed, path_) {
33
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
34
+ throw new ArtifactPinnedError(`chtypes: ${path_} is not a lock file object; re-lock with \`fetch --lock\``);
35
+ }
36
+ const doc = parsed;
37
+ const schema = doc['schema'];
38
+ if (schema !== LOCK_SCHEMA) {
39
+ throw new ArtifactPinnedError(`chtypes: ${path_} is schema ${JSON.stringify(schema)}, not v1's schema ${LOCK_SCHEMA}` +
40
+ (schema === 1 || schema === 2 ? ' (a v0 lock is never reinterpreted)' : '') +
41
+ '; re-lock with `fetch --lock`');
42
+ }
43
+ if (doc['abi'] !== 1) {
44
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s abi is ${JSON.stringify(doc['abi'])}, not 1; re-lock with \`fetch --lock\``);
45
+ }
46
+ const platformsRaw = doc['platforms'];
47
+ if (!Array.isArray(platformsRaw) || platformsRaw.length === 0) {
48
+ throw new ArtifactPinnedError(`chtypes: ${path_} names no platforms; re-lock with \`fetch --lock\``);
49
+ }
50
+ const platforms = [];
51
+ for (const p of platformsRaw) {
52
+ if (typeof p !== 'string' || !isPlatformKey(p)) {
53
+ throw new ArtifactPinnedError(`chtypes: ${path_} names an unknown platform ${JSON.stringify(p)}`);
54
+ }
55
+ platforms.push(p);
56
+ }
57
+ const requestsRaw = doc['requests'];
58
+ if (requestsRaw === null || typeof requestsRaw !== 'object' || Array.isArray(requestsRaw)) {
59
+ throw new ArtifactPinnedError(`chtypes: ${path_} has no readable requests table`);
60
+ }
61
+ const requests = {};
62
+ for (const [spelling, byPlatform] of Object.entries(requestsRaw)) {
63
+ if (byPlatform === null || typeof byPlatform !== 'object' || Array.isArray(byPlatform)) {
64
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s request ${JSON.stringify(spelling)} is malformed`);
65
+ }
66
+ const row = {};
67
+ for (const [platform, pinRaw] of Object.entries(byPlatform)) {
68
+ if (!isPlatformKey(platform) || !platforms.includes(platform)) {
69
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s request ${JSON.stringify(spelling)} names platform ${JSON.stringify(platform)}, not in its own platforms list`);
70
+ }
71
+ if (pinRaw === null || typeof pinRaw !== 'object' || Array.isArray(pinRaw)) {
72
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s pin for ${spelling}/${platform} is malformed`);
73
+ }
74
+ const p = pinRaw;
75
+ const version = p['version'];
76
+ const build = p['build'];
77
+ const manifest = p['manifest'];
78
+ const layer = p['layer'];
79
+ const bundle = p['bundle'];
80
+ const index = p['index'];
81
+ if (typeof version !== 'string' || typeof build !== 'string') {
82
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s pin for ${spelling}/${platform} is missing version or build`);
83
+ }
84
+ if (typeof manifest !== 'string' || typeof layer !== 'string' || typeof bundle !== 'string') {
85
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s pin for ${spelling}/${platform} is missing a digest`);
86
+ }
87
+ pinName(manifest, 'manifest');
88
+ pinName(layer, 'layer');
89
+ pinName(bundle, 'bundle');
90
+ if (index !== undefined) {
91
+ if (typeof index !== 'string')
92
+ throw new ArtifactPinnedError(`chtypes: ${path_}'s pin for ${spelling}/${platform} has a non-string index`);
93
+ pinName(index, 'index');
94
+ }
95
+ row[platform] = { version, build, manifest, layer, bundle, ...(index !== undefined ? { index } : {}) };
96
+ }
97
+ requests[spelling] = row;
98
+ }
99
+ return { schema: LOCK_SCHEMA, abi: 1, platforms, requests };
100
+ }
101
+ /** `undefined` when no lock file exists at `lockPath`. */
102
+ export async function readLock(lockPath) {
103
+ let raw;
104
+ try {
105
+ raw = await readFile(lockPath, 'utf8');
106
+ }
107
+ catch (err) {
108
+ if (err.code === 'ENOENT')
109
+ return undefined;
110
+ throw err;
111
+ }
112
+ let parsed;
113
+ try {
114
+ parsed = JSON.parse(raw);
115
+ }
116
+ catch (err) {
117
+ throw new ArtifactPinnedError(`chtypes: ${lockPath} is not valid JSON: ${err.message}`);
118
+ }
119
+ return validateLock(parsed, lockPath);
120
+ }
121
+ export async function writeLock(lockPath, lock) {
122
+ const serializable = { schema: LOCK_SCHEMA, abi: 1, platforms: lock.platforms, requests: lock.requests };
123
+ await mkdir(path.dirname(lockPath), { recursive: true });
124
+ const tmp = `${lockPath}.tmp-${process.pid}-${randomBytes(6).toString('hex')}`;
125
+ await writeFile(tmp, `${JSON.stringify(serializable, null, 2)}\n`);
126
+ await rename(tmp, lockPath);
127
+ }
128
+ export function getPin(lock, spelling, platform) {
129
+ return lock.requests[spelling]?.[platform];
130
+ }
131
+ /** Returns a new lock with `pin` set for `spelling`/`platform`, adding `platform` to the declared list if new. */
132
+ export function withPin(lock, spelling, platform, pin) {
133
+ // Platforms are kept in the contract's own order (`PLATFORMS`), never
134
+ // insertion order, so two writers that pinned the same set agree byte for byte.
135
+ const unsorted = lock.platforms.includes(platform) ? lock.platforms : [...lock.platforms, platform];
136
+ const platforms = PLATFORMS.map((p) => p.key).filter((k) => unsorted.includes(k));
137
+ const row = { ...(lock.requests[spelling] ?? {}), [platform]: pin };
138
+ return { ...lock, platforms, requests: { ...lock.requests, [spelling]: row } };
139
+ }
140
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/ocifetch/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Resolve (`docs/guides/fetch-v1.md` §3): the version spelling check, the
3
+ * multi-base tag GET returning an OCI image index, platform selection, and
4
+ * by-digest fetches (manifests and blobs) with their own integrity check
5
+ * (size + sha256 against the descriptor that named them — independent of,
6
+ * and prior to, the trust check in `dsse.ts`).
7
+ *
8
+ * Every by-digest fetch tries every configured base in order (guide §7 A5):
9
+ * a 404 moves to the next base, and on the **last** base a 404 is retried
10
+ * within the normal budget before `CHTYPES_SOURCE_UNREACHABLE` ("a listed
11
+ * digest that 404s is a host fault", never `UNPUBLISHED` — that verdict is
12
+ * for the tag alone).
13
+ */
14
+ import { type RequestOptions } from './http.js';
15
+ import { type PlatformKey } from './types.js';
16
+ /**
17
+ * Refuses the two documented spelling mistakes (a `v` prefix, a
18
+ * `-lts`/`-stable` channel suffix) before any network call (guide §3). A
19
+ * spelling that is simply not numeric is NOT refused here: the tag lookup
20
+ * answers for it (`CHTYPES_ARTIFACT_UNPUBLISHED` when nothing matches), the
21
+ * same path any arbitrary OCI tag takes — and the conformance trees publish
22
+ * symbolic tags such as `t-untrusted-key`. `SPELLING_REGEX` is a positive
23
+ * pattern used elsewhere (`versionWithinRequest`) to decide whether a
24
+ * resolved predicate's version is compared against the request at all.
25
+ */
26
+ export declare function checkSpelling(spelling: string): void;
27
+ /** A descriptor's `size` is absent when it comes from a lock pin (schema 3 stores digests only, never sizes). */
28
+ export interface Descriptor {
29
+ readonly mediaType: string;
30
+ readonly digest: string;
31
+ readonly size?: number;
32
+ }
33
+ export interface ManifestInfo {
34
+ readonly digest: string;
35
+ readonly bytes: Buffer;
36
+ readonly layer: Descriptor;
37
+ readonly config: Descriptor | undefined;
38
+ }
39
+ /**
40
+ * Parses an OCI image manifest's layer (exactly one, required) and config
41
+ * descriptors. `CHTYPES_SOURCE_INCOMPATIBLE` is reserved for a recognized-but-wrong
42
+ * media type (guide §3); unparseable JSON or a manifest that disagrees with
43
+ * its own shape (not exactly one layer) is `CORRUPT` — "a release that
44
+ * disagrees with itself", the same bucket a hash mismatch falls into.
45
+ */
46
+ export declare function parseManifest(digest: string, bytes: Buffer): ManifestInfo;
47
+ /**
48
+ * Verifies fetched bytes against the descriptor that named them (OCI content
49
+ * addressing — independent of signature trust, and checked **before** any
50
+ * decompression or JSON parsing of untrusted content). `size` is checked
51
+ * only when the descriptor carries one — a lock pin (schema 3) has a digest
52
+ * only, never a size. A mismatch is `CORRUPT`: "any hash mismatch along the
53
+ * chain" (the same verdict v0's `ArtifactCorruptError` names), never
54
+ * `SOURCE_INCOMPATIBLE`, which is reserved for a wrong media type.
55
+ */
56
+ export declare function verifyDescriptor(descriptor: Descriptor, bytes: Buffer, what: string): void;
57
+ /**
58
+ * The same check as `verifyDescriptor`, for a caller that streamed the bytes
59
+ * through a hasher rather than holding them in one `Buffer` — `unpack.ts`'s
60
+ * layer download, which is never buffered whole in memory.
61
+ */
62
+ export declare function verifyDigestAndSize(descriptor: Descriptor, actualSha256Hex: string, actualSize: number, what: string): void;
63
+ /**
64
+ * `GET manifests/<digest>`, tried across every base (guide §6: `--frozen`'s
65
+ * manifest fetch; also `fetchSigned`'s referrer manifest hop), always with
66
+ * the manifest `Accept` header (delivery-side review).
67
+ */
68
+ export declare function fetchManifestBytesByDigest(bases: readonly string[], descriptor: Descriptor, options: RequestOptions): Promise<Buffer>;
69
+ /** `GET blobs/<digest>`, tried across every base, fully buffered — a bundle, never the (potentially huge) library layer. */
70
+ export declare function fetchBlobBytesByDigest(bases: readonly string[], descriptor: Descriptor, options: RequestOptions): Promise<Buffer>;
71
+ export interface ByteSink {
72
+ reset(): void;
73
+ write(chunk: Buffer): void;
74
+ }
75
+ /**
76
+ * `GET blobs/<digest>` straight into `sink` (`unpack.ts`'s hashing temp
77
+ * file) — the library layer, which is never buffered whole in memory. Tries
78
+ * every base in order, same as every other by-digest fetch in this module. A
79
+ * `file://` base has no streaming primitive of its own, so it is read whole
80
+ * and written to the sink in one call — acceptable because fixture layers
81
+ * are small test artifacts, never the multi-hundred-megabyte real ones.
82
+ */
83
+ export declare function fetchBlobToSink(bases: readonly string[], descriptor: Descriptor, options: RequestOptions, sink: ByteSink): Promise<void>;
84
+ /** `fetchManifestBytesByDigest` plus parsing — `--frozen`'s and `fetchSigned`'s "give me this manifest" primitive. */
85
+ export declare function fetchManifestByDigest(bases: readonly string[], digest: string, options: RequestOptions): Promise<ManifestInfo>;
86
+ export interface IndexResolveResult {
87
+ readonly repositoryRoot: string;
88
+ readonly indexDigest: string;
89
+ readonly indexBytes: Buffer;
90
+ readonly manifest: ManifestInfo;
91
+ }
92
+ /**
93
+ * `GET manifests/<spelling>` across `bases` in order (guide §3, §7 A5's tag
94
+ * rule: a tag 404 moves to the next base, and every base 404ing is
95
+ * `UNPUBLISHED`), then the platform's manifest by digest across every base
96
+ * (mirrors may carry the same tag pointing at the same digest, so a base
97
+ * that served the index is not the only one asked for its blobs).
98
+ */
99
+ export declare function resolveTag(bases: readonly string[], spelling: string, platform: PlatformKey, options: RequestOptions): Promise<IndexResolveResult>;
100
+ //# sourceMappingURL=oci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oci.d.ts","sourceRoot":"","sources":["../../src/ocifetch/oci.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAAE,KAAK,cAAc,EAA+C,MAAM,WAAW,CAAC;AAC7F,OAAO,EAAiE,KAAK,WAAW,EAAgB,MAAM,YAAY,CAAC;AAE3H;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAOpD;AAED,iHAAiH;AACjH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;CACzC;AAmCD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAqBzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAO3H;AAmDD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,4HAA4H;AAC5H,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B9I;AAED,sHAAsH;AACtH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAGpI;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAiF7B"}