@voltro/plugin-rooms 0.0.0-stage → 0.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (495) hide show
  1. package/CHANGELOG.md +24492 -0
  2. package/LICENSE +61 -0
  3. package/README.md +9204 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +12496 -0
  6. package/dist/actor.js +1473 -0
  7. package/dist/apiBinding.js +677 -0
  8. package/dist/apiRegistryBinding.js +398 -0
  9. package/dist/apiReservations.js +432 -0
  10. package/dist/baselines.js +72 -0
  11. package/dist/bots.d.ts +1485 -0
  12. package/dist/bots.js +562 -0
  13. package/dist/catalog.js +79 -0
  14. package/dist/checkpointJson.js +23 -0
  15. package/dist/checkpointStore.js +385 -0
  16. package/dist/client.js +55 -0
  17. package/dist/clockSync.js +50 -0
  18. package/dist/collision.js +155 -0
  19. package/dist/commandDelivery.js +100 -0
  20. package/dist/commandRecord.js +10 -0
  21. package/dist/commandWithdrawal.js +182 -0
  22. package/dist/connection.js +496 -0
  23. package/dist/controlCarrier.js +374 -0
  24. package/dist/controlRegistry.js +78 -0
  25. package/dist/controlTarget.js +44 -0
  26. package/dist/controlTransport.js +573 -0
  27. package/dist/developmentBinding.js +112 -0
  28. package/dist/directory.js +322 -0
  29. package/dist/directoryProjection.js +116 -0
  30. package/dist/errors.d.ts +125 -0
  31. package/dist/errors.js +52 -0
  32. package/dist/fixed.d.ts +284 -0
  33. package/dist/fixed.js +10 -0
  34. package/dist/fixed32.js +133 -0
  35. package/dist/fixedCollision.js +59 -0
  36. package/dist/fixedCollision32.js +108 -0
  37. package/dist/fixedMath.js +55 -0
  38. package/dist/fixedRaw.js +10 -0
  39. package/dist/fixedSlabs.js +33 -0
  40. package/dist/fixedTrig.js +47 -0
  41. package/dist/fixedTrig32.js +37 -0
  42. package/dist/fixedVectors.js +112 -0
  43. package/dist/fixedVectors32.js +94 -0
  44. package/dist/fixedWide.js +49 -0
  45. package/dist/fixedWords.js +45 -0
  46. package/dist/gateway.js +56 -0
  47. package/dist/geometry-retention-app/rooms.geometryJournalRetention.workflow.server.tsx +4 -0
  48. package/dist/geometry-retention-app/rooms.geometryJournalRetention.workflow.tsx +14 -0
  49. package/dist/geometry-worker/worker.d.mts +2 -0
  50. package/dist/geometry-worker/worker.mjs +50 -0
  51. package/dist/geometry.d.ts +2249 -0
  52. package/dist/geometry.js +40 -0
  53. package/dist/geometryActivation.js +81 -0
  54. package/dist/geometryActorInventory.js +107 -0
  55. package/dist/geometryAdminClient.js +86 -0
  56. package/dist/geometryAdminData.js +31 -0
  57. package/dist/geometryAdminFixtures.js +49 -0
  58. package/dist/geometryAdminPorts.js +4 -0
  59. package/dist/geometryAdminRpc.js +57 -0
  60. package/dist/geometryAdminRpcRoutes.js +48 -0
  61. package/dist/geometryAdminSchemas.js +38 -0
  62. package/dist/geometryAdministration.js +189 -0
  63. package/dist/geometryAdministrationPorts.js +4 -0
  64. package/dist/geometryApiBinding.js +164 -0
  65. package/dist/geometryAppStorage.js +57 -0
  66. package/dist/geometryArtifacts.js +197 -0
  67. package/dist/geometryAssetBundle.js +116 -0
  68. package/dist/geometryAssetClient.js +24 -0
  69. package/dist/geometryAssetData.js +105 -0
  70. package/dist/geometryAssetHttp.js +122 -0
  71. package/dist/geometryAssetPorts.js +4 -0
  72. package/dist/geometryAssetRpc.js +29 -0
  73. package/dist/geometryAssetRpcRoutes.js +39 -0
  74. package/dist/geometryAssetStorageGrant.js +102 -0
  75. package/dist/geometryBoxOverlap.js +109 -0
  76. package/dist/geometryCatalogueDigest.js +110 -0
  77. package/dist/geometryCellCoverage.js +84 -0
  78. package/dist/geometryCellLoader.js +27 -0
  79. package/dist/geometryChannel.js +133 -0
  80. package/dist/geometryChunkHttp.js +53 -0
  81. package/dist/geometryChunkLeases.js +21 -0
  82. package/dist/geometryClient.d.ts +1429 -0
  83. package/dist/geometryClient.js +148 -0
  84. package/dist/geometryClientChunks.js +329 -0
  85. package/dist/geometryClientDelta.js +24 -0
  86. package/dist/geometryClientHttp.js +36 -0
  87. package/dist/geometryClientInterest.js +108 -0
  88. package/dist/geometryClientStatic.js +33 -0
  89. package/dist/geometryCms.d.ts +763 -0
  90. package/dist/geometryCms.js +216 -0
  91. package/dist/geometryCommitCoordinator.js +240 -0
  92. package/dist/geometryCompactionFixture.js +83 -0
  93. package/dist/geometryCompactionStrategies.js +37 -0
  94. package/dist/geometryConnectionClient.js +22 -0
  95. package/dist/geometryDerivationFixtures.js +140 -0
  96. package/dist/geometryDerivationStrategies.js +26 -0
  97. package/dist/geometryDigest.js +12 -0
  98. package/dist/geometryEditChannel.js +69 -0
  99. package/dist/geometryEditIngress.js +262 -0
  100. package/dist/geometryEdits.js +365 -0
  101. package/dist/geometryEnvelope.js +40 -0
  102. package/dist/geometryGridRaycast.js +91 -0
  103. package/dist/geometryGridSweep.js +91 -0
  104. package/dist/geometryHeightfield.js +165 -0
  105. package/dist/geometryHeightfieldRaycast.js +73 -0
  106. package/dist/geometryHeightfieldSweep.js +84 -0
  107. package/dist/geometryHeightfieldVolume.js +44 -0
  108. package/dist/geometryHost.js +321 -0
  109. package/dist/geometryHostDirectory.js +206 -0
  110. package/dist/geometryHostMutations.js +136 -0
  111. package/dist/geometryHostStreams.js +123 -0
  112. package/dist/geometryHttpBody.js +75 -0
  113. package/dist/geometryHttpRoutes.js +111 -0
  114. package/dist/geometryImportGltf.js +299 -0
  115. package/dist/geometryImportLdtk.js +53 -0
  116. package/dist/geometryImportPng.js +143 -0
  117. package/dist/geometryImportPublication.js +66 -0
  118. package/dist/geometryImportTiled.js +38 -0
  119. package/dist/geometryImportTiles.js +135 -0
  120. package/dist/geometryImportVox.js +129 -0
  121. package/dist/geometryImportedSource.js +100 -0
  122. package/dist/geometryInspectEndpoint.js +247 -0
  123. package/dist/geometryInspection.js +91 -0
  124. package/dist/geometryInstall.js +120 -0
  125. package/dist/geometryJournalArchiveData.js +20 -0
  126. package/dist/geometryJournalArchiveIndex.js +329 -0
  127. package/dist/geometryJournalArchiveTable.js +20 -0
  128. package/dist/geometryJournalCompaction.js +99 -0
  129. package/dist/geometryJournalPatch.js +46 -0
  130. package/dist/geometryJournalRetention.js +111 -0
  131. package/dist/geometryJournalRetentionSchemas.js +35 -0
  132. package/dist/geometryJournalRetentionSweep.js +111 -0
  133. package/dist/geometryJournalRetentionWorkflow.js +27 -0
  134. package/dist/geometryJournalRetentionWorkflowData.js +30 -0
  135. package/dist/geometryJournalStorage.js +147 -0
  136. package/dist/geometryLoader.js +117 -0
  137. package/dist/geometryManifest.js +112 -0
  138. package/dist/geometryManifestChannel.js +92 -0
  139. package/dist/geometryManifestClient.js +121 -0
  140. package/dist/geometryManifestData.js +48 -0
  141. package/dist/geometryManifestPorts.js +4 -0
  142. package/dist/geometryManifestPublication.js +108 -0
  143. package/dist/geometryManifestSource.js +67 -0
  144. package/dist/geometryMigrationJournal.js +13 -0
  145. package/dist/geometryMigrationStrategies.js +6 -0
  146. package/dist/geometryMigrations.js +322 -0
  147. package/dist/geometryNativeMetadata.js +51 -0
  148. package/dist/geometryPatch.js +169 -0
  149. package/dist/geometryPersistence.js +448 -0
  150. package/dist/geometryPersistenceCapture.js +68 -0
  151. package/dist/geometryPersistenceData.js +139 -0
  152. package/dist/geometryPersistencePorts.js +4 -0
  153. package/dist/geometryPlayerAdmission.js +33 -0
  154. package/dist/geometryPlayerEditOwner.js +264 -0
  155. package/dist/geometryPlayerEdits.js +48 -0
  156. package/dist/geometryPrepared.js +187 -0
  157. package/dist/geometryPrivacyFence.js +23 -0
  158. package/dist/geometryProceduralPublication.js +90 -0
  159. package/dist/geometryProceduralWorker.js +163 -0
  160. package/dist/geometryPublication.js +109 -0
  161. package/dist/geometryRayAlgebra.js +115 -0
  162. package/dist/geometryReadClient.js +156 -0
  163. package/dist/geometryReadPorts.js +4 -0
  164. package/dist/geometryReadRpc.js +26 -0
  165. package/dist/geometryReadRpcRoutes.js +46 -0
  166. package/dist/geometryReliablePublication.js +81 -0
  167. package/dist/geometryReloadPorts.js +45 -0
  168. package/dist/geometryReloadSource.js +277 -0
  169. package/dist/geometryRenderCache.js +164 -0
  170. package/dist/geometryRenderLod.js +101 -0
  171. package/dist/geometryRollback.js +124 -0
  172. package/dist/geometryRollbackCoordinator.js +202 -0
  173. package/dist/geometryRollbackPorts.js +45 -0
  174. package/dist/geometryRollbackSource.js +208 -0
  175. package/dist/geometryRollbackStore.js +197 -0
  176. package/dist/geometrySchemas.js +26 -0
  177. package/dist/geometryServer.d.ts +2766 -0
  178. package/dist/geometryServer.js +62 -0
  179. package/dist/geometryShapeRaycast.js +110 -0
  180. package/dist/geometryShapeSegments.js +33 -0
  181. package/dist/geometryShapes.js +222 -0
  182. package/dist/geometrySnapshot.js +75 -0
  183. package/dist/geometrySnapshotChannel.js +159 -0
  184. package/dist/geometrySnapshotClient.js +158 -0
  185. package/dist/geometrySnapshotPreparation.js +75 -0
  186. package/dist/geometrySnapshotServer.js +190 -0
  187. package/dist/geometrySqlOwner.js +20 -0
  188. package/dist/geometryStorage.js +126 -0
  189. package/dist/geometryStorageGrant.js +68 -0
  190. package/dist/geometryStorageIdentity.js +8 -0
  191. package/dist/geometryTileArtifact.js +9 -0
  192. package/dist/geometryTileCodec.js +193 -0
  193. package/dist/geometryTileCollision.js +95 -0
  194. package/dist/geometryTileNavigation.js +127 -0
  195. package/dist/geometryTileView.js +34 -0
  196. package/dist/geometryVersionActivation.js +113 -0
  197. package/dist/geometryVersionClient.js +237 -0
  198. package/dist/geometryVersionCompare.js +39 -0
  199. package/dist/geometryVersionMigration.js +105 -0
  200. package/dist/geometryVoxel.js +252 -0
  201. package/dist/geometryWorldEntitySubject.js +31 -0
  202. package/dist/geometryWorldExtent.js +11 -0
  203. package/dist/geometryWorldMetadata.js +37 -0
  204. package/dist/geometryWorldStrategyFixtures.js +126 -0
  205. package/dist/geometryWorldView.js +306 -0
  206. package/dist/host.js +127 -0
  207. package/dist/hostBinding.js +276 -0
  208. package/dist/hostCellObservation.js +113 -0
  209. package/dist/hostClientCapacity.js +89 -0
  210. package/dist/hostCommandScope.js +63 -0
  211. package/dist/hostController.js +3093 -0
  212. package/dist/hostDeployment.js +64 -0
  213. package/dist/hostDrain.js +151 -0
  214. package/dist/hostDrainPorts.js +4 -0
  215. package/dist/hostDriver.js +178 -0
  216. package/dist/hostLane.js +287 -0
  217. package/dist/hostListener.js +78 -0
  218. package/dist/hostListenerBinding.js +18 -0
  219. package/dist/hostLoopObservation.js +89 -0
  220. package/dist/hostMetrics.js +55 -0
  221. package/dist/hostRegistryBinding.js +417 -0
  222. package/dist/hostSelection.js +15 -0
  223. package/dist/hostShutdown.js +46 -0
  224. package/dist/hostTurnObservation.js +52 -0
  225. package/dist/identities.js +3 -0
  226. package/dist/index.d.ts +8632 -0
  227. package/dist/index.js +231 -0
  228. package/dist/inputReceipts.js +62 -0
  229. package/dist/inputRedundancy.js +54 -0
  230. package/dist/inspect.js +237 -0
  231. package/dist/lockstep.d.ts +436 -0
  232. package/dist/lockstep.js +381 -0
  233. package/dist/lockstepAdmission.js +261 -0
  234. package/dist/lockstepAdmissionCodec.js +93 -0
  235. package/dist/lockstepAdmissionPorts.js +4 -0
  236. package/dist/lockstepClientSession.js +577 -0
  237. package/dist/lockstepDefinition.js +147 -0
  238. package/dist/lockstepHostLoop.js +242 -0
  239. package/dist/lockstepInitialAdmission.js +66 -0
  240. package/dist/lockstepInitialStrategyFixtures.js +44 -0
  241. package/dist/lockstepJournal.js +394 -0
  242. package/dist/lockstepJournalCodec.js +253 -0
  243. package/dist/lockstepJournalPorts.js +4 -0
  244. package/dist/lockstepJournalRebuild.js +207 -0
  245. package/dist/lockstepJournalRows.js +56 -0
  246. package/dist/lockstepMembers.js +130 -0
  247. package/dist/lockstepMessages.js +46 -0
  248. package/dist/lockstepOwnedRoom.js +763 -0
  249. package/dist/lockstepPolicies.js +83 -0
  250. package/dist/lockstepReact.js +46 -0
  251. package/dist/lockstepRecoveryTruth.js +120 -0
  252. package/dist/lockstepRosterConfig.js +31 -0
  253. package/dist/lockstepSeed.js +11 -0
  254. package/dist/lockstepSeedFixture.js +19 -0
  255. package/dist/lockstepServer.d.ts +3897 -0
  256. package/dist/lockstepServer.js +324 -0
  257. package/dist/lockstepServerConfig.js +100 -0
  258. package/dist/lockstepServerRoles.js +402 -0
  259. package/dist/lockstepServerStrategyFixtures.js +32 -0
  260. package/dist/lockstepStrategies.js +5 -0
  261. package/dist/lockstepStrategyFixtures.js +136 -0
  262. package/dist/lockstepTerminal.js +89 -0
  263. package/dist/lockstepTerminalPorts.js +4 -0
  264. package/dist/lockstepTransport.js +772 -0
  265. package/dist/lockstepTransportConfig.js +31 -0
  266. package/dist/lockstepWireRoster.js +33 -0
  267. package/dist/matchRoomProvider.js +31 -0
  268. package/dist/matchRooms.js +18 -0
  269. package/dist/membershipObserver.js +46 -0
  270. package/dist/moderation.js +97 -0
  271. package/dist/movementSpecials.js +103 -0
  272. package/dist/ownership.js +16 -0
  273. package/dist/ownershipWithdrawal.js +17 -0
  274. package/dist/pcg32.js +95 -0
  275. package/dist/ports.d.ts +1241 -0
  276. package/dist/ports.js +10 -0
  277. package/dist/quaternion.js +69 -0
  278. package/dist/react.d.ts +406 -0
  279. package/dist/react.js +108 -0
  280. package/dist/reaper-app/rooms.reaper.workflow.server.tsx +5 -0
  281. package/dist/reaper-app/rooms.reaper.workflow.tsx +13 -0
  282. package/dist/reaper.js +242 -0
  283. package/dist/reaperSchemas.js +41 -0
  284. package/dist/reaperWorkflow.js +69 -0
  285. package/dist/recovery.js +188 -0
  286. package/dist/recoverySeats.js +25 -0
  287. package/dist/replay.d.ts +273 -0
  288. package/dist/replay.js +484 -0
  289. package/dist/replayPorts.js +4 -0
  290. package/dist/replayRecording.js +66 -0
  291. package/dist/replaySchema.js +156 -0
  292. package/dist/replayStorage.d.ts +149 -0
  293. package/dist/replayStorage.js +484 -0
  294. package/dist/reservationBatch.js +421 -0
  295. package/dist/reservationSchemas.js +16 -0
  296. package/dist/reservations.js +258 -0
  297. package/dist/reservePort.js +68 -0
  298. package/dist/resolvedOptions.js +3 -0
  299. package/dist/room.d.ts +1006 -0
  300. package/dist/room.js +283 -0
  301. package/dist/roomAccessSweep.js +94 -0
  302. package/dist/roomAppCommandControl.js +58 -0
  303. package/dist/roomAuthoringStrategy.js +16 -0
  304. package/dist/roomErasure.js +197 -0
  305. package/dist/roomPoolRuntimeDefaults.js +23 -0
  306. package/dist/roomPoolSelection.js +18 -0
  307. package/dist/roomPoolTopology.js +211 -0
  308. package/dist/rpc.d.ts +551 -0
  309. package/dist/rpc.js +111 -0
  310. package/dist/rpcClient.js +151 -0
  311. package/dist/rpcRoutes.js +27 -0
  312. package/dist/runtime.js +1122 -0
  313. package/dist/schemaHistory.js +97 -0
  314. package/dist/seatStore.js +150 -0
  315. package/dist/seatStrategyFixtures.js +51 -0
  316. package/dist/seatSubject.js +31 -0
  317. package/dist/seats.js +129 -0
  318. package/dist/serverSession.js +810 -0
  319. package/dist/serverSessionConfig.js +42 -0
  320. package/dist/sessionAdmission.js +52 -0
  321. package/dist/sidecarAdmission.js +102 -0
  322. package/dist/sidecarConfig.js +115 -0
  323. package/dist/sidecarConfigPublication.js +63 -0
  324. package/dist/sidecarHostListener.js +207 -0
  325. package/dist/sidecarIpc.js +204 -0
  326. package/dist/sidecarPeer.js +309 -0
  327. package/dist/sidecarProcessPort.js +27 -0
  328. package/dist/sidecarRuntime.js +167 -0
  329. package/dist/sidecarSelection.js +141 -0
  330. package/dist/sidecarWire.js +177 -0
  331. package/dist/sidecarWrites.js +162 -0
  332. package/dist/simulation.d.ts +391 -0
  333. package/dist/simulation.js +281 -0
  334. package/dist/simulationAuthoring.js +28 -0
  335. package/dist/simulationBytes.js +26 -0
  336. package/dist/simulationConformance.js +304 -0
  337. package/dist/simulationInputHistoryCapture.js +34 -0
  338. package/dist/simulationInputHistoryWire.js +192 -0
  339. package/dist/simulationOptionsWire.js +77 -0
  340. package/dist/simulationRecoveryWire.js +133 -0
  341. package/dist/simulationReplay.js +126 -0
  342. package/dist/simulationSnapshotWire.js +111 -0
  343. package/dist/simulationState.js +177 -0
  344. package/dist/snapshotBlob.js +125 -0
  345. package/dist/snapshotBlobCleanup.js +92 -0
  346. package/dist/snapshotBlobIndex.js +37 -0
  347. package/dist/snapshotBudget.js +79 -0
  348. package/dist/snapshotChain.js +184 -0
  349. package/dist/snapshotErasure.js +171 -0
  350. package/dist/snapshotInspection.js +104 -0
  351. package/dist/snapshotSegmentBlobs.js +57 -0
  352. package/dist/snapshotUploads.js +165 -0
  353. package/dist/socketTransport.js +252 -0
  354. package/dist/spatial.js +103 -0
  355. package/dist/spectatorPolicy.js +25 -0
  356. package/dist/spectatorProducer.js +88 -0
  357. package/dist/startFailureCause.js +3 -0
  358. package/dist/stateCodec.js +657 -0
  359. package/dist/strategies.d.ts +210 -0
  360. package/dist/strategies.js +8 -0
  361. package/dist/strategiesServer.d.ts +286 -0
  362. package/dist/strategiesServer.js +11 -0
  363. package/dist/strategyFixtures.js +181 -0
  364. package/dist/streamFraming.js +121 -0
  365. package/dist/streamTransport.js +265 -0
  366. package/dist/subjectAdmission.js +49 -0
  367. package/dist/subjectPrivacy.js +280 -0
  368. package/dist/subjectPrivacyBinding.js +89 -0
  369. package/dist/systemManifest.js +181 -0
  370. package/dist/tables.js +158 -0
  371. package/dist/testHarness.js +88 -0
  372. package/dist/testing.d.ts +3684 -0
  373. package/dist/testing.js +220 -0
  374. package/dist/testingPorts.js +270 -0
  375. package/dist/testingServer.d.ts +4060 -0
  376. package/dist/testingServer.js +18 -0
  377. package/dist/transform.d.ts +692 -0
  378. package/dist/transform.js +216 -0
  379. package/dist/transform3d.js +117 -0
  380. package/dist/transformCollection.js +23 -0
  381. package/dist/transformCollection3d.js +23 -0
  382. package/dist/transformCollectionCore.js +155 -0
  383. package/dist/transformFrames.js +120 -0
  384. package/dist/transformPrediction3d.js +126 -0
  385. package/dist/transformRules.js +122 -0
  386. package/dist/transformSchemas.js +19 -0
  387. package/dist/transport.js +31 -0
  388. package/dist/transportAuthoring.js +28 -0
  389. package/dist/transportCleanup.js +21 -0
  390. package/dist/transportConformance.js +123 -0
  391. package/dist/transportConnector.js +81 -0
  392. package/dist/transportEndpoints.js +37 -0
  393. package/dist/transportsServer.d.ts +5515 -0
  394. package/dist/transportsServer.js +6 -0
  395. package/dist/viewProjection.js +15 -0
  396. package/dist/web.d.ts +2286 -0
  397. package/dist/web.js +517 -0
  398. package/dist/webTransportClient.js +172 -0
  399. package/dist/wire.d.ts +992 -0
  400. package/dist/wire.js +491 -0
  401. package/dist/withdrawalPort.js +27 -0
  402. package/dist/world.d.ts +1894 -0
  403. package/dist/world.js +332 -0
  404. package/dist/worldActorReceipts.js +47 -0
  405. package/dist/worldActorTransferSnapshot.js +13 -0
  406. package/dist/worldAdmissionPending.js +7 -0
  407. package/dist/worldBoundaryCoordinator.js +147 -0
  408. package/dist/worldCatalog.js +80 -0
  409. package/dist/worldCellAllocation.js +202 -0
  410. package/dist/worldCellDestination.js +67 -0
  411. package/dist/worldCells.js +488 -0
  412. package/dist/worldChange.js +31 -0
  413. package/dist/worldClient.js +663 -0
  414. package/dist/worldClientControl.js +140 -0
  415. package/dist/worldClientPendingInput.js +15 -0
  416. package/dist/worldClientRpc.js +132 -0
  417. package/dist/worldClientRpcRoutes.js +42 -0
  418. package/dist/worldClientSchemas.js +27 -0
  419. package/dist/worldCommands.js +139 -0
  420. package/dist/worldData.js +41 -0
  421. package/dist/worldDefaultBinding.js +376 -0
  422. package/dist/worldDefaultGroupAdmission.js +81 -0
  423. package/dist/worldDefaultGroupAppServices.js +30 -0
  424. package/dist/worldDefaultGroupCompensation.js +108 -0
  425. package/dist/worldDefaultGroupContinuation.js +95 -0
  426. package/dist/worldDefaultGroupControl.js +71 -0
  427. package/dist/worldDefaultGroupMembers.js +84 -0
  428. package/dist/worldDefaultGroups.js +20 -0
  429. package/dist/worldDefaultPending.js +78 -0
  430. package/dist/worldDefaultService.js +244 -0
  431. package/dist/worldEntities.js +2979 -0
  432. package/dist/worldEntityCodec.js +20 -0
  433. package/dist/worldEntityHandoffView.js +153 -0
  434. package/dist/worldGeometry.js +169 -0
  435. package/dist/worldGhostAdmission.js +64 -0
  436. package/dist/worldGhostDestination.js +117 -0
  437. package/dist/worldGhostGateway.js +131 -0
  438. package/dist/worldGhostHandshake.js +107 -0
  439. package/dist/worldGhostHost.js +41 -0
  440. package/dist/worldGhostIngress.js +131 -0
  441. package/dist/worldGhostNeighborhood.js +69 -0
  442. package/dist/worldGhostNeighbors.js +85 -0
  443. package/dist/worldGhostOutbound.js +109 -0
  444. package/dist/worldGhostPublisher.js +215 -0
  445. package/dist/worldGhostReceiver.js +212 -0
  446. package/dist/worldGhostSender.js +145 -0
  447. package/dist/worldGhostSocket.js +77 -0
  448. package/dist/worldGhostWire.js +171 -0
  449. package/dist/worldGroupCommand.js +48 -0
  450. package/dist/worldGroupDeadline.js +114 -0
  451. package/dist/worldGroupPreparation.js +114 -0
  452. package/dist/worldGroupReadyControl.js +127 -0
  453. package/dist/worldGroupSupervisor.js +119 -0
  454. package/dist/worldHandoffMetrics.js +58 -0
  455. package/dist/worldHandoffView.js +99 -0
  456. package/dist/worldHostSource.js +68 -0
  457. package/dist/worldInspectEndpoint.js +249 -0
  458. package/dist/worldInspection.js +108 -0
  459. package/dist/worldInstanceAdmission.js +30 -0
  460. package/dist/worldInstanceAllocation.js +115 -0
  461. package/dist/worldInstanceDestination.js +63 -0
  462. package/dist/worldInstanceExpiry.js +281 -0
  463. package/dist/worldInstanceExpirySupervisor.js +87 -0
  464. package/dist/worldInstanceLifecycle.js +102 -0
  465. package/dist/worldInstanceState.js +51 -0
  466. package/dist/worldInstances.js +477 -0
  467. package/dist/worldJoin.js +55 -0
  468. package/dist/worldLayers.js +150 -0
  469. package/dist/worldLeases.js +77 -0
  470. package/dist/worldManifest.js +24 -0
  471. package/dist/worldMovement.js +62 -0
  472. package/dist/worldPersistence.js +133 -0
  473. package/dist/worldProjection.js +220 -0
  474. package/dist/worldReact.js +109 -0
  475. package/dist/worldRecoveryActor.js +34 -0
  476. package/dist/worldReturnAnchor.js +48 -0
  477. package/dist/worldRoomHooks.js +56 -0
  478. package/dist/worldRoomPool.js +26 -0
  479. package/dist/worldRoomSteps.js +132 -0
  480. package/dist/worldSeatBinding.js +35 -0
  481. package/dist/worldServer.d.ts +6936 -0
  482. package/dist/worldServer.js +48 -0
  483. package/dist/worldSourceSeatPending.js +8 -0
  484. package/dist/worldStrategyFixtures.js +163 -0
  485. package/dist/worldTesting.js +26 -0
  486. package/dist/worldTransitionDefaults.js +197 -0
  487. package/dist/worldTransitionExecutor.js +518 -0
  488. package/dist/worldTransitionGroup.js +112 -0
  489. package/dist/worldTransitionPhysicalSteps.js +39 -0
  490. package/dist/worldTransitionResolver.js +227 -0
  491. package/dist/worldTransitionSeatGroup.js +63 -0
  492. package/dist/worldTransitionSeats.js +259 -0
  493. package/dist/worldTransitionState.js +94 -0
  494. package/dist/worldTransitions.js +100 -0
  495. package/package.json +189 -4
@@ -0,0 +1,3093 @@
1
+ import { BudgetExceeded as e, ProtocolError as t, RoomForbidden as n, RoomFull as r, RoomGone as i, RoomHibernatePending as a, RoomLocked as o } from "./errors.js";
2
+ import { simulationOwnData as s } from "./simulationAuthoring.js";
3
+ import { roomPoolLockstepCatchUp as c } from "./roomPoolRuntimeDefaults.js";
4
+ import { createSimulationOptionsCodec as l } from "./simulationOptionsWire.js";
5
+ import { captureRoomSeatAttributes as u } from "./room.js";
6
+ import { RoomStateCodec as d } from "./stateCodec.js";
7
+ import { geometryPersistenceId as f } from "./geometryPersistenceData.js";
8
+ import { captureRoomGeometryReloadRequest as p, captureRoomGeometryRollbackRequest as m } from "./geometryAdminData.js";
9
+ import { captureWorldData as h } from "./worldData.js";
10
+ import { captureRoomTransportDataMethod as g } from "./transportAuthoring.js";
11
+ import { RoomTransportCleanupFailure as _ } from "./transportCleanup.js";
12
+ import { roomHostTransportEndpoints as v } from "./transportEndpoints.js";
13
+ import { ROOMS_TABLE as y, ROOM_CREATIONS_TABLE as b, ROOM_HOSTS_TABLE as x } from "./identities.js";
14
+ import { captureWorldCatalog as ee, worldCellAt as S } from "./world.js";
15
+ import { canonicalRoomJson as C } from "./checkpointJson.js";
16
+ import { assertRoomSubjectAdmission as w } from "./subjectAdmission.js";
17
+ import { assertRoomSeatSecrets as te, resolveRoomSeatTokenStrategies as T, verifyRoomSeatWithStrategy as ne } from "./seats.js";
18
+ import { assertRoomPoolRecoveryTarget as re, captureRoomPoolCatalog as ie, resolveRoomPool as ae, roomPoolHostedNames as oe, roomPoolRuntimeDefaults as E } from "./roomPoolTopology.js";
19
+ import { dataStoreWorldCells as D } from "./worldCells.js";
20
+ import { roomReservationBatchSessionId as se } from "./reservationBatch.js";
21
+ import { readWorldTransitionSeatGroup as ce, worldTransitionSeatBatch as le } from "./worldTransitionSeatGroup.js";
22
+ import { withWorldRecoveryActor as ue } from "./worldRecoveryActor.js";
23
+ import { assertWorldActorSnapshotSource as de, captureWorldActorTransferSnapshot as O } from "./worldActorTransferSnapshot.js";
24
+ import { makeWorldBoundaryCoordinator as fe } from "./worldBoundaryCoordinator.js";
25
+ import { makeRoomWorldGhostReceiver as pe } from "./worldGhostHost.js";
26
+ import { makeWorldGhostPublisher as me } from "./worldGhostPublisher.js";
27
+ import { captureRoomWorldGhostOutboundOptions as k, ownWorldGhostOutbound as he } from "./worldGhostOutbound.js";
28
+ import { dataStoreWorldGhostDestination as ge } from "./worldGhostDestination.js";
29
+ import { roomWorldEntityCodec as A } from "./worldEntityCodec.js";
30
+ import { openWorldGhostSocket as _e } from "./worldGhostSocket.js";
31
+ import { bindWorldGhostIngress as ve } from "./worldGhostIngress.js";
32
+ import { assertWorldInstanceRecreation as ye, dataStoreWorldInstances as be, worldInstanceCreationKey as j } from "./worldInstances.js";
33
+ import { retireFailedWorldInstanceRoom as M, synchronizeWorldInstanceRoom as N } from "./worldInstanceLifecycle.js";
34
+ import { assertWorldCellRecreation as xe, worldCellCreationKey as Se } from "./worldCellAllocation.js";
35
+ import { insideRoomHostCommandScope as P, makeRoomHostCommandWindow as Ce, queueRoomHostCommandOperation as F, runRoomHostCommandOperation as we, withRoomHostCommandScope as Te } from "./hostCommandScope.js";
36
+ import { assertWorldTransitionExecution as I, withWorldTransitionGroupMember as Ee, worldTransitionExecutionGroup as De } from "./worldTransitionExecutor.js";
37
+ import { captureRoomWorldEntitySource as Oe } from "./worldHostSource.js";
38
+ import { RoomHostCellObservation as ke } from "./hostCellObservation.js";
39
+ import { dataStoreRoomCheckpoints as Ae } from "./checkpointStore.js";
40
+ import { captureRoomHostDrainPolicy as je, dataStoreRoomHostDrain as Me } from "./hostDrain.js";
41
+ import { dataStoreWorldGhostNeighbors as Ne } from "./worldGhostNeighbors.js";
42
+ import { captureRoomLockstepTransportLimits as Pe } from "./lockstepTransportConfig.js";
43
+ import { dataStoreRoomLockstepJournal as Fe } from "./lockstepJournal.js";
44
+ import { dataStoreRoomLockstepAdmission as Ie } from "./lockstepAdmission.js";
45
+ import { dataStoreRoomLockstepTerminal as Le } from "./lockstepTerminal.js";
46
+ import { captureRoomSnapshotBudget as L, defaultRoomSnapshotBudget as Re } from "./snapshotBudget.js";
47
+ import { captureRoomHostGeometryBinding as R, prepareRoomHostGeometry as z } from "./geometryHost.js";
48
+ import { RoomRuntime as ze } from "./runtime.js";
49
+ import { captureRoomLockstepInitialStrategies as Be, firstFreeRoomLockstepPlayerId as Ve, startFullRoomLockstepRoster as He } from "./lockstepInitialAdmission.js";
50
+ import { RoomLockstepOwnedRoom as B } from "./lockstepOwnedRoom.js";
51
+ import { randomRoomLockstepSeed as Ue, resolveRoomLockstepSeed as We } from "./lockstepSeed.js";
52
+ import { matchRoomCreationKey as Ge } from "./matchRooms.js";
53
+ import { RoomCommandDelivery as Ke } from "./commandDelivery.js";
54
+ import { dataStoreRoomDirectory as qe } from "./directory.js";
55
+ import { dataStoreRoomReservations as Je } from "./reservations.js";
56
+ import { roomOwnershipRevoked as V } from "./ownership.js";
57
+ import { captureRoomHostWithdrawalInput as Ye } from "./ownershipWithdrawal.js";
58
+ import { and as H, eq as U, inSet as Xe } from "@voltro/database";
59
+ import { Subject as W, checkGuardsEffect as Ze } from "@voltro/protocol";
60
+ import { Effect as G, Result as K, Schema as q } from "effect";
61
+ import { createHash as J } from "node:crypto";
62
+ // src/hostController.ts
63
+ var Y = async (e, t) => {
64
+ let n = await G.runPromise(G.result(e), { signal: t });
65
+ if (K.isFailure(n)) throw n.failure;
66
+ return n.success;
67
+ }, X = (e) => {
68
+ if (e.type === "system" || e.type === "service" || !e.tenantId?.trim()) throw new n({ roomId: "" });
69
+ return {
70
+ tenantId: e.tenantId,
71
+ subjectId: e.id,
72
+ ...e.type === "anonymous" ? {} : { subjectType: e.type },
73
+ ...e.type === "user" && e.kind === "guest" ? { subjectKind: "guest" } : {}
74
+ };
75
+ }, Z = class extends Error {
76
+ retryCleanup;
77
+ name = "RoomHostControllerStartFailure";
78
+ constructor(e) {
79
+ super("Room controller acquisition cleanup remains incomplete"), this.retryCleanup = e;
80
+ }
81
+ }, Q = (e, t) => {
82
+ let n = !1, r = !1, i = null;
83
+ return () => {
84
+ if (r) return Promise.resolve();
85
+ if (i) return i;
86
+ let a = (async () => {
87
+ n ||= (await Y(e.setReady(t, !1)), !0), await Y(e.unregister(t)), r = !0;
88
+ })();
89
+ return i = a, a.then(() => {
90
+ i = null;
91
+ }, () => {
92
+ i = null;
93
+ }), a;
94
+ };
95
+ }, $ = class $ {
96
+ host;
97
+ catalog;
98
+ store;
99
+ options;
100
+ runtime;
101
+ directory;
102
+ lockstepSeed;
103
+ lockstepInitial;
104
+ worldBoundaryClamps = 0;
105
+ worldBoundaryObserved = /* @__PURE__ */ new WeakMap();
106
+ ghostMaintenance;
107
+ boundaryMaintenance;
108
+ boundaryCellFactories = /* @__PURE__ */ new Map();
109
+ boundaryCoordinators = /* @__PURE__ */ new Map();
110
+ ghostCellFactories = /* @__PURE__ */ new Map();
111
+ ghostPublisherSequences = /* @__PURE__ */ new WeakMap();
112
+ ghostPublishers = /* @__PURE__ */ new Map();
113
+ ghostOutbounds = /* @__PURE__ */ new Set();
114
+ ghostTransports = /* @__PURE__ */ new Set();
115
+ ghostReceivers = /* @__PURE__ */ new Map();
116
+ owned = /* @__PURE__ */ new Map();
117
+ uninstalledCreations = /* @__PURE__ */ new Map();
118
+ pendingGeometryCleanup = /* @__PURE__ */ new Map();
119
+ geometryReloads = /* @__PURE__ */ new Map();
120
+ geometryRollbacks = /* @__PURE__ */ new Map();
121
+ lane = Promise.resolve();
122
+ queued = 0;
123
+ maxQueued;
124
+ nextHeartbeatAt;
125
+ closing = !1;
126
+ closed = !1;
127
+ activated = !1;
128
+ routingFenced = !1;
129
+ closeTask = null;
130
+ plannedDrain = null;
131
+ plannedRooms = /* @__PURE__ */ new Map();
132
+ delivery;
133
+ commandWindow = null;
134
+ seatToken;
135
+ spectatorGroups;
136
+ replayRecordings;
137
+ geometry;
138
+ cells;
139
+ constructor(e, t, n, r, i, a) {
140
+ this.host = e, this.catalog = t, this.store = n, this.options = r, this.directory = i, this.lockstepSeed = r.strategies?.lockstepSeed ?? Ue, this.lockstepInitial = Be({
141
+ playerId: r.strategies?.lockstepPlayerId ?? Ve,
142
+ start: r.strategies?.lockstepStart ?? He
143
+ }), this.seatToken = T(r.strategies?.seatToken), this.spectatorGroups = r.spectatorGroups, this.replayRecordings = r.replayRecordings, this.geometry = R(r.geometry), this.cells = new ke(r.worlds, e.id, r.capacity), this.activated = r.startSuspended !== !0, this.maxQueued = r.maxQueuedOperations ?? 128, this.nextHeartbeatAt = r.clock.now() + r.heartbeatEveryMs;
144
+ let o = r.ports?.checkpoints?.(e.id) ?? Ae(n, {
145
+ hostId: e.id,
146
+ epochNow: r.epochNow,
147
+ snapshotCodec: (e) => new d(t.get(e).state),
148
+ snapshotBlobs: r.snapshotBlobs,
149
+ maxInlineBytes: r.maxInlineBytes
150
+ });
151
+ this.runtime = new ze(r.capacity, r.clock, o, {
152
+ snapshotBudgetFactory: () => a,
153
+ poolDefaults: E(r.pools, r.pool)
154
+ }), this.delivery = new Ke(o, r.application, r.capacity, void 0, (e) => this.executeAppCommand(e));
155
+ }
156
+ static async start(e, n, r) {
157
+ let i = Object.getOwnPropertyDescriptor(r, "worldSnapshotMaxBytes");
158
+ if (i && (!("value" in i) || !Number.isSafeInteger(i.value) || i.value < 1 || i.value > 16777216) || !i && "worldSnapshotMaxBytes" in r) throw new t({ detail: "World snapshot recovery requires an own bounded byte budget" });
159
+ let a = Object.getOwnPropertyDescriptor(r, "worldGhostMaxConnections");
160
+ if (a && (!("value" in a) || !Number.isSafeInteger(a.value) || a.value < 1 || a.value > 65536) || !a && "worldGhostMaxConnections" in r) throw new t({ detail: "World ghost sockets require an own bounded connection inventory" });
161
+ if (r.ports && "hostDrain" in r.ports) {
162
+ let e = Object.getOwnPropertyDescriptor(r.ports, "hostDrain");
163
+ if (!e || !("value" in e) || typeof e.value != "function") throw new t({ detail: "Host drain requires its own callable provider factory" });
164
+ r = {
165
+ ...r,
166
+ ports: {
167
+ ...r.ports,
168
+ hostDrain: r.ports.hostDrain.bind(r.ports)
169
+ }
170
+ };
171
+ }
172
+ let o = Object.getOwnPropertyDescriptor(r, "resolveWorldPlayer");
173
+ if (o && (!("value" in o) || typeof o.value != "function") || !o && "resolveWorldPlayer" in r) throw new t({ detail: "World player selection requires an own server callback" });
174
+ o && (r = {
175
+ ...r,
176
+ resolveWorldPlayer: o.value.bind(r)
177
+ });
178
+ let c = Object.getOwnPropertyDescriptor(r, "worldEntities");
179
+ if (c && !("value" in c) || !c && "worldEntities" in r) throw new t({ detail: "Host World recovery requires an own capability" });
180
+ c?.value !== void 0 && (r = {
181
+ ...r,
182
+ worldEntities: Oe(c.value)
183
+ });
184
+ let l = Object.getOwnPropertyDescriptor(r, "geometry");
185
+ if (l && (!("value" in l) || !l.enumerable) || !l && "geometry" in r) throw new t({ detail: "Host geometry requires own complete source binding" });
186
+ let u = R(l?.value), d = Object.getOwnPropertyDescriptor(r, "webTransportAddress"), f = Object.getOwnPropertyDescriptor(r, "webTransportCertificateHash");
187
+ if (d && (!("value" in d) || !d.enumerable) || !d && "webTransportAddress" in r || f && (!("value" in f) || !f.enumerable) || !f && "webTransportCertificateHash" in r) throw new t({ detail: "Room host native endpoint requires own routing data" });
188
+ let p = v(r.address, d?.value, f?.value);
189
+ for (let e of [
190
+ "pools",
191
+ "pool",
192
+ "clientCapacity"
193
+ ]) {
194
+ let n = Object.getOwnPropertyDescriptor(r, e);
195
+ if (n && (!n.enumerable || !("value" in n)) || !n && e in r) throw new t({ detail: "Host pool options require own data" });
196
+ }
197
+ if (r.pools === void 0) {
198
+ if (r.pool !== void 0 || r.clientCapacity !== void 0) throw new t({ detail: "Host pool options require an admitted topology" });
199
+ } else {
200
+ let e = ie(r.pools, n.inventory().map((e) => e.descriptor.name)), i = r.pool ?? e.default, a = Object.hasOwn(e.pools, i) ? e.pools[i] : void 0, o = r.clientCapacity ?? a?.capacity?.clients;
201
+ if (!a || !a.regions.includes(r.region) || !Number.isSafeInteger(o) || o < 1) throw new t({ detail: "Host pool requires an explicit positive client capacity" });
202
+ r = {
203
+ ...r,
204
+ pools: e,
205
+ pool: i,
206
+ clientCapacity: o
207
+ };
208
+ }
209
+ let m = new Set(oe(r.pools, r.pool, n.inventory().map((e) => e.descriptor.name))), h = n.inventory().filter((e) => m.has(e.descriptor.name));
210
+ if (u?.worlds.some((e) => e.geometry && [...e.zones, ...e.instances].some((e) => m.has(e.room) && n.get(e.room).mode === "lockstep"))) throw new t({ detail: "World geometry requires its state-sync Host preparation; Lockstep geometry binding remains unimplemented" });
211
+ if (r.startSuspended !== void 0 && typeof r.startSuspended != "boolean") throw new t({ detail: "Invalid host activation policy" });
212
+ if (r.spectatorGroups !== void 0 && typeof r.spectatorGroups != "function") throw new t({ detail: "Invalid spectator view-group resolver" });
213
+ if (r.replayRecordings !== void 0 && typeof r.replayRecordings != "function") throw new t({ detail: "Invalid host replay recording resolver" });
214
+ if (!r.spectatorGroups && h.some((e) => e.descriptor.spectator)) throw new t({ detail: "Configured spectator history requires a host view-group resolver before registration" });
215
+ if (h.some((e) => e.descriptor.mode === "lockstep")) {
216
+ if (r.ports === void 0) throw new t({ detail: "Declared Lockstep requires complete coordinated erasure before host registration" });
217
+ let e = s(r.ports, [
218
+ "directory",
219
+ "checkpoints",
220
+ "recovery",
221
+ "erasure",
222
+ "hostDrain",
223
+ "lockstepAdmission",
224
+ "lockstepJournal",
225
+ "lockstepTerminal"
226
+ ], ["erasure"]), n = s(e.erasure, ["erase"], ["erase"]), i = s(r.strategies ?? {}, [
227
+ "selectHost",
228
+ "seatToken",
229
+ "snapshotBudget",
230
+ "lockstepSeed",
231
+ "lockstepPlayerId",
232
+ "lockstepStart"
233
+ ], []);
234
+ if (typeof n.erase != "function" || [
235
+ "lockstepSeed",
236
+ "lockstepPlayerId",
237
+ "lockstepStart"
238
+ ].some((e) => Object.hasOwn(i, e) && typeof i[e] != "function")) throw new t({ detail: "Declared Lockstep needs complete coordinated erasure and callable server seed/initial roster slots" });
239
+ for (let n of [
240
+ "lockstepAdmission",
241
+ "lockstepJournal",
242
+ "lockstepTerminal"
243
+ ]) if (Object.hasOwn(e, n) && typeof e[n] != "function") throw new t({ detail: "Lockstep replacement must provide an actual complete scoped capability factory" });
244
+ r = {
245
+ ...r,
246
+ ports: Object.freeze({
247
+ ...e,
248
+ erasure: Object.freeze({ erase: n.erase.bind(e.erasure) })
249
+ }),
250
+ strategies: Object.freeze(i),
251
+ lockstepTransport: Pe(r.lockstepTransport)
252
+ };
253
+ }
254
+ let g;
255
+ if (r.worldPersistence !== void 0) {
256
+ let e = r.worldPersistence, n = Object.getOwnPropertyDescriptor(e, "runDue"), i = Object.getOwnPropertyDescriptor(e, "close");
257
+ if (!n || !("value" in n) || typeof n.value != "function" || !i || !("value" in i) || typeof i.value != "function") throw new t({ detail: "World persistence requires explicit complete supervisor methods" });
258
+ let a = e.runDue.bind(e), o = e.close.bind(e), s = (e) => G.suspend(() => {
259
+ let n = e();
260
+ return G.isEffect(n) ? n : G.fail(new t({ detail: "World persistence supervisor requires an Effect" }));
261
+ });
262
+ g = Object.freeze({
263
+ runDue: () => s(a),
264
+ close: () => s(o)
265
+ });
266
+ }
267
+ r = {
268
+ ...r,
269
+ worlds: r.worlds === void 0 ? void 0 : ee(r.worlds),
270
+ address: p.ws,
271
+ webTransportAddress: p.wt,
272
+ webTransportCertificateHash: p.wtCertificateHash,
273
+ spectatorGroups: r.spectatorGroups,
274
+ worldPersistence: g,
275
+ ...u ? { geometry: u } : {}
276
+ }, te(r.secrets), T(r.strategies?.seatToken);
277
+ let _ = L(r.strategies?.snapshotBudget ?? Re, r.snapshotBudget ?? {});
278
+ for (let e of [
279
+ r.capacity,
280
+ r.heartbeatTtlMs,
281
+ r.heartbeatEveryMs,
282
+ r.seatTtlMs,
283
+ r.maxQueuedOperations ?? 128
284
+ ]) if (!Number.isSafeInteger(e) || e <= 0) throw new t({ detail: "Invalid host control budgets" });
285
+ if (r.heartbeatEveryMs >= r.heartbeatTtlMs) throw new t({ detail: "Host heartbeat cadence must be shorter than its routing TTL" });
286
+ let y = r.measuredCpu();
287
+ if (!Number.isFinite(y) || y < 0 || y > 1) throw new t({ detail: "Host CPU must be an actual normalized measurement" });
288
+ let b = r.ports?.directory ?? qe(e, {
289
+ epochNow: r.epochNow,
290
+ heartbeatTtlMs: r.heartbeatTtlMs,
291
+ strategies: r.strategies,
292
+ pools: r.pools
293
+ }), x = await Y(b.register({
294
+ address: r.address,
295
+ webTransportAddress: r.webTransportAddress,
296
+ webTransportCertificateHash: r.webTransportCertificateHash,
297
+ region: r.region,
298
+ capacity: r.capacity,
299
+ pool: r.pool,
300
+ clientCapacity: r.clientCapacity,
301
+ ready: r.startSuspended !== !0,
302
+ membership: r.membership,
303
+ load: {
304
+ rooms: 0,
305
+ clients: 0,
306
+ cpu: y
307
+ }
308
+ }));
309
+ if (x.pool !== r.pool || x.clientCapacity !== r.clientCapacity || x.region !== r.region || x.capacity !== r.capacity || x.address !== p.ws || x.webTransportAddress !== p.wt || x.webTransportCertificateHash !== p.wtCertificateHash || x.ready !== (r.startSuspended !== !0) || r.membership && (x.membership?.instanceId !== r.membership.instanceId || x.membership?.startedAt !== r.membership.startedAt)) {
310
+ let e = Q(b, x.id);
311
+ try {
312
+ await e();
313
+ } catch {
314
+ throw new Z(e);
315
+ }
316
+ throw new t({ detail: "Room directory provider did not preserve requested readiness admission" });
317
+ }
318
+ try {
319
+ return new $(x, n, e, r, b, _);
320
+ } catch (e) {
321
+ let t = Q(b, x.id);
322
+ try {
323
+ await t();
324
+ } catch {
325
+ throw new Z(t);
326
+ }
327
+ throw e;
328
+ }
329
+ }
330
+ spectatorGroup(e, n, r, i) {
331
+ if (!e.spectator) return;
332
+ if (!this.spectatorGroups) throw new t({ detail: "Room spectator policy requires a host-owned view-group resolver" });
333
+ let a = this.spectatorGroups(Object.freeze({
334
+ roomId: n,
335
+ tenantId: r,
336
+ epoch: i,
337
+ name: e.name
338
+ }));
339
+ if (!a || typeof a.view != "function" || typeof a.authorize != "function") throw new t({ detail: "Spectator resolver must return a synchronous complete group binding" });
340
+ return Object.freeze({
341
+ view: a.view.bind(a),
342
+ authorize: a.authorize.bind(a)
343
+ });
344
+ }
345
+ requireOwned(e, t) {
346
+ let n = this.owned.get(e);
347
+ if (!n || n.listing.tenantId !== t) throw new i({ roomId: e });
348
+ return n;
349
+ }
350
+ async authorize(e, t, r, i = "", a) {
351
+ let o = X(t);
352
+ if (this.options.pools && ae(this.options.pools, e.name, o.tenantId, this.host.region, this.host.pool), o.subjectId === null && e.auth !== "public" || await Y(Ze(t, e.guards, r, {
353
+ defaultDeny: !0,
354
+ procedure: `rooms.${e.name}`
355
+ }), a)) throw new n({ roomId: i });
356
+ return o;
357
+ }
358
+ operation(t, n = !1) {
359
+ return this.closed || (!this.activated || this.closing) && !n ? Promise.reject(new i({ roomId: "host" })) : this.queued >= this.maxQueued ? Promise.reject(new e({
360
+ budget: "hostControlOperations",
361
+ limit: this.maxQueued
362
+ })) : F(this, this.queued !== 0, () => {
363
+ this.queued++;
364
+ let e = this.lane.then(t);
365
+ return this.lane = e.then(() => {
366
+ this.queued--;
367
+ }, () => {
368
+ this.queued--;
369
+ }), e;
370
+ });
371
+ }
372
+ worldOperation(e) {
373
+ if (this.closed || !this.activated) return Promise.reject(new i({ roomId: "host" }));
374
+ let t = we(this, e);
375
+ if (t) return t;
376
+ let n = this.commandWindow;
377
+ return n ? F(this, this.queued !== 0, () => this.enqueueCommandWorld(n, e)) : this.operation(e);
378
+ }
379
+ enqueueCommandWorld(n, r) {
380
+ return this.commandWindow === n ? this.queued >= this.maxQueued ? Promise.reject(new e({
381
+ budget: "hostControlOperations",
382
+ limit: this.maxQueued
383
+ })) : (this.queued++, n.run(r).finally(() => {
384
+ this.queued--;
385
+ })) : Promise.reject(new t({ detail: "Host command World operation window has expired" }));
386
+ }
387
+ async executeAppCommand(e) {
388
+ if (this.commandWindow) throw new t({ detail: "Host application command windows cannot overlap" });
389
+ let n = Ce(this);
390
+ this.commandWindow = n;
391
+ try {
392
+ await Te(this, e, (e) => this.enqueueCommandWorld(n, e));
393
+ } finally {
394
+ try {
395
+ await n.close();
396
+ } finally {
397
+ this.commandWindow = null;
398
+ }
399
+ }
400
+ }
401
+ capturedWorldOperation(e, n) {
402
+ try {
403
+ let t = e();
404
+ return this.worldOperation(() => n(t));
405
+ } catch {
406
+ return Promise.reject(new t({ detail: "World Host command request could not be captured" }));
407
+ }
408
+ }
409
+ capturedOperation(e, n, r = !1) {
410
+ try {
411
+ let t = e();
412
+ return this.operation(() => n(t), r);
413
+ } catch {
414
+ return Promise.reject(new t({ detail: "Room host request could not be captured" }));
415
+ }
416
+ }
417
+ activate() {
418
+ return this.operation(async () => {
419
+ if (this.closing || this.closed) throw new i({ roomId: "host" });
420
+ if (this.activated) return;
421
+ let e = this.runtime.metrics();
422
+ if (await Y(this.directory.heartbeat(this.host.id, {
423
+ rooms: e.ownedRooms,
424
+ clients: e.sessions,
425
+ cpu: this.options.measuredCpu()
426
+ })), await Y(this.directory.setReady(this.host.id, !0)), this.closing) throw new i({ roomId: "host" });
427
+ this.activated = !0;
428
+ }, !0);
429
+ }
430
+ create(n, r, i, a = {}, o) {
431
+ return this.capturedOperation(() => ({
432
+ options: structuredClone(r),
433
+ subject: structuredClone(i),
434
+ listing: structuredClone(a),
435
+ attributes: o === void 0 ? void 0 : u(n, o)
436
+ }), async ({ options: r, subject: i, listing: a, attributes: o }) => {
437
+ if (await this.cleanupGeometry(), this.owned.size + this.uninstalledCreations.size + this.pendingGeometryCleanup.size >= this.options.capacity) throw new e({
438
+ budget: "retainedHostRooms",
439
+ limit: this.options.capacity
440
+ });
441
+ let s = this.catalog.get(n), c = await this.authorize(s, i, {
442
+ name: n,
443
+ options: r
444
+ });
445
+ if (this.options.worlds?.some((e) => e.instances.some((e) => e.room === n))) throw new t({ detail: "Instance Room creation requires an explicit group placement" });
446
+ if (await w(this.store, c), s.mode === "lockstep") return this.createLockstep(s, r, i, c, a);
447
+ if (!s.initialState) throw new t({ detail: "Room author must define initialState before creation is available" });
448
+ let l = q.decodeUnknownSync(s.options)(r), u = C(q.encodeSync(s.options)(l)), d = JSON.parse(u), f = await Y(this.directory.createOwnedRoom(this.host.id, {
449
+ ...c,
450
+ pool: this.host.pool,
451
+ name: n,
452
+ options: d,
453
+ maxClients: s.maxClients,
454
+ metadata: a.metadata ?? {},
455
+ private: a.private ?? !1,
456
+ staged: !0
457
+ }));
458
+ return await this.installCreatedRoom(f, s, r, u, a.private ?? !1), Y(this.reservationsFor(i).reserve(f.id, c, "player", o));
459
+ });
460
+ }
461
+ prepareMatchRoom(n, r, i, a) {
462
+ return this.capturedOperation(() => ({
463
+ options: structuredClone(r),
464
+ subject: structuredClone(i),
465
+ requestId: String(a)
466
+ }), async (r) => {
467
+ await this.cleanupGeometry();
468
+ let i = this.catalog.get(n);
469
+ if (i.world || this.options.worlds?.some((e) => e.zones.some((e) => e.room === n) || e.instances.some((e) => e.room === n))) throw new t({ detail: "World Rooms are placed by their World, not as match Rooms" });
470
+ if (i.mode === "lockstep" || !i.initialState) throw new t({ detail: "Match Rooms need a state-sync Room with initialState" });
471
+ let a = await this.authorize(i, r.subject, {
472
+ name: n,
473
+ options: r.options
474
+ });
475
+ await w(this.store, a);
476
+ let o = q.decodeUnknownSync(i.options)(r.options), s = C(q.encodeSync(i.options)(o)), c = await Y(this.directory.createOwnedRoom(this.host.id, {
477
+ ...a,
478
+ pool: this.host.pool,
479
+ name: n,
480
+ options: JSON.parse(s),
481
+ maxClients: i.maxClients,
482
+ metadata: {},
483
+ private: !0,
484
+ staged: !0,
485
+ creationKey: Ge(a.tenantId, n, r.requestId)
486
+ })), l = this.owned.get(c.id);
487
+ if (l) {
488
+ if (l.listing.tenantId !== a.tenantId || l.listing.epoch !== c.epoch || l.descriptor !== i || l.optionFingerprint !== s) throw new t({ detail: "Match Room retry changed its Room" });
489
+ return (!l.published || this.runtime.hasPendingCheckpoint(c.id)) && await this.runtime.persist(c.id), l.published = !0, c;
490
+ }
491
+ let u = await Y(this.directory.observeOwnership(c.id, a.tenantId));
492
+ if (u?.state !== "creating" || u.hostId !== this.host.id || u.epoch !== c.epoch) throw new t({ detail: "Match Room retry cannot reset a published Room" });
493
+ if (this.owned.size + this.uninstalledCreations.size + this.pendingGeometryCleanup.size >= this.options.capacity) throw new e({
494
+ budget: "retainedHostRooms",
495
+ limit: this.options.capacity
496
+ });
497
+ try {
498
+ return await this.installCreatedRoom(c, i, r.options, s, !0), c;
499
+ } catch (e) {
500
+ if (!this.owned.has(c.id) && !this.pendingGeometryCleanup.has(c.id)) {
501
+ this.pendingGeometryCleanup.set(c.id, {
502
+ listing: c,
503
+ geometry: void 0,
504
+ abandonCreation: !0
505
+ });
506
+ try {
507
+ await this.cleanupGeometry();
508
+ } catch (t) {
509
+ throw AggregateError([e, t], "Match Room creation cleanup remains retained");
510
+ }
511
+ }
512
+ throw e;
513
+ }
514
+ });
515
+ }
516
+ prepareWorldRoom(n, r, i, a, o, s = 1, c) {
517
+ return this.capturedWorldOperation(() => ({
518
+ options: structuredClone(r),
519
+ subject: structuredClone(i),
520
+ creationKey: a,
521
+ creationGeneration: s,
522
+ worldCell: o === void 0 ? void 0 : h(o, 4096),
523
+ worldInstance: c === void 0 ? void 0 : h(c, 4096)
524
+ }), async (r) => {
525
+ await this.cleanupGeometry();
526
+ let i = this.catalog.get(n);
527
+ if (!i.world || !i.initialState || !this.options.worlds?.some((e) => e.zones.some((e) => e.room === n) || e.instances.some((e) => e.room === n))) throw new t({ detail: "World Room preparation requires an actual configured state-sync World Room" });
528
+ let a = r.worldCell, o = r.worldInstance, s = {
529
+ name: n,
530
+ options: r.options,
531
+ ...a ? {
532
+ worldCell: a,
533
+ creationGeneration: r.creationGeneration
534
+ } : {},
535
+ ...o ? {
536
+ worldInstance: o,
537
+ creationGeneration: r.creationGeneration,
538
+ operation: r.creationGeneration > 1 ? "reset" : "prepare"
539
+ } : {}
540
+ }, c = await this.authorize(i, r.subject, s);
541
+ if (await w(this.store, c), !Number.isSafeInteger(r.creationGeneration) || r.creationGeneration < 1 || r.creationGeneration > 2147483647 || !a && !o && r.creationGeneration !== 1) throw new t({ detail: "World creation generation requires an explicit bounded placement" });
542
+ if (o && (a || Object.keys(o).sort().join(",") !== "groupId,instance,tenantId,worldId" || o.tenantId !== c.tenantId || j(o, r.creationGeneration) !== r.creationKey || !this.options.worlds.some((e) => e.name === o.worldId && e.instances.some((e) => e.id === o.instance && e.room === n)) || this.options.worlds.some((e) => e.zones.some((e) => e.room === n)))) throw new t({ detail: "World instance creation differs from its actual group and Room authority" });
543
+ if (!o && this.options.worlds.some((e) => e.instances.some((e) => e.room === n))) throw new t({ detail: "Instance Room preparation requires an explicit group placement" });
544
+ o && r.creationGeneration > 1 && await ye(this.store, this.options.worlds.find((e) => e.name === o.worldId), o, r.creationGeneration);
545
+ let l = o ? be(this.store, {
546
+ worlds: this.options.worlds,
547
+ epochNow: this.options.epochNow,
548
+ maxManagedGroups: 65536,
549
+ authorize: (e) => G.tryPromise({
550
+ try: async () => {
551
+ await this.authorize(i, r.subject, {
552
+ ...s,
553
+ operation: e
554
+ }), await w(this.store, c);
555
+ },
556
+ catch: () => new t({ detail: "Instance group placement authorization is no longer current" })
557
+ })
558
+ }) : void 0, u = a && this.options.worlds.find((e) => e.name === a.worldId);
559
+ if (a && (Object.keys(a).sort().join(",") !== "at,layer,worldId,zoneId" || !u || !Number.isSafeInteger(a.layer) || a.layer < 1 || !u.zones.some((e) => e.id === a.zoneId && e.room === n && (e.layering || a.layer === 1)) || Se(c.tenantId, u, a, r.creationGeneration) !== r.creationKey)) throw new t({ detail: "World creation placement does not match its admitted cell digest" });
560
+ a && u && r.creationGeneration > 1 && await xe(this.store, c.tenantId, u, a, r.creationGeneration);
561
+ let d = a ? D(this.store, {
562
+ worlds: this.options.worlds,
563
+ epochNow: this.options.epochNow,
564
+ maxListedCells: 1,
565
+ authorize: () => G.tryPromise({
566
+ try: async () => {
567
+ await this.authorize(i, r.subject, s), await w(this.store, c);
568
+ },
569
+ catch: () => new t({ detail: "World placement authorization is no longer current" })
570
+ })
571
+ }) : void 0, f = q.decodeUnknownSync(i.options)(r.options), p = C(q.encodeSync(i.options)(f)), m = await Y(this.directory.createOwnedRoom(this.host.id, {
572
+ ...c,
573
+ pool: this.host.pool,
574
+ name: n,
575
+ options: JSON.parse(p),
576
+ maxClients: i.maxClients,
577
+ metadata: {},
578
+ private: !0,
579
+ staged: !0,
580
+ creationKey: r.creationKey
581
+ })), h = this.owned.get(m.id);
582
+ if (h) {
583
+ if (h.listing.tenantId !== c.tenantId || h.listing.epoch !== m.epoch || h.descriptor !== i || h.optionFingerprint !== p) throw new t({ detail: "World creation retry changed its actual actor" });
584
+ return (!h.published || this.runtime.hasPendingCheckpoint(m.id)) && await this.runtime.persist(m.id), d && a && await Y(d.publish({
585
+ tenantId: c.tenantId,
586
+ ...a,
587
+ roomId: m.id,
588
+ hostId: this.host.id,
589
+ epoch: m.epoch
590
+ })), l && o && await Y(l.publish({
591
+ ...o,
592
+ generation: r.creationGeneration,
593
+ roomId: m.id,
594
+ hostId: this.host.id,
595
+ epoch: m.epoch
596
+ })), h.published = !0, m;
597
+ }
598
+ let g = await Y(this.directory.observeOwnership(m.id, c.tenantId));
599
+ if (g?.state !== "creating" || g.hostId !== this.host.id || g.epoch !== m.epoch) throw new t({ detail: "World creation cannot reset a published actor; actual recovery is required" });
600
+ if (this.owned.size + this.uninstalledCreations.size + this.pendingGeometryCleanup.size >= this.options.capacity) throw new e({
601
+ budget: "retainedHostRooms",
602
+ limit: this.options.capacity
603
+ });
604
+ l && o && await Y((r.creationGeneration > 1 ? l.reset : l.prepare)({
605
+ ...o,
606
+ generation: r.creationGeneration,
607
+ roomId: m.id,
608
+ hostId: this.host.id,
609
+ epoch: m.epoch
610
+ }));
611
+ try {
612
+ return d && a && await Y(d.prepare({
613
+ tenantId: c.tenantId,
614
+ ...a,
615
+ roomId: m.id,
616
+ hostId: this.host.id,
617
+ epoch: m.epoch
618
+ })), await this.installCreatedRoom(m, i, r.options, p, !0), l && o && await Y(l.publish({
619
+ ...o,
620
+ generation: r.creationGeneration,
621
+ roomId: m.id,
622
+ hostId: this.host.id,
623
+ epoch: m.epoch
624
+ })), d && a && await Y(d.publish({
625
+ tenantId: c.tenantId,
626
+ ...a,
627
+ roomId: m.id,
628
+ hostId: this.host.id,
629
+ epoch: m.epoch
630
+ })), m;
631
+ } catch (e) {
632
+ if (!this.owned.has(m.id) && !this.pendingGeometryCleanup.has(m.id)) {
633
+ this.pendingGeometryCleanup.set(m.id, {
634
+ listing: m,
635
+ geometry: void 0,
636
+ abandonCreation: !0
637
+ });
638
+ try {
639
+ await this.cleanupGeometry();
640
+ } catch (t) {
641
+ throw AggregateError([e, t], "World placement creation cleanup remains retained");
642
+ }
643
+ }
644
+ throw e;
645
+ }
646
+ });
647
+ }
648
+ abandonWorldInstance(e, n, r = 1) {
649
+ return this.capturedWorldOperation(() => ({
650
+ identity: h(e, 4096),
651
+ subject: structuredClone(n),
652
+ generation: r
653
+ }), async (e) => {
654
+ let n = e.identity, r = j(n, e.generation);
655
+ if (Object.keys(n).sort().join(",") !== "groupId,instance,tenantId,worldId") throw new t({ detail: "Invalid instance abandonment identity" });
656
+ let i = this.options.worlds?.find((e) => e.name === n.worldId), a = i?.instances.find((e) => e.id === n.instance);
657
+ if (!i || !a) throw new t({ detail: "Instance abandonment requires its configured World" });
658
+ let o = this.catalog.get(a.room), s = await this.authorize(o, e.subject, {
659
+ worldInstance: n,
660
+ creationGeneration: e.generation,
661
+ operation: "abandon"
662
+ });
663
+ if (s.tenantId !== n.tenantId) throw new t({ detail: "Instance abandonment crossed its tenant" });
664
+ await w(this.store, s);
665
+ let c = await this.store.query({
666
+ table: b,
667
+ predicate: H(U("tenantId", s.tenantId), U("requestKey", r)),
668
+ order: [],
669
+ take: 2,
670
+ skip: void 0,
671
+ projection: ["roomId"]
672
+ });
673
+ if (c.length !== 1 || typeof c[0].roomId != "string") throw new t({ detail: "Instance abandonment requires its original creation receipt" });
674
+ let l = c[0].roomId, u = await this.store.query({
675
+ table: y,
676
+ predicate: H(U("id", l), U("tenantId", s.tenantId)),
677
+ order: [],
678
+ take: 2,
679
+ skip: void 0,
680
+ projection: ["name"]
681
+ });
682
+ if (u.length !== 1 || u[0].name !== a.room) throw new t({ detail: "Instance creation receipt names another declared Room" });
683
+ let d = () => {
684
+ if (this.owned.has(l) || this.uninstalledCreations.has(l)) throw new t({ detail: "Instance abandonment cannot replace a retained actor" });
685
+ };
686
+ d();
687
+ let f = await Y(this.directory.observeOwnership(l, s.tenantId));
688
+ if (!f || f.hostId !== this.host.id || f.epoch !== 1 || !["creating", "disposed"].includes(f.state)) throw new t({ detail: "Instance abandonment lost original unpublished ownership" });
689
+ f.state === "creating" && await Y(this.directory.abandonCreation(this.host.id, l, s.tenantId)), await M(this.store, this.options.worlds, {
690
+ tenantId: s.tenantId,
691
+ roomId: l,
692
+ hostId: this.host.id,
693
+ epoch: 1
694
+ }, this.options.epochNow, d), await this.cleanupGeometry();
695
+ });
696
+ }
697
+ async installCreatedRoom(e, n, r, a, o) {
698
+ if (n.mode === "lockstep") throw new t({ detail: "Lockstep rooms install through lockstep admission" });
699
+ let s = !1, c;
700
+ try {
701
+ if (c = await Y(z(this.geometry, {
702
+ roomId: e.id,
703
+ tenantId: e.tenantId,
704
+ hostId: this.host.id,
705
+ epoch: e.epoch,
706
+ name: n.name
707
+ })), c) {
708
+ let t = await Y(this.directory.observeOwnership(e.id, e.tenantId));
709
+ if (V(t, {
710
+ roomId: e.id,
711
+ tenantId: e.tenantId,
712
+ hostId: this.host.id,
713
+ epoch: e.epoch
714
+ }) || t?.state !== "creating" && t?.state !== "live") throw new i({ roomId: e.id });
715
+ }
716
+ return this.runtime.create(e.id, e.tenantId, n, r, e.epoch, this.reservationsFor().admission, {
717
+ epochNow: this.options.epochNow,
718
+ secrets: this.options.secrets,
719
+ seatToken: this.seatToken,
720
+ authorizeWorldTarget: this.authorizeWorldTarget,
721
+ ...this.options.resolveWorldPlayer ? { authorizeWorldPlayer: this.authorizeWorldPlayer } : {},
722
+ ...c ? { geometry: c } : {},
723
+ spectatorGroup: this.spectatorGroup(n, e.id, e.tenantId, e.epoch),
724
+ replayRecording: this.replayRecordings?.(Object.freeze({
725
+ roomId: e.id,
726
+ tenantId: e.tenantId,
727
+ name: n.name,
728
+ epoch: e.epoch
729
+ }))
730
+ }), s = !0, this.owned.set(e.id, {
731
+ listing: e,
732
+ descriptor: n,
733
+ optionFingerprint: a,
734
+ private: o,
735
+ published: !1,
736
+ ...c ? { geometry: c } : {}
737
+ }), await this.runtime.persist(e.id), this.requireOwned(e.id, e.tenantId).published = !0, e;
738
+ } catch (t) {
739
+ if (!s) {
740
+ this.pendingGeometryCleanup.set(e.id, {
741
+ listing: e,
742
+ geometry: c,
743
+ abandonCreation: !0
744
+ });
745
+ try {
746
+ await this.cleanupGeometry();
747
+ } catch (e) {
748
+ throw AggregateError([t, e], "Room creation and compensation failed");
749
+ }
750
+ }
751
+ throw t;
752
+ }
753
+ }
754
+ kickSubject(e, n, r, a) {
755
+ return this.capturedOperation(() => ({
756
+ roomId: String(e),
757
+ tenantId: String(n),
758
+ subjectId: String(r),
759
+ reason: String(a)
760
+ }), async (e) => {
761
+ if (!e.roomId || !e.tenantId || !e.subjectId || e.reason.length > 200) throw new t({ detail: "Invalid Room kick request" });
762
+ if (!this.requireOwned(e.roomId, e.tenantId).published) throw new i({ roomId: e.roomId });
763
+ return { kicked: await this.runtime.kickSubject(e.roomId, e.tenantId, e.subjectId, e.reason) };
764
+ });
765
+ }
766
+ closeSessions(e, n, r) {
767
+ return this.capturedOperation(() => ({
768
+ roomId: String(e),
769
+ tenantId: String(n),
770
+ reason: String(r)
771
+ }), async (e) => {
772
+ if (!e.roomId || !e.tenantId || e.reason.length > 200) throw new t({ detail: "Invalid Room close request" });
773
+ if (!this.requireOwned(e.roomId, e.tenantId).published) throw new i({ roomId: e.roomId });
774
+ return { kicked: await this.runtime.kickSubject(e.roomId, e.tenantId, null, e.reason) };
775
+ });
776
+ }
777
+ reloadGeometry(e, n, r) {
778
+ return this.capturedOperation(() => ({
779
+ roomId: f(e),
780
+ request: p(n),
781
+ subject: structuredClone(r)
782
+ }), async (e) => {
783
+ let n = X(e.subject), r = this.requireOwned(e.roomId, n.tenantId), a = r.geometry, o = this.geometry?.reload;
784
+ if (!a || !o || !r.published || r.descriptor.mode === "lockstep") throw new t({ detail: "Room has no admitted administrative geometry reload source" });
785
+ let s = async () => {
786
+ await w(this.store, n), await Y(o.authorize(e.subject, a, e.request));
787
+ let t = await Y(this.directory.observeOwnership(e.roomId, n.tenantId));
788
+ if (V(t, {
789
+ roomId: e.roomId,
790
+ tenantId: n.tenantId,
791
+ hostId: this.host.id,
792
+ epoch: r.listing.epoch
793
+ }) || t?.state !== "live") throw r.published = !1, await this.runtime.withdrawOwnership(e.roomId, n.tenantId, r.listing.epoch), new i({ roomId: e.roomId });
794
+ };
795
+ if (this.geometryRollbacks.get(e.roomId)?.admitted === !1) throw new t({ detail: "Incomplete geometry rollback must resolve before reload" });
796
+ await s(), await this.releaseGeometryRollback(e.roomId);
797
+ let c = C([
798
+ n.tenantId,
799
+ n.subjectId,
800
+ e.subject.type
801
+ ]), l = this.geometryReloads.get(e.roomId), u = l !== void 0 && JSON.stringify(l.request) === JSON.stringify(e.request) && l.subjectKey === c;
802
+ if (l && !l.admitted && !u) throw new t({ detail: "Incomplete geometry reload requires its exact owner request and Subject" });
803
+ if (l?.releasePending && await this.releaseGeometryReload(e.roomId), u && l?.admitted) return;
804
+ let d = u ? l : {
805
+ resource: a,
806
+ request: e.request,
807
+ subjectKey: c,
808
+ token: null,
809
+ admitted: !1,
810
+ releasePending: !1
811
+ };
812
+ this.geometryReloads.set(e.roomId, d);
813
+ let f = null;
814
+ try {
815
+ d.token ||= (await this.runtime.quiesceGeometry(e.roomId), d.releasePending = !0, await Y(o.prepare(a, d.request))), await s(), d.releasePending = !0, await Y(o.resume(a, d.request, d.token)), await s(), await this.runtime.activateGeometryVersion(e.roomId, d.token), d.admitted = !0;
816
+ } catch (e) {
817
+ f = e;
818
+ }
819
+ try {
820
+ await this.releaseGeometryReload(e.roomId);
821
+ } catch {
822
+ throw new t({ detail: "Geometry reload coordination cleanup remains retained; repeat its exact request" });
823
+ }
824
+ if (f) throw f;
825
+ });
826
+ }
827
+ async releaseGeometryReload(e) {
828
+ let n = this.geometryReloads.get(e), r = this.geometry?.reload;
829
+ if (n?.releasePending) {
830
+ if (!r) throw new t({ detail: "Actual geometry reload cleanup source is missing" });
831
+ await Y(r.release(n.resource, n.request)), n.releasePending = !1;
832
+ }
833
+ }
834
+ rollbackGeometry(e, n, r) {
835
+ return this.capturedOperation(() => ({
836
+ roomId: f(e),
837
+ request: m(n),
838
+ subject: structuredClone(r)
839
+ }), async (e) => {
840
+ let n = X(e.subject), r = this.requireOwned(e.roomId, n.tenantId), a = r.geometry, o = this.geometry?.rollback;
841
+ if (!a || !o || !r.published || r.descriptor.mode === "lockstep") throw new t({ detail: "Room has no admitted administrative geometry rollback source" });
842
+ let s = async () => {
843
+ await w(this.store, n), e.request.target !== null && await w(this.store, {
844
+ tenantId: n.tenantId,
845
+ subjectId: e.request.target.id
846
+ }), await Y(o.authorize(e.subject, a, e.request));
847
+ let t = await Y(this.directory.observeOwnership(e.roomId, n.tenantId));
848
+ if (V(t, {
849
+ roomId: e.roomId,
850
+ tenantId: n.tenantId,
851
+ hostId: this.host.id,
852
+ epoch: r.listing.epoch
853
+ }) || t?.state !== "live") throw r.published = !1, await this.runtime.withdrawOwnership(e.roomId, n.tenantId, r.listing.epoch), new i({ roomId: e.roomId });
854
+ };
855
+ if (this.geometryReloads.get(e.roomId)?.admitted === !1) throw new t({ detail: "Incomplete geometry reload must resolve before rollback" });
856
+ await s(), await this.releaseGeometryReload(e.roomId);
857
+ let c = C([
858
+ n.tenantId,
859
+ n.subjectId,
860
+ e.subject.type
861
+ ]), l = this.geometryRollbacks.get(e.roomId), u = l !== void 0 && JSON.stringify(l.request) === JSON.stringify(e.request) && l.subjectKey === c;
862
+ if (l && !l.admitted && !u) throw new t({ detail: "Incomplete geometry rollback requires its exact owner request and Subject" });
863
+ if (l?.releasePending && l.token && await this.releaseGeometryRollback(e.roomId), u && l?.admitted) return;
864
+ let d = u ? l : {
865
+ resource: a,
866
+ request: e.request,
867
+ subjectKey: c,
868
+ token: null,
869
+ admitted: !1,
870
+ releasePending: !1
871
+ };
872
+ this.geometryRollbacks.set(e.roomId, d);
873
+ let f = null;
874
+ try {
875
+ d.token ||= (await this.runtime.quiesceGeometry(e.roomId), d.releasePending = !0, await Y(o.prepare(e.subject, a, d.request))), await s(), d.releasePending = !0, await Y(o.resume(e.subject, a, d.request, d.token)), await s(), await this.runtime.activateGeometryChange(e.roomId, d.token), d.admitted = !0;
876
+ } catch (e) {
877
+ f = e;
878
+ }
879
+ try {
880
+ await this.releaseGeometryRollback(e.roomId);
881
+ } catch {
882
+ throw new t({ detail: "Geometry rollback coordination cleanup remains retained; repeat its exact request" });
883
+ }
884
+ if (f) throw f;
885
+ });
886
+ }
887
+ async releaseGeometryRollback(e) {
888
+ let n = this.geometryRollbacks.get(e), r = this.geometry?.rollback;
889
+ if (n?.releasePending) {
890
+ if (!r) throw new t({ detail: "Actual geometry rollback cleanup source is missing" });
891
+ await Y(r.release(n.resource, n.request)), n.releasePending = !1;
892
+ }
893
+ }
894
+ lockstepServices(e, n) {
895
+ let r = this.options.ports?.erasure;
896
+ if (!r) throw new t({ detail: "Lockstep ownership requires complete coordinated erasure" });
897
+ let i = Object.freeze({
898
+ hostId: this.host.id,
899
+ roomId: n.id,
900
+ tenantId: n.tenantId,
901
+ epoch: n.epoch
902
+ }), a = {
903
+ roomId: n.id,
904
+ tenantId: n.tenantId,
905
+ epoch: n.epoch
906
+ }, o = (e) => e.roomId === i.roomId && e.tenantId === i.tenantId && e.epoch === i.epoch ? G.void : G.fail(new t({ detail: "Lockstep capability escaped the current controller Room scope" })), s = {
907
+ hostId: this.host.id,
908
+ epochNow: this.options.epochNow,
909
+ erasure: r,
910
+ authorize: o
911
+ }, l = this.options.ports?.lockstepAdmission?.(e, i) ?? Ie(this.store, e, s), u = this.options.ports?.lockstepJournal?.(e, i) ?? Fe(this.store, e.simulation, {
912
+ ...s,
913
+ maxPlayers: e.maxClients
914
+ });
915
+ return {
916
+ journalScope: a,
917
+ terminal: this.options.ports?.lockstepTerminal?.(e, i) ?? Le(this.store, e, {
918
+ hostId: this.host.id,
919
+ epochNow: this.options.epochNow,
920
+ authorize: o
921
+ }),
922
+ dependencies: {
923
+ maxCatchUpTicks: c(e, E(this.options.pools, this.options.pool)),
924
+ hostId: this.host.id,
925
+ admission: l,
926
+ journal: u,
927
+ runEffect: G.runPromise,
928
+ clock: this.options.clock,
929
+ seats: this.reservationsFor().admission,
930
+ sessionOptions: {
931
+ epochNow: this.options.epochNow,
932
+ secrets: this.options.secrets,
933
+ seatToken: this.seatToken
934
+ },
935
+ transport: this.options.lockstepTransport
936
+ }
937
+ };
938
+ }
939
+ async installLockstepSuccessor(e) {
940
+ let r = e.listing, i = this.owned.get(r.id);
941
+ if (i) {
942
+ if (i.descriptor.mode !== "lockstep" || i.listing.tenantId !== r.tenantId || i.listing.epoch !== r.epoch || !this.runtime.retains(r.id)) throw new n({ roomId: r.id });
943
+ return;
944
+ }
945
+ let a = this.catalog.get(r.name);
946
+ if (a.mode !== "lockstep" || r.maxClients !== a.maxClients) throw new t({ detail: "Recovered Lockstep declaration or capacity changed" });
947
+ let { journalScope: o, terminal: s, dependencies: c } = this.lockstepServices(a, r), u = await B.restore(a, o, e.lockstep, c);
948
+ try {
949
+ let t = Buffer.from(l(a.simulation).encode(e.lockstep.options)).toString("base64url");
950
+ this.runtime.addLockstep(u, {
951
+ terminal: s,
952
+ runEffect: G.runPromise
953
+ }), this.owned.set(r.id, {
954
+ listing: r,
955
+ descriptor: a,
956
+ optionFingerprint: t,
957
+ private: e.private,
958
+ published: !1
959
+ });
960
+ } catch (e) {
961
+ try {
962
+ await u.disposeAsync(!0);
963
+ } catch (t) {
964
+ throw AggregateError([e, t], "Lockstep successor installation and withdrawal failed");
965
+ }
966
+ throw e;
967
+ }
968
+ }
969
+ async createLockstep(e, n, r, i, a) {
970
+ if (i.subjectId === null || !this.options.ports?.erasure) throw new t({ detail: "Lockstep creation requires Subject identity and complete coordinated erasure" });
971
+ let o = l(e.simulation), s = o.capture(n), c = Buffer.from(o.encode(s)).toString("base64url"), u = We(this.lockstepSeed), d = await Y(this.directory.createOwnedRoom(this.host.id, {
972
+ ...i,
973
+ pool: this.host.pool,
974
+ name: e.name,
975
+ options: null,
976
+ maxClients: e.maxClients,
977
+ metadata: a.metadata ?? {},
978
+ private: a.private ?? !1,
979
+ staged: !0
980
+ })), { journalScope: f, terminal: p, dependencies: m } = this.lockstepServices(e, d), h = null, g = !1;
981
+ try {
982
+ return h = await B.create(e, {
983
+ ...f,
984
+ requestId: `room:${d.id}:creation`,
985
+ creatorSubjectId: i.subjectId,
986
+ seed: u,
987
+ options: s
988
+ }, m), this.runtime.addLockstep(h, {
989
+ terminal: p,
990
+ runEffect: G.runPromise
991
+ }), g = !0, this.owned.set(d.id, {
992
+ listing: d,
993
+ descriptor: e,
994
+ optionFingerprint: c,
995
+ private: a.private ?? !1,
996
+ published: !1
997
+ }), await this.runtime.publishLockstep(d.id), this.requireOwned(d.id, i.tenantId).published = !0, await Y(this.reservationsFor(r).reserve(d.id, i));
998
+ } catch (e) {
999
+ if (!g) {
1000
+ this.uninstalledCreations.set(d.id, {
1001
+ listing: d,
1002
+ owner: h
1003
+ });
1004
+ try {
1005
+ await this.cleanupUninstalledCreations();
1006
+ } catch (t) {
1007
+ throw AggregateError([e, t], "Lockstep creation and retained cleanup failed");
1008
+ }
1009
+ }
1010
+ throw e;
1011
+ }
1012
+ }
1013
+ async cleanupUninstalledCreations() {
1014
+ let e = [];
1015
+ for (let [t, n] of this.uninstalledCreations) try {
1016
+ n.owner && await n.owner.disposeAsync();
1017
+ let e = await Y(this.directory.observeOwnership(t, n.listing.tenantId));
1018
+ !V(e, {
1019
+ roomId: t,
1020
+ tenantId: n.listing.tenantId,
1021
+ hostId: this.host.id,
1022
+ epoch: n.listing.epoch
1023
+ }) && e?.state !== "disposed" && await Y(this.directory.abandonCreation(this.host.id, t, n.listing.tenantId)), this.uninstalledCreations.delete(t);
1024
+ } catch (t) {
1025
+ e.push(t);
1026
+ }
1027
+ if (e.length) throw AggregateError(e, "Uninstalled Lockstep creation cleanup remains retained");
1028
+ }
1029
+ async cleanupGeometry() {
1030
+ let e = [];
1031
+ for (let [n, r] of this.pendingGeometryCleanup) try {
1032
+ if (await r.geometry?.close(), r.abandonCreation) {
1033
+ let e = await Y(this.directory.observeOwnership(n, r.listing.tenantId));
1034
+ if (!V(e, {
1035
+ roomId: n,
1036
+ tenantId: r.listing.tenantId,
1037
+ hostId: this.host.id,
1038
+ epoch: r.listing.epoch
1039
+ }) && e?.state !== "disposed" && await Y(this.directory.abandonCreation(this.host.id, n, r.listing.tenantId)), this.geometry?.cleanupCreation) {
1040
+ let e = this.geometry.cleanupCreation(Object.freeze({
1041
+ roomId: n,
1042
+ tenantId: r.listing.tenantId,
1043
+ hostId: this.host.id,
1044
+ epoch: r.listing.epoch,
1045
+ name: r.listing.name
1046
+ }));
1047
+ if (!G.isEffect(e) || await Y(e) !== void 0) throw new t({ detail: "World creating-Room routing cleanup must confirm its actual Effect" });
1048
+ }
1049
+ if (this.options.worlds?.length && this.catalog.get(r.listing.name).world) {
1050
+ if (this.options.worlds.some((e) => e.instances.some((e) => e.room === r.listing.name))) {
1051
+ await M(this.store, this.options.worlds, {
1052
+ tenantId: r.listing.tenantId,
1053
+ roomId: n,
1054
+ hostId: this.host.id,
1055
+ epoch: r.listing.epoch
1056
+ }, this.options.epochNow, () => {
1057
+ if (this.pendingGeometryCleanup.get(n) !== r || this.owned.has(n)) throw new t({ detail: "Failed instance cleanup lost retained creation authority" });
1058
+ }), this.pendingGeometryCleanup.delete(n);
1059
+ continue;
1060
+ }
1061
+ await Y(D(this.store, {
1062
+ worlds: this.options.worlds,
1063
+ epochNow: this.options.epochNow,
1064
+ maxListedCells: 1,
1065
+ authorize: (e, i) => G.sync(() => {
1066
+ if (this.pendingGeometryCleanup.get(n) !== r || i.tenantId !== r.listing.tenantId) throw new t({ detail: "World creation cleanup lost its retained Host owner" });
1067
+ })
1068
+ }).synchronizeRoom({
1069
+ tenantId: r.listing.tenantId,
1070
+ roomId: n,
1071
+ hostId: this.host.id,
1072
+ epoch: r.listing.epoch
1073
+ }));
1074
+ }
1075
+ }
1076
+ this.pendingGeometryCleanup.delete(n);
1077
+ } catch (t) {
1078
+ e.push(t);
1079
+ }
1080
+ if (e.length) throw AggregateError(e, "Exact uninstalled geometry cleanup remains retained");
1081
+ }
1082
+ admitLockstep(e, t, n, r) {
1083
+ return this.operation(async () => {
1084
+ let a = this.requireOwned(e, t);
1085
+ if (!a.published || a.descriptor.mode !== "lockstep") throw new i({ roomId: e });
1086
+ return this.runtime.admitLockstep(e, n, r);
1087
+ });
1088
+ }
1089
+ startLockstep(e, t) {
1090
+ return this.operation(async () => {
1091
+ let n = this.requireOwned(e, t);
1092
+ if (!n.published || n.descriptor.mode !== "lockstep") throw new i({ roomId: e });
1093
+ return this.runtime.startLockstep(e);
1094
+ });
1095
+ }
1096
+ captureWorldTransitionSnapshot(e, n, r, a, o) {
1097
+ return this.capturedWorldOperation(() => h(a, 4096), async (a) => {
1098
+ let s = this.requireOwned(e, n), c = this.options.worldEntities?.transitions;
1099
+ if (!s.published || s.listing.epoch !== r || s.descriptor.mode === "lockstep" || !s.descriptor.world || !c?.retainActorSnapshot || a.tenantId !== n || a.roomId !== e) throw new i({ roomId: e });
1100
+ let l = async () => {
1101
+ let t = await Y(this.directory.observeOwnership(e, n));
1102
+ if (!t || t.hostId !== this.host.id || t.epoch !== r || t.state !== "live") throw new i({ roomId: e });
1103
+ };
1104
+ await l();
1105
+ let u = c.observe(a);
1106
+ if (!G.isEffect(u)) throw new t({ detail: "World transfer capture requires actual transition observation" });
1107
+ let d = await Y(u);
1108
+ if (!d || d.origin.tenantId !== n || d.origin.roomId !== e || d.origin.requestId !== a.requestId || d.source.roomId !== e) throw new t({ detail: "World transfer capture lost its source request" });
1109
+ let f = d.actorSnapshot, p = d.actorSnapshotRevision;
1110
+ if (!f) {
1111
+ if (d.phase !== "reserving" || d.source.epoch !== r) throw new t({ detail: "World transfer capture requires current reserving source epoch" });
1112
+ let i = await this.runtime.captureWorldEntity(e, n, r, d.entityId, o);
1113
+ if (C(i.data) !== C(d.sourceData)) throw new t({ detail: "World persistence projection changed since transition resolution" });
1114
+ let a = A(s.descriptor.state, {
1115
+ maxBytes: o,
1116
+ maxFieldId: Math.min(4096, o * 7),
1117
+ maxCollectionLength: Math.min(16384, o)
1118
+ }), c = q.decodeUnknownSync(a.schema)(i.entity), l = a.full(c);
1119
+ if (K.isFailure(l)) throw l.failure;
1120
+ f = O({
1121
+ schemaHash: a.schemaHash,
1122
+ bytes: Array.from(l.success),
1123
+ entity: i.entity
1124
+ }, o), p = d.revision;
1125
+ }
1126
+ f = O(f, o);
1127
+ let m = c.retainActorSnapshot({
1128
+ origin: a,
1129
+ expectedRevision: p,
1130
+ snapshot: f
1131
+ });
1132
+ if (!G.isEffect(m)) throw new t({ detail: "World transfer capture requires actual durable snapshot retention" });
1133
+ let h = await Y(m);
1134
+ return await l(), h;
1135
+ });
1136
+ }
1137
+ decodeWorldActorSnapshot(e, n, r) {
1138
+ if (e.mode === "lockstep") throw new t({ detail: "World transfer payload requires state-sync schema" });
1139
+ let i = O(n, r), a = A(e.state, {
1140
+ maxBytes: r,
1141
+ maxFieldId: Math.min(4096, r * 7),
1142
+ maxCollectionLength: Math.min(16384, r)
1143
+ });
1144
+ if (i.schemaHash !== a.schemaHash) throw new t({ detail: "World target entity schema differs from the retained snapshot" });
1145
+ let o = q.decodeUnknownSync(a.schema)(i.entity), s = a.full(o);
1146
+ if (K.isFailure(s)) throw s.failure;
1147
+ if (s.success.length !== i.bytes.length || s.success.some((e, t) => e !== i.bytes[t])) throw new t({ detail: "World target snapshot bytes contradict its captured source entity" });
1148
+ let c = a.decodeFull(Uint8Array.from(i.bytes));
1149
+ if (K.isFailure(c)) throw c.failure;
1150
+ return h(JSON.parse(JSON.stringify(c.success)), r);
1151
+ }
1152
+ worldTransitionPayload(e, n, r, i) {
1153
+ if (!n.actorSnapshot) throw new t({ detail: "World transfer requires its retained snapshot" });
1154
+ return {
1155
+ epoch: r,
1156
+ requestId: `${n.id}:enter`,
1157
+ entity: this.decodeWorldActorSnapshot(e, n.actorFinalSnapshot?.snapshot ?? n.actorSnapshot, i),
1158
+ location: n.source
1159
+ };
1160
+ }
1161
+ applyWorldSourceTransition(e, t, n, r, i, a, o, s) {
1162
+ return this.capturedWorldOperation(() => h({
1163
+ origin: r,
1164
+ operation: i
1165
+ }, 4096), async (r) => this.applyWorldSourceTransitionOwned(e, t, n, r, a, o, s));
1166
+ }
1167
+ async applyWorldSourceTransitionOwned(e, n, r, a, o, s, c, l, u, d) {
1168
+ let f = this.requireOwned(e, n), p = this.options.worldEntities?.transitions;
1169
+ if ((l === void 0 ? !f.published : f.published || !this.runtime.isPublicationHeld(e) || a.operation !== "rollback" || r !== l + 1) || f.listing.epoch !== r || f.descriptor.mode === "lockstep" || !f.descriptor.world || !p?.admitActorSource || a.origin.tenantId !== n || a.origin.roomId !== e || !["detach", "rollback"].includes(a.operation)) throw new i({ roomId: e });
1170
+ let m = async () => {
1171
+ let i = l === void 0 ? p.admitActorSource({
1172
+ origin: a.origin,
1173
+ roomId: e,
1174
+ hostId: this.host.id,
1175
+ epoch: r,
1176
+ operation: a.operation
1177
+ }) : p.admitActorSourceRecovery?.({
1178
+ origin: a.origin,
1179
+ roomId: e,
1180
+ hostId: this.host.id,
1181
+ epoch: r,
1182
+ priorEpoch: l,
1183
+ worldRecoveryEpoch: u
1184
+ }, d);
1185
+ if (!G.isEffect(i)) throw new t({ detail: "World source requires actual current entity admission" });
1186
+ let s = await Y(i);
1187
+ if (s.origin.tenantId !== n || s.origin.roomId !== e || s.origin.requestId !== a.origin.requestId || s.source.roomId !== e || (l === void 0 ? s.source.epoch !== r : s.source.epoch < (u ?? l) || s.source.epoch > l)) throw new t({ detail: "World source admission escaped its request" });
1188
+ let c = a.operation === "rollback" ? "rollback" : s.mode === "portal" ? "detach" : "switchClient";
1189
+ return await Y(I(o, s, c)), s;
1190
+ }, h = await m();
1191
+ if (a.operation === "rollback") {
1192
+ let i = this.runtime.worldFinalizationRequest(e, n, r);
1193
+ if (i !== null && i !== `${h.id}:exit`) {
1194
+ let a = (await Y(De(o, h, "rollback"))).find((t) => `${t.id}:exit` === i && t.source.roomId === e && t.origin.tenantId === n && t.phase === "failed");
1195
+ if (!a) throw new t({ detail: "World rollback cannot release a foreign actor finalization" });
1196
+ await Y(Ee(o, h, a, "rollback", (i) => G.tryPromise({
1197
+ try: () => this.applyWorldSourceTransitionOwned(e, n, r, {
1198
+ origin: a.origin,
1199
+ operation: "rollback"
1200
+ }, i, s, c, l, u, d),
1201
+ catch: () => new t({ detail: "World held group source compensation remains incomplete" })
1202
+ })));
1203
+ }
1204
+ }
1205
+ let g = async () => {
1206
+ let e = await m();
1207
+ if (e.id !== h.id || e.revision !== h.revision) throw new t({ detail: "World source changed during final handoff" });
1208
+ }, _ = async () => {
1209
+ await this.runtime.persist(e), await g();
1210
+ let t = a.operation === "detach" ? "exit" : "enter";
1211
+ h.mode === "seamless" && this.runtime.hasWorldReceipt(e, n, r, `${h.id}:${t}`, t) && await this.runtime.notifyWorldHandoff(e, n, {
1212
+ kind: "WorldHandoff",
1213
+ phase: a.operation === "detach" ? "departed" : "cancelled",
1214
+ transitionId: h.id,
1215
+ entityId: h.entityId,
1216
+ sourceEpoch: r,
1217
+ targetRoomId: h.target.roomId,
1218
+ targetEpoch: h.target.epoch,
1219
+ holdMs: 1e3
1220
+ }, g), await this.runtime.completeWorldFinalization(e, n, r, `${h.id}:exit`, g);
1221
+ };
1222
+ if (a.operation === "detach" && h.mode === "portal" && !this.runtime.hasWorldReceipt(e, n, r, `${h.id}:exit`, "exit")) {
1223
+ if (!p.retainActorDeparture) throw new t({ detail: "World portal departure requires actual durable source fencing" });
1224
+ this.worldTransitionPayload(f.descriptor, h, r, s), await this.runtime.finalizeWorldExit(e, n, {
1225
+ epoch: r,
1226
+ entityId: h.entityId,
1227
+ requestId: `${h.id}:exit`,
1228
+ location: h.target,
1229
+ ...h.subject ? { subjectId: h.subject.id } : {}
1230
+ }, s, async () => {
1231
+ let e = p.retainActorDeparture({
1232
+ origin: a.origin,
1233
+ expectedRevision: h.revision
1234
+ });
1235
+ if (!G.isEffect(e)) throw new t({ detail: "World portal departure requires an actual durable Effect" });
1236
+ let n = await Y(e);
1237
+ if (n.id !== h.id || n.revision !== h.revision || n.actorDepartureRevision !== h.revision) throw new t({ detail: "World portal departure acknowledgment changed its source phase" });
1238
+ }, g, h.actorSnapshot.entity, c), await _();
1239
+ return;
1240
+ }
1241
+ if (a.operation === "detach" && h.mode === "seamless" && !this.runtime.hasWorldReceipt(e, n, r, `${h.id}:exit`, "exit")) {
1242
+ if (!p.finalizeActorSnapshot) throw new t({ detail: "World seamless handoff requires actual final snapshot source" });
1243
+ let i = this.ghostReceivers.get(e), o = i?.epoch === r ? i.afterglowMs : void 0, l = o === void 0 ? void 0 : h.createdAt + o;
1244
+ if (l !== void 0 && (!Number.isSafeInteger(l) || l < 0)) throw new t({ detail: "Source afterglow deadline exceeds its bounded transition lifetime" });
1245
+ let u = this.runtime.worldFinalizationRequest(e, n, r) === null ? l === void 0 ? void 0 : {
1246
+ requestId: `wghost-${J("sha256").update(JSON.stringify([
1247
+ "afterglow",
1248
+ n,
1249
+ e,
1250
+ r,
1251
+ h.id
1252
+ ])).digest("hex")}:ghost`,
1253
+ expiresAt: l
1254
+ } : this.runtime.worldFinalizationAfterglow(e, n, r);
1255
+ await this.runtime.finalizeWorldExit(e, n, {
1256
+ epoch: r,
1257
+ entityId: h.entityId,
1258
+ requestId: `${h.id}:exit`,
1259
+ location: h.target,
1260
+ ...u ? { afterglow: u } : {},
1261
+ ...h.subject ? { subjectId: h.subject.id } : {}
1262
+ }, s, async (e) => {
1263
+ let n = A(f.descriptor.state, {
1264
+ maxBytes: s,
1265
+ maxFieldId: Math.min(4096, s * 7),
1266
+ maxCollectionLength: Math.min(16384, s)
1267
+ }), r = q.decodeUnknownSync(n.schema)(e.entity), i = n.full(r);
1268
+ if (K.isFailure(i)) throw i.failure;
1269
+ let o = O({
1270
+ schemaHash: n.schemaHash,
1271
+ bytes: Array.from(i.success),
1272
+ entity: e.entity
1273
+ }, s), c = p.finalizeActorSnapshot({
1274
+ origin: a.origin,
1275
+ expectedRevision: h.revision,
1276
+ snapshot: o,
1277
+ data: e.data
1278
+ });
1279
+ if (!G.isEffect(c)) throw new t({ detail: "World final snapshot requires actual durable Effect" });
1280
+ let l = await Y(c);
1281
+ if (l.id !== h.id || l.revision !== h.revision || !l.actorFinalSnapshot || C(l.actorFinalSnapshot.snapshot) !== C(o) || C(l.actorFinalSnapshot.data) !== C(e.data)) throw new t({ detail: "World final snapshot acknowledgment conflicts with captured actor" });
1282
+ }, g, h.actorFinalSnapshot?.snapshot.entity, c), await _();
1283
+ return;
1284
+ }
1285
+ if (a.operation === "rollback" && !this.runtime.hasWorldReceipt(e, n, r, `${h.id}:exit`, "exit")) {
1286
+ if ((h.actorFinalSnapshot || h.actorDepartureRevision !== void 0) && !this.runtime.hasWorldReceipt(e, n, r, `${h.id}:enter`, "enter")) {
1287
+ let t = h.actorFinalSnapshot?.snapshot ?? h.actorSnapshot;
1288
+ if (this.worldTransitionPayload(f.descriptor, h, r, s), l === void 0) {
1289
+ let i = await this.runtime.captureWorldEntity(e, n, r, h.entityId, s);
1290
+ de(i.entity, t, s);
1291
+ }
1292
+ await this.runtime.reconcileWorldSource(e, n, {
1293
+ epoch: r,
1294
+ requestId: `${h.id}:enter`,
1295
+ entity: t.entity,
1296
+ location: h.target
1297
+ }, s, g, c);
1298
+ } else await this.runtime.captureWorldEntity(e, n, r, h.entityId, s);
1299
+ await _();
1300
+ return;
1301
+ }
1302
+ this.worldTransitionPayload(f.descriptor, h, r, s);
1303
+ let v = a.operation === "detach" ? "exit" : "enter", y = {
1304
+ epoch: r,
1305
+ requestId: `${h.id}:${v}`,
1306
+ entity: (h.actorFinalSnapshot?.snapshot ?? h.actorSnapshot).entity,
1307
+ location: h.target
1308
+ }, b = a.operation === "rollback" ? this.runtime.worldReceiptSnapshot(e, n, r).filter((e) => e.projection?.expiresAt !== void 0 && e.projection.entity.id === h.entityId).map((e) => ({
1309
+ epoch: r,
1310
+ requestId: e.requestId,
1311
+ entity: e.projection.entity,
1312
+ location: e.projection.location
1313
+ })) : [];
1314
+ await this.runtime.applyWorldHook(e, n, v, y, s, c, async () => {
1315
+ let e = await m();
1316
+ if (e.id !== h.id || e.revision !== h.revision) throw new t({ detail: "World source changed before draft publication" });
1317
+ }, a.operation === "rollback", void 0, !1, b), await _();
1318
+ }
1319
+ authorizeWorldPlayer = (e) => G.tryPromise({
1320
+ try: async () => {
1321
+ let n = this.requireOwned(e.roomId, e.tenantId);
1322
+ if (!this.options.worlds?.some((e) => e.zones.some((e) => e.room === n.descriptor.name))) return;
1323
+ let r = this.options.worldEntities, a = this.options.resolveWorldPlayer;
1324
+ if (this.closed || this.closing || !n.published || n.listing.epoch !== e.epoch || !r?.admitActorPlayer || !a || e.role !== "player" || e.subjectId === null || this.runtime.isPublicationHeld(e.roomId)) throw new i({ roomId: e.roomId });
1325
+ let o = this.options.resolveSubject(e);
1326
+ if (!G.isEffect(o)) throw new t({ detail: "World player requires actual Subject resolution" });
1327
+ let s = q.decodeUnknownSync(W)(await Y(o));
1328
+ if (s.type !== "user" || s.id !== e.subjectId || s.tenantId !== e.tenantId) throw new t({ detail: "World player differs from its authenticated Subject" });
1329
+ let c = a(Object.freeze({ ...e }), Object.freeze(structuredClone(s)));
1330
+ if (!G.isEffect(c)) throw new t({ detail: "World character selection requires an actual Effect" });
1331
+ let l = await Y(c), u = r.admitActorPlayer({
1332
+ tenantId: e.tenantId,
1333
+ roomId: e.roomId,
1334
+ hostId: this.host.id,
1335
+ epoch: e.epoch,
1336
+ entityId: l,
1337
+ subject: {
1338
+ id: s.id,
1339
+ kind: s.kind === "guest" ? "guest" : "user"
1340
+ }
1341
+ });
1342
+ if (!G.isEffect(u)) throw new t({ detail: "World player admission requires actual entity authority" });
1343
+ let d = await Y(u);
1344
+ return typeof d == "object" && d ? h(d, this.options.worldSnapshotMaxBytes ?? 65536) : void 0;
1345
+ },
1346
+ catch: () => new t({ detail: "World player ownership admission refused" })
1347
+ });
1348
+ authorizeWorldTarget = (e, n, r) => G.tryPromise({
1349
+ try: async () => {
1350
+ let a = this.requireOwned(e.roomId, e.tenantId), o = this.options.worldEntities?.transitions;
1351
+ if (this.closed || this.closing || !a.published || a.listing.epoch !== e.epoch || !o?.admitActorSeat || e.role !== "player" || e.subjectId === null || this.runtime.isPublicationHeld(e.roomId)) throw new i({ roomId: e.roomId });
1352
+ let s = this.options.resolveSubject(e);
1353
+ if (!G.isEffect(s)) throw new t({ detail: "World Seat requires actual current Subject resolution" });
1354
+ let c = q.decodeUnknownSync(W)(await Y(s));
1355
+ if (c.type !== "user" || c.tenantId !== e.tenantId || c.id !== e.subjectId) throw new t({ detail: "World Seat Subject differs from its authenticated player" });
1356
+ let l = c.kind === "guest" ? "guest" : "user", u = o.admitActorSeat({
1357
+ origin: {
1358
+ tenantId: e.tenantId,
1359
+ roomId: n.sourceRoomId,
1360
+ requestId: n.requestId
1361
+ },
1362
+ roomId: e.roomId,
1363
+ hostId: this.host.id,
1364
+ epoch: e.epoch,
1365
+ binding: n,
1366
+ sessionId: e.sessionId,
1367
+ subjectId: e.subjectId,
1368
+ subjectKind: l,
1369
+ credentialDigest: r
1370
+ });
1371
+ if (!G.isEffect(u)) throw new t({ detail: "World Session admission requires actual SQL authority" });
1372
+ let d = await Y(u);
1373
+ return d.phase === "settled" ? "settled" : d.phase === "committed" ? "committed" : "pending";
1374
+ },
1375
+ catch: () => new t({ detail: "World target Session authority is incomplete" })
1376
+ });
1377
+ commitWorldTransition(e, n, r, a, o, s, c) {
1378
+ return this.capturedWorldOperation(() => h(a, 4096), async (a) => {
1379
+ let l = this.requireOwned(e, n), u = this.options.worldEntities?.transitions;
1380
+ if (!l.published || l.listing.epoch !== r || l.descriptor.mode === "lockstep" || !l.descriptor.world || !u?.admitActorTarget || a.tenantId !== n) throw new i({ roomId: e });
1381
+ let d = async () => {
1382
+ let i = u.admitActorTarget({
1383
+ origin: a,
1384
+ roomId: e,
1385
+ hostId: this.host.id,
1386
+ epoch: r
1387
+ });
1388
+ if (!G.isEffect(i)) throw new t({ detail: "World publication requires actual current target admission" });
1389
+ let s = await Y(i);
1390
+ if (s.origin.tenantId !== n || s.origin.roomId !== a.roomId || s.origin.requestId !== a.requestId || s.target.roomId !== e || s.target.epoch !== r || s.phase !== "committed") throw new t({ detail: "World target admission escaped the committed request" });
1391
+ return await Y(I(o, s, "settle")), s;
1392
+ }, f = await d(), p = {
1393
+ ...this.worldTransitionPayload(l.descriptor, f, r, s),
1394
+ ...l.descriptor.world.movement ? { arrival: f.target } : {}
1395
+ }, m = [];
1396
+ for (let t of this.runtime.worldReceiptSnapshot(e, n, r)) if (t.operation === "ghost") {
1397
+ if (t.projection && t.projection.entity.id === f.entityId) m.push({
1398
+ epoch: r,
1399
+ requestId: t.requestId,
1400
+ entity: t.projection.entity,
1401
+ location: t.projection.location
1402
+ });
1403
+ else if (t.requestId === `${f.id}:ghost`) {
1404
+ let { actorFinalSnapshot: e, ...n } = f;
1405
+ m.push({
1406
+ ...this.worldTransitionPayload(l.descriptor, n, r, s),
1407
+ requestId: t.requestId
1408
+ });
1409
+ }
1410
+ }
1411
+ await this.runtime.applyWorldHook(e, n, "enter", p, s, c, async () => {
1412
+ let e = await d();
1413
+ if (e.id !== f.id || e.revision !== f.revision) throw new t({ detail: "World target changed before draft publication" });
1414
+ }, !1, void 0, !1, m), await this.runtime.persist(e), await d(), f.subject && await this.runtime.activateWorldMembers(e, n, r, {
1415
+ transitionId: f.id,
1416
+ sourceRoomId: f.origin.roomId,
1417
+ requestId: f.origin.requestId,
1418
+ entityId: f.entityId
1419
+ }, async () => {
1420
+ await d();
1421
+ });
1422
+ });
1423
+ }
1424
+ ghostWorldTransition(e, n, r, a, o, s, c) {
1425
+ return this.capturedWorldOperation(() => h(a, 4096), async (a) => {
1426
+ let l = this.requireOwned(e, n), u = this.options.worldEntities?.transitions;
1427
+ if (!l.published || l.listing.epoch !== r || l.descriptor.mode === "lockstep" || !l.descriptor.world || !u?.admitActorGhost || a.tenantId !== n) throw new i({ roomId: e });
1428
+ let d = async () => {
1429
+ let i = u.admitActorGhost({
1430
+ origin: a,
1431
+ roomId: e,
1432
+ hostId: this.host.id,
1433
+ epoch: r
1434
+ });
1435
+ if (!G.isEffect(i)) throw new t({ detail: "World ghost requires actual SQL admission" });
1436
+ let s = await Y(i);
1437
+ if (s.origin.tenantId !== n || s.origin.roomId !== a.roomId || s.origin.requestId !== a.requestId || s.target.roomId !== e || s.target.epoch !== r || s.mode !== "seamless" || s.phase !== "ghosting") throw new t({ detail: "World ghost admission escaped its actual transition" });
1438
+ return await Y(I(o, s, "ghost")), s;
1439
+ };
1440
+ if (this.options.worldSnapshotMaxBytes === void 0 || !Number.isSafeInteger(s) || s < 1 || s > this.options.worldSnapshotMaxBytes) throw new t({ detail: "World ghost exceeds its configured recovery snapshot budget" });
1441
+ let f = await d(), p = {
1442
+ ...this.worldTransitionPayload(l.descriptor, f, r, s),
1443
+ requestId: `${f.id}:ghost`
1444
+ };
1445
+ await this.runtime.applyWorldHook(e, n, "ghost", p, s, c, async () => {
1446
+ let e = await d();
1447
+ if (e.id !== f.id || e.revision !== f.revision) throw new t({ detail: "World ghost changed before draft publication" });
1448
+ }), await this.runtime.persist(e), await d();
1449
+ });
1450
+ }
1451
+ previewWorldTransition(e, n, r, a, o, s) {
1452
+ return this.capturedWorldOperation(() => h(a, 4096), async (a) => {
1453
+ let c = this.requireOwned(e, n), l = this.options.worldEntities?.transitions;
1454
+ if (!c.published || c.listing.epoch !== r || c.descriptor.mode === "lockstep" || !c.descriptor.world || !l || a.tenantId !== n) throw new i({ roomId: e });
1455
+ let u = async () => {
1456
+ let t = await Y(this.directory.observeOwnership(e, n));
1457
+ if (!t || t.hostId !== this.host.id || t.epoch !== r || t.state !== "live") throw new i({ roomId: e });
1458
+ };
1459
+ await u();
1460
+ let d = l.observe(a);
1461
+ if (!G.isEffect(d)) throw new t({ detail: "World target requires actual transition observation" });
1462
+ let f = await Y(d);
1463
+ if (!f || f.origin.tenantId !== n || f.origin.roomId !== a.roomId || f.origin.requestId !== a.requestId || f.target.roomId !== e || f.target.epoch !== r || !["reserving", "switching"].includes(f.phase) || !f.actorSnapshot) throw new t({ detail: "World target lost its snapshot, phase or target epoch" });
1464
+ let p = {
1465
+ ...this.worldTransitionPayload(c.descriptor, f, r, o),
1466
+ ...c.descriptor.world.movement ? { arrival: f.target } : {}
1467
+ };
1468
+ await this.runtime.previewWorldEnter(e, n, p, o, s), await u();
1469
+ let m = l.observe(a);
1470
+ if (!G.isEffect(m)) throw new t({ detail: "World target requires final transition observation" });
1471
+ let h = await Y(m);
1472
+ if (!h || h.id !== f.id || h.revision !== f.revision || h.phase !== f.phase) throw new t({ detail: "World target transition changed during preparation" });
1473
+ });
1474
+ }
1475
+ previewWorldEnter(e, t, n, r, a) {
1476
+ return this.capturedWorldOperation(() => h(n, r), async (n) => {
1477
+ let o = this.requireOwned(e, t);
1478
+ if (!o.published || o.listing.epoch !== n.epoch || o.descriptor.mode === "lockstep" || !o.descriptor.world) throw new i({ roomId: e });
1479
+ let s = async () => {
1480
+ let r = await Y(this.directory.observeOwnership(e, t));
1481
+ if (!r || r.hostId !== this.host.id || r.epoch !== n.epoch || r.state !== "live") throw new i({ roomId: e });
1482
+ };
1483
+ await s(), await this.runtime.previewWorldEnter(e, t, n, r, a), await s();
1484
+ });
1485
+ }
1486
+ withdrawWorldTargetSession(e, n, r, a, o, s) {
1487
+ return this.capturedWorldOperation(() => h(a, 4096), async (a) => {
1488
+ let c = this.requireOwned(e, n), l = this.options.worldEntities?.transitions;
1489
+ if (!c.published || c.listing.epoch !== r || !l || a.tenantId !== n) throw new i({ roomId: e });
1490
+ let u = async () => {
1491
+ let s = await Y(this.directory.observeOwnership(e, n));
1492
+ if (!s || s.hostId !== this.host.id || s.epoch !== r || s.state !== "live") throw new i({ roomId: e });
1493
+ let c = l.observe(a);
1494
+ if (!G.isEffect(c)) throw new t({ detail: "World target withdrawal requires actual transition observation" });
1495
+ let u = await Y(c);
1496
+ if (!u || u.phase !== "failed" || u.origin.tenantId !== n || u.origin.roomId !== a.roomId || u.origin.requestId !== a.requestId || u.target.roomId !== e || u.target.epoch !== r) throw new t({ detail: "World target Session withdrawal escaped its failed transition" });
1497
+ return await Y(I(o, u, "rollback")), u;
1498
+ }, d = await u();
1499
+ if (d.mode === "seamless" && d.actorSnapshot) {
1500
+ if (!Number.isSafeInteger(s) || s < 1) throw new t({ detail: "Seamless target withdrawal requires its explicit snapshot byte budget" });
1501
+ let { actorFinalSnapshot: i, ...a } = d, o = {
1502
+ ...this.worldTransitionPayload(c.descriptor, a, r, s),
1503
+ requestId: `${d.id}:ghost`
1504
+ };
1505
+ await this.runtime.cancelWorldGhost(e, n, o, s, async () => {
1506
+ await u();
1507
+ }), await this.runtime.persist(e), await u();
1508
+ }
1509
+ if (!d.subject) {
1510
+ await this.runtime.cancelWorldPreview(e, n, r, `${d.id}:enter`, async () => {
1511
+ await u();
1512
+ });
1513
+ return;
1514
+ }
1515
+ let f = await Y(ce(this.store, l.observe.bind(l), d, d.group?.size ?? 1)), p = le(f, !0), m = p.seats.findIndex((e) => e.subjectId === d.subject.id), h = se(p, m);
1516
+ await this.runtime.settleSessions(e, n, r), await u();
1517
+ let g = this.runtime.readSessionAdmission(e, h);
1518
+ if (g && (g.tenantId !== n || g.roomId !== e || g.epoch !== r || g.subjectId !== d.subject.id || g.role !== "player")) throw new t({ detail: "World target Session does not match its actual transition Subject" });
1519
+ await this.runtime.leaveSession(e, h), await u(), await this.runtime.cancelWorldPreview(e, n, r, `${d.id}:enter`, async () => {
1520
+ await u();
1521
+ });
1522
+ });
1523
+ }
1524
+ async compensateTerminalWorldGhost(e, n, r, a, o, s) {
1525
+ if (a.phase !== "rolledBack" || a.mode !== "seamless" || a.target.roomId !== e || !this.runtime.hasWorldReceipt(e, n, r, o, "ghost")) return;
1526
+ let c = this.options.worldEntities?.transitions, l = this.options.worldSnapshotMaxBytes;
1527
+ if (!c?.observeActorReceipt || l === void 0 || !a.actorSnapshot || a.target.epoch > r) throw new t({ detail: "Terminal ghost recovery lacks its bounded original snapshot authority" });
1528
+ let u = async () => {
1529
+ let l = await Y(this.directory.observeOwnership(e, n));
1530
+ if (!l || l.hostId !== this.host.id || l.epoch !== r || l.state !== (s ? "creating" : "live")) throw new i({ roomId: e });
1531
+ let u = c.observeActorReceipt({
1532
+ tenantId: n,
1533
+ roomId: e,
1534
+ transitionId: a.id
1535
+ });
1536
+ if (!G.isEffect(u)) throw new t({ detail: "Terminal ghost recovery requires actual transition observation" });
1537
+ let d = await Y(u);
1538
+ if (!d || d.id !== a.id || d.revision !== a.revision || d.phase !== "rolledBack" || d.target.roomId !== e || o !== `${d.id}:ghost`) throw new t({ detail: "Terminal ghost recovery lost its exact rollback receipt" });
1539
+ };
1540
+ await u();
1541
+ let { actorFinalSnapshot: d, ...f } = a, p = {
1542
+ ...this.worldTransitionPayload(this.requireOwned(e, n).descriptor, f, r, l),
1543
+ requestId: o
1544
+ };
1545
+ await this.runtime.cancelWorldGhost(e, n, p, l, u), await this.runtime.persist(e), await u();
1546
+ }
1547
+ async retireTerminalWorldReceipts(e, n, r, a = !1) {
1548
+ let o = this.requireOwned(e, n), s = this.options.worldEntities?.transitions;
1549
+ if (o.listing.epoch !== r || (a ? o.published || !this.runtime.isPublicationHeld(e) : !o.published || this.runtime.isPublicationHeld(e))) throw new i({ roomId: e });
1550
+ if (this.runtime.hasPendingCheckpoint(e) || this.runtime.worldFinalizationRequest(e, n, r) !== null) return;
1551
+ let c = async () => {
1552
+ let t = await Y(this.directory.observeOwnership(e, n));
1553
+ if (!t || t.hostId !== this.host.id || t.epoch !== r || t.state !== (a ? "creating" : "live")) throw new i({ roomId: e });
1554
+ };
1555
+ if (await c(), a || this.runtime.worldLifecycleQuiet(e)) {
1556
+ for (let i of this.runtime.worldReceiptSnapshot(e, n, r)) {
1557
+ if (i.projection) {
1558
+ if (!a) {
1559
+ let e = this.options.epochNow();
1560
+ if (!Number.isSafeInteger(e) || e < 0) throw new t({ detail: "Afterglow expiry requires current epoch time" });
1561
+ if (i.projection.expiresAt === void 0 || e < i.projection.expiresAt) continue;
1562
+ }
1563
+ let s = this.options.worldSnapshotMaxBytes;
1564
+ if (s === void 0 || o.descriptor.mode === "lockstep") throw new t({ detail: "Ghost recovery requires its configured entity codec budget" });
1565
+ let l = h(i.projection, s), u = A(o.descriptor.state, {
1566
+ maxBytes: s,
1567
+ maxFieldId: Math.min(4096, s * 7),
1568
+ maxCollectionLength: Math.min(16384, s)
1569
+ }), d = q.decodeUnknownSync(u.schema)(l.entity), f = u.full(d);
1570
+ if (K.isFailure(f)) throw f.failure;
1571
+ await c(), await this.runtime.cancelWorldGhost(e, n, {
1572
+ epoch: r,
1573
+ requestId: i.requestId,
1574
+ entity: l.entity,
1575
+ location: l.location
1576
+ }, s, c), await this.runtime.persist(e), await c();
1577
+ continue;
1578
+ }
1579
+ if (a && /^wghost-[0-9a-f]{64}:ghost$/.test(i.requestId)) throw new t({ detail: "Legacy streaming ghost checkpoint lacks its exact removal payload" });
1580
+ if (!s?.observeActorReceipt) continue;
1581
+ let l = `:${i.operation}`;
1582
+ if (!i.requestId.endsWith(l)) continue;
1583
+ let u = i.requestId.slice(0, -l.length);
1584
+ if (!/^[A-Za-z0-9][A-Za-z0-9_.:-]*$/.test(u)) continue;
1585
+ let d = s.observeActorReceipt({
1586
+ tenantId: n,
1587
+ roomId: e,
1588
+ transitionId: u
1589
+ });
1590
+ if (!G.isEffect(d)) throw new t({ detail: "World cleanup requires actual receipt observation" });
1591
+ let f = await Y(d);
1592
+ if (f && ["settled", "rolledBack"].includes(f.phase)) {
1593
+ if (f.id !== u || f.origin.tenantId !== n || f.source.roomId !== e && f.target.roomId !== e) throw new t({ detail: "World terminal cleanup escaped its actor scope" });
1594
+ await c(), i.operation === "ghost" && await this.compensateTerminalWorldGhost(e, n, r, f, i.requestId, a), await this.runtime.retireWorldReceipt(e, n, r, i.requestId, i.operation), await this.runtime.persist(e);
1595
+ }
1596
+ }
1597
+ await c();
1598
+ }
1599
+ }
1600
+ retireWorldReceipt(e, n, r, a, o, s) {
1601
+ return this.capturedWorldOperation(() => h({
1602
+ origin: a,
1603
+ requestId: o,
1604
+ operation: s
1605
+ }, 4096), async (a) => {
1606
+ let o = this.requireOwned(e, n), s = this.options.worldEntities?.transitions;
1607
+ if (!o.published || o.listing.epoch !== r || !s || a.origin.tenantId !== n || ![
1608
+ "enter",
1609
+ "exit",
1610
+ "ghost"
1611
+ ].includes(a.operation)) throw new i({ roomId: e });
1612
+ let c = await Y(this.directory.observeOwnership(e, n));
1613
+ if (!c || c.hostId !== this.host.id || c.epoch !== r || c.state !== "live") throw new i({ roomId: e });
1614
+ let l = s.observe(a.origin);
1615
+ if (!G.isEffect(l)) throw new t({ detail: "World receipt retirement requires actual transition observation" });
1616
+ let u = await Y(l);
1617
+ if (!u || u.origin.tenantId !== n || u.origin.roomId !== a.origin.roomId || u.origin.requestId !== a.origin.requestId || !["settled", "rolledBack"].includes(u.phase) || u.source.roomId !== e && u.target.roomId !== e || a.requestId !== `${u.id}:${a.operation}`) throw new t({ detail: "World actor receipt lacks matching terminal transition authority" });
1618
+ a.operation === "ghost" && await this.compensateTerminalWorldGhost(e, n, r, u, a.requestId, !1), await this.runtime.retireWorldReceipt(e, n, r, a.requestId, a.operation), await this.runtime.persist(e);
1619
+ });
1620
+ }
1621
+ applyWorldHook(e, t, n, r, a, o) {
1622
+ return this.capturedWorldOperation(() => h(r, a), async (r) => {
1623
+ let s = this.requireOwned(e, t);
1624
+ if (!s.published || s.listing.epoch !== r.epoch || s.descriptor.mode === "lockstep" || !s.descriptor.world || r.requestId === void 0) throw new i({ roomId: e });
1625
+ let c = await Y(this.directory.observeOwnership(e, t));
1626
+ if (!c || c.hostId !== this.host.id || c.epoch !== r.epoch || c.state !== "live") throw new i({ roomId: e });
1627
+ await this.runtime.applyWorldHook(e, t, n, r, a, o), await this.runtime.persist(e);
1628
+ });
1629
+ }
1630
+ worldNeighborGhostInput(e, n, r, i, a, o) {
1631
+ let s = this.requireOwned(e, n), c = i.capture, l = c.source;
1632
+ if (!s.published || s.listing.epoch !== r || !s.descriptor.world || !Number.isSafeInteger(i.sequence) || i.sequence < 1 || i.sequence > 2147483647 || l.tenantId !== n || l.hostId !== a.hostId || c.snapshot.entity.id !== c.entityId || this.options.worldSnapshotMaxBytes === void 0 || o > this.options.worldSnapshotMaxBytes) throw new t({ detail: "World neighbor projection escaped its actual target or byte budget" });
1633
+ return {
1634
+ epoch: r,
1635
+ requestId: `wghost-${J("sha256").update(JSON.stringify([
1636
+ n,
1637
+ e,
1638
+ r,
1639
+ l.roomId,
1640
+ l.epoch,
1641
+ a.hostId,
1642
+ a.instanceId,
1643
+ a.startedAt,
1644
+ c.entityId,
1645
+ i.sequence
1646
+ ])).digest("hex")}:ghost`,
1647
+ entity: this.decodeWorldActorSnapshot(s.descriptor, c.snapshot, o),
1648
+ location: {
1649
+ worldId: l.worldId,
1650
+ zoneId: l.zoneId,
1651
+ at: l.at,
1652
+ layer: l.layer,
1653
+ roomId: l.roomId,
1654
+ epoch: l.epoch
1655
+ }
1656
+ };
1657
+ }
1658
+ async assertWorldGhostPeer(e, n = !1) {
1659
+ let r = this.host.membership, i = n && e.hostId !== this.host.id;
1660
+ if (n && r?.instanceId === void 0) throw new t({ detail: "World ghost target lacks its registered instance" });
1661
+ let a = [e, ...i ? [{
1662
+ hostId: this.host.id,
1663
+ instanceId: r.instanceId,
1664
+ startedAt: r.startedAt
1665
+ }] : []], o = await this.store.query({
1666
+ table: x,
1667
+ predicate: i ? Xe("id", a.map((e) => e.hostId)) : U("id", e.hostId),
1668
+ order: [],
1669
+ take: a.length + 1,
1670
+ skip: void 0,
1671
+ projection: [
1672
+ "id",
1673
+ "instanceId",
1674
+ "membershipStartedAt",
1675
+ "ready",
1676
+ "draining",
1677
+ "lastHeartbeatAt",
1678
+ "pool"
1679
+ ]
1680
+ }), s = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN;
1681
+ if (o.length !== a.length || !a.every((e) => {
1682
+ let t = o.filter((t) => !i || t.id === e.hostId);
1683
+ return t.length === 1 && t[0].instanceId === e.instanceId && s(t[0].membershipStartedAt) === e.startedAt && (t[0].pool ?? null) === (this.host.pool ?? null) && t[0].ready === !0 && t[0].draining === !1 && s(t[0].lastHeartbeatAt) > this.options.epochNow() - this.options.heartbeatTtlMs;
1684
+ }) || n && !i && e.instanceId !== r.instanceId) throw new t({ detail: "World ghost peer registration is stale or unavailable" });
1685
+ }
1686
+ admitWorldGhostHandshake(e, n) {
1687
+ return this.capturedWorldOperation(() => h(e, 16384), async (e) => {
1688
+ let r = this.host.membership, a = this.requireOwned(e.roomId, e.tenantId), o = this.options.worldSnapshotMaxBytes;
1689
+ if (!r || e.purpose !== "voltro.rooms.ghost.hello.v1" || e.target.hostId !== this.host.id || e.target.instanceId !== r.instanceId || e.target.startedAt !== r.startedAt || !a.published || a.listing.epoch !== e.epoch || !a.descriptor.world || o === void 0 || typeof n != "function") throw new i({ roomId: e.roomId });
1690
+ if (A(a.descriptor.state, {
1691
+ maxBytes: o,
1692
+ maxFieldId: Math.min(4096, o * 7),
1693
+ maxCollectionLength: Math.min(16384, o)
1694
+ }).schemaHash !== e.schemaHash) throw new t({ detail: "Ghost peer entity schema differs from actual target" });
1695
+ let s = async () => {
1696
+ if (this.closing || this.closed || !this.activated || this.owned.get(e.roomId) !== a || !a.published || e.expiresAt <= this.options.epochNow() || e.issuedAt > this.options.epochNow()) throw new i({ roomId: e.roomId });
1697
+ let t = await Y(this.directory.observeOwnership(e.roomId, e.tenantId));
1698
+ if (!t || t.hostId !== this.host.id || t.epoch !== e.epoch || t.state !== "live") throw new i({ roomId: e.roomId });
1699
+ await this.assertWorldGhostPeer(e.source), await this.assertWorldGhostPeer(e.target);
1700
+ };
1701
+ await s();
1702
+ let c = n(e);
1703
+ if (!G.isEffect(c) || await Y(c) !== void 0) throw new t({ detail: "Ghost handshake lacks actual target policy" });
1704
+ await s();
1705
+ });
1706
+ }
1707
+ async admitWorldNeighborGhostOwned(e, n, r, i, a, o, s, c) {
1708
+ this.worldNeighborGhostInput(e, n, r, a, o, s);
1709
+ let l = this.options.worldEntities, u = a.capture.source;
1710
+ if (!l?.admitActorNeighbor || i.roomId !== e || i.epoch !== r || typeof c != "function") throw new t({ detail: "World neighbor requires acquired peer and actual SQL admission" });
1711
+ let d = c(o);
1712
+ if (!G.isEffect(d) || await Y(d) !== void 0) throw new t({ detail: "World neighbor peer authority is incomplete" });
1713
+ await this.assertWorldGhostPeer(o, !0);
1714
+ let f = l.admitActorNeighbor({
1715
+ tenantId: n,
1716
+ entityId: a.capture.entityId,
1717
+ roomId: u.roomId,
1718
+ hostId: u.hostId,
1719
+ epoch: u.epoch,
1720
+ expectedRevision: a.capture.revision,
1721
+ source: {
1722
+ worldId: u.worldId,
1723
+ zoneId: u.zoneId,
1724
+ at: u.at,
1725
+ layer: u.layer,
1726
+ roomId: u.roomId,
1727
+ epoch: u.epoch
1728
+ },
1729
+ target: i,
1730
+ targetHostId: this.host.id
1731
+ });
1732
+ if (!G.isEffect(f)) throw new t({ detail: "World neighbor requires actual SQL authority" });
1733
+ await Y(f);
1734
+ }
1735
+ admitWorldNeighborGhost(e, t, n, r, i, a, o, s) {
1736
+ return this.capturedWorldOperation(() => ({
1737
+ target: h(r, 4096),
1738
+ frame: h(i, o),
1739
+ peer: h(a, 1024)
1740
+ }), (r) => this.admitWorldNeighborGhostOwned(e, t, n, r.target, r.frame, r.peer, o, s));
1741
+ }
1742
+ applyWorldNeighborGhost(e, n, r, i, a, o, s, c, l) {
1743
+ return this.capturedWorldOperation(() => ({
1744
+ target: h(i, 4096),
1745
+ frame: h(a, s),
1746
+ peer: h(o, 1024),
1747
+ previous: l === void 0 ? void 0 : {
1748
+ frame: h(l.frame, s),
1749
+ peer: h(l.peer, 1024)
1750
+ }
1751
+ }), async (i) => {
1752
+ let a = () => this.admitWorldNeighborGhostOwned(e, n, r, i.target, i.frame, i.peer, s, c);
1753
+ await a();
1754
+ let o = this.worldNeighborGhostInput(e, n, r, i.frame, i.peer, s);
1755
+ if (i.previous) {
1756
+ if (i.previous.frame.capture.entityId !== i.frame.capture.entityId) throw new t({ detail: "World ghost replacement changed entity identity" });
1757
+ let c = this.worldNeighborGhostInput(e, n, r, i.previous.frame, i.previous.peer, s);
1758
+ await this.runtime.replaceWorldGhostProjection(e, n, o, c, s, a);
1759
+ } else {
1760
+ let c = this.runtime.worldReceiptSnapshot(e, n, r).filter((e) => e.projection?.expiresAt !== void 0 && e.projection.entity.id === i.frame.capture.entityId);
1761
+ if (c.length > 1) throw new t({ detail: "Reverse ghost stream has ambiguous local afterglow" });
1762
+ let l = c[0];
1763
+ l ? await this.runtime.replaceWorldGhostProjection(e, n, o, {
1764
+ epoch: r,
1765
+ requestId: l.requestId,
1766
+ entity: l.projection.entity,
1767
+ location: l.projection.location
1768
+ }, s, a) : await this.runtime.applyWorldHook(e, n, "ghost", o, s, void 0, a, !1, void 0, !0);
1769
+ }
1770
+ await this.runtime.persist(e), await a();
1771
+ });
1772
+ }
1773
+ ownWorldGhostReceiver(e, n, r, i, a) {
1774
+ let o = this.requireOwned(e, n);
1775
+ if (P() || this.closed || this.closing || !this.activated || !o.published || o.listing.epoch !== r || this.ghostReceivers.has(e) || this.ghostReceivers.size >= this.options.capacity) throw new t({ detail: "Ghost receiver requires exclusive live target Room lifetime" });
1776
+ if (a !== void 0 && (!Number.isSafeInteger(a) || a < 1 || a > 6e4)) throw new t({ detail: "Source afterglow requires its acquired receiver lifetime bound" });
1777
+ let c = s(i, [
1778
+ "receive",
1779
+ "withdraw",
1780
+ "runDue",
1781
+ "close"
1782
+ ], [
1783
+ "receive",
1784
+ "withdraw",
1785
+ "runDue",
1786
+ "close"
1787
+ ]);
1788
+ if (Object.values(c).some((e) => typeof e != "function")) throw new t({ detail: "Ghost receiver requires actual acquired operations" });
1789
+ let l = {
1790
+ tenantId: n,
1791
+ epoch: r,
1792
+ receiver: i,
1793
+ ...a === void 0 ? {} : { afterglowMs: a }
1794
+ }, u = i.close.bind(i), d = i.runDue.bind(i), f = !1, p = (t) => G.sync(() => {
1795
+ f && t.retained === 0 && t.deferred.length === 0 && this.ghostReceivers.get(e) === l && this.ghostReceivers.delete(e);
1796
+ }), m = Object.freeze({
1797
+ receive: i.receive.bind(i),
1798
+ withdraw: i.withdraw.bind(i),
1799
+ runDue: () => G.tap(d(), p),
1800
+ close: () => G.suspend(() => (f = !0, G.tap(u(), p)))
1801
+ });
1802
+ return l.receiver = m, this.ghostReceivers.set(e, l), m;
1803
+ }
1804
+ configureWorldGhostCells(e, n) {
1805
+ return this.operation(async () => {
1806
+ if (this.closing || this.closed || typeof n != "function" || !this.options.worlds?.some((t) => t.name === e) || this.ghostCellFactories.has(e)) throw new t({ detail: "Ghost cell lifecycle requires one declared World policy" });
1807
+ this.ghostCellFactories.set(e, n);
1808
+ }, !0);
1809
+ }
1810
+ async acquireWorldGhostCells() {
1811
+ if (this.closed || this.closing || !this.activated || !this.ghostCellFactories.size) return;
1812
+ let e = [];
1813
+ for (let [n, r] of [...this.owned]) if (r.published && r.descriptor.world && (this.ghostReceivers.get(n)?.epoch !== r.listing.epoch || this.ghostPublishers.get(n)?.owned !== r)) {
1814
+ for (let [a, o] of this.ghostCellFactories) if (this.options.worlds?.find((e) => e.name === a)?.zones.some((e) => e.room === r.descriptor.name)) try {
1815
+ let e = await this.worldOperation(async () => {
1816
+ if (this.owned.get(n) !== r || !r.published) throw new i({ roomId: n });
1817
+ let e = await Y(D(this.store, {
1818
+ worlds: this.options.worlds,
1819
+ epochNow: this.options.epochNow,
1820
+ maxListedCells: 1,
1821
+ authorize: () => G.sync(() => {
1822
+ if (this.owned.get(n) !== r || !r.published) throw new i({ roomId: n });
1823
+ })
1824
+ }).observeRoom({
1825
+ tenantId: r.listing.tenantId,
1826
+ worldId: a,
1827
+ roomId: n
1828
+ }));
1829
+ if (e && (e.cell.hostId !== this.host.id || e.cell.epoch !== r.listing.epoch)) throw new i({ roomId: n });
1830
+ return e;
1831
+ });
1832
+ if (!e) continue;
1833
+ let { cell: c, at: l } = e, u = Object.freeze({
1834
+ worldId: a,
1835
+ zoneId: c.zoneId,
1836
+ roomId: n,
1837
+ epoch: c.epoch,
1838
+ layer: c.layer,
1839
+ at: l
1840
+ }), d = o(Object.freeze({
1841
+ tenantId: c.tenantId,
1842
+ target: u
1843
+ }));
1844
+ if (d instanceof Promise) throw d.catch(() => void 0), new t({ detail: "Ghost cell policies must be synchronous" });
1845
+ s(d, ["receiver", "publisher"], ["receiver", "publisher"]);
1846
+ let f = [
1847
+ "maxEntities",
1848
+ "maxFrameBytes",
1849
+ "maxRetainedBytes",
1850
+ "ttlMs",
1851
+ "now",
1852
+ "authorizePeer"
1853
+ ], p = [
1854
+ "publication",
1855
+ "neighborhood",
1856
+ "position",
1857
+ "outbound"
1858
+ ];
1859
+ if (s(d.receiver, f, f), s(d.publisher, p, p), this.owned.get(n) !== r || !r.published || this.closing) throw new i({ roomId: n });
1860
+ this.ghostReceivers.has(n) || pe(this, {
1861
+ ...d.receiver,
1862
+ tenantId: c.tenantId,
1863
+ target: u
1864
+ }), this.ghostPublishers.has(n) || await this.ownWorldGhostPublisher(n, c.tenantId, c.epoch, {
1865
+ ...d.publisher,
1866
+ worldId: a
1867
+ });
1868
+ break;
1869
+ } catch (t) {
1870
+ e.push(t);
1871
+ }
1872
+ }
1873
+ if (e.length) throw AggregateError(e, "World cell ghost acquisition remains incomplete");
1874
+ }
1875
+ ownWorldGhostPublisher(e, n, r, a) {
1876
+ return this.capturedWorldOperation(() => {
1877
+ s(a, [
1878
+ "worldId",
1879
+ "publication",
1880
+ "neighborhood",
1881
+ "position",
1882
+ "outbound"
1883
+ ], [
1884
+ "worldId",
1885
+ "publication",
1886
+ "neighborhood",
1887
+ "position",
1888
+ "outbound"
1889
+ ]);
1890
+ let e = [
1891
+ "now",
1892
+ "cadenceMs",
1893
+ "maxEntities",
1894
+ "maxChannels",
1895
+ "maxFramesPerTurn",
1896
+ "maxBytesPerTurn",
1897
+ "maxRetainedBytes",
1898
+ "maxSnapshotBytes",
1899
+ "maxFrameBytes"
1900
+ ], n = s(a.publication, e, e), r = [
1901
+ "maxZoneChecks",
1902
+ "maxCandidateCells",
1903
+ "maxObservationBytes",
1904
+ "authorize"
1905
+ ], i = s(a.neighborhood, r, r);
1906
+ if (typeof a.position != "function" || typeof n.now != "function" || typeof i.authorize != "function") throw new t({ detail: "Ghost publisher requires captured source policies" });
1907
+ return {
1908
+ worldId: a.worldId,
1909
+ publication: {
1910
+ ...n,
1911
+ now: n.now.bind(a.publication)
1912
+ },
1913
+ neighborhood: {
1914
+ ...i,
1915
+ authorize: i.authorize.bind(a.neighborhood)
1916
+ },
1917
+ position: a.position.bind(a),
1918
+ outbound: k(a.outbound)
1919
+ };
1920
+ }, async (a) => {
1921
+ let o = this.requireOwned(e, n), s = this.options.worlds?.find((e) => e.name === a.worldId);
1922
+ if (!o.published || o.listing.epoch !== r || !s || !o.descriptor.world || !s.zones.some((e) => e.room === o.descriptor.name) || this.ghostPublishers.has(e) || this.options.worldSnapshotMaxBytes === void 0 || a.publication.maxSnapshotBytes > this.options.worldSnapshotMaxBytes || a.publication.maxSnapshotBytes > a.outbound.sender.maxSnapshotBytes || a.publication.maxFrameBytes !== a.outbound.sender.maxFrameBytes) throw new t({ detail: "Ghost publisher lacks its actual bounded source lifetime" });
1923
+ let c = Ne(this.store, {
1924
+ ...a.neighborhood,
1925
+ world: s,
1926
+ tenantId: n,
1927
+ epochNow: this.options.epochNow
1928
+ }), l = me({
1929
+ ...a.publication,
1930
+ list: () => this.listWorldGhostEntityIds(e, n, r, a.publication.maxEntities, 1048576),
1931
+ capture: (t) => this.captureWorldGhostSource(e, n, r, t, a.publication.maxSnapshotBytes, a.position),
1932
+ neighbors: async (e) => (await Y(c.observe(e.source))).neighbors.flatMap((e) => e.placement?.state === "live" ? [e.placement] : []),
1933
+ nextSequence: () => {
1934
+ if (this.owned.get(e) !== o || o.listing.epoch !== r) throw new i({ roomId: e });
1935
+ let n = (this.ghostPublisherSequences.get(o) ?? 0) + 1;
1936
+ if (n > 2147483647) throw new t({ detail: "Ghost source exhausted its epoch sequence space" });
1937
+ return this.ghostPublisherSequences.set(o, n), n;
1938
+ },
1939
+ open: (t) => this.openWorldGhostChannel(e, n, r, t, a.outbound)
1940
+ }), u = {
1941
+ owned: o,
1942
+ publisher: l
1943
+ };
1944
+ return this.ghostPublishers.set(e, u), Object.freeze({
1945
+ ...l,
1946
+ close: async () => {
1947
+ await l.close(), this.ghostPublishers.get(e) === u && this.ghostPublishers.delete(e);
1948
+ }
1949
+ });
1950
+ });
1951
+ }
1952
+ openWorldGhostChannel(e, n, r, a, o) {
1953
+ return P() ? Promise.reject(new t({ detail: "Ghost socket acquisition must run outside command delivery" })) : this.capturedWorldOperation(() => ({
1954
+ target: h(a, 4096),
1955
+ options: k(o)
1956
+ }), async (a) => {
1957
+ let o = this.requireOwned(e, n), s = this.host.membership, c = this.options.worldGhostMaxConnections, l = a.options;
1958
+ if (!o.published || o.listing.epoch !== r || !o.descriptor.world || !s || s.instanceId === void 0 || c === void 0 || this.ghostTransports.size + this.ghostOutbounds.size >= c || this.options.worldSnapshotMaxBytes === void 0 || l.sender.maxSnapshotBytes > this.options.worldSnapshotMaxBytes || [...this.ghostOutbounds].some((t) => t.roomId === e && t.tenantId === n && t.epoch === r && t.target.roomId === a.target.roomId && t.target.epoch === a.target.epoch)) throw new t({ detail: "World source lacks its bounded outbound channel lifetime" });
1959
+ let u = Object.freeze({
1960
+ hostId: this.host.id,
1961
+ instanceId: s.instanceId,
1962
+ startedAt: s.startedAt
1963
+ }), d = A(o.descriptor.state, {
1964
+ maxBytes: l.sender.maxFrameBytes,
1965
+ maxFieldId: Math.min(4096, l.sender.maxFrameBytes * 7),
1966
+ maxCollectionLength: Math.min(16384, l.sender.maxFrameBytes)
1967
+ }), f = ge(this.store, {
1968
+ tenantId: n,
1969
+ source: u,
1970
+ path: l.path,
1971
+ epochNow: this.options.epochNow,
1972
+ heartbeatTtlMs: this.options.heartbeatTtlMs,
1973
+ authorize: l.authorize
1974
+ }), p = async () => {
1975
+ if (P()) throw new t({ detail: "Ghost socket operations must run outside command delivery" });
1976
+ if (this.closing || this.closed || !this.activated || this.owned.get(e) !== o || !o.published || o.listing.epoch !== r) throw new i({ roomId: e });
1977
+ let a = await Y(this.directory.observeOwnership(e, n));
1978
+ if (!a || a.hostId !== this.host.id || a.epoch !== r || a.state !== "live") throw new i({ roomId: e });
1979
+ await this.assertWorldGhostPeer(u);
1980
+ }, m, h = he({
1981
+ maxSnapshotBytes: l.sender.maxSnapshotBytes,
1982
+ current: p,
1983
+ validate: (i) => {
1984
+ if (P()) throw new t({ detail: "Ghost publication must run outside command delivery" });
1985
+ let a = i.capture.source;
1986
+ if (a.roomId !== e || a.tenantId !== n || a.epoch !== r || a.hostId !== this.host.id || i.capture.snapshot.schemaHash !== d.schemaHash) throw new t({ detail: "Ghost frame escaped its actual source actor scope" });
1987
+ },
1988
+ acquire: async (e) => {
1989
+ let t = await Y(f.resolve(a.target));
1990
+ return m.destination = t, await p(), _e(t.address, e, {
1991
+ carrier: l.carrier,
1992
+ scope: {
1993
+ source: u,
1994
+ target: t.target,
1995
+ tenantId: n,
1996
+ roomId: t.cell.roomId,
1997
+ epoch: t.cell.epoch,
1998
+ schemaHash: d.schemaHash
1999
+ },
2000
+ sender: {
2001
+ ...l.sender,
2002
+ state: o.descriptor.state
2003
+ },
2004
+ socket: l.socket,
2005
+ handshakeTimeoutMs: l.handshakeTimeoutMs,
2006
+ maxSignedBytes: l.maxSignedBytes
2007
+ });
2008
+ },
2009
+ release: () => {
2010
+ this.ghostOutbounds.delete(m);
2011
+ }
2012
+ });
2013
+ return m = {
2014
+ roomId: e,
2015
+ tenantId: n,
2016
+ epoch: r,
2017
+ target: a.target,
2018
+ owner: h,
2019
+ current: p
2020
+ }, this.ghostOutbounds.add(m), m;
2021
+ }).then(async (e) => {
2022
+ try {
2023
+ return await e.owner.ready;
2024
+ } catch (t) {
2025
+ try {
2026
+ await e.owner.close();
2027
+ } catch {
2028
+ throw new _(() => e.owner.close());
2029
+ }
2030
+ throw t;
2031
+ }
2032
+ });
2033
+ }
2034
+ bindWorldGhostTransport(e, n, r, i) {
2035
+ let a, o;
2036
+ try {
2037
+ a = h(e, 16384), o = h(r, 1024);
2038
+ } catch (e) {
2039
+ return Promise.reject(e);
2040
+ }
2041
+ return this.admitWorldGhostHandshake(a, i).then(() => this.worldOperation(async () => {
2042
+ let e = this.requireOwned(a.roomId, a.tenantId), r = this.ghostReceivers.get(a.roomId), i = this.options.worldGhostMaxConnections;
2043
+ if (i === void 0 || this.ghostTransports.size + this.ghostOutbounds.size >= i || !r || r.tenantId !== a.tenantId || r.epoch !== a.epoch || !e.published || e.listing.epoch !== a.epoch || n.signal.aborted || this.options.worldSnapshotMaxBytes === void 0 || o.maxSnapshotBytes > this.options.worldSnapshotMaxBytes) throw new t({ detail: "Ghost transport lacks its bounded acquired target lifetime" });
2044
+ let s = g(n, "close", "Ghost transport requires actual withdrawal"), c = ve(n, {
2045
+ ...o,
2046
+ state: e.descriptor.state,
2047
+ receive: (e) => r.receiver.receive(e, a.source),
2048
+ withdraw: (e) => r.receiver.withdraw(e, a.source)
2049
+ }), l, u = {
2050
+ hello: a,
2051
+ signal: n.signal,
2052
+ receiver: r.receiver,
2053
+ close: () => {
2054
+ if (l) return l;
2055
+ let e = Promise.resolve().then(async () => {
2056
+ let e = [];
2057
+ try {
2058
+ s(1e3, "World ghost target lifetime ended");
2059
+ } catch (t) {
2060
+ e.push(t);
2061
+ }
2062
+ try {
2063
+ await c.close();
2064
+ } catch (t) {
2065
+ e.push(t);
2066
+ }
2067
+ if (e.length) throw AggregateError(e, "Ghost target ingress cleanup remains incomplete");
2068
+ this.ghostTransports.delete(u);
2069
+ });
2070
+ return l = e, e.catch(() => {
2071
+ l === e && (l = void 0);
2072
+ }), e;
2073
+ }
2074
+ };
2075
+ return this.ghostTransports.add(u), Object.freeze({
2076
+ close: u.close,
2077
+ settled: c.settled,
2078
+ snapshot: c.snapshot
2079
+ });
2080
+ }));
2081
+ }
2082
+ runWorldGhostReceivers(e) {
2083
+ let t = this.ghostMaintenance;
2084
+ if (t && !e) return t;
2085
+ let n = Promise.resolve().then(async () => {
2086
+ t && await t.catch(() => void 0), await this.runWorldGhostMaintenance(e);
2087
+ });
2088
+ return this.ghostMaintenance = n, n.then(() => {
2089
+ this.ghostMaintenance === n && (this.ghostMaintenance = void 0);
2090
+ }, () => {
2091
+ this.ghostMaintenance === n && (this.ghostMaintenance = void 0);
2092
+ }), n;
2093
+ }
2094
+ async runWorldGhostMaintenance(e) {
2095
+ let n = [];
2096
+ if (!e && !this.closing && (this.ghostCellFactories.size || this.ghostPublishers.size || this.ghostReceivers.size)) try {
2097
+ await this.worldOperation(async () => {
2098
+ for (let [e, t] of this.owned) if (t.published && t.descriptor.mode !== "lockstep" && t.descriptor.world && !this.runtime.isPublicationHeld(e)) try {
2099
+ await this.synchronizeWorldCell(e, t);
2100
+ } catch (e) {
2101
+ n.push(e);
2102
+ }
2103
+ });
2104
+ } catch (e) {
2105
+ n.push(e);
2106
+ }
2107
+ for (let [t, r] of [...this.ghostPublishers]) try {
2108
+ let n = await Y(this.directory.observeOwnership(t, r.owned.listing.tenantId));
2109
+ (e || r.publisher.snapshot().closed || this.owned.get(t) !== r.owned || !r.owned.published || !n || n.hostId !== this.host.id || n.epoch !== r.owned.listing.epoch || n.state !== "live") && (await r.publisher.close(), this.ghostPublishers.get(t) === r && this.ghostPublishers.delete(t));
2110
+ } catch (e) {
2111
+ n.push(e);
2112
+ }
2113
+ for (let t of [...this.ghostOutbounds]) try {
2114
+ let n = e || t.owner.status() === "failed" || t.owner.status() === "closing";
2115
+ if (!n) try {
2116
+ if (await t.current(), t.destination) {
2117
+ let e = t.destination, r = await Y(this.directory.observeOwnership(e.cell.roomId, t.tenantId));
2118
+ r && r.hostId === e.target.hostId && r.epoch === e.cell.epoch && r.state === "live" || (n = !0), await this.assertWorldGhostPeer(e.target);
2119
+ }
2120
+ } catch {
2121
+ n = !0;
2122
+ }
2123
+ n && await t.owner.close();
2124
+ } catch (e) {
2125
+ n.push(e);
2126
+ }
2127
+ for (let t of [...this.ghostTransports]) try {
2128
+ let n = e || t.signal.aborted || this.ghostReceivers.get(t.hello.roomId)?.receiver !== t.receiver;
2129
+ if (!n) {
2130
+ let e = await Y(this.directory.observeOwnership(t.hello.roomId, t.hello.tenantId));
2131
+ n = !e || e.hostId !== this.host.id || e.epoch !== t.hello.epoch || e.state !== "live";
2132
+ try {
2133
+ await this.assertWorldGhostPeer(t.hello.source);
2134
+ } catch {
2135
+ n = !0;
2136
+ }
2137
+ }
2138
+ n && await t.close();
2139
+ } catch (e) {
2140
+ n.push(e);
2141
+ }
2142
+ for (let [r, i] of [...this.ghostReceivers]) try {
2143
+ let n = await Y(this.directory.observeOwnership(r, i.tenantId)), a = V(n, {
2144
+ roomId: r,
2145
+ tenantId: i.tenantId,
2146
+ hostId: this.host.id,
2147
+ epoch: i.epoch
2148
+ }), o = await Y(e || a ? i.receiver.close() : i.receiver.runDue());
2149
+ if ((e || a) && (o.retained !== 0 || o.deferred.length !== 0)) throw new t({ detail: "Host ghost cleanup retains unacknowledged projections" });
2150
+ } catch (e) {
2151
+ n.push(e);
2152
+ }
2153
+ if (!e && !this.closing && !this.closed) {
2154
+ try {
2155
+ await this.acquireWorldGhostCells();
2156
+ } catch (e) {
2157
+ n.push(e);
2158
+ }
2159
+ for (let e of [...this.ghostPublishers.values()]) try {
2160
+ await e.publisher.runDue();
2161
+ } catch (e) {
2162
+ n.push(e);
2163
+ }
2164
+ }
2165
+ if (n.length) throw AggregateError(n, "Host ghost receiver lifecycle remains incomplete");
2166
+ }
2167
+ removeWorldNeighborGhost(e, t, n, r, a, o) {
2168
+ return this.capturedOperation(() => ({
2169
+ frame: h(r, o),
2170
+ peer: h(a, 1024)
2171
+ }), async (r) => {
2172
+ let a = await Y(this.directory.observeOwnership(e, t));
2173
+ if (V(a, {
2174
+ roomId: e,
2175
+ tenantId: t,
2176
+ hostId: this.host.id,
2177
+ epoch: n
2178
+ })) return;
2179
+ let s = this.worldNeighborGhostInput(e, t, n, r.frame, r.peer, o), c = async () => {
2180
+ let r = await Y(this.directory.observeOwnership(e, t));
2181
+ if (!r || r.hostId !== this.host.id || r.epoch !== n || r.state !== "live") throw new i({ roomId: e });
2182
+ };
2183
+ await c(), await this.runtime.cancelWorldGhost(e, t, s, o, c), await this.runtime.persist(e), await c();
2184
+ }, !0);
2185
+ }
2186
+ configureWorldBoundaryCells(e, n) {
2187
+ return this.operation(async () => {
2188
+ if (this.closing || this.closed || typeof n != "function" || this.boundaryCellFactories.has(e) || !this.options.worlds?.some((t) => t.name === e)) throw new t({ detail: "Boundary cells require one declared World factory" });
2189
+ this.boundaryCellFactories.set(e, n);
2190
+ }, !0);
2191
+ }
2192
+ async acquireWorldBoundaryCells() {
2193
+ if (!this.activated || this.closing || this.closed || !this.boundaryCellFactories.size) return;
2194
+ let e = [];
2195
+ for (let [n, r] of [...this.owned]) if (r.published && r.descriptor.world?.movement && this.boundaryCoordinators.get(n)?.owned !== r) {
2196
+ for (let [a, o] of this.boundaryCellFactories) if (this.options.worlds?.find((e) => e.name === a)?.zones.some((e) => e.room === r.descriptor.name)) try {
2197
+ let e = await this.worldOperation(async () => {
2198
+ if (this.owned.get(n) !== r || !r.published) throw new i({ roomId: n });
2199
+ await this.synchronizeWorldCell(n, r);
2200
+ let e = await Y(D(this.store, {
2201
+ worlds: this.options.worlds,
2202
+ epochNow: this.options.epochNow,
2203
+ maxListedCells: 1,
2204
+ authorize: () => G.sync(() => {
2205
+ if (this.owned.get(n) !== r || !r.published) throw new i({ roomId: n });
2206
+ })
2207
+ }).observeRoom({
2208
+ tenantId: r.listing.tenantId,
2209
+ worldId: a,
2210
+ roomId: n
2211
+ }));
2212
+ if (e && (e.cell.hostId !== this.host.id || e.cell.epoch !== r.listing.epoch)) throw new i({ roomId: n });
2213
+ return e;
2214
+ });
2215
+ if (!e) continue;
2216
+ let { cell: c, at: l } = e, u = Object.freeze({
2217
+ worldId: a,
2218
+ zoneId: c.zoneId,
2219
+ roomId: n,
2220
+ epoch: c.epoch,
2221
+ layer: c.layer,
2222
+ at: l
2223
+ }), d = o(Object.freeze({
2224
+ tenantId: c.tenantId,
2225
+ source: u
2226
+ }));
2227
+ if (d instanceof Promise) throw d.catch(() => void 0), new t({ detail: "Boundary cell factories must be synchronous" });
2228
+ if (s(d, ["executor", "policy"], ["executor", "policy"]), this.owned.get(n) !== r || this.closing || !r.published) throw new i({ roomId: n });
2229
+ await this.ownWorldBoundaryCoordinator(n, c.tenantId, c.epoch, a, d.executor, d.policy);
2230
+ break;
2231
+ } catch (t) {
2232
+ e.push(t);
2233
+ }
2234
+ }
2235
+ if (e.length) throw AggregateError(e, "World boundary cell acquisition remains incomplete");
2236
+ }
2237
+ ownWorldBoundaryCoordinator(e, n, r, a, o, c) {
2238
+ return this.capturedWorldOperation(() => {
2239
+ let e = [
2240
+ "maxPending",
2241
+ "maxEntriesPerTurn",
2242
+ "maxBytes",
2243
+ "prepareTtlMs"
2244
+ ];
2245
+ s(c, e, e);
2246
+ for (let e of [
2247
+ "prepare",
2248
+ "commit",
2249
+ "cancel",
2250
+ "resume",
2251
+ "status"
2252
+ ]) {
2253
+ let n = Object.getOwnPropertyDescriptor(o, e);
2254
+ if (!n || !("value" in n) || typeof n.value != "function") throw new t({ detail: "Boundary owner requires own executor capabilities" });
2255
+ }
2256
+ return {
2257
+ policy: { ...c },
2258
+ executor: {
2259
+ prepare: o.prepare.bind(o),
2260
+ commit: o.commit.bind(o),
2261
+ cancel: o.cancel.bind(o),
2262
+ resume: o.resume.bind(o),
2263
+ status: o.status.bind(o)
2264
+ }
2265
+ };
2266
+ }, async (o) => {
2267
+ let s = this.requireOwned(e, n), c = this.options.worlds?.find((e) => e.name === a);
2268
+ if (!s.published || s.listing.epoch !== r || !s.descriptor.world?.movement || !c || !c.zones.some((e) => e.room === s.descriptor.name) || this.boundaryCoordinators.has(e) || !this.options.worldEntities?.transitions?.scanSourceTransitions) throw new i({ roomId: e });
2269
+ let l = fe(this, o.executor, {
2270
+ ...o.policy,
2271
+ tenantId: n,
2272
+ roomId: e,
2273
+ epoch: r,
2274
+ world: c,
2275
+ epochNow: this.options.epochNow
2276
+ }), u = {
2277
+ owned: s,
2278
+ coordinator: l
2279
+ };
2280
+ return this.boundaryCoordinators.set(e, u), Object.freeze({
2281
+ observation: l.observation,
2282
+ runDue: () => P() || this.owned.get(e) !== s || this.closing || this.closed ? Promise.reject(new t({ detail: "Boundary work requires its current owner outside command delivery" })) : l.runDue(),
2283
+ close: async () => {
2284
+ if (P()) throw new t({ detail: "Boundary cleanup must run outside command delivery" });
2285
+ await l.close(), this.boundaryCoordinators.get(e) === u && this.boundaryCoordinators.delete(e);
2286
+ }
2287
+ });
2288
+ });
2289
+ }
2290
+ runWorldBoundaries(e) {
2291
+ let t = this.boundaryMaintenance;
2292
+ if (t && !e) return t;
2293
+ let n = Promise.resolve().then(async () => {
2294
+ t && await t.catch(() => void 0);
2295
+ let n = [];
2296
+ for (let [t, r] of [...this.boundaryCoordinators]) try {
2297
+ let n = e ? null : await Y(this.directory.observeOwnership(t, r.owned.listing.tenantId));
2298
+ (e || this.closing || this.closed || r.coordinator.observation().closed || this.owned.get(t) !== r.owned || !r.owned.published || !n || n.hostId !== this.host.id || n.epoch !== r.owned.listing.epoch || n.state !== "live") && (await r.coordinator.close(), this.boundaryCoordinators.get(t) === r && this.boundaryCoordinators.delete(t));
2299
+ } catch (e) {
2300
+ n.push(e);
2301
+ }
2302
+ if (!e && !this.closing && !this.closed) {
2303
+ try {
2304
+ await this.acquireWorldBoundaryCells();
2305
+ } catch (e) {
2306
+ n.push(e);
2307
+ }
2308
+ for (let e of [...this.boundaryCoordinators.values()]) try {
2309
+ await e.coordinator.runDue();
2310
+ } catch (e) {
2311
+ n.push(e);
2312
+ }
2313
+ }
2314
+ if (n.length) throw AggregateError(n, "Host boundary coordination remains incomplete");
2315
+ });
2316
+ return this.boundaryMaintenance = n, n.then(() => {
2317
+ this.boundaryMaintenance === n && (this.boundaryMaintenance = void 0);
2318
+ }, () => {
2319
+ this.boundaryMaintenance === n && (this.boundaryMaintenance = void 0);
2320
+ }), n;
2321
+ }
2322
+ scanWorldSourceTransitions(e, t, n, r, a, o) {
2323
+ return this.worldOperation(async () => {
2324
+ let s = this.requireOwned(e, t), c = this.options.worldEntities?.transitions?.scanSourceTransitions;
2325
+ if (!s.published || s.listing.epoch !== n || !s.descriptor.world || !c || !this.options.worlds?.some((e) => e.name === r && e.zones.some((e) => e.room === s.descriptor.name))) throw new i({ roomId: e });
2326
+ let l = await Y(c({
2327
+ roomId: e,
2328
+ tenantId: t,
2329
+ epoch: n,
2330
+ worldId: r,
2331
+ hostId: this.host.id,
2332
+ maxRows: a,
2333
+ maxBytes: o
2334
+ })), u = await Y(this.directory.observeOwnership(e, t));
2335
+ if (this.owned.get(e) !== s || !u || u.hostId !== this.host.id || u.epoch !== n || u.state !== "live") throw new i({ roomId: e });
2336
+ return l;
2337
+ });
2338
+ }
2339
+ captureWorldBoundaryIntents(e, n, r, a) {
2340
+ return this.worldOperation(async () => {
2341
+ let o = this.requireOwned(e, n), s = this.options.worldEntities, c = this.options.worlds?.find((e) => e.name === a);
2342
+ if (!o.published || o.listing.epoch !== r || !o.descriptor.world?.movement || !s?.admitActorProjection || !c) throw new i({ roomId: e });
2343
+ if (!this.runtime.worldMovementSnapshot(e, n, r).bound) return Object.freeze({
2344
+ epoch: r,
2345
+ tick: 0,
2346
+ intents: Object.freeze([])
2347
+ });
2348
+ let l = await this.runtime.captureWorldMovement(e, n, r), u = [];
2349
+ for (let i of l.intents) {
2350
+ let o = {
2351
+ tenantId: n,
2352
+ entityId: i.entityId,
2353
+ roomId: e,
2354
+ hostId: this.host.id,
2355
+ epoch: r
2356
+ }, l = await Y(s.admitActorProjection(o)), d = c.zones.find((e) => e.id === l.zoneId);
2357
+ if (!d || l.worldId !== a || l.roomId !== e || l.epoch !== r || S(c, {
2358
+ zone: d.id,
2359
+ at: i.sourceAt
2360
+ }).id !== l.cellId) throw new t({ detail: "Boundary intention lost its actual source cell" });
2361
+ let f = c.zones.filter((e) => (e.id === d.id || d.neighbors.includes(e.id)) && i.targetAt[0] >= e.bounds[0][0] && i.targetAt[0] < e.bounds[1][0] && i.targetAt[1] >= e.bounds[0][1] && i.targetAt[1] < e.bounds[1][1]);
2362
+ if (!f.length) continue;
2363
+ if (f.length !== 1) throw new t({ detail: "Boundary intention has ambiguous neighboring zones" });
2364
+ if (S(c, {
2365
+ zone: f[0].id,
2366
+ at: i.targetAt
2367
+ }).id === l.cellId && f[0].id === d.id) continue;
2368
+ let p = await Y(s.admitActorProjection(o));
2369
+ if (p.revision !== l.revision || p.worldId !== l.worldId || p.zoneId !== l.zoneId || p.cellId !== l.cellId || p.layer !== l.layer || p.roomId !== e || p.epoch !== r) throw new t({ detail: "Boundary source ownership changed during observation" });
2370
+ u.push(Object.freeze({
2371
+ crossing: i.crossing,
2372
+ revision: l.revision,
2373
+ intention: Object.freeze({
2374
+ entityId: i.entityId,
2375
+ target: Object.freeze({
2376
+ kind: "cell",
2377
+ zone: f[0].id,
2378
+ at: i.targetAt
2379
+ }),
2380
+ options: Object.freeze({
2381
+ mode: "seamless",
2382
+ reason: "boundary",
2383
+ crossPool: !1
2384
+ })
2385
+ })
2386
+ }));
2387
+ }
2388
+ let d = await this.runtime.captureWorldMovement(e, n, r);
2389
+ if (d.tick !== l.tick || JSON.stringify(d.intents) !== JSON.stringify(l.intents)) throw new t({ detail: "Boundary movement changed while checking SQL admission" });
2390
+ return Object.freeze({
2391
+ epoch: r,
2392
+ tick: l.tick,
2393
+ intents: Object.freeze(u)
2394
+ });
2395
+ });
2396
+ }
2397
+ listWorldGhostEntityIds(e, t, n, r, a) {
2398
+ return this.worldOperation(async () => {
2399
+ let o = this.requireOwned(e, t);
2400
+ if (!o.published || o.listing.epoch !== n || !o.descriptor.world) throw new i({ roomId: e });
2401
+ let s = async () => {
2402
+ let r = await Y(this.directory.observeOwnership(e, t));
2403
+ if (!r || r.hostId !== this.host.id || r.epoch !== n || r.state !== "live") throw new i({ roomId: e });
2404
+ };
2405
+ await s();
2406
+ let c = await this.runtime.listWorldEntityIds(e, t, n, r, a);
2407
+ return await s(), c;
2408
+ });
2409
+ }
2410
+ captureWorldGhostSource(e, n, r, a, o, s) {
2411
+ return this.worldOperation(async () => {
2412
+ let c = this.requireOwned(e, n), l = this.options.worldEntities;
2413
+ if (!c.published || c.listing.epoch !== r || c.descriptor.mode === "lockstep" || !c.descriptor.world || !l?.admitActorProjection || typeof s != "function" || this.options.worldSnapshotMaxBytes === void 0 || !Number.isSafeInteger(o) || o < 1 || o > this.options.worldSnapshotMaxBytes) throw new i({ roomId: e });
2414
+ let u = async () => {
2415
+ let i = l.admitActorProjection({
2416
+ tenantId: n,
2417
+ entityId: a,
2418
+ roomId: e,
2419
+ hostId: this.host.id,
2420
+ epoch: r
2421
+ });
2422
+ if (!G.isEffect(i)) throw new t({ detail: "Ghost source requires actual persisted projection admission" });
2423
+ let o = await Y(i);
2424
+ if (o.tenantId !== n || o.entityId !== a || o.roomId !== e || o.epoch !== r) throw new t({ detail: "Ghost source admission escaped its actual actor" });
2425
+ return o;
2426
+ }, d = await u(), f = await this.runtime.captureWorldProjection(e, n, r, a, o), p = s(f.entity);
2427
+ if (p instanceof Promise) throw p.catch(() => void 0), new t({ detail: "Ghost position projection must be synchronous" });
2428
+ let m = h(p, 128), g = this.options.worlds?.find((e) => e.name === d.worldId);
2429
+ if (!g || S(g, {
2430
+ zone: d.zoneId,
2431
+ at: m
2432
+ }).id !== d.cellId) throw new t({ detail: "Ghost position escaped its still-authoritative source cell" });
2433
+ let _ = A(c.descriptor.state, {
2434
+ maxBytes: o,
2435
+ maxFieldId: Math.min(4096, o * 7),
2436
+ maxCollectionLength: Math.min(16384, o)
2437
+ }), v = _.full(f.entity);
2438
+ if (K.isFailure(v)) throw v.failure;
2439
+ let y = O({
2440
+ schemaHash: _.schemaHash,
2441
+ bytes: Array.from(v.success),
2442
+ entity: f.entity
2443
+ }, o), b = await u();
2444
+ if (b.revision !== d.revision || b.worldId !== d.worldId || b.zoneId !== d.zoneId || b.cellId !== d.cellId || b.layer !== d.layer) throw new t({ detail: "Ghost source changed while capturing actor bytes" });
2445
+ return h({
2446
+ source: {
2447
+ tenantId: n,
2448
+ worldId: d.worldId,
2449
+ zoneId: d.zoneId,
2450
+ layer: d.layer,
2451
+ roomId: e,
2452
+ hostId: this.host.id,
2453
+ epoch: r,
2454
+ at: m
2455
+ },
2456
+ entityId: a,
2457
+ revision: d.revision,
2458
+ tick: f.tick,
2459
+ snapshot: y
2460
+ }, o);
2461
+ });
2462
+ }
2463
+ captureWorldEntity(e, t, n, r, a) {
2464
+ return this.worldOperation(async () => {
2465
+ let o = this.requireOwned(e, t);
2466
+ if (!o.published || o.listing.epoch !== n || o.descriptor.mode === "lockstep" || !o.descriptor.world) throw new i({ roomId: e });
2467
+ let s = async () => {
2468
+ let r = await Y(this.directory.observeOwnership(e, t));
2469
+ if (!r || r.hostId !== this.host.id || r.epoch !== n || r.state !== "live") throw new i({ roomId: e });
2470
+ };
2471
+ await s();
2472
+ let c = await this.runtime.captureWorldEntity(e, t, n, r, a);
2473
+ return await s(), c;
2474
+ });
2475
+ }
2476
+ adopt(r, a, o) {
2477
+ return this.operation(async () => {
2478
+ let s = this.options.ports?.recovery;
2479
+ if (!s) throw new t({ detail: "Room adoption requires the actual recovery port" });
2480
+ let c = this.owned.get(r);
2481
+ if (!c && this.owned.size >= this.options.capacity) throw new e({
2482
+ budget: "retainedHostRooms",
2483
+ limit: this.options.capacity
2484
+ });
2485
+ let l = await Y(s.claim(this.host.id, r, a, o));
2486
+ if (l.listing.hostId !== this.host.id || l.listing.id !== r || l.listing.tenantId !== a || l.listing.epoch !== o + 1) throw new t({ detail: "Recovery port returned an unrelated ownership claim" });
2487
+ if (re(this.options.pools, l.listing.name, a, l.listing.pool, this.host.pool, this.host.region), l.mode === "lockstep") {
2488
+ await this.installLockstepSuccessor(l), await this.runtime.publishLockstep(r);
2489
+ let e = this.requireOwned(r, a);
2490
+ return e.published = !0, Object.freeze({
2491
+ roomId: r,
2492
+ epoch: e.listing.epoch,
2493
+ recoveredTick: l.recoveredTick,
2494
+ ticksLost: null
2495
+ });
2496
+ }
2497
+ if (l.checkpoint.roomId !== r || l.checkpoint.tenantId !== a || l.checkpoint.epoch > l.listing.epoch) throw new t({ detail: "Recovery port returned an unrelated state checkpoint" });
2498
+ if (c && (c.listing.tenantId !== a || c.listing.epoch !== l.listing.epoch)) throw new n({ roomId: r });
2499
+ let u = this.options.worlds?.some((e) => e.zones.some((e) => e.room === l.listing.name) || e.instances.some((e) => e.room === l.listing.name)) === !0, d = async () => {
2500
+ if (!u) return;
2501
+ let e = this.options.worldEntities;
2502
+ if (!e || typeof e.recoverRoom != "function") throw new t({ detail: "World Room adoption requires actual entity recovery authority" });
2503
+ let n = l.checkpoint.worldRecoveryEpoch ?? Math.min(l.checkpoint.epoch, o), i = Object.freeze({
2504
+ tenantId: a,
2505
+ roomId: r,
2506
+ hostId: this.host.id,
2507
+ priorEpoch: o,
2508
+ epoch: l.listing.epoch,
2509
+ worldRecoveryEpoch: n
2510
+ });
2511
+ await ue(i, (e, t, i, s, c) => this.applyWorldSourceTransitionOwned(r, a, l.listing.epoch, {
2512
+ origin: e,
2513
+ operation: "rollback"
2514
+ }, t, i, s, o, n, c), async (n) => {
2515
+ let r = e.recoverRoom(i, n);
2516
+ if (!G.isEffect(r)) throw new t({ detail: "World entity recovery must return an actual Effect" });
2517
+ await Y(r);
2518
+ });
2519
+ };
2520
+ if (u && !this.options.worldEntities) throw new t({ detail: "World Room adoption requires actual entity recovery authority" });
2521
+ if (!c) {
2522
+ let e = this.catalog.get(l.listing.name);
2523
+ if (e.mode === "lockstep") throw new t({ detail: "Lockstep ownership adoption requires its SQL journal runtime binding" });
2524
+ if (l.listing.maxClients !== e.maxClients) throw new t({ detail: "Recovered Room capacity no longer matches its descriptor" });
2525
+ let n = q.decodeUnknownSync(e.options)(l.options), o = C(q.encodeSync(e.options)(n)), s = await Y(z(this.geometry, {
2526
+ roomId: r,
2527
+ tenantId: a,
2528
+ hostId: this.host.id,
2529
+ epoch: l.listing.epoch,
2530
+ name: e.name
2531
+ }));
2532
+ try {
2533
+ if (s) {
2534
+ let e = await Y(this.directory.observeOwnership(r, a));
2535
+ if (V(e, {
2536
+ roomId: r,
2537
+ tenantId: a,
2538
+ hostId: this.host.id,
2539
+ epoch: l.listing.epoch
2540
+ }) || e?.state !== "creating" && e?.state !== "live") throw new i({ roomId: r });
2541
+ }
2542
+ this.runtime.restore(l.checkpoint, e, n, l.listing.epoch, this.reservationsFor().admission, {
2543
+ epochNow: this.options.epochNow,
2544
+ secrets: this.options.secrets,
2545
+ seatToken: this.seatToken,
2546
+ authorizeWorldTarget: this.authorizeWorldTarget,
2547
+ ...this.options.resolveWorldPlayer ? { authorizeWorldPlayer: this.authorizeWorldPlayer } : {},
2548
+ ...s ? { geometry: s } : {},
2549
+ spectatorGroup: this.spectatorGroup(e, r, a, l.listing.epoch),
2550
+ replayRecording: this.replayRecordings?.(Object.freeze({
2551
+ roomId: r,
2552
+ tenantId: a,
2553
+ name: e.name,
2554
+ epoch: l.listing.epoch
2555
+ }))
2556
+ }, !0), this.owned.set(r, {
2557
+ listing: l.listing,
2558
+ descriptor: e,
2559
+ optionFingerprint: o,
2560
+ private: l.private,
2561
+ published: !1,
2562
+ ...s ? { geometry: s } : {}
2563
+ });
2564
+ } catch (e) {
2565
+ if (s) {
2566
+ this.pendingGeometryCleanup.set(r, {
2567
+ listing: l.listing,
2568
+ geometry: s,
2569
+ abandonCreation: !1
2570
+ });
2571
+ try {
2572
+ await this.cleanupGeometry();
2573
+ } catch (t) {
2574
+ throw AggregateError([e, t], "Successor geometry cleanup remains retained without abandoning SQL recovery");
2575
+ }
2576
+ }
2577
+ throw e;
2578
+ }
2579
+ }
2580
+ let f = this.requireOwned(r, a);
2581
+ if (f.published) await d(), await this.synchronizeWorldCell(r, f);
2582
+ else {
2583
+ if (this.runtime.isPublicationHeld(r)) {
2584
+ let e = await Y(this.directory.observeOwnership(r, a));
2585
+ if (!e || e.hostId !== this.host.id || e.epoch !== l.listing.epoch || !["creating", "live"].includes(e.state)) throw new i({ roomId: r });
2586
+ u && e.state === "creating" && await this.runtime.persist(r), await d(), u && e.state === "creating" && await this.retireTerminalWorldReceipts(r, a, l.listing.epoch, !0), await this.runtime.publishHeld(r, d);
2587
+ } else await d(), await this.runtime.persist(r), await d();
2588
+ await this.synchronizeWorldCell(r, f), f.published = !0;
2589
+ }
2590
+ return Object.freeze({
2591
+ roomId: r,
2592
+ epoch: f.listing.epoch,
2593
+ recoveredTick: l.recoveredTick,
2594
+ ticksLost: null
2595
+ });
2596
+ });
2597
+ }
2598
+ async join(e, t, n, a) {
2599
+ t = structuredClone(t), n = structuredClone(n);
2600
+ let s = await this.operation(async () => {
2601
+ let r = this.catalog.get(e), i = await this.authorize(r, n, {
2602
+ name: e,
2603
+ options: t
2604
+ }), a = q.decodeUnknownSync(r.options)(t), o = r.mode === "lockstep" ? Buffer.from(l(r.simulation).encode(t)).toString("base64url") : C(q.encodeSync(r.options)(a));
2605
+ return [...this.owned.values()].filter((t) => t.published && !t.private && t.listing.name === e && t.listing.tenantId === i.tenantId && t.optionFingerprint === o && (t.descriptor.mode !== "lockstep" || this.runtime.lockstepRosterOpen(t.listing.id))).map((e) => e.listing.id).sort();
2606
+ });
2607
+ for (let e of s) try {
2608
+ return await this.reserve(e, n, "player", a);
2609
+ } catch (e) {
2610
+ if (!(e instanceof r || e instanceof o || e instanceof i)) throw e;
2611
+ }
2612
+ return this.create(e, t, n, {}, a);
2613
+ }
2614
+ reservationsFor(e, t = !1) {
2615
+ return Je(this.store, {
2616
+ secrets: this.options.secrets,
2617
+ epochNow: this.options.epochNow,
2618
+ worlds: this.options.worlds,
2619
+ seatToken: this.seatToken,
2620
+ seatTtlMs: this.options.seatTtlMs,
2621
+ graceMs: (e) => {
2622
+ let t = this.owned.get(e);
2623
+ if (!t) throw new i({ roomId: e });
2624
+ return t.descriptor.reconnect.graceMs;
2625
+ },
2626
+ hostHeartbeatTtlMs: this.options.heartbeatTtlMs,
2627
+ ownerHostId: this.host.id,
2628
+ authorize: (r, a) => G.tryPromise({
2629
+ try: async () => {
2630
+ if (!e) throw new n({ roomId: r });
2631
+ let o = this.requireOwned(r, a.tenantId);
2632
+ if (!o.published || !t && o.descriptor.mode === "lockstep" && !this.runtime.lockstepRosterOpen(r)) throw new i({ roomId: r });
2633
+ let s = await this.authorize(o.descriptor, e, { roomId: r }, r);
2634
+ if (s.subjectId !== a.subjectId || s.tenantId !== a.tenantId) throw new n({ roomId: r });
2635
+ },
2636
+ catch: () => new n({ roomId: r })
2637
+ })
2638
+ });
2639
+ }
2640
+ reserve(e, n, r = "player", a) {
2641
+ return this.capturedOperation(() => ({
2642
+ subject: structuredClone(n),
2643
+ attributes: a === void 0 ? void 0 : u(e, a)
2644
+ }), async ({ subject: n, attributes: a }) => {
2645
+ let o = X(n), s = this.requireOwned(e, o.tenantId);
2646
+ if (!s.published || s.descriptor.mode === "lockstep" && !this.runtime.lockstepRosterOpen(e)) throw new i({ roomId: e });
2647
+ if (s.descriptor.mode === "lockstep" && r !== "player") throw new t({ detail: "Lockstep initial roster cannot reserve spectator seats" });
2648
+ return await this.authorize(s.descriptor, n, {
2649
+ roomId: e,
2650
+ role: r
2651
+ }, e), Y(this.reservationsFor(n).reserve(e, o, r, a));
2652
+ });
2653
+ }
2654
+ resume(e, t, n) {
2655
+ return this.capturedOperation(() => ({
2656
+ subject: structuredClone(t),
2657
+ attributes: n === void 0 ? void 0 : u(e, n)
2658
+ }), async ({ subject: t, attributes: n }) => {
2659
+ let r = X(t);
2660
+ return Y(this.reservationsFor(t, !0).resume(e, r, n));
2661
+ });
2662
+ }
2663
+ leave(e, t, n) {
2664
+ return this.capturedOperation(() => {
2665
+ if (!(t instanceof Uint8Array) || t.byteLength < 1 || t.byteLength > 8192) throw Error("Invalid withdrawal bytes");
2666
+ return {
2667
+ token: Uint8Array.from(t),
2668
+ subject: structuredClone(n)
2669
+ };
2670
+ }, async ({ token: t, subject: n }) => {
2671
+ let r = X(n), i = await Y(this.reservationsFor().release(e, t, r));
2672
+ return i !== null && await this.runtime.leaveSession(i, e), { ok: !0 };
2673
+ }, !0);
2674
+ }
2675
+ list(e, t, n = 64) {
2676
+ return this.capturedOperation(() => structuredClone(t), async (t) => {
2677
+ let r = this.catalog.get(e), i = await this.authorize(r, t, { name: e });
2678
+ return (await Y(this.directory.list(i.tenantId, e, n))).filter((e) => e.hostId === this.host.id && this.owned.get(e.id)?.published);
2679
+ });
2680
+ }
2681
+ async verifySeat(e, r) {
2682
+ if (!this.activated || this.closing || this.closed) throw new i({ roomId: "host" });
2683
+ let a = ne(e, this.options.secrets, this.options.epochNow(), this.seatToken.verify), o = this.requireOwned(a.roomId, a.tenantId);
2684
+ if (!o.published || o.listing.epoch !== a.epoch) throw new n({ roomId: a.roomId });
2685
+ let s = await Y(this.options.resolveSubject(a), r), c = await this.authorize(o.descriptor, s, {
2686
+ roomId: a.roomId,
2687
+ sessionId: a.sessionId,
2688
+ role: a.role
2689
+ }, a.roomId, r);
2690
+ if (r?.aborted) throw new t({ detail: "Room gateway admission was cancelled" });
2691
+ if (c.tenantId !== a.tenantId || c.subjectId !== a.subjectId) throw new n({ roomId: a.roomId });
2692
+ if (await w(this.store, c), r?.aborted) throw new t({ detail: "Room gateway admission was cancelled" });
2693
+ return a;
2694
+ }
2695
+ connect(e, t, r) {
2696
+ if (!this.activated || this.closing || this.closed) throw new i({ roomId: e.roomId });
2697
+ let a = this.requireOwned(e.roomId, e.tenantId);
2698
+ if (!a.published || a.listing.epoch !== e.epoch) throw new n({ roomId: e.roomId });
2699
+ let o = this.runtime.connect(e.roomId, t);
2700
+ return o.admitFirstFrame(r), o;
2701
+ }
2702
+ turn() {
2703
+ if (P()) return Promise.reject(new t({ detail: "Host lifecycle cannot run inside command delivery" }));
2704
+ if (!this.activated && !this.closing && !this.closed) return Promise.resolve(0);
2705
+ let e;
2706
+ return this.runWorldBoundaries(!1).catch((t) => {
2707
+ e = t;
2708
+ }).then(() => this.runWorldGhostReceivers(!1)).then(() => this.operation(async () => {
2709
+ await this.cleanupUninstalledCreations(), await this.cleanupGeometry(), await this.reconcileOwnership();
2710
+ for (let e of this.owned.keys()) this.runtime.isPublicationHeld(e) || await this.runtime.synchronizeGeometry(e);
2711
+ this.options.worldPersistence && await Y(this.options.worldPersistence.runDue());
2712
+ let t = [];
2713
+ for (let [e, n] of this.owned) if (n.published && n.descriptor.mode !== "lockstep" && n.descriptor.world) try {
2714
+ await this.retireTerminalWorldReceipts(e, n.listing.tenantId, n.listing.epoch);
2715
+ } catch (e) {
2716
+ t.push(e);
2717
+ }
2718
+ for (let [e, n] of this.owned) if (!this.runtime.isPublicationHeld(e)) try {
2719
+ await this.delivery.deliver(e, n.listing.tenantId);
2720
+ } catch (e) {
2721
+ t.push(e);
2722
+ }
2723
+ for (let [e, n] of this.owned) if (n.published && n.descriptor.mode === "lockstep") try {
2724
+ await this.runtime.prepareLockstepInitialRoster(e, this.lockstepInitial);
2725
+ } catch (e) {
2726
+ t.push(e);
2727
+ }
2728
+ for (let [e, n] of this.owned) if (n.published && n.descriptor.mode !== "lockstep" && n.descriptor.world?.movement && this.runtime.worldFinalizationRequest(e, n.listing.tenantId, n.listing.epoch) === null) try {
2729
+ await this.bindWorldCellMovement(e, n);
2730
+ } catch (e) {
2731
+ t.push(e);
2732
+ }
2733
+ let n = 0;
2734
+ try {
2735
+ n = await this.runtime.turn();
2736
+ } catch (e) {
2737
+ t.push(e);
2738
+ }
2739
+ try {
2740
+ this.observeWorldBoundaryClamps();
2741
+ } catch (e) {
2742
+ t.push(e);
2743
+ }
2744
+ if (this.options.worldPersistence) try {
2745
+ await Y(this.options.worldPersistence.runDue());
2746
+ } catch (e) {
2747
+ t.push(e);
2748
+ }
2749
+ let r = new Set(this.runtime.host.activeRooms().map((e) => e.id));
2750
+ for (let [e, n] of [...this.owned]) {
2751
+ if (this.runtime.isPublicationHeld(e)) continue;
2752
+ let i = null;
2753
+ try {
2754
+ i = await this.delivery.deliver(e, n.listing.tenantId);
2755
+ } catch (e) {
2756
+ t.push(e);
2757
+ }
2758
+ if (!r.has(e)) {
2759
+ if (n.published = !1, this.runtime.isHibernating(e)) try {
2760
+ await Y(this.reservationsFor().sweepExpired(e, n.listing.tenantId));
2761
+ } catch (e) {
2762
+ t.push(e);
2763
+ }
2764
+ if (i === 0 && !this.runtime.retains(e)) {
2765
+ try {
2766
+ await this.synchronizeWorldCell(e, n);
2767
+ } catch (e) {
2768
+ t.push(e);
2769
+ continue;
2770
+ }
2771
+ await this.releaseGeometryReload(e), await this.releaseGeometryRollback(e), this.geometryReloads.delete(e), this.geometryRollbacks.delete(e), this.owned.delete(e);
2772
+ }
2773
+ } else if (!this.runtime.hasPendingCheckpoint(e)) {
2774
+ if (n.descriptor.mode === "lockstep" && !n.published) try {
2775
+ await this.runtime.publishLockstep(e);
2776
+ } catch (e) {
2777
+ t.push(e);
2778
+ continue;
2779
+ }
2780
+ try {
2781
+ await Y(this.reservationsFor().sweepExpired(e, n.listing.tenantId)), await this.runtime.synchronizeGeometry(e), await this.synchronizeWorldCell(e, n), n.published = !0;
2782
+ } catch (e) {
2783
+ n.published = !1, t.push(e);
2784
+ }
2785
+ }
2786
+ }
2787
+ let i = this.options.clock.now();
2788
+ if (i >= this.nextHeartbeatAt) {
2789
+ let e = this.runtime.metrics();
2790
+ await Y(this.directory.heartbeat(this.host.id, {
2791
+ rooms: e.ownedRooms,
2792
+ clients: e.sessions,
2793
+ cpu: this.options.measuredCpu()
2794
+ })), this.nextHeartbeatAt = i + this.options.heartbeatEveryMs;
2795
+ }
2796
+ if (t.length) throw AggregateError(t, "Room host control turn failed");
2797
+ if (await this.cells.refresh(this.store, this.cellOwners()), e) throw e;
2798
+ return n;
2799
+ }));
2800
+ }
2801
+ async bindWorldCellMovement(e, n) {
2802
+ let r = n.listing.tenantId, a = n.listing.epoch;
2803
+ await this.runtime.configureWorldCellMovement(e, r, a), await this.synchronizeWorldCell(e, n);
2804
+ let o = this.options.worlds?.filter((e) => e.zones.some((e) => e.room === n.descriptor.name)) ?? [];
2805
+ if (!o.length) {
2806
+ let t = this.options.worlds?.filter((e) => e.instances.some((e) => e.room === n.descriptor.name)) ?? [];
2807
+ t.length === 1 && await this.runtime.configureWorldCellMovement(e, r, a, t[0].map.bounds, 0);
2808
+ return;
2809
+ }
2810
+ let s = D(this.store, {
2811
+ worlds: o,
2812
+ epochNow: this.options.epochNow,
2813
+ maxListedCells: 1,
2814
+ authorize: () => G.sync(() => {
2815
+ if (this.owned.get(e) !== n || !n.published) throw new i({ roomId: e });
2816
+ })
2817
+ }), c, l = 0;
2818
+ for (let n of o) {
2819
+ let i = await Y(s.observeRoom({
2820
+ tenantId: r,
2821
+ worldId: n.name,
2822
+ roomId: e
2823
+ }));
2824
+ if (i) {
2825
+ if (c || i.cell.hostId !== this.host.id || i.cell.epoch !== a) throw new t({ detail: "World movement has ambiguous or foreign cell authority" });
2826
+ c = S(n, {
2827
+ zone: i.cell.zoneId,
2828
+ at: i.at
2829
+ }).bounds, l = n.handoff.marginUnits;
2830
+ }
2831
+ }
2832
+ c && await this.runtime.configureWorldCellMovement(e, r, a, c, l);
2833
+ }
2834
+ async synchronizeWorldCell(e, n) {
2835
+ n.descriptor.world && this.options.worlds?.length && (this.options.worlds.some((e) => e.instances.some((e) => e.room === n.descriptor.name)) ? await N(this.store, this.options.worlds, {
2836
+ tenantId: n.listing.tenantId,
2837
+ roomId: e,
2838
+ hostId: this.host.id,
2839
+ epoch: n.listing.epoch
2840
+ }, this.options.epochNow, () => {
2841
+ if (this.owned.get(e) !== n) throw new t({ detail: "Instance lifecycle lost its retained Host actor" });
2842
+ }) : await Y(D(this.store, {
2843
+ worlds: this.options.worlds,
2844
+ epochNow: this.options.epochNow,
2845
+ maxListedCells: 1,
2846
+ authorize: (r, i) => G.sync(() => {
2847
+ if (this.owned.get(e) !== n || i.tenantId !== n.listing.tenantId || !this.options.worlds.some((e) => e.name === i.worldId && e.zones.some((e) => e.room === n.descriptor.name))) throw new t({ detail: "World lifecycle requires the actual retained Host Room and catalogue" });
2848
+ })
2849
+ }).synchronizeRoom({
2850
+ tenantId: n.listing.tenantId,
2851
+ roomId: e,
2852
+ hostId: this.host.id,
2853
+ epoch: n.listing.epoch
2854
+ })));
2855
+ }
2856
+ async reconcileOwnership() {
2857
+ for (let [e, t] of this.owned) {
2858
+ let n = await Y(this.directory.observeOwnership(e, t.listing.tenantId));
2859
+ V(n, {
2860
+ roomId: e,
2861
+ tenantId: t.listing.tenantId,
2862
+ hostId: this.host.id,
2863
+ epoch: t.listing.epoch
2864
+ }) && (t.published = !1, await this.runtime.withdrawOwnership(e, t.listing.tenantId, t.listing.epoch), await this.releaseGeometryReload(e), await this.releaseGeometryRollback(e), this.geometryReloads.delete(e), this.geometryRollbacks.delete(e), this.owned.delete(e));
2865
+ }
2866
+ }
2867
+ withdraw(e) {
2868
+ let n;
2869
+ try {
2870
+ n = Ye(e);
2871
+ } catch {
2872
+ return Promise.reject(new t({ detail: "Invalid room ownership withdrawal" }));
2873
+ }
2874
+ return this.operation(async () => {
2875
+ let e = await Y(this.directory.observeOwnership(n.roomId, n.tenantId));
2876
+ if (!e || e.roomId !== n.roomId || e.tenantId !== n.tenantId || e.hostId !== this.host.id || e.epoch !== n.withdrawnEpoch || e.state !== "disposed") throw new t({ detail: "Room withdrawal does not match its exact newer SQL authority" });
2877
+ let r = this.owned.get(n.roomId);
2878
+ if (r) {
2879
+ if (r.listing.tenantId !== n.tenantId || r.listing.epoch !== n.priorEpoch) throw new t({ detail: "Room withdrawal targets another retained actor epoch" });
2880
+ r.published = !1, await this.runtime.withdrawOwnership(n.roomId, n.tenantId, n.priorEpoch), await this.releaseGeometryReload(n.roomId), await this.releaseGeometryRollback(n.roomId), this.geometryReloads.delete(n.roomId), this.geometryRollbacks.delete(n.roomId), this.owned.delete(n.roomId);
2881
+ }
2882
+ }, !0);
2883
+ }
2884
+ drain(e) {
2885
+ if (P()) return Promise.reject(new t({ detail: "Host lifecycle cannot run inside command delivery" }));
2886
+ if (this.closed) return Promise.resolve();
2887
+ try {
2888
+ let n = je(e), { graceMs: r, maxCheckpointBytes: i } = n;
2889
+ if (this.plannedDrain) {
2890
+ if (this.plannedDrain.policy.graceMs !== r || this.plannedDrain.policy.maxCheckpointBytes !== i) throw new t({ detail: "Planned drain retry cannot change its retained policy" });
2891
+ } else {
2892
+ if (this.closing || this.closeTask || !this.host.membership || this.host.membership.instanceId === void 0) throw new t({ detail: "Planned drain requires its registered process before terminal shutdown" });
2893
+ let e = Object.freeze({
2894
+ hostId: this.host.id,
2895
+ instanceId: this.host.membership.instanceId,
2896
+ startedAt: this.host.membership.startedAt
2897
+ }), r = {
2898
+ ...n,
2899
+ epochNow: this.options.epochNow,
2900
+ snapshotBlobs: this.options.snapshotBlobs,
2901
+ snapshotCodec: (e) => new d(this.catalog.get(e).state),
2902
+ lockstep: { descriptor: (e) => {
2903
+ let t = this.catalog.get(e);
2904
+ return t.mode === "lockstep" ? t : void 0;
2905
+ } }
2906
+ }, i = (this.options.ports?.hostDrain ?? ((e, t) => Me(this.store, e, t)))(e, r), a = s(i, ["begin", "handoff"], ["begin", "handoff"]);
2907
+ if (typeof a.begin != "function" || typeof a.handoff != "function") throw new t({ detail: "Planned drain provider must supply both actual operations" });
2908
+ this.plannedDrain = {
2909
+ policy: n,
2910
+ port: Object.freeze({
2911
+ begin: i.begin.bind(i),
2912
+ handoff: i.handoff.bind(i)
2913
+ }),
2914
+ begun: !1,
2915
+ worldClosed: !1
2916
+ };
2917
+ }
2918
+ } catch (e) {
2919
+ return Promise.reject(e);
2920
+ }
2921
+ if (this.closeTask) return this.closeTask;
2922
+ this.closing = !0, this.activated = !1;
2923
+ let n = this.plannedDrain, r = this.runWorldBoundaries(!0).then(() => this.runWorldGhostReceivers(!0)).then(() => this.operation(async () => {
2924
+ let e = async (e) => {
2925
+ if (!G.isEffect(e)) throw new t({ detail: "Planned drain provider must return its actual Effect" });
2926
+ return Y(G.uninterruptible(e));
2927
+ };
2928
+ n.begun || (await e(n.port.begin()), n.begun = !0, this.routingFenced = !0), await this.cleanupUninstalledCreations(), await this.cleanupGeometry(), n.worldClosed ||= (this.options.worldPersistence && await Y(this.options.worldPersistence.close()), !0);
2929
+ let r = [];
2930
+ for (let [i, a] of this.owned) try {
2931
+ let r = this.plannedRooms.get(i);
2932
+ if (r && !r.boundary) {
2933
+ let e = await Y(this.directory.observeOwnership(i, a.listing.tenantId));
2934
+ if (V(e, {
2935
+ roomId: i,
2936
+ tenantId: a.listing.tenantId,
2937
+ hostId: this.host.id,
2938
+ epoch: a.listing.epoch
2939
+ })) {
2940
+ await this.runtime.withdrawOwnership(i, a.listing.tenantId, a.listing.epoch), await this.releasePlannedRoom(i);
2941
+ continue;
2942
+ }
2943
+ }
2944
+ if (!r) {
2945
+ let e = await Y(this.directory.observeOwnership(i, a.listing.tenantId));
2946
+ if (V(e, {
2947
+ roomId: i,
2948
+ tenantId: a.listing.tenantId,
2949
+ hostId: this.host.id,
2950
+ epoch: a.listing.epoch
2951
+ })) {
2952
+ await this.runtime.withdrawOwnership(i, a.listing.tenantId, a.listing.epoch), await this.releasePlannedRoom(i);
2953
+ continue;
2954
+ }
2955
+ if (this.runtime.isHibernating(i) && await Y(this.reservationsFor().sweepExpired(i, a.listing.tenantId)), await this.delivery.deliver(i, a.listing.tenantId) > 0) throw new t({ detail: "Planned drain retains accepted lifecycle commands; retry" });
2956
+ let n = await this.runtime.settleForDrain(i);
2957
+ if (await this.delivery.deliver(i, a.listing.tenantId) > 0) throw new t({ detail: "Planned drain retains terminal lifecycle commands; retry" });
2958
+ let o = await Y(this.directory.observeOwnership(i, a.listing.tenantId));
2959
+ if (V(o, {
2960
+ roomId: i,
2961
+ tenantId: a.listing.tenantId,
2962
+ hostId: this.host.id,
2963
+ epoch: a.listing.epoch
2964
+ }), n === "retired") {
2965
+ if (o.epoch !== a.listing.epoch || ![
2966
+ "disposed",
2967
+ "faulted",
2968
+ "hibernated"
2969
+ ].includes(o.state) || o.state !== "hibernated" && o.hostId !== this.host.id) throw new t({ detail: "Retired Room has no matching durable lifecycle boundary" });
2970
+ await this.synchronizeWorldCell(i, a), await this.releasePlannedRoom(i);
2971
+ continue;
2972
+ }
2973
+ if (o.hostId !== this.host.id || o.epoch !== a.listing.epoch || o.state !== "live") throw new t({ detail: "Active Room did not confirm its retained SQL publication" });
2974
+ a.published = !0, r = {
2975
+ boundary: null,
2976
+ commandsDrained: !1,
2977
+ handedOff: !1,
2978
+ notified: !1,
2979
+ withdrawn: !1
2980
+ }, this.plannedRooms.set(i, r);
2981
+ }
2982
+ if (!r.handedOff) {
2983
+ if (!r.commandsDrained) {
2984
+ if (await this.delivery.deliver(i, a.listing.tenantId) > 0) throw new t({ detail: "Planned drain retains bounded application delivery work; retry" });
2985
+ if (r.boundary ??= await this.runtime.prepareDrain(i), await this.delivery.deliver(i, a.listing.tenantId) > 0) throw new t({ detail: "Planned drain retains final checkpoint commands; retry" });
2986
+ r.commandsDrained = !0;
2987
+ }
2988
+ if (!r.boundary) throw new t({ detail: "Planned drain lost its retained boundary" });
2989
+ let o = await Y(this.directory.observeOwnership(i, a.listing.tenantId));
2990
+ if (!(V(o, {
2991
+ roomId: i,
2992
+ tenantId: a.listing.tenantId,
2993
+ hostId: this.host.id,
2994
+ epoch: a.listing.epoch
2995
+ }) && o.epoch > a.listing.epoch && o.hostId !== this.host.id && ["creating", "live"].includes(o.state))) {
2996
+ let o = s(await e(n.port.handoff(r.boundary)), [
2997
+ "hostId",
2998
+ "roomId",
2999
+ "tenantId",
3000
+ "epoch",
3001
+ "tick",
3002
+ "state"
3003
+ ], [
3004
+ "hostId",
3005
+ "roomId",
3006
+ "tenantId",
3007
+ "epoch",
3008
+ "tick",
3009
+ "state"
3010
+ ]);
3011
+ if (o.hostId !== this.host.id || o.roomId !== i || o.tenantId !== a.listing.tenantId || o.epoch !== a.listing.epoch || o.tick !== r.boundary.tick || o.state !== "orphaned") throw new t({ detail: "Planned handoff returned another ownership receipt" });
3012
+ }
3013
+ r.handedOff = !0, a.published = !1;
3014
+ }
3015
+ r.notified || (await this.runtime.notifyDrainMigration(i, n.policy.graceMs), r.notified = !0), r.withdrawn || (await this.runtime.withdrawOwnership(i, a.listing.tenantId, a.listing.epoch), r.withdrawn = !0), await this.releasePlannedRoom(i);
3016
+ } catch (e) {
3017
+ r.push(e);
3018
+ }
3019
+ if (r.length) throw AggregateError(r, "Planned Host drain retains incomplete Rooms");
3020
+ await this.runtime.close(), await Y(this.directory.unregister(this.host.id)), this.closed = !0;
3021
+ }, !0));
3022
+ return this.closeTask = r, r.then(() => {
3023
+ this.closeTask = null;
3024
+ }, () => {
3025
+ this.closeTask = null;
3026
+ }), r;
3027
+ }
3028
+ async releasePlannedRoom(e) {
3029
+ await this.releaseGeometryReload(e), await this.releaseGeometryRollback(e), this.geometryReloads.delete(e), this.geometryRollbacks.delete(e), this.owned.delete(e), this.plannedRooms.delete(e);
3030
+ }
3031
+ close() {
3032
+ if (P()) return Promise.reject(new t({ detail: "Host lifecycle cannot run inside command delivery" }));
3033
+ if (this.plannedDrain) return this.drain(this.plannedDrain.policy);
3034
+ if (this.closed) return Promise.resolve();
3035
+ if (this.closeTask) return this.closeTask;
3036
+ this.closing = !0, this.activated = !1;
3037
+ let e = this.runWorldBoundaries(!0).then(() => this.runWorldGhostReceivers(!0)).then(() => this.operation(async () => {
3038
+ this.routingFenced ||= (await Y(this.directory.setReady(this.host.id, !1)), !0), await this.cleanupUninstalledCreations(), await this.cleanupGeometry(), await this.reconcileOwnership();
3039
+ for (let e of this.geometryReloads.keys()) await this.releaseGeometryReload(e);
3040
+ for (let e of this.geometryRollbacks.keys()) await this.releaseGeometryRollback(e);
3041
+ let e = async () => {
3042
+ for (let [e, t] of this.owned) {
3043
+ for (; await this.delivery.deliver(e, t.listing.tenantId) > 0;);
3044
+ this.runtime.isHibernating(e) && await Y(this.reservationsFor().sweepExpired(e, t.listing.tenantId));
3045
+ }
3046
+ };
3047
+ await e();
3048
+ try {
3049
+ await this.runtime.close();
3050
+ } catch (t) {
3051
+ if (!(t instanceof a)) throw t;
3052
+ await e(), await this.runtime.close();
3053
+ }
3054
+ for (let [e, t] of this.owned) for (; await this.delivery.deliver(e, t.listing.tenantId) > 0;);
3055
+ for (let [e, t] of this.owned) await this.synchronizeWorldCell(e, t);
3056
+ this.options.worldPersistence && await Y(this.options.worldPersistence.close()), await Y(this.directory.unregister(this.host.id)), this.owned.clear(), this.geometryReloads.clear(), this.geometryRollbacks.clear(), this.closed = !0;
3057
+ }, !0));
3058
+ return this.closeTask = e, e.then(() => {
3059
+ this.closeTask = null;
3060
+ }, () => {
3061
+ this.closeTask = null;
3062
+ }), e;
3063
+ }
3064
+ cellOwners() {
3065
+ return [...this.owned].map(([e, t]) => ({
3066
+ roomId: e,
3067
+ tenantId: t.listing.tenantId,
3068
+ epoch: t.listing.epoch,
3069
+ name: t.descriptor.name,
3070
+ published: t.published
3071
+ }));
3072
+ }
3073
+ observeWorldBoundaryClamps() {
3074
+ let e = new Set(this.runtime.host.activeRooms().map((e) => e.id));
3075
+ for (let [n, r] of this.owned) if (e.has(n) && r.descriptor.mode !== "lockstep" && r.descriptor.world?.movement) {
3076
+ let e = this.runtime.worldMovementSnapshot(n, r.listing.tenantId, r.listing.epoch).clamped, i = e - (this.worldBoundaryObserved.get(r) ?? 0);
3077
+ if (!Number.isSafeInteger(i) || i < 0 || this.worldBoundaryClamps > 2 ** 53 - 1 - i) throw new t({ detail: "World boundary observation exceeded its monotonic Host counter" });
3078
+ this.worldBoundaryClamps += i, this.worldBoundaryObserved.set(r, e);
3079
+ }
3080
+ }
3081
+ metrics() {
3082
+ return {
3083
+ ...this.runtime.metrics(),
3084
+ worldBoundaryClamps: this.worldBoundaryClamps,
3085
+ worldHandoffs: this.options.worldEntities?.handoffMetrics?.(),
3086
+ cells: this.closing || !this.activated ? null : this.cells.snapshot(this.cellOwners()),
3087
+ queuedOperations: this.queued,
3088
+ closing: this.closing,
3089
+ ready: this.activated
3090
+ };
3091
+ }
3092
+ };
3093
+ export { $ as RoomHostController, Z as RoomHostControllerStartFailure };