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,56 @@
1
+ /**
2
+ * Fail-closed guard for durable container state.
3
+ *
4
+ * Every path in `container.persistent_mounts[]` is state the compiler expects
5
+ * a host-backed named volume to hold. `spawnfile run`/`spawnfile up` and
6
+ * `spawnfile deploy` mount them; a hand-rolled `docker run` of the same image
7
+ * does not, and nothing in the image declares `VOLUME`, so the container would
8
+ * silently write its whole durable record onto the container's own writable
9
+ * layer and lose it on `docker rm`. That is exactly how a newsroom's message
10
+ * history was destroyed by a routine recreate.
11
+ *
12
+ * These checks make that case loud instead of silent: the entrypoint refuses
13
+ * to start unless each durable path is a real mount point, naming the mount
14
+ * id, the path, and the volume name to attach. `SPAWNFILE_ALLOW_EPHEMERAL_STATE=1`
15
+ * is the deliberate opt-out for throwaway containers.
16
+ *
17
+ * Detection reads `/proc/self/mountinfo` and looks for an EXACT mount point,
18
+ * rather than comparing `stat -c %d` against the parent directory: two nested
19
+ * durable volumes live on the same host filesystem and therefore share a
20
+ * device number, which would make a device comparison report a genuinely
21
+ * backed inner mount as unbacked.
22
+ *
23
+ * The kernel octal-escapes four characters in the mountinfo mount-point field
24
+ * (`show_mountinfo` passes `" \t\n\\"` to `seq_path_root`), so a declared
25
+ * `mount: "/var/lib/my store"` appears there as `/var/lib/my\040store`. The
26
+ * comparison is therefore made against the compiler-escaped form — computed
27
+ * here, where it is exactly testable — while the operator-facing message keeps
28
+ * the real path. Escaping at compile time rather than decoding in shell keeps
29
+ * the check a deterministic string compare with no dependence on how a
30
+ * particular `printf %b` implementation treats `\nnn` vs `\0nnn`. For a path
31
+ * containing none of those four characters both forms are identical.
32
+ */
33
+ export declare const EPHEMERAL_STATE_OPT_OUT_ENV = "SPAWNFILE_ALLOW_EPHEMERAL_STATE";
34
+ export interface BackedMountRequirement {
35
+ id: string;
36
+ mount_path: string;
37
+ volume_name: string;
38
+ }
39
+ /** The mount-point field exactly as `/proc/self/mountinfo` renders this path. */
40
+ export declare const escapeMountInfoPath: (value: string) => string;
41
+ export declare const createBackedMountShellFunction: () => string[];
42
+ /**
43
+ * One check per durable mount, deduplicated by path and ordered by path so the
44
+ * rendered entrypoint is a deterministic function of the compile plan.
45
+ */
46
+ export declare const createBackedMountChecks: (mounts: readonly BackedMountRequirement[]) => string[];
47
+ /**
48
+ * The full guard — function plus checks — or nothing at all when the compile
49
+ * declares no durable mounts.
50
+ */
51
+ export declare const createBackedMountGuard: (mounts: readonly BackedMountRequirement[]) => string[];
52
+ /**
53
+ * Compile-time operator surface: how many durable mounts this organization
54
+ * requires a launcher to attach.
55
+ */
56
+ export declare const describeBackedMountRequirement: (mounts: readonly BackedMountRequirement[]) => string | null;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Fail-closed guard for durable container state.
3
+ *
4
+ * Every path in `container.persistent_mounts[]` is state the compiler expects
5
+ * a host-backed named volume to hold. `spawnfile run`/`spawnfile up` and
6
+ * `spawnfile deploy` mount them; a hand-rolled `docker run` of the same image
7
+ * does not, and nothing in the image declares `VOLUME`, so the container would
8
+ * silently write its whole durable record onto the container's own writable
9
+ * layer and lose it on `docker rm`. That is exactly how a newsroom's message
10
+ * history was destroyed by a routine recreate.
11
+ *
12
+ * These checks make that case loud instead of silent: the entrypoint refuses
13
+ * to start unless each durable path is a real mount point, naming the mount
14
+ * id, the path, and the volume name to attach. `SPAWNFILE_ALLOW_EPHEMERAL_STATE=1`
15
+ * is the deliberate opt-out for throwaway containers.
16
+ *
17
+ * Detection reads `/proc/self/mountinfo` and looks for an EXACT mount point,
18
+ * rather than comparing `stat -c %d` against the parent directory: two nested
19
+ * durable volumes live on the same host filesystem and therefore share a
20
+ * device number, which would make a device comparison report a genuinely
21
+ * backed inner mount as unbacked.
22
+ *
23
+ * The kernel octal-escapes four characters in the mountinfo mount-point field
24
+ * (`show_mountinfo` passes `" \t\n\\"` to `seq_path_root`), so a declared
25
+ * `mount: "/var/lib/my store"` appears there as `/var/lib/my\040store`. The
26
+ * comparison is therefore made against the compiler-escaped form — computed
27
+ * here, where it is exactly testable — while the operator-facing message keeps
28
+ * the real path. Escaping at compile time rather than decoding in shell keeps
29
+ * the check a deterministic string compare with no dependence on how a
30
+ * particular `printf %b` implementation treats `\nnn` vs `\0nnn`. For a path
31
+ * containing none of those four characters both forms are identical.
32
+ */
33
+ export const EPHEMERAL_STATE_OPT_OUT_ENV = "SPAWNFILE_ALLOW_EPHEMERAL_STATE";
34
+ const shellQuote = (value) => `'${value.replace(/'/g, `'"'"'`)}'`;
35
+ const MOUNTINFO_ESCAPES = {
36
+ "\\": "\\134",
37
+ " ": "\\040",
38
+ "\t": "\\011",
39
+ "\n": "\\012"
40
+ };
41
+ /** The mount-point field exactly as `/proc/self/mountinfo` renders this path. */
42
+ export const escapeMountInfoPath = (value) => value.replace(/[\\ \t\n]/gu, (character) => MOUNTINFO_ESCAPES[character]);
43
+ export const createBackedMountShellFunction = () => [
44
+ "require_backed_mount() {",
45
+ ' local mount_id="$1"',
46
+ // As mountinfo renders it (octal-escaped), for the comparison only.
47
+ ' local mount_field="$2"',
48
+ // The real path, for every operator-facing message.
49
+ ' local mount_target="$3"',
50
+ ' local mount_volume="$4"',
51
+ " local mount_point",
52
+ ` if [ "\${${EPHEMERAL_STATE_OPT_OUT_ENV}:-}" = "1" ]; then`,
53
+ " return 0",
54
+ " fi",
55
+ " if [ ! -r /proc/self/mountinfo ]; then",
56
+ ' echo "Durable mount $mount_id at $mount_target cannot be verified: /proc/self/mountinfo is unreadable" >&2',
57
+ " exit 1",
58
+ " fi",
59
+ " while read -r _ _ _ _ mount_point _; do",
60
+ ' if [ "$mount_point" = "$mount_field" ]; then',
61
+ " return 0",
62
+ " fi",
63
+ " done < /proc/self/mountinfo",
64
+ ' echo "Durable mount $mount_id is not backed by a volume at $mount_target; this container would lose that state when it is removed." >&2',
65
+ ` echo "Start this image with 'spawnfile run' or 'spawnfile up', or pass: --mount type=volume,source=\$mount_volume,target=\$mount_target" >&2`,
66
+ ` echo "Set ${EPHEMERAL_STATE_OPT_OUT_ENV}=1 to run this container without durable state." >&2`,
67
+ " exit 1",
68
+ "}"
69
+ ];
70
+ /**
71
+ * One check per durable mount, deduplicated by path and ordered by path so the
72
+ * rendered entrypoint is a deterministic function of the compile plan.
73
+ */
74
+ export const createBackedMountChecks = (mounts) => {
75
+ const byPath = new Map();
76
+ for (const mount of mounts) {
77
+ if (!byPath.has(mount.mount_path))
78
+ byPath.set(mount.mount_path, mount);
79
+ }
80
+ return [...byPath.values()]
81
+ .sort((left, right) => left.mount_path.localeCompare(right.mount_path))
82
+ .map((mount) => `require_backed_mount ${shellQuote(mount.id)} ${shellQuote(escapeMountInfoPath(mount.mount_path))} ${shellQuote(mount.mount_path)} ${shellQuote(mount.volume_name)}`);
83
+ };
84
+ /**
85
+ * The full guard — function plus checks — or nothing at all when the compile
86
+ * declares no durable mounts.
87
+ */
88
+ export const createBackedMountGuard = (mounts) => {
89
+ const checks = createBackedMountChecks(mounts);
90
+ return checks.length === 0 ? [] : [...createBackedMountShellFunction(), "", ...checks, ""];
91
+ };
92
+ /**
93
+ * Compile-time operator surface: how many durable mounts this organization
94
+ * requires a launcher to attach.
95
+ */
96
+ export const describeBackedMountRequirement = (mounts) => {
97
+ const count = new Set(mounts.map((mount) => mount.mount_path)).size;
98
+ if (count === 0)
99
+ return null;
100
+ return `${count} durable mount${count === 1 ? "" : "s"} must be attached at start: use 'spawnfile run'/'spawnfile up', or pass matching --mount type=volume args. The entrypoint refuses to start otherwise (set ${EPHEMERAL_STATE_OPT_OUT_ENV}=1 to accept state loss).`;
101
+ };
@@ -0,0 +1,112 @@
1
+ import type { RuntimeTargetPlan } from "./containerArtifactsTypes.js";
2
+ import { type DaimonGrokRegistration, type DaimonGrokServiceConfigOptions } from "./containerDaimonGrokWorkerRender.js";
3
+ import { DAIMON_BROKER_UID, DAIMON_FIRST_WORKER_UID, DAIMON_ORGANIZATION_UID } from "../runtime/daimon/runtimeIdentity.js";
4
+ export { DAIMON_BROKER_UID, DAIMON_FIRST_WORKER_UID, DAIMON_ORGANIZATION_UID };
5
+ export declare const DAIMON_BROKER_EXECUTABLE = "/opt/daimon/bin/daimon-engine-broker";
6
+ export declare const DAIMON_BROKER_REGISTRATIONS = "/etc/daimon-engine-broker/registrations.bin";
7
+ export declare const DAIMON_BROKER_SOCKET = "/run/daimon-engine-broker/control.sock";
8
+ export declare const DAIMON_BROKER_BACKEND_SOCKET = "/run/daimon-engine-broker/backend.sock";
9
+ export declare const DAIMON_BROKER_LAUNCHER_SOCKET = "/run/daimon-engine-broker/launcher.sock";
10
+ export declare const DAIMON_BROKER_SERVICE_CONFIG = "/etc/daimon-engine-broker/service.json";
11
+ export declare const DAIMON_BROKER_REALM = "/var/lib/spawnfile/daimon/grok-subscription-realm";
12
+ /**
13
+ * Private temp for the broker and its relay (uid 2100, outside the organization
14
+ * group): shared `/tmp` and `/var/tmp` are `root:2000 1774` in a Grok
15
+ * organization, so any non-root process outside group 2000 needs its own
16
+ * `TMPDIR`. It lives in the broker's `/run` directory, which every worker denies.
17
+ */
18
+ export declare const DAIMON_BROKER_TMPDIR = "/run/daimon-engine-broker/tmp";
19
+ export { DAIMON_ORGANIZATION_STATE_DIRECTORY, DAIMON_WORKER_ROOT, resolveDaimonGrokRegistrations } from "./containerDaimonGrokWorkerRender.js";
20
+ interface WorkspaceSecurityResource {
21
+ backingPath: string;
22
+ kind: "bundle" | "git" | "volume";
23
+ linkPath: string;
24
+ mode: "mutable" | "readonly";
25
+ resolvedIdentity: string | null;
26
+ }
27
+ export declare const renderDaimonWorkspaceResourceSecurity: (resources: WorkspaceSecurityResource[], owners?: {
28
+ linkUid: number;
29
+ linkGid: number;
30
+ readonlyUid: number;
31
+ readonlyGid: number;
32
+ privilegedUid: number;
33
+ privilegedGid: number;
34
+ }, resourceRoot?: string) => string[];
35
+ /**
36
+ * Fixes ownership and mode of the per-turn usage ledger directory for every
37
+ * Daimon organization, not just ones with a Grok agent. AGY and Codex both
38
+ * write here too (`onTurnUsage` in Daimon's `engineDispatcher.ts`), from the
39
+ * organization-uid runtime process (`uid`/`gid` below, set in
40
+ * `renderDaimonUidEntrypoint`) rather than the privileged broker — so this
41
+ * must run whether or not any Grok registration exists, and the directory
42
+ * must be group-writable (0770), not merely group-readable (0750): a mode
43
+ * that only lets the group list the directory silently defeated every
44
+ * AGY/Codex advisory usage write and, with it, Daimon's wake-fuse token
45
+ * ceiling, which now refuses to start at all if this ledger is missing or
46
+ * unreadable (`wakeFuse.ts`'s `ensureUsageLedgerReadable`).
47
+ *
48
+ * The directory itself is never created here: it is a persistent volume
49
+ * mount (`daimon-grok-usage-ledger` in `config.ts`, unconditional for every
50
+ * Daimon organization) that Docker always materializes before the entrypoint
51
+ * runs — exactly like `DAIMON_WAKE_FUSE_DIRECTORY`, whose own fix-up
52
+ * (`renderDaimonUidEntrypoint`) uses this same three-step order. `chown` to
53
+ * root first, `chmod` next, `chown` to the final owner last — never
54
+ * `install -d`'s create-then-chown-then-chmod order, and never a single
55
+ * `chown owner:group` followed by `chmod`: root only ever chmods a path it
56
+ * currently owns, so it never needs `CAP_FOWNER` (`runProject.ts`'s
57
+ * capability set grants `CAP_CHOWN` but not `CAP_FOWNER`) — chmod-ing
58
+ * *after* the final `chown` hands ownership to the broker uid fails with
59
+ * `EPERM` the moment root no longer owns the path.
60
+ */
61
+ export declare const renderDaimonUsageLedgerProvisioning: () => string[];
62
+ /**
63
+ * Empties a directory without touching a mount point inside it.
64
+ *
65
+ * `rm -rf` and `find -delete` both fail `EBUSY` on a mount point — it is
66
+ * another filesystem's root, and its entry cannot be unlinked while it is
67
+ * mounted. A deployment that mounts a tmpfs below a directory it later clears
68
+ * would otherwise abort provisioning on a bare `find` failure, which is exactly
69
+ * how a live training launch died. Mount points are left in place and descended
70
+ * into; anything else that cannot be removed is reported by name.
71
+ *
72
+ * Mount points come from `/proc/self/mountinfo` field 5. The kernel
73
+ * octal-escapes space, tab, newline and backslash there; every path this
74
+ * compiler provisions is free of all four, and a path that is not would simply
75
+ * fail to match and be treated as an ordinary directory.
76
+ */
77
+ export declare const MOUNT_AWARE_CLEAR_HELPER: string[];
78
+ export declare const renderDaimonBrokerProvisioning: (plans: RuntimeTargetPlan[]) => string[];
79
+ /**
80
+ * The root broker provisioning program itself, over already-resolved
81
+ * registrations and workspace resources.
82
+ *
83
+ * Production reaches it through {@link renderDaimonBrokerProvisioning}; the
84
+ * broker-capable training container reaches it directly for its single fixed
85
+ * slot, with `serviceOptions` pointing the turn store at per-slot tmpfs and
86
+ * declaring the evaluator inference ledger. Both callers get byte-identical
87
+ * credential, registration, worker-home, temp and spill provisioning — the
88
+ * whole point of sharing it rather than writing a second root program.
89
+ *
90
+ * It is re-runnable: the shell wrapper removes `/etc/daimon-engine-broker` and
91
+ * `/run/daimon-engine-broker` first, so a slot recycle replays exactly the
92
+ * audited start-up path, credential-journal recovery included.
93
+ */
94
+ export declare const renderDaimonBrokerProvisioningProgram: (registrations: readonly DaimonGrokRegistration[], workspaceResources: WorkspaceSecurityResource[], serviceOptions?: DaimonGrokServiceConfigOptions,
95
+ /**
96
+ * How the broker's `/etc` and `/run` roots are reset before provisioning.
97
+ * A production organization owns both as ordinary image directories and
98
+ * removes them outright. The training container mounts each as its own
99
+ * tmpfs, which cannot be unlinked, so it empties them instead — the same
100
+ * end state, reached the only way a mount point allows.
101
+ */
102
+ rootReset?: "remove" | "clear",
103
+ /** Deny targets the worker provisioning creates when absent; see `renderDaimonGrokWorkerProvisioning`. */
104
+ optionalDenyPaths?: readonly string[],
105
+ /**
106
+ * Where the broker and relay get their private `TMPDIR`. Production keeps it
107
+ * inside the control root, which it removes and recreates exactly once. A
108
+ * deployment that re-provisions that root — the training slot recycle — must
109
+ * pass a path outside it: a `tmp/` inside a cleared root is a mount point in
110
+ * the training launch, and clearing a mount point fails `EBUSY`.
111
+ */
112
+ brokerTmpdir?: string) => string[];
@@ -0,0 +1,191 @@
1
+ import { DAIMON_GROK_ENGINE_BROKER, DAIMON_GROK_TURN_USAGE_LEDGER } from "../runtime/daimon/contractManifest.js";
2
+ import { resolveDaimonGrokRegistrations } from "./containerDaimonGrokWorkerRender.js";
3
+ import { renderDaimonGrokWorkerProvisioning } from "./containerDaimonGrokWorkerProvisioning.js";
4
+ import { DAIMON_BROKER_UID, DAIMON_FIRST_WORKER_UID, DAIMON_ORGANIZATION_UID } from "../runtime/daimon/runtimeIdentity.js";
5
+ export { DAIMON_BROKER_UID, DAIMON_FIRST_WORKER_UID, DAIMON_ORGANIZATION_UID };
6
+ export const DAIMON_BROKER_EXECUTABLE = "/opt/daimon/bin/daimon-engine-broker";
7
+ export const DAIMON_BROKER_REGISTRATIONS = "/etc/daimon-engine-broker/registrations.bin";
8
+ export const DAIMON_BROKER_SOCKET = "/run/daimon-engine-broker/control.sock";
9
+ export const DAIMON_BROKER_BACKEND_SOCKET = "/run/daimon-engine-broker/backend.sock";
10
+ export const DAIMON_BROKER_LAUNCHER_SOCKET = "/run/daimon-engine-broker/launcher.sock";
11
+ export const DAIMON_BROKER_SERVICE_CONFIG = "/etc/daimon-engine-broker/service.json";
12
+ export const DAIMON_BROKER_REALM = "/var/lib/spawnfile/daimon/grok-subscription-realm";
13
+ /**
14
+ * Private temp for the broker and its relay (uid 2100, outside the organization
15
+ * group): shared `/tmp` and `/var/tmp` are `root:2000 1774` in a Grok
16
+ * organization, so any non-root process outside group 2000 needs its own
17
+ * `TMPDIR`. It lives in the broker's `/run` directory, which every worker denies.
18
+ */
19
+ export const DAIMON_BROKER_TMPDIR = "/run/daimon-engine-broker/tmp";
20
+ export { DAIMON_ORGANIZATION_STATE_DIRECTORY, DAIMON_WORKER_ROOT, resolveDaimonGrokRegistrations } from "./containerDaimonGrokWorkerRender.js";
21
+ export const renderDaimonWorkspaceResourceSecurity = (resources, owners = { linkUid: 2_000, linkGid: 2_000, readonlyUid: 2_000, readonlyGid: 2_000, privilegedUid: 0, privilegedGid: 0 }, resourceRoot = "/var/lib/spawnfile/resources/") => [
22
+ `const workspaceResources = ${JSON.stringify(resources)};`,
23
+ "const resourceByLink = new Map(workspaceResources.map((resource) => [resource.linkPath, resource])); if (resourceByLink.size !== workspaceResources.length) throw new Error('duplicate worker workspace resource link');",
24
+ `const validateResourceLink = (target, info) => { const resource = resourceByLink.get(target); if (!resource || info.uid !== ${owners.linkUid} || info.gid !== ${owners.linkGid} || info.nlink !== 1) throw new Error('unsafe worker workspace link'); const raw = fs.readlinkSync(target), normalized = require('node:path').posix.normalize(raw); if (!raw.startsWith('/') || normalized !== raw || raw !== resource.backingPath || !raw.startsWith(${JSON.stringify(resourceRoot)})) throw new Error('unsafe worker workspace link target'); const backing = fs.lstatSync(raw); if (!backing.isDirectory() || backing.isSymbolicLink()) throw new Error('unsafe worker workspace resource'); const mode = backing.mode & 0o777; if (resource.kind === 'volume') { const lifecycleOwner = (backing.uid === ${owners.privilegedUid} && backing.gid === ${owners.privilegedGid}) || (backing.uid === ${owners.linkUid} && backing.gid === ${owners.linkGid}); if (!lifecycleOwner || mode !== 0o755 || typeof resource.resolvedIdentity !== 'string') throw new Error('unsafe worker workspace volume'); const expected = Buffer.from(\`${"${resource.resolvedIdentity}"}\\n\`); if (expected.length !== 72) throw new Error('unsafe worker workspace volume identity'); const sentinel = \`${"${raw}"}/.spawnfile-resource-identity\`; let fd; try { fd = fs.openSync(sentinel, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK); const before = fs.fstatSync(fd); if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1 || before.uid !== ${owners.privilegedUid} || before.gid !== ${owners.privilegedGid} || (before.mode & 0o777) !== 0o644 || before.size !== expected.length) throw new Error('unsafe worker workspace volume identity'); const bytes = fs.readFileSync(fd), after = fs.fstatSync(fd); if (!bytes.equals(expected) || after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeMs !== before.mtimeMs || after.ctimeMs !== before.ctimeMs) throw new Error('unsafe worker workspace volume identity'); } finally { expected.fill(0); if (fd !== undefined) fs.closeSync(fd); } } else if (resource.mode === 'readonly') { if (backing.uid !== ${owners.readonlyUid} || backing.gid !== ${owners.readonlyGid} || mode !== 0o555) throw new Error('unsafe readonly worker workspace resource'); } else if (backing.uid !== ${owners.privilegedUid} || backing.gid !== ${owners.privilegedGid} || mode !== 0o755) throw new Error('unsafe mutable worker workspace resource'); };`,
25
+ "const secureWorkspace = (root, uid) => { const visit = (target) => { const info = fs.lstatSync(target); if (info.isSymbolicLink()) { validateResourceLink(target, info); return; } if (info.isDirectory()) { fs.chownSync(target, 0, 0); fs.chmodSync(target, 0o750); for (const name of fs.readdirSync(target)) visit(`${target}/${name}`); fs.chownSync(target, 2000, uid); } else if (info.isFile()) { fs.chownSync(target, 0, 0); fs.chmodSync(target, 0o640); fs.chownSync(target, 2000, uid); } else throw new Error('unsafe worker workspace node'); }; visit(root); };"
26
+ ];
27
+ /**
28
+ * Fixes ownership and mode of the per-turn usage ledger directory for every
29
+ * Daimon organization, not just ones with a Grok agent. AGY and Codex both
30
+ * write here too (`onTurnUsage` in Daimon's `engineDispatcher.ts`), from the
31
+ * organization-uid runtime process (`uid`/`gid` below, set in
32
+ * `renderDaimonUidEntrypoint`) rather than the privileged broker — so this
33
+ * must run whether or not any Grok registration exists, and the directory
34
+ * must be group-writable (0770), not merely group-readable (0750): a mode
35
+ * that only lets the group list the directory silently defeated every
36
+ * AGY/Codex advisory usage write and, with it, Daimon's wake-fuse token
37
+ * ceiling, which now refuses to start at all if this ledger is missing or
38
+ * unreadable (`wakeFuse.ts`'s `ensureUsageLedgerReadable`).
39
+ *
40
+ * The directory itself is never created here: it is a persistent volume
41
+ * mount (`daimon-grok-usage-ledger` in `config.ts`, unconditional for every
42
+ * Daimon organization) that Docker always materializes before the entrypoint
43
+ * runs — exactly like `DAIMON_WAKE_FUSE_DIRECTORY`, whose own fix-up
44
+ * (`renderDaimonUidEntrypoint`) uses this same three-step order. `chown` to
45
+ * root first, `chmod` next, `chown` to the final owner last — never
46
+ * `install -d`'s create-then-chown-then-chmod order, and never a single
47
+ * `chown owner:group` followed by `chmod`: root only ever chmods a path it
48
+ * currently owns, so it never needs `CAP_FOWNER` (`runProject.ts`'s
49
+ * capability set grants `CAP_CHOWN` but not `CAP_FOWNER`) — chmod-ing
50
+ * *after* the final `chown` hands ownership to the broker uid fails with
51
+ * `EPERM` the moment root no longer owns the path.
52
+ */
53
+ export const renderDaimonUsageLedgerProvisioning = () => {
54
+ const { directoryPath } = DAIMON_GROK_TURN_USAGE_LEDGER;
55
+ return [
56
+ `chown 0:0 ${directoryPath} && chmod 0770 ${directoryPath} && chown ${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID} ${directoryPath}`,
57
+ `setpriv --clear-groups --reuid ${DAIMON_ORGANIZATION_UID} --regid ${DAIMON_ORGANIZATION_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu 'probe=${directoryPath}/.daimon-usage-probe; umask 007; : > "$probe"; rm "$probe"'`
58
+ ];
59
+ };
60
+ /**
61
+ * Empties a directory without touching a mount point inside it.
62
+ *
63
+ * `rm -rf` and `find -delete` both fail `EBUSY` on a mount point — it is
64
+ * another filesystem's root, and its entry cannot be unlinked while it is
65
+ * mounted. A deployment that mounts a tmpfs below a directory it later clears
66
+ * would otherwise abort provisioning on a bare `find` failure, which is exactly
67
+ * how a live training launch died. Mount points are left in place and descended
68
+ * into; anything else that cannot be removed is reported by name.
69
+ *
70
+ * Mount points come from `/proc/self/mountinfo` field 5. The kernel
71
+ * octal-escapes space, tab, newline and backslash there; every path this
72
+ * compiler provisions is free of all four, and a path that is not would simply
73
+ * fail to match and be treated as an ordinary directory.
74
+ */
75
+ export const MOUNT_AWARE_CLEAR_HELPER = [
76
+ "spawnfile_mount_points=$(awk '{print $5}' /proc/self/mountinfo)",
77
+ "spawnfile_is_mount() { printf '%s\\n' \"$spawnfile_mount_points\" | grep -qxF \"$1\"; }",
78
+ "spawnfile_holds_mount() { printf '%s\\n' \"$spawnfile_mount_points\" | grep -qE \"^$(printf '%s' \"$1\" | sed 's/[][\\.*^$/]/\\\\&/g')(/|$)\"; }",
79
+ "spawnfile_clear_tree() {",
80
+ " spawnfile_root=$1",
81
+ " [ -d \"$spawnfile_root\" ] || return 0",
82
+ " for spawnfile_entry in \"$spawnfile_root\"/* \"$spawnfile_root\"/.[!.]* \"$spawnfile_root\"/..?*; do",
83
+ " if [ ! -e \"$spawnfile_entry\" ] && [ ! -L \"$spawnfile_entry\" ]; then continue; fi",
84
+ " if spawnfile_is_mount \"$spawnfile_entry\"; then continue; fi",
85
+ " if spawnfile_holds_mount \"$spawnfile_entry\"; then spawnfile_clear_tree \"$spawnfile_entry\"; continue; fi",
86
+ " rm -rf \"$spawnfile_entry\" || { echo \"cannot clear $spawnfile_entry: it is in use; a mount below a provisioned root must be declared outside it\" >&2; return 1; }",
87
+ " done",
88
+ "}",
89
+ // Removes the target outright, unless it is or contains a mount point: then its contents go and the
90
+ // mount points and the directories holding them stay, because neither can be unlinked while mounted.
91
+ "spawnfile_remove_tree() {",
92
+ " if [ ! -e \"$1\" ] && [ ! -L \"$1\" ]; then return 0; fi",
93
+ " if spawnfile_holds_mount \"$1\"; then spawnfile_clear_tree \"$1\"; return $?; fi",
94
+ " rm -rf \"$1\" || { echo \"cannot remove $1: it is in use\" >&2; return 1; }",
95
+ "}"
96
+ ];
97
+ export const renderDaimonBrokerProvisioning = (plans) => {
98
+ const registrations = resolveDaimonGrokRegistrations(plans);
99
+ if (registrations.length === 0)
100
+ return [];
101
+ const workspaceResources = plans
102
+ .filter((plan) => plan.runtimeName === "daimon")
103
+ .flatMap((plan) => plan.resources ?? [])
104
+ .map((resource) => ({
105
+ backingPath: resource.backingPath,
106
+ kind: resource.kind,
107
+ linkPath: resource.linkPath,
108
+ mode: resource.mode,
109
+ resolvedIdentity: "resolvedIdentity" in resource && typeof resource.resolvedIdentity === "string"
110
+ ? resource.resolvedIdentity
111
+ : null
112
+ }))
113
+ .sort((left, right) => left.linkPath.localeCompare(right.linkPath));
114
+ return renderDaimonBrokerProvisioningProgram(registrations, workspaceResources);
115
+ };
116
+ /**
117
+ * The root broker provisioning program itself, over already-resolved
118
+ * registrations and workspace resources.
119
+ *
120
+ * Production reaches it through {@link renderDaimonBrokerProvisioning}; the
121
+ * broker-capable training container reaches it directly for its single fixed
122
+ * slot, with `serviceOptions` pointing the turn store at per-slot tmpfs and
123
+ * declaring the evaluator inference ledger. Both callers get byte-identical
124
+ * credential, registration, worker-home, temp and spill provisioning — the
125
+ * whole point of sharing it rather than writing a second root program.
126
+ *
127
+ * It is re-runnable: the shell wrapper removes `/etc/daimon-engine-broker` and
128
+ * `/run/daimon-engine-broker` first, so a slot recycle replays exactly the
129
+ * audited start-up path, credential-journal recovery included.
130
+ */
131
+ export const renderDaimonBrokerProvisioningProgram = (registrations, workspaceResources, serviceOptions = {},
132
+ /**
133
+ * How the broker's `/etc` and `/run` roots are reset before provisioning.
134
+ * A production organization owns both as ordinary image directories and
135
+ * removes them outright. The training container mounts each as its own
136
+ * tmpfs, which cannot be unlinked, so it empties them instead — the same
137
+ * end state, reached the only way a mount point allows.
138
+ */
139
+ rootReset = "remove",
140
+ /** Deny targets the worker provisioning creates when absent; see `renderDaimonGrokWorkerProvisioning`. */
141
+ optionalDenyPaths,
142
+ /**
143
+ * Where the broker and relay get their private `TMPDIR`. Production keeps it
144
+ * inside the control root, which it removes and recreates exactly once. A
145
+ * deployment that re-provisions that root — the training slot recycle — must
146
+ * pass a path outside it: a `tmp/` inside a cleared root is a mount point in
147
+ * the training launch, and clearing a mount point fails `EBUSY`.
148
+ */
149
+ brokerTmpdir = DAIMON_BROKER_TMPDIR) => {
150
+ const program = [
151
+ "const crypto = require('node:crypto'); const fs = require('node:fs');",
152
+ `const registrations = ${JSON.stringify(registrations.map(({ agentId, home, slot, uid, workspace }) => ({ agentId, home, slot, uid, workspace })))};`,
153
+ `const executable = '${DAIMON_GROK_ENGINE_BROKER.grokExecutablePath}';`,
154
+ "const digest = crypto.createHash('sha256').update(fs.readFileSync(executable)).digest();",
155
+ `if (!${JSON.stringify([DAIMON_GROK_ENGINE_BROKER.grokCliArtifacts.arm64.sha256, DAIMON_GROK_ENGINE_BROKER.grokCliArtifacts.x64.sha256])}.includes(digest.toString('hex'))) throw new Error('Grok executable is not the manifest-pinned ${DAIMON_GROK_ENGINE_BROKER.grokCliVersion} build');`,
156
+ "const cString = (buffer, offset, length, value) => { const bytes = Buffer.from(value); if (bytes.length < 1 || bytes.length >= length || bytes.includes(0)) throw new Error('invalid broker registration'); bytes.copy(buffer, offset); };",
157
+ `const records = registrations.map((entry) => { const record = Buffer.alloc(692); record.writeUInt32LE(${DAIMON_GROK_ENGINE_BROKER.nativeAbiVersion}, 0); record.writeUInt32LE(entry.slot, 4); record.writeUInt32LE(entry.uid, 8); record.writeUInt32LE(entry.uid, 12); cString(record, 16, 129, entry.agentId); cString(record, 145, 256, entry.workspace); cString(record, 401, 256, entry.home); digest.copy(record, 657); return record; });`,
158
+ "fs.mkdirSync('/etc/daimon-engine-broker', { recursive: true, mode: 0o700 }); fs.chownSync('/etc/daimon-engine-broker', 0, 0); fs.chmodSync('/etc/daimon-engine-broker', 0o700);",
159
+ "fs.writeFileSync('/etc/daimon-engine-broker/registrations.bin', Buffer.concat(records), { mode: 0o400, flag: 'wx' });",
160
+ "fs.chownSync('/etc/daimon-engine-broker/registrations.bin', 0, 0); fs.chmodSync('/etc/daimon-engine-broker/registrations.bin', 0o400);",
161
+ `fs.mkdirSync('${DAIMON_BROKER_REALM}', { recursive: true, mode: 0o700 }); fs.chownSync('${DAIMON_BROKER_REALM}', 0, 0); fs.chmodSync('${DAIMON_BROKER_REALM}', 0o700);`,
162
+ // The usage ledger directory itself is provisioned unconditionally by
163
+ // `renderDaimonUsageLedgerProvisioning` (every Daimon organization writes
164
+ // here, not just Grok ones) before this script's caller reaches the
165
+ // broker startup this function guards; this script only ever reads the
166
+ // path below, for the sandbox denylist.
167
+ `const bootstrap = '/var/lib/spawnfile/daimon/grok-bootstrap-auth', authority = '${DAIMON_BROKER_REALM}/auth.json';`,
168
+ "const readSecure = (file, owner, label) => { const before = fs.lstatSync(file); if (!before.isFile() || before.isSymbolicLink() || (owner !== undefined && (before.uid !== owner || before.gid !== owner)) || (before.mode & 0o777) !== 0o600 || before.nlink !== 1 || before.size < 2 || before.size > 65536) throw new Error(`unsafe broker credential ${label}`); const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK); try { const opened = fs.fstatSync(fd); if (opened.dev !== before.dev || opened.ino !== before.ino) throw new Error(`unsafe broker credential ${label}`); const bytes = Buffer.alloc(opened.size); let offset = 0; while (offset < bytes.length) { const count = fs.readSync(fd, bytes, offset, bytes.length - offset, offset); if (count < 1) throw new Error(`unsafe broker credential ${label}`); offset += count; } return bytes; } finally { fs.closeSync(fd); } };",
169
+ `const atomicOwned = (target, bytes) => { const temporary = \`${"${target}"}.\${process.pid}.\${crypto.randomUUID()}.tmp\`; try { const output = fs.openSync(temporary, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW, 0o600); try { let written = 0; while (written < bytes.length) written += fs.writeSync(output, bytes, written, bytes.length - written, written); fs.fchmodSync(output, 0o600); fs.fchownSync(output, 2100, 2100); fs.fsyncSync(output); } finally { fs.closeSync(output); } fs.renameSync(temporary, target); const directory = fs.openSync(require('node:path').dirname(target), fs.constants.O_RDONLY | fs.constants.O_DIRECTORY); try { fs.fsyncSync(directory); } finally { fs.closeSync(directory); } } catch (error) { try { fs.unlinkSync(temporary); } catch {} throw error; } };`,
170
+ "let existing; try { existing = fs.lstatSync(authority); } catch (error) { if (error.code !== 'ENOENT') throw error; } const bootstrapBytes = readSecure(bootstrap, undefined, 'bootstrap'); let bootstrapRecord; try { const root = JSON.parse(bootstrapBytes.toString('utf8')), rows = root && typeof root === 'object' && !Array.isArray(root) ? Object.entries(root).filter(([key, value]) => /^https:\\/\\/auth\\.x\\.ai::/.test(key) && value && typeof value === 'object' && !Array.isArray(value)).map(([, value]) => value) : []; if (rows.length !== 1 || typeof rows[0].key !== 'string' || !rows[0].key.trim() || typeof rows[0].refresh_token !== 'string' || !rows[0].refresh_token.trim() || typeof rows[0].expires_at !== 'string' || !Number.isFinite(Date.parse(rows[0].expires_at))) throw new Error(); bootstrapRecord = true; } catch { bootstrapBytes.fill(0); throw new Error('invalid broker credential bootstrap'); } if (!bootstrapRecord) throw new Error('invalid broker credential bootstrap'); const bootstrapDigest = crypto.createHash('sha256').update(bootstrapBytes).digest('hex');",
171
+ `const journalRoot = '${DAIMON_BROKER_REALM}/.daimon-broker'; let journalRootExists = false; try { const info = fs.lstatSync(journalRoot); if (!info.isDirectory() || info.isSymbolicLink() || info.uid !== 2100 || info.gid !== 2100 || (info.mode & 0o777) !== 0o700) throw new Error('unsafe broker credential journal directory'); fs.chownSync(journalRoot, 0, 0); fs.chmodSync(journalRoot, 0o700); journalRootExists = true; } catch (error) { if (error.code !== 'ENOENT') throw error; }`,
172
+ `try { const journalPath = '${DAIMON_BROKER_REALM}/.daimon-broker/credential-journal.json'; let journal; try { const raw = readSecure(journalPath, 2100, 'recovery journal'); journal = JSON.parse(raw.toString('utf8')); raw.fill(0); } catch (error) { if (error.code !== 'ENOENT') throw error; } const stale = journal?.version === 'noopolis.daimon.broker-credential-journal.v1' && journal.state === 'stale'; const recover = () => { if (!stale || !Number.isSafeInteger(journal.generation) || journal.generation < 0 || !/^[a-f0-9]{64}$/.test(journal.sourceDigest) || journal.sourceDigest !== journal.promotedDigest || bootstrapDigest === journal.sourceDigest) throw new Error('unsafe broker credential recovery'); atomicOwned(authority, bootstrapBytes); const recovered = Buffer.from(\`${"${JSON.stringify({ version: 'noopolis.daimon.broker-credential-journal.v1', state: 'promoted', generation: journal.generation + 1, sourceDigest: journal.sourceDigest, promotedDigest: bootstrapDigest })}"}\\n\`); try { atomicOwned(journalPath, recovered); } finally { recovered.fill(0); } }; if (!existing) { if (stale) recover(); else atomicOwned(authority, bootstrapBytes); } else { const authorityBytes = readSecure(authority, 2100, 'authority'); try { const authorityDigest = crypto.createHash('sha256').update(authorityBytes).digest('hex'); if (stale) { if (authorityDigest !== journal.sourceDigest && authorityDigest !== bootstrapDigest) throw new Error('unsafe broker credential recovery'); if (authorityDigest === bootstrapDigest) { const recovered = Buffer.from(\`${"${JSON.stringify({ version: 'noopolis.daimon.broker-credential-journal.v1', state: 'promoted', generation: journal.generation + 1, sourceDigest: journal.sourceDigest, promotedDigest: bootstrapDigest })}"}\\n\`); try { atomicOwned(journalPath, recovered); } finally { recovered.fill(0); } } else recover(); } } finally { authorityBytes.fill(0); } } } finally { bootstrapBytes.fill(0); }`,
173
+ "if (journalRootExists) { fs.chownSync(journalRoot, 0, 0); fs.chmodSync(journalRoot, 0o700); fs.chownSync(journalRoot, 2100, 2100); }",
174
+ ...renderDaimonWorkspaceResourceSecurity(workspaceResources),
175
+ ...renderDaimonGrokWorkerProvisioning(registrations, serviceOptions, ...(optionalDenyPaths ? [optionalDenyPaths] : [])),
176
+ `fs.chownSync('${DAIMON_BROKER_REALM}', 0, 0); fs.chmodSync('${DAIMON_BROKER_REALM}', 0o700); fs.chownSync('${DAIMON_BROKER_REALM}', 2100, 2100);`,
177
+ "fs.chmodSync('/etc/daimon-engine-broker', 0o555);"
178
+ ].join("\n");
179
+ return [
180
+ "if [ -d /etc/daimon-engine-broker ]; then chmod u+rwx /etc/daimon-engine-broker; fi",
181
+ "if [ -d /run/daimon-engine-broker ]; then chmod u+rwx /run/daimon-engine-broker; fi",
182
+ ...(rootReset === "remove"
183
+ ? ["rm -rf /etc/daimon-engine-broker /run/daimon-engine-broker"]
184
+ : [...MOUNT_AWARE_CLEAR_HELPER, "for broker_root in /etc/daimon-engine-broker /run/daimon-engine-broker; do spawnfile_clear_tree \"$broker_root\"; done"]),
185
+ `install -d -o root -g ${DAIMON_BROKER_UID} -m 0731 /run/daimon-engine-broker`,
186
+ `install -d -o ${DAIMON_BROKER_UID} -g ${DAIMON_BROKER_UID} -m 0700 ${brokerTmpdir}`,
187
+ "node <<'SPAWNFILE_DAIMON_BROKER_PROVISION'",
188
+ program,
189
+ "SPAWNFILE_DAIMON_BROKER_PROVISION"
190
+ ];
191
+ };
@@ -0,0 +1,38 @@
1
+ import { type DaimonGrokRegistration, type DaimonGrokServiceConfigOptions } from "./containerDaimonGrokWorkerRender.js";
2
+ /**
3
+ * Root provisioning for every brokered Grok worker, as lines of the broker's
4
+ * node provisioning program (which already defines `crypto`, `fs`, and
5
+ * `secureWorkspace`).
6
+ *
7
+ * Layout per Daimon's `GROK_ENGINE_BROKER.worker.home` (attested by the broker
8
+ * before every turn): `$GROK_HOME` (`<home>/.grok`) and `$GROK_HOME/sessions`
9
+ * are `root:<worker> 1771`; `config.toml` (Daimon's renderer bytes for the
10
+ * declared model x effort), `sandbox.toml`, and the empty `trusted_folders.toml`,
11
+ * `managed_config.toml` and `requirements.toml` are `root:root 0444`, so the
12
+ * worker can neither write, rename nor unlink any file that decides a turn —
13
+ * trust included; `sessions/sandbox-events.jsonl` is `<worker>:<broker> 0640`.
14
+ *
15
+ * Every path handed to Daimon (workspace, home, profile, events, and each deny
16
+ * entry) must be canonical: it exists, is not a symlink, and resolves to itself.
17
+ * Daimon never resolves these paths, so a symlinked entry would silently mask
18
+ * the wrong inode. Root chmods only paths it owns at that moment (no
19
+ * `CAP_FOWNER`): reclaim, mode, then hand over.
20
+ */
21
+ export declare const renderDaimonGrokWorkerProvisioning: (registrations: readonly DaimonGrokRegistration[], serviceOptions?: DaimonGrokServiceConfigOptions,
22
+ /**
23
+ * Deny targets this program creates root-owned `0700` when they are absent,
24
+ * so every mask always has an inode. The default is the production
25
+ * container's set; the training container passes its own, because its roots
26
+ * are tmpfs mounts and `/run/secrets` and the shared state roots do not
27
+ * exist there at all.
28
+ */
29
+ optionalDenyPaths?: readonly string[]) => string[];
30
+ /**
31
+ * Grok 1.0.34 runs every sandbox profile inside bubblewrap, which needs
32
+ * unprivileged user namespaces. Ubuntu 24.04+ hosts (and Colima's default VM)
33
+ * ship `kernel.apparmor_restrict_unprivileged_userns=1`, under which bubblewrap
34
+ * cannot create them even with the pinned seccomp profile — every worker turn
35
+ * would then fail attestation long after startup. The container sees the host
36
+ * kernel's sysctls read-only, so this refuses to start with the fix named.
37
+ */
38
+ export declare const renderDaimonGrokHostPreflight: (procSys?: string) => string[];