everything-dev 2.0.0-rc.6 → 2.0.0-rc.7

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 (116) hide show
  1. package/README.md +2 -2
  2. package/dist/build.cjs +1 -1
  3. package/dist/build.mjs +1 -1
  4. package/dist/bundle-cache.cjs +1 -1
  5. package/dist/bundle-cache.cjs.map +1 -1
  6. package/dist/bundle-cache.mjs +1 -1
  7. package/dist/bundle-cache.mjs.map +1 -1
  8. package/dist/cli.cjs +2 -2
  9. package/dist/cli.cjs.map +1 -1
  10. package/dist/cli.mjs +1 -1
  11. package/dist/cli.mjs.map +1 -1
  12. package/dist/commands/deploy.cjs +111 -1
  13. package/dist/commands/deploy.cjs.map +1 -1
  14. package/dist/commands/deploy.mjs +112 -2
  15. package/dist/commands/deploy.mjs.map +1 -1
  16. package/dist/commands/smoke.cjs +41 -0
  17. package/dist/commands/smoke.cjs.map +1 -0
  18. package/dist/commands/smoke.mjs +41 -0
  19. package/dist/commands/smoke.mjs.map +1 -0
  20. package/dist/commands/upgrade.cjs +2 -2
  21. package/dist/commands/upgrade.cjs.map +1 -1
  22. package/dist/commands/upgrade.mjs +1 -1
  23. package/dist/commands/upgrade.mjs.map +1 -1
  24. package/dist/contract.cjs +27 -1
  25. package/dist/contract.cjs.map +1 -1
  26. package/dist/contract.d.cts +65 -1
  27. package/dist/contract.d.mts +65 -1
  28. package/dist/contract.meta.cjs +13 -1
  29. package/dist/contract.meta.cjs.map +1 -1
  30. package/dist/contract.meta.d.cts +23 -1
  31. package/dist/contract.meta.d.mts +23 -1
  32. package/dist/contract.meta.mjs +13 -1
  33. package/dist/contract.meta.mjs.map +1 -1
  34. package/dist/contract.mjs +26 -2
  35. package/dist/contract.mjs.map +1 -1
  36. package/dist/dev-log-pipeline.cjs +6 -0
  37. package/dist/dev-log-pipeline.cjs.map +1 -1
  38. package/dist/dev-log-pipeline.mjs +6 -0
  39. package/dist/dev-log-pipeline.mjs.map +1 -1
  40. package/dist/dev-program.cjs +20 -3
  41. package/dist/dev-program.cjs.map +1 -1
  42. package/dist/dev-program.mjs +20 -4
  43. package/dist/dev-program.mjs.map +1 -1
  44. package/dist/dev-session.cjs +1 -0
  45. package/dist/dev-session.cjs.map +1 -1
  46. package/dist/dev-session.mjs +1 -0
  47. package/dist/dev-session.mjs.map +1 -1
  48. package/dist/fastkv.cjs +21 -3
  49. package/dist/fastkv.cjs.map +1 -1
  50. package/dist/fastkv.d.cts +14 -1
  51. package/dist/fastkv.d.mts +14 -1
  52. package/dist/fastkv.mjs +21 -5
  53. package/dist/fastkv.mjs.map +1 -1
  54. package/dist/{mf.cjs → federation.cjs} +6 -13
  55. package/dist/federation.cjs.map +1 -0
  56. package/dist/{mf.d.cts → federation.d.cts} +2 -2
  57. package/dist/{mf.d.mts → federation.d.mts} +2 -2
  58. package/dist/{mf.mjs → federation.mjs} +6 -13
  59. package/dist/federation.mjs.map +1 -0
  60. package/dist/http-client.cjs +70 -53
  61. package/dist/http-client.cjs.map +1 -1
  62. package/dist/http-client.mjs +70 -54
  63. package/dist/http-client.mjs.map +1 -1
  64. package/dist/image-deploy.cjs +9 -0
  65. package/dist/image-deploy.cjs.map +1 -1
  66. package/dist/image-deploy.mjs +9 -1
  67. package/dist/image-deploy.mjs.map +1 -1
  68. package/dist/index.cjs +4 -0
  69. package/dist/index.d.cts +3 -3
  70. package/dist/index.d.mts +3 -3
  71. package/dist/index.mjs +3 -3
  72. package/dist/orchestrator.cjs +39 -35
  73. package/dist/orchestrator.cjs.map +1 -1
  74. package/dist/orchestrator.mjs +39 -35
  75. package/dist/orchestrator.mjs.map +1 -1
  76. package/dist/plugin.cjs +2 -0
  77. package/dist/plugin.cjs.map +1 -1
  78. package/dist/plugin.d.cts +24 -0
  79. package/dist/plugin.d.mts +24 -0
  80. package/dist/plugin.mjs +2 -0
  81. package/dist/plugin.mjs.map +1 -1
  82. package/dist/process-registry.cjs +1 -1
  83. package/dist/process-registry.mjs +1 -1
  84. package/dist/publish.cjs +3 -3
  85. package/dist/publish.cjs.map +1 -1
  86. package/dist/publish.mjs +4 -4
  87. package/dist/publish.mjs.map +1 -1
  88. package/dist/resolver.cjs +293 -0
  89. package/dist/resolver.cjs.map +1 -0
  90. package/dist/resolver.d.cts +99 -0
  91. package/dist/resolver.d.mts +99 -0
  92. package/dist/resolver.mjs +284 -0
  93. package/dist/resolver.mjs.map +1 -0
  94. package/dist/smoke.cjs +262 -0
  95. package/dist/smoke.cjs.map +1 -0
  96. package/dist/smoke.mjs +260 -0
  97. package/dist/smoke.mjs.map +1 -0
  98. package/dist/version-manifest-resolve.cjs +3 -3
  99. package/dist/version-manifest-resolve.cjs.map +1 -1
  100. package/dist/version-manifest-resolve.mjs +1 -1
  101. package/dist/version-manifest-resolve.mjs.map +1 -1
  102. package/dist/workspace.cjs +1 -1
  103. package/dist/workspace.mjs +1 -1
  104. package/package.json +9 -9
  105. package/dist/bundle-fs-resolve.cjs +0 -235
  106. package/dist/bundle-fs-resolve.cjs.map +0 -1
  107. package/dist/bundle-fs-resolve.d.cts +0 -82
  108. package/dist/bundle-fs-resolve.d.mts +0 -82
  109. package/dist/bundle-fs-resolve.mjs +0 -228
  110. package/dist/bundle-fs-resolve.mjs.map +0 -1
  111. package/dist/bundle-path.cjs +0 -48
  112. package/dist/bundle-path.cjs.map +0 -1
  113. package/dist/bundle-path.mjs +0 -45
  114. package/dist/bundle-path.mjs.map +0 -1
  115. package/dist/mf.cjs.map +0 -1
  116. package/dist/mf.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"version-manifest-resolve.cjs","names":["bundleUrlToStagedPath","existsSync","resolveContained","path","readdirSync","statSync","WorkspaceVersionManifestSchema","readFileSync","createHash"],"sources":["../src/version-manifest-resolve.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n type WorkspaceVersionManifest,\n WorkspaceVersionManifestSchema,\n} from \"every-plugin/version-manifest\";\nimport { bundleUrlToStagedPath, resolveContained } from \"./bundle-path\";\n\n/**\n * Version-manifest slot resolution (atomic-deploys 04): a config slot's\n * `pin` ({ manifest, integrity }) resolves to the derived entry-level fields\n * every consumer needs. The cache is keyed by the full pin — the pinned\n * bytes are immutable, so a verified entry is cached for the process\n * lifetime and serves as last-known-good if the origin later fails; a fetch\n * or SRI failure with nothing cached propagates (a boot-time resolution\n * failure fails the deploy, which is the platform's rollback).\n */\n\nexport interface ResolvedSlotVersion {\n /** Absolute URL of the content-hashed container entry. */\n entryUrl: string;\n entryIntegrity: string;\n /** Absolute URL of the hashed browser manifest (mf-manifest), when present. */\n browserManifestUrl?: string;\n /** Absolute URL of the content-hashed SSR entry, when present. */\n ssrEntryUrl?: string;\n ssrIntegrity?: string;\n /** Full per-file digest map of the dist (object path → SRI), when the\n * pinned manifest carries one — the diff base for skip-unchanged uploads. */\n files?: Record<string, string>;\n}\n\nexport interface SlotPin {\n /** versioned manifest filename, relative to the slot's production base */\n manifest: string;\n /** the manifest document's own SRI */\n integrity: string;\n}\n\nconst cache = new Map<string, ResolvedSlotVersion>();\n\nexport function clearSlotVersionCache(): void {\n cache.clear();\n}\n\nfunction fetchText(url: string, fetchImpl: typeof fetch): Promise<string> {\n return fetchImpl(url).then((response) => {\n if (!response.ok) throw new Error(`version manifest fetch failed: ${response.status}`);\n return response.text();\n });\n}\n\nfunction slotVersionFromManifest(\n base: string,\n manifest: WorkspaceVersionManifest,\n): ResolvedSlotVersion {\n const trimmedBase = base.replace(/\\/$/, \"\");\n return {\n entryUrl: `${trimmedBase}/${manifest.entry}`,\n entryIntegrity: manifest.entryIntegrity,\n ...(manifest.browserManifest\n ? { browserManifestUrl: `${trimmedBase}/${manifest.browserManifest.file}` }\n : {}),\n ...(manifest.ssr\n ? {\n ssrEntryUrl: `${trimmedBase}/${manifest.ssr.entry}`,\n ssrIntegrity: manifest.ssr.integrity,\n }\n : {}),\n ...(manifest.files ? { files: manifest.files } : {}),\n };\n}\n\n/**\n * Staged-slot preference (ADR 0020/0021 self-contained tier): when a runtime\n * stages its own namespace under `BOS_BUNDLE_DIR`, a slot resolves from the\n * staged dist's own version manifest instead of the config's pin — pinned\n * manifest bytes that predate the image (deploy lag after a release bump)\n * cannot exist in the staged namespace, so their hashed files would 404 the\n * disk and fall through to the network, where the stale immutable bytes\n * still answer 200 and boot a foreign build. The staged manifest is trusted\n * (staged by the image build itself) and skipped entirely when the slot is\n * absent from the staged namespace or the pinned manifest is present (the\n * normal healthy case, which keeps the pin's SRI check).\n */\nfunction readStagedSlotVersion(base: string, pin: SlotPin): ResolvedSlotVersion | null {\n const bundleDir = process.env.BOS_BUNDLE_DIR;\n if (!bundleDir) return null;\n\n const slotDir = bundleUrlToStagedPath(base, bundleDir);\n if (!slotDir || !existsSync(slotDir)) return null;\n\n const pinnedManifestPath = resolveContained(slotDir, pin.manifest);\n if (!pinnedManifestPath || existsSync(pinnedManifestPath)) return null;\n\n const versionsDir = path.join(slotDir, \"versions\");\n if (!existsSync(versionsDir)) return null;\n const manifests = readdirSync(versionsDir)\n .filter((name) => name.endsWith(\".json\"))\n .map((name) => path.join(versionsDir, name))\n .filter((file) => statSync(file).isFile())\n .sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs || (a < b ? -1 : 1));\n if (manifests.length === 0) return null;\n const manifestPath = manifests[0];\n if (!manifestPath) return null;\n\n try {\n const manifest = WorkspaceVersionManifestSchema.parse(\n JSON.parse(readFileSync(manifestPath, \"utf8\")),\n );\n return slotVersionFromManifest(base, manifest);\n } catch {\n return null;\n }\n}\n\nexport async function resolveSlotVersion(input: {\n base: string;\n pin: SlotPin;\n fetchImpl?: typeof fetch;\n}): Promise<ResolvedSlotVersion> {\n const key = `${input.base}::${input.pin.manifest}::${input.pin.integrity}`;\n // content-addressed: a verified pin is cached for the process lifetime and\n // never refetched — the cache IS the last-known-good\n const cached = cache.get(key);\n if (cached) return cached;\n\n const staged = readStagedSlotVersion(input.base, input.pin);\n if (staged) {\n cache.set(key, staged);\n return staged;\n }\n\n const manifestUrl = `${input.base.replace(/\\/$/, \"\")}/${input.pin.manifest.replace(/^\\//, \"\")}`;\n const body = await fetchText(manifestUrl, input.fetchImpl ?? fetch);\n const computed = `sha384-${createHash(\"sha384\").update(body).digest(\"base64\")}`;\n if (computed !== input.pin.integrity) {\n throw new Error(\n `[SRI] version manifest integrity mismatch for ${manifestUrl}\\n Expected: ${input.pin.integrity}\\n Computed: ${computed}`,\n );\n }\n const manifest: WorkspaceVersionManifest = WorkspaceVersionManifestSchema.parse(JSON.parse(body));\n\n const resolved = slotVersionFromManifest(input.base, manifest);\n cache.set(key, resolved);\n return resolved;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"version-manifest-resolve.cjs","names":["bundleUrlToStagedPath","existsSync","resolveContained","path","readdirSync","statSync","WorkspaceVersionManifestSchema","readFileSync","createHash"],"sources":["../src/version-manifest-resolve.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n type WorkspaceVersionManifest,\n WorkspaceVersionManifestSchema,\n} from \"every-plugin/version-manifest\";\nimport { bundleUrlToStagedPath, resolveContained } from \"./resolver\";\n\n/**\n * Version-manifest slot resolution (atomic-deploys 04): a config slot's\n * `pin` ({ manifest, integrity }) resolves to the derived entry-level fields\n * every consumer needs. The cache is keyed by the full pin — the pinned\n * bytes are immutable, so a verified entry is cached for the process\n * lifetime and serves as last-known-good if the origin later fails; a fetch\n * or SRI failure with nothing cached propagates (a boot-time resolution\n * failure fails the deploy, which is the platform's rollback).\n */\n\nexport interface ResolvedSlotVersion {\n /** Absolute URL of the content-hashed container entry. */\n entryUrl: string;\n entryIntegrity: string;\n /** Absolute URL of the hashed browser manifest (mf-manifest), when present. */\n browserManifestUrl?: string;\n /** Absolute URL of the content-hashed SSR entry, when present. */\n ssrEntryUrl?: string;\n ssrIntegrity?: string;\n /** Full per-file digest map of the dist (object path → SRI), when the\n * pinned manifest carries one — the diff base for skip-unchanged uploads. */\n files?: Record<string, string>;\n}\n\nexport interface SlotPin {\n /** versioned manifest filename, relative to the slot's production base */\n manifest: string;\n /** the manifest document's own SRI */\n integrity: string;\n}\n\nconst cache = new Map<string, ResolvedSlotVersion>();\n\nexport function clearSlotVersionCache(): void {\n cache.clear();\n}\n\nfunction fetchText(url: string, fetchImpl: typeof fetch): Promise<string> {\n return fetchImpl(url).then((response) => {\n if (!response.ok) throw new Error(`version manifest fetch failed: ${response.status}`);\n return response.text();\n });\n}\n\nfunction slotVersionFromManifest(\n base: string,\n manifest: WorkspaceVersionManifest,\n): ResolvedSlotVersion {\n const trimmedBase = base.replace(/\\/$/, \"\");\n return {\n entryUrl: `${trimmedBase}/${manifest.entry}`,\n entryIntegrity: manifest.entryIntegrity,\n ...(manifest.browserManifest\n ? { browserManifestUrl: `${trimmedBase}/${manifest.browserManifest.file}` }\n : {}),\n ...(manifest.ssr\n ? {\n ssrEntryUrl: `${trimmedBase}/${manifest.ssr.entry}`,\n ssrIntegrity: manifest.ssr.integrity,\n }\n : {}),\n ...(manifest.files ? { files: manifest.files } : {}),\n };\n}\n\n/**\n * Staged-slot preference (ADR 0020/0021 self-contained tier): when a runtime\n * stages its own namespace under `BOS_BUNDLE_DIR`, a slot resolves from the\n * staged dist's own version manifest instead of the config's pin — pinned\n * manifest bytes that predate the image (deploy lag after a release bump)\n * cannot exist in the staged namespace, so their hashed files would 404 the\n * disk and fall through to the network, where the stale immutable bytes\n * still answer 200 and boot a foreign build. The staged manifest is trusted\n * (staged by the image build itself) and skipped entirely when the slot is\n * absent from the staged namespace or the pinned manifest is present (the\n * normal healthy case, which keeps the pin's SRI check).\n */\nfunction readStagedSlotVersion(base: string, pin: SlotPin): ResolvedSlotVersion | null {\n const bundleDir = process.env.BOS_BUNDLE_DIR;\n if (!bundleDir) return null;\n\n const slotDir = bundleUrlToStagedPath(base, bundleDir);\n if (!slotDir || !existsSync(slotDir)) return null;\n\n const pinnedManifestPath = resolveContained(slotDir, pin.manifest);\n if (!pinnedManifestPath || existsSync(pinnedManifestPath)) return null;\n\n const versionsDir = path.join(slotDir, \"versions\");\n if (!existsSync(versionsDir)) return null;\n const manifests = readdirSync(versionsDir)\n .filter((name) => name.endsWith(\".json\"))\n .map((name) => path.join(versionsDir, name))\n .filter((file) => statSync(file).isFile())\n .sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs || (a < b ? -1 : 1));\n if (manifests.length === 0) return null;\n const manifestPath = manifests[0];\n if (!manifestPath) return null;\n\n try {\n const manifest = WorkspaceVersionManifestSchema.parse(\n JSON.parse(readFileSync(manifestPath, \"utf8\")),\n );\n return slotVersionFromManifest(base, manifest);\n } catch {\n return null;\n }\n}\n\nexport async function resolveSlotVersion(input: {\n base: string;\n pin: SlotPin;\n fetchImpl?: typeof fetch;\n}): Promise<ResolvedSlotVersion> {\n const key = `${input.base}::${input.pin.manifest}::${input.pin.integrity}`;\n // content-addressed: a verified pin is cached for the process lifetime and\n // never refetched — the cache IS the last-known-good\n const cached = cache.get(key);\n if (cached) return cached;\n\n const staged = readStagedSlotVersion(input.base, input.pin);\n if (staged) {\n cache.set(key, staged);\n return staged;\n }\n\n const manifestUrl = `${input.base.replace(/\\/$/, \"\")}/${input.pin.manifest.replace(/^\\//, \"\")}`;\n const body = await fetchText(manifestUrl, input.fetchImpl ?? fetch);\n const computed = `sha384-${createHash(\"sha384\").update(body).digest(\"base64\")}`;\n if (computed !== input.pin.integrity) {\n throw new Error(\n `[SRI] version manifest integrity mismatch for ${manifestUrl}\\n Expected: ${input.pin.integrity}\\n Computed: ${computed}`,\n );\n }\n const manifest: WorkspaceVersionManifest = WorkspaceVersionManifestSchema.parse(JSON.parse(body));\n\n const resolved = slotVersionFromManifest(input.base, manifest);\n cache.set(key, resolved);\n return resolved;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { bundleUrlToStagedPath, resolveContained } from "./bundle-path.mjs";
1
+ import { bundleUrlToStagedPath, resolveContained } from "./resolver.mjs";
2
2
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { createHash } from "node:crypto";
@@ -1 +1 @@
1
- {"version":3,"file":"version-manifest-resolve.mjs","names":[],"sources":["../src/version-manifest-resolve.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n type WorkspaceVersionManifest,\n WorkspaceVersionManifestSchema,\n} from \"every-plugin/version-manifest\";\nimport { bundleUrlToStagedPath, resolveContained } from \"./bundle-path\";\n\n/**\n * Version-manifest slot resolution (atomic-deploys 04): a config slot's\n * `pin` ({ manifest, integrity }) resolves to the derived entry-level fields\n * every consumer needs. The cache is keyed by the full pin — the pinned\n * bytes are immutable, so a verified entry is cached for the process\n * lifetime and serves as last-known-good if the origin later fails; a fetch\n * or SRI failure with nothing cached propagates (a boot-time resolution\n * failure fails the deploy, which is the platform's rollback).\n */\n\nexport interface ResolvedSlotVersion {\n /** Absolute URL of the content-hashed container entry. */\n entryUrl: string;\n entryIntegrity: string;\n /** Absolute URL of the hashed browser manifest (mf-manifest), when present. */\n browserManifestUrl?: string;\n /** Absolute URL of the content-hashed SSR entry, when present. */\n ssrEntryUrl?: string;\n ssrIntegrity?: string;\n /** Full per-file digest map of the dist (object path → SRI), when the\n * pinned manifest carries one — the diff base for skip-unchanged uploads. */\n files?: Record<string, string>;\n}\n\nexport interface SlotPin {\n /** versioned manifest filename, relative to the slot's production base */\n manifest: string;\n /** the manifest document's own SRI */\n integrity: string;\n}\n\nconst cache = new Map<string, ResolvedSlotVersion>();\n\nexport function clearSlotVersionCache(): void {\n cache.clear();\n}\n\nfunction fetchText(url: string, fetchImpl: typeof fetch): Promise<string> {\n return fetchImpl(url).then((response) => {\n if (!response.ok) throw new Error(`version manifest fetch failed: ${response.status}`);\n return response.text();\n });\n}\n\nfunction slotVersionFromManifest(\n base: string,\n manifest: WorkspaceVersionManifest,\n): ResolvedSlotVersion {\n const trimmedBase = base.replace(/\\/$/, \"\");\n return {\n entryUrl: `${trimmedBase}/${manifest.entry}`,\n entryIntegrity: manifest.entryIntegrity,\n ...(manifest.browserManifest\n ? { browserManifestUrl: `${trimmedBase}/${manifest.browserManifest.file}` }\n : {}),\n ...(manifest.ssr\n ? {\n ssrEntryUrl: `${trimmedBase}/${manifest.ssr.entry}`,\n ssrIntegrity: manifest.ssr.integrity,\n }\n : {}),\n ...(manifest.files ? { files: manifest.files } : {}),\n };\n}\n\n/**\n * Staged-slot preference (ADR 0020/0021 self-contained tier): when a runtime\n * stages its own namespace under `BOS_BUNDLE_DIR`, a slot resolves from the\n * staged dist's own version manifest instead of the config's pin — pinned\n * manifest bytes that predate the image (deploy lag after a release bump)\n * cannot exist in the staged namespace, so their hashed files would 404 the\n * disk and fall through to the network, where the stale immutable bytes\n * still answer 200 and boot a foreign build. The staged manifest is trusted\n * (staged by the image build itself) and skipped entirely when the slot is\n * absent from the staged namespace or the pinned manifest is present (the\n * normal healthy case, which keeps the pin's SRI check).\n */\nfunction readStagedSlotVersion(base: string, pin: SlotPin): ResolvedSlotVersion | null {\n const bundleDir = process.env.BOS_BUNDLE_DIR;\n if (!bundleDir) return null;\n\n const slotDir = bundleUrlToStagedPath(base, bundleDir);\n if (!slotDir || !existsSync(slotDir)) return null;\n\n const pinnedManifestPath = resolveContained(slotDir, pin.manifest);\n if (!pinnedManifestPath || existsSync(pinnedManifestPath)) return null;\n\n const versionsDir = path.join(slotDir, \"versions\");\n if (!existsSync(versionsDir)) return null;\n const manifests = readdirSync(versionsDir)\n .filter((name) => name.endsWith(\".json\"))\n .map((name) => path.join(versionsDir, name))\n .filter((file) => statSync(file).isFile())\n .sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs || (a < b ? -1 : 1));\n if (manifests.length === 0) return null;\n const manifestPath = manifests[0];\n if (!manifestPath) return null;\n\n try {\n const manifest = WorkspaceVersionManifestSchema.parse(\n JSON.parse(readFileSync(manifestPath, \"utf8\")),\n );\n return slotVersionFromManifest(base, manifest);\n } catch {\n return null;\n }\n}\n\nexport async function resolveSlotVersion(input: {\n base: string;\n pin: SlotPin;\n fetchImpl?: typeof fetch;\n}): Promise<ResolvedSlotVersion> {\n const key = `${input.base}::${input.pin.manifest}::${input.pin.integrity}`;\n // content-addressed: a verified pin is cached for the process lifetime and\n // never refetched — the cache IS the last-known-good\n const cached = cache.get(key);\n if (cached) return cached;\n\n const staged = readStagedSlotVersion(input.base, input.pin);\n if (staged) {\n cache.set(key, staged);\n return staged;\n }\n\n const manifestUrl = `${input.base.replace(/\\/$/, \"\")}/${input.pin.manifest.replace(/^\\//, \"\")}`;\n const body = await fetchText(manifestUrl, input.fetchImpl ?? fetch);\n const computed = `sha384-${createHash(\"sha384\").update(body).digest(\"base64\")}`;\n if (computed !== input.pin.integrity) {\n throw new Error(\n `[SRI] version manifest integrity mismatch for ${manifestUrl}\\n Expected: ${input.pin.integrity}\\n Computed: ${computed}`,\n );\n }\n const manifest: WorkspaceVersionManifest = WorkspaceVersionManifestSchema.parse(JSON.parse(body));\n\n const resolved = slotVersionFromManifest(input.base, manifest);\n cache.set(key, resolved);\n return resolved;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"version-manifest-resolve.mjs","names":[],"sources":["../src/version-manifest-resolve.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n type WorkspaceVersionManifest,\n WorkspaceVersionManifestSchema,\n} from \"every-plugin/version-manifest\";\nimport { bundleUrlToStagedPath, resolveContained } from \"./resolver\";\n\n/**\n * Version-manifest slot resolution (atomic-deploys 04): a config slot's\n * `pin` ({ manifest, integrity }) resolves to the derived entry-level fields\n * every consumer needs. The cache is keyed by the full pin — the pinned\n * bytes are immutable, so a verified entry is cached for the process\n * lifetime and serves as last-known-good if the origin later fails; a fetch\n * or SRI failure with nothing cached propagates (a boot-time resolution\n * failure fails the deploy, which is the platform's rollback).\n */\n\nexport interface ResolvedSlotVersion {\n /** Absolute URL of the content-hashed container entry. */\n entryUrl: string;\n entryIntegrity: string;\n /** Absolute URL of the hashed browser manifest (mf-manifest), when present. */\n browserManifestUrl?: string;\n /** Absolute URL of the content-hashed SSR entry, when present. */\n ssrEntryUrl?: string;\n ssrIntegrity?: string;\n /** Full per-file digest map of the dist (object path → SRI), when the\n * pinned manifest carries one — the diff base for skip-unchanged uploads. */\n files?: Record<string, string>;\n}\n\nexport interface SlotPin {\n /** versioned manifest filename, relative to the slot's production base */\n manifest: string;\n /** the manifest document's own SRI */\n integrity: string;\n}\n\nconst cache = new Map<string, ResolvedSlotVersion>();\n\nexport function clearSlotVersionCache(): void {\n cache.clear();\n}\n\nfunction fetchText(url: string, fetchImpl: typeof fetch): Promise<string> {\n return fetchImpl(url).then((response) => {\n if (!response.ok) throw new Error(`version manifest fetch failed: ${response.status}`);\n return response.text();\n });\n}\n\nfunction slotVersionFromManifest(\n base: string,\n manifest: WorkspaceVersionManifest,\n): ResolvedSlotVersion {\n const trimmedBase = base.replace(/\\/$/, \"\");\n return {\n entryUrl: `${trimmedBase}/${manifest.entry}`,\n entryIntegrity: manifest.entryIntegrity,\n ...(manifest.browserManifest\n ? { browserManifestUrl: `${trimmedBase}/${manifest.browserManifest.file}` }\n : {}),\n ...(manifest.ssr\n ? {\n ssrEntryUrl: `${trimmedBase}/${manifest.ssr.entry}`,\n ssrIntegrity: manifest.ssr.integrity,\n }\n : {}),\n ...(manifest.files ? { files: manifest.files } : {}),\n };\n}\n\n/**\n * Staged-slot preference (ADR 0020/0021 self-contained tier): when a runtime\n * stages its own namespace under `BOS_BUNDLE_DIR`, a slot resolves from the\n * staged dist's own version manifest instead of the config's pin — pinned\n * manifest bytes that predate the image (deploy lag after a release bump)\n * cannot exist in the staged namespace, so their hashed files would 404 the\n * disk and fall through to the network, where the stale immutable bytes\n * still answer 200 and boot a foreign build. The staged manifest is trusted\n * (staged by the image build itself) and skipped entirely when the slot is\n * absent from the staged namespace or the pinned manifest is present (the\n * normal healthy case, which keeps the pin's SRI check).\n */\nfunction readStagedSlotVersion(base: string, pin: SlotPin): ResolvedSlotVersion | null {\n const bundleDir = process.env.BOS_BUNDLE_DIR;\n if (!bundleDir) return null;\n\n const slotDir = bundleUrlToStagedPath(base, bundleDir);\n if (!slotDir || !existsSync(slotDir)) return null;\n\n const pinnedManifestPath = resolveContained(slotDir, pin.manifest);\n if (!pinnedManifestPath || existsSync(pinnedManifestPath)) return null;\n\n const versionsDir = path.join(slotDir, \"versions\");\n if (!existsSync(versionsDir)) return null;\n const manifests = readdirSync(versionsDir)\n .filter((name) => name.endsWith(\".json\"))\n .map((name) => path.join(versionsDir, name))\n .filter((file) => statSync(file).isFile())\n .sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs || (a < b ? -1 : 1));\n if (manifests.length === 0) return null;\n const manifestPath = manifests[0];\n if (!manifestPath) return null;\n\n try {\n const manifest = WorkspaceVersionManifestSchema.parse(\n JSON.parse(readFileSync(manifestPath, \"utf8\")),\n );\n return slotVersionFromManifest(base, manifest);\n } catch {\n return null;\n }\n}\n\nexport async function resolveSlotVersion(input: {\n base: string;\n pin: SlotPin;\n fetchImpl?: typeof fetch;\n}): Promise<ResolvedSlotVersion> {\n const key = `${input.base}::${input.pin.manifest}::${input.pin.integrity}`;\n // content-addressed: a verified pin is cached for the process lifetime and\n // never refetched — the cache IS the last-known-good\n const cached = cache.get(key);\n if (cached) return cached;\n\n const staged = readStagedSlotVersion(input.base, input.pin);\n if (staged) {\n cache.set(key, staged);\n return staged;\n }\n\n const manifestUrl = `${input.base.replace(/\\/$/, \"\")}/${input.pin.manifest.replace(/^\\//, \"\")}`;\n const body = await fetchText(manifestUrl, input.fetchImpl ?? fetch);\n const computed = `sha384-${createHash(\"sha384\").update(body).digest(\"base64\")}`;\n if (computed !== input.pin.integrity) {\n throw new Error(\n `[SRI] version manifest integrity mismatch for ${manifestUrl}\\n Expected: ${input.pin.integrity}\\n Computed: ${computed}`,\n );\n }\n const manifest: WorkspaceVersionManifest = WorkspaceVersionManifestSchema.parse(JSON.parse(body));\n\n const resolved = slotVersionFromManifest(input.base, manifest);\n cache.set(key, resolved);\n return resolved;\n}\n"],"mappings":"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"}
@@ -2,8 +2,8 @@ const require_run = require('./utils/run.cjs');
2
2
  let node_fs = require("node:fs");
3
3
  let node_path = require("node:path");
4
4
  let effect = require("effect");
5
- let yaml = require("yaml");
6
5
  let node_fs_promises = require("node:fs/promises");
6
+ let yaml = require("yaml");
7
7
 
8
8
  //#region src/workspace.ts
9
9
  var DepsBuildFailure = class extends effect.Data.TaggedError("DepsBuildFailure") {
@@ -2,8 +2,8 @@ import { run } from "./utils/run.mjs";
2
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import { Data } from "effect";
5
- import { parse } from "yaml";
6
5
  import { readdir, stat } from "node:fs/promises";
6
+ import { parse } from "yaml";
7
7
 
8
8
  //#region src/workspace.ts
9
9
  var DepsBuildFailure = class extends Data.TaggedError("DepsBuildFailure") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "everything-dev",
3
- "version": "2.0.0-rc.6",
3
+ "version": "2.0.0-rc.7",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=20.11"
@@ -54,10 +54,10 @@
54
54
  "import": "./dist/version-manifest-resolve.mjs",
55
55
  "require": "./dist/version-manifest-resolve.cjs"
56
56
  },
57
- "./bundle-fs-resolve": {
58
- "types": "./dist/bundle-fs-resolve.d.mts",
59
- "import": "./dist/bundle-fs-resolve.mjs",
60
- "require": "./dist/bundle-fs-resolve.cjs"
57
+ "./resolver": {
58
+ "types": "./dist/resolver.d.mts",
59
+ "import": "./dist/resolver.mjs",
60
+ "require": "./dist/resolver.cjs"
61
61
  },
62
62
  "./fastkv": {
63
63
  "types": "./dist/fastkv.d.mts",
@@ -69,10 +69,10 @@
69
69
  "import": "./dist/contract.meta.mjs",
70
70
  "require": "./dist/contract.meta.cjs"
71
71
  },
72
- "./mf": {
73
- "types": "./dist/mf.d.mts",
74
- "import": "./dist/mf.mjs",
75
- "require": "./dist/mf.cjs"
72
+ "./federation": {
73
+ "types": "./dist/federation.d.mts",
74
+ "import": "./dist/federation.mjs",
75
+ "require": "./dist/federation.cjs"
76
76
  },
77
77
  "./integrity": {
78
78
  "types": "./dist/integrity.d.mts",
@@ -1,235 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
- const require_bundle_path = require('./bundle-path.cjs');
4
- const require_config = require('./config.cjs');
5
- const require_bundle_cache = require('./bundle-cache.cjs');
6
- let node_fs = require("node:fs");
7
- let node_path = require("node:path");
8
- node_path = require_runtime.__toESM(node_path, 1);
9
- let effect = require("effect");
10
- let node_fs_promises = require("node:fs/promises");
11
- let every_plugin_build_artifact_names = require("every-plugin/build/artifact-names");
12
-
13
- //#region src/bundle-fs-resolve.ts
14
- var BundleReadError = class extends effect.Schema.TaggedError()("BundleReadError", {
15
- path: effect.Schema.String,
16
- cause: effect.Schema.optional(effect.Schema.Unknown)
17
- }) {};
18
- const MIME_TYPES = {
19
- ".js": "text/javascript",
20
- ".mjs": "text/javascript",
21
- ".cjs": "text/javascript",
22
- ".css": "text/css",
23
- ".json": "application/json",
24
- ".map": "application/json",
25
- ".svg": "image/svg+xml",
26
- ".png": "image/png",
27
- ".jpg": "image/jpeg",
28
- ".jpeg": "image/jpeg",
29
- ".gif": "image/gif",
30
- ".webp": "image/webp",
31
- ".avif": "image/avif",
32
- ".ico": "image/x-icon",
33
- ".html": "text/html",
34
- ".htm": "text/html",
35
- ".webmanifest": "application/manifest+json",
36
- ".md": "text/markdown",
37
- ".ts": "text/plain",
38
- ".woff": "font/woff",
39
- ".woff2": "font/woff2",
40
- ".ttf": "font/ttf",
41
- ".otf": "font/otf",
42
- ".eot": "application/vnd.ms-fontobject",
43
- ".wasm": "application/wasm",
44
- ".txt": "text/plain",
45
- ".xml": "application/xml"
46
- };
47
- /**
48
- * Own-namespace path for a bundle URL: the shared URL→staged-path mapping,
49
- * narrowed to the runtime identity — a URL whose encoded namespace differs
50
- * from `namespace.account`/`namespace.gateway` must fall to the network/cache
51
- * path, never serve a sibling namespace's staged bytes.
52
- */
53
- function bundleUrlToLocalPath(url, namespace) {
54
- const filePath = require_bundle_path.bundleUrlToStagedPath(url, namespace.bundleDir);
55
- if (!filePath) return null;
56
- const nsDir = node_path.default.resolve(namespace.bundleDir, namespace.account, namespace.gateway);
57
- if (filePath !== nsDir && !filePath.startsWith(nsDir + node_path.default.sep)) return null;
58
- return filePath;
59
- }
60
- var BundleResolver = class BundleResolver extends effect.Context.Service()("everything-dev/bundle-fs-resolve/BundleResolver") {
61
- static layer(namespace) {
62
- const respond = effect.Effect.fn("BundleResolver.respond")(function* (url) {
63
- const filePath = bundleUrlToLocalPath(url, namespace);
64
- if (!filePath) return null;
65
- const bytes = yield* effect.Effect.tryPromise({
66
- try: () => (0, node_fs_promises.readFile)(filePath),
67
- catch: (cause) => new BundleReadError({
68
- path: filePath,
69
- cause
70
- })
71
- }).pipe(effect.Effect.catchTag("BundleReadError", () => effect.Effect.succeed(null)));
72
- if (bytes === null) return null;
73
- const name = node_path.default.basename(filePath);
74
- const contentType = MIME_TYPES[node_path.default.extname(name).toLowerCase()] ?? "application/octet-stream";
75
- return new Response(new Uint8Array(bytes), { headers: {
76
- "content-type": contentType,
77
- "cache-control": (0, every_plugin_build_artifact_names.cacheControlOf)(name),
78
- etag: `"${Buffer.from(bytes.subarray(0, 4096)).toString("base64").slice(0, 24)}"`
79
- } });
80
- });
81
- return effect.Layer.effect(BundleResolver, effect.Effect.succeed(BundleResolver.of({ lookup: (input) => {
82
- const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
83
- return respond(url);
84
- } })));
85
- }
86
- };
87
- const staleResponse = (bytes, url) => {
88
- const name = url.split("?")[0].split("/").pop() ?? "";
89
- const contentType = MIME_TYPES[node_path.default.extname(name).toLowerCase()] ?? "application/octet-stream";
90
- return new Response(bytes.slice().buffer, {
91
- status: 200,
92
- headers: {
93
- "content-type": contentType,
94
- "x-bundle-cache": "stale"
95
- }
96
- });
97
- };
98
- const FETCH_RETRY_ATTEMPTS = 3;
99
- const FETCH_RETRY_BASE_DELAY_MS = 250;
100
- const isTransientStatus = (status) => status === 429 || status >= 500;
101
- function requestMethod(input, init) {
102
- if (init?.method) return init.method.toUpperCase();
103
- if (typeof input === "string" || input instanceof URL) return "GET";
104
- return input.method.toUpperCase();
105
- }
106
- /**
107
- * Bounded transient-failure retry for idempotent GETs crossing the
108
- * interceptor (ADR 0021 amendment — the CDN-only image): a cold boot has no
109
- * staged fallback, so one edge/registry hiccup during the load window would
110
- * hard-fail the host or a plugin with no recourse. Network errors and
111
- * 429/5xx responses retry twice (250ms, 750ms backoff) before propagating;
112
- * non-transient statuses and non-GET requests pass through untouched. After
113
- * exhausting attempts a stale-if-error cache still sees the final failure.
114
- */
115
- async function fetchWithTransientRetry(original, input, init) {
116
- if (requestMethod(input, init) !== "GET") return original(input, init);
117
- let lastError;
118
- let lastResponse = null;
119
- for (let attempt = 0; attempt < FETCH_RETRY_ATTEMPTS; attempt++) {
120
- if (attempt > 0) await new Promise((resolve) => setTimeout(resolve, FETCH_RETRY_BASE_DELAY_MS * 3 ** (attempt - 1)));
121
- try {
122
- const response = await original(input, init);
123
- if (!isTransientStatus(response.status)) return response;
124
- lastResponse = response;
125
- } catch (error) {
126
- lastError = error;
127
- }
128
- }
129
- if (lastResponse) return lastResponse;
130
- throw lastError;
131
- }
132
- /**
133
- * Installs the resolver as a global fetch interceptor — the one seam every
134
- * boot-time consumer shares (config manifest discovery, contract-type
135
- * fetches, orchestrator host loading, MF remoteEntry/identity probes).
136
- * One layered resolution policy: staged disk → network → stale-if-error.
137
- * Own-namespace URLs resolve from the staged directory and fall through to
138
- * the original fetch on a miss (a partially-staged namespace boots over the
139
- * wire instead of failing); a miss never touches the write-through cache —
140
- * for the own namespace the staged disk IS the resilience artifact. Foreign
141
- * `/bundles/…` URLs get the network with the stale-if-error cache; every
142
- * other URL falls through to the original fetch untouched. Inert when
143
- * neither a staged namespace nor a cache is configured.
144
- */
145
- function installGlobalBundleFetch(options) {
146
- const namespace = options.namespace;
147
- const cacheDir = options.cacheDir;
148
- const runtime = namespace ? effect.ManagedRuntime.make(BundleResolver.layer(namespace)) : null;
149
- const original = globalThis.fetch;
150
- const patched = (async (input, init) => {
151
- const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
152
- if (namespace && bundleUrlToLocalPath(url, namespace)) {
153
- if (!runtime) throw new Error("unreachable: resolver runtime missing");
154
- const response = await runtime.runPromise(effect.Effect.gen(function* () {
155
- return yield* (yield* BundleResolver).lookup(input);
156
- }));
157
- if (response !== null) return response;
158
- return fetchWithTransientRetry(original, input, init);
159
- }
160
- if (cacheDir !== void 0 && require_bundle_cache.bundleCachePath(url, { cacheDir })) return (async () => {
161
- try {
162
- const response = await fetchWithTransientRetry(original, input, init);
163
- if (response.ok) try {
164
- const bytes = new Uint8Array(await response.clone().arrayBuffer());
165
- await require_bundle_cache.writeBundleCache(url, bytes, { cacheDir });
166
- } catch {}
167
- else {
168
- const cached = await require_bundle_cache.readBundleCache(url, { cacheDir });
169
- if (cached) return staleResponse(cached, url);
170
- }
171
- return response;
172
- } catch (error) {
173
- const cached = await require_bundle_cache.readBundleCache(url, { cacheDir });
174
- if (cached) return staleResponse(cached, url);
175
- throw error;
176
- }
177
- })();
178
- return fetchWithTransientRetry(original, input, init);
179
- });
180
- const originalPreconnect = original.preconnect;
181
- if (originalPreconnect) patched.preconnect = originalPreconnect.bind(original);
182
- globalThis.fetch = patched;
183
- return { uninstall: async () => {
184
- if (globalThis.fetch === patched) globalThis.fetch = original;
185
- if (runtime) await runtime.dispose();
186
- } };
187
- }
188
- /**
189
- * Boot-time installer for the CLI: derives the own namespace from
190
- * `BOS_BUNDLE_DIR` plus the runtime identity (`BOS_ACCOUNT`/`BOS_GATEWAY`
191
- * registry env taking precedence over the bos.config.json fields), and the
192
- * foreign-namespace cache from `BOS_BUNDLE_CACHE_DIR`. Tier auto-detection
193
- * (ADR 0021): an identity whose namespace is not actually staged under the
194
- * bundle dir drops to the registry tier — plain network fetch — instead of
195
- * deterministically 404ing own-namespace URLs against a foreign image's
196
- * staged bytes. Never throws — a missing or malformed identity leaves the
197
- * default network fetch in place.
198
- */
199
- function installBundleFetchFromEnv(input) {
200
- const bundleDir = process.env.BOS_BUNDLE_DIR;
201
- const cacheDir = process.env.BOS_BUNDLE_CACHE_DIR;
202
- if (!bundleDir && cacheDir === void 0) return null;
203
- let configAccount;
204
- let configGateway;
205
- const configPath = input.configPath;
206
- if (configPath && !require_config.isAppDescriptorPath(configPath)) try {
207
- const parsed = JSON.parse((0, node_fs.readFileSync)(configPath, "utf8"));
208
- configAccount = parsed.account;
209
- configGateway = parsed.domain;
210
- } catch {}
211
- const account = process.env.BOS_ACCOUNT ?? configAccount;
212
- const gateway = process.env.BOS_GATEWAY ?? configGateway;
213
- if (bundleDir && (!account || !gateway)) return null;
214
- let namespace;
215
- if (bundleDir && account && gateway) {
216
- if ((0, node_fs.existsSync)(node_path.default.join(bundleDir, account, gateway))) namespace = {
217
- bundleDir,
218
- account,
219
- gateway
220
- };
221
- else console.warn(`[bundles] staged namespace ${account}/${gateway} not found under ${bundleDir} — registry tier (network fetch)`);
222
- }
223
- return installGlobalBundleFetch({
224
- namespace,
225
- cacheDir: cacheDir ?? (namespace ? require_bundle_cache.bundleCacheRoot() : void 0)
226
- });
227
- }
228
-
229
- //#endregion
230
- exports.BundleReadError = BundleReadError;
231
- exports.BundleResolver = BundleResolver;
232
- exports.bundleUrlToLocalPath = bundleUrlToLocalPath;
233
- exports.installBundleFetchFromEnv = installBundleFetchFromEnv;
234
- exports.installGlobalBundleFetch = installGlobalBundleFetch;
235
- //# sourceMappingURL=bundle-fs-resolve.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bundle-fs-resolve.cjs","names":["Schema","bundleUrlToStagedPath","path","Context","Effect","readFile","cacheControlOf","Layer","ManagedRuntime","bundleCachePath","writeBundleCache","readBundleCache","isAppDescriptorPath","readFileSync","existsSync","bundleCacheRoot"],"sources":["../src/bundle-fs-resolve.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Context, Effect, Layer, ManagedRuntime, Schema } from \"effect\";\nimport { cacheControlOf } from \"every-plugin/build/artifact-names\";\nimport {\n bundleCachePath,\n bundleCacheRoot,\n readBundleCache,\n writeBundleCache,\n} from \"./bundle-cache\";\nimport { bundleUrlToStagedPath } from \"./bundle-path\";\nimport { isAppDescriptorPath } from \"./config\";\n\n/**\n * Local-first bundle resolution (ADR 0011 amendment; unified policy, ADR 0021\n * amendment): a self-contained runtime image stages its own namespace under\n * `BOS_BUNDLE_DIR` as `bundles/<account>/<gateway>/<workspace>/…` and consumes\n * those bytes directly from disk; a miss falls through to the network, so a\n * partially-staged namespace boots over the wire instead of failing. The\n * registry tier (children, `BOS_BUNDLE_DIR` unset) keeps the network fetch —\n * the namespace guard below only ever matches the runtime's own\n * account/gateway, never another runtime's layout.\n */\n\nexport interface BundleNamespace {\n readonly bundleDir: string;\n readonly account: string;\n readonly gateway: string;\n}\n\nexport class BundleReadError extends Schema.TaggedError<BundleReadError>()(\"BundleReadError\", {\n path: Schema.String,\n cause: Schema.optional(Schema.Unknown),\n}) {}\n\nconst MIME_TYPES: Record<string, string> = {\n \".js\": \"text/javascript\",\n \".mjs\": \"text/javascript\",\n \".cjs\": \"text/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".map\": \"application/json\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".ico\": \"image/x-icon\",\n \".html\": \"text/html\",\n \".htm\": \"text/html\",\n \".webmanifest\": \"application/manifest+json\",\n \".md\": \"text/markdown\",\n \".ts\": \"text/plain\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".otf\": \"font/otf\",\n \".eot\": \"application/vnd.ms-fontobject\",\n \".wasm\": \"application/wasm\",\n \".txt\": \"text/plain\",\n \".xml\": \"application/xml\",\n};\n\n/**\n * Own-namespace path for a bundle URL: the shared URL→staged-path mapping,\n * narrowed to the runtime identity — a URL whose encoded namespace differs\n * from `namespace.account`/`namespace.gateway` must fall to the network/cache\n * path, never serve a sibling namespace's staged bytes.\n */\nexport function bundleUrlToLocalPath(url: string, namespace: BundleNamespace): string | null {\n const filePath = bundleUrlToStagedPath(url, namespace.bundleDir);\n if (!filePath) return null;\n\n const nsDir = path.resolve(namespace.bundleDir, namespace.account, namespace.gateway);\n if (filePath !== nsDir && !filePath.startsWith(nsDir + path.sep)) return null;\n\n return filePath;\n}\n\nexport class BundleResolver extends Context.Service<\n BundleResolver,\n {\n /** Resolve a fetch target from the staged namespace; null = miss or not our namespace — fall through to the network. */\n readonly lookup: (input: string | URL | Request) => Effect.Effect<Response | null>;\n }\n>()(\"everything-dev/bundle-fs-resolve/BundleResolver\") {\n static layer(namespace: BundleNamespace): Layer.Layer<BundleResolver> {\n const respond = Effect.fn(\"BundleResolver.respond\")(function* (\n url: string,\n ): Effect.fn.Return<Response | null, never> {\n const filePath = bundleUrlToLocalPath(url, namespace);\n if (!filePath) return null;\n const bytes = yield* Effect.tryPromise({\n try: () => readFile(filePath),\n catch: (cause) => new BundleReadError({ path: filePath, cause }),\n }).pipe(Effect.catchTag(\"BundleReadError\", () => Effect.succeed(null)));\n if (bytes === null) return null;\n const name = path.basename(filePath);\n const contentType =\n MIME_TYPES[path.extname(name).toLowerCase()] ?? \"application/octet-stream\";\n return new Response(new Uint8Array(bytes), {\n headers: {\n \"content-type\": contentType,\n \"cache-control\": cacheControlOf(name),\n etag: `\"${Buffer.from(bytes.subarray(0, 4096)).toString(\"base64\").slice(0, 24)}\"`,\n },\n });\n });\n\n return Layer.effect(\n BundleResolver,\n Effect.succeed(\n BundleResolver.of({\n lookup: (input) => {\n const url =\n typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n return respond(url);\n },\n }),\n ),\n );\n }\n}\n\nexport interface BundleFetchHandle {\n readonly uninstall: () => Promise<void>;\n}\n\nexport interface BundleFetchOptions {\n /** Own-namespace FS resolution — requires a staged `BOS_BUNDLE_DIR`. */\n namespace?: BundleNamespace;\n /**\n * Foreign-namespace stale-if-error cache (child tier): `/bundles/…` URLs\n * outside the own namespace write through to disk on success and serve\n * the last-known-good bytes when the origin fails. Enabled implicitly\n * when `namespace` is present (deployment contexts), or explicitly via\n * `BOS_BUNDLE_CACHE_DIR`.\n */\n cacheDir?: string;\n}\n\ntype FetchImpl = typeof globalThis.fetch;\n\nconst staleResponse = (bytes: Uint8Array, url: string): Response => {\n const name = url.split(\"?\")[0].split(\"/\").pop() ?? \"\";\n const contentType = MIME_TYPES[path.extname(name).toLowerCase()] ?? \"application/octet-stream\";\n return new Response(bytes.slice().buffer, {\n status: 200,\n headers: { \"content-type\": contentType, \"x-bundle-cache\": \"stale\" },\n });\n};\n\nconst FETCH_RETRY_ATTEMPTS = 3;\nconst FETCH_RETRY_BASE_DELAY_MS = 250;\n\nconst isTransientStatus = (status: number): boolean => status === 429 || status >= 500;\n\nfunction requestMethod(input: Parameters<FetchImpl>[0], init?: Parameters<FetchImpl>[1]): string {\n if (init?.method) return init.method.toUpperCase();\n if (typeof input === \"string\" || input instanceof URL) return \"GET\";\n return input.method.toUpperCase();\n}\n\n/**\n * Bounded transient-failure retry for idempotent GETs crossing the\n * interceptor (ADR 0021 amendment — the CDN-only image): a cold boot has no\n * staged fallback, so one edge/registry hiccup during the load window would\n * hard-fail the host or a plugin with no recourse. Network errors and\n * 429/5xx responses retry twice (250ms, 750ms backoff) before propagating;\n * non-transient statuses and non-GET requests pass through untouched. After\n * exhausting attempts a stale-if-error cache still sees the final failure.\n */\nasync function fetchWithTransientRetry(\n original: FetchImpl,\n input: Parameters<FetchImpl>[0],\n init?: Parameters<FetchImpl>[1],\n): Promise<Response> {\n if (requestMethod(input, init) !== \"GET\") return original(input, init);\n let lastError: unknown;\n let lastResponse: Response | null = null;\n for (let attempt = 0; attempt < FETCH_RETRY_ATTEMPTS; attempt++) {\n if (attempt > 0) {\n await new Promise((resolve) =>\n setTimeout(resolve, FETCH_RETRY_BASE_DELAY_MS * 3 ** (attempt - 1)),\n );\n }\n try {\n const response = await original(input, init);\n if (!isTransientStatus(response.status)) return response;\n lastResponse = response;\n } catch (error) {\n lastError = error;\n }\n }\n if (lastResponse) return lastResponse;\n throw lastError;\n}\n\n/**\n * Installs the resolver as a global fetch interceptor — the one seam every\n * boot-time consumer shares (config manifest discovery, contract-type\n * fetches, orchestrator host loading, MF remoteEntry/identity probes).\n * One layered resolution policy: staged disk → network → stale-if-error.\n * Own-namespace URLs resolve from the staged directory and fall through to\n * the original fetch on a miss (a partially-staged namespace boots over the\n * wire instead of failing); a miss never touches the write-through cache —\n * for the own namespace the staged disk IS the resilience artifact. Foreign\n * `/bundles/…` URLs get the network with the stale-if-error cache; every\n * other URL falls through to the original fetch untouched. Inert when\n * neither a staged namespace nor a cache is configured.\n */\nexport function installGlobalBundleFetch(options: BundleFetchOptions): BundleFetchHandle {\n const namespace = options.namespace;\n const cacheDir = options.cacheDir;\n const runtime = namespace ? ManagedRuntime.make(BundleResolver.layer(namespace)) : null;\n const original: FetchImpl = globalThis.fetch;\n const patched = (async (input: Parameters<FetchImpl>[0], init?: Parameters<FetchImpl>[1]) => {\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n\n if (namespace && bundleUrlToLocalPath(url, namespace)) {\n if (!runtime) throw new Error(\"unreachable: resolver runtime missing\");\n const response = await runtime.runPromise(\n Effect.gen(function* () {\n const resolver = yield* BundleResolver;\n return yield* resolver.lookup(input);\n }),\n );\n if (response !== null) return response;\n return fetchWithTransientRetry(original, input, init);\n }\n\n if (cacheDir !== undefined && bundleCachePath(url, { cacheDir })) {\n return (async () => {\n try {\n const response = await fetchWithTransientRetry(original, input, init);\n if (response.ok) {\n try {\n const bytes = new Uint8Array(await response.clone().arrayBuffer());\n await writeBundleCache(url, bytes, { cacheDir });\n } catch {\n // write-through is best-effort\n }\n } else {\n const cached = await readBundleCache(url, { cacheDir });\n if (cached) return staleResponse(cached, url);\n }\n return response;\n } catch (error) {\n const cached = await readBundleCache(url, { cacheDir });\n if (cached) return staleResponse(cached, url);\n throw error;\n }\n })();\n }\n\n return fetchWithTransientRetry(original, input, init);\n }) as FetchImpl;\n const originalPreconnect = (original as Partial<FetchImpl>).preconnect;\n if (originalPreconnect) {\n patched.preconnect = originalPreconnect.bind(original);\n }\n globalThis.fetch = patched;\n return {\n uninstall: async () => {\n if (globalThis.fetch === patched) {\n globalThis.fetch = original;\n }\n if (runtime) await runtime.dispose();\n },\n };\n}\n\n/**\n * Boot-time installer for the CLI: derives the own namespace from\n * `BOS_BUNDLE_DIR` plus the runtime identity (`BOS_ACCOUNT`/`BOS_GATEWAY`\n * registry env taking precedence over the bos.config.json fields), and the\n * foreign-namespace cache from `BOS_BUNDLE_CACHE_DIR`. Tier auto-detection\n * (ADR 0021): an identity whose namespace is not actually staged under the\n * bundle dir drops to the registry tier — plain network fetch — instead of\n * deterministically 404ing own-namespace URLs against a foreign image's\n * staged bytes. Never throws — a missing or malformed identity leaves the\n * default network fetch in place.\n */\nexport function installBundleFetchFromEnv(input: {\n configPath?: string | null;\n}): BundleFetchHandle | null {\n const bundleDir = process.env.BOS_BUNDLE_DIR;\n const cacheDir = process.env.BOS_BUNDLE_CACHE_DIR;\n if (!bundleDir && cacheDir === undefined) return null;\n\n let configAccount: string | undefined;\n let configGateway: string | undefined;\n const configPath = input.configPath;\n if (configPath && !isAppDescriptorPath(configPath)) {\n try {\n const parsed = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n account?: string;\n domain?: string;\n };\n configAccount = parsed.account;\n configGateway = parsed.domain;\n } catch {\n // unreadable config — identity may still come from the registry env\n }\n }\n\n const account = process.env.BOS_ACCOUNT ?? configAccount;\n const gateway = process.env.BOS_GATEWAY ?? configGateway;\n if (bundleDir && (!account || !gateway)) return null;\n\n let namespace: BundleNamespace | undefined;\n if (bundleDir && account && gateway) {\n if (existsSync(path.join(bundleDir, account, gateway))) {\n namespace = { bundleDir, account, gateway };\n } else {\n console.warn(\n `[bundles] staged namespace ${account}/${gateway} not found under ${bundleDir} — registry tier (network fetch)`,\n );\n }\n }\n return installGlobalBundleFetch({\n namespace,\n cacheDir: cacheDir ?? (namespace ? bundleCacheRoot() : undefined),\n });\n}\n"],"mappings":"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"}
@@ -1,82 +0,0 @@
1
- import { Context, Effect, Layer, Schema } from "effect";
2
- //#region src/bundle-fs-resolve.d.ts
3
- /**
4
- * Local-first bundle resolution (ADR 0011 amendment; unified policy, ADR 0021
5
- * amendment): a self-contained runtime image stages its own namespace under
6
- * `BOS_BUNDLE_DIR` as `bundles/<account>/<gateway>/<workspace>/…` and consumes
7
- * those bytes directly from disk; a miss falls through to the network, so a
8
- * partially-staged namespace boots over the wire instead of failing. The
9
- * registry tier (children, `BOS_BUNDLE_DIR` unset) keeps the network fetch —
10
- * the namespace guard below only ever matches the runtime's own
11
- * account/gateway, never another runtime's layout.
12
- */
13
- interface BundleNamespace {
14
- readonly bundleDir: string;
15
- readonly account: string;
16
- readonly gateway: string;
17
- }
18
- declare const BundleReadError_base: Schema.Class<BundleReadError, Schema.TaggedStruct<"BundleReadError", {
19
- readonly path: Schema.String;
20
- readonly cause: Schema.optional<Schema.Unknown>;
21
- }>, import("effect/Cause").YieldableError>;
22
- declare class BundleReadError extends BundleReadError_base {}
23
- /**
24
- * Own-namespace path for a bundle URL: the shared URL→staged-path mapping,
25
- * narrowed to the runtime identity — a URL whose encoded namespace differs
26
- * from `namespace.account`/`namespace.gateway` must fall to the network/cache
27
- * path, never serve a sibling namespace's staged bytes.
28
- */
29
- declare function bundleUrlToLocalPath(url: string, namespace: BundleNamespace): string | null;
30
- declare const BundleResolver_base: Context.ServiceClass<BundleResolver, "everything-dev/bundle-fs-resolve/BundleResolver", {
31
- /** Resolve a fetch target from the staged namespace; null = miss or not our namespace — fall through to the network. */
32
- readonly lookup: (input: string | URL | Request) => Effect.Effect<Response | null>;
33
- }>;
34
- declare class BundleResolver extends BundleResolver_base {
35
- static layer(namespace: BundleNamespace): Layer.Layer<BundleResolver>;
36
- }
37
- interface BundleFetchHandle {
38
- readonly uninstall: () => Promise<void>;
39
- }
40
- interface BundleFetchOptions {
41
- /** Own-namespace FS resolution — requires a staged `BOS_BUNDLE_DIR`. */
42
- namespace?: BundleNamespace;
43
- /**
44
- * Foreign-namespace stale-if-error cache (child tier): `/bundles/…` URLs
45
- * outside the own namespace write through to disk on success and serve
46
- * the last-known-good bytes when the origin fails. Enabled implicitly
47
- * when `namespace` is present (deployment contexts), or explicitly via
48
- * `BOS_BUNDLE_CACHE_DIR`.
49
- */
50
- cacheDir?: string;
51
- }
52
- /**
53
- * Installs the resolver as a global fetch interceptor — the one seam every
54
- * boot-time consumer shares (config manifest discovery, contract-type
55
- * fetches, orchestrator host loading, MF remoteEntry/identity probes).
56
- * One layered resolution policy: staged disk → network → stale-if-error.
57
- * Own-namespace URLs resolve from the staged directory and fall through to
58
- * the original fetch on a miss (a partially-staged namespace boots over the
59
- * wire instead of failing); a miss never touches the write-through cache —
60
- * for the own namespace the staged disk IS the resilience artifact. Foreign
61
- * `/bundles/…` URLs get the network with the stale-if-error cache; every
62
- * other URL falls through to the original fetch untouched. Inert when
63
- * neither a staged namespace nor a cache is configured.
64
- */
65
- declare function installGlobalBundleFetch(options: BundleFetchOptions): BundleFetchHandle;
66
- /**
67
- * Boot-time installer for the CLI: derives the own namespace from
68
- * `BOS_BUNDLE_DIR` plus the runtime identity (`BOS_ACCOUNT`/`BOS_GATEWAY`
69
- * registry env taking precedence over the bos.config.json fields), and the
70
- * foreign-namespace cache from `BOS_BUNDLE_CACHE_DIR`. Tier auto-detection
71
- * (ADR 0021): an identity whose namespace is not actually staged under the
72
- * bundle dir drops to the registry tier — plain network fetch — instead of
73
- * deterministically 404ing own-namespace URLs against a foreign image's
74
- * staged bytes. Never throws — a missing or malformed identity leaves the
75
- * default network fetch in place.
76
- */
77
- declare function installBundleFetchFromEnv(input: {
78
- configPath?: string | null;
79
- }): BundleFetchHandle | null;
80
- //#endregion
81
- export { BundleFetchHandle, BundleFetchOptions, BundleNamespace, BundleReadError, BundleResolver, bundleUrlToLocalPath, installBundleFetchFromEnv, installGlobalBundleFetch };
82
- //# sourceMappingURL=bundle-fs-resolve.d.cts.map
@@ -1,82 +0,0 @@
1
- import { Context, Effect, Layer, Schema } from "effect";
2
- //#region src/bundle-fs-resolve.d.ts
3
- /**
4
- * Local-first bundle resolution (ADR 0011 amendment; unified policy, ADR 0021
5
- * amendment): a self-contained runtime image stages its own namespace under
6
- * `BOS_BUNDLE_DIR` as `bundles/<account>/<gateway>/<workspace>/…` and consumes
7
- * those bytes directly from disk; a miss falls through to the network, so a
8
- * partially-staged namespace boots over the wire instead of failing. The
9
- * registry tier (children, `BOS_BUNDLE_DIR` unset) keeps the network fetch —
10
- * the namespace guard below only ever matches the runtime's own
11
- * account/gateway, never another runtime's layout.
12
- */
13
- interface BundleNamespace {
14
- readonly bundleDir: string;
15
- readonly account: string;
16
- readonly gateway: string;
17
- }
18
- declare const BundleReadError_base: Schema.Class<BundleReadError, Schema.TaggedStruct<"BundleReadError", {
19
- readonly path: Schema.String;
20
- readonly cause: Schema.optional<Schema.Unknown>;
21
- }>, import("effect/Cause").YieldableError>;
22
- declare class BundleReadError extends BundleReadError_base {}
23
- /**
24
- * Own-namespace path for a bundle URL: the shared URL→staged-path mapping,
25
- * narrowed to the runtime identity — a URL whose encoded namespace differs
26
- * from `namespace.account`/`namespace.gateway` must fall to the network/cache
27
- * path, never serve a sibling namespace's staged bytes.
28
- */
29
- declare function bundleUrlToLocalPath(url: string, namespace: BundleNamespace): string | null;
30
- declare const BundleResolver_base: Context.ServiceClass<BundleResolver, "everything-dev/bundle-fs-resolve/BundleResolver", {
31
- /** Resolve a fetch target from the staged namespace; null = miss or not our namespace — fall through to the network. */
32
- readonly lookup: (input: string | URL | Request) => Effect.Effect<Response | null>;
33
- }>;
34
- declare class BundleResolver extends BundleResolver_base {
35
- static layer(namespace: BundleNamespace): Layer.Layer<BundleResolver>;
36
- }
37
- interface BundleFetchHandle {
38
- readonly uninstall: () => Promise<void>;
39
- }
40
- interface BundleFetchOptions {
41
- /** Own-namespace FS resolution — requires a staged `BOS_BUNDLE_DIR`. */
42
- namespace?: BundleNamespace;
43
- /**
44
- * Foreign-namespace stale-if-error cache (child tier): `/bundles/…` URLs
45
- * outside the own namespace write through to disk on success and serve
46
- * the last-known-good bytes when the origin fails. Enabled implicitly
47
- * when `namespace` is present (deployment contexts), or explicitly via
48
- * `BOS_BUNDLE_CACHE_DIR`.
49
- */
50
- cacheDir?: string;
51
- }
52
- /**
53
- * Installs the resolver as a global fetch interceptor — the one seam every
54
- * boot-time consumer shares (config manifest discovery, contract-type
55
- * fetches, orchestrator host loading, MF remoteEntry/identity probes).
56
- * One layered resolution policy: staged disk → network → stale-if-error.
57
- * Own-namespace URLs resolve from the staged directory and fall through to
58
- * the original fetch on a miss (a partially-staged namespace boots over the
59
- * wire instead of failing); a miss never touches the write-through cache —
60
- * for the own namespace the staged disk IS the resilience artifact. Foreign
61
- * `/bundles/…` URLs get the network with the stale-if-error cache; every
62
- * other URL falls through to the original fetch untouched. Inert when
63
- * neither a staged namespace nor a cache is configured.
64
- */
65
- declare function installGlobalBundleFetch(options: BundleFetchOptions): BundleFetchHandle;
66
- /**
67
- * Boot-time installer for the CLI: derives the own namespace from
68
- * `BOS_BUNDLE_DIR` plus the runtime identity (`BOS_ACCOUNT`/`BOS_GATEWAY`
69
- * registry env taking precedence over the bos.config.json fields), and the
70
- * foreign-namespace cache from `BOS_BUNDLE_CACHE_DIR`. Tier auto-detection
71
- * (ADR 0021): an identity whose namespace is not actually staged under the
72
- * bundle dir drops to the registry tier — plain network fetch — instead of
73
- * deterministically 404ing own-namespace URLs against a foreign image's
74
- * staged bytes. Never throws — a missing or malformed identity leaves the
75
- * default network fetch in place.
76
- */
77
- declare function installBundleFetchFromEnv(input: {
78
- configPath?: string | null;
79
- }): BundleFetchHandle | null;
80
- //#endregion
81
- export { BundleFetchHandle, BundleFetchOptions, BundleNamespace, BundleReadError, BundleResolver, bundleUrlToLocalPath, installBundleFetchFromEnv, installGlobalBundleFetch };
82
- //# sourceMappingURL=bundle-fs-resolve.d.mts.map