spawnfile 0.1.14 → 0.1.17

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 (546) hide show
  1. package/README.md +60 -159
  2. package/dist/audit/checksShared.d.ts +1 -1
  3. package/dist/auth/importers.d.ts +10 -0
  4. package/dist/auth/importers.js +29 -4
  5. package/dist/auth/index.d.ts +2 -0
  6. package/dist/auth/index.js +1 -0
  7. package/dist/auth/paths.d.ts +1 -1
  8. package/dist/auth/profileStore.js +9 -9
  9. package/dist/auth/targetSecretSourceFsIdentity.d.ts +40 -0
  10. package/dist/auth/targetSecretSourceFsIdentity.js +42 -0
  11. package/dist/auth/targetSecretSourceFsPublish.d.ts +2 -0
  12. package/dist/auth/targetSecretSourceFsPublish.js +3 -1
  13. package/dist/auth/targetSecretSourceFsPublishImmutable.d.ts +2 -1
  14. package/dist/auth/targetSecretSourceFsPublishImmutable.js +104 -71
  15. package/dist/auth/targetSecretSourceFsRead.js +5 -14
  16. package/dist/auth/trainingAuth.d.ts +21 -0
  17. package/dist/auth/trainingAuth.js +86 -0
  18. package/dist/auth/types.d.ts +1 -1
  19. package/dist/cli/authCommands.d.ts +1 -1
  20. package/dist/cli/authCommands.js +9 -0
  21. package/dist/cli/canaryCutoverCommand.d.ts +2 -0
  22. package/dist/cli/canaryCutoverCommand.js +30 -0
  23. package/dist/cli/capabilitiesCommand.d.ts +3 -0
  24. package/dist/cli/capabilitiesCommand.js +12 -0
  25. package/dist/cli/capabilitiesReceipt.d.ts +56 -0
  26. package/dist/cli/capabilitiesReceipt.js +56 -0
  27. package/dist/cli/compileBuildCommands.js +13 -0
  28. package/dist/cli/composedLifecycleContractSet.d.ts +21 -0
  29. package/dist/cli/composedLifecycleContractSet.js +204 -0
  30. package/dist/cli/devCommands.js +2 -0
  31. package/dist/cli/downCommand.js +19 -8
  32. package/dist/cli/evidenceExportHelperCommand.d.ts +13 -0
  33. package/dist/cli/evidenceExportHelperCommand.js +51 -0
  34. package/dist/cli/index.js +12 -3
  35. package/dist/cli/lifecycleMachine.d.ts +7 -1
  36. package/dist/cli/lifecycleMachine.js +2 -2
  37. package/dist/cli/paideiaDelegation.d.ts +17 -0
  38. package/dist/cli/paideiaDelegation.js +210 -0
  39. package/dist/cli/paideiaSupervisor.d.ts +17 -0
  40. package/dist/cli/paideiaSupervisor.js +48 -0
  41. package/dist/cli/productStateCloneCommand.d.ts +2 -0
  42. package/dist/cli/productStateCloneCommand.js +34 -0
  43. package/dist/cli/runCli.d.ts +13 -3
  44. package/dist/cli/runCli.js +37 -9
  45. package/dist/cli/targetCommands.d.ts +4 -7
  46. package/dist/cli/targetCommands.js +16 -46
  47. package/dist/cli/targetConfigPreparedPlan.d.ts +3 -0
  48. package/dist/cli/targetConfigPreparedPlan.js +74 -0
  49. package/dist/cli/targetConfigResolver.d.ts +3 -0
  50. package/dist/cli/targetConfigResolver.js +111 -0
  51. package/dist/cli/targetConfigResolverCommand.d.ts +6 -0
  52. package/dist/cli/targetConfigResolverCommand.js +43 -0
  53. package/dist/cli/targetConfigResolverContracts.d.ts +56 -0
  54. package/dist/cli/targetConfigResolverContracts.js +30 -0
  55. package/dist/cli/targetConfigResolverDocker.d.ts +4 -0
  56. package/dist/cli/targetConfigResolverDocker.js +47 -0
  57. package/dist/cli/targetConfigResolverValidation.d.ts +10 -0
  58. package/dist/cli/targetConfigResolverValidation.js +94 -0
  59. package/dist/cli/targetDefaultAuthorities.d.ts +2 -0
  60. package/dist/cli/targetDefaultAuthorities.js +3 -0
  61. package/dist/cli/targetDefaultConfig.d.ts +7 -0
  62. package/dist/cli/targetDefaultConfig.js +22 -5
  63. package/dist/cli/targetDefaultConfigStdin.js +7 -1
  64. package/dist/cli/targetDefaultHandlerFactory.js +23 -2
  65. package/dist/cli/targetDefaultHandlers.d.ts +2 -2
  66. package/dist/cli/targetProductionCommands.d.ts +5 -0
  67. package/dist/cli/targetProductionCommands.js +45 -0
  68. package/dist/cli/trainCommand.d.ts +3 -0
  69. package/dist/cli/trainCommand.js +61 -0
  70. package/dist/cli/upCommand.js +35 -6
  71. package/dist/cli/upLifecycleRecovery.d.ts +2 -2
  72. package/dist/cli/upLifecycleRecovery.js +188 -44
  73. package/dist/cli/usageCommand.d.ts +40 -0
  74. package/dist/cli/usageCommand.js +284 -0
  75. package/dist/cli/usageCommandLive.d.ts +84 -0
  76. package/dist/cli/usageCommandLive.js +95 -0
  77. package/dist/cli/usageDeploymentSource.d.ts +9 -0
  78. package/dist/cli/usageDeploymentSource.js +22 -0
  79. package/dist/cli/workspaceResourceMigrationCommand.d.ts +8 -0
  80. package/dist/cli/workspaceResourceMigrationCommand.js +36 -0
  81. package/dist/compiler/buildCompilePlanTeams.d.ts +1 -1
  82. package/dist/compiler/buildCompilePlanTeams.js +6 -1
  83. package/dist/compiler/compilePlanHelpers.js +3 -0
  84. package/dist/compiler/compileProject.d.ts +2 -0
  85. package/dist/compiler/compileProject.js +5 -1
  86. package/dist/compiler/compileProjectSupport.js +9 -0
  87. package/dist/compiler/containerArtifacts.d.ts +3 -1
  88. package/dist/compiler/containerArtifacts.js +92 -40
  89. package/dist/compiler/containerArtifactsPlans.d.ts +1 -1
  90. package/dist/compiler/containerArtifactsPlans.js +24 -7
  91. package/dist/compiler/containerArtifactsRender.d.ts +2 -1
  92. package/dist/compiler/containerArtifactsRender.js +91 -58
  93. package/dist/compiler/containerArtifactsTypes.d.ts +8 -0
  94. package/dist/compiler/containerBackedMountRender.d.ts +56 -0
  95. package/dist/compiler/containerBackedMountRender.js +101 -0
  96. package/dist/compiler/containerDaimonBrokerRender.d.ts +112 -0
  97. package/dist/compiler/containerDaimonBrokerRender.js +191 -0
  98. package/dist/compiler/containerDaimonGrokWorkerProvisioning.d.ts +38 -0
  99. package/dist/compiler/containerDaimonGrokWorkerProvisioning.js +108 -0
  100. package/dist/compiler/containerDaimonGrokWorkerRender.d.ts +172 -0
  101. package/dist/compiler/containerDaimonGrokWorkerRender.js +268 -0
  102. package/dist/compiler/containerDaimonOwnershipGuardRender.d.ts +12 -0
  103. package/dist/compiler/containerDaimonOwnershipGuardRender.js +191 -0
  104. package/dist/compiler/containerDaimonUidEntrypointRender.d.ts +24 -0
  105. package/dist/compiler/containerDaimonUidEntrypointRender.js +297 -0
  106. package/dist/compiler/containerEntrypointRender.d.ts +7 -0
  107. package/dist/compiler/containerEntrypointRender.js +28 -22
  108. package/dist/compiler/containerPersistentMounts.d.ts +30 -0
  109. package/dist/compiler/containerPersistentMounts.js +66 -0
  110. package/dist/compiler/containerReadinessPaths.d.ts +1 -0
  111. package/dist/compiler/containerReadinessPaths.js +1 -0
  112. package/dist/compiler/containerRuntimeLinkMaterializer.d.ts +2 -0
  113. package/dist/compiler/containerRuntimeLinkMaterializer.js +12 -0
  114. package/dist/compiler/containerRuntimeReadinessRender.d.ts +7 -0
  115. package/dist/compiler/containerRuntimeReadinessRender.js +40 -0
  116. package/dist/compiler/containerStateOwnershipRender.d.ts +4 -0
  117. package/dist/compiler/containerStateOwnershipRender.js +75 -0
  118. package/dist/compiler/containerTargetResources.d.ts +22 -1
  119. package/dist/compiler/containerTargetResources.js +94 -2
  120. package/dist/compiler/containerVolumeBootstrap.d.ts +3 -0
  121. package/dist/compiler/containerVolumeBootstrap.js +3 -0
  122. package/dist/compiler/containerWorkspaceResourceRender.js +49 -1
  123. package/dist/compiler/daimonTelemetryArtifacts.d.ts +2 -2
  124. package/dist/compiler/daimonTelemetryArtifacts.js +5 -10
  125. package/dist/compiler/deploymentLineage.d.ts +40 -0
  126. package/dist/compiler/deploymentLineage.js +50 -0
  127. package/dist/compiler/index.d.ts +3 -0
  128. package/dist/compiler/index.js +3 -0
  129. package/dist/compiler/initProject.d.ts +2 -0
  130. package/dist/compiler/initProject.js +39 -1
  131. package/dist/compiler/localMoltnetAuthority.d.ts +64 -0
  132. package/dist/compiler/localMoltnetAuthority.js +177 -0
  133. package/dist/compiler/memoryArtifacts.d.ts +1 -1
  134. package/dist/compiler/memoryArtifacts.js +108 -32
  135. package/dist/compiler/modelEnv.d.ts +5 -0
  136. package/dist/compiler/modelEnv.js +8 -2
  137. package/dist/compiler/moltnetArtifactPaths.d.ts +17 -12
  138. package/dist/compiler/moltnetArtifactPaths.js +17 -15
  139. package/dist/compiler/moltnetArtifactTypes.d.ts +10 -0
  140. package/dist/compiler/moltnetArtifacts.d.ts +1 -1
  141. package/dist/compiler/moltnetArtifacts.js +52 -12
  142. package/dist/compiler/moltnetBinaries.d.ts +16 -4
  143. package/dist/compiler/moltnetBinaries.js +46 -6
  144. package/dist/compiler/moltnetClientConfig.js +1 -1
  145. package/dist/compiler/moltnetConfigLowering.d.ts +3 -1
  146. package/dist/compiler/moltnetConfigLowering.js +30 -6
  147. package/dist/compiler/moltnetNodeConfig.js +1 -1
  148. package/dist/compiler/moltnetReleaseAuthority.d.ts +24 -1
  149. package/dist/compiler/moltnetReleaseAuthority.js +33 -4
  150. package/dist/compiler/moltnetRepresentativeResolution.d.ts +1 -1
  151. package/dist/compiler/moltnetRepresentativeResolution.js +2 -2
  152. package/dist/compiler/moltnetResolution.js +9 -15
  153. package/dist/compiler/moltnetRoomMemberships.js +20 -5
  154. package/dist/compiler/moltnetRoomPolicyCompatibility.d.ts +1 -1
  155. package/dist/compiler/moltnetRoomPolicyCompatibility.js +3 -1
  156. package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
  157. package/dist/compiler/moltnetRuntimeConfig.js +22 -2
  158. package/dist/compiler/moltnetServerPlans.js +19 -0
  159. package/dist/compiler/organizationExternalParticipants.d.ts +3 -0
  160. package/dist/compiler/organizationExternalParticipants.js +176 -0
  161. package/dist/compiler/organizationIdentity.d.ts +3 -9
  162. package/dist/compiler/organizationIdentity.js +37 -270
  163. package/dist/compiler/organizationIdentityGraph.d.ts +15 -0
  164. package/dist/compiler/organizationIdentityGraph.js +115 -0
  165. package/dist/compiler/organizationReadyEvidence.d.ts +8 -0
  166. package/dist/compiler/organizationReadyEvidence.js +23 -3
  167. package/dist/compiler/runProject.d.ts +4 -2
  168. package/dist/compiler/runProject.js +32 -6
  169. package/dist/compiler/runProjectAuth.d.ts +3 -1
  170. package/dist/compiler/runProjectAuth.js +19 -3
  171. package/dist/compiler/runProjectDaimonCodexDocker.d.ts +3 -0
  172. package/dist/compiler/runProjectDaimonCodexDocker.js +36 -0
  173. package/dist/compiler/runProjectDocker.d.ts +8 -4
  174. package/dist/compiler/runProjectDocker.js +43 -18
  175. package/dist/compiler/runProjectDockerDaimonGuards.d.ts +15 -0
  176. package/dist/compiler/runProjectDockerDaimonGuards.js +122 -0
  177. package/dist/compiler/runProjectDockerReservation.d.ts +3 -0
  178. package/dist/compiler/runProjectDockerReservation.js +118 -0
  179. package/dist/compiler/runProjectLifecycle.js +1 -1
  180. package/dist/compiler/training/broker/declaration.d.ts +45 -0
  181. package/dist/compiler/training/broker/declaration.js +55 -0
  182. package/dist/compiler/training/broker/entrypoint.d.ts +39 -0
  183. package/dist/compiler/training/broker/entrypoint.js +111 -0
  184. package/dist/compiler/training/broker/index.d.ts +10 -0
  185. package/dist/compiler/training/broker/index.js +10 -0
  186. package/dist/compiler/training/broker/main.d.ts +2 -0
  187. package/dist/compiler/training/broker/main.js +14 -0
  188. package/dist/compiler/training/broker/paths.d.ts +196 -0
  189. package/dist/compiler/training/broker/paths.js +241 -0
  190. package/dist/compiler/training/broker/processes.d.ts +42 -0
  191. package/dist/compiler/training/broker/processes.js +99 -0
  192. package/dist/compiler/training/broker/projection.d.ts +51 -0
  193. package/dist/compiler/training/broker/projection.js +76 -0
  194. package/dist/compiler/training/broker/provisioning.d.ts +87 -0
  195. package/dist/compiler/training/broker/provisioning.js +213 -0
  196. package/dist/compiler/training/broker/receipt.d.ts +77 -0
  197. package/dist/compiler/training/broker/receipt.js +110 -0
  198. package/dist/compiler/training/broker/registration.d.ts +41 -0
  199. package/dist/compiler/training/broker/registration.js +102 -0
  200. package/dist/compiler/training/broker/runtime.d.ts +25 -0
  201. package/dist/compiler/training/broker/runtime.js +173 -0
  202. package/dist/compiler/training/broker/seccompRoutes.d.ts +31 -0
  203. package/dist/compiler/training/broker/seccompRoutes.js +36 -0
  204. package/dist/compiler/training/broker/supervisor.d.ts +109 -0
  205. package/dist/compiler/training/broker/supervisor.js +173 -0
  206. package/dist/compiler/training/container/contract.d.ts +31 -0
  207. package/dist/compiler/training/container/contract.js +33 -0
  208. package/dist/compiler/training/container/index.d.ts +4 -0
  209. package/dist/compiler/training/container/index.js +2 -0
  210. package/dist/compiler/training/container/launch.d.ts +18 -0
  211. package/dist/compiler/training/container/launch.js +173 -0
  212. package/dist/compiler/training/container/prepare.d.ts +8 -0
  213. package/dist/compiler/training/container/prepare.js +80 -0
  214. package/dist/compiler/training/container/process.d.ts +14 -0
  215. package/dist/compiler/training/container/process.js +70 -0
  216. package/dist/compiler/training/container/security.d.ts +36 -0
  217. package/dist/compiler/training/container/security.js +58 -0
  218. package/dist/compiler/training/context.d.ts +7 -0
  219. package/dist/compiler/training/context.js +93 -0
  220. package/dist/compiler/training/contract.d.ts +142 -0
  221. package/dist/compiler/training/contract.js +34 -0
  222. package/dist/compiler/training/index.d.ts +4 -0
  223. package/dist/compiler/training/index.js +3 -0
  224. package/dist/compiler/training/preparation/assets/Dockerfile +98 -0
  225. package/dist/compiler/training/preparation/assets/package-lock.json +3787 -0
  226. package/dist/compiler/training/preparation/broker.d.ts +21 -0
  227. package/dist/compiler/training/preparation/broker.js +43 -0
  228. package/dist/compiler/training/preparation/contextModes.d.ts +12 -0
  229. package/dist/compiler/training/preparation/contextModes.js +38 -0
  230. package/dist/compiler/training/preparation/contract.d.ts +182 -0
  231. package/dist/compiler/training/preparation/contract.js +94 -0
  232. package/dist/compiler/training/preparation/copyAssets.d.ts +1 -0
  233. package/dist/compiler/training/preparation/copyAssets.js +8 -0
  234. package/dist/compiler/training/preparation/daimonParent.d.ts +42 -0
  235. package/dist/compiler/training/preparation/daimonParent.js +114 -0
  236. package/dist/compiler/training/preparation/files.d.ts +25 -0
  237. package/dist/compiler/training/preparation/files.js +85 -0
  238. package/dist/compiler/training/preparation/image.d.ts +28 -0
  239. package/dist/compiler/training/preparation/image.js +102 -0
  240. package/dist/compiler/training/preparation/index.d.ts +3 -0
  241. package/dist/compiler/training/preparation/index.js +2 -0
  242. package/dist/compiler/training/preparation/inputs.d.ts +23 -0
  243. package/dist/compiler/training/preparation/inputs.js +93 -0
  244. package/dist/compiler/training/preparation/prepare.d.ts +33 -0
  245. package/dist/compiler/training/preparation/prepare.js +186 -0
  246. package/dist/compiler/training/preparation/scratch.d.ts +19 -0
  247. package/dist/compiler/training/preparation/scratch.js +48 -0
  248. package/dist/compiler/training/repair/compatibility.d.ts +11 -0
  249. package/dist/compiler/training/repair/compatibility.js +34 -0
  250. package/dist/compiler/training/repair/contract.d.ts +506 -0
  251. package/dist/compiler/training/repair/contract.js +31 -0
  252. package/dist/compiler/training/repair/index.d.ts +3 -0
  253. package/dist/compiler/training/repair/index.js +3 -0
  254. package/dist/compiler/training/repair/prepare.d.ts +230 -0
  255. package/dist/compiler/training/repair/prepare.js +74 -0
  256. package/dist/compiler/training/repair/witness.d.ts +203 -0
  257. package/dist/compiler/training/repair/witness.js +42 -0
  258. package/dist/compiler/types.d.ts +2 -0
  259. package/dist/compiler/upProject.d.ts +26 -1
  260. package/dist/compiler/upProject.js +117 -178
  261. package/dist/compiler/upProjectHandoff.d.ts +62 -0
  262. package/dist/compiler/upProjectHandoff.js +204 -0
  263. package/dist/compiler/upReceipt.js +49 -4
  264. package/dist/compiler/updateProjectModels.js +1 -0
  265. package/dist/compiler/view/types.d.ts +1 -1
  266. package/dist/compiler/workspaceBundleArtifacts.d.ts +3 -0
  267. package/dist/compiler/workspaceBundleArtifacts.js +106 -0
  268. package/dist/compiler/workspaceResources.d.ts +4 -1
  269. package/dist/compiler/workspaceResources.js +12 -7
  270. package/dist/deployment/artifactsExportPlan.js +51 -1
  271. package/dist/deployment/canaryCutover.d.ts +42 -0
  272. package/dist/deployment/canaryCutover.js +140 -0
  273. package/dist/deployment/candidateDiagnostics.d.ts +15 -0
  274. package/dist/deployment/candidateDiagnostics.js +90 -0
  275. package/dist/deployment/dockerLogs.js +4 -1
  276. package/dist/deployment/dockerManager.js +9 -3
  277. package/dist/deployment/dockerProbeGateway.d.ts +17 -0
  278. package/dist/deployment/dockerProbeGateway.js +17 -2
  279. package/dist/deployment/downDeployment.d.ts +5 -0
  280. package/dist/deployment/downDeployment.js +109 -8
  281. package/dist/deployment/downReceiptTypes.d.ts +17 -2
  282. package/dist/deployment/downReceiptTypes.js +17 -2
  283. package/dist/deployment/index.d.ts +4 -0
  284. package/dist/deployment/index.js +4 -0
  285. package/dist/deployment/lifecycleCompletionContracts.d.ts +66 -0
  286. package/dist/deployment/lifecycleCompletionContracts.js +34 -0
  287. package/dist/deployment/lifecycleCompletionPaths.d.ts +4 -1
  288. package/dist/deployment/lifecycleCompletionPaths.js +3 -0
  289. package/dist/deployment/lifecycleCompletionPublication.d.ts +2 -0
  290. package/dist/deployment/lifecycleCompletionPublication.js +18 -4
  291. package/dist/deployment/lifecycleCompletionStore.d.ts +1 -1
  292. package/dist/deployment/lifecycleCompletionStore.js +7 -7
  293. package/dist/deployment/lifecycleUpRecords.d.ts +11 -0
  294. package/dist/deployment/lifecycleUpRecords.js +127 -0
  295. package/dist/deployment/native/AGENTS.md +11 -0
  296. package/dist/deployment/native/rename-noreplace-arm64 +0 -0
  297. package/dist/deployment/native/rename-noreplace-arm64.provenance.json +1 -0
  298. package/dist/deployment/native/rename-noreplace-x64 +0 -0
  299. package/dist/deployment/native/rename-noreplace-x64.provenance.json +1 -0
  300. package/dist/deployment/noReplaceActivation.d.ts +17 -0
  301. package/dist/deployment/noReplaceActivation.js +50 -0
  302. package/dist/deployment/organizationHandoffAuthorityFsBudget.d.ts +110 -0
  303. package/dist/deployment/organizationHandoffAuthorityFsBudget.js +156 -0
  304. package/dist/deployment/organizationHandoffAuthorityFsClient.js +82 -27
  305. package/dist/deployment/organizationHandoffAuthorityFsElection.d.ts +21 -0
  306. package/dist/deployment/organizationHandoffAuthorityFsElection.js +57 -0
  307. package/dist/deployment/organizationHandoffAuthorityFsWorker.js +254 -108
  308. package/dist/deployment/organizationHandoffAuthorityFsWorkerStall.fixture.d.ts +1 -0
  309. package/dist/deployment/organizationHandoffAuthorityFsWorkerStall.fixture.js +16 -0
  310. package/dist/deployment/organizationHandoffAuthorityStore.js +14 -7
  311. package/dist/deployment/organizationHandoffAuthorityTypes.d.ts +2 -2
  312. package/dist/deployment/organizationHandoffAuthorityTypes.js +2 -1
  313. package/dist/deployment/organizationReady.d.ts +2 -0
  314. package/dist/deployment/organizationReady.js +36 -4
  315. package/dist/deployment/productStateClone.d.ts +43 -0
  316. package/dist/deployment/productStateClone.js +319 -0
  317. package/dist/deployment/upLifecycleRecoveryState.d.ts +23 -0
  318. package/dist/deployment/upLifecycleRecoveryState.js +12 -0
  319. package/dist/deployment/upReceiptTypes.d.ts +32 -6
  320. package/dist/deployment/upReceiptTypes.js +29 -2
  321. package/dist/deployment/workspaceResourceMigration.d.ts +55 -0
  322. package/dist/deployment/workspaceResourceMigration.js +315 -0
  323. package/dist/dev/project.d.ts +7 -0
  324. package/dist/dev/project.js +9 -0
  325. package/dist/distribution/consumeImage.d.ts +2 -0
  326. package/dist/distribution/consumeImage.js +98 -73
  327. package/dist/distribution/consumeImageDaimonDocker.d.ts +3 -0
  328. package/dist/distribution/consumeImageDaimonDocker.js +45 -0
  329. package/dist/distribution/consumeImageLifecycle.d.ts +17 -0
  330. package/dist/distribution/consumeImageLifecycle.js +231 -0
  331. package/dist/distribution/consumeImageSupport.d.ts +12 -0
  332. package/dist/distribution/consumeImageSupport.js +15 -0
  333. package/dist/distribution/distributionReportSchema.d.ts +11 -1
  334. package/dist/distribution/distributionReportSchema.js +15 -2
  335. package/dist/distribution/dockerRunner.d.ts +6 -1
  336. package/dist/distribution/dockerRunner.js +31 -4
  337. package/dist/distribution/imageRuntimeAuth.d.ts +9 -1
  338. package/dist/distribution/imageRuntimeAuth.js +70 -1
  339. package/dist/distribution/index.d.ts +1 -1
  340. package/dist/distribution/index.js +1 -1
  341. package/dist/distribution/preflight.js +5 -1
  342. package/dist/distribution/types.d.ts +14 -1
  343. package/dist/distribution/types.js +3 -0
  344. package/dist/evidenceExportHelper/boundedExecutor.d.ts +3 -0
  345. package/dist/evidenceExportHelper/boundedExecutor.js +33 -0
  346. package/dist/evidenceExportHelper/helperProgram.mjs +156 -0
  347. package/dist/evidenceExportHelper/index.d.ts +4 -0
  348. package/dist/evidenceExportHelper/index.js +4 -0
  349. package/dist/evidenceExportHelper/preparedAuthority.d.ts +64 -0
  350. package/dist/evidenceExportHelper/preparedAuthority.js +228 -0
  351. package/dist/evidenceExportHelper/preparedBuilder.d.ts +10 -0
  352. package/dist/evidenceExportHelper/preparedBuilder.js +183 -0
  353. package/dist/evidenceExportHelper/preparedBuilderTypes.d.ts +19 -0
  354. package/dist/evidenceExportHelper/preparedBuilderTypes.js +1 -0
  355. package/dist/evidenceExportHelper/recipe.d.ts +7 -0
  356. package/dist/evidenceExportHelper/recipe.js +83 -0
  357. package/dist/filesystem/io.d.ts +2 -0
  358. package/dist/filesystem/io.js +16 -1
  359. package/dist/manifest/executionSchemas.d.ts +27 -0
  360. package/dist/manifest/executionSchemas.js +21 -2
  361. package/dist/manifest/mcpSchemas.d.ts +1 -0
  362. package/dist/manifest/mcpSchemas.js +3 -0
  363. package/dist/manifest/renderSpawnfileNetworks.js +11 -0
  364. package/dist/manifest/renderSpawnfileWorkspace.js +5 -0
  365. package/dist/manifest/scheduleSchemas.d.ts +3 -1
  366. package/dist/manifest/scheduleSchemas.js +91 -5
  367. package/dist/manifest/schemas.d.ts +237 -12
  368. package/dist/manifest/schemas.js +5 -2
  369. package/dist/manifest/teamNetworkAccessSchemas.d.ts +5 -1
  370. package/dist/manifest/teamNetworkAccessSchemas.js +11 -0
  371. package/dist/manifest/teamNetworkAuthSchemas.d.ts +1 -1
  372. package/dist/manifest/teamNetworkSchemas.d.ts +17 -3
  373. package/dist/manifest/teamNetworkSchemas.js +19 -1
  374. package/dist/manifest/teamNetworkServerSchemas.d.ts +8 -3
  375. package/dist/manifest/teamNetworkServerSchemas.js +18 -2
  376. package/dist/manifest/workspaceSchemas.d.ts +16 -0
  377. package/dist/manifest/workspaceSchemas.js +11 -0
  378. package/dist/report/types.d.ts +34 -4
  379. package/dist/runtime/common.d.ts +28 -1
  380. package/dist/runtime/common.js +33 -3
  381. package/dist/runtime/container.js +49 -33
  382. package/dist/runtime/daimon/adapter.d.ts +14 -0
  383. package/dist/runtime/daimon/adapter.js +243 -0
  384. package/dist/runtime/daimon/attention.d.ts +8 -0
  385. package/dist/runtime/daimon/attention.js +32 -0
  386. package/dist/runtime/daimon/config.d.ts +25 -0
  387. package/dist/runtime/daimon/config.js +272 -0
  388. package/dist/runtime/daimon/contractManifest.d.ts +295 -0
  389. package/dist/runtime/daimon/contractManifest.js +319 -0
  390. package/dist/runtime/daimon/grokModel.d.ts +19 -0
  391. package/dist/runtime/daimon/grokModel.js +33 -0
  392. package/dist/runtime/daimon/grokWorkerConfigBytes.d.ts +26 -0
  393. package/dist/runtime/daimon/grokWorkerConfigBytes.js +36 -0
  394. package/dist/runtime/daimon/grokWorkerContract.d.ts +22 -0
  395. package/dist/runtime/daimon/grokWorkerContract.js +48 -0
  396. package/dist/runtime/daimon/memory.d.ts +57 -0
  397. package/dist/runtime/daimon/memory.js +125 -0
  398. package/dist/runtime/daimon/runAuth.d.ts +51 -0
  399. package/dist/runtime/daimon/runAuth.js +279 -0
  400. package/dist/runtime/daimon/runtimeIdentity.d.ts +22 -0
  401. package/dist/runtime/daimon/runtimeIdentity.js +22 -0
  402. package/dist/runtime/daimon/scheduleAuthority.d.ts +3 -0
  403. package/dist/runtime/daimon/scheduleAuthority.js +17 -0
  404. package/dist/runtime/index.d.ts +4 -0
  405. package/dist/runtime/index.js +4 -0
  406. package/dist/runtime/install.d.ts +3 -0
  407. package/dist/runtime/install.js +3 -0
  408. package/dist/runtime/localDaimonAuthority.d.ts +11 -0
  409. package/dist/runtime/localDaimonAuthority.js +77 -0
  410. package/dist/runtime/mnemeMcp.d.ts +13 -0
  411. package/dist/runtime/mnemeMcp.js +26 -0
  412. package/dist/runtime/openclaw/adapter.js +2 -2
  413. package/dist/runtime/pi/adapter.d.ts +0 -1
  414. package/dist/runtime/pi/adapter.js +2 -6
  415. package/dist/runtime/pi/appCliSource.js +1 -1
  416. package/dist/runtime/pi/appScheduleSource.js +6 -2
  417. package/dist/runtime/pi/appTemplateTypes.d.ts +1 -1
  418. package/dist/runtime/picoclaw/adapter.js +2 -2
  419. package/dist/runtime/registry.d.ts +3 -0
  420. package/dist/runtime/registry.js +19 -2
  421. package/dist/runtime/scheduleUtils.d.ts +1 -0
  422. package/dist/runtime/scheduleUtils.js +5 -1
  423. package/dist/runtime/types.d.ts +25 -0
  424. package/dist/runtime/usageLedger.d.ts +158 -0
  425. package/dist/runtime/usageLedger.js +269 -0
  426. package/dist/runtime/usageLedgerRead.d.ts +48 -0
  427. package/dist/runtime/usageLedgerRead.js +102 -0
  428. package/dist/runtime/usageRequestLedger.d.ts +42 -0
  429. package/dist/runtime/usageRequestLedger.js +72 -0
  430. package/dist/shared/daimonCodexDocker.d.ts +32 -0
  431. package/dist/shared/daimonCodexDocker.js +120 -0
  432. package/dist/shared/daimonGrokSeccompProfile.d.ts +10 -0
  433. package/dist/shared/daimonGrokSeccompProfile.js +11 -0
  434. package/dist/shared/index.d.ts +2 -0
  435. package/dist/shared/index.js +2 -0
  436. package/dist/shared/types.d.ts +1 -1
  437. package/dist/shared/volumeNames.d.ts +6 -0
  438. package/dist/shared/volumeNames.js +14 -0
  439. package/dist/target/dockerArtifactsProvider.js +34 -7
  440. package/dist/target/dockerBaseImage.d.ts +2 -0
  441. package/dist/target/dockerBaseImage.js +11 -0
  442. package/dist/target/dockerCommandExecutor.d.ts +11 -0
  443. package/dist/target/dockerCommandExecutor.js +53 -2
  444. package/dist/target/dockerCommandExecutorCore.d.ts +2 -1
  445. package/dist/target/dockerCommandExecutorCore.js +4 -2
  446. package/dist/target/dockerPublicArtifactSnapshot.d.ts +3 -3
  447. package/dist/target/dockerPublicArtifactSnapshot.js +17 -33
  448. package/dist/target/dockerTarget.d.ts +1 -0
  449. package/dist/target/dockerTargetBinding.d.ts +1 -2
  450. package/dist/target/dockerTargetBinding.js +2 -3
  451. package/dist/target/dockerTargetExecFile.d.ts +19 -0
  452. package/dist/target/dockerTargetExecFile.js +194 -0
  453. package/dist/target/dockerWorldServiceProvider.d.ts +4 -0
  454. package/dist/target/dockerWorldServiceProvider.js +13 -1
  455. package/dist/target/evidenceExport.d.ts +3 -1
  456. package/dist/target/evidenceExport.js +12 -3
  457. package/dist/target/evidenceExportOperationsTestKit.js +3 -3
  458. package/dist/target/evidenceExportProvider.d.ts +2 -0
  459. package/dist/target/evidenceExportProvider.js +15 -5
  460. package/dist/target/publicArtifactSnapshot.d.ts +31 -0
  461. package/dist/target/publicArtifactSnapshot.js +37 -3
  462. package/examples/README.md +45 -0
  463. package/examples/agent-with-subagents/AGENTS.md +3 -0
  464. package/examples/agent-with-subagents/Spawnfile +30 -0
  465. package/examples/agent-with-subagents/subagents/critic/AGENTS.md +3 -0
  466. package/examples/agent-with-subagents/subagents/critic/Spawnfile +15 -0
  467. package/examples/agent-with-subagents/subagents/researcher/AGENTS.md +3 -0
  468. package/examples/agent-with-subagents/subagents/researcher/Spawnfile +17 -0
  469. package/examples/daimon-org/Spawnfile +68 -0
  470. package/examples/daimon-org/TEAM.md +4 -0
  471. package/examples/daimon-org/agents/mapper/AGENTS.md +4 -0
  472. package/examples/daimon-org/agents/mapper/Spawnfile +37 -0
  473. package/examples/daimon-org/shared/skills/file-note/SKILL.md +9 -0
  474. package/examples/daimon-org/teams/review/Spawnfile +53 -0
  475. package/examples/daimon-org/teams/review/agents/reviewer/AGENTS.md +4 -0
  476. package/examples/daimon-org/teams/review/agents/reviewer/Spawnfile +37 -0
  477. package/examples/daimon-public-host/AGENTS.md +3 -0
  478. package/examples/daimon-public-host/Spawnfile +21 -0
  479. package/examples/distribution-org/Spawnfile +43 -0
  480. package/examples/distribution-org/TEAM.md +4 -0
  481. package/examples/distribution-org/agents/coordinator/AGENTS.md +1 -0
  482. package/examples/distribution-org/agents/coordinator/Spawnfile +20 -0
  483. package/examples/distribution-org/agents/researcher/AGENTS.md +1 -0
  484. package/examples/distribution-org/agents/researcher/Spawnfile +20 -0
  485. package/examples/jungian-daimon-org/Spawnfile +41 -0
  486. package/examples/jungian-daimon-org/TEAM.md +21 -0
  487. package/examples/jungian-daimon-org/teams/luna/Spawnfile +47 -0
  488. package/examples/jungian-daimon-org/teams/luna/TEAM.md +4 -0
  489. package/examples/jungian-daimon-org/teams/luna/agents/animus/AGENTS.md +10 -0
  490. package/examples/jungian-daimon-org/teams/luna/agents/animus/Spawnfile +33 -0
  491. package/examples/jungian-daimon-org/teams/luna/agents/representative/AGENTS.md +21 -0
  492. package/examples/jungian-daimon-org/teams/luna/agents/representative/Spawnfile +30 -0
  493. package/examples/jungian-daimon-org/teams/luna/agents/shadow/AGENTS.md +10 -0
  494. package/examples/jungian-daimon-org/teams/luna/agents/shadow/Spawnfile +33 -0
  495. package/examples/jungian-daimon-org/teams/selene/Spawnfile +47 -0
  496. package/examples/jungian-daimon-org/teams/selene/TEAM.md +4 -0
  497. package/examples/jungian-daimon-org/teams/selene/agents/animus/AGENTS.md +10 -0
  498. package/examples/jungian-daimon-org/teams/selene/agents/animus/Spawnfile +33 -0
  499. package/examples/jungian-daimon-org/teams/selene/agents/representative/AGENTS.md +19 -0
  500. package/examples/jungian-daimon-org/teams/selene/agents/representative/Spawnfile +33 -0
  501. package/examples/jungian-daimon-org/teams/selene/agents/shadow/AGENTS.md +10 -0
  502. package/examples/jungian-daimon-org/teams/selene/agents/shadow/Spawnfile +30 -0
  503. package/examples/mixed-runtime-org/Spawnfile +71 -0
  504. package/examples/mixed-runtime-org/TEAM.md +8 -0
  505. package/examples/mixed-runtime-org/agents/analyst/AGENTS.md +8 -0
  506. package/examples/mixed-runtime-org/agents/analyst/Spawnfile +27 -0
  507. package/examples/mixed-runtime-org/agents/conductor/AGENTS.md +8 -0
  508. package/examples/mixed-runtime-org/agents/conductor/Spawnfile +27 -0
  509. package/examples/mixed-runtime-org/agents/localist/AGENTS.md +7 -0
  510. package/examples/mixed-runtime-org/agents/localist/Spawnfile +50 -0
  511. package/examples/moltnet-team-chat/Spawnfile +43 -0
  512. package/examples/moltnet-team-chat/TEAM.md +5 -0
  513. package/examples/moltnet-team-chat/agents/coordinator/AGENTS.md +9 -0
  514. package/examples/moltnet-team-chat/agents/coordinator/Spawnfile +26 -0
  515. package/examples/moltnet-team-chat/teams/analysis/Spawnfile +23 -0
  516. package/examples/moltnet-team-chat/teams/analysis/TEAM.md +3 -0
  517. package/examples/moltnet-team-chat/teams/analysis/agents/observer/AGENTS.md +5 -0
  518. package/examples/moltnet-team-chat/teams/analysis/agents/observer/Spawnfile +19 -0
  519. package/examples/moltnet-team-chat/teams/analysis/agents/representative/AGENTS.md +5 -0
  520. package/examples/moltnet-team-chat/teams/analysis/agents/representative/Spawnfile +19 -0
  521. package/examples/moltnet-team-chat/teams/field/Spawnfile +41 -0
  522. package/examples/moltnet-team-chat/teams/field/TEAM.md +3 -0
  523. package/examples/moltnet-team-chat/teams/field/agents/observer/AGENTS.md +5 -0
  524. package/examples/moltnet-team-chat/teams/field/agents/observer/Spawnfile +26 -0
  525. package/examples/moltnet-team-chat/teams/field/agents/representative/AGENTS.md +11 -0
  526. package/examples/moltnet-team-chat/teams/field/agents/representative/Spawnfile +26 -0
  527. package/examples/single-agent/AGENTS.md +3 -0
  528. package/examples/single-agent/HEARTBEAT.md +3 -0
  529. package/examples/single-agent/IDENTITY.md +3 -0
  530. package/examples/single-agent/MEMORY.md +3 -0
  531. package/examples/single-agent/SOUL.md +3 -0
  532. package/examples/single-agent/Spawnfile +41 -0
  533. package/examples/single-agent/skills/web_search/SKILL.md +6 -0
  534. package/moltnet-releases.json +5 -4
  535. package/package.json +36 -9
  536. package/runtimes.yaml +5 -2
  537. package/dist/cli/targetWorldClockCrossProcess.test-helper.d.ts +0 -13
  538. package/dist/cli/targetWorldClockCrossProcess.test-helper.js +0 -109
  539. package/dist/deployment/providerRuntimeBoundaryScanner.test-helper.d.ts +0 -8
  540. package/dist/deployment/providerRuntimeBoundaryScanner.test-helper.js +0 -60
  541. package/dist/deployment/simfileFixtureBoundary.test-helper.d.ts +0 -8
  542. package/dist/deployment/simfileFixtureBoundary.test-helper.js +0 -103
  543. package/dist/ownership/simfileRunOperatorInputs.d.ts +0 -103
  544. package/dist/ownership/simfileRunOperatorInputs.js +0 -139
  545. package/dist/target/cleanupRunDocker.test-helper.d.ts +0 -67
  546. package/dist/target/cleanupRunDocker.test-helper.js +0 -238
@@ -0,0 +1,191 @@
1
+ import path from "node:path";
2
+ import { VOLUME_BOOTSTRAP_MARKER, VOLUME_BOOTSTRAP_MARKER_CONTENT } from "./containerVolumeBootstrap.js";
3
+ const SPAWNFILE_PRIVATE_STATE_ROOT = "/var/lib/spawnfile";
4
+ export const renderDaimonOwnershipProgram = (opaqueTargets, opaqueDescendantRoots, immutableRuntimeRoots, volumeIdentityFiles, privateDirectories, privateFiles, privateModeDirectories, creatablePrivateDirectories) => [
5
+ "const fs = require('node:fs');",
6
+ "const constants = fs.constants;",
7
+ "const uid = Number(process.argv[2]);",
8
+ "const roots = process.argv.slice(3);",
9
+ "const fail = (message) => { process.stderr.write(`Daimon ownership guard: ${message}\\n`); process.exit(1); };",
10
+ `const opaquePaths = new Set(${JSON.stringify(opaqueTargets)});`,
11
+ `const opaqueDescendantRoots = new Set(${JSON.stringify(opaqueDescendantRoots)});`,
12
+ `const immutableRuntimeRoots = ${JSON.stringify(immutableRuntimeRoots)};`,
13
+ `const volumeIdentityFiles = ${JSON.stringify(volumeIdentityFiles)};`,
14
+ "const volumeIdentityPaths = new Set(volumeIdentityFiles.map((entry) => entry.path)); if (volumeIdentityPaths.size !== volumeIdentityFiles.length) fail('duplicate volume identity path');",
15
+ `const privateDirectories = ${JSON.stringify(privateDirectories)};`,
16
+ `const privateFiles = ${JSON.stringify(privateFiles)};`,
17
+ `const privateModeDirectories = ${JSON.stringify(privateModeDirectories)};`,
18
+ `const creatablePrivateDirectories = ${JSON.stringify(creatablePrivateDirectories)};`,
19
+ "if (!Number.isSafeInteger(uid) || uid < 1 || roots.length === 0) fail('invalid compiler-authored roots');",
20
+ "const decodeMountPath = (value) => value.replace(/\\\\([0-7]{3})/g, (_, octal) => String.fromCharCode(Number.parseInt(octal, 8)));",
21
+ "const mountOptionsFor = (target) => {",
22
+ " const matches = fs.readFileSync('/proc/self/mountinfo', 'utf8').trim().split('\\n').map((line) => line.split(' ')).filter((parts) => parts.length > 5).map((parts) => ({ point: decodeMountPath(parts[4]), options: parts[5].split(',') })).filter((mount) => target === mount.point || target.startsWith(`${mount.point}/`));",
23
+ " return matches.sort((left, right) => right.point.length - left.point.length)[0]?.options ?? [];",
24
+ "};",
25
+ "const openDirectoryPath = (target) => {",
26
+ " if (!target.startsWith('/') || target === '/' || target.includes('//') || target.split('/').includes('..')) fail('unsafe compiler-authored root');",
27
+ " let fd = fs.openSync('/', constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);",
28
+ " try {",
29
+ " for (const segment of target.slice(1).split('/')) {",
30
+ " if (!segment || segment === '.' || segment === '..') fail('unsafe compiler-authored root');",
31
+ " const next = fs.openSync(`/proc/self/fd/${fd}/${segment}`, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);",
32
+ " fs.closeSync(fd); fd = next;",
33
+ " }",
34
+ " const info = fs.fstatSync(fd);",
35
+ " if (!info.isDirectory()) fail('root is not a directory');",
36
+ " if (mountOptionsFor(target).includes('ro')) fail('root is read-only');",
37
+ " return fd;",
38
+ " } catch (error) { try { fs.closeSync(fd); } catch {} fail('root has a symbolic-link or unavailable path component'); }",
39
+ "};",
40
+ "const openRegularFilePath = (target) => {",
41
+ " if (!target.startsWith('/') || target === '/' || target.includes('//') || target.split('/').includes('..')) fail('unsafe compiler-authored file');",
42
+ " let fd = fs.openSync('/', constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);",
43
+ " try {",
44
+ " const segments = target.slice(1).split('/');",
45
+ " for (const [index, segment] of segments.entries()) {",
46
+ " if (!segment || segment === '.' || segment === '..') fail('unsafe compiler-authored file');",
47
+ " const isFile = index === segments.length - 1;",
48
+ " const next = fs.openSync(`/proc/self/fd/${fd}/${segment}`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK | (isFile ? 0 : constants.O_DIRECTORY));",
49
+ " fs.closeSync(fd); fd = next;",
50
+ " }",
51
+ " const info = fs.fstatSync(fd);",
52
+ " if (!info.isFile() || info.nlink !== 1) fail('compiler-authored file is not one regular file');",
53
+ " if (mountOptionsFor(target).includes('ro')) fail('compiler-authored file is read-only');",
54
+ " return fd;",
55
+ " } catch (error) { try { fs.closeSync(fd); } catch {} fail('file has a symbolic-link or unavailable path component'); }",
56
+ "};",
57
+ "const secureFixedTraversalAncestor = (target) => {",
58
+ " const fd = openDirectoryPath(target);",
59
+ " try {",
60
+ " const info = fs.fstatSync(fd);",
61
+ " const mode = info.mode & 0o777;",
62
+ " if (info.uid !== 0 || info.gid !== 0 || (mode !== 0o775 && mode !== 0o755 && mode !== 0o711)) fail('fixed state ancestor has an unexpected preimage');",
63
+ " fs.fchmodSync(fd, 0o711);",
64
+ " const secured = fs.fstatSync(fd);",
65
+ " if (secured.uid !== 0 || secured.gid !== 0 || (secured.mode & 0o777) !== 0o711) fail('fixed state ancestor traversal mode did not apply');",
66
+ " } finally { fs.closeSync(fd); }",
67
+ "};",
68
+ "const secureSharedStateAncestor = (target) => {",
69
+ " const fd = openDirectoryPath(target);",
70
+ " try {",
71
+ " const info = fs.fstatSync(fd);",
72
+ " const mode = info.mode & 0o777;",
73
+ " const current = info.uid === 0 && info.gid === 0 && mode === 0o711;",
74
+ " const legacy = info.uid === uid && info.gid === uid && mode === 0o700;",
75
+ " if (!current && !legacy) fail('shared state ancestor has an unexpected preimage');",
76
+ " fs.fchownSync(fd, 0, 0); fs.fchmodSync(fd, 0o711);",
77
+ " const secured = fs.fstatSync(fd);",
78
+ " if (secured.uid !== 0 || secured.gid !== 0 || (secured.mode & 0o777) !== 0o711) fail('shared state ancestor traversal mode did not apply');",
79
+ " } finally { fs.closeSync(fd); }",
80
+ "};",
81
+ "const createPrivateDirectoryPath = ({ anchor, target }) => {",
82
+ " if (target !== anchor && !target.startsWith(`${anchor}/`)) fail('private directory escapes its compiler-authored anchor');",
83
+ " let fd = openDirectoryPath(anchor);",
84
+ " const anchorInfo = fs.fstatSync(fd);",
85
+ " const createdFds = [];",
86
+ " let preparationError;",
87
+ " let current = anchor;",
88
+ " try {",
89
+ " const relative = target.slice(anchor.length).replace(/^\\//, '');",
90
+ " for (const segment of relative ? relative.split('/') : []) {",
91
+ " if (!segment || segment === '.' || segment === '..') throw new Error('unsafe');",
92
+ " fs.fchownSync(fd, 0, 0);",
93
+ " const childPath = `/proc/self/fd/${fd}/${segment}`;",
94
+ " try { fs.mkdirSync(childPath, { mode: 0o700 }); } catch (error) { if (error.code !== 'EEXIST') throw error; }",
95
+ " const next = fs.openSync(childPath, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);",
96
+ " createdFds.push(fd); fd = next; current = `${current}/${segment}`;",
97
+ " const info = fs.fstatSync(fd);",
98
+ " if (!info.isDirectory() || mountOptionsFor(current).includes('ro')) throw new Error('unsafe-or-read-only');",
99
+ " }",
100
+ " createdFds.push(fd); fd = -1;",
101
+ " for (const ownedFd of createdFds.slice(1).reverse()) { fs.fchownSync(ownedFd, 0, 0); fs.fchmodSync(ownedFd, 0o700); fs.fchownSync(ownedFd, uid, uid); }",
102
+ " } catch (error) { preparationError = error.code ?? error.message ?? 'unknown'; } finally { const anchorFd = createdFds[0] ?? fd; if (anchorFd >= 0) try { fs.fchownSync(anchorFd, anchorInfo.uid, anchorInfo.gid); } catch { preparationError = 'restore-anchor-ownership'; }; if (fd >= 0) try { fs.closeSync(fd); } catch {}; for (const ownedFd of createdFds) try { fs.closeSync(ownedFd); } catch {} }",
103
+ " if (preparationError) fail(`unable to prepare compiler-authored private directory: ${preparationError}`);",
104
+ "};",
105
+ "const ownTree = (fd, device, currentPath) => {",
106
+ " const info = fs.fstatSync(fd);",
107
+ " if (!info.isDirectory() || info.dev !== device) return;",
108
+ " fs.fchownSync(fd, uid, uid);",
109
+ " for (const entry of fs.readdirSync(`/proc/self/fd/${fd}`, { withFileTypes: true })) {",
110
+ " const childPath = `${currentPath}/${entry.name}`;",
111
+ " if (opaquePaths.has(childPath) || opaqueDescendantRoots.has(childPath) || volumeIdentityPaths.has(childPath)) continue;",
112
+ " if (entry.isSymbolicLink()) continue;",
113
+ " if (!entry.isFile() && !entry.isDirectory()) fail('state tree contains an unsupported entry');",
114
+ " let child;",
115
+ " try { child = fs.openSync(`/proc/self/fd/${fd}/${entry.name}`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK | (entry.isDirectory() ? constants.O_DIRECTORY : 0)); } catch { fail('state tree contains a symbolic link or unavailable entry'); }",
116
+ " try { const childInfo = fs.fstatSync(child); if (childInfo.dev !== device || mountOptionsFor(childPath).includes('ro')) continue; if (childInfo.isDirectory()) ownTree(child, device, childPath); else if (childInfo.isFile() && childInfo.nlink === 1) fs.fchownSync(child, uid, uid); else if (!childInfo.isFile()) fail('state tree contains an unsupported entry'); } finally { fs.closeSync(child); }",
117
+ " }",
118
+ "};",
119
+ "const validateImmutableTree = (fd, device, currentPath) => {",
120
+ " const info = fs.fstatSync(fd);",
121
+ " if (!info.isDirectory() || info.dev !== device || info.uid !== 0 || info.gid !== 0 || (info.mode & 0o777) !== 0o711) fail('immutable runtime directory is unsafe');",
122
+ " for (const entry of fs.readdirSync(`/proc/self/fd/${fd}`, { withFileTypes: true })) {",
123
+ " let child; try { child = fs.openSync(`/proc/self/fd/${fd}/${entry.name}`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK | (entry.isDirectory() ? constants.O_DIRECTORY : 0)); } catch { fail('immutable runtime contains a symbolic link or unavailable entry'); }",
124
+ " try { const childInfo = fs.fstatSync(child); if (childInfo.dev !== device || childInfo.uid !== 0 || childInfo.gid !== 0) fail('immutable runtime entry is unsafe'); if (childInfo.isDirectory()) validateImmutableTree(child, device, `${currentPath}/${entry.name}`); else if (!childInfo.isFile() || childInfo.nlink !== 1 || (childInfo.mode & 0o222) !== 0) fail('immutable runtime contains an unsupported entry'); } finally { fs.closeSync(child); }",
125
+ " }",
126
+ "};",
127
+ "const securePrivateDirectory = (fd) => {",
128
+ " try {",
129
+ " fs.fchownSync(fd, 0, 0);",
130
+ " fs.fchmodSync(fd, 0o700);",
131
+ " fs.fchownSync(fd, uid, uid);",
132
+ " } catch {",
133
+ " try { fs.fchownSync(fd, uid, uid); } catch {}",
134
+ " fail('unable to secure private directory');",
135
+ " }",
136
+ " const info = fs.fstatSync(fd);",
137
+ " if (info.uid !== uid || info.gid !== uid || (info.mode & 0o777) !== 0o700) fail('private directory ownership or mode did not apply');",
138
+ "};",
139
+ "const securePrivateFile = (fd) => {",
140
+ " try {",
141
+ " fs.fchownSync(fd, 0, 0);",
142
+ " fs.fchmodSync(fd, 0o600);",
143
+ " fs.fchownSync(fd, uid, uid);",
144
+ " } catch {",
145
+ " try { fs.fchownSync(fd, uid, uid); } catch {}",
146
+ " fail('unable to secure private file');",
147
+ " }",
148
+ " const info = fs.fstatSync(fd);",
149
+ " if (info.uid !== uid || info.gid !== uid || (info.mode & 0o777) !== 0o600) fail('private file ownership or mode did not apply');",
150
+ "};",
151
+ `const volumeBootstrapMarker = ${JSON.stringify(VOLUME_BOOTSTRAP_MARKER)}, volumeBootstrapContent = ${JSON.stringify(`${VOLUME_BOOTSTRAP_MARKER_CONTENT}\n`)};`,
152
+ "const verifyVolumeIdentityFile = (fd, expected, mode, device) => { const before = fs.fstatSync(fd); if (!before.isFile() || before.nlink !== 1 || before.uid !== 0 || before.gid !== 0 || (before.mode & 0o777) !== mode || before.dev !== device || before.size !== Buffer.byteLength(expected)) fail('volume identity anchor is unsafe'); const bytes = Buffer.alloc(before.size); let offset=0; while(offset<bytes.length){const count=fs.readSync(fd,bytes,offset,bytes.length-offset,offset);if(count<1)fail('volume identity anchor read failed');offset+=count;} const after = fs.fstatSync(fd); if (!bytes.equals(Buffer.from(expected)) || after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeMs !== before.mtimeMs || after.ctimeMs !== before.ctimeMs) fail('volume identity anchor changed'); };",
153
+ "const secureVolumeIdentity = (entry) => { const parentPath = require('node:path').posix.dirname(entry.path); if (entry.path !== `${parentPath}/.spawnfile-resource-identity`) fail('volume identity anchor path is invalid'); const parent = openDirectoryPath(parentPath); let marker, sentinel; try { const parentInfo = fs.fstatSync(parent), parentMode = parentInfo.mode & 0o777, freshParent = parentInfo.uid === 0 && parentInfo.gid === 0 && parentMode === 0o755, establishedParent = parentInfo.uid === uid && parentInfo.gid === uid && parentMode === 0o755; if (!freshParent && !establishedParent) fail('volume identity parent is unsafe'); const names = fs.readdirSync(`/proc/self/fd/${parent}`).sort(), hasSentinel = names.includes('.spawnfile-resource-identity'), hasMarker = names.includes(volumeBootstrapMarker); if (hasSentinel) { sentinel = fs.openSync(`/proc/self/fd/${parent}/.spawnfile-resource-identity`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK); verifyVolumeIdentityFile(sentinel, `${entry.identity}\n`, 0o644, parentInfo.dev); if (hasMarker) { if (!freshParent || names.length !== 2) fail('volume bootstrap recovery preimage is unsafe'); marker = fs.openSync(`/proc/self/fd/${parent}/${volumeBootstrapMarker}`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK); verifyVolumeIdentityFile(marker, volumeBootstrapContent, 0o600, parentInfo.dev); fs.fsyncSync(sentinel); fs.fsyncSync(parent); verifyVolumeIdentityFile(sentinel, `${entry.identity}\n`, 0o644, parentInfo.dev); verifyVolumeIdentityFile(marker, volumeBootstrapContent, 0o600, parentInfo.dev); fs.unlinkSync(`/proc/self/fd/${parent}/${volumeBootstrapMarker}`); fs.fsyncSync(parent); } return; } if (!freshParent || names.length !== 1 || !hasMarker) fail('volume bootstrap preimage is unsafe'); marker = fs.openSync(`/proc/self/fd/${parent}/${volumeBootstrapMarker}`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK); verifyVolumeIdentityFile(marker, volumeBootstrapContent, 0o600, parentInfo.dev); const expected = Buffer.from(`${entry.identity}\n`); try { sentinel = fs.openSync(`/proc/self/fd/${parent}/.spawnfile-resource-identity`, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW | constants.O_NONBLOCK, 0o644); let offset=0; while(offset<expected.length){const written=fs.writeSync(sentinel,expected,offset,expected.length-offset,offset);if(written<1)fail('volume identity anchor write failed');offset+=written;} fs.fchownSync(sentinel,0,0);fs.fchmodSync(sentinel,0o644);fs.fsyncSync(sentinel); } finally { expected.fill(0); } fs.closeSync(sentinel); sentinel=undefined; sentinel=fs.openSync(`/proc/self/fd/${parent}/.spawnfile-resource-identity`,constants.O_RDONLY|constants.O_NOFOLLOW|constants.O_NONBLOCK);verifyVolumeIdentityFile(sentinel,`${entry.identity}\n`,0o644,parentInfo.dev);fs.fsyncSync(parent);verifyVolumeIdentityFile(marker,volumeBootstrapContent,0o600,parentInfo.dev);fs.unlinkSync(`/proc/self/fd/${parent}/${volumeBootstrapMarker}`);fs.fsyncSync(parent); } finally { if(marker!==undefined)fs.closeSync(marker);if(sentinel!==undefined)fs.closeSync(sentinel);fs.closeSync(parent); } };",
154
+ "for (const target of ['/var', '/var/lib']) secureFixedTraversalAncestor(target);",
155
+ `secureSharedStateAncestor('${SPAWNFILE_PRIVATE_STATE_ROOT}');`,
156
+ // `/var/lib/spawnfile/daimon` hosts several independently-owned children
157
+ // (AGY/Grok subscription realms and the wake fuse at organization uid, the
158
+ // broker realm and usage ledger at broker/broker:organization uid), so —
159
+ // exactly like SPAWNFILE_PRIVATE_STATE_ROOT above — it must stay a shared,
160
+ // root-owned, universally traversable ancestor, never chowned to any one
161
+ // child's uid. Docker always creates it fresh as root:root when it first
162
+ // provisions any volume mounted under it (guaranteed for every Daimon
163
+ // organization now that the usage ledger is provisioned unconditionally:
164
+ // `renderDaimonUsageLedgerProvisioning`), so the plain fixed-traversal
165
+ // preimage — never the organization uid — is the only state this needs to
166
+ // tolerate.
167
+ `secureFixedTraversalAncestor('${SPAWNFILE_PRIVATE_STATE_ROOT}/daimon');`,
168
+ "for (const target of immutableRuntimeRoots) { const fd = openDirectoryPath(target); try { validateImmutableTree(fd, fs.fstatSync(fd).dev, target); const start = openRegularFilePath(`${target}/daimon-start.sh`); try { const info = fs.fstatSync(start); if ((info.mode & 0o111) === 0 || (info.mode & 0o222) !== 0 || info.uid !== 0 || info.gid !== 0) fail('Daimon start script is not immutable executable'); } finally { fs.closeSync(start); } } finally { fs.closeSync(fd); } }",
169
+ "for (const entry of volumeIdentityFiles) secureVolumeIdentity(entry);",
170
+ "for (const target of creatablePrivateDirectories) createPrivateDirectoryPath(target);",
171
+ "for (const target of privateDirectories) { if (opaquePaths.has(target)) fail('compiler-authored directory overlaps opaque path'); const fd = openDirectoryPath(target); try { fs.fchownSync(fd, uid, uid); } finally { fs.closeSync(fd); } }",
172
+ "for (const target of privateModeDirectories) { if (opaquePaths.has(target)) fail('private directory overlaps opaque path'); const fd = openDirectoryPath(target); try { securePrivateDirectory(fd); } finally { fs.closeSync(fd); } }",
173
+ "for (const target of privateFiles) { if (opaquePaths.has(target)) fail('compiler-authored file overlaps opaque path'); const fd = openRegularFilePath(target); try { securePrivateFile(fd); } finally { fs.closeSync(fd); } }",
174
+ "for (const root of roots) { if (opaquePaths.has(root) || opaqueDescendantRoots.has(root)) fail('state root overlaps opaque path'); const fd = openDirectoryPath(root); try { ownTree(fd, fs.fstatSync(fd).dev, root); } finally { fs.closeSync(fd); } }"
175
+ ].join("\n");
176
+ export const resolveDaimonVolumeIdentityFiles = (runtimePlans) => {
177
+ const byPath = new Map();
178
+ const resourceRoot = "/var/lib/spawnfile/resources";
179
+ for (const resource of runtimePlans.flatMap((plan) => plan.resources ?? [])) {
180
+ if (resource.kind !== "volume" || !("replacementSentinel" in resource) || typeof resource.replacementSentinel !== "string" || !("resolvedIdentity" in resource) || typeof resource.resolvedIdentity !== "string")
181
+ continue;
182
+ const relative = typeof resource.backingPath === "string" ? path.posix.relative(resourceRoot, resource.backingPath) : "";
183
+ if (typeof resource.backingPath !== "string" || path.posix.normalize(resource.backingPath) !== resource.backingPath || resource.backingPath.includes("//") || !relative || relative.startsWith("../") || path.posix.isAbsolute(relative) || resource.replacementSentinel !== path.posix.join(resource.backingPath, ".spawnfile-resource-identity") || !/^sha256:[a-f0-9]{64}$/u.test(resource.resolvedIdentity))
184
+ throw new Error("invalid compiler-authored volume identity anchor");
185
+ const existing = byPath.get(resource.replacementSentinel);
186
+ if (existing !== undefined && existing !== resource.resolvedIdentity)
187
+ throw new Error("conflicting compiler-authored volume identity anchor");
188
+ byPath.set(resource.replacementSentinel, resource.resolvedIdentity);
189
+ }
190
+ return [...byPath].map(([path, identity]) => ({ path, identity })).sort((left, right) => left.path.localeCompare(right.path));
191
+ };
@@ -0,0 +1,24 @@
1
+ import type { RuntimeTargetPlan } from "./containerArtifactsTypes.js";
2
+ import type { EntrypointOptions } from "./containerEntrypointRender.js";
3
+ import { type BackedMountRequirement } from "./containerBackedMountRender.js";
4
+ export { resolveDaimonVolumeIdentityFiles } from "./containerDaimonOwnershipGuardRender.js";
5
+ export declare const DAIMON_AUTHORIZED_UID_ENV = "SPAWNFILE_DAIMON_AUTHORIZED_UID";
6
+ export declare const DAIMON_RUNTIME_UID = 2000;
7
+ export declare const DAIMON_UID_ENTRYPOINT_PATH = "/opt/spawnfile/daimon-uid-entrypoint.sh";
8
+ export declare const DAIMON_RUNTIME_HOMES_DIRECTORY = "runtime-homes";
9
+ export declare const DAIMON_BROKER_STARTUP_TIMEOUT_SECONDS = 60;
10
+ export declare const renderDaimonBrokerSocketWait: (timeoutSeconds?: number, pollSeconds?: number) => string[];
11
+ export declare const resolveDaimonUidEntrypointStateRoots: (runtimePlans: RuntimeTargetPlan[]) => string[];
12
+ export interface DaimonUidEntrypointOwnershipPlan {
13
+ creatablePrivateDirectories: Array<{
14
+ anchor: string;
15
+ target: string;
16
+ }>;
17
+ opaqueDescendantRoots: string[];
18
+ privateDirectories: string[];
19
+ privateFiles: string[];
20
+ privateModeDirectories: string[];
21
+ stateRoots: string[];
22
+ }
23
+ export declare const resolveDaimonUidEntrypointOwnershipPlan: (runtimePlans: RuntimeTargetPlan[], persistentMountPaths?: string[], moltnet?: EntrypointOptions["moltnet"]) => DaimonUidEntrypointOwnershipPlan;
24
+ export declare const renderDaimonUidEntrypoint: (runtimePlans: RuntimeTargetPlan[], persistentMountPaths?: string[], moltnet?: EntrypointOptions["moltnet"], persistentMounts?: readonly BackedMountRequirement[]) => string;
@@ -0,0 +1,297 @@
1
+ import path from "node:path";
2
+ import { DAIMON_RUNTIME_ACCEPTANCE_STORE_MOUNT_ID, DAIMON_WAKE_FUSE_DIRECTORY } from "../runtime/daimon/config.js";
3
+ import { DAIMON_GROK_TURN_USAGE_LEDGER } from "../runtime/daimon/contractManifest.js";
4
+ import { MOLTNET_READINESS_DIRECTORY } from "./containerReadinessPaths.js";
5
+ import { createBackedMountGuard } from "./containerBackedMountRender.js";
6
+ import { renderDaimonOwnershipProgram, resolveDaimonVolumeIdentityFiles } from "./containerDaimonOwnershipGuardRender.js";
7
+ export { resolveDaimonVolumeIdentityFiles } from "./containerDaimonOwnershipGuardRender.js";
8
+ import { renderDaimonGrokHostPreflight } from "./containerDaimonGrokWorkerProvisioning.js";
9
+ import { DAIMON_BROKER_EXECUTABLE, DAIMON_BROKER_BACKEND_SOCKET, DAIMON_BROKER_LAUNCHER_SOCKET, DAIMON_BROKER_REALM, DAIMON_BROKER_SOCKET, DAIMON_BROKER_TMPDIR, DAIMON_BROKER_UID, DAIMON_ORGANIZATION_UID, renderDaimonBrokerProvisioning, renderDaimonUsageLedgerProvisioning, resolveDaimonGrokRegistrations } from "./containerDaimonBrokerRender.js";
10
+ export const DAIMON_AUTHORIZED_UID_ENV = "SPAWNFILE_DAIMON_AUTHORIZED_UID";
11
+ export const DAIMON_RUNTIME_UID = DAIMON_ORGANIZATION_UID;
12
+ export const DAIMON_UID_ENTRYPOINT_PATH = "/opt/spawnfile/daimon-uid-entrypoint.sh";
13
+ export const DAIMON_RUNTIME_HOMES_DIRECTORY = "runtime-homes";
14
+ export const DAIMON_BROKER_STARTUP_TIMEOUT_SECONDS = 60;
15
+ export const renderDaimonBrokerSocketWait = (timeoutSeconds = DAIMON_BROKER_STARTUP_TIMEOUT_SECONDS, pollSeconds = 0.1) => [
16
+ `broker_startup_timeout_seconds=${timeoutSeconds}`,
17
+ `broker_startup_poll_seconds=${pollSeconds}`,
18
+ "broker_startup_started=$SECONDS",
19
+ "broker_process_status_root=/proc",
20
+ "wait_for_broker_socket() {",
21
+ " socket=$1; child=$2; label=$3",
22
+ " while [ ! -S \"$socket\" ]; do",
23
+ " if ! kill -0 \"$child\" 2>/dev/null; then set +e; wait \"$child\"; child_status=$?; set -e; echo \"$label exited before readiness (status $child_status)\" >&2; return 1; fi",
24
+ " if [ $((SECONDS - broker_startup_started)) -ge \"$broker_startup_timeout_seconds\" ]; then echo \"$label readiness timed out after ${broker_startup_timeout_seconds}s\" >&2; return 1; fi",
25
+ " sleep \"$broker_startup_poll_seconds\"",
26
+ " done",
27
+ "}",
28
+ "wait_for_broker_identity() {",
29
+ " child=$1; expected_uid=$2; expected_caps=$3; label=$4",
30
+ " while kill -0 \"$child\" 2>/dev/null; do",
31
+ " status_path=$broker_process_status_root/$child/status",
32
+ " observed_uid=$(awk '/^Uid:/{print $2}' \"$status_path\" 2>/dev/null || true)",
33
+ " observed_caps=$(awk '/^CapBnd:/{print $2}' \"$status_path\" 2>/dev/null || true)",
34
+ " if [ \"$observed_uid\" = \"$expected_uid\" ] && [ \"$observed_caps\" = \"$expected_caps\" ]; then return 0; fi",
35
+ " if [ $((SECONDS - broker_startup_started)) -ge \"$broker_startup_timeout_seconds\" ]; then echo \"$label identity readiness timed out after ${broker_startup_timeout_seconds}s\" >&2; return 1; fi",
36
+ " sleep \"$broker_startup_poll_seconds\"",
37
+ " done",
38
+ " set +e; wait \"$child\"; child_status=$?; set -e; echo \"$label exited before identity readiness (status $child_status)\" >&2; return 1",
39
+ "}"
40
+ ];
41
+ const SPAWNFILE_PRIVATE_STATE_ROOT = "/var/lib/spawnfile";
42
+ /**
43
+ * `/var/lib/spawnfile/daimon` hosts several independently-owned children —
44
+ * the AGY/Grok subscription realms (organization uid), the broker realm and
45
+ * usage ledger (broker uid, or broker:organization), the wake fuse
46
+ * (organization uid) — so it must stay a shared, root-owned, universally
47
+ * traversable ancestor (0711), exactly like `SPAWNFILE_PRIVATE_STATE_ROOT`
48
+ * itself, never chowned to the organization uid. Before this exclusion, any
49
+ * organization with an AGY agent (whose realm mount lives here and is not
50
+ * itself excluded from the ancestor walk below) got this directory chowned
51
+ * to the organization uid as a side effect of securing that one mount —
52
+ * which then made every *other* child that must be provisioned here as a
53
+ * different uid (most concretely, the usage ledger provisioned unconditionally
54
+ * by `renderDaimonUsageLedgerProvisioning`) fail to be created at all, because
55
+ * the entrypoint runs that provisioning as root without `CAP_DAC_OVERRIDE`
56
+ * (`runProject.ts`'s capability set), which cannot write into a directory it
57
+ * does not own by matching uid or gid.
58
+ */
59
+ const DAIMON_SHARED_STATE_ROOT = `${SPAWNFILE_PRIVATE_STATE_ROOT}/daimon`;
60
+ const DAIMON_AGY_SUBSCRIPTION_REALM_MOUNT_ID = "daimon-agy-subscription-realm";
61
+ const DAIMON_AGY_RUNTIME_HOME_MOUNT_ID_PREFIX = "daimon-agy-runtime-home-";
62
+ const DAIMON_PORTABLE_ENGINE_HOME_MOUNT_ID_PREFIX = "daimon-engine-home-";
63
+ const quote = (value) => `'${value.replace(/'/g, `'"'"'`)}'`;
64
+ const nodeSlug = (nodeId) => nodeId.replace(/^agent:/u, "")
65
+ .toLowerCase()
66
+ .replace(/[^a-z0-9]+/g, "-")
67
+ .replace(/^-+|-+$/g, "");
68
+ const opaqueMountTargets = (runtimePlans) => [...new Set(runtimePlans
69
+ .filter((plan) => plan.runtimeName === "daimon")
70
+ .flatMap((plan) => [
71
+ ...(plan.opaqueMountTargets ?? []),
72
+ ...(plan.resources ?? []).map((resource) => resource.linkPath),
73
+ ...Object.entries(plan.engineByNodeId ?? {})
74
+ .filter(([, engine]) => engine === "codex")
75
+ .map(([nodeId, engine]) => path.posix.join(plan.instancePaths.instanceRoot ?? "", DAIMON_RUNTIME_HOMES_DIRECTORY, nodeSlug(nodeId), ".daimon-inbound", `${engine}-auth`))
76
+ ])
77
+ .filter((target) => target.startsWith("/")))].sort();
78
+ export const resolveDaimonUidEntrypointStateRoots = (runtimePlans) => [
79
+ ...new Set([
80
+ ...runtimePlans.flatMap((plan) => [
81
+ plan.instancePaths.workspacePath,
82
+ ...(plan.instancePaths.homePath ? [plan.instancePaths.homePath] : []),
83
+ ...(plan.runtimeName === "daimon" && plan.instancePaths.instanceRoot
84
+ ? [path.posix.join(plan.instancePaths.instanceRoot, DAIMON_RUNTIME_HOMES_DIRECTORY)]
85
+ : [])
86
+ ])
87
+ ])
88
+ ].filter((root) => root.startsWith("/")).sort();
89
+ const writableStateRoots = (runtimePlans, persistentMountPaths) => [
90
+ ...new Set([
91
+ ...resolveDaimonUidEntrypointStateRoots(runtimePlans),
92
+ ...persistentMountPaths
93
+ ])
94
+ ].filter((root) => root.startsWith("/")
95
+ && root !== DAIMON_BROKER_REALM
96
+ && root !== DAIMON_GROK_TURN_USAGE_LEDGER.directoryPath
97
+ && root !== DAIMON_WAKE_FUSE_DIRECTORY).sort();
98
+ const privateDirectoriesThrough = (target) => {
99
+ if (target !== SPAWNFILE_PRIVATE_STATE_ROOT &&
100
+ !target.startsWith(`${SPAWNFILE_PRIVATE_STATE_ROOT}/`))
101
+ return [];
102
+ const relative = path.posix.relative(SPAWNFILE_PRIVATE_STATE_ROOT, target);
103
+ const segments = relative === "" ? [] : relative.split("/");
104
+ return [
105
+ SPAWNFILE_PRIVATE_STATE_ROOT,
106
+ ...segments.map((_, index) => path.posix.join(SPAWNFILE_PRIVATE_STATE_ROOT, ...segments.slice(0, index + 1)))
107
+ ];
108
+ };
109
+ const privateModeDirectories = (runtimePlans, moltnet) => [
110
+ ...new Set(runtimePlans
111
+ .filter((plan) => plan.runtimeName === "daimon")
112
+ .flatMap((plan) => plan.persistentMounts ?? [])
113
+ .filter((mount) => mount.id === DAIMON_RUNTIME_ACCEPTANCE_STORE_MOUNT_ID
114
+ || mount.id === DAIMON_AGY_SUBSCRIPTION_REALM_MOUNT_ID
115
+ || mount.id.startsWith(DAIMON_AGY_RUNTIME_HOME_MOUNT_ID_PREFIX)
116
+ || mount.id.startsWith(DAIMON_PORTABLE_ENGINE_HOME_MOUNT_ID_PREFIX))
117
+ // The acceptance store's own parent — `<instance-root>/state`, i.e.
118
+ // `DAIMON_ORGANIZATION_STATE_DIRECTORY` — is secured with it. Docker
119
+ // creates that parent root-owned and world-readable when it materializes
120
+ // this mount, and the ancestor pass below only *chowns* it, so it stayed
121
+ // 0755 and was the one path under `/var/lib/spawnfile` a Grok worker uid
122
+ // could open. Securing it to 0700 2000:2000 backs the acceptance store's
123
+ // sandbox `deny` entry with unix modes as defense in depth (see
124
+ // `containerDaimonGrokWorkerRender.ts`). Nothing loses access: the only thing
125
+ // beneath it is this store, already 0700 2000:2000, so every reader that
126
+ // works today is the organization uid or a `docker exec` root holding
127
+ // CAP_DAC_READ_SEARCH.
128
+ .flatMap((mount) => mount.id === DAIMON_RUNTIME_ACCEPTANCE_STORE_MOUNT_ID
129
+ ? [mount.mount_path, path.posix.dirname(mount.mount_path)]
130
+ : [mount.mount_path])
131
+ .filter((target) => target.startsWith("/"))
132
+ .concat((moltnet?.nodePlans ?? []).flatMap((plan) => plan.receiptStorePath ? [path.posix.dirname(plan.receiptStorePath)] : [])))
133
+ ].sort();
134
+ const portableEngineHomeDirectories = (runtimePlans) => [
135
+ ...new Set(runtimePlans
136
+ .filter((plan) => plan.runtimeName === "daimon")
137
+ .flatMap((plan) => plan.persistentMounts ?? [])
138
+ .filter((mount) => mount.id.startsWith(DAIMON_PORTABLE_ENGINE_HOME_MOUNT_ID_PREFIX))
139
+ .map((mount) => mount.mount_path)
140
+ .filter((target) => target.startsWith("/")))
141
+ ].sort();
142
+ const moltnetConfigPaths = (moltnet) => {
143
+ if (!moltnet)
144
+ return [];
145
+ return [
146
+ ...moltnet.serverPlans.flatMap((plan) => plan.mode === "managed" && plan.configPath ? [plan.configPath] : []),
147
+ ...moltnet.nodePlans.map((plan) => plan.configPath)
148
+ ].filter((configPath) => configPath.startsWith("/")).sort();
149
+ };
150
+ const daimonConfigPaths = (runtimePlans) => [
151
+ ...new Set(runtimePlans
152
+ .filter((plan) => plan.runtimeName === "daimon")
153
+ .map((plan) => plan.instancePaths.configPath)
154
+ .filter((configPath) => configPath.startsWith("/")))
155
+ ].sort();
156
+ const moltnetReceiptDirectories = (moltnet) => [...new Set((moltnet?.nodePlans ?? []).flatMap((plan) => plan.receiptStorePath ? [path.posix.dirname(plan.receiptStorePath)] : []))].filter((directory) => directory.startsWith("/")).sort();
157
+ export const resolveDaimonUidEntrypointOwnershipPlan = (runtimePlans, persistentMountPaths = [], moltnet) => {
158
+ const opaqueDescendantRoots = portableEngineHomeDirectories(runtimePlans);
159
+ const stateRoots = writableStateRoots(runtimePlans, persistentMountPaths)
160
+ .filter((root) => !opaqueDescendantRoots.some((opaqueRoot) => root === opaqueRoot || root.startsWith(`${opaqueRoot}/`)));
161
+ const privateFiles = [
162
+ ...new Set([...daimonConfigPaths(runtimePlans), ...moltnetConfigPaths(moltnet)])
163
+ ].sort();
164
+ const modeDirectories = [
165
+ ...new Set([
166
+ ...privateModeDirectories(runtimePlans, moltnet),
167
+ ...daimonConfigPaths(runtimePlans).map((configPath) => path.posix.dirname(configPath))
168
+ ])
169
+ ].sort();
170
+ const receiptDirectories = moltnetReceiptDirectories(moltnet);
171
+ const creatableTargets = [
172
+ ...receiptDirectories,
173
+ ...((moltnet?.nodePlans.length ?? 0) > 0 ? [MOLTNET_READINESS_DIRECTORY] : [])
174
+ ];
175
+ const privateDirectories = [
176
+ ...new Set([
177
+ ...stateRoots.flatMap(privateDirectoriesThrough),
178
+ ...moltnetReceiptDirectories(moltnet).flatMap(privateDirectoriesThrough),
179
+ ...privateFiles.flatMap((configPath) => privateDirectoriesThrough(path.posix.dirname(configPath)))
180
+ ])
181
+ ].filter((directory) => directory !== SPAWNFILE_PRIVATE_STATE_ROOT && directory !== DAIMON_SHARED_STATE_ROOT).sort();
182
+ return {
183
+ creatablePrivateDirectories: creatableTargets.map((target) => ({
184
+ anchor: target === MOLTNET_READINESS_DIRECTORY
185
+ ? "/run"
186
+ : stateRoots.filter((root) => target === root || target.startsWith(`${root}/`))
187
+ .sort((left, right) => right.length - left.length)[0] ?? SPAWNFILE_PRIVATE_STATE_ROOT,
188
+ target
189
+ })),
190
+ opaqueDescendantRoots,
191
+ privateDirectories,
192
+ privateFiles,
193
+ privateModeDirectories: modeDirectories,
194
+ stateRoots
195
+ };
196
+ };
197
+ export const renderDaimonUidEntrypoint = (runtimePlans, persistentMountPaths = [], moltnet, persistentMounts = []) => {
198
+ const opaqueTargets = opaqueMountTargets(runtimePlans);
199
+ const daimonPlan = runtimePlans.find((plan) => plan.runtimeName === "daimon");
200
+ const daimonConfigPath = daimonPlan?.instancePaths.configPath;
201
+ const daimonStartPath = daimonPlan
202
+ ? path.posix.join(daimonPlan.runtimeRoot, "daimon-start.sh")
203
+ : "";
204
+ const ownershipPlan = resolveDaimonUidEntrypointOwnershipPlan(runtimePlans, persistentMountPaths, moltnet);
205
+ const immutableRuntimeRoots = [
206
+ ...new Set(runtimePlans
207
+ .filter((plan) => plan.runtimeName === "daimon")
208
+ .map((plan) => plan.runtimeRoot)
209
+ .filter((runtimeRoot) => runtimeRoot.startsWith("/opt/spawnfile/runtime-installs/")))
210
+ ].sort();
211
+ const volumeIdentityFiles = resolveDaimonVolumeIdentityFiles(runtimePlans);
212
+ return [
213
+ "#!/usr/bin/env bash",
214
+ "set -euo pipefail",
215
+ `uid=${DAIMON_ORGANIZATION_UID}`,
216
+ 'gid="$uid"',
217
+ `runtime_command=(${quote("/opt/spawnfile/entrypoint.sh")} --spawnfile-runtime-identity "$uid" "$gid")`,
218
+ 'if [ "$#" -gt 0 ]; then',
219
+ ` if [ "$#" -ne 5 ] || [ "$1" != auth ] || [ "$2" != agy ] || [ "$3" != login ] || [ "$4" != --config ] || [ "$5" != ${quote(daimonConfigPath ?? "")} ]; then echo "Unsupported Daimon container command" >&2; exit 1; fi`,
220
+ ` runtime_command=(bash ${quote(daimonStartPath)} "$@")`,
221
+ "fi",
222
+ // Fail closed BEFORE the ownership guard touches anything: an unbacked
223
+ // durable path would otherwise be bootstrapped, owned and written on the
224
+ // container's own writable layer, and lost on `docker rm`.
225
+ ...createBackedMountGuard(persistentMounts),
226
+ `state_roots=(${ownershipPlan.stateRoots.map(quote).join(" ")})`,
227
+ "node - \"$uid\" \"${state_roots[@]}\" <<'SPAWNFILE_DAIMON_OWNERSHIP'",
228
+ renderDaimonOwnershipProgram(opaqueTargets, ownershipPlan.opaqueDescendantRoots, immutableRuntimeRoots, volumeIdentityFiles, ownershipPlan.privateDirectories, ownershipPlan.privateFiles, ownershipPlan.privateModeDirectories, ownershipPlan.creatablePrivateDirectories),
229
+ "SPAWNFILE_DAIMON_OWNERSHIP",
230
+ `for fixed_uid in ${DAIMON_ORGANIZATION_UID} ${DAIMON_BROKER_UID} ${resolveDaimonGrokRegistrations(runtimePlans).map((entry) => entry.uid).join(" ")}; do`,
231
+ ' if ! getent group "$fixed_uid" >/dev/null; then groupadd -K GID_MIN=1 --gid "$fixed_uid" "daimon-$fixed_uid"; fi',
232
+ ' if ! getent passwd "$fixed_uid" >/dev/null; then useradd -K UID_MIN=1 --no-create-home --no-log-init --uid "$fixed_uid" --gid "$fixed_uid" --home-dir /nonexistent --shell /usr/sbin/nologin "daimon-$fixed_uid"; fi',
233
+ "done",
234
+ ...(resolveDaimonGrokRegistrations(runtimePlans).length === 0 ? [] : renderDaimonGrokHostPreflight()),
235
+ ...renderDaimonBrokerProvisioning(runtimePlans),
236
+ 'if ! getent passwd "$uid" >/dev/null; then',
237
+ ' runtime_identity="daimon-$uid"',
238
+ ' runtime_group="$(getent group "$gid" | cut -d: -f1 || true)"',
239
+ ' if [ -z "$runtime_group" ]; then groupadd -K GID_MIN=1 --gid "$gid" "$runtime_identity"; runtime_group="$runtime_identity"; fi',
240
+ ' useradd -K UID_MIN=1 --no-create-home --no-log-init --uid "$uid" --gid "$gid" --home-dir /nonexistent --shell /usr/sbin/nologin "$runtime_identity"',
241
+ 'fi',
242
+ 'if ! getent passwd "$uid" >/dev/null; then echo "Daimon authorized UID has no local identity" >&2; exit 1; fi',
243
+ `chown 0:0 ${quote(DAIMON_WAKE_FUSE_DIRECTORY)} && chmod 0700 ${quote(DAIMON_WAKE_FUSE_DIRECTORY)} && chown ${DAIMON_ORGANIZATION_UID}:${DAIMON_ORGANIZATION_UID} ${quote(DAIMON_WAKE_FUSE_DIRECTORY)}`,
244
+ // Unconditional: AGY and Codex write the per-turn usage ledger from the
245
+ // organization-uid runtime process below, not the (Grok-only) broker, so
246
+ // this cannot be gated on `resolveDaimonGrokRegistrations`.
247
+ ...renderDaimonUsageLedgerProvisioning(),
248
+ ...(resolveDaimonGrokRegistrations(runtimePlans).length === 0 ? [] : [
249
+ ...renderDaimonBrokerSocketWait(),
250
+ "startup_children=()",
251
+ "cleanup_broker_startup() { status=$?; trap - EXIT; for child in \"${startup_children[@]}\"; do kill -TERM \"$child\" 2>/dev/null || true; wait \"$child\" 2>/dev/null || true; done; return \"$status\"; }",
252
+ "trap cleanup_broker_startup EXIT",
253
+ "trap 'exit 143' TERM INT HUP",
254
+ `install -d -o ${DAIMON_BROKER_UID} -g ${DAIMON_BROKER_UID} -m 0700 ${quote(DAIMON_BROKER_REALM)}`,
255
+ `if [ -e ${quote(`${DAIMON_BROKER_REALM}/auth.json`)} ]; then test -f ${quote(`${DAIMON_BROKER_REALM}/auth.json`)} && test ! -L ${quote(`${DAIMON_BROKER_REALM}/auth.json`)}; chown 0:0 ${quote(`${DAIMON_BROKER_REALM}/auth.json`)}; chmod 0600 ${quote(`${DAIMON_BROKER_REALM}/auth.json`)}; chown ${DAIMON_BROKER_UID}:${DAIMON_BROKER_UID} ${quote(`${DAIMON_BROKER_REALM}/auth.json`)}; fi`,
256
+ `setpriv --clear-groups --reuid ${DAIMON_BROKER_UID} --regid ${DAIMON_BROKER_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu 'probe=${DAIMON_BROKER_REALM}/.daimon-ancestry-probe; umask 077; : > "$probe"; rm "$probe"'`,
257
+ `setpriv --clear-groups --reuid ${DAIMON_ORGANIZATION_UID} --regid ${DAIMON_ORGANIZATION_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu '! test -r ${DAIMON_BROKER_REALM}'`,
258
+ ...resolveDaimonGrokRegistrations(runtimePlans).map((entry) => `setpriv --clear-groups --reuid ${entry.uid} --regid ${entry.uid} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu '! test -r ${DAIMON_BROKER_REALM}'`),
259
+ `setpriv --inh-caps=-all --ambient-caps=-all --bounding-set=-all,+chown,+setuid,+setgid -- ${quote(DAIMON_BROKER_EXECUTABLE)} &`,
260
+ "launcher_pid=$!",
261
+ "startup_children+=(\"$launcher_pid\")",
262
+ `wait_for_broker_socket ${quote(DAIMON_BROKER_LAUNCHER_SOCKET)} "$launcher_pid" "engine broker launcher"`,
263
+ `wait_for_broker_identity "$launcher_pid" 0 00000000000000c1 "engine broker launcher"`,
264
+ `setpriv --clear-groups --reuid ${DAIMON_BROKER_UID} --regid ${DAIMON_BROKER_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- env TMPDIR=${quote(DAIMON_BROKER_TMPDIR)} ${quote(path.posix.join(daimonPlan?.runtimeRoot ?? "", "bin/daimon-runtime"))} engine-broker serve &`,
265
+ "broker_pid=$!",
266
+ "startup_children+=(\"$broker_pid\")",
267
+ `wait_for_broker_socket ${quote(DAIMON_BROKER_BACKEND_SOCKET)} "$broker_pid" "engine broker backend"`,
268
+ `wait_for_broker_identity "$broker_pid" ${DAIMON_BROKER_UID} 0000000000000000 "engine broker backend"`,
269
+ `setpriv --inh-caps=-all --ambient-caps=-all --bounding-set=-all,+chown,+setuid,+setgid,+setpcap -- env TMPDIR=${quote(DAIMON_BROKER_TMPDIR)} ${quote(DAIMON_BROKER_EXECUTABLE)} --relay &`,
270
+ "relay_pid=$!",
271
+ "startup_children+=(\"$relay_pid\")",
272
+ `wait_for_broker_socket ${quote(DAIMON_BROKER_SOCKET)} "$relay_pid" "engine broker control relay"`,
273
+ `wait_for_broker_identity "$relay_pid" ${DAIMON_BROKER_UID} 0000000000000000 "engine broker control relay"`,
274
+ `[ -S ${quote(DAIMON_BROKER_SOCKET)} ] || exit 1`,
275
+ "for child_spec in \"$launcher_pid:0:00000000000000c1\" \"$relay_pid:2100:0000000000000000\" \"$broker_pid:2100:0000000000000000\"; do child=${child_spec%%:*}; rest=${child_spec#*:}; expected_uid=${rest%%:*}; expected_caps=${rest##*:}; observed_uid=$(awk '/^Uid:/{print $2}' \"/proc/$child/status\"); cap_bnd=$(awk '/^CapBnd:/{print $2}' \"/proc/$child/status\"); [ \"$observed_uid\" = \"$expected_uid\" ] && [ \"$cap_bnd\" = \"$expected_caps\" ] || exit 1; done"
276
+ ]),
277
+ "setpriv --clear-groups --reuid \"$uid\" --regid \"$gid\" --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu '",
278
+ " if [ \"$EUID\" -eq 0 ]; then exit 1; fi",
279
+ " test \"$(sed -n \"s/^CapEff:[[:space:]]*//p\" /proc/self/status)\" = 0000000000000000",
280
+ " exec \"$@\"",
281
+ `' bash "\${runtime_command[@]}" &`,
282
+ "runtime_pid=$!",
283
+ "trap - EXIT TERM INT HUP",
284
+ "stopping=0",
285
+ "stop_children() { stopping=1; kill -TERM \"$runtime_pid\" 2>/dev/null || true; for child in \"${relay_pid:-}\" \"${broker_pid:-}\" \"${launcher_pid:-}\"; do [ -z \"$child\" ] || kill -TERM \"$child\" 2>/dev/null || true; done; }",
286
+ "trap stop_children TERM INT HUP",
287
+ 'watch_pids=("$runtime_pid")',
288
+ ...(resolveDaimonGrokRegistrations(runtimePlans).length === 0 ? [] : ['watch_pids+=("$relay_pid" "$broker_pid" "$launcher_pid")']),
289
+ "finished_pid=",
290
+ 'set +e; wait -n -p finished_pid "${watch_pids[@]}"; status=$?; set -e',
291
+ 'if [ "${finished_pid:-}" != "$runtime_pid" ]; then status=1; fi',
292
+ 'kill -TERM "$runtime_pid" 2>/dev/null || true',
293
+ "for child in \"${relay_pid:-}\" \"${broker_pid:-}\" \"${launcher_pid:-}\"; do [ -z \"$child\" ] || { kill -TERM \"$child\" 2>/dev/null || true; wait \"$child\" 2>/dev/null || true; }; done",
294
+ 'wait "$runtime_pid" 2>/dev/null || true',
295
+ "exit \"$status\""
296
+ ].join("\n") + "\n";
297
+ };
@@ -1,14 +1,21 @@
1
1
  import type { RuntimeTargetPlan } from "./containerArtifactsTypes.js";
2
2
  import type { MoltnetArtifacts } from "./moltnetArtifacts.js";
3
+ import { type BackedMountRequirement } from "./containerBackedMountRender.js";
3
4
  export interface EntrypointOptions {
4
5
  hasMoltnet?: boolean;
5
6
  hasStagedMoltnetBinaries?: boolean;
7
+ hasWorkspaceBundles?: boolean;
6
8
  moltnet?: {
7
9
  externalParticipantArtifacts?: NonNullable<MoltnetArtifacts["externalParticipantArtifacts"]>;
8
10
  nodePlans: MoltnetArtifacts["nodePlans"];
9
11
  serverPlans: MoltnetArtifacts["serverPlans"];
10
12
  };
11
13
  moltnetPublishedPorts?: number[];
14
+ /**
15
+ * Durable mounts this image requires a launcher to attach. Drives the
16
+ * fail-closed `require_backed_mount` guard; see containerBackedMountRender.ts.
17
+ */
18
+ persistentMounts?: readonly BackedMountRequirement[];
12
19
  persistentMountPaths?: string[];
13
20
  }
14
21
  export declare const renderEntrypoint: (runtimePlans: RuntimeTargetPlan[], requiredSecrets: string[], options?: EntrypointOptions) => string;