@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.
- package/CHANGELOG.md +26 -0
- package/README.md +34 -38
- package/dist/abi1/buildinfo.d.ts +40 -0
- package/dist/abi1/buildinfo.d.ts.map +1 -0
- package/dist/abi1/buildinfo.js +83 -0
- package/dist/abi1/buildinfo.js.map +1 -0
- package/dist/abi1/calls.gen.d.ts +55 -0
- package/dist/abi1/calls.gen.d.ts.map +1 -0
- package/dist/abi1/calls.gen.js +110 -0
- package/dist/abi1/calls.gen.js.map +1 -0
- package/dist/abi1/decls.gen.d.ts +115 -0
- package/dist/abi1/decls.gen.d.ts.map +1 -0
- package/dist/abi1/decls.gen.js +1613 -0
- package/dist/abi1/decls.gen.js.map +1 -0
- package/dist/abi1/errmap.gen.d.ts +18 -0
- package/dist/abi1/errmap.gen.d.ts.map +1 -0
- package/dist/abi1/errmap.gen.js +66 -0
- package/dist/abi1/errmap.gen.js.map +1 -0
- package/dist/abi1/errors.d.ts +107 -0
- package/dist/abi1/errors.d.ts.map +1 -0
- package/dist/abi1/errors.js +134 -0
- package/dist/abi1/errors.js.map +1 -0
- package/dist/abi1/handles.d.ts +31 -0
- package/dist/abi1/handles.d.ts.map +1 -0
- package/dist/abi1/handles.js +76 -0
- package/dist/abi1/handles.js.map +1 -0
- package/dist/abi1/index.d.ts +17 -0
- package/dist/abi1/index.d.ts.map +1 -0
- package/dist/abi1/index.js +17 -0
- package/dist/abi1/index.js.map +1 -0
- package/dist/abi1/libc.d.ts +54 -0
- package/dist/abi1/libc.d.ts.map +1 -0
- package/dist/abi1/libc.gen.d.ts +12 -0
- package/dist/abi1/libc.gen.d.ts.map +1 -0
- package/dist/abi1/libc.gen.js +75 -0
- package/dist/abi1/libc.gen.js.map +1 -0
- package/dist/abi1/libc.js +109 -0
- package/dist/abi1/libc.js.map +1 -0
- package/dist/abi1/loader.d.ts +99 -0
- package/dist/abi1/loader.d.ts.map +1 -0
- package/dist/abi1/loader.js +261 -0
- package/dist/abi1/loader.js.map +1 -0
- package/dist/abi1/raw.d.ts +104 -0
- package/dist/abi1/raw.d.ts.map +1 -0
- package/dist/abi1/raw.js +296 -0
- package/dist/abi1/raw.js.map +1 -0
- package/dist/abi1/strictjson.d.ts +19 -0
- package/dist/abi1/strictjson.d.ts.map +1 -0
- package/dist/abi1/strictjson.js +78 -0
- package/dist/abi1/strictjson.js.map +1 -0
- package/dist/abi1/vocab.gen.d.ts +169 -0
- package/dist/abi1/vocab.gen.d.ts.map +1 -0
- package/dist/abi1/vocab.gen.js +306 -0
- package/dist/abi1/vocab.gen.js.map +1 -0
- package/dist/cli.d.ts +25 -26
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +206 -218
- package/dist/cli.js.map +1 -1
- package/dist/documents.d.ts +195 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +389 -0
- package/dist/documents.js.map +1 -0
- package/dist/env.d.ts +16 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +57 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +19 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -23
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +11 -89
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +16 -180
- package/dist/json.js.map +1 -1
- package/dist/library.d.ts +53 -309
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +77 -315
- package/dist/library.js.map +1 -1
- package/dist/ocifetch/constants.gen.d.ts +84 -0
- package/dist/ocifetch/constants.gen.d.ts.map +1 -0
- package/dist/ocifetch/constants.gen.js +92 -0
- package/dist/ocifetch/constants.gen.js.map +1 -0
- package/dist/ocifetch/dsse.d.ts +114 -0
- package/dist/ocifetch/dsse.d.ts.map +1 -0
- package/dist/ocifetch/dsse.js +331 -0
- package/dist/ocifetch/dsse.js.map +1 -0
- package/dist/ocifetch/ensure.d.ts +65 -0
- package/dist/ocifetch/ensure.d.ts.map +1 -0
- package/dist/ocifetch/ensure.js +775 -0
- package/dist/ocifetch/ensure.js.map +1 -0
- package/dist/ocifetch/errors.d.ts +92 -0
- package/dist/ocifetch/errors.d.ts.map +1 -0
- package/dist/ocifetch/errors.js +101 -0
- package/dist/ocifetch/errors.js.map +1 -0
- package/dist/ocifetch/goldens.d.ts +44 -0
- package/dist/ocifetch/goldens.d.ts.map +1 -0
- package/dist/ocifetch/goldens.js +62 -0
- package/dist/ocifetch/goldens.js.map +1 -0
- package/dist/ocifetch/http.d.ts +124 -0
- package/dist/ocifetch/http.d.ts.map +1 -0
- package/dist/ocifetch/http.js +549 -0
- package/dist/ocifetch/http.js.map +1 -0
- package/dist/ocifetch/index.d.ts +17 -0
- package/dist/ocifetch/index.d.ts.map +1 -0
- package/dist/ocifetch/index.js +14 -0
- package/dist/ocifetch/index.js.map +1 -0
- package/dist/ocifetch/layout.d.ts +126 -0
- package/dist/ocifetch/layout.d.ts.map +1 -0
- package/dist/ocifetch/layout.js +375 -0
- package/dist/ocifetch/layout.js.map +1 -0
- package/dist/ocifetch/localverify.d.ts +43 -0
- package/dist/ocifetch/localverify.d.ts.map +1 -0
- package/dist/ocifetch/localverify.js +164 -0
- package/dist/ocifetch/localverify.js.map +1 -0
- package/dist/ocifetch/lock.d.ts +39 -0
- package/dist/ocifetch/lock.d.ts.map +1 -0
- package/dist/ocifetch/lock.js +140 -0
- package/dist/ocifetch/lock.js.map +1 -0
- package/dist/ocifetch/oci.d.ts +100 -0
- package/dist/ocifetch/oci.d.ts.map +1 -0
- package/dist/ocifetch/oci.js +323 -0
- package/dist/ocifetch/oci.js.map +1 -0
- package/dist/ocifetch/referrers.d.ts +55 -0
- package/dist/ocifetch/referrers.d.ts.map +1 -0
- package/dist/ocifetch/referrers.js +132 -0
- package/dist/ocifetch/referrers.js.map +1 -0
- package/dist/ocifetch/types.d.ts +167 -0
- package/dist/ocifetch/types.d.ts.map +1 -0
- package/dist/ocifetch/types.js +88 -0
- package/dist/ocifetch/types.js.map +1 -0
- package/dist/ocifetch/unpack.d.ts +55 -0
- package/dist/ocifetch/unpack.d.ts.map +1 -0
- package/dist/ocifetch/unpack.js +205 -0
- package/dist/ocifetch/unpack.js.map +1 -0
- package/dist/registry.d.ts +38 -387
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +94 -819
- package/dist/registry.js.map +1 -1
- package/dist/schema.d.ts +77 -588
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +87 -549
- package/dist/schema.js.map +1 -1
- package/dist/settings.d.ts +27 -36
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +75 -25
- package/dist/settings.js.map +1 -1
- package/dist/setup.d.ts +37 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +60 -0
- package/dist/setup.js.map +1 -0
- package/dist/tar.d.ts +27 -11
- package/dist/tar.d.ts.map +1 -1
- package/dist/tar.js +54 -32
- package/dist/tar.js.map +1 -1
- package/package.json +2 -2
- package/dist/discover.d.ts +0 -142
- package/dist/discover.d.ts.map +0 -1
- package/dist/discover.js +0 -288
- package/dist/discover.js.map +0 -1
- package/dist/error-codes.d.ts +0 -80
- package/dist/error-codes.d.ts.map +0 -1
- package/dist/error-codes.js +0 -139
- package/dist/error-codes.js.map +0 -1
- package/dist/errors.d.ts +0 -284
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -321
- package/dist/errors.js.map +0 -1
- package/dist/fetch.d.ts +0 -382
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js +0 -1498
- package/dist/fetch.js.map +0 -1
- package/dist/ffi.d.ts +0 -410
- package/dist/ffi.d.ts.map +0 -1
- package/dist/ffi.js +0 -1154
- package/dist/ffi.js.map +0 -1
- package/dist/format.d.ts +0 -128
- package/dist/format.d.ts.map +0 -1
- package/dist/format.js +0 -132
- package/dist/format.js.map +0 -1
- package/dist/numeric.d.ts +0 -20
- package/dist/numeric.d.ts.map +0 -1
- package/dist/numeric.js +0 -107
- package/dist/numeric.js.map +0 -1
- package/dist/paths.d.ts +0 -55
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js +0 -87
- package/dist/paths.js.map +0 -1
- package/dist/results.d.ts +0 -495
- package/dist/results.d.ts.map +0 -1
- package/dist/results.js +0 -406
- package/dist/results.js.map +0 -1
- package/dist/transform.d.ts +0 -73
- package/dist/transform.d.ts.map +0 -1
- package/dist/transform.js +0 -533
- package/dist/transform.js.map +0 -1
|
@@ -0,0 +1,323 @@
|
|
|
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 { createHash } from 'node:crypto';
|
|
15
|
+
import { asString, field, items, parseJsonValue } from '../json.js';
|
|
16
|
+
import { MANIFEST_MAX_BYTES, MAX_UNPACKED_BYTES, MEDIA_TYPE_INDEX, MEDIA_TYPE_MANIFEST, SPELLING_REFUSE_HINT_REGEX } from './constants.gen.js';
|
|
17
|
+
import { ArtifactCorruptError, ArtifactUnpublishedError, SourceIncompatibleError, SourceUnreachableError } from './errors.js';
|
|
18
|
+
import { readFileUrl, requestBuffered, requestToSink } from './http.js';
|
|
19
|
+
import { digestOfHex, endpointUrl, hexOfDigest, MANIFEST_ACCEPT_HEADER, platformInfo } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Refuses the two documented spelling mistakes (a `v` prefix, a
|
|
22
|
+
* `-lts`/`-stable` channel suffix) before any network call (guide §3). A
|
|
23
|
+
* spelling that is simply not numeric is NOT refused here: the tag lookup
|
|
24
|
+
* answers for it (`CHTYPES_ARTIFACT_UNPUBLISHED` when nothing matches), the
|
|
25
|
+
* same path any arbitrary OCI tag takes — and the conformance trees publish
|
|
26
|
+
* symbolic tags such as `t-untrusted-key`. `SPELLING_REGEX` is a positive
|
|
27
|
+
* pattern used elsewhere (`versionWithinRequest`) to decide whether a
|
|
28
|
+
* resolved predicate's version is compared against the request at all.
|
|
29
|
+
*/
|
|
30
|
+
export function checkSpelling(spelling) {
|
|
31
|
+
if (new RegExp(SPELLING_REFUSE_HINT_REGEX).test(spelling)) {
|
|
32
|
+
throw new Error(`chtypes: ${JSON.stringify(spelling)} is not a v1 version spelling (no "v" prefix, no "-lts"/"-stable" suffix); ` +
|
|
33
|
+
'use the bare version, e.g. "26.8" or "26.8.15.10"');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** A `GET …/manifests/<ref>` (the tag resolve) — always carries the manifest `Accept` header (delivery-side review: our host ignores it, a mirror may need it). */
|
|
37
|
+
async function getJsonAt(url, maxBytes, options) {
|
|
38
|
+
const res = url.startsWith('file:')
|
|
39
|
+
? await readFileUrl(url, maxBytes)
|
|
40
|
+
: await requestBuffered(url, { ...options, maxBytes, headers: { ...options.headers, accept: MANIFEST_ACCEPT_HEADER } });
|
|
41
|
+
if (res.status !== 200)
|
|
42
|
+
return { status: res.status, body: res.body, json: null };
|
|
43
|
+
const json = parseJsonValue(res.body);
|
|
44
|
+
return { status: res.status, body: res.body, json };
|
|
45
|
+
}
|
|
46
|
+
function descriptorField(json, key) {
|
|
47
|
+
const d = field(json, key);
|
|
48
|
+
if (d === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
const digest = asString(field(d, 'digest'));
|
|
51
|
+
if (digest === '')
|
|
52
|
+
return undefined;
|
|
53
|
+
return { mediaType: asString(field(d, 'mediaType')), digest, size: numberField(d, 'size') };
|
|
54
|
+
}
|
|
55
|
+
function numberField(json, key) {
|
|
56
|
+
const v = field(json, key);
|
|
57
|
+
if (v === undefined || v.kind !== 'number')
|
|
58
|
+
return 0;
|
|
59
|
+
const n = Number(v.raw.toString('utf8'));
|
|
60
|
+
return Number.isFinite(n) ? n : 0;
|
|
61
|
+
}
|
|
62
|
+
function sha256Hex(buf) {
|
|
63
|
+
return createHash('sha256').update(buf).digest('hex');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Parses an OCI image manifest's layer (exactly one, required) and config
|
|
67
|
+
* descriptors. `CHTYPES_SOURCE_INCOMPATIBLE` is reserved for a recognized-but-wrong
|
|
68
|
+
* media type (guide §3); unparseable JSON or a manifest that disagrees with
|
|
69
|
+
* its own shape (not exactly one layer) is `CORRUPT` — "a release that
|
|
70
|
+
* disagrees with itself", the same bucket a hash mismatch falls into.
|
|
71
|
+
*/
|
|
72
|
+
export function parseManifest(digest, bytes) {
|
|
73
|
+
const json = parseJsonValue(bytes);
|
|
74
|
+
if (json === null)
|
|
75
|
+
throw new ArtifactCorruptError(`chtypes: manifest ${digest} is not valid JSON`);
|
|
76
|
+
const mediaType = asString(field(json, 'mediaType'));
|
|
77
|
+
if (mediaType !== '' && mediaType !== MEDIA_TYPE_MANIFEST) {
|
|
78
|
+
throw new SourceIncompatibleError(`chtypes: manifest ${digest} has mediaType ${JSON.stringify(mediaType)}, not ${MEDIA_TYPE_MANIFEST}`);
|
|
79
|
+
}
|
|
80
|
+
const layers = items(field(json, 'layers'));
|
|
81
|
+
if (layers.length !== 1) {
|
|
82
|
+
throw new ArtifactCorruptError(`chtypes: manifest ${digest} has ${layers.length} layers, expected exactly 1`);
|
|
83
|
+
}
|
|
84
|
+
const layerJson = layers[0];
|
|
85
|
+
const layerDigest = asString(field(layerJson, 'digest'));
|
|
86
|
+
if (layerDigest === '')
|
|
87
|
+
throw new ArtifactCorruptError(`chtypes: manifest ${digest}'s layer has no digest`);
|
|
88
|
+
const layer = {
|
|
89
|
+
mediaType: asString(field(layerJson, 'mediaType')),
|
|
90
|
+
digest: layerDigest,
|
|
91
|
+
size: numberField(layerJson, 'size'),
|
|
92
|
+
};
|
|
93
|
+
const config = descriptorField(json, 'config');
|
|
94
|
+
return { digest, bytes, layer, config };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Verifies fetched bytes against the descriptor that named them (OCI content
|
|
98
|
+
* addressing — independent of signature trust, and checked **before** any
|
|
99
|
+
* decompression or JSON parsing of untrusted content). `size` is checked
|
|
100
|
+
* only when the descriptor carries one — a lock pin (schema 3) has a digest
|
|
101
|
+
* only, never a size. A mismatch is `CORRUPT`: "any hash mismatch along the
|
|
102
|
+
* chain" (the same verdict v0's `ArtifactCorruptError` names), never
|
|
103
|
+
* `SOURCE_INCOMPATIBLE`, which is reserved for a wrong media type.
|
|
104
|
+
*/
|
|
105
|
+
export function verifyDescriptor(descriptor, bytes, what) {
|
|
106
|
+
verifyDigestAndSize(descriptor, sha256Hex(bytes), bytes.length, what);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The same check as `verifyDescriptor`, for a caller that streamed the bytes
|
|
110
|
+
* through a hasher rather than holding them in one `Buffer` — `unpack.ts`'s
|
|
111
|
+
* layer download, which is never buffered whole in memory.
|
|
112
|
+
*/
|
|
113
|
+
export function verifyDigestAndSize(descriptor, actualSha256Hex, actualSize, what) {
|
|
114
|
+
if (descriptor.size !== undefined && actualSize !== descriptor.size) {
|
|
115
|
+
throw new ArtifactCorruptError(`chtypes: ${what} is ${actualSize} bytes, descriptor named ${descriptor.size}`);
|
|
116
|
+
}
|
|
117
|
+
if (actualSha256Hex !== hexOfDigest(descriptor.digest)) {
|
|
118
|
+
throw new ArtifactCorruptError(`chtypes: ${what}'s sha256 does not match its own descriptor`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function fetchByDigestAcrossBases(bases, pathFor, descriptor, what, defaultMaxBytes, options, extraHeaders) {
|
|
122
|
+
if (bases.length === 0)
|
|
123
|
+
throw new Error('chtypes: no base URLs configured');
|
|
124
|
+
let lastUnreachable;
|
|
125
|
+
for (let i = 0; i < bases.length; i++) {
|
|
126
|
+
const base = bases[i];
|
|
127
|
+
const isLast = i === bases.length - 1;
|
|
128
|
+
const url = endpointUrl(base, pathFor(descriptor.digest));
|
|
129
|
+
const maxBytes = descriptor.size ?? defaultMaxBytes;
|
|
130
|
+
let res;
|
|
131
|
+
try {
|
|
132
|
+
res = url.startsWith('file:')
|
|
133
|
+
? await readFileUrl(url, maxBytes)
|
|
134
|
+
: await requestBuffered(url, {
|
|
135
|
+
...options,
|
|
136
|
+
maxBytes,
|
|
137
|
+
retryOn404: isLast,
|
|
138
|
+
headers: { ...options.headers, ...extraHeaders },
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
// A temporary error (guide §2: a timeout, a 5xx exhausted, a dead
|
|
143
|
+
// host) moves to the next base — never a verification failure, which
|
|
144
|
+
// propagates immediately (`mirror-no-failover-on-verify-fail`).
|
|
145
|
+
if (err instanceof SourceUnreachableError && !isLast) {
|
|
146
|
+
lastUnreachable = err;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
if (res.status === 404)
|
|
152
|
+
continue;
|
|
153
|
+
if (res.status !== 200)
|
|
154
|
+
throw new SourceUnreachableError(`chtypes: ${url} returned status ${res.status}`);
|
|
155
|
+
verifyDescriptor(descriptor, res.body, what);
|
|
156
|
+
return res.body;
|
|
157
|
+
}
|
|
158
|
+
if (lastUnreachable !== undefined)
|
|
159
|
+
throw lastUnreachable;
|
|
160
|
+
// Unreachable through an ordinary persistent 404 on the last base: that
|
|
161
|
+
// already throws `SourceUnreachableError` from inside `requestBuffered`
|
|
162
|
+
// (via `retryOn404`) before control returns here. This covers only an
|
|
163
|
+
// empty `bases` list.
|
|
164
|
+
throw new SourceUnreachableError(`chtypes: ${what} (${descriptor.digest}) was not found on any configured base`);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* `GET manifests/<digest>`, tried across every base (guide §6: `--frozen`'s
|
|
168
|
+
* manifest fetch; also `fetchSigned`'s referrer manifest hop), always with
|
|
169
|
+
* the manifest `Accept` header (delivery-side review).
|
|
170
|
+
*/
|
|
171
|
+
export async function fetchManifestBytesByDigest(bases, descriptor, options) {
|
|
172
|
+
if (descriptor.size !== undefined && descriptor.size > MANIFEST_MAX_BYTES) {
|
|
173
|
+
throw new ArtifactCorruptError(`chtypes: manifest ${descriptor.digest}'s descriptor names ${descriptor.size} bytes, over the ${MANIFEST_MAX_BYTES}-byte manifest cap`);
|
|
174
|
+
}
|
|
175
|
+
return fetchByDigestAcrossBases(bases, (d) => `/manifests/${d}`, descriptor, `manifest ${descriptor.digest}`, MANIFEST_MAX_BYTES, options, {
|
|
176
|
+
accept: MANIFEST_ACCEPT_HEADER,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/** `GET blobs/<digest>`, tried across every base, fully buffered — a bundle, never the (potentially huge) library layer. */
|
|
180
|
+
export async function fetchBlobBytesByDigest(bases, descriptor, options) {
|
|
181
|
+
return fetchByDigestAcrossBases(bases, (d) => `/blobs/${d}`, descriptor, `blob ${descriptor.digest}`, MAX_UNPACKED_BYTES, options);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* `GET blobs/<digest>` straight into `sink` (`unpack.ts`'s hashing temp
|
|
185
|
+
* file) — the library layer, which is never buffered whole in memory. Tries
|
|
186
|
+
* every base in order, same as every other by-digest fetch in this module. A
|
|
187
|
+
* `file://` base has no streaming primitive of its own, so it is read whole
|
|
188
|
+
* and written to the sink in one call — acceptable because fixture layers
|
|
189
|
+
* are small test artifacts, never the multi-hundred-megabyte real ones.
|
|
190
|
+
*/
|
|
191
|
+
export async function fetchBlobToSink(bases, descriptor, options, sink) {
|
|
192
|
+
if (bases.length === 0)
|
|
193
|
+
throw new Error('chtypes: no base URLs configured');
|
|
194
|
+
const maxBytes = descriptor.size ?? MAX_UNPACKED_BYTES;
|
|
195
|
+
let lastUnreachable;
|
|
196
|
+
for (let i = 0; i < bases.length; i++) {
|
|
197
|
+
const base = bases[i];
|
|
198
|
+
const isLast = i === bases.length - 1;
|
|
199
|
+
const url = endpointUrl(base, `/blobs/${descriptor.digest}`);
|
|
200
|
+
try {
|
|
201
|
+
if (url.startsWith('file:')) {
|
|
202
|
+
const res = await readFileUrl(url, maxBytes);
|
|
203
|
+
if (res.status === 404)
|
|
204
|
+
continue;
|
|
205
|
+
if (res.status !== 200)
|
|
206
|
+
throw new SourceUnreachableError(`chtypes: ${url} returned status ${res.status}`);
|
|
207
|
+
sink.reset();
|
|
208
|
+
sink.write(res.body);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const res = await requestToSink(url, { ...options, maxBytes, retryOn404: isLast }, sink);
|
|
212
|
+
if (res.status === 404)
|
|
213
|
+
continue;
|
|
214
|
+
if (res.status !== 200 && res.status !== 206)
|
|
215
|
+
throw new SourceUnreachableError(`chtypes: ${url} returned status ${res.status}`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
if (err instanceof SourceUnreachableError && !isLast) {
|
|
220
|
+
lastUnreachable = err;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (lastUnreachable !== undefined)
|
|
227
|
+
throw lastUnreachable;
|
|
228
|
+
throw new SourceUnreachableError(`chtypes: blob ${descriptor.digest} was not found on any configured base`);
|
|
229
|
+
}
|
|
230
|
+
/** `fetchManifestBytesByDigest` plus parsing — `--frozen`'s and `fetchSigned`'s "give me this manifest" primitive. */
|
|
231
|
+
export async function fetchManifestByDigest(bases, digest, options) {
|
|
232
|
+
const bytes = await fetchManifestBytesByDigest(bases, { mediaType: MEDIA_TYPE_MANIFEST, digest }, options);
|
|
233
|
+
return parseManifest(digest, bytes);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* `GET manifests/<spelling>` across `bases` in order (guide §3, §7 A5's tag
|
|
237
|
+
* rule: a tag 404 moves to the next base, and every base 404ing is
|
|
238
|
+
* `UNPUBLISHED`), then the platform's manifest by digest across every base
|
|
239
|
+
* (mirrors may carry the same tag pointing at the same digest, so a base
|
|
240
|
+
* that served the index is not the only one asked for its blobs).
|
|
241
|
+
*/
|
|
242
|
+
export async function resolveTag(bases, spelling, platform, options) {
|
|
243
|
+
checkSpelling(spelling);
|
|
244
|
+
if (bases.length === 0)
|
|
245
|
+
throw new Error('chtypes: no base URLs configured');
|
|
246
|
+
const info = platformInfo(platform);
|
|
247
|
+
const triedBases = [];
|
|
248
|
+
for (let baseIndex = 0; baseIndex < bases.length; baseIndex++) {
|
|
249
|
+
const base = bases[baseIndex];
|
|
250
|
+
const isLastBase = baseIndex === bases.length - 1;
|
|
251
|
+
const url = endpointUrl(base, `/manifests/${spelling}`);
|
|
252
|
+
let status;
|
|
253
|
+
let body;
|
|
254
|
+
let json;
|
|
255
|
+
try {
|
|
256
|
+
({ status, body, json } = await getJsonAt(url, MANIFEST_MAX_BYTES, options));
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
// A temporary error (guide §2: a timeout, a 5xx exhausted, a dead
|
|
260
|
+
// host) moves to the next base, same as a tag 404 — never a
|
|
261
|
+
// verification failure, which propagates immediately.
|
|
262
|
+
if (err instanceof SourceUnreachableError && !isLastBase) {
|
|
263
|
+
triedBases.push(base);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
throw err;
|
|
267
|
+
}
|
|
268
|
+
if (status === 404) {
|
|
269
|
+
triedBases.push(base);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (status !== 200) {
|
|
273
|
+
// A persistent retryable status on the last base already threw from
|
|
274
|
+
// inside `requestBuffered`; anything reaching here (400, 418, …) is an
|
|
275
|
+
// anomaly this fetcher does not have a specific verdict for.
|
|
276
|
+
throw new SourceUnreachableError(`chtypes: ${url} returned status ${status}`);
|
|
277
|
+
}
|
|
278
|
+
if (json === null) {
|
|
279
|
+
throw new ArtifactCorruptError(`chtypes: ${url} did not return valid JSON`);
|
|
280
|
+
}
|
|
281
|
+
const mediaType = asString(field(json, 'mediaType'));
|
|
282
|
+
if (mediaType !== '' && mediaType !== MEDIA_TYPE_INDEX) {
|
|
283
|
+
throw new SourceIncompatibleError(`chtypes: ${url} has mediaType ${JSON.stringify(mediaType)}, not ${MEDIA_TYPE_INDEX}`);
|
|
284
|
+
}
|
|
285
|
+
const manifests = items(field(json, 'manifests'));
|
|
286
|
+
const matches = manifests.filter((m) => {
|
|
287
|
+
const p = field(m, 'platform');
|
|
288
|
+
return asString(field(p, 'os')) === info.os && asString(field(p, 'architecture')) === info.architecture;
|
|
289
|
+
});
|
|
290
|
+
if (matches.length === 0) {
|
|
291
|
+
const offered = manifests
|
|
292
|
+
.map((m) => {
|
|
293
|
+
const p = field(m, 'platform');
|
|
294
|
+
return `${asString(field(p, 'os'))}-${asString(field(p, 'architecture'))}`;
|
|
295
|
+
})
|
|
296
|
+
.filter((k) => k !== '-');
|
|
297
|
+
throw new ArtifactUnpublishedError(`chtypes: ${spelling} offers no manifest for ${platform}; the index offers: ${offered.join(', ') || '(none)'}`);
|
|
298
|
+
}
|
|
299
|
+
if (matches.length > 1) {
|
|
300
|
+
// `index-duplicate-platform`: the index disagrees with itself about
|
|
301
|
+
// which manifest is this platform's — `CORRUPT`, the plan's own
|
|
302
|
+
// annotation for this case.
|
|
303
|
+
throw new ArtifactCorruptError(`chtypes: ${spelling}'s index names ${platform} more than once`);
|
|
304
|
+
}
|
|
305
|
+
const d = matches[0];
|
|
306
|
+
const manifestDigest = asString(field(d, 'digest'));
|
|
307
|
+
if (manifestDigest === '')
|
|
308
|
+
throw new ArtifactCorruptError(`chtypes: ${spelling}'s ${platform} descriptor has no digest`);
|
|
309
|
+
const manifestDescriptor = {
|
|
310
|
+
mediaType: asString(field(d, 'mediaType')),
|
|
311
|
+
digest: manifestDigest,
|
|
312
|
+
size: numberField(d, 'size'),
|
|
313
|
+
};
|
|
314
|
+
if (manifestDescriptor.mediaType !== MEDIA_TYPE_MANIFEST) {
|
|
315
|
+
throw new SourceIncompatibleError(`chtypes: ${spelling}'s ${platform} descriptor has mediaType ${JSON.stringify(manifestDescriptor.mediaType)}, not ${MEDIA_TYPE_MANIFEST}`);
|
|
316
|
+
}
|
|
317
|
+
const manifestBytes = await fetchManifestBytesByDigest(bases, manifestDescriptor, options);
|
|
318
|
+
const manifest = parseManifest(manifestDigest, manifestBytes);
|
|
319
|
+
return { repositoryRoot: base, indexDigest: digestOfHex(sha256Hex(body)), indexBytes: body, manifest };
|
|
320
|
+
}
|
|
321
|
+
throw new ArtifactUnpublishedError(`chtypes: ${spelling} is unpublished: every base 404d the tag (${triedBases.join(', ')})`);
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=oci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oci.js","sourceRoot":"","sources":["../../src/ocifetch/oci.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Referrer discovery (`docs/guides/fetch-v1.md` §4): the OCI referrers API,
|
|
3
|
+
* **and** the tag-schema fallback (`sha256-<hex>`) — both implemented, never
|
|
4
|
+
* only one, because which a host serves is a property of that host, not of
|
|
5
|
+
* this fetcher.
|
|
6
|
+
*
|
|
7
|
+
* **The fallback tag is consulted only when the referrers API's own answer
|
|
8
|
+
* has no bundle of the trusted signature artifactType** — an empty list, a
|
|
9
|
+
* list holding only other artifactTypes (goldens, say), or the API itself
|
|
10
|
+
* unsupported (errors, or any non-200). When the referrers API already
|
|
11
|
+
* names a candidate of that artifactType, the fallback tag is never fetched
|
|
12
|
+
* — this keeps the request count the same shape as Go, Python and Rust's
|
|
13
|
+
* lanes, which conformance cases assert on (a case can require "no fallback
|
|
14
|
+
* request" for a referrers-API-only host). A referrers-API 404 reads the
|
|
15
|
+
* same as "unsupported": fall back at once, with no retry — this is a
|
|
16
|
+
* discovery probe, not a promise that a specific digest exists (unlike a
|
|
17
|
+
* by-digest manifest/blob fetch, which does retry a 404 on the last base;
|
|
18
|
+
* `oci.ts`'s `retryOn404`).
|
|
19
|
+
*/
|
|
20
|
+
import { type RequestOptions } from './http.js';
|
|
21
|
+
export interface ReferrerDescriptor {
|
|
22
|
+
readonly digest: string;
|
|
23
|
+
readonly mediaType: string;
|
|
24
|
+
readonly artifactType: string | undefined;
|
|
25
|
+
readonly size: number;
|
|
26
|
+
}
|
|
27
|
+
/** The fallback tag schema name for a digest, e.g. `sha256:ab12..` -> `sha256-ab12..`. */
|
|
28
|
+
export declare function fallbackTagFor(digest: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Every referrer of `artifactType` for `digest` within `repositoryRoot`,
|
|
31
|
+
* from the referrers API alone. `[]` whenever the API's own answer has no
|
|
32
|
+
* bundle of this `artifactType` — an empty list, a list of only other
|
|
33
|
+
* artifactTypes, a 404 (treated as "unsupported here", not retried — see
|
|
34
|
+
* this module's header), or any other error — and in every one of those
|
|
35
|
+
* cases `discoverSignatureCandidates` then also tries the fallback tag.
|
|
36
|
+
*/
|
|
37
|
+
export declare function discoverReferrers(repositoryRoot: string, digest: string, artifactType: string, options: RequestOptions): Promise<ReferrerDescriptor[]>;
|
|
38
|
+
/**
|
|
39
|
+
* The fallback tag's own referrer list for `digest` (the tag-schema index,
|
|
40
|
+
* `GET manifests/<tag>` — always with the manifest `Accept` header), filtered
|
|
41
|
+
* the same way as the referrers API. Only ever called by
|
|
42
|
+
* `discoverSignatureCandidates` when the referrers API found nothing of the
|
|
43
|
+
* trusted artifactType.
|
|
44
|
+
*/
|
|
45
|
+
export declare function discoverFallbackTag(repositoryRoot: string, digest: string, artifactType: string, options: RequestOptions): Promise<ReferrerDescriptor[]>;
|
|
46
|
+
/**
|
|
47
|
+
* The candidate list a caller should try verifying in order, stopping at
|
|
48
|
+
* the first success. Queries the referrers API first; the fallback tag is
|
|
49
|
+
* fetched **only** when the referrers API named no candidate of
|
|
50
|
+
* `artifactType` at all (see this module's header) — never unconditionally,
|
|
51
|
+
* so a referrers-API-only host sees exactly one discovery request, matching
|
|
52
|
+
* Go, Python and Rust.
|
|
53
|
+
*/
|
|
54
|
+
export declare function discoverSignatureCandidates(repositoryRoot: string, digest: string, artifactType: string, options: RequestOptions): Promise<ReferrerDescriptor[]>;
|
|
55
|
+
//# sourceMappingURL=referrers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referrers.d.ts","sourceRoot":"","sources":["../../src/ocifetch/referrers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAE,KAAK,cAAc,EAAgC,MAAM,WAAW,CAAC;AAG9E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMrD;AAkDD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAe/B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAM/B;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAI/B"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Referrer discovery (`docs/guides/fetch-v1.md` §4): the OCI referrers API,
|
|
3
|
+
* **and** the tag-schema fallback (`sha256-<hex>`) — both implemented, never
|
|
4
|
+
* only one, because which a host serves is a property of that host, not of
|
|
5
|
+
* this fetcher.
|
|
6
|
+
*
|
|
7
|
+
* **The fallback tag is consulted only when the referrers API's own answer
|
|
8
|
+
* has no bundle of the trusted signature artifactType** — an empty list, a
|
|
9
|
+
* list holding only other artifactTypes (goldens, say), or the API itself
|
|
10
|
+
* unsupported (errors, or any non-200). When the referrers API already
|
|
11
|
+
* names a candidate of that artifactType, the fallback tag is never fetched
|
|
12
|
+
* — this keeps the request count the same shape as Go, Python and Rust's
|
|
13
|
+
* lanes, which conformance cases assert on (a case can require "no fallback
|
|
14
|
+
* request" for a referrers-API-only host). A referrers-API 404 reads the
|
|
15
|
+
* same as "unsupported": fall back at once, with no retry — this is a
|
|
16
|
+
* discovery probe, not a promise that a specific digest exists (unlike a
|
|
17
|
+
* by-digest manifest/blob fetch, which does retry a 404 on the last base;
|
|
18
|
+
* `oci.ts`'s `retryOn404`).
|
|
19
|
+
*/
|
|
20
|
+
import { asString, field, items, parseJsonValue } from '../json.js';
|
|
21
|
+
import { MANIFEST_MAX_BYTES, MAX_REFERRERS } from './constants.gen.js';
|
|
22
|
+
import { ArtifactCorruptError } from './errors.js';
|
|
23
|
+
import { readFileUrl, requestBuffered } from './http.js';
|
|
24
|
+
import { endpointUrl, MANIFEST_ACCEPT_HEADER } from './types.js';
|
|
25
|
+
/** The fallback tag schema name for a digest, e.g. `sha256:ab12..` -> `sha256-ab12..`. */
|
|
26
|
+
export function fallbackTagFor(digest) {
|
|
27
|
+
const [algo, hex] = digest.split(':', 2);
|
|
28
|
+
if (algo !== 'sha256' || hex === undefined) {
|
|
29
|
+
throw new ArtifactCorruptError(`chtypes: cannot derive a fallback tag from digest ${JSON.stringify(digest)}`);
|
|
30
|
+
}
|
|
31
|
+
return `sha256-${hex}`;
|
|
32
|
+
}
|
|
33
|
+
async function getJson(url, maxBytes, options, extraHeaders) {
|
|
34
|
+
const res = url.startsWith('file:')
|
|
35
|
+
? await readFileUrl(url, maxBytes)
|
|
36
|
+
: await requestBuffered(url, {
|
|
37
|
+
...options,
|
|
38
|
+
maxBytes,
|
|
39
|
+
headers: { ...options.headers, ...extraHeaders },
|
|
40
|
+
});
|
|
41
|
+
if (res.status !== 200)
|
|
42
|
+
return { status: res.status, json: null };
|
|
43
|
+
const json = parseJsonValue(res.body);
|
|
44
|
+
if (json === null)
|
|
45
|
+
throw new ArtifactCorruptError(`chtypes: ${url} did not return valid JSON`);
|
|
46
|
+
return { status: res.status, json };
|
|
47
|
+
}
|
|
48
|
+
function descriptorsFromIndex(json) {
|
|
49
|
+
// A host may omit the index's own `mediaType`; the `manifests` array is
|
|
50
|
+
// read either way, so this is not itself a shape check (`oci.ts` checks
|
|
51
|
+
// media types where their presence is load-bearing).
|
|
52
|
+
const manifests = items(field(json, 'manifests'));
|
|
53
|
+
const out = [];
|
|
54
|
+
for (const m of manifests.slice(0, MAX_REFERRERS)) {
|
|
55
|
+
const digest = asString(field(m, 'digest'));
|
|
56
|
+
const descMediaType = asString(field(m, 'mediaType'));
|
|
57
|
+
const artifactTypeField = field(m, 'artifactType');
|
|
58
|
+
const size = numberField(m, 'size');
|
|
59
|
+
if (digest === '')
|
|
60
|
+
continue;
|
|
61
|
+
out.push({
|
|
62
|
+
digest,
|
|
63
|
+
mediaType: descMediaType,
|
|
64
|
+
artifactType: artifactTypeField === undefined ? undefined : asString(artifactTypeField),
|
|
65
|
+
size,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
function numberField(json, key) {
|
|
71
|
+
const v = field(json, key);
|
|
72
|
+
if (v === undefined || v.kind !== 'number')
|
|
73
|
+
return 0;
|
|
74
|
+
const n = Number(v.raw.toString('utf8'));
|
|
75
|
+
return Number.isFinite(n) ? n : 0;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Every referrer of `artifactType` for `digest` within `repositoryRoot`,
|
|
79
|
+
* from the referrers API alone. `[]` whenever the API's own answer has no
|
|
80
|
+
* bundle of this `artifactType` — an empty list, a list of only other
|
|
81
|
+
* artifactTypes, a 404 (treated as "unsupported here", not retried — see
|
|
82
|
+
* this module's header), or any other error — and in every one of those
|
|
83
|
+
* cases `discoverSignatureCandidates` then also tries the fallback tag.
|
|
84
|
+
*/
|
|
85
|
+
export async function discoverReferrers(repositoryRoot, digest, artifactType, options) {
|
|
86
|
+
const url = `${endpointUrl(repositoryRoot, `/referrers/${digest}`)}?artifactType=${encodeURIComponent(artifactType)}`;
|
|
87
|
+
const fromApi = [];
|
|
88
|
+
try {
|
|
89
|
+
const { status, json } = await getJson(url, MANIFEST_MAX_BYTES, options);
|
|
90
|
+
if (status === 200 && json !== null) {
|
|
91
|
+
for (const d of descriptorsFromIndex(json)) {
|
|
92
|
+
if (d.artifactType === artifactType)
|
|
93
|
+
fromApi.push(d);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// The referrers API is not guaranteed on every host (mirrors) — read as
|
|
99
|
+
// "no candidates here", exactly as an empty or goldens-only answer would.
|
|
100
|
+
}
|
|
101
|
+
return fromApi;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The fallback tag's own referrer list for `digest` (the tag-schema index,
|
|
105
|
+
* `GET manifests/<tag>` — always with the manifest `Accept` header), filtered
|
|
106
|
+
* the same way as the referrers API. Only ever called by
|
|
107
|
+
* `discoverSignatureCandidates` when the referrers API found nothing of the
|
|
108
|
+
* trusted artifactType.
|
|
109
|
+
*/
|
|
110
|
+
export async function discoverFallbackTag(repositoryRoot, digest, artifactType, options) {
|
|
111
|
+
const tag = fallbackTagFor(digest);
|
|
112
|
+
const url = endpointUrl(repositoryRoot, `/manifests/${tag}`);
|
|
113
|
+
const { status, json } = await getJson(url, MANIFEST_MAX_BYTES, options, { accept: MANIFEST_ACCEPT_HEADER });
|
|
114
|
+
if (status !== 200 || json === null)
|
|
115
|
+
return [];
|
|
116
|
+
return descriptorsFromIndex(json).filter((d) => d.artifactType === artifactType);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The candidate list a caller should try verifying in order, stopping at
|
|
120
|
+
* the first success. Queries the referrers API first; the fallback tag is
|
|
121
|
+
* fetched **only** when the referrers API named no candidate of
|
|
122
|
+
* `artifactType` at all (see this module's header) — never unconditionally,
|
|
123
|
+
* so a referrers-API-only host sees exactly one discovery request, matching
|
|
124
|
+
* Go, Python and Rust.
|
|
125
|
+
*/
|
|
126
|
+
export async function discoverSignatureCandidates(repositoryRoot, digest, artifactType, options) {
|
|
127
|
+
const fromApi = await discoverReferrers(repositoryRoot, digest, artifactType, options);
|
|
128
|
+
if (fromApi.length > 0)
|
|
129
|
+
return fromApi;
|
|
130
|
+
return discoverFallbackTag(repositoryRoot, digest, artifactType, options);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=referrers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referrers.js","sourceRoot":"","sources":["../../src/ocifetch/referrers.ts"],"names":[],"mappings":"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"}
|