@fungi.computer/oyster 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/README.md +376 -72
  2. package/dist/agents.d.ts +3 -2
  3. package/dist/agents.js +4 -2
  4. package/dist/app-builds.d.ts +81 -8
  5. package/dist/app-builds.js +210 -60
  6. package/dist/app-storage.d.ts +3 -3
  7. package/dist/approval-capability.d.ts +5 -0
  8. package/dist/approval-capability.js +46 -0
  9. package/dist/approval-home.d.ts +51 -0
  10. package/dist/approval-home.js +226 -0
  11. package/dist/apps/catalog.d.ts +335 -0
  12. package/dist/apps/catalog.js +46 -0
  13. package/dist/apps/gate.d.ts +20 -6
  14. package/dist/apps/gate.js +42 -16
  15. package/dist/apps/index.d.ts +3 -1
  16. package/dist/apps/index.js +3 -1
  17. package/dist/apps/installation.d.ts +132 -51
  18. package/dist/apps/installation.js +176 -70
  19. package/dist/apps/permissions.d.ts +247 -0
  20. package/dist/apps/permissions.js +255 -0
  21. package/dist/boot-capability-route.d.ts +15 -0
  22. package/dist/boot-capability-route.js +196 -0
  23. package/dist/boot-capability.d.ts +103 -0
  24. package/dist/boot-capability.js +141 -0
  25. package/dist/boot-construction.d.ts +12 -0
  26. package/dist/boot-construction.js +175 -0
  27. package/dist/boot-gate.d.ts +267 -0
  28. package/dist/boot-gate.js +236 -0
  29. package/dist/boot-host-script.d.ts +2 -0
  30. package/dist/boot-host-script.js +1 -0
  31. package/dist/boot-mount.d.ts +21 -0
  32. package/dist/boot-mount.js +65 -0
  33. package/dist/browser/boot.d.ts +73 -0
  34. package/dist/browser/boot.js +502 -0
  35. package/dist/browser/browser.d.ts +104 -0
  36. package/dist/browser/browser.js +374 -0
  37. package/dist/browser/capability-source.d.ts +76 -0
  38. package/dist/browser/capability-source.js +338 -0
  39. package/dist/browser/cdp-client.d.ts +56 -0
  40. package/dist/browser/cdp-client.js +184 -0
  41. package/dist/browser/errors.d.ts +79 -0
  42. package/dist/browser/errors.js +32 -0
  43. package/dist/browser/index.d.ts +16 -0
  44. package/dist/browser/index.js +14 -0
  45. package/dist/browser/lease-registry.d.ts +61 -0
  46. package/dist/browser/lease-registry.js +101 -0
  47. package/dist/browser/operations.d.ts +225 -0
  48. package/dist/browser/operations.js +137 -0
  49. package/dist/browser/page.d.ts +25 -0
  50. package/dist/browser/page.js +172 -0
  51. package/dist/browser/quick-reads.d.ts +29 -0
  52. package/dist/browser/quick-reads.js +160 -0
  53. package/dist/browser/sessions.d.ts +52 -0
  54. package/dist/browser/sessions.js +118 -0
  55. package/dist/browser/url-policy.d.ts +18 -0
  56. package/dist/browser/url-policy.js +58 -0
  57. package/dist/build/app-imports.d.ts +12 -0
  58. package/dist/build/app-imports.js +105 -0
  59. package/dist/build/build-policy.d.ts +5 -3
  60. package/dist/build/build-policy.js +5 -3
  61. package/dist/build/candidate-builder.d.ts +1 -1
  62. package/dist/build/candidate-cli.mjs +8375 -334
  63. package/dist/build/local-build.d.ts +2 -0
  64. package/dist/build/local-build.js +28 -6
  65. package/dist/build/snapshot-package-store.d.ts +1 -1
  66. package/dist/build/snapshot-package-store.js +7 -2
  67. package/dist/build/workspace-build.d.ts +92 -5
  68. package/dist/build/workspace-build.js +93 -19
  69. package/dist/build.d.ts +1 -1
  70. package/dist/build.js +1 -1
  71. package/dist/catalog-frame.js +1 -1
  72. package/dist/cloudflare.d.ts +13 -3
  73. package/dist/cloudflare.js +102 -4
  74. package/dist/frame-binding-wire-script.js +1 -1
  75. package/dist/frame-binding-wire.js +4 -2
  76. package/dist/git-auth.d.ts +0 -2
  77. package/dist/git-auth.js +0 -2
  78. package/dist/git.d.ts +0 -1
  79. package/dist/git.js +0 -2
  80. package/dist/host.d.ts +39 -13
  81. package/dist/host.js +268 -142
  82. package/dist/index.d.ts +25 -15
  83. package/dist/index.js +39 -16
  84. package/dist/install-release-cli.d.ts +2 -0
  85. package/dist/install-release-cli.js +46 -0
  86. package/dist/installation-client.d.ts +43 -0
  87. package/dist/installation-client.js +178 -0
  88. package/dist/installation-execution.d.ts +11 -0
  89. package/dist/installation-execution.js +184 -0
  90. package/dist/installation-operations.d.ts +1437 -0
  91. package/dist/installation-operations.js +664 -0
  92. package/dist/installation-store-generation.d.ts +3 -0
  93. package/dist/installation-store-generation.js +16 -0
  94. package/dist/instance-id.d.ts +10 -0
  95. package/dist/instance-id.js +10 -0
  96. package/dist/instance-refusal.d.ts +11 -0
  97. package/dist/instance-refusal.js +21 -0
  98. package/dist/internal/delivery.js +4 -2
  99. package/dist/internal/host-gate.js +7 -1
  100. package/dist/internal/registry-installations.js +4 -4
  101. package/dist/keys.d.ts +5 -1
  102. package/dist/keys.js +10 -2
  103. package/dist/machine-link/authority.d.ts +89 -0
  104. package/dist/machine-link/authority.js +37 -0
  105. package/dist/machine-link/client.d.ts +66 -0
  106. package/dist/machine-link/client.js +94 -0
  107. package/dist/machine-link/delivery.d.ts +18 -0
  108. package/dist/machine-link/delivery.js +55 -0
  109. package/dist/machine-link/enrollment.d.ts +111 -0
  110. package/dist/machine-link/enrollment.js +286 -0
  111. package/dist/machine-link/fences.d.ts +37 -0
  112. package/dist/machine-link/fences.js +166 -0
  113. package/dist/machine-link/home.d.ts +20 -0
  114. package/dist/machine-link/home.js +24 -0
  115. package/dist/machine-link/host.d.ts +43 -0
  116. package/dist/machine-link/host.js +189 -0
  117. package/dist/machine-link/index.d.ts +15 -0
  118. package/dist/machine-link/index.js +15 -0
  119. package/dist/machine-link/link.d.ts +48 -0
  120. package/dist/machine-link/link.js +223 -0
  121. package/dist/machine-link/presence.d.ts +10 -0
  122. package/dist/machine-link/presence.js +25 -0
  123. package/dist/machine-link/workers.d.ts +6 -0
  124. package/dist/machine-link/workers.js +6 -0
  125. package/dist/mcp-owner.d.ts +2 -2
  126. package/dist/mcp-owner.js +41 -33
  127. package/dist/mcp.d.ts +15 -3
  128. package/dist/mcp.js +146 -25
  129. package/dist/pack.d.ts +14 -3
  130. package/dist/pack.js +44 -19
  131. package/dist/page/app-access.d.ts +7 -0
  132. package/dist/page/app-access.js +75 -0
  133. package/dist/page/boot-host.js +57 -0
  134. package/dist/page/capabilities.d.ts +3 -3
  135. package/dist/page/capabilities.js +16 -12
  136. package/dist/page/computer-handles.d.ts +3 -3
  137. package/dist/page/computer-target.d.ts +3 -0
  138. package/dist/page/computer-target.js +9 -0
  139. package/dist/page/mount.d.ts +23 -3
  140. package/dist/page/mount.js +152 -16
  141. package/dist/page-assets.d.ts +22 -0
  142. package/dist/page-assets.js +28 -0
  143. package/dist/page-script.d.ts +3 -0
  144. package/dist/page-script.js +5 -4
  145. package/dist/release.d.ts +13 -6
  146. package/dist/release.js +10 -7
  147. package/dist/root-data.d.ts +16 -6
  148. package/dist/root-data.js +2 -2
  149. package/dist/source/index.d.ts +1 -1
  150. package/dist/source/team-source.d.ts +20 -8
  151. package/dist/source/team-source.js +39 -10
  152. package/dist/source/template-seed.d.ts +2 -2
  153. package/dist/standalone/agent-mail.d.ts +24 -0
  154. package/dist/standalone/agent-mail.js +62 -0
  155. package/dist/standalone/agent-store.d.ts +9 -0
  156. package/dist/standalone/agent-store.js +30 -0
  157. package/dist/standalone/agents.d.ts +68 -9
  158. package/dist/standalone/agents.js +428 -56
  159. package/dist/standalone/app-builds-binding.d.ts +20 -2
  160. package/dist/standalone/app-builds-binding.js +147 -23
  161. package/dist/standalone/app-set.d.ts +5 -2
  162. package/dist/standalone/app-set.js +174 -143
  163. package/dist/standalone/browser.d.ts +11 -0
  164. package/dist/standalone/browser.js +72 -0
  165. package/dist/standalone/builds.d.ts +13 -4
  166. package/dist/standalone/builds.js +28 -44
  167. package/dist/standalone/computer-egress.d.ts +2 -0
  168. package/dist/standalone/computer-egress.js +13 -4
  169. package/dist/standalone/computer-fleet.d.ts +43 -0
  170. package/dist/standalone/computer-fleet.js +200 -0
  171. package/dist/standalone/computer.d.ts +44 -9
  172. package/dist/standalone/computer.js +129 -22
  173. package/dist/standalone/install-apps-cli.js +43 -6
  174. package/dist/standalone/instance.d.ts +2 -2
  175. package/dist/standalone/instance.js +8 -11
  176. package/dist/standalone/machine-link.d.ts +354 -0
  177. package/dist/standalone/machine-link.js +368 -0
  178. package/dist/standalone/media.d.ts +2 -2
  179. package/dist/standalone/media.js +19 -16
  180. package/dist/standalone/preview.d.ts +2 -2
  181. package/dist/standalone/preview.js +37 -10
  182. package/dist/standalone/registry.d.ts +149 -9
  183. package/dist/standalone/registry.js +299 -8
  184. package/dist/standalone/worker.d.ts +19 -5
  185. package/dist/standalone/worker.js +90 -54
  186. package/dist/standalone/workflow-binding.d.ts +18 -22
  187. package/dist/standalone/workflow-binding.js +18 -18
  188. package/dist/standalone/workflow-control.d.ts +4 -0
  189. package/dist/standalone/workflow-control.js +40 -0
  190. package/dist/standalone/workflow-events.d.ts +2 -2
  191. package/dist/standalone/workflow-events.js +9 -10
  192. package/dist/standalone/workflow-git-capture.js +4 -3
  193. package/dist/standalone/workflow-host.d.ts +162 -161
  194. package/dist/standalone/workflow-host.js +101 -21
  195. package/dist/standalone/workflow-node-capture.js +11 -4
  196. package/dist/standalone/workflow-schedules.d.ts +5 -2
  197. package/dist/standalone/workflow-schedules.js +9 -10
  198. package/dist/standalone/workflow-trigger-host.d.ts +65 -5
  199. package/dist/standalone/workflow-trigger-host.js +2 -2
  200. package/dist/standalone/workflow-webhooks.d.ts +22 -0
  201. package/dist/standalone/workflow-webhooks.js +39 -0
  202. package/dist/standalone/workflows.d.ts +140 -43
  203. package/dist/standalone/workflows.js +198 -39
  204. package/dist/storage-frame.d.ts +6 -6
  205. package/dist/testing/capabilities.js +14 -3
  206. package/dist/testing/installation.js +26 -2
  207. package/dist/testing/worker.js +1 -1
  208. package/dist/testing/workers-runtime.d.ts +8 -2
  209. package/dist/testing/workers-runtime.js +20 -2
  210. package/dist/webhook-abuse.d.ts +25 -0
  211. package/dist/webhook-abuse.js +54 -0
  212. package/dist/webhook-custody.d.ts +144 -0
  213. package/dist/webhook-custody.js +222 -0
  214. package/dist/webhook-ingress.d.ts +36 -0
  215. package/dist/webhook-ingress.js +146 -0
  216. package/dist/webhooks.d.ts +111 -0
  217. package/dist/webhooks.js +189 -0
  218. package/dist/workers-git.d.ts +12 -17
  219. package/dist/workers-git.js +60 -52
  220. package/dist/workers.d.ts +224 -13
  221. package/dist/workers.js +351 -51
  222. package/dist/workflow-agent-authority.d.ts +8 -0
  223. package/dist/workflow-agent-authority.js +42 -0
  224. package/dist/workflows.d.ts +66 -0
  225. package/dist/workflows.js +97 -0
  226. package/docs/api/README.md +63 -37
  227. package/docs/api/agents.md +17 -0
  228. package/docs/api/app-storage.md +1 -1
  229. package/docs/api/apps.md +1394 -543
  230. package/docs/api/browser/boot.md +132 -0
  231. package/docs/api/browser.md +1440 -0
  232. package/docs/api/build-contract.md +38 -25
  233. package/docs/api/build.md +263 -84
  234. package/docs/api/cloudflare.md +93 -7
  235. package/docs/api/git.md +3 -13
  236. package/docs/api/host.md +944 -118
  237. package/docs/api/index.md +320 -18
  238. package/docs/api/keys.md +24 -1
  239. package/docs/api/mcp.md +59 -12
  240. package/docs/api/modules.md +33 -40
  241. package/docs/api/pack.md +57 -8
  242. package/docs/api/page/mount.md +92 -4
  243. package/docs/api/workers-git.md +103 -24
  244. package/docs/api/workers.md +1581 -244
  245. package/docs/site/agent-quickstart.mdx +28 -14
  246. package/examples/standalone/worker.ts +3 -1
  247. package/examples/standalone/wrangler.jsonc +2 -0
  248. package/package.json +73 -71
  249. package/dist/installation-consent.d.ts +0 -81
  250. package/dist/installation-consent.js +0 -84
  251. package/dist/shell/app-directory.d.ts +0 -542
  252. package/dist/shell/app-directory.js +0 -196
  253. package/dist/shell/browser-actions.d.ts +0 -7
  254. package/dist/shell/browser-actions.js +0 -56
  255. package/dist/shell/command-host.d.ts +0 -112
  256. package/dist/shell/command-host.js +0 -502
  257. package/dist/shell/commands.d.ts +0 -25
  258. package/dist/shell/commands.js +0 -78
  259. package/dist/shell/index.d.ts +0 -8
  260. package/dist/shell/index.js +0 -8
  261. package/dist/shell/keys.d.ts +0 -41
  262. package/dist/shell/keys.js +0 -134
  263. package/dist/shell/shell-module.d.ts +0 -55
  264. package/dist/shell/shell-module.js +0 -86
  265. package/dist/shell/window-manager.d.ts +0 -128
  266. package/dist/shell/window-manager.js +0 -730
  267. package/dist/shell/workbench-contract.d.ts +0 -68
  268. package/dist/shell/workbench-directory.d.ts +0 -332
  269. package/dist/shell/workbench-directory.js +0 -35
  270. package/dist/shell/workbench-host-types.d.ts +0 -96
  271. package/dist/shell/workbench-host-types.js +0 -1
  272. package/dist/shell/workbench-host.d.ts +0 -34
  273. package/dist/shell/workbench-host.js +0 -352
  274. package/dist/shell/workbench-model.d.ts +0 -194
  275. package/dist/shell/workbench-model.js +0 -53
  276. package/dist/shell/workbench.d.ts +0 -4
  277. package/dist/shell/workbench.js +0 -2
  278. package/docs/api/shell/app-directory.md +0 -599
  279. package/docs/api/shell/command-host.md +0 -224
  280. package/docs/api/shell/commands.md +0 -197
  281. package/docs/api/shell/keys.md +0 -183
  282. package/docs/api/shell/shell-module.md +0 -204
  283. package/docs/api/shell/window-manager.md +0 -267
  284. package/docs/api/shell/workbench-directory.md +0 -119
  285. package/docs/api/shell/workbench.md +0 -205
  286. package/docs/api/shell.md +0 -1915
  287. /package/dist/{shell/workbench-contract.js → page/boot-host.d.ts} +0 -0
@@ -0,0 +1,141 @@
1
+ import { defineIdFamily } from "@fungi.computer/cairn/id";
2
+ import { createHash } from "node:crypto";
3
+ import { z } from "zod";
4
+ import { parseArtifactRef, parseReleaseId, parseSha256Digest, } from "@fungi.computer/puffball";
5
+ import { BOOT_DEADLINE_MS, BOOT_TRANSPORT_GRACE_MS, BootGateError, bootMountDiagnosticsSchema, } from "./boot-gate.js";
6
+ import { defaultAssetPolicy } from "./release.js";
7
+ export const BOOT_CAPABILITY_HEADER = "x-oyster-boot-capability";
8
+ const bootCapabilityAssetSchema = z.strictObject({
9
+ path: z.string().min(1).max(4096),
10
+ contentType: z.string().min(1).max(256),
11
+ artifactRef: z.string().min(1).max(512).transform(parseArtifactRef),
12
+ digest: z.string().min(1).max(80).transform(parseSha256Digest),
13
+ byteLength: z
14
+ .number()
15
+ .int()
16
+ .nonnegative()
17
+ .max(defaultAssetPolicy.maxObjectBytes),
18
+ });
19
+ export const bootCapabilityLeaseSchema = z.strictObject({
20
+ id: z.string().min(1).max(128),
21
+ identity: z.strictObject({
22
+ appId: z.string().min(1).max(256),
23
+ releaseId: z.string().transform(parseReleaseId),
24
+ surfaceId: z.literal("host-boot"),
25
+ }),
26
+ base: z.string().min(1).max(2048),
27
+ expiresAt: z.number().int().positive(),
28
+ assets: z.array(bootCapabilityAssetSchema).max(defaultAssetPolicy.maxObjects),
29
+ });
30
+ export const bootCapabilityGrantSchema = z.strictObject({
31
+ lease: bootCapabilityLeaseSchema,
32
+ tokenDigest: z.string().regex(/^[0-9a-f]{64}$/),
33
+ });
34
+ /** Build metadata retained by the lease must exactly match the verified boot UI. */
35
+ export function capabilityAssets(assets, byteLengths) {
36
+ if (assets.length !== byteLengths.length)
37
+ throw new Error("Boot capability asset metadata is incomplete");
38
+ return assets.map((asset, index) => {
39
+ const byteLength = byteLengths[index];
40
+ if (byteLength === undefined)
41
+ throw new Error("Boot capability asset metadata is incomplete");
42
+ return { ...asset, byteLength };
43
+ });
44
+ }
45
+ export function validateCapabilityAssetSet(lease) {
46
+ const total = lease.assets.reduce((sum, asset) => sum + asset.byteLength, 0);
47
+ if (total > defaultAssetPolicy.maxTotalBytes ||
48
+ new Set(lease.assets.map((asset) => asset.path)).size !==
49
+ lease.assets.length)
50
+ throw new Error("Boot capability asset set is invalid");
51
+ }
52
+ const bootCapabilityIds = defineIdFamily({
53
+ family: "oyster-boot-capability",
54
+ version: 1,
55
+ kinds: { lease: { prefix: "bcap" } },
56
+ });
57
+ /**
58
+ * Mint one boot capability for every host: a fresh 256-bit token for the
59
+ * caller's request header, only its SHA-256 digest in the store, and a lease
60
+ * whose asset sizes come from the bucket's own metadata. An asset the bucket
61
+ * does not hold, or one beyond the asset policy, refuses before anything is
62
+ * stored.
63
+ */
64
+ export async function issueBootCapability(input) {
65
+ const byteLengths = [];
66
+ let totalBytes = 0;
67
+ for (const asset of input.ui.assets) {
68
+ const head = await input.bucket.head(asset.artifactRef);
69
+ if (head === null || head.size > defaultAssetPolicy.maxObjectBytes)
70
+ throw new BootGateError("ui_mount_failed");
71
+ totalBytes += head.size;
72
+ if (totalBytes > defaultAssetPolicy.maxTotalBytes)
73
+ throw new BootGateError("ui_mount_failed");
74
+ byteLengths.push(head.size);
75
+ }
76
+ const lease = {
77
+ id: bootCapabilityIds.lease.generate(),
78
+ identity: input.ui.identity,
79
+ base: input.ui.base,
80
+ expiresAt: input.expiresAt,
81
+ assets: capabilityAssets(input.ui.assets, byteLengths),
82
+ };
83
+ validateCapabilityAssetSet(lease);
84
+ const token = btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))))
85
+ .replaceAll("+", "-")
86
+ .replaceAll("/", "_")
87
+ .replace(/=+$/u, "");
88
+ const tokenDigest = createHash("sha256").update(token, "utf8").digest("hex");
89
+ await input.capabilities.issue({ lease, tokenDigest });
90
+ return { token, leaseId: lease.id };
91
+ }
92
+ /**
93
+ * One UI page check for a Release, for every host, reading no UI bytes:
94
+ * issue a capability, open the pinned boot page, revoke the capability, and
95
+ * report in the boot gate's vocabulary. A page that did not mount fails,
96
+ * with diagnostics sanitized by the gate's schema; a timeout, unconfirmed
97
+ * cleanup, an unavailable runner, or no browser or origin is not checked.
98
+ */
99
+ export async function reportBootPage(input) {
100
+ const ui = await input.readUi();
101
+ if (ui === null)
102
+ return { kind: "passed" };
103
+ if (input.check === null || input.origin === null)
104
+ return { kind: "not_checked", code: "boot_browser_binding_missing" };
105
+ const deadlineAt = input.now() + BOOT_DEADLINE_MS;
106
+ let issued;
107
+ try {
108
+ issued = await issueBootCapability({
109
+ ui,
110
+ bucket: input.bucket,
111
+ capabilities: input.capabilities,
112
+ expiresAt: deadlineAt + BOOT_TRANSPORT_GRACE_MS,
113
+ });
114
+ }
115
+ catch (cause) {
116
+ if (cause instanceof BootGateError && cause.code === "ui_mount_failed")
117
+ return { kind: "failed", code: "ui_mount_failed" };
118
+ throw cause;
119
+ }
120
+ let result;
121
+ try {
122
+ result = await input.check({
123
+ origin: input.origin,
124
+ releaseId: ui.identity.releaseId,
125
+ capability: { header: BOOT_CAPABILITY_HEADER, token: issued.token },
126
+ deadlineAt,
127
+ });
128
+ }
129
+ finally {
130
+ await input.capabilities.revoke(issued.leaseId);
131
+ }
132
+ if (result.kind === "mounted")
133
+ return { kind: "passed" };
134
+ if (result.code === "ui_mount_failed")
135
+ return {
136
+ kind: "failed",
137
+ code: "ui_mount_failed",
138
+ diagnostics: bootMountDiagnosticsSchema.parse(result.diagnostics),
139
+ };
140
+ return { kind: "not_checked", code: result.code };
141
+ }
@@ -0,0 +1,12 @@
1
+ import type { Backend, Instance } from "./index.js";
2
+ import type { AppInstanceContext, AppInstanceLoader } from "./cloudflare.js";
3
+ import type { GuestLimits } from "./guest-policy.js";
4
+ /** One bounded disposable sibling; it can never become the live App facet. */
5
+ export declare const BACKEND_CONSTRUCTION_FACET = "candidate";
6
+ /**
7
+ * The Instance owns the disposable facet and supplies its already-read prior
8
+ * state schema. Only initialized App storage is copied; supervisor state and
9
+ * authority are never copied. A unique Loader ID isolates candidate globals.
10
+ * No invocation frame or guestEnv factory is accepted.
11
+ */
12
+ export declare function checkBackendConstruction<FacetClass>(ctx: Pick<AppInstanceContext<FacetClass>, "facets">, loader: AppInstanceLoader<FacetClass> | undefined, artifact: Backend, limits: GuestLimits, priorStateSchema: Instance["stateSchema"]): Promise<void>;
@@ -0,0 +1,175 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
53
+ import { rpcHandleSchema, rpcMethod } from "@fungi.computer/agar/rpc";
54
+ import { z } from "zod";
55
+ import * as Result from "effect/Result";
56
+ import { correlationKey } from "@fungi.computer/cairn";
57
+ import { BOOT_DEADLINE_MS, BootGateError } from "./boot-gate.js";
58
+ const probeSchema = rpcHandleSchema({
59
+ construct: rpcMethod(z.undefined()).input(z.tuple([])),
60
+ });
61
+ /** One bounded disposable sibling; it can never become the live App facet. */
62
+ export const BACKEND_CONSTRUCTION_FACET = "candidate";
63
+ /**
64
+ * The Instance owns the disposable facet and supplies its already-read prior
65
+ * state schema. Only initialized App storage is copied; supervisor state and
66
+ * authority are never copied. A unique Loader ID isolates candidate globals.
67
+ * No invocation frame or guestEnv factory is accepted.
68
+ */
69
+ export async function checkBackendConstruction(ctx, loader, artifact, limits, priorStateSchema) {
70
+ if (loader === undefined)
71
+ throw new BootGateError("boot_runner_unavailable");
72
+ const name = BACKEND_CONSTRUCTION_FACET;
73
+ const loaderId = `boot:${correlationKey()}`;
74
+ let stage = "backend_load_failed";
75
+ let timeout;
76
+ const result = await (async () => {
77
+ try {
78
+ const env_1 = { stack: [], error: void 0, hasError: false };
79
+ try {
80
+ const deadline = new Promise((_, reject) => {
81
+ timeout = setTimeout(() => {
82
+ reject(new BootGateError("boot_timeout"));
83
+ }, BOOT_DEADLINE_MS);
84
+ });
85
+ if (priorStateSchema !== null) {
86
+ if (ctx.facets.clone === undefined)
87
+ throw new BootGateError("boot_clone_unavailable");
88
+ ctx.facets.clone("app", name);
89
+ }
90
+ else {
91
+ // A crash may have left the bounded sibling behind. Fresh means empty,
92
+ // not a retry against storage written by an earlier constructor.
93
+ ctx.facets.delete(name);
94
+ }
95
+ const stub = __addDisposableResource(env_1, probeSchema.parse(ctx.facets.get(name, () => ({
96
+ class: loader
97
+ .get(loaderId, () => ({
98
+ compatibilityDate: artifact.backend.compatibilityDate,
99
+ mainModule: "boot.js",
100
+ modules: {
101
+ "backend.js": artifact.backend.code,
102
+ "boot.js": constructionModule(artifact.backend.exportName),
103
+ },
104
+ env: {},
105
+ globalOutbound: null,
106
+ limits,
107
+ }))
108
+ .getDurableObjectClass("BootConstruction"),
109
+ }))), false);
110
+ stage = "backend_construction_failed";
111
+ await Promise.race([stub.construct(), deadline]);
112
+ return Result.succeed(undefined);
113
+ }
114
+ catch (e_1) {
115
+ env_1.error = e_1;
116
+ env_1.hasError = true;
117
+ }
118
+ finally {
119
+ __disposeResources(env_1);
120
+ }
121
+ }
122
+ catch (cause) {
123
+ return Result.fail(cause instanceof BootGateError
124
+ ? cause
125
+ : new BootGateError(stage, { cause }));
126
+ }
127
+ finally {
128
+ if (timeout !== undefined)
129
+ clearTimeout(timeout);
130
+ }
131
+ })();
132
+ // Cleanup uncertainty takes precedence over the captured probe result.
133
+ try {
134
+ try {
135
+ ctx.facets.abort(name, new Error("Candidate boot ended"));
136
+ }
137
+ finally {
138
+ ctx.facets.delete(name);
139
+ }
140
+ }
141
+ catch (cause) {
142
+ throw new BootGateError("boot_cleanup_failed", { cause });
143
+ }
144
+ if (Result.isFailure(result))
145
+ throw result.failure;
146
+ }
147
+ function constructionModule(exportName) {
148
+ return `import { DurableObject } from "cloudflare:workers";
149
+ // Capture trusted operations BEFORE evaluating any candidate module.
150
+ const construct = Reflect.construct;
151
+ const freeze = Object.freeze;
152
+ // These are host test bindings, not invocation loopbacks. They deny all
153
+ // external operations. SQLite is the disposable facet's fresh or copied storage.
154
+ const unavailable = () => { throw new Error("Host test binding unavailable"); };
155
+ const env = freeze({
156
+ APP_STORAGE: freeze({
157
+ read: unavailable, write: unavailable, reset: unavailable
158
+ })
159
+ });
160
+ export class BootConstruction extends DurableObject {
161
+ constructor(ctx, bindings) {
162
+ super(ctx, bindings);
163
+ ctx.blockConcurrencyWhile(async () => {
164
+ const backend = await import("./backend.js");
165
+ construct(backend[${JSON.stringify(exportName)}], [ctx, env]);
166
+ });
167
+ }
168
+ // Native constructor blocking must finish before RPC dispatch. No App-mutated
169
+ // Promise methods or candidate-supplied completion value decide readiness.
170
+ construct() {}
171
+ }
172
+ // A candidate can import this module, but cannot patch the host check.
173
+ freeze(BootConstruction.prototype);
174
+ freeze(BootConstruction);`;
175
+ }
@@ -0,0 +1,267 @@
1
+ import { z } from "zod";
2
+ import { type Release } from "@fungi.computer/puffball";
3
+ import { type ArtifactStore } from "./release.js";
4
+ /** Only the host can produce these outcomes; they are not an App build input. */
5
+ export declare const bootFailureSchema: z.ZodEnum<{
6
+ backend_load_failed: "backend_load_failed";
7
+ backend_construction_failed: "backend_construction_failed";
8
+ ui_mount_failed: "ui_mount_failed";
9
+ boot_runner_unavailable: "boot_runner_unavailable";
10
+ boot_browser_binding_missing: "boot_browser_binding_missing";
11
+ boot_clone_unavailable: "boot_clone_unavailable";
12
+ boot_timeout: "boot_timeout";
13
+ boot_cleanup_failed: "boot_cleanup_failed";
14
+ }>;
15
+ export type BootFailure = z.output<typeof bootFailureSchema>;
16
+ export declare const BOOT_MOUNT_DIAGNOSTIC_LIMITS: Readonly<{
17
+ maxEntriesPerKind: 20;
18
+ maxEntriesTotal: 48;
19
+ maxTextChars: 300;
20
+ maxPathChars: 2048;
21
+ maxDroppedCount: 1024;
22
+ }>;
23
+ export declare const bootMountFailurePredicateSchema: z.ZodEnum<{
24
+ unexpected_candidate_request: "unexpected_candidate_request";
25
+ response_status: "response_status";
26
+ request_failed: "request_failed";
27
+ page_error: "page_error";
28
+ candidate_not_mounted: "candidate_not_mounted";
29
+ }>;
30
+ export type BootMountFailurePredicate = z.output<typeof bootMountFailurePredicateSchema>;
31
+ /** Closed, safe names for exceptions used in host-side mount diagnostics. */
32
+ export declare const bootMountDiagnosticErrorNameSchema: z.ZodEnum<{
33
+ TypeError: "TypeError";
34
+ RangeError: "RangeError";
35
+ SyntaxError: "SyntaxError";
36
+ AbortError: "AbortError";
37
+ TimeoutError: "TimeoutError";
38
+ Other: "Other";
39
+ Error: "Error";
40
+ }>;
41
+ export type BootMountDiagnosticErrorName = z.output<typeof bootMountDiagnosticErrorNameSchema>;
42
+ declare const bootMountRequestFailureKindSchema: z.ZodEnum<{
43
+ unexpected_candidate_request: "unexpected_candidate_request";
44
+ response_status: "response_status";
45
+ request_failed: "request_failed";
46
+ }>;
47
+ export type BootMountRequestFailureKind = z.output<typeof bootMountRequestFailureKindSchema>;
48
+ /** Bounded, URL-redacted observations from one failed candidate mount. */
49
+ export declare const bootMountDiagnosticsSchema: z.ZodObject<{
50
+ failedPredicate: z.ZodEnum<{
51
+ unexpected_candidate_request: "unexpected_candidate_request";
52
+ response_status: "response_status";
53
+ request_failed: "request_failed";
54
+ page_error: "page_error";
55
+ candidate_not_mounted: "candidate_not_mounted";
56
+ }>;
57
+ errorName: z.ZodOptional<z.ZodEnum<{
58
+ TypeError: "TypeError";
59
+ RangeError: "RangeError";
60
+ SyntaxError: "SyntaxError";
61
+ AbortError: "AbortError";
62
+ TimeoutError: "TimeoutError";
63
+ Other: "Other";
64
+ Error: "Error";
65
+ }>>;
66
+ finalUrlPath: z.ZodString;
67
+ consoleErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
68
+ pageErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
69
+ failedRequests: z.ZodArray<z.ZodObject<{
70
+ path: z.ZodString;
71
+ status: z.ZodOptional<z.ZodNumber>;
72
+ failureKind: z.ZodOptional<z.ZodEnum<{
73
+ unexpected_candidate_request: "unexpected_candidate_request";
74
+ response_status: "response_status";
75
+ request_failed: "request_failed";
76
+ }>>;
77
+ }, z.core.$strict>>;
78
+ droppedCount: z.ZodNumber;
79
+ }, z.core.$strict>;
80
+ export type BootMountDiagnostics = z.output<typeof bootMountDiagnosticsSchema>;
81
+ /** Safe host-authored reason; never reflects guest logs, exceptions or credentials. */
82
+ export declare class BootGateError extends Error {
83
+ readonly code: BootFailure;
84
+ readonly name = "BootGateError";
85
+ readonly diagnostics?: BootMountDiagnostics;
86
+ constructor(code: BootFailure, options?: ErrorOptions & {
87
+ diagnostics?: BootMountDiagnostics;
88
+ });
89
+ }
90
+ /** A finite host policy, not a candidate-configurable health check. */
91
+ export declare const BOOT_DEADLINE_MS = 10000;
92
+ /** The original outer-request allowance, reserved for transport and cleanup. */
93
+ export declare const BOOT_TRANSPORT_GRACE_MS = 2000;
94
+ /** Immutable artifact references only; bytes use the private native data plane. */
95
+ export declare const bootUiSchema: z.ZodObject<{
96
+ identity: z.ZodObject<{
97
+ appId: z.ZodString;
98
+ releaseId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@fungi.computer/puffball").ReleaseId, string>>;
99
+ surfaceId: z.ZodLiteral<"host-boot">;
100
+ }, z.core.$strict>;
101
+ base: z.ZodString;
102
+ assets: z.ZodArray<z.ZodObject<{
103
+ path: z.ZodString;
104
+ contentType: z.ZodString;
105
+ artifactRef: z.ZodPipe<z.ZodString, z.ZodTransform<import("@fungi.computer/puffball").ArtifactRef, string>>;
106
+ digest: z.ZodPipe<z.ZodString, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, string>>;
107
+ }, z.core.$strict>>;
108
+ }, z.core.$strict>;
109
+ export type BootUi = z.output<typeof bootUiSchema>;
110
+ /** Captures the same no-grant UI representation as a private candidate preview. */
111
+ export declare function readBootUi(store: ArtifactStore, release: Release): Promise<BootUi | null>;
112
+ export declare const bootCheckResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
113
+ kind: z.ZodLiteral<"passed">;
114
+ }, z.core.$strict>, z.ZodObject<{
115
+ kind: z.ZodLiteral<"not_checked">;
116
+ code: z.ZodEnum<{
117
+ boot_runner_unavailable: "boot_runner_unavailable";
118
+ boot_browser_binding_missing: "boot_browser_binding_missing";
119
+ boot_clone_unavailable: "boot_clone_unavailable";
120
+ boot_timeout: "boot_timeout";
121
+ boot_cleanup_failed: "boot_cleanup_failed";
122
+ }>;
123
+ }, z.core.$strict>, z.ZodObject<{
124
+ kind: z.ZodLiteral<"refused">;
125
+ code: z.ZodEnum<{
126
+ backend_load_failed: "backend_load_failed";
127
+ backend_construction_failed: "backend_construction_failed";
128
+ ui_mount_failed: "ui_mount_failed";
129
+ boot_runner_unavailable: "boot_runner_unavailable";
130
+ boot_browser_binding_missing: "boot_browser_binding_missing";
131
+ boot_clone_unavailable: "boot_clone_unavailable";
132
+ boot_timeout: "boot_timeout";
133
+ boot_cleanup_failed: "boot_cleanup_failed";
134
+ }>;
135
+ diagnostics: z.ZodOptional<z.ZodObject<{
136
+ failedPredicate: z.ZodEnum<{
137
+ unexpected_candidate_request: "unexpected_candidate_request";
138
+ response_status: "response_status";
139
+ request_failed: "request_failed";
140
+ page_error: "page_error";
141
+ candidate_not_mounted: "candidate_not_mounted";
142
+ }>;
143
+ errorName: z.ZodOptional<z.ZodEnum<{
144
+ TypeError: "TypeError";
145
+ RangeError: "RangeError";
146
+ SyntaxError: "SyntaxError";
147
+ AbortError: "AbortError";
148
+ TimeoutError: "TimeoutError";
149
+ Other: "Other";
150
+ Error: "Error";
151
+ }>>;
152
+ finalUrlPath: z.ZodString;
153
+ consoleErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
154
+ pageErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
155
+ failedRequests: z.ZodArray<z.ZodObject<{
156
+ path: z.ZodString;
157
+ status: z.ZodOptional<z.ZodNumber>;
158
+ failureKind: z.ZodOptional<z.ZodEnum<{
159
+ unexpected_candidate_request: "unexpected_candidate_request";
160
+ response_status: "response_status";
161
+ request_failed: "request_failed";
162
+ }>>;
163
+ }, z.core.$strict>>;
164
+ droppedCount: z.ZodNumber;
165
+ }, z.core.$strict>>;
166
+ }, z.core.$strict>], "kind">;
167
+ export type BootCheckResult = z.output<typeof bootCheckResultSchema>;
168
+ /** A UI check recorded on an installation operation, never installation authority. */
169
+ export declare const uiBootCheckOutcomeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
170
+ kind: z.ZodLiteral<"passed">;
171
+ }, z.core.$strict>, z.ZodObject<{
172
+ kind: z.ZodLiteral<"failed">;
173
+ code: z.ZodLiteral<"ui_mount_failed">;
174
+ diagnostics: z.ZodOptional<z.ZodObject<{
175
+ failedPredicate: z.ZodEnum<{
176
+ unexpected_candidate_request: "unexpected_candidate_request";
177
+ response_status: "response_status";
178
+ request_failed: "request_failed";
179
+ page_error: "page_error";
180
+ candidate_not_mounted: "candidate_not_mounted";
181
+ }>;
182
+ errorName: z.ZodOptional<z.ZodEnum<{
183
+ TypeError: "TypeError";
184
+ RangeError: "RangeError";
185
+ SyntaxError: "SyntaxError";
186
+ AbortError: "AbortError";
187
+ TimeoutError: "TimeoutError";
188
+ Other: "Other";
189
+ Error: "Error";
190
+ }>>;
191
+ finalUrlPath: z.ZodString;
192
+ consoleErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
193
+ pageErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
194
+ failedRequests: z.ZodArray<z.ZodObject<{
195
+ path: z.ZodString;
196
+ status: z.ZodOptional<z.ZodNumber>;
197
+ failureKind: z.ZodOptional<z.ZodEnum<{
198
+ unexpected_candidate_request: "unexpected_candidate_request";
199
+ response_status: "response_status";
200
+ request_failed: "request_failed";
201
+ }>>;
202
+ }, z.core.$strict>>;
203
+ droppedCount: z.ZodNumber;
204
+ }, z.core.$strict>>;
205
+ }, z.core.$strict>, z.ZodObject<{
206
+ kind: z.ZodLiteral<"not_checked">;
207
+ code: z.ZodEnum<{
208
+ boot_runner_unavailable: "boot_runner_unavailable";
209
+ boot_browser_binding_missing: "boot_browser_binding_missing";
210
+ boot_clone_unavailable: "boot_clone_unavailable";
211
+ boot_timeout: "boot_timeout";
212
+ boot_cleanup_failed: "boot_cleanup_failed";
213
+ ui_check_not_run_on_host: "ui_check_not_run_on_host";
214
+ }>;
215
+ }, z.core.$strict>], "kind">;
216
+ /**
217
+ * A UI check result recorded on an installation operation, never installation authority.
218
+ *
219
+ * @inline
220
+ */
221
+ export type UiBootCheckOutcome = z.output<typeof uiBootCheckOutcomeSchema>;
222
+ /** Owner-facing 422 body; diagnostics are never copied into other failures. */
223
+ export declare const bootRefusalSchema: z.ZodObject<{
224
+ error: z.ZodEnum<{
225
+ backend_load_failed: "backend_load_failed";
226
+ backend_construction_failed: "backend_construction_failed";
227
+ ui_mount_failed: "ui_mount_failed";
228
+ boot_runner_unavailable: "boot_runner_unavailable";
229
+ boot_browser_binding_missing: "boot_browser_binding_missing";
230
+ boot_clone_unavailable: "boot_clone_unavailable";
231
+ boot_timeout: "boot_timeout";
232
+ boot_cleanup_failed: "boot_cleanup_failed";
233
+ }>;
234
+ message: z.ZodString;
235
+ diagnostics: z.ZodOptional<z.ZodObject<{
236
+ failedPredicate: z.ZodEnum<{
237
+ unexpected_candidate_request: "unexpected_candidate_request";
238
+ response_status: "response_status";
239
+ request_failed: "request_failed";
240
+ page_error: "page_error";
241
+ candidate_not_mounted: "candidate_not_mounted";
242
+ }>;
243
+ errorName: z.ZodOptional<z.ZodEnum<{
244
+ TypeError: "TypeError";
245
+ RangeError: "RangeError";
246
+ SyntaxError: "SyntaxError";
247
+ AbortError: "AbortError";
248
+ TimeoutError: "TimeoutError";
249
+ Other: "Other";
250
+ Error: "Error";
251
+ }>>;
252
+ finalUrlPath: z.ZodString;
253
+ consoleErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
254
+ pageErrors: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>;
255
+ failedRequests: z.ZodArray<z.ZodObject<{
256
+ path: z.ZodString;
257
+ status: z.ZodOptional<z.ZodNumber>;
258
+ failureKind: z.ZodOptional<z.ZodEnum<{
259
+ unexpected_candidate_request: "unexpected_candidate_request";
260
+ response_status: "response_status";
261
+ request_failed: "request_failed";
262
+ }>>;
263
+ }, z.core.$strict>>;
264
+ droppedCount: z.ZodNumber;
265
+ }, z.core.$strict>>;
266
+ }, z.core.$strict>;
267
+ export {};