@wavehouse/chtypes 2.0.0-dev.1 → 2.0.0-dev.11

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 (145) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +5 -1
  3. package/dist/abi2/buildinfo.d.ts +1 -1
  4. package/dist/abi2/buildinfo.js +3 -3
  5. package/dist/abi2/buildinfo.js.map +1 -1
  6. package/dist/abi2/calls.gen.d.ts +5 -5
  7. package/dist/abi2/calls.gen.d.ts.map +1 -1
  8. package/dist/abi2/calls.gen.js +11 -11
  9. package/dist/abi2/calls.gen.js.map +1 -1
  10. package/dist/abi2/decls.gen.d.ts +2 -1
  11. package/dist/abi2/decls.gen.d.ts.map +1 -1
  12. package/dist/abi2/decls.gen.js +78 -20
  13. package/dist/abi2/decls.gen.js.map +1 -1
  14. package/dist/abi2/errmap.gen.js +1 -1
  15. package/dist/abi2/errors.d.ts +21 -40
  16. package/dist/abi2/errors.d.ts.map +1 -1
  17. package/dist/abi2/errors.js +20 -44
  18. package/dist/abi2/errors.js.map +1 -1
  19. package/dist/abi2/index.d.ts +2 -2
  20. package/dist/abi2/index.d.ts.map +1 -1
  21. package/dist/abi2/index.js +1 -1
  22. package/dist/abi2/index.js.map +1 -1
  23. package/dist/abi2/libc.gen.d.ts +2 -0
  24. package/dist/abi2/libc.gen.d.ts.map +1 -1
  25. package/dist/abi2/libc.gen.js +11 -1
  26. package/dist/abi2/libc.gen.js.map +1 -1
  27. package/dist/abi2/loader.d.ts +4 -2
  28. package/dist/abi2/loader.d.ts.map +1 -1
  29. package/dist/abi2/loader.js +2 -2
  30. package/dist/abi2/loader.js.map +1 -1
  31. package/dist/abi2/raw.d.ts.map +1 -1
  32. package/dist/abi2/raw.js +4 -1
  33. package/dist/abi2/raw.js.map +1 -1
  34. package/dist/abi2/vocab.gen.d.ts +90 -1
  35. package/dist/abi2/vocab.gen.d.ts.map +1 -1
  36. package/dist/abi2/vocab.gen.js +144 -4
  37. package/dist/abi2/vocab.gen.js.map +1 -1
  38. package/dist/cli.d.ts +11 -5
  39. package/dist/cli.d.ts.map +1 -1
  40. package/dist/cli.js +130 -20
  41. package/dist/cli.js.map +1 -1
  42. package/dist/documents.d.ts +100 -7
  43. package/dist/documents.d.ts.map +1 -1
  44. package/dist/documents.js +135 -8
  45. package/dist/documents.js.map +1 -1
  46. package/dist/env.d.ts +8 -1
  47. package/dist/env.d.ts.map +1 -1
  48. package/dist/env.js +17 -8
  49. package/dist/env.js.map +1 -1
  50. package/dist/index.d.ts +10 -7
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +8 -5
  53. package/dist/index.js.map +1 -1
  54. package/dist/library.d.ts +13 -2
  55. package/dist/library.d.ts.map +1 -1
  56. package/dist/library.js +24 -5
  57. package/dist/library.js.map +1 -1
  58. package/dist/ocifetch/channel.d.ts +84 -0
  59. package/dist/ocifetch/channel.d.ts.map +1 -1
  60. package/dist/ocifetch/channel.js +157 -2
  61. package/dist/ocifetch/channel.js.map +1 -1
  62. package/dist/ocifetch/constants.gen.d.ts +28 -0
  63. package/dist/ocifetch/constants.gen.d.ts.map +1 -1
  64. package/dist/ocifetch/constants.gen.js +30 -1
  65. package/dist/ocifetch/constants.gen.js.map +1 -1
  66. package/dist/ocifetch/dsse.d.ts +5 -1
  67. package/dist/ocifetch/dsse.d.ts.map +1 -1
  68. package/dist/ocifetch/dsse.js +10 -3
  69. package/dist/ocifetch/dsse.js.map +1 -1
  70. package/dist/ocifetch/ensure.d.ts +68 -8
  71. package/dist/ocifetch/ensure.d.ts.map +1 -1
  72. package/dist/ocifetch/ensure.js +305 -66
  73. package/dist/ocifetch/ensure.js.map +1 -1
  74. package/dist/ocifetch/errors.d.ts +101 -25
  75. package/dist/ocifetch/errors.d.ts.map +1 -1
  76. package/dist/ocifetch/errors.js +74 -36
  77. package/dist/ocifetch/errors.js.map +1 -1
  78. package/dist/ocifetch/hold.d.ts +66 -0
  79. package/dist/ocifetch/hold.d.ts.map +1 -0
  80. package/dist/ocifetch/hold.js +150 -0
  81. package/dist/ocifetch/hold.js.map +1 -0
  82. package/dist/ocifetch/http.d.ts +10 -2
  83. package/dist/ocifetch/http.d.ts.map +1 -1
  84. package/dist/ocifetch/http.js +31 -12
  85. package/dist/ocifetch/http.js.map +1 -1
  86. package/dist/ocifetch/index.d.ts +10 -5
  87. package/dist/ocifetch/index.d.ts.map +1 -1
  88. package/dist/ocifetch/index.js +8 -3
  89. package/dist/ocifetch/index.js.map +1 -1
  90. package/dist/ocifetch/localverify.d.ts +3 -1
  91. package/dist/ocifetch/localverify.d.ts.map +1 -1
  92. package/dist/ocifetch/localverify.js +6 -1
  93. package/dist/ocifetch/localverify.js.map +1 -1
  94. package/dist/ocifetch/lock.d.ts +2 -1
  95. package/dist/ocifetch/lock.d.ts.map +1 -1
  96. package/dist/ocifetch/lock.js +7 -5
  97. package/dist/ocifetch/lock.js.map +1 -1
  98. package/dist/ocifetch/oci.d.ts +45 -3
  99. package/dist/ocifetch/oci.d.ts.map +1 -1
  100. package/dist/ocifetch/oci.js +125 -58
  101. package/dist/ocifetch/oci.js.map +1 -1
  102. package/dist/ocifetch/prune.d.ts +48 -0
  103. package/dist/ocifetch/prune.d.ts.map +1 -0
  104. package/dist/ocifetch/prune.js +383 -0
  105. package/dist/ocifetch/prune.js.map +1 -0
  106. package/dist/ocifetch/referrers.d.ts +24 -0
  107. package/dist/ocifetch/referrers.d.ts.map +1 -1
  108. package/dist/ocifetch/referrers.js +92 -5
  109. package/dist/ocifetch/referrers.js.map +1 -1
  110. package/dist/ocifetch/resolve.d.ts +37 -0
  111. package/dist/ocifetch/resolve.d.ts.map +1 -0
  112. package/dist/ocifetch/resolve.js +90 -0
  113. package/dist/ocifetch/resolve.js.map +1 -0
  114. package/dist/ocifetch/retired.d.ts +61 -0
  115. package/dist/ocifetch/retired.d.ts.map +1 -0
  116. package/dist/ocifetch/retired.js +236 -0
  117. package/dist/ocifetch/retired.js.map +1 -0
  118. package/dist/ocifetch/revocation.d.ts +151 -0
  119. package/dist/ocifetch/revocation.d.ts.map +1 -0
  120. package/dist/ocifetch/revocation.js +481 -0
  121. package/dist/ocifetch/revocation.js.map +1 -0
  122. package/dist/ocifetch/types.d.ts +18 -2
  123. package/dist/ocifetch/types.d.ts.map +1 -1
  124. package/dist/ocifetch/types.js.map +1 -1
  125. package/dist/registry.d.ts +80 -3
  126. package/dist/registry.d.ts.map +1 -1
  127. package/dist/registry.js +168 -9
  128. package/dist/registry.js.map +1 -1
  129. package/dist/schema.d.ts +52 -9
  130. package/dist/schema.d.ts.map +1 -1
  131. package/dist/schema.js +6 -6
  132. package/dist/schema.js.map +1 -1
  133. package/dist/server.d.ts +27 -0
  134. package/dist/server.d.ts.map +1 -0
  135. package/dist/server.js +35 -0
  136. package/dist/server.js.map +1 -0
  137. package/dist/settings.d.ts +101 -9
  138. package/dist/settings.d.ts.map +1 -1
  139. package/dist/settings.js +201 -27
  140. package/dist/settings.js.map +1 -1
  141. package/dist/setup.d.ts +3 -2
  142. package/dist/setup.d.ts.map +1 -1
  143. package/dist/setup.js +2 -3
  144. package/dist/setup.js.map +1 -1
  145. package/package.json +2 -2
@@ -0,0 +1,90 @@
1
+ /**
2
+ * `chtypes resolve` (`docs/guides/fetch-v1.md` §3, "What a request resolves
3
+ * to"; public issue #493): what a line, a patch or an exact version resolves
4
+ * to on every platform the registry offers, each verified exactly as a fetch
5
+ * verifies it (§4), and never a layer downloaded. Offline it is the cache's
6
+ * answer instead, the lookup an open makes.
7
+ */
8
+ import { noteIgnoredOverrides, offlineMode } from './channel.js';
9
+ import { PLATFORMS } from './constants.gen.js';
10
+ import { missingNotes, requestOptionsFor, resolveBases, resolveInstalled, verifyManifestTrust, withNotes } from './ensure.js';
11
+ import { ArtifactMissingError, ArtifactUnpublishedError } from './errors.js';
12
+ import { unwritable } from './faults.js';
13
+ import { cacheRoot } from './layout.js';
14
+ import { checkSpelling, fetchManifestBytesByDigest, parseManifest, resolveIndex, selectPlatformDescriptor } from './oci.js';
15
+ /**
16
+ * What `spelling` resolves to, one `Resolution` per platform, in the
17
+ * constants' platform order. Online it resolves the index (through the dev
18
+ * channel's alias first, §3), and for each platform the index offers it
19
+ * fetches the manifest by digest and verifies its signed statement against the
20
+ * request (§4), exactly as `ensure` does; no layer is requested and nothing is
21
+ * written. A platform the index does not offer is left out, and an index that
22
+ * offers none of them is `ArtifactUnpublishedError`. Offline it answers from
23
+ * the cache: each platform's `resolveInstalled`, and `ArtifactMissingError`
24
+ * when no platform has an installed build. A refused spelling is refused
25
+ * first, before anything is read (`SpellingRefusedError`).
26
+ */
27
+ export async function resolveBuilds(spelling, options = {}) {
28
+ noteIgnoredOverrides(options);
29
+ try {
30
+ return await resolveIn(spelling, options);
31
+ }
32
+ catch (err) {
33
+ // An offline lookup may verify a pre-seeded entry into the cache: a write
34
+ // that failed there is one class in every mode, as for `ensure`.
35
+ throw await unwritable(err, cacheRoot(options.cacheDir));
36
+ }
37
+ }
38
+ async function resolveIn(spelling, options) {
39
+ checkSpelling(spelling);
40
+ if (offlineMode(options.offline)) {
41
+ const resolutions = [];
42
+ for (const p of PLATFORMS) {
43
+ const hit = await resolveInstalled(spelling, p.key, options);
44
+ if (hit !== undefined) {
45
+ resolutions.push({ platform: p.key, version: hit.version, build: hit.build, manifest: hit.digests.manifest });
46
+ }
47
+ }
48
+ if (resolutions.length === 0) {
49
+ throw new ArtifactMissingError(withNotes(`chtypes: no installed artifact for ${spelling} on any platform, and --offline forbids a network fetch`, await missingNotes(options)));
50
+ }
51
+ return { resolutions, warnings: [] };
52
+ }
53
+ const bases = resolveBases(options);
54
+ const baseReqOptions = requestOptionsFor(options, bases);
55
+ const reqOptions = { ...baseReqOptions, maxBytes: 0 };
56
+ const index = await resolveIndex(bases, spelling, reqOptions);
57
+ const resolutions = [];
58
+ const warnings = [];
59
+ for (const p of PLATFORMS) {
60
+ let descriptor;
61
+ try {
62
+ descriptor = selectPlatformDescriptor(index, spelling, p.key);
63
+ }
64
+ catch (err) {
65
+ if (err instanceof ArtifactUnpublishedError)
66
+ continue; // the index does not offer this platform
67
+ throw err;
68
+ }
69
+ const manifest = parseManifest(descriptor.digest, await fetchManifestBytesByDigest(bases, descriptor, reqOptions));
70
+ // Under allow-unsigned with no verified statement, the version and build
71
+ // are the config blob's, as an unsigned install records them.
72
+ const verified = await verifyManifestTrust(index.repositoryRoot, manifest, index.aliasAbsent, p.key, spelling, options, baseReqOptions);
73
+ warnings.push(...verified.warnings);
74
+ resolutions.push({
75
+ platform: p.key,
76
+ version: stringMember(verified.predicate.clickhouse_version),
77
+ build: stringMember(verified.predicate.build),
78
+ manifest: manifest.digest,
79
+ });
80
+ }
81
+ if (resolutions.length === 0) {
82
+ throw new ArtifactUnpublishedError(`chtypes: the index for ${spelling} offers no platform this SDK knows`);
83
+ }
84
+ return { resolutions, warnings };
85
+ }
86
+ /** A predicate member read as the signed statement holds it: its text, or `''` for anything that is not a string. */
87
+ function stringMember(v) {
88
+ return typeof v === 'string' ? v : '';
89
+ }
90
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/ocifetch/resolve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * A retired repository (`docs/guides/fetch-v1.md` §2, "A retired repository";
3
+ * public issue #571). The registry's operator answers every route of a
4
+ * retired repository with 410 Gone (`RETIRED_STATUSES`) and a short error
5
+ * document. That is permanent: `http.ts` never retries it and throws
6
+ * `SourceRetiredError`, which every loop over bases or candidates lets
7
+ * through, so the caller sees the URL that answered and the registry's own
8
+ * message, made safe to print by `retiredMessage`, the one function every
9
+ * binding has (`tests/fixtures/retired-message/cases.json` is the table all
10
+ * four answer alike).
11
+ */
12
+ import type * as http from 'node:http';
13
+ import { type Advisory, ArtifactRevokedError, type FetchV1Error, SourceRetiredError } from './errors.js';
14
+ /** Is this status a retired repository's? */
15
+ export declare function isRetiredStatus(status: number): boolean;
16
+ /**
17
+ * The registry's own message in a retired repository's response body, made
18
+ * safe to print, or `null` when it sent none. `body` is what was read of it
19
+ * (at most `RETIRED_BODY_MAX_BYTES`). When it is UTF-8 JSON whose
20
+ * `errors[0].message` is a string, that string is the message: every code
21
+ * point in U+0000-U+001F, U+007F-U+009F, U+200E, U+200F, U+202A-U+202E and
22
+ * U+2066-U+2069 is removed, and the rest is cut to
23
+ * `RETIRED_MESSAGE_MAX_CODE_POINTS` code points, with U+2026 appended when it
24
+ * was cut. Nothing else is changed, and an empty result is no message.
25
+ */
26
+ export declare function retiredMessage(body: Uint8Array): string | null;
27
+ /**
28
+ * `text` made safe to print, the retired message's rule for every served
29
+ * string: every code point in U+0000-U+001F, U+007F-U+009F, U+200E, U+200F,
30
+ * U+202A-U+202E and U+2066-U+2069 removed, then cut to
31
+ * `RETIRED_MESSAGE_MAX_CODE_POINTS` code points with U+2026 appended when it was
32
+ * cut. A string holding a lone surrogate is not Unicode text and is `''`, as is
33
+ * one that is empty once made safe.
34
+ */
35
+ export declare function sanitizeRetiredText(text: string): string;
36
+ /** The error text for a retired repository's answer: the URL and status that answered, and the registry's message when it sent one. */
37
+ export declare function retiredText(url: string, status: number, body: Uint8Array): string;
38
+ /**
39
+ * A 410's body read as a revocation (guide, "Build-level revocation", "A `410`
40
+ * on a tag"): `undefined` unless it is UTF-8 JSON whose `errors[0].detail.revoked`
41
+ * is an object; otherwise that object's advisories, each field made safe, and one
42
+ * that is absent, not a string, empty once made safe or a lone surrogate left
43
+ * `''`. An entry that is not an object, or leaves every field empty, is skipped.
44
+ * A repeated key reads as its last value, and a byte order mark is not JSON.
45
+ * `tests/fixtures/revoked-410/cases.json` is the table all four bindings answer
46
+ * alike.
47
+ */
48
+ export declare function revoked410(body: Uint8Array): readonly Advisory[] | undefined;
49
+ /** What follows `<url> answered 410 Gone: ` for a revoked tag. */
50
+ export declare function revoked410Text(advisories: readonly Advisory[]): string;
51
+ /**
52
+ * The error for a 410 (guide §2): `ArtifactRevokedError` when `revocation` is on
53
+ * (generation 2) and the body's `errors[0].detail.revoked` is an object, else a
54
+ * retired repository's `SourceRetiredError`. Both are permanent.
55
+ */
56
+ export declare function goneError(url: string, status: number, body: Uint8Array, revocation: boolean): FetchV1Error;
57
+ /** Is `err` a 410's: `SourceRetiredError` or, under generation 2, `ArtifactRevokedError`? Either is permanent, so every loop over bases or candidates throws it at once. */
58
+ export declare function isGone(err: unknown): err is SourceRetiredError | ArtifactRevokedError;
59
+ /** At most `maxBytes` of a response body. A body that fails part way is no body. */
60
+ export declare function readRetiredBody(stream: http.IncomingMessage, maxBytes: number): Promise<Buffer>;
61
+ //# sourceMappingURL=retired.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retired.d.ts","sourceRoot":"","sources":["../../src/ocifetch/retired.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,KAAK,QAAQ,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEzG,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAkCD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAe9D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYxD;AAED,uIAAuI;AACvI,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAIjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,QAAQ,EAAE,GAAG,SAAS,CAmC5E;AAsBD,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAGtE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,GAAG,YAAY,CAY1G;AAED,4KAA4K;AAC5K,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,kBAAkB,GAAG,oBAAoB,CAErF;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB/F"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * A retired repository (`docs/guides/fetch-v1.md` §2, "A retired repository";
3
+ * public issue #571). The registry's operator answers every route of a
4
+ * retired repository with 410 Gone (`RETIRED_STATUSES`) and a short error
5
+ * document. That is permanent: `http.ts` never retries it and throws
6
+ * `SourceRetiredError`, which every loop over bases or candidates lets
7
+ * through, so the caller sees the URL that answered and the registry's own
8
+ * message, made safe to print by `retiredMessage`, the one function every
9
+ * binding has (`tests/fixtures/retired-message/cases.json` is the table all
10
+ * four answer alike).
11
+ */
12
+ import { RETIRED_MESSAGE_MAX_CODE_POINTS, RETIRED_STATUSES } from './constants.gen.js';
13
+ import { ArtifactRevokedError, SourceRetiredError } from './errors.js';
14
+ /** Is this status a retired repository's? */
15
+ export function isRetiredStatus(status) {
16
+ return RETIRED_STATUSES.includes(status);
17
+ }
18
+ function removed(codePoint) {
19
+ return (codePoint <= 0x1f ||
20
+ (codePoint >= 0x7f && codePoint <= 0x9f) ||
21
+ codePoint === 0x200e ||
22
+ codePoint === 0x200f ||
23
+ (codePoint >= 0x202a && codePoint <= 0x202e) ||
24
+ (codePoint >= 0x2066 && codePoint <= 0x2069));
25
+ }
26
+ /** A UTF-16 surrogate that is not half of a high-then-low pair: not a Unicode string. */
27
+ function hasLoneSurrogate(s) {
28
+ for (let i = 0; i < s.length; i++) {
29
+ const c = s.charCodeAt(i);
30
+ if (c >= 0xd800 && c <= 0xdbff) {
31
+ const d = s.charCodeAt(i + 1);
32
+ if (d >= 0xdc00 && d <= 0xdfff) {
33
+ i++;
34
+ continue;
35
+ }
36
+ return true;
37
+ }
38
+ if (c >= 0xdc00 && c <= 0xdfff)
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+ function objectOrUndefined(v) {
44
+ return v !== null && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
45
+ }
46
+ /**
47
+ * The registry's own message in a retired repository's response body, made
48
+ * safe to print, or `null` when it sent none. `body` is what was read of it
49
+ * (at most `RETIRED_BODY_MAX_BYTES`). When it is UTF-8 JSON whose
50
+ * `errors[0].message` is a string, that string is the message: every code
51
+ * point in U+0000-U+001F, U+007F-U+009F, U+200E, U+200F, U+202A-U+202E and
52
+ * U+2066-U+2069 is removed, and the rest is cut to
53
+ * `RETIRED_MESSAGE_MAX_CODE_POINTS` code points, with U+2026 appended when it
54
+ * was cut. Nothing else is changed, and an empty result is no message.
55
+ */
56
+ export function retiredMessage(body) {
57
+ let doc;
58
+ try {
59
+ // fatal: invalid UTF-8 is no message. ignoreBOM: a byte order mark stays
60
+ // in the text, so JSON.parse refuses it, as the other bindings' readers do.
61
+ doc = JSON.parse(new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(body));
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ const errors = objectOrUndefined(doc)?.['errors'];
67
+ if (!Array.isArray(errors) || errors.length === 0)
68
+ return null;
69
+ const message = objectOrUndefined(errors[0])?.['message'];
70
+ if (typeof message !== 'string')
71
+ return null;
72
+ const safe = sanitizeRetiredText(message);
73
+ return safe === '' ? null : safe;
74
+ }
75
+ /**
76
+ * `text` made safe to print, the retired message's rule for every served
77
+ * string: every code point in U+0000-U+001F, U+007F-U+009F, U+200E, U+200F,
78
+ * U+202A-U+202E and U+2066-U+2069 removed, then cut to
79
+ * `RETIRED_MESSAGE_MAX_CODE_POINTS` code points with U+2026 appended when it was
80
+ * cut. A string holding a lone surrogate is not Unicode text and is `''`, as is
81
+ * one that is empty once made safe.
82
+ */
83
+ export function sanitizeRetiredText(text) {
84
+ if (hasLoneSurrogate(text))
85
+ return '';
86
+ const kept = [];
87
+ for (const ch of text) {
88
+ // A string iterates by code point, so a character outside the BMP is one.
89
+ if (!removed(ch.codePointAt(0) ?? 0))
90
+ kept.push(ch);
91
+ }
92
+ if (kept.length > RETIRED_MESSAGE_MAX_CODE_POINTS) {
93
+ kept.length = RETIRED_MESSAGE_MAX_CODE_POINTS;
94
+ kept.push('…');
95
+ }
96
+ return kept.join('');
97
+ }
98
+ /** The error text for a retired repository's answer: the URL and status that answered, and the registry's message when it sent one. */
99
+ export function retiredText(url, status, body) {
100
+ const message = retiredMessage(body);
101
+ const text = `${url} answered ${status} Gone: the repository is retired`;
102
+ return message === null ? text : `${text}; the registry says: ${message}`;
103
+ }
104
+ /**
105
+ * A 410's body read as a revocation (guide, "Build-level revocation", "A `410`
106
+ * on a tag"): `undefined` unless it is UTF-8 JSON whose `errors[0].detail.revoked`
107
+ * is an object; otherwise that object's advisories, each field made safe, and one
108
+ * that is absent, not a string, empty once made safe or a lone surrogate left
109
+ * `''`. An entry that is not an object, or leaves every field empty, is skipped.
110
+ * A repeated key reads as its last value, and a byte order mark is not JSON.
111
+ * `tests/fixtures/revoked-410/cases.json` is the table all four bindings answer
112
+ * alike.
113
+ */
114
+ export function revoked410(body) {
115
+ let doc;
116
+ try {
117
+ doc = JSON.parse(new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(body));
118
+ }
119
+ catch {
120
+ return undefined;
121
+ }
122
+ const errors = objectOrUndefined(doc)?.['errors'];
123
+ if (!Array.isArray(errors) || errors.length === 0)
124
+ return undefined;
125
+ const detail = objectOrUndefined(objectOrUndefined(errors[0])?.['detail']);
126
+ const revoked = objectOrUndefined(detail?.['revoked']);
127
+ if (revoked === undefined)
128
+ return undefined;
129
+ const entries = revoked['advisories'];
130
+ const advisories = [];
131
+ if (!Array.isArray(entries))
132
+ return advisories;
133
+ for (const e of entries) {
134
+ const obj = objectOrUndefined(e);
135
+ if (obj === undefined)
136
+ continue;
137
+ const field = (key) => {
138
+ const v = obj[key];
139
+ return typeof v === 'string' ? sanitizeRetiredText(v) : '';
140
+ };
141
+ const a = {
142
+ id: field('id'),
143
+ url: field('url'),
144
+ class: field('class'),
145
+ summary: field('summary'),
146
+ build: field('build'),
147
+ supersededBy: field('superseded_by'),
148
+ revokedAt: '',
149
+ };
150
+ if (a.id === '' && a.url === '' && a.class === '' && a.summary === '' && a.build === '' && a.supersededBy === '')
151
+ continue;
152
+ advisories.push(a);
153
+ }
154
+ return advisories;
155
+ }
156
+ /**
157
+ * One 410 advisory: `<id> <url> (<class>) build <build>, superseded by build
158
+ * <superseded_by>: <summary>`, a part whose field is empty left out with the
159
+ * separator before it, and the first part present taking none.
160
+ */
161
+ function advisoryText(a) {
162
+ let s = '';
163
+ const join = (sep, part) => {
164
+ if (s !== '')
165
+ s += sep;
166
+ s += part;
167
+ };
168
+ if (a.id !== '')
169
+ join(' ', a.id);
170
+ if (a.url !== '')
171
+ join(' ', a.url);
172
+ if (a.class !== '')
173
+ join(' ', `(${a.class})`);
174
+ if (a.build !== '')
175
+ join(' ', `build ${a.build}`);
176
+ if (a.supersededBy !== '')
177
+ join(', ', `superseded by build ${a.supersededBy}`);
178
+ if (a.summary !== '')
179
+ join(': ', a.summary);
180
+ return s;
181
+ }
182
+ /** What follows `<url> answered 410 Gone: ` for a revoked tag. */
183
+ export function revoked410Text(advisories) {
184
+ const parts = advisories.map(advisoryText).filter((t) => t !== '');
185
+ return parts.length === 0 ? 'revoked, and the registry names no advisory' : `revoked: ${parts.join('; ')}`;
186
+ }
187
+ /**
188
+ * The error for a 410 (guide §2): `ArtifactRevokedError` when `revocation` is on
189
+ * (generation 2) and the body's `errors[0].detail.revoked` is an object, else a
190
+ * retired repository's `SourceRetiredError`. Both are permanent.
191
+ */
192
+ export function goneError(url, status, body, revocation) {
193
+ if (revocation) {
194
+ const advisories = revoked410(body);
195
+ if (advisories !== undefined) {
196
+ return new ArtifactRevokedError(`chtypes: ${url} answered ${status} Gone: ${revoked410Text(advisories)}`, {
197
+ signed: false,
198
+ manifest: '',
199
+ advisories,
200
+ });
201
+ }
202
+ }
203
+ return new SourceRetiredError(`chtypes: ${retiredText(url, status, body)}`);
204
+ }
205
+ /** Is `err` a 410's: `SourceRetiredError` or, under generation 2, `ArtifactRevokedError`? Either is permanent, so every loop over bases or candidates throws it at once. */
206
+ export function isGone(err) {
207
+ return err instanceof SourceRetiredError || err instanceof ArtifactRevokedError;
208
+ }
209
+ /** At most `maxBytes` of a response body. A body that fails part way is no body. */
210
+ export function readRetiredBody(stream, maxBytes) {
211
+ return new Promise((resolve) => {
212
+ const chunks = [];
213
+ let total = 0;
214
+ let done = false;
215
+ const finish = (body) => {
216
+ if (done)
217
+ return;
218
+ done = true;
219
+ resolve(body);
220
+ };
221
+ stream.on('data', (chunk) => {
222
+ if (done)
223
+ return;
224
+ chunks.push(chunk);
225
+ total += chunk.length;
226
+ if (total >= maxBytes) {
227
+ finish(Buffer.concat(chunks).subarray(0, maxBytes));
228
+ stream.destroy();
229
+ }
230
+ });
231
+ stream.on('end', () => finish(Buffer.concat(chunks)));
232
+ stream.on('error', () => finish(Buffer.alloc(0)));
233
+ stream.on('close', () => finish(Buffer.alloc(0)));
234
+ });
235
+ }
236
+ //# sourceMappingURL=retired.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retired.js","sourceRoot":"","sources":["../../src/ocifetch/retired.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Build-level revocation (`docs/guides/fetch-v1.md`, "Build-level revocation";
3
+ * public issue #625). A revocation is a signed referrer of a platform manifest,
4
+ * read from the listing its signature lookup reads; one that verifies refuses the
5
+ * build with `ArtifactRevokedError` and is stored in the build's cache entry, and
6
+ * one that does not is ignored with one warning. A 410 whose body's
7
+ * `errors[0].detail.revoked` is an object is the same code (`retired.ts`). A
8
+ * status that cannot be read fails open with one warning, or in strict mode is the
9
+ * transport's error. Generation 2 only (`Channel.revocation`): the v1 contract has
10
+ * none of it.
11
+ *
12
+ * Four paths check, each with its own budget, exactly as Go's `revocation.go`:
13
+ *
14
+ * - an install reads its revocation candidates from the trust listing it already
15
+ * made, under the retry table;
16
+ * - `--frozen` reads one listing, warm or cold, under the retry table;
17
+ * - a build already installed and used without a download (a registry open,
18
+ * preload, an ensure that finds it installed) is checked at most once per
19
+ * process (the memo below), one attempt per base, no backoff, and one deadline
20
+ * for the whole check;
21
+ * - `--lock` and `update` refuse a revoked build on every platform they pin.
22
+ */
23
+ import { type FetchV1ErrorCode, type Revocation } from './errors.js';
24
+ import type { RequestOptions } from './http.js';
25
+ import { type ReferrerDescriptor } from './referrers.js';
26
+ import type { Resolved, Statement, TrustedKey } from './types.js';
27
+ /** What one revocation check reads from the call's options, derived once (`ensure.ts`'s `revocationContext`). */
28
+ export interface RevocationContext {
29
+ /** The configured bases, in order. */
30
+ readonly bases: readonly string[];
31
+ /** The trust list the build itself is checked under. */
32
+ readonly trustedKeys: readonly TrustedKey[];
33
+ /** The request options every fetch over `bases` sends (`requestOptionsFor`). */
34
+ readonly request: Omit<RequestOptions, 'maxBytes'>;
35
+ /** The cache root a writable entry lies under. */
36
+ readonly cacheRoot: string;
37
+ readonly offline: boolean;
38
+ /** Per call, and never with a lock or an update (`revocationContext` drops it). */
39
+ readonly allowRevoked: boolean;
40
+ /** A revocation status that cannot be read is the transport's error, not a warning. */
41
+ readonly requireRevocationCheck: boolean;
42
+ }
43
+ /** Whether the active contract has revocation at all. */
44
+ export declare function revocationOn(): boolean;
45
+ /**
46
+ * The build a check concerns: its own digests and signed predicate, and its
47
+ * installed entry (`dir`) when it has one, writable when that entry is in the
48
+ * user cache.
49
+ */
50
+ export interface RevocationSubject {
51
+ readonly manifest: string;
52
+ readonly layer: string;
53
+ readonly predicate: Readonly<Record<string, unknown>>;
54
+ readonly version: string;
55
+ readonly platform: string;
56
+ readonly build: string;
57
+ readonly request: string;
58
+ readonly dir: string;
59
+ readonly writable: boolean;
60
+ }
61
+ /** The subject an installed build's `Resolved` names. */
62
+ export declare function subjectOf(ctx: RevocationContext, res: Resolved): RevocationSubject;
63
+ /** The subject of a build not yet installed: the signed statement verified for it. */
64
+ export declare function subjectOfStatement(statement: Statement, manifest: string, layer: string, platform: string, request: string): RevocationSubject;
65
+ /**
66
+ * One revocation bundle against `sub` (the guide's five rules): the signature
67
+ * under `keys`, the statement and predicate types, the subject and manifest, the
68
+ * build's identity, and the advisory's shape. The revocation, or why it does not
69
+ * verify. A signed payload that is not a statement is ignored, never CORRUPT.
70
+ */
71
+ export declare function verifyRevocation(body: Buffer, keys: readonly TrustedKey[], sub: RevocationSubject): {
72
+ readonly revocation: Revocation;
73
+ } | {
74
+ readonly reason: string;
75
+ };
76
+ /**
77
+ * The guide's message for a verified revocation: `<version> <platform> build
78
+ * <build> (manifest <digest>) is revoked: <id> <url> (<class>); superseded by
79
+ * build <superseded_by>: <summary>`, a part whose field is empty left out.
80
+ */
81
+ export declare function revokedText(sub: RevocationSubject, rev: Revocation): string;
82
+ /** One verified revocation: the bundle, for the stored record, and what it says. */
83
+ export interface FoundRevocation {
84
+ readonly bundle: Buffer;
85
+ readonly revocation: Revocation;
86
+ }
87
+ /** Why a status could not be read: the text, and the code the transport's error carries in strict mode. */
88
+ export interface Unread {
89
+ readonly text: string;
90
+ readonly code: FetchV1ErrorCode;
91
+ }
92
+ /**
93
+ * What one check learned: a verified revocation, the warnings for the candidates
94
+ * it ignored, and, when it could not read the status, why.
95
+ */
96
+ export interface RevocationOutcome {
97
+ verified: FoundRevocation | undefined;
98
+ readonly warnings: string[];
99
+ unread: Unread | undefined;
100
+ }
101
+ /**
102
+ * Fetches and verifies each revocation candidate in turn; the first that
103
+ * verifies is the answer. A candidate whose bytes cannot be fetched leaves the
104
+ * status unread; one fetched but corrupt or not verifying is ignored with a
105
+ * warning. Its only error is a 410's.
106
+ */
107
+ export declare function checkCandidates(ctx: RevocationContext, bases: readonly string[], cands: readonly ReferrerDescriptor[], sub: RevocationSubject, single: boolean, signal?: AbortSignal): Promise<RevocationOutcome>;
108
+ /**
109
+ * One network check of `sub`: its listing, then its candidates. A listing that
110
+ * names no signature referrer is an unread status.
111
+ */
112
+ export declare function checkListing(ctx: RevocationContext, sub: RevocationSubject, single: boolean, signal?: AbortSignal): Promise<RevocationOutcome>;
113
+ /**
114
+ * Turns an outcome into the call's answer, its warnings pushed on `warn`: a
115
+ * verified revocation is stored in an installed, writable entry (when `store`)
116
+ * and refuses the build, or with the override becomes one warning; an unread
117
+ * status is one warning, or in strict mode the transport's error.
118
+ */
119
+ export declare function settle(ctx: RevocationContext, sub: RevocationSubject, out: RevocationOutcome, store: boolean, warn: string[]): Promise<void>;
120
+ /** Stores a verified revocation's bundle, byte for byte, in an installed build's entry: a temporary file, then a rename. */
121
+ export declare function writeRevocationRecord(dir: string, bundle: Buffer): Promise<void>;
122
+ /** The revocation an install let through under the override, stored in the entry it installed (a failed write is ignored). */
123
+ export declare function storePending(ctx: RevocationContext, dir: string, pending: FoundRevocation | undefined): Promise<void>;
124
+ /**
125
+ * Reads `sub`'s stored record, if its entry holds one: verified, it decides the
126
+ * call (returns `true`; a refusal is thrown); one that does not verify is a
127
+ * warning, and the call goes on.
128
+ */
129
+ export declare function checkStored(ctx: RevocationContext, sub: RevocationSubject, warn: string[]): Promise<boolean>;
130
+ /** The revocation `res`'s stored record holds, when it verifies, and its message (`chtypes verify`'s). */
131
+ export declare function storedRevocation(ctx: RevocationContext, res: Resolved): Promise<{
132
+ readonly revocation: Revocation;
133
+ readonly text: string;
134
+ } | undefined>;
135
+ /** The check every call that answers from the cache with no request makes (`--offline`, `--frozen --offline`): the stored record. */
136
+ export declare function checkInstalledStored(ctx: RevocationContext, res: Resolved): Promise<readonly string[]>;
137
+ /** `--frozen`'s check of the build installed under its pin: the stored record, then one listing under the retry table. */
138
+ export declare function checkFrozenInstalled(ctx: RevocationContext, res: Resolved): Promise<readonly string[]>;
139
+ /** Forgets every kept outcome, as a new process would. A conformance runner calls it before every case. Test-only. */
140
+ export declare function resetRevocationMemoForTests(): void;
141
+ /** Shortens (or, with `undefined`, restores) the installed-build check's one deadline. Test-only. */
142
+ export declare function setRevocationCheckDeadlineForTests(seconds: number | undefined): void;
143
+ /**
144
+ * The installed-build check: the stored record, then, unless offline, the kept
145
+ * outcome or one check of its own, with one attempt per base, no backoff and one
146
+ * deadline. Concurrent checks of one build share one; a kept "not checked"
147
+ * answers only a call without strict mode, and a check that ends in an error
148
+ * keeps nothing. Warnings go on `warn`; a refusal is thrown.
149
+ */
150
+ export declare function checkInstalledOnce(ctx: RevocationContext, res: Resolved, warn: string[]): Promise<void>;
151
+ //# sourceMappingURL=revocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revocation.d.ts","sourceRoot":"","sources":["../../src/ocifetch/revocation.ts"],"names":[],"mappings":"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"}