@tiangong-lca/cli 0.1.9 → 0.1.10

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 (70) hide show
  1. package/README.md +8 -5
  2. package/assets/runtime/cli-runtime-descriptor.schema.json +138 -0
  3. package/assets/runtime/cli-runtime-expectation.schema.json +38 -0
  4. package/assets/runtime/runtime-bootstrap-lock.schema.json +254 -0
  5. package/assets/runtime/runtime-command-result.schema.json +95 -0
  6. package/assets/runtime/runtime-manifest.schema.json +380 -0
  7. package/dist/src/cli.js +5 -1
  8. package/dist/src/cli.js.map +1 -1
  9. package/dist/src/lib/dataset-import-lca.js +2 -2
  10. package/dist/src/lib/dataset-import-lca.js.map +1 -1
  11. package/dist/src/lib/runtime/archive-writer.d.ts +7 -0
  12. package/dist/src/lib/runtime/archive-writer.js +89 -0
  13. package/dist/src/lib/runtime/archive-writer.js.map +1 -0
  14. package/dist/src/lib/runtime/archive.d.ts +2 -0
  15. package/dist/src/lib/runtime/archive.js +122 -0
  16. package/dist/src/lib/runtime/archive.js.map +1 -0
  17. package/dist/src/lib/runtime/command.d.ts +8 -0
  18. package/dist/src/lib/runtime/command.js +57 -0
  19. package/dist/src/lib/runtime/command.js.map +1 -0
  20. package/dist/src/lib/runtime/descriptor.d.ts +11 -0
  21. package/dist/src/lib/runtime/descriptor.js +126 -0
  22. package/dist/src/lib/runtime/descriptor.js.map +1 -0
  23. package/dist/src/lib/runtime/download.d.ts +9 -0
  24. package/dist/src/lib/runtime/download.js +118 -0
  25. package/dist/src/lib/runtime/download.js.map +1 -0
  26. package/dist/src/lib/runtime/exec-command.d.ts +7 -0
  27. package/dist/src/lib/runtime/exec-command.js +83 -0
  28. package/dist/src/lib/runtime/exec-command.js.map +1 -0
  29. package/dist/src/lib/runtime/execute.d.ts +11 -0
  30. package/dist/src/lib/runtime/execute.js +125 -0
  31. package/dist/src/lib/runtime/execute.js.map +1 -0
  32. package/dist/src/lib/runtime/files.d.ts +7 -0
  33. package/dist/src/lib/runtime/files.js +91 -0
  34. package/dist/src/lib/runtime/files.js.map +1 -0
  35. package/dist/src/lib/runtime/host.d.ts +8 -0
  36. package/dist/src/lib/runtime/host.js +37 -0
  37. package/dist/src/lib/runtime/host.js.map +1 -0
  38. package/dist/src/lib/runtime/leases.d.ts +12 -0
  39. package/dist/src/lib/runtime/leases.js +72 -0
  40. package/dist/src/lib/runtime/leases.js.map +1 -0
  41. package/dist/src/lib/runtime/managed-command.d.ts +6 -0
  42. package/dist/src/lib/runtime/managed-command.js +99 -0
  43. package/dist/src/lib/runtime/managed-command.js.map +1 -0
  44. package/dist/src/lib/runtime/manager.d.ts +33 -0
  45. package/dist/src/lib/runtime/manager.js +196 -0
  46. package/dist/src/lib/runtime/manager.js.map +1 -0
  47. package/dist/src/lib/runtime/manifest-types.d.ts +73 -0
  48. package/dist/src/lib/runtime/manifest-types.js +4 -0
  49. package/dist/src/lib/runtime/manifest-types.js.map +1 -0
  50. package/dist/src/lib/runtime/manifest-values.d.ts +15 -0
  51. package/dist/src/lib/runtime/manifest-values.js +124 -0
  52. package/dist/src/lib/runtime/manifest-values.js.map +1 -0
  53. package/dist/src/lib/runtime/manifest.d.ts +7 -0
  54. package/dist/src/lib/runtime/manifest.js +220 -0
  55. package/dist/src/lib/runtime/manifest.js.map +1 -0
  56. package/dist/src/lib/runtime/process.d.ts +3 -0
  57. package/dist/src/lib/runtime/process.js +55 -0
  58. package/dist/src/lib/runtime/process.js.map +1 -0
  59. package/dist/src/lib/runtime/storage.d.ts +8 -0
  60. package/dist/src/lib/runtime/storage.js +142 -0
  61. package/dist/src/lib/runtime/storage.js.map +1 -0
  62. package/dist/src/lib/runtime/types.d.ts +45 -0
  63. package/dist/src/lib/runtime/types.js +9 -0
  64. package/dist/src/lib/runtime/types.js.map +1 -0
  65. package/dist/src/main.js +13 -1
  66. package/dist/src/main.js.map +1 -1
  67. package/dist/src/runtime.d.ts +15 -0
  68. package/dist/src/runtime.js +22 -0
  69. package/dist/src/runtime.js.map +1 -0
  70. package/package.json +5 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../../src/lib/runtime/manager.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { withBatchRunLock } from '../../batch.js';\nimport { contentHash, hashRuntimeFile, runtimeError } from './files.js';\nimport { assertTrustedManifest, componentKey } from './manifest.js';\nimport { assertRuntimeHost, inspectRuntimeHost } from './host.js';\nimport {\n cachePath,\n defaultRuntimeCache,\n ensureRuntimeCache,\n openRuntimeCache,\n readCacheJson,\n writeOnce,\n} from './storage.js';\nimport { downloadRuntimeArchive, type DownloadOptions } from './download.js';\nimport { extractRuntimeArchive } from './archive.js';\nimport { acquireRuntimeLease, leasedRuntimeKeys, withRuntimeLeaseLock } from './leases.js';\nimport type { RuntimeComponent, RuntimeHost, TrustedRuntimeManifest } from './manifest-types.js';\n\nexport type RuntimeManagerOptions = DownloadOptions & {\n cacheDir?: string;\n host?: RuntimeHost;\n lease?: { id: string; owner: string };\n archiveSeeds?: Readonly<Record<string, string>>;\n};\nexport type RuntimeComponentStatus = {\n id: string;\n version: string;\n key: string;\n status: 'ready' | 'missing' | 'unverified' | 'corrupt';\n root: string;\n reason: string | null;\n};\nexport type RuntimeManagerReport = {\n schema: 'tiangong-lca.runtime-status.v1';\n manifest_sha256: string;\n platform: string;\n status: 'ready' | 'missing' | 'blocked';\n components: RuntimeComponentStatus[];\n};\nfunction receipt(component: RuntimeComponent) {\n return {\n schema: 'tiangong-lca.runtime-component.v1',\n key: componentKey(component),\n archive_sha256: component.archive.sha256,\n content_sha256: component.content_sha256,\n };\n}\nexport function verifyRuntimeComponent(\n root: string,\n component: RuntimeComponent,\n platform: string,\n): void {\n const expected = new Map(component.files.map((file) => [file.path, file]));\n let count = 0;\n const walk = (relative: string): void => {\n const directory = relative ? cachePath(root, relative) : root;\n const stat = fs.lstatSync(directory);\n if (stat.isSymbolicLink() || !stat.isDirectory())\n runtimeError('RUNTIME_COMPONENT_PATH', 'Component directories cannot be links.');\n for (const name of fs.readdirSync(directory)) {\n const file = relative ? `${relative}/${name}` : name;\n const target = cachePath(root, file);\n const item = fs.lstatSync(target);\n if (item.isDirectory()) walk(file);\n else {\n const expectedFile = expected.get(file);\n if (!expectedFile)\n runtimeError('RUNTIME_COMPONENT_EXTRA', 'Component contains an unregistered file.');\n const actual = hashRuntimeFile(target, file);\n if (\n actual.bytes !== expectedFile.bytes ||\n actual.sha256 !== expectedFile.sha256 ||\n (platform !== 'win32-x64' && (item.mode & 0o777) !== expectedFile.mode)\n )\n runtimeError(\n 'RUNTIME_COMPONENT_CHANGED',\n 'Component file bytes, digest or executable mode changed.',\n );\n count++;\n }\n }\n };\n walk('');\n if (count !== component.files.length)\n runtimeError('RUNTIME_COMPONENT_MISSING', 'Component inventory is incomplete.');\n}\nfunction inspectComponent(\n cache: string,\n component: RuntimeComponent,\n platform: string,\n): RuntimeComponentStatus {\n const key = componentKey(component),\n relative = `components/${key}`,\n root = cachePath(cache, `${relative}/root`);\n const base = { id: component.id, version: component.version, key, root };\n if (!fs.existsSync(cachePath(cache, relative)))\n return { ...base, status: 'missing', reason: null };\n try {\n if (\n fs\n .readdirSync(cachePath(cache, relative))\n .some((name) => !['root', 'receipt.json'].includes(name))\n )\n runtimeError(\n 'RUNTIME_COMPONENT_EXTRA',\n 'Component installation directory contains unknown data.',\n );\n if (!fs.existsSync(cachePath(cache, `${relative}/receipt.json`)))\n return { ...base, status: 'unverified', reason: 'runtime_install_incomplete' };\n if (\n contentHash(readCacheJson(cache, `${relative}/receipt.json`)) !==\n contentHash(receipt(component))\n )\n runtimeError(\n 'RUNTIME_RECEIPT_CHANGED',\n 'Component installation receipt does not match the selected manifest.',\n );\n verifyRuntimeComponent(root, component, platform);\n return { ...base, status: 'ready', reason: null };\n } catch (error) {\n return {\n ...base,\n status: 'corrupt',\n reason:\n typeof (error as { code?: unknown }).code === 'string'\n ? (error as { code: string }).code\n : 'runtime_component_invalid',\n };\n }\n}\nfunction selected(value: TrustedRuntimeManifest, options: RuntimeManagerOptions) {\n assertTrustedManifest(value);\n const host = options.host ?? inspectRuntimeHost();\n assertRuntimeHost(value, host);\n return {\n host,\n components: value.manifest.components.filter(\n (component) => component.platform === host.platform,\n ),\n };\n}\nexport function inspectRuntimeComponents(\n value: TrustedRuntimeManifest,\n options: RuntimeManagerOptions = {},\n): RuntimeManagerReport {\n const { host, components } = selected(value, options),\n cache = openRuntimeCache(options.cacheDir ?? defaultRuntimeCache(), false);\n const states = components.map((component) => inspectComponent(cache, component, host.platform));\n return {\n schema: 'tiangong-lca.runtime-status.v1',\n manifest_sha256: value.sha256,\n platform: host.platform,\n status: states.every((item) => item.status === 'ready')\n ? 'ready'\n : states.some((item) => item.status === 'corrupt' || item.status === 'unverified')\n ? 'blocked'\n : 'missing',\n components: states,\n };\n}\nasync function installComponent(\n cache: string,\n component: RuntimeComponent,\n options: RuntimeManagerOptions,\n platform: string,\n): Promise<void> {\n const key = componentKey(component);\n await withBatchRunLock(\n {\n runPath: cachePath(cache, `locks/${key}.json`),\n identity: { schema: 'runtime-component-lock.v1', key },\n reason: 'Runtime component installation',\n },\n async () => {\n const state = inspectComponent(cache, component, platform);\n if (state.status === 'ready') return;\n const target = cachePath(cache, `components/${key}`);\n if (state.status === 'unverified') {\n // Bootstrap may publish a complete tree before Node can produce the CLI receipt.\n // It is cache data only: adopt after every declared byte/mode and absence of extra files is proved.\n verifyRuntimeComponent(state.root, component, platform);\n writeOnce(\n cache,\n `components/${key}/receipt.json`,\n Buffer.from(JSON.stringify(receipt(component)) + '\\n'),\n );\n return;\n }\n if (state.status === 'corrupt')\n runtimeError(\n 'RUNTIME_CACHE_CORRUPT',\n 'A selected cached component is corrupt; preserve active leases and prune it explicitly.',\n );\n const staging = cachePath(cache, `tmp/${key}-${randomUUID()}`);\n fs.mkdirSync(staging, { recursive: true, mode: 0o700 });\n try {\n const archive = path.join(staging, 'component.tar.gz'),\n seed = options.archiveSeeds?.[key];\n if (seed) {\n const fact = hashRuntimeFile(seed, 'archive');\n if (fact.bytes !== component.archive.bytes || fact.sha256 !== component.archive.sha256)\n runtimeError(\n 'RUNTIME_ARCHIVE_SEED',\n 'Supplied archive seed differs from the trusted component.',\n );\n fs.copyFileSync(seed, archive, fs.constants.COPYFILE_EXCL);\n } else await downloadRuntimeArchive(component.archive, archive, options);\n await extractRuntimeArchive(archive, path.join(staging, 'root'), component, options.signal);\n verifyRuntimeComponent(path.join(staging, 'root'), component, platform);\n fs.unlinkSync(archive);\n writeOnce(staging, 'receipt.json', Buffer.from(JSON.stringify(receipt(component)) + '\\n'));\n fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });\n cachePath(cache, `components/${key}`);\n if (fs.existsSync(target))\n runtimeError(\n 'RUNTIME_INSTALL_CONFLICT',\n 'Another component tree appeared outside the installation lock.',\n );\n fs.renameSync(staging, target);\n } finally {\n if (fs.existsSync(staging)) fs.rmSync(staging, { recursive: true, force: true });\n }\n },\n );\n}\nexport async function ensureRuntimeComponents(\n value: TrustedRuntimeManifest,\n options: RuntimeManagerOptions = {},\n): Promise<RuntimeManagerReport> {\n const { host, components } = selected(value, options);\n options.signal?.throwIfAborted();\n const cache = await ensureRuntimeCache(options.cacheDir ?? defaultRuntimeCache());\n if (options.lease)\n await acquireRuntimeLease(\n cache,\n options.lease.id,\n options.lease.owner,\n components.map(componentKey),\n );\n for (const component of components) {\n options.signal?.throwIfAborted();\n await installComponent(cache, component, options, host.platform);\n }\n return inspectRuntimeComponents(value, { ...options, cacheDir: cache, host });\n}\nexport async function pruneRuntimeComponents(\n value: TrustedRuntimeManifest,\n options: RuntimeManagerOptions = {},\n): Promise<{ removed: string[]; retained: string[] }> {\n const { components } = selected(value, options);\n const cache = openRuntimeCache(options.cacheDir ?? defaultRuntimeCache(), false);\n if (!fs.existsSync(cachePath(cache, '.runtime-cache.json'))) return { removed: [], retained: [] };\n return withRuntimeLeaseLock(cache, async () => {\n const pinned = leasedRuntimeKeys(cache),\n removed: string[] = [],\n retained: string[] = [];\n for (const component of components) {\n const key = componentKey(component);\n if (pinned.has(key)) {\n retained.push(key);\n continue;\n }\n await withBatchRunLock(\n {\n runPath: cachePath(cache, `locks/${key}.json`),\n identity: { schema: 'runtime-component-lock.v1', key },\n reason: 'Explicit unused runtime pruning',\n },\n () => {\n const target = cachePath(cache, `components/${key}`);\n if (!fs.existsSync(target)) return;\n if (fs.readdirSync(target).some((name) => !['root', 'receipt.json'].includes(name)))\n runtimeError(\n 'RUNTIME_PRUNE_UNOWNED',\n 'Unknown files must be preserved instead of pruned.',\n );\n if (\n contentHash(readCacheJson(cache, `components/${key}/receipt.json`)) !==\n contentHash(receipt(component))\n )\n runtimeError(\n 'RUNTIME_PRUNE_UNOWNED',\n 'Only an installation with its exact ownership receipt can be pruned.',\n );\n fs.rmSync(target, { recursive: true, force: false });\n removed.push(key);\n },\n );\n }\n return { removed, retained };\n });\n}\n"]}
@@ -0,0 +1,73 @@
1
+ import type { RuntimePlatform } from './types.js';
2
+ export declare const RUNTIME_MANIFEST_SCHEMA: 'tiangong-lca.runtime-manifest.v1';
3
+ export declare const RUNTIME_BOOTSTRAP_PROTOCOL: 'tiangong-lca.runtime-bootstrap.v1';
4
+ export declare const RUNTIME_ARCHIVE_FORMAT: 'tar-gzip-ustar-v1';
5
+ export type ComponentFile = Readonly<{
6
+ path: string;
7
+ bytes: number;
8
+ sha256: string;
9
+ mode: 420 | 493;
10
+ }>;
11
+ export type RuntimeComponent = Readonly<{
12
+ id: string;
13
+ version: string;
14
+ platform: RuntimePlatform;
15
+ archive: Readonly<{
16
+ format: typeof RUNTIME_ARCHIVE_FORMAT;
17
+ url: string;
18
+ bytes: number;
19
+ sha256: string;
20
+ }>;
21
+ files: readonly ComponentFile[];
22
+ content_sha256: string;
23
+ production_lock: string;
24
+ sbom: string;
25
+ licenses: readonly string[];
26
+ provenance: readonly string[];
27
+ protocols: readonly string[];
28
+ asset_fingerprints: Readonly<Record<string, string>>;
29
+ }>;
30
+ export type ComponentPath = Readonly<{
31
+ component: string;
32
+ path: string;
33
+ }>;
34
+ export type RuntimeLaunch = Readonly<{
35
+ id: string;
36
+ platform: RuntimePlatform;
37
+ executable: ComponentPath;
38
+ environment: 'isolated' | 'cli-auth';
39
+ argv: readonly (ComponentPath | Readonly<{
40
+ literal: string;
41
+ }>)[];
42
+ }>;
43
+ export type WorkspaceCompatibility = Readonly<{
44
+ schema: string;
45
+ features: readonly string[];
46
+ }>;
47
+ export type RuntimeManifest = Readonly<{
48
+ schema: typeof RUNTIME_MANIFEST_SCHEMA;
49
+ bootstrap_protocol: typeof RUNTIME_BOOTSTRAP_PROTOCOL;
50
+ product: Readonly<{
51
+ id: string;
52
+ version: string;
53
+ }>;
54
+ minimum_hosts: Readonly<Partial<Record<RuntimePlatform, Readonly<{
55
+ os_release: string;
56
+ glibc: string | null;
57
+ }>>>>;
58
+ workspace: Readonly<{
59
+ read: readonly WorkspaceCompatibility[];
60
+ write: readonly WorkspaceCompatibility[];
61
+ }>;
62
+ components: readonly RuntimeComponent[];
63
+ launches: readonly RuntimeLaunch[];
64
+ }>;
65
+ export type TrustedRuntimeManifest = Readonly<{
66
+ sha256: string;
67
+ manifest: RuntimeManifest;
68
+ }>;
69
+ export type RuntimeHost = Readonly<{
70
+ platform: RuntimePlatform;
71
+ osRelease: string;
72
+ glibc: string | null;
73
+ }>;
@@ -0,0 +1,4 @@
1
+ export const RUNTIME_MANIFEST_SCHEMA = 'tiangong-lca.runtime-manifest.v1';
2
+ export const RUNTIME_BOOTSTRAP_PROTOCOL = 'tiangong-lca.runtime-bootstrap.v1';
3
+ export const RUNTIME_ARCHIVE_FORMAT = 'tar-gzip-ustar-v1';
4
+ //# sourceMappingURL=manifest-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-types.js","sourceRoot":"","sources":["../../../../src/lib/runtime/manifest-types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAG,kCAA2C,CAAC;AACnF,MAAM,CAAC,MAAM,0BAA0B,GAAG,mCAA4C,CAAC;AACvF,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAA4B,CAAC","sourcesContent":["import type { RuntimePlatform } from './types.js';\n\nexport const RUNTIME_MANIFEST_SCHEMA = 'tiangong-lca.runtime-manifest.v1' as const;\nexport const RUNTIME_BOOTSTRAP_PROTOCOL = 'tiangong-lca.runtime-bootstrap.v1' as const;\nexport const RUNTIME_ARCHIVE_FORMAT = 'tar-gzip-ustar-v1' as const;\nexport type ComponentFile = Readonly<{\n path: string;\n bytes: number;\n sha256: string;\n mode: 420 | 493;\n}>;\nexport type RuntimeComponent = Readonly<{\n id: string;\n version: string;\n platform: RuntimePlatform;\n archive: Readonly<{\n format: typeof RUNTIME_ARCHIVE_FORMAT;\n url: string;\n bytes: number;\n sha256: string;\n }>;\n files: readonly ComponentFile[];\n content_sha256: string;\n production_lock: string;\n sbom: string;\n licenses: readonly string[];\n provenance: readonly string[];\n protocols: readonly string[];\n asset_fingerprints: Readonly<Record<string, string>>;\n}>;\nexport type ComponentPath = Readonly<{ component: string; path: string }>;\nexport type RuntimeLaunch = Readonly<{\n id: string;\n platform: RuntimePlatform;\n executable: ComponentPath;\n environment: 'isolated' | 'cli-auth';\n argv: readonly (ComponentPath | Readonly<{ literal: string }>)[];\n}>;\nexport type WorkspaceCompatibility = Readonly<{ schema: string; features: readonly string[] }>;\nexport type RuntimeManifest = Readonly<{\n schema: typeof RUNTIME_MANIFEST_SCHEMA;\n bootstrap_protocol: typeof RUNTIME_BOOTSTRAP_PROTOCOL;\n product: Readonly<{ id: string; version: string }>;\n minimum_hosts: Readonly<\n Partial<Record<RuntimePlatform, Readonly<{ os_release: string; glibc: string | null }>>>\n >;\n workspace: Readonly<{\n read: readonly WorkspaceCompatibility[];\n write: readonly WorkspaceCompatibility[];\n }>;\n components: readonly RuntimeComponent[];\n launches: readonly RuntimeLaunch[];\n}>;\nexport type TrustedRuntimeManifest = Readonly<{ sha256: string; manifest: RuntimeManifest }>;\nexport type RuntimeHost = Readonly<{\n platform: RuntimePlatform;\n osRelease: string;\n glibc: string | null;\n}>;\n"]}
@@ -0,0 +1,15 @@
1
+ import { type RuntimePlatform } from './types.js';
2
+ export declare function record(value: unknown, label: string): Record<string, unknown>;
3
+ export declare function invalid(label: string): never;
4
+ export declare function exact(value: Record<string, unknown>, keys: readonly string[], label: string): void;
5
+ export declare function text(value: unknown, label: string, max?: number): string;
6
+ export declare function id(value: unknown): string;
7
+ export declare function version(value: unknown): string;
8
+ export declare function sha(value: unknown): string;
9
+ export declare function integer(value: unknown, max: number, minimum?: number): number;
10
+ export declare function array(value: unknown, max: number, minimum?: number): unknown[];
11
+ export declare function platform(value: unknown): RuntimePlatform;
12
+ export declare function relativeFile(value: unknown): string;
13
+ export declare function unique(values: readonly string[], label: string): void;
14
+ export declare function distributionUrl(value: unknown, redirected?: boolean): string;
15
+ export declare function deepFreeze<T>(value: T): T;
@@ -0,0 +1,124 @@
1
+ import { runtimeError } from './files.js';
2
+ import { RUNTIME_PLATFORMS } from './types.js';
3
+ export function record(value, label) {
4
+ if (!value || typeof value !== 'object' || Array.isArray(value))
5
+ invalid(label);
6
+ return value;
7
+ }
8
+ export function invalid(label) {
9
+ return runtimeError('RUNTIME_MANIFEST_INVALID', `Runtime manifest has invalid ${label}.`);
10
+ }
11
+ export function exact(value, keys, label) {
12
+ if (Object.keys(value).length !== keys.length || keys.some((key) => !Object.hasOwn(value, key)))
13
+ invalid(label);
14
+ }
15
+ export function text(value, label, max = 256) {
16
+ if (typeof value !== 'string' ||
17
+ !value ||
18
+ value.length > max ||
19
+ value.split('').some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127))
20
+ invalid(label);
21
+ return value;
22
+ }
23
+ export function id(value) {
24
+ const result = text(value, 'identifier', 64);
25
+ if (!/^[a-z0-9][a-z0-9._-]*$/u.test(result) || result === '.' || result === '..')
26
+ invalid('identifier');
27
+ return result;
28
+ }
29
+ export function version(value) {
30
+ const result = text(value, 'version', 40);
31
+ if (!/^(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)$/u.test(result))
32
+ invalid('exact stable version');
33
+ return result;
34
+ }
35
+ export function sha(value) {
36
+ const result = text(value, 'SHA-256', 64);
37
+ if (!/^[0-9a-f]{64}$/u.test(result))
38
+ invalid('SHA-256');
39
+ return result;
40
+ }
41
+ export function integer(value, max, minimum = 0) {
42
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > max)
43
+ invalid('bounded integer');
44
+ return value;
45
+ }
46
+ export function array(value, max, minimum = 0) {
47
+ if (!Array.isArray(value) || value.length > max || value.length < minimum)
48
+ invalid('bounded array');
49
+ return value;
50
+ }
51
+ export function platform(value) {
52
+ if (!RUNTIME_PLATFORMS.includes(value))
53
+ invalid('platform');
54
+ return value;
55
+ }
56
+ export function relativeFile(value) {
57
+ const result = text(value, 'portable file path', 255);
58
+ if (Buffer.byteLength(result) > 255 ||
59
+ result.includes('\\') ||
60
+ result.includes(':') ||
61
+ result.startsWith('/') ||
62
+ result
63
+ .split('/')
64
+ .some((part) => !part ||
65
+ part === '.' ||
66
+ part === '..' ||
67
+ /^(?:\.env(?:\..*)?|\.git|\.npmrc|\.ssh)$/iu.test(part) ||
68
+ /[. ]$/u.test(part) ||
69
+ /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu.test(part)))
70
+ invalid('portable file path');
71
+ const segments = result.split('/');
72
+ if (segments.length > 32 ||
73
+ Buffer.byteLength(segments.at(-1)) > 100 ||
74
+ (Buffer.byteLength(result) > 100 &&
75
+ !segments
76
+ .slice(0, -1)
77
+ .some((_, i) => Buffer.byteLength(segments.slice(0, i + 1).join('/')) <= 155 &&
78
+ Buffer.byteLength(segments.slice(i + 1).join('/')) <= 100)))
79
+ invalid('USTAR path');
80
+ return result;
81
+ }
82
+ export function unique(values, label) {
83
+ if (new Set(values).size !== values.length)
84
+ invalid(`duplicate ${label}`);
85
+ }
86
+ export function distributionUrl(value, redirected = false) {
87
+ const input = text(value, 'distribution URL', 4096);
88
+ let url;
89
+ try {
90
+ url = new URL(input);
91
+ }
92
+ catch {
93
+ invalid('distribution URL');
94
+ }
95
+ if (url.protocol !== 'https:' || url.username || url.password || url.hash || url.port)
96
+ invalid('distribution URL');
97
+ const primary = ['github.com', 'nodejs.org', 'registry.npmjs.org'];
98
+ const redirects = ['release-assets.githubusercontent.com', 'objects.githubusercontent.com'];
99
+ if (!primary.includes(url.hostname) && !(redirected && redirects.includes(url.hostname)))
100
+ invalid('distribution origin');
101
+ if (!redirected) {
102
+ if (url.search || /\/(?:latest|heads)(?:\/|$)/u.test(url.pathname))
103
+ invalid('immutable distribution URL');
104
+ if (url.hostname === 'github.com' &&
105
+ !/^\/[^/]+\/[^/]+\/releases\/download\/[^/]+\/[^/]+$/u.test(url.pathname))
106
+ invalid('release asset URL');
107
+ if (url.hostname === 'nodejs.org' &&
108
+ !/^\/dist\/v[0-9]+\.[0-9]+\.[0-9]+\/[^/]+$/u.test(url.pathname))
109
+ invalid('Node release URL');
110
+ if (url.hostname === 'registry.npmjs.org' &&
111
+ !/\/-\/[^/]+-[0-9]+\.[0-9]+\.[0-9]+\.tgz$/u.test(url.pathname))
112
+ invalid('registry tarball URL');
113
+ }
114
+ return url.href;
115
+ }
116
+ export function deepFreeze(value) {
117
+ if (value && typeof value === 'object' && !Object.isFrozen(value)) {
118
+ for (const item of Object.values(value))
119
+ deepFreeze(item);
120
+ Object.freeze(value);
121
+ }
122
+ return value;
123
+ }
124
+ //# sourceMappingURL=manifest-values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-values.js","sourceRoot":"","sources":["../../../../src/lib/runtime/manifest-values.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAwB,MAAM,YAAY,CAAC;AAErE,MAAM,UAAU,MAAM,CAAC,KAAc,EAAE,KAAa;IAClD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAChF,OAAO,KAAgC,CAAC;AAC1C,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,YAAY,CAAC,0BAA0B,EAAE,gCAAgC,KAAK,GAAG,CAAC,CAAC;AAC5F,CAAC;AACD,MAAM,UAAU,KAAK,CACnB,KAA8B,EAC9B,IAAuB,EACvB,KAAa;IAEb,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7F,OAAO,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC;AACD,MAAM,UAAU,IAAI,CAAC,KAAc,EAAE,KAAa,EAAE,GAAG,GAAG,GAAG;IAC3D,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,KAAK;QACN,KAAK,CAAC,MAAM,GAAG,GAAG;QAClB,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;QAErF,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,OAAO,KAAK,CAAC;AACf,CAAC;AACD,MAAM,UAAU,EAAE,CAAC,KAAc;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,IAAI;QAC9E,OAAO,CAAC,YAAY,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,4DAA4D,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5E,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,GAAG,CAAC,KAAc;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,KAAc,EAAE,GAAW,EAAE,OAAO,GAAG,CAAC;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,OAAO,IAAI,KAAK,GAAG,GAAG;QAC7F,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AACD,MAAM,UAAU,KAAK,CAAC,KAAc,EAAE,GAAW,EAAE,OAAO,GAAG,CAAC;IAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO;QACvE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAwB,CAAC;QAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/E,OAAO,KAAwB,CAAC;AAClC,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACtD,IACE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,GAAG;QAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QACrB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QACtB,MAAM;aACH,KAAK,CAAC,GAAG,CAAC;aACV,IAAI,CACH,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,IAAI;YACL,IAAI,KAAK,GAAG;YACZ,IAAI,KAAK,IAAI;YACb,4CAA4C,CAAC,IAAI,CAAC,IAAI,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;YACnB,kDAAkD,CAAC,IAAI,CAAC,IAAI,CAAC,CAChE;QAEH,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,IACE,QAAQ,CAAC,MAAM,GAAG,EAAE;QACpB,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,GAAG,GAAG;QACzC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,GAAG;YAC9B,CAAC,QAAQ;iBACN,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;iBACZ,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG;gBAC5D,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAC5D,CAAC;QAEN,OAAO,CAAC,YAAY,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,MAAM,CAAC,MAAyB,EAAE,KAAa;IAC7D,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;AAC5E,CAAC;AACD,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,UAAU,GAAG,KAAK;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI;QACnF,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,oBAAoB,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,CAAC,sCAAsC,EAAE,+BAA+B,CAAC,CAAC;IAC5F,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtF,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,IAAI,GAAG,CAAC,MAAM,IAAI,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAChE,OAAO,CAAC,4BAA4B,CAAC,CAAC;QACxC,IACE,GAAG,CAAC,QAAQ,KAAK,YAAY;YAC7B,CAAC,qDAAqD,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAEzE,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC/B,IACE,GAAG,CAAC,QAAQ,KAAK,YAAY;YAC7B,CAAC,2CAA2C,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAE/D,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC9B,IACE,GAAG,CAAC,QAAQ,KAAK,oBAAoB;YACrC,CAAC,0CAA0C,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAE9D,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC;AACD,MAAM,UAAU,UAAU,CAAI,KAAQ;IACpC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { runtimeError } from './files.js';\nimport { RUNTIME_PLATFORMS, type RuntimePlatform } from './types.js';\n\nexport function record(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) invalid(label);\n return value as Record<string, unknown>;\n}\nexport function invalid(label: string): never {\n return runtimeError('RUNTIME_MANIFEST_INVALID', `Runtime manifest has invalid ${label}.`);\n}\nexport function exact(\n value: Record<string, unknown>,\n keys: readonly string[],\n label: string,\n): void {\n if (Object.keys(value).length !== keys.length || keys.some((key) => !Object.hasOwn(value, key)))\n invalid(label);\n}\nexport function text(value: unknown, label: string, max = 256): string {\n if (\n typeof value !== 'string' ||\n !value ||\n value.length > max ||\n value.split('').some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127)\n )\n invalid(label);\n return value;\n}\nexport function id(value: unknown): string {\n const result = text(value, 'identifier', 64);\n if (!/^[a-z0-9][a-z0-9._-]*$/u.test(result) || result === '.' || result === '..')\n invalid('identifier');\n return result;\n}\nexport function version(value: unknown): string {\n const result = text(value, 'version', 40);\n if (!/^(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)$/u.test(result))\n invalid('exact stable version');\n return result;\n}\nexport function sha(value: unknown): string {\n const result = text(value, 'SHA-256', 64);\n if (!/^[0-9a-f]{64}$/u.test(result)) invalid('SHA-256');\n return result;\n}\nexport function integer(value: unknown, max: number, minimum = 0): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > max)\n invalid('bounded integer');\n return value;\n}\nexport function array(value: unknown, max: number, minimum = 0): unknown[] {\n if (!Array.isArray(value) || value.length > max || value.length < minimum)\n invalid('bounded array');\n return value;\n}\nexport function platform(value: unknown): RuntimePlatform {\n if (!RUNTIME_PLATFORMS.includes(value as RuntimePlatform)) invalid('platform');\n return value as RuntimePlatform;\n}\nexport function relativeFile(value: unknown): string {\n const result = text(value, 'portable file path', 255);\n if (\n Buffer.byteLength(result) > 255 ||\n result.includes('\\\\') ||\n result.includes(':') ||\n result.startsWith('/') ||\n result\n .split('/')\n .some(\n (part) =>\n !part ||\n part === '.' ||\n part === '..' ||\n /^(?:\\.env(?:\\..*)?|\\.git|\\.npmrc|\\.ssh)$/iu.test(part) ||\n /[. ]$/u.test(part) ||\n /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\\.|$)/iu.test(part),\n )\n )\n invalid('portable file path');\n const segments = result.split('/');\n if (\n segments.length > 32 ||\n Buffer.byteLength(segments.at(-1)!) > 100 ||\n (Buffer.byteLength(result) > 100 &&\n !segments\n .slice(0, -1)\n .some(\n (_, i) =>\n Buffer.byteLength(segments.slice(0, i + 1).join('/')) <= 155 &&\n Buffer.byteLength(segments.slice(i + 1).join('/')) <= 100,\n ))\n )\n invalid('USTAR path');\n return result;\n}\nexport function unique(values: readonly string[], label: string): void {\n if (new Set(values).size !== values.length) invalid(`duplicate ${label}`);\n}\nexport function distributionUrl(value: unknown, redirected = false): string {\n const input = text(value, 'distribution URL', 4096);\n let url: URL;\n try {\n url = new URL(input);\n } catch {\n invalid('distribution URL');\n }\n if (url.protocol !== 'https:' || url.username || url.password || url.hash || url.port)\n invalid('distribution URL');\n const primary = ['github.com', 'nodejs.org', 'registry.npmjs.org'];\n const redirects = ['release-assets.githubusercontent.com', 'objects.githubusercontent.com'];\n if (!primary.includes(url.hostname) && !(redirected && redirects.includes(url.hostname)))\n invalid('distribution origin');\n if (!redirected) {\n if (url.search || /\\/(?:latest|heads)(?:\\/|$)/u.test(url.pathname))\n invalid('immutable distribution URL');\n if (\n url.hostname === 'github.com' &&\n !/^\\/[^/]+\\/[^/]+\\/releases\\/download\\/[^/]+\\/[^/]+$/u.test(url.pathname)\n )\n invalid('release asset URL');\n if (\n url.hostname === 'nodejs.org' &&\n !/^\\/dist\\/v[0-9]+\\.[0-9]+\\.[0-9]+\\/[^/]+$/u.test(url.pathname)\n )\n invalid('Node release URL');\n if (\n url.hostname === 'registry.npmjs.org' &&\n !/\\/-\\/[^/]+-[0-9]+\\.[0-9]+\\.[0-9]+\\.tgz$/u.test(url.pathname)\n )\n invalid('registry tarball URL');\n }\n return url.href;\n}\nexport function deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n for (const item of Object.values(value)) deepFreeze(item);\n Object.freeze(value);\n }\n return value;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { RuntimeComponent, RuntimeManifest, TrustedRuntimeManifest, WorkspaceCompatibility } from './manifest-types.js';
2
+ export declare function parseRuntimeManifest(value: unknown): RuntimeManifest;
3
+ export declare function trustRuntimeManifest(bytes: Uint8Array, expectedSha256: string): TrustedRuntimeManifest;
4
+ export declare function loadTrustedRuntimeManifest(file: string, expectedSha256: string): TrustedRuntimeManifest;
5
+ export declare function assertTrustedManifest(value: TrustedRuntimeManifest): void;
6
+ export declare function componentKey(value: RuntimeComponent): string;
7
+ export declare function assertWorkspaceCompatibility(value: TrustedRuntimeManifest, request: WorkspaceCompatibility, access: 'read' | 'write'): void;
@@ -0,0 +1,220 @@
1
+ import fs from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
+ import { contentHash, runtimeError } from './files.js';
4
+ import { array, deepFreeze, distributionUrl, exact, id, integer, invalid, platform, record, relativeFile, sha, text, unique, version, } from './manifest-values.js';
5
+ import { RUNTIME_ARCHIVE_FORMAT, RUNTIME_BOOTSTRAP_PROTOCOL, RUNTIME_MANIFEST_SCHEMA, } from './manifest-types.js';
6
+ const trusted = new WeakSet();
7
+ function compatibility(value) {
8
+ const result = array(value, 32).map((item) => {
9
+ const entry = record(item, 'workspace compatibility');
10
+ exact(entry, ['schema', 'features'], 'workspace compatibility');
11
+ const features = array(entry.features, 64).map((value) => text(value, 'workspace feature', 128));
12
+ unique(features, 'workspace feature');
13
+ return { schema: text(entry.schema, 'workspace schema', 128), features };
14
+ });
15
+ unique(result.map((entry) => entry.schema), 'workspace schema');
16
+ return result;
17
+ }
18
+ function component(value) {
19
+ const item = record(value, 'component');
20
+ exact(item, [
21
+ 'id',
22
+ 'version',
23
+ 'platform',
24
+ 'archive',
25
+ 'files',
26
+ 'content_sha256',
27
+ 'production_lock',
28
+ 'sbom',
29
+ 'licenses',
30
+ 'provenance',
31
+ 'protocols',
32
+ 'asset_fingerprints',
33
+ ], 'component');
34
+ const archive = record(item.archive, 'archive');
35
+ exact(archive, ['format', 'url', 'bytes', 'sha256'], 'archive');
36
+ if (archive.format !== RUNTIME_ARCHIVE_FORMAT)
37
+ invalid('archive format');
38
+ let total = 0;
39
+ const files = array(item.files, 50_000, 1).map((value) => {
40
+ const file = record(value, 'component file');
41
+ exact(file, ['path', 'bytes', 'sha256', 'mode'], 'component file');
42
+ if (file.mode !== 420 && file.mode !== 493)
43
+ invalid('file mode');
44
+ const bytes = integer(file.bytes, 512 * 1024 * 1024);
45
+ total += bytes;
46
+ return { path: relativeFile(file.path), bytes, sha256: sha(file.sha256), mode: file.mode };
47
+ });
48
+ if (total > 2 * 1024 * 1024 * 1024)
49
+ invalid('unpacked size');
50
+ const paths = files.map((file) => file.path);
51
+ unique(paths.map((path) => path.toLowerCase()), 'case-folded file path');
52
+ if (JSON.stringify(paths) !== JSON.stringify([...paths].sort()))
53
+ invalid('file order');
54
+ const pathSet = new Set(paths.map((path) => path.toLowerCase()));
55
+ for (const file of paths) {
56
+ const parts = file.split('/');
57
+ for (let i = 1; i < parts.length; i++)
58
+ if (pathSet.has(parts.slice(0, i).join('/').toLowerCase()))
59
+ invalid('file/directory collision');
60
+ }
61
+ const content = sha(item.content_sha256);
62
+ if (content !== contentHash(files))
63
+ invalid('component content SHA-256');
64
+ const requiredFile = (value) => {
65
+ const file = relativeFile(value);
66
+ if (!paths.includes(file))
67
+ invalid('metadata file reference');
68
+ return file;
69
+ };
70
+ const licenses = array(item.licenses, 64, 1).map(requiredFile), provenance = array(item.provenance, 64, 1).map(requiredFile);
71
+ unique(licenses, 'license');
72
+ unique(provenance, 'provenance');
73
+ const protocols = array(item.protocols, 32, 1).map((value) => text(value, 'component protocol', 128));
74
+ unique(protocols, 'protocol');
75
+ const fingerprints = record(item.asset_fingerprints, 'asset fingerprints');
76
+ if (Object.keys(fingerprints).length > 64)
77
+ invalid('fingerprint count');
78
+ const asset_fingerprints = Object.fromEntries(Object.entries(fingerprints).map(([key, value]) => [id(key), sha(value)]));
79
+ return {
80
+ id: id(item.id),
81
+ version: version(item.version),
82
+ platform: platform(item.platform),
83
+ archive: {
84
+ format: RUNTIME_ARCHIVE_FORMAT,
85
+ url: distributionUrl(archive.url),
86
+ bytes: integer(archive.bytes, 512 * 1024 * 1024, 1),
87
+ sha256: sha(archive.sha256),
88
+ },
89
+ files,
90
+ content_sha256: content,
91
+ production_lock: requiredFile(item.production_lock),
92
+ sbom: requiredFile(item.sbom),
93
+ licenses,
94
+ provenance,
95
+ protocols,
96
+ asset_fingerprints,
97
+ };
98
+ }
99
+ function componentPath(value, components, target, executable = false) {
100
+ const entry = record(value, 'component path');
101
+ exact(entry, ['component', 'path'], 'component path');
102
+ const componentId = id(entry.component), file = relativeFile(entry.path);
103
+ const owner = components.find((item) => item.platform === target && item.id === componentId);
104
+ const fact = owner?.files.find((item) => item.path === file);
105
+ if (!fact || (executable && fact.mode !== 493))
106
+ invalid('launch file reference');
107
+ return { component: componentId, path: file };
108
+ }
109
+ export function parseRuntimeManifest(value) {
110
+ const item = record(value, 'manifest');
111
+ exact(item, [
112
+ 'schema',
113
+ 'bootstrap_protocol',
114
+ 'product',
115
+ 'minimum_hosts',
116
+ 'workspace',
117
+ 'components',
118
+ 'launches',
119
+ ], 'manifest');
120
+ if (item.schema !== RUNTIME_MANIFEST_SCHEMA ||
121
+ item.bootstrap_protocol !== RUNTIME_BOOTSTRAP_PROTOCOL)
122
+ invalid('manifest protocol version');
123
+ const product = record(item.product, 'product');
124
+ exact(product, ['id', 'version'], 'product');
125
+ const workspace = record(item.workspace, 'workspace');
126
+ exact(workspace, ['read', 'write'], 'workspace');
127
+ const read = compatibility(workspace.read), write = compatibility(workspace.write);
128
+ for (const entry of write)
129
+ if (!read.some((candidate) => candidate.schema === entry.schema &&
130
+ entry.features.every((feature) => candidate.features.includes(feature))))
131
+ invalid('write compatibility outside read support');
132
+ const components = array(item.components, 128, 1).map(component);
133
+ unique(components.map((item) => `${item.platform}:${item.id}`), 'platform component');
134
+ const minimum = record(item.minimum_hosts, 'minimum hosts');
135
+ const minimum_hosts = Object.fromEntries(Object.entries(minimum).map(([key, value]) => {
136
+ const target = platform(key), host = record(value, 'minimum host');
137
+ exact(host, ['os_release', 'glibc'], 'minimum host');
138
+ if ((target.startsWith('linux-') && typeof host.glibc !== 'string') ||
139
+ (!target.startsWith('linux-') && host.glibc !== null))
140
+ invalid('host ABI');
141
+ const glibc = host.glibc === null ? null : text(host.glibc, 'glibc version', 40);
142
+ if (glibc !== null && !/^[0-9]+\.[0-9]+$/u.test(glibc))
143
+ invalid('glibc version');
144
+ return [target, { os_release: version(host.os_release), glibc }];
145
+ }));
146
+ const supported = [...new Set(components.map((item) => item.platform))].sort();
147
+ if (JSON.stringify(Object.keys(minimum_hosts).sort()) !== JSON.stringify(supported))
148
+ invalid('host/component platform coverage');
149
+ const launches = array(item.launches, 64, 1).map((value) => {
150
+ const launch = record(value, 'launch');
151
+ exact(launch, ['id', 'platform', 'executable', 'environment', 'argv'], 'launch');
152
+ if (launch.environment !== 'isolated' && launch.environment !== 'cli-auth')
153
+ invalid('launch environment');
154
+ const target = platform(launch.platform);
155
+ const argv = array(launch.argv, 32).map((value) => {
156
+ const arg = record(value, 'launch argument');
157
+ if (Object.hasOwn(arg, 'literal')) {
158
+ exact(arg, ['literal'], 'literal argument');
159
+ return { literal: text(arg.literal, 'literal argument', 4096) };
160
+ }
161
+ return componentPath(arg, components, target);
162
+ });
163
+ return {
164
+ id: id(launch.id),
165
+ platform: target,
166
+ executable: componentPath(launch.executable, components, target, true),
167
+ environment: launch.environment,
168
+ argv,
169
+ };
170
+ });
171
+ unique(launches.map((item) => `${item.platform}:${item.id}`), 'platform launch');
172
+ for (const target of supported)
173
+ if (!launches.some((launch) => launch.platform === target))
174
+ invalid('platform launch coverage');
175
+ return deepFreeze({
176
+ schema: RUNTIME_MANIFEST_SCHEMA,
177
+ bootstrap_protocol: RUNTIME_BOOTSTRAP_PROTOCOL,
178
+ product: { id: id(product.id), version: version(product.version) },
179
+ minimum_hosts,
180
+ workspace: { read, write },
181
+ components,
182
+ launches,
183
+ });
184
+ }
185
+ export function trustRuntimeManifest(bytes, expectedSha256) {
186
+ sha(expectedSha256);
187
+ if (bytes.byteLength > 32 * 1024 * 1024 ||
188
+ createHash('sha256').update(bytes).digest('hex') !== expectedSha256)
189
+ runtimeError('RUNTIME_MANIFEST_INTEGRITY', 'Runtime manifest bytes do not match the independent trust anchor.');
190
+ let value;
191
+ try {
192
+ value = JSON.parse(Buffer.from(bytes).toString('utf8'));
193
+ }
194
+ catch {
195
+ invalid('JSON');
196
+ }
197
+ const result = Object.freeze({ sha256: expectedSha256, manifest: parseRuntimeManifest(value) });
198
+ trusted.add(result);
199
+ return result;
200
+ }
201
+ export function loadTrustedRuntimeManifest(file, expectedSha256) {
202
+ const stat = fs.lstatSync(file);
203
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 32 * 1024 * 1024)
204
+ runtimeError('RUNTIME_MANIFEST_FILE', 'Runtime manifest must be a bounded regular file.');
205
+ return trustRuntimeManifest(fs.readFileSync(file), expectedSha256);
206
+ }
207
+ export function assertTrustedManifest(value) {
208
+ if (!value || !trusted.has(value))
209
+ runtimeError('RUNTIME_MANIFEST_UNTRUSTED', 'Supply a manifest verified against an independent trusted digest.');
210
+ }
211
+ export function componentKey(value) {
212
+ return contentHash(value);
213
+ }
214
+ export function assertWorkspaceCompatibility(value, request, access) {
215
+ assertTrustedManifest(value);
216
+ const support = value.manifest.workspace[access]?.find((entry) => entry.schema === request.schema);
217
+ if (!support || !request.features.every((feature) => support.features.includes(feature)))
218
+ runtimeError('RUNTIME_WORKSPACE_INCOMPATIBLE', 'The selected runtime does not support the requested workspace access/schema/features.');
219
+ }
220
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../src/lib/runtime/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EACL,KAAK,EACL,UAAU,EACV,eAAe,EACf,KAAK,EACL,EAAE,EACF,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,GAAG,EACH,IAAI,EACJ,MAAM,EACN,OAAO,GACR,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAU7B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAU,CAAC;AAEtC,SAAS,aAAa,CAAC,KAAc;IACnC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;QACtD,KAAK,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,yBAAyB,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACvD,IAAI,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,CAAC,CACtC,CAAC;QACF,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QACtC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,MAAM,CACJ,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EACnC,kBAAkB,CACnB,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,SAAS,SAAS,CAAC,KAAc;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACxC,KAAK,CACH,IAAI,EACJ;QACE,IAAI;QACJ,SAAS;QACT,UAAU;QACV,SAAS;QACT,OAAO;QACP,gBAAgB;QAChB,iBAAiB;QACjB,MAAM;QACN,UAAU;QACV,YAAY;QACZ,WAAW;QACX,oBAAoB;KACrB,EACD,WAAW,CACZ,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM,KAAK,sBAAsB;QAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,GAAoB,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAC7C,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC;QACnE,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG;YAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;QACrD,KAAK,IAAI,KAAK,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC7F,CAAC,CAAC,CAAC;IACH,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CACJ,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EACvC,uBAAuB,CACxB,CAAC;IACF,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;YACnC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;gBACxD,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,OAAO,KAAK,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACzE,MAAM,YAAY,GAAG,CAAC,KAAc,EAAE,EAAE;QACtC,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,EAC5D,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC/D,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5B,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3D,IAAI,CAAC,KAAK,EAAE,oBAAoB,EAAE,GAAG,CAAC,CACvC,CAAC;IACF,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC9B,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACxE,MAAM,kBAAkB,GAAG,MAAM,CAAC,WAAW,CAC3C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAC1E,CAAC;IACF,OAAO;QACL,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QAC9B,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjC,OAAO,EAAE;YACP,MAAM,EAAE,sBAAsB;YAC9B,GAAG,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC;YACjC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;SAC5B;QACD,KAAK;QACL,cAAc,EAAE,OAAO;QACvB,eAAe,EAAE,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC;QACnD,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QAC7B,QAAQ;QACR,UAAU;QACV,SAAS;QACT,kBAAkB;KACnB,CAAC;AACJ,CAAC;AACD,SAAS,aAAa,CACpB,KAAc,EACd,UAAuC,EACvC,MAAc,EACd,UAAU,GAAG,KAAK;IAElB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC9C,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EACrC,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,IAAI,IAAI,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;IAC7F,MAAM,IAAI,GAAG,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC7D,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACjF,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAChD,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACvC,KAAK,CACH,IAAI,EACJ;QACE,QAAQ;QACR,oBAAoB;QACpB,SAAS;QACT,eAAe;QACf,WAAW;QACX,YAAY;QACZ,UAAU;KACX,EACD,UAAU,CACX,CAAC;IACF,IACE,IAAI,CAAC,MAAM,KAAK,uBAAuB;QACvC,IAAI,CAAC,kBAAkB,KAAK,0BAA0B;QAEtD,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACtD,KAAK,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EACxC,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,KAAK;QACvB,IACE,CAAC,IAAI,CAAC,IAAI,CACR,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YACjC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAC1E;YAED,OAAO,CAAC,0CAA0C,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,CACJ,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EACvD,oBAAoB,CACrB,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CACtC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,EAC1B,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC;QACrD,IACE,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC;YAC/D,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC;YAErD,OAAO,CAAC,UAAU,CAAC,CAAC;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;QACjF,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,eAAe,CAAC,CAAC;QACjF,OAAO,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CACH,CAAC;IACF,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/E,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;QACjF,OAAO,CAAC,kCAAkC,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAoB,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC1E,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;QACjF,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU;YACxE,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAChD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;YAC7C,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;gBAClC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC,CAAC;gBAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC;YAClE,CAAC;YACD,OAAO,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QACH,OAAO;YACL,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YACjB,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC;YACtE,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,IAAI;SACL,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,CACJ,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EACrD,iBAAiB,CAClB,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,SAAS;QAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC;YAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAClG,OAAO,UAAU,CAAC;QAChB,MAAM,EAAE,uBAAuB;QAC/B,kBAAkB,EAAE,0BAA0B;QAC9C,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QAClE,aAAa;QACb,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QAC1B,UAAU;QACV,QAAQ;KACT,CAAC,CAAC;AACL,CAAC;AACD,MAAM,UAAU,oBAAoB,CAClC,KAAiB,EACjB,cAAsB;IAEtB,GAAG,CAAC,cAAc,CAAC,CAAC;IACpB,IACE,KAAK,CAAC,UAAU,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;QACnC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,cAAc;QAEnE,YAAY,CACV,4BAA4B,EAC5B,mEAAmE,CACpE,CAAC;IACJ,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,0BAA0B,CACxC,IAAY,EACZ,cAAsB;IAEtB,MAAM,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;QACzE,YAAY,CAAC,uBAAuB,EAAE,kDAAkD,CAAC,CAAC;IAC5F,OAAO,oBAAoB,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,CAAC;AACrE,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,KAA6B;IACjE,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QAC/B,YAAY,CACV,4BAA4B,EAC5B,mEAAmE,CACpE,CAAC;AACN,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,KAAuB;IAClD,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AACD,MAAM,UAAU,4BAA4B,CAC1C,KAA6B,EAC7B,OAA+B,EAC/B,MAAwB;IAExB,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,CACpD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAC3C,CAAC;IACF,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtF,YAAY,CACV,gCAAgC,EAChC,uFAAuF,CACxF,CAAC;AACN,CAAC","sourcesContent":["import fs from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { contentHash, runtimeError } from './files.js';\nimport {\n array,\n deepFreeze,\n distributionUrl,\n exact,\n id,\n integer,\n invalid,\n platform,\n record,\n relativeFile,\n sha,\n text,\n unique,\n version,\n} from './manifest-values.js';\nimport {\n RUNTIME_ARCHIVE_FORMAT,\n RUNTIME_BOOTSTRAP_PROTOCOL,\n RUNTIME_MANIFEST_SCHEMA,\n} from './manifest-types.js';\nimport type {\n ComponentFile,\n ComponentPath,\n RuntimeComponent,\n RuntimeLaunch,\n RuntimeManifest,\n TrustedRuntimeManifest,\n WorkspaceCompatibility,\n} from './manifest-types.js';\nconst trusted = new WeakSet<object>();\n\nfunction compatibility(value: unknown): WorkspaceCompatibility[] {\n const result = array(value, 32).map((item) => {\n const entry = record(item, 'workspace compatibility');\n exact(entry, ['schema', 'features'], 'workspace compatibility');\n const features = array(entry.features, 64).map((value) =>\n text(value, 'workspace feature', 128),\n );\n unique(features, 'workspace feature');\n return { schema: text(entry.schema, 'workspace schema', 128), features };\n });\n unique(\n result.map((entry) => entry.schema),\n 'workspace schema',\n );\n return result;\n}\nfunction component(value: unknown): RuntimeComponent {\n const item = record(value, 'component');\n exact(\n item,\n [\n 'id',\n 'version',\n 'platform',\n 'archive',\n 'files',\n 'content_sha256',\n 'production_lock',\n 'sbom',\n 'licenses',\n 'provenance',\n 'protocols',\n 'asset_fingerprints',\n ],\n 'component',\n );\n const archive = record(item.archive, 'archive');\n exact(archive, ['format', 'url', 'bytes', 'sha256'], 'archive');\n if (archive.format !== RUNTIME_ARCHIVE_FORMAT) invalid('archive format');\n let total = 0;\n const files: ComponentFile[] = array(item.files, 50_000, 1).map((value) => {\n const file = record(value, 'component file');\n exact(file, ['path', 'bytes', 'sha256', 'mode'], 'component file');\n if (file.mode !== 420 && file.mode !== 493) invalid('file mode');\n const bytes = integer(file.bytes, 512 * 1024 * 1024);\n total += bytes;\n return { path: relativeFile(file.path), bytes, sha256: sha(file.sha256), mode: file.mode };\n });\n if (total > 2 * 1024 * 1024 * 1024) invalid('unpacked size');\n const paths = files.map((file) => file.path);\n unique(\n paths.map((path) => path.toLowerCase()),\n 'case-folded file path',\n );\n if (JSON.stringify(paths) !== JSON.stringify([...paths].sort())) invalid('file order');\n const pathSet = new Set(paths.map((path) => path.toLowerCase()));\n for (const file of paths) {\n const parts = file.split('/');\n for (let i = 1; i < parts.length; i++)\n if (pathSet.has(parts.slice(0, i).join('/').toLowerCase()))\n invalid('file/directory collision');\n }\n const content = sha(item.content_sha256);\n if (content !== contentHash(files)) invalid('component content SHA-256');\n const requiredFile = (value: unknown) => {\n const file = relativeFile(value);\n if (!paths.includes(file)) invalid('metadata file reference');\n return file;\n };\n const licenses = array(item.licenses, 64, 1).map(requiredFile),\n provenance = array(item.provenance, 64, 1).map(requiredFile);\n unique(licenses, 'license');\n unique(provenance, 'provenance');\n const protocols = array(item.protocols, 32, 1).map((value) =>\n text(value, 'component protocol', 128),\n );\n unique(protocols, 'protocol');\n const fingerprints = record(item.asset_fingerprints, 'asset fingerprints');\n if (Object.keys(fingerprints).length > 64) invalid('fingerprint count');\n const asset_fingerprints = Object.fromEntries(\n Object.entries(fingerprints).map(([key, value]) => [id(key), sha(value)]),\n );\n return {\n id: id(item.id),\n version: version(item.version),\n platform: platform(item.platform),\n archive: {\n format: RUNTIME_ARCHIVE_FORMAT,\n url: distributionUrl(archive.url),\n bytes: integer(archive.bytes, 512 * 1024 * 1024, 1),\n sha256: sha(archive.sha256),\n },\n files,\n content_sha256: content,\n production_lock: requiredFile(item.production_lock),\n sbom: requiredFile(item.sbom),\n licenses,\n provenance,\n protocols,\n asset_fingerprints,\n };\n}\nfunction componentPath(\n value: unknown,\n components: readonly RuntimeComponent[],\n target: string,\n executable = false,\n): ComponentPath {\n const entry = record(value, 'component path');\n exact(entry, ['component', 'path'], 'component path');\n const componentId = id(entry.component),\n file = relativeFile(entry.path);\n const owner = components.find((item) => item.platform === target && item.id === componentId);\n const fact = owner?.files.find((item) => item.path === file);\n if (!fact || (executable && fact.mode !== 493)) invalid('launch file reference');\n return { component: componentId, path: file };\n}\nexport function parseRuntimeManifest(value: unknown): RuntimeManifest {\n const item = record(value, 'manifest');\n exact(\n item,\n [\n 'schema',\n 'bootstrap_protocol',\n 'product',\n 'minimum_hosts',\n 'workspace',\n 'components',\n 'launches',\n ],\n 'manifest',\n );\n if (\n item.schema !== RUNTIME_MANIFEST_SCHEMA ||\n item.bootstrap_protocol !== RUNTIME_BOOTSTRAP_PROTOCOL\n )\n invalid('manifest protocol version');\n const product = record(item.product, 'product');\n exact(product, ['id', 'version'], 'product');\n const workspace = record(item.workspace, 'workspace');\n exact(workspace, ['read', 'write'], 'workspace');\n const read = compatibility(workspace.read),\n write = compatibility(workspace.write);\n for (const entry of write)\n if (\n !read.some(\n (candidate) =>\n candidate.schema === entry.schema &&\n entry.features.every((feature) => candidate.features.includes(feature)),\n )\n )\n invalid('write compatibility outside read support');\n const components = array(item.components, 128, 1).map(component);\n unique(\n components.map((item) => `${item.platform}:${item.id}`),\n 'platform component',\n );\n const minimum = record(item.minimum_hosts, 'minimum hosts');\n const minimum_hosts = Object.fromEntries(\n Object.entries(minimum).map(([key, value]) => {\n const target = platform(key),\n host = record(value, 'minimum host');\n exact(host, ['os_release', 'glibc'], 'minimum host');\n if (\n (target.startsWith('linux-') && typeof host.glibc !== 'string') ||\n (!target.startsWith('linux-') && host.glibc !== null)\n )\n invalid('host ABI');\n const glibc = host.glibc === null ? null : text(host.glibc, 'glibc version', 40);\n if (glibc !== null && !/^[0-9]+\\.[0-9]+$/u.test(glibc)) invalid('glibc version');\n return [target, { os_release: version(host.os_release), glibc }];\n }),\n );\n const supported = [...new Set(components.map((item) => item.platform))].sort();\n if (JSON.stringify(Object.keys(minimum_hosts).sort()) !== JSON.stringify(supported))\n invalid('host/component platform coverage');\n const launches: RuntimeLaunch[] = array(item.launches, 64, 1).map((value) => {\n const launch = record(value, 'launch');\n exact(launch, ['id', 'platform', 'executable', 'environment', 'argv'], 'launch');\n if (launch.environment !== 'isolated' && launch.environment !== 'cli-auth')\n invalid('launch environment');\n const target = platform(launch.platform);\n const argv = array(launch.argv, 32).map((value) => {\n const arg = record(value, 'launch argument');\n if (Object.hasOwn(arg, 'literal')) {\n exact(arg, ['literal'], 'literal argument');\n return { literal: text(arg.literal, 'literal argument', 4096) };\n }\n return componentPath(arg, components, target);\n });\n return {\n id: id(launch.id),\n platform: target,\n executable: componentPath(launch.executable, components, target, true),\n environment: launch.environment,\n argv,\n };\n });\n unique(\n launches.map((item) => `${item.platform}:${item.id}`),\n 'platform launch',\n );\n for (const target of supported)\n if (!launches.some((launch) => launch.platform === target)) invalid('platform launch coverage');\n return deepFreeze({\n schema: RUNTIME_MANIFEST_SCHEMA,\n bootstrap_protocol: RUNTIME_BOOTSTRAP_PROTOCOL,\n product: { id: id(product.id), version: version(product.version) },\n minimum_hosts,\n workspace: { read, write },\n components,\n launches,\n });\n}\nexport function trustRuntimeManifest(\n bytes: Uint8Array,\n expectedSha256: string,\n): TrustedRuntimeManifest {\n sha(expectedSha256);\n if (\n bytes.byteLength > 32 * 1024 * 1024 ||\n createHash('sha256').update(bytes).digest('hex') !== expectedSha256\n )\n runtimeError(\n 'RUNTIME_MANIFEST_INTEGRITY',\n 'Runtime manifest bytes do not match the independent trust anchor.',\n );\n let value: unknown;\n try {\n value = JSON.parse(Buffer.from(bytes).toString('utf8'));\n } catch {\n invalid('JSON');\n }\n const result = Object.freeze({ sha256: expectedSha256, manifest: parseRuntimeManifest(value) });\n trusted.add(result);\n return result;\n}\nexport function loadTrustedRuntimeManifest(\n file: string,\n expectedSha256: string,\n): TrustedRuntimeManifest {\n const stat = fs.lstatSync(file);\n if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 32 * 1024 * 1024)\n runtimeError('RUNTIME_MANIFEST_FILE', 'Runtime manifest must be a bounded regular file.');\n return trustRuntimeManifest(fs.readFileSync(file), expectedSha256);\n}\nexport function assertTrustedManifest(value: TrustedRuntimeManifest): void {\n if (!value || !trusted.has(value))\n runtimeError(\n 'RUNTIME_MANIFEST_UNTRUSTED',\n 'Supply a manifest verified against an independent trusted digest.',\n );\n}\nexport function componentKey(value: RuntimeComponent): string {\n return contentHash(value);\n}\nexport function assertWorkspaceCompatibility(\n value: TrustedRuntimeManifest,\n request: WorkspaceCompatibility,\n access: 'read' | 'write',\n): void {\n assertTrustedManifest(value);\n const support = value.manifest.workspace[access]?.find(\n (entry) => entry.schema === request.schema,\n );\n if (!support || !request.features.every((feature) => support.features.includes(feature)))\n runtimeError(\n 'RUNTIME_WORKSPACE_INCOMPATIBLE',\n 'The selected runtime does not support the requested workspace access/schema/features.',\n );\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { FoundryCommandSpecAsyncSpawnOptions, FoundryCommandSpecSpawnResult } from '../../command-spec.js';
2
+ /** Resolve only after close, including cancellation and output overflow, so callers retain component leases. */
3
+ export declare function spawnRuntimeProcess(executable: string, argv: readonly string[], options: FoundryCommandSpecAsyncSpawnOptions): Promise<FoundryCommandSpecSpawnResult>;