@crowdedkingdoms/crowdyjs 17.14.0-dev.1 → 18.0.1-dev.1

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 (289) hide show
  1. package/MIGRATION.md +129 -1
  2. package/README.md +97 -164
  3. package/dist/crowdy-client.d.ts +12 -31
  4. package/dist/crowdy-client.d.ts.map +1 -1
  5. package/dist/crowdy-client.js +15 -37
  6. package/dist/crowdy-dsh/bridge.d.ts.map +1 -1
  7. package/dist/crowdy-dsh/bridge.js +3 -6
  8. package/dist/crowdy-studio/controller.d.ts +34 -59
  9. package/dist/crowdy-studio/controller.d.ts.map +1 -1
  10. package/dist/crowdy-studio/controller.js +96 -225
  11. package/dist/crowdy-studio/diagnostics.d.ts +3 -12
  12. package/dist/crowdy-studio/diagnostics.d.ts.map +1 -1
  13. package/dist/crowdy-studio/dom-shell.d.ts +2 -4
  14. package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
  15. package/dist/crowdy-studio/dom-shell.js +16 -49
  16. package/dist/crowdy-studio/embed/hud-layer.d.ts +1 -2
  17. package/dist/crowdy-studio/embed/hud-layer.d.ts.map +1 -1
  18. package/dist/crowdy-studio/embed/panel.d.ts +3 -13
  19. package/dist/crowdy-studio/embed/panel.d.ts.map +1 -1
  20. package/dist/crowdy-studio/embed/panel.js +3 -6
  21. package/dist/crowdy-studio/index.d.ts +1 -3
  22. package/dist/crowdy-studio/index.d.ts.map +1 -1
  23. package/dist/crowdy-studio/index.js +0 -2
  24. package/dist/crowdy-studio/models.d.ts +3 -4
  25. package/dist/crowdy-studio/models.d.ts.map +1 -1
  26. package/dist/crowdy-studio/starter-projects.d.ts +8 -12
  27. package/dist/crowdy-studio/starter-projects.d.ts.map +1 -1
  28. package/dist/crowdy-studio/starter-projects.js +12 -103
  29. package/dist/domains/appAccess.d.ts +14 -1
  30. package/dist/domains/appAccess.d.ts.map +1 -1
  31. package/dist/domains/appAccess.js +37 -1
  32. package/dist/domains/apps.d.ts +1 -10
  33. package/dist/domains/apps.d.ts.map +1 -1
  34. package/dist/domains/apps.js +1 -16
  35. package/dist/domains/host.d.ts +3 -3
  36. package/dist/domains/host.js +3 -3
  37. package/dist/domains/hosting.d.ts +0 -6
  38. package/dist/domains/hosting.d.ts.map +1 -1
  39. package/dist/domains/hosting.js +1 -16
  40. package/dist/domains/marketplace.d.ts +9 -70
  41. package/dist/domains/marketplace.d.ts.map +1 -1
  42. package/dist/domains/marketplace.js +9 -120
  43. package/dist/domains/organizations.d.ts +1 -9
  44. package/dist/domains/organizations.d.ts.map +1 -1
  45. package/dist/domains/organizations.js +1 -15
  46. package/dist/domains/payments.d.ts +5 -48
  47. package/dist/domains/payments.d.ts.map +1 -1
  48. package/dist/domains/payments.js +5 -57
  49. package/dist/domains/playerWallet.d.ts +6 -12
  50. package/dist/domains/playerWallet.d.ts.map +1 -1
  51. package/dist/domains/playerWallet.js +6 -21
  52. package/dist/domains/quotas.d.ts +20 -7
  53. package/dist/domains/quotas.d.ts.map +1 -1
  54. package/dist/domains/quotas.js +15 -6
  55. package/dist/domains/users.d.ts +7 -74
  56. package/dist/domains/users.d.ts.map +1 -1
  57. package/dist/domains/users.js +7 -105
  58. package/dist/errors.d.ts +7 -13
  59. package/dist/errors.d.ts.map +1 -1
  60. package/dist/errors.js +6 -10
  61. package/dist/generated/graphql.d.ts +955 -8272
  62. package/dist/generated/graphql.d.ts.map +1 -1
  63. package/dist/generated/graphql.js +5 -329
  64. package/dist/grid-mods/exec-client-halves.d.ts +19 -3
  65. package/dist/grid-mods/exec-client-halves.d.ts.map +1 -1
  66. package/dist/grid-mods/exec-client-halves.js +17 -2
  67. package/dist/grid-mods/grid-host-calls.d.ts +29 -17
  68. package/dist/grid-mods/grid-host-calls.d.ts.map +1 -1
  69. package/dist/grid-mods/grid-host-calls.js +40 -46
  70. package/dist/grid-mods/mod-runtime.d.ts +18 -11
  71. package/dist/grid-mods/mod-runtime.d.ts.map +1 -1
  72. package/dist/grid-mods/mod-runtime.js +4 -2
  73. package/dist/grid-scope.d.ts +0 -189
  74. package/dist/grid-scope.d.ts.map +1 -1
  75. package/dist/grid-scope.js +0 -70
  76. package/dist/index.d.ts +12 -18
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +10 -16
  79. package/dist/kit/actions.d.ts +5 -9
  80. package/dist/kit/actions.d.ts.map +1 -1
  81. package/dist/kit/actions.js +5 -9
  82. package/dist/kit/index.d.ts +2 -33
  83. package/dist/kit/index.d.ts.map +1 -1
  84. package/dist/kit/index.js +1 -32
  85. package/dist/kit/kit.d.ts +8 -208
  86. package/dist/kit/kit.d.ts.map +1 -1
  87. package/dist/kit/kit.js +5 -163
  88. package/dist/kit/social.d.ts +1 -3
  89. package/dist/kit/social.d.ts.map +1 -1
  90. package/dist/kit/social.js +1 -3
  91. package/dist/kit/wire.d.ts +16 -5
  92. package/dist/kit/wire.d.ts.map +1 -1
  93. package/dist/kit/wire.js +19 -5
  94. package/dist/live-coding/assets/browser-authoring-index.json +1 -1
  95. package/dist/live-coding/assets/manifest.json +1 -1
  96. package/dist/live-coding/browser-authoring-index.generated.d.ts.map +1 -1
  97. package/dist/live-coding/browser-authoring-index.generated.js +1496 -4386
  98. package/dist/live-coding/rust-analysis.d.ts.map +1 -1
  99. package/dist/live-coding/rust-analysis.js +30 -34
  100. package/dist/player-runtime/client-host-calls.d.ts +8 -0
  101. package/dist/player-runtime/client-host-calls.d.ts.map +1 -0
  102. package/dist/player-runtime/client-host-calls.js +28 -0
  103. package/dist/player-runtime/glue-runtime.d.ts +24 -20
  104. package/dist/player-runtime/glue-runtime.d.ts.map +1 -1
  105. package/dist/player-runtime/glue-runtime.js +26 -55
  106. package/dist/player-runtime/glue-sab.d.ts +2 -2
  107. package/dist/player-runtime/glue-sab.js +2 -2
  108. package/dist/player-runtime/player-code-broker.d.ts +70 -43
  109. package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
  110. package/dist/player-runtime/player-code-broker.js +159 -64
  111. package/dist/player-runtime/player-glue-worker.d.ts +8 -9
  112. package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
  113. package/dist/player-runtime/player-glue-worker.js +26 -11
  114. package/dist/stores/inbox.d.ts +1 -1
  115. package/dist/stores/inbox.d.ts.map +1 -1
  116. package/dist/stores/index.d.ts +0 -11
  117. package/dist/stores/index.d.ts.map +1 -1
  118. package/dist/stores/index.js +0 -4
  119. package/dist/stores/session.d.ts +0 -2
  120. package/dist/stores/session.d.ts.map +1 -1
  121. package/package.json +1 -1
  122. package/dist/crowdy-studio/model-lint-log.d.ts +0 -76
  123. package/dist/crowdy-studio/model-lint-log.d.ts.map +0 -1
  124. package/dist/crowdy-studio/model-lint-log.js +0 -93
  125. package/dist/crowdy-studio/model-lint.d.ts +0 -61
  126. package/dist/crowdy-studio/model-lint.d.ts.map +0 -1
  127. package/dist/crowdy-studio/model-lint.js +0 -45
  128. package/dist/domains/compute.d.ts +0 -208
  129. package/dist/domains/compute.d.ts.map +0 -1
  130. package/dist/domains/compute.js +0 -274
  131. package/dist/domains/controlPlane.d.ts +0 -38
  132. package/dist/domains/controlPlane.d.ts.map +0 -1
  133. package/dist/domains/controlPlane.js +0 -43
  134. package/dist/domains/gameModel.d.ts +0 -1174
  135. package/dist/domains/gameModel.d.ts.map +0 -1
  136. package/dist/domains/gameModel.js +0 -1333
  137. package/dist/domains/playerCompute.d.ts +0 -91
  138. package/dist/domains/playerCompute.d.ts.map +0 -1
  139. package/dist/domains/playerCompute.js +0 -136
  140. package/dist/domains/playerModel.d.ts +0 -20
  141. package/dist/domains/playerModel.d.ts.map +0 -1
  142. package/dist/domains/playerModel.js +0 -54
  143. package/dist/kit/abilities.d.ts +0 -66
  144. package/dist/kit/abilities.d.ts.map +0 -1
  145. package/dist/kit/abilities.js +0 -71
  146. package/dist/kit/blueprints/combat.d.ts +0 -81
  147. package/dist/kit/blueprints/combat.d.ts.map +0 -1
  148. package/dist/kit/blueprints/combat.js +0 -357
  149. package/dist/kit/blueprints/core.d.ts +0 -222
  150. package/dist/kit/blueprints/core.d.ts.map +0 -1
  151. package/dist/kit/blueprints/core.js +0 -185
  152. package/dist/kit/blueprints/decks.d.ts +0 -50
  153. package/dist/kit/blueprints/decks.d.ts.map +0 -1
  154. package/dist/kit/blueprints/decks.js +0 -163
  155. package/dist/kit/blueprints/economy.d.ts +0 -88
  156. package/dist/kit/blueprints/economy.d.ts.map +0 -1
  157. package/dist/kit/blueprints/economy.js +0 -533
  158. package/dist/kit/blueprints/guild.d.ts +0 -51
  159. package/dist/kit/blueprints/guild.d.ts.map +0 -1
  160. package/dist/kit/blueprints/guild.js +0 -50
  161. package/dist/kit/blueprints/index.d.ts +0 -23
  162. package/dist/kit/blueprints/index.d.ts.map +0 -1
  163. package/dist/kit/blueprints/index.js +0 -22
  164. package/dist/kit/blueprints/inventory.d.ts +0 -84
  165. package/dist/kit/blueprints/inventory.d.ts.map +0 -1
  166. package/dist/kit/blueprints/inventory.js +0 -257
  167. package/dist/kit/blueprints/leaderboards.d.ts +0 -49
  168. package/dist/kit/blueprints/leaderboards.d.ts.map +0 -1
  169. package/dist/kit/blueprints/leaderboards.js +0 -126
  170. package/dist/kit/blueprints/liveops.d.ts +0 -42
  171. package/dist/kit/blueprints/liveops.d.ts.map +0 -1
  172. package/dist/kit/blueprints/liveops.js +0 -170
  173. package/dist/kit/blueprints/locks.d.ts +0 -82
  174. package/dist/kit/blueprints/locks.d.ts.map +0 -1
  175. package/dist/kit/blueprints/locks.js +0 -155
  176. package/dist/kit/blueprints/loot.d.ts +0 -90
  177. package/dist/kit/blueprints/loot.d.ts.map +0 -1
  178. package/dist/kit/blueprints/loot.js +0 -229
  179. package/dist/kit/blueprints/matches.d.ts +0 -84
  180. package/dist/kit/blueprints/matches.d.ts.map +0 -1
  181. package/dist/kit/blueprints/matches.js +0 -349
  182. package/dist/kit/blueprints/moderation.d.ts +0 -32
  183. package/dist/kit/blueprints/moderation.d.ts.map +0 -1
  184. package/dist/kit/blueprints/moderation.js +0 -140
  185. package/dist/kit/blueprints/npcs.d.ts +0 -78
  186. package/dist/kit/blueprints/npcs.d.ts.map +0 -1
  187. package/dist/kit/blueprints/npcs.js +0 -125
  188. package/dist/kit/blueprints/plots.d.ts +0 -63
  189. package/dist/kit/blueprints/plots.d.ts.map +0 -1
  190. package/dist/kit/blueprints/plots.js +0 -151
  191. package/dist/kit/blueprints/progression.d.ts +0 -68
  192. package/dist/kit/blueprints/progression.d.ts.map +0 -1
  193. package/dist/kit/blueprints/progression.js +0 -324
  194. package/dist/kit/blueprints/quests.d.ts +0 -72
  195. package/dist/kit/blueprints/quests.d.ts.map +0 -1
  196. package/dist/kit/blueprints/quests.js +0 -285
  197. package/dist/kit/blueprints/worldsim.d.ts +0 -91
  198. package/dist/kit/blueprints/worldsim.d.ts.map +0 -1
  199. package/dist/kit/blueprints/worldsim.js +0 -468
  200. package/dist/kit/combat.d.ts +0 -141
  201. package/dist/kit/combat.d.ts.map +0 -1
  202. package/dist/kit/combat.js +0 -196
  203. package/dist/kit/decks.d.ts +0 -157
  204. package/dist/kit/decks.d.ts.map +0 -1
  205. package/dist/kit/decks.js +0 -186
  206. package/dist/kit/director.d.ts +0 -88
  207. package/dist/kit/director.d.ts.map +0 -1
  208. package/dist/kit/director.js +0 -86
  209. package/dist/kit/economy.d.ts +0 -289
  210. package/dist/kit/economy.d.ts.map +0 -1
  211. package/dist/kit/economy.js +0 -427
  212. package/dist/kit/engine.d.ts +0 -48
  213. package/dist/kit/engine.d.ts.map +0 -1
  214. package/dist/kit/engine.js +0 -113
  215. package/dist/kit/features.d.ts +0 -60
  216. package/dist/kit/features.d.ts.map +0 -1
  217. package/dist/kit/features.js +0 -65
  218. package/dist/kit/instances.d.ts +0 -52
  219. package/dist/kit/instances.d.ts.map +0 -1
  220. package/dist/kit/instances.js +0 -60
  221. package/dist/kit/inventory.d.ts +0 -129
  222. package/dist/kit/inventory.d.ts.map +0 -1
  223. package/dist/kit/inventory.js +0 -200
  224. package/dist/kit/leaderboards.d.ts +0 -86
  225. package/dist/kit/leaderboards.d.ts.map +0 -1
  226. package/dist/kit/leaderboards.js +0 -133
  227. package/dist/kit/liveops.d.ts +0 -112
  228. package/dist/kit/liveops.d.ts.map +0 -1
  229. package/dist/kit/liveops.js +0 -183
  230. package/dist/kit/loot.d.ts +0 -128
  231. package/dist/kit/loot.d.ts.map +0 -1
  232. package/dist/kit/loot.js +0 -160
  233. package/dist/kit/matches.d.ts +0 -301
  234. package/dist/kit/matches.d.ts.map +0 -1
  235. package/dist/kit/matches.js +0 -458
  236. package/dist/kit/matchmaking.d.ts +0 -57
  237. package/dist/kit/matchmaking.d.ts.map +0 -1
  238. package/dist/kit/matchmaking.js +0 -59
  239. package/dist/kit/minigames.d.ts +0 -30
  240. package/dist/kit/minigames.d.ts.map +0 -1
  241. package/dist/kit/minigames.js +0 -38
  242. package/dist/kit/mobs.d.ts +0 -90
  243. package/dist/kit/mobs.d.ts.map +0 -1
  244. package/dist/kit/mobs.js +0 -98
  245. package/dist/kit/moderation.d.ts +0 -73
  246. package/dist/kit/moderation.d.ts.map +0 -1
  247. package/dist/kit/moderation.js +0 -103
  248. package/dist/kit/movement.d.ts +0 -78
  249. package/dist/kit/movement.d.ts.map +0 -1
  250. package/dist/kit/movement.js +0 -103
  251. package/dist/kit/notifications.d.ts +0 -45
  252. package/dist/kit/notifications.d.ts.map +0 -1
  253. package/dist/kit/notifications.js +0 -67
  254. package/dist/kit/npcs.d.ts +0 -226
  255. package/dist/kit/npcs.d.ts.map +0 -1
  256. package/dist/kit/npcs.js +0 -141
  257. package/dist/kit/objects.d.ts +0 -116
  258. package/dist/kit/objects.d.ts.map +0 -1
  259. package/dist/kit/objects.js +0 -119
  260. package/dist/kit/pets.d.ts +0 -85
  261. package/dist/kit/pets.d.ts.map +0 -1
  262. package/dist/kit/pets.js +0 -96
  263. package/dist/kit/plots.d.ts +0 -85
  264. package/dist/kit/plots.d.ts.map +0 -1
  265. package/dist/kit/plots.js +0 -113
  266. package/dist/kit/progression.d.ts +0 -181
  267. package/dist/kit/progression.d.ts.map +0 -1
  268. package/dist/kit/progression.js +0 -265
  269. package/dist/kit/quests.d.ts +0 -171
  270. package/dist/kit/quests.d.ts.map +0 -1
  271. package/dist/kit/quests.js +0 -237
  272. package/dist/kit/racing.d.ts +0 -85
  273. package/dist/kit/racing.d.ts.map +0 -1
  274. package/dist/kit/racing.js +0 -99
  275. package/dist/kit/shared.d.ts +0 -73
  276. package/dist/kit/shared.d.ts.map +0 -1
  277. package/dist/kit/shared.js +0 -101
  278. package/dist/kit/telemetry.d.ts +0 -66
  279. package/dist/kit/telemetry.d.ts.map +0 -1
  280. package/dist/kit/telemetry.js +0 -133
  281. package/dist/kit/territory.d.ts +0 -97
  282. package/dist/kit/territory.d.ts.map +0 -1
  283. package/dist/kit/territory.js +0 -114
  284. package/dist/kit/worldsim.d.ts +0 -263
  285. package/dist/kit/worldsim.d.ts.map +0 -1
  286. package/dist/kit/worldsim.js +0 -268
  287. package/dist/stores/model.d.ts +0 -81
  288. package/dist/stores/model.d.ts.map +0 -1
  289. package/dist/stores/model.js +0 -163
package/MIGRATION.md CHANGED
@@ -1,3 +1,125 @@
1
+ # CrowdyJS v18 — the legacy engines are gone
2
+
3
+ **Breaking.** The game API deleted its legacy developer-code engines on dev (cks-game-api #417,
4
+ ck-api `v2.27.0`): Studio compute, the game model and its automations, player compute (its
5
+ browser CLIENT modules too) and the player model. `18.0.0` removes their SDK surface. Their
6
+ code moves to ck-exec (`client.exec`): an app's server code as hubs and spokes, a player's grid
7
+ code as mods, and a mod's browser code as its CLIENT half. Nothing is migrated for you; port the
8
+ code, then upgrade.
9
+
10
+ **Which 18.** 18.0.0 was published only on the `dev` channel (`18.0.0-dev.1`). **18.0.1 is the
11
+ first 18.x a client on the production channel will see**, and it carries everything on this page:
12
+ the legacy engines' removal (18.0.0) and the platform-administration removal
13
+ ([below](#platform-administration-is-not-in-the-sdk), 18.0.1).
14
+
15
+ **What it needs.** 18.0.0 calls nothing the legacy engines served, so it runs against any API
16
+ with ck-exec CLIENT halves (ck-api `v2.24.0`, as 17.14.0 did). **Crowdy Studio's CLIENT
17
+ projects need ck-api `v2.25.1` or later:** `v2.24.0` and `v2.25.0` refuse to save a
18
+ `crowdy-client-sdk` crate in a Studio project (`CROWDY_STUDIO_MANIFEST_INVALID`, cks-game-api
19
+ #425). The other way round, a 17.x SDK against `v2.27.0` fails every call into a deleted field
20
+ as a GraphQL validation error.
21
+
22
+ | 17.x | 18.0 |
23
+ | --- | --- |
24
+ | `client.gameModel` (containers, properties, functions, `invoke`, sessions, events, timers, automations, `seed`, lint, the player-count feed) | A hub's own state and endpoints: `client.exec.connect(appId, { nodeType, key })`, then `call` / `subscribe`; timers are `ctx.timer_after` / `ctx.timer_every` in the hub; sessions are a keyed hub (the `session` starter) |
25
+ | `gameModel.defineFeature`, `grantTierFeature`, `revokeTierFeature`, `features`, `tierFeatures` | `client.appAccess.defineFeature`, `grantTierFeature`, `revokeTierFeature`, `features(appId)`, `tierFeatures(appId, tierId?)` (same fields; a hub reads them with `players.features`) |
26
+ | `client.compute` (modules, `invoke`, templates, runs, logs) | `client.exec.starters` / `build` / `waitForBuild` / `deploy`, `logs`, `instances`, `versions`, `activateVersion`, `setEnabled`; manual calls through `connectAsDeveloper` |
27
+ | `client.playerModel` (containers, automations) | A mod's own state and timers |
28
+ | `client.playerCompute` SERVER side (`deploy` with `target: SERVER`, `setEnabled`, `setRequires`, `invoke`, `runs`, `logs`) | Mods: `client.exec.modBuild` / `waitForModBuild` / `modDeploy` / `modSetEnabled`, calls through `connect(appId, { nodeType: execModType(name), key: gridId })`, `modLogs` |
29
+ | `client.playerCompute` CLIENT modules (`deploy`, `versions`, `artifact`, `artifactBytes`, `usage`, `myModules`, `delete`, `setSwitch`, `switches`) | A mod's CLIENT half: `client.exec.modClientBuild` (polled with `modBuildStatus` / `waitForModBuild`), `modClientDeploy` / `modClientDelete`, `modClientArtifactBytes`; its kill ladder is the mod's, `modSetSwitch` |
30
+ | `marketplace.gridClientMods`, `consentGridClientMod`, `trustGridAuthor`, `clientArtifact`, `clientArtifactBytes`, and `client.grid(...).compute.clientMods` | `client.exec.gridClientMods`, `consentClientMod`, `trustAuthor`, `modClientArtifactBytes` (which checks the bytes against their digest); `ExecClientHalves` runs a grid's CLIENT halves |
31
+ | `marketplace.listings` / `versions` / `publishListing` / `publishVersion` / `acquire` / `install` / `uninstall` / `myAcquisitions` / `myInstalls` | `client.exec.modPublish` / `modListings` / `modInstall` / `modUnpublish`; a listing carries its mod's CLIENT half |
32
+ | `playerWallet.policies` / `setPolicy` / `deletePolicy` (`playerWasmPolicies`) | Mods run under the platform's mod limits; the kill ladder is `client.exec.modSetSwitch` |
33
+ | `client.operator` (`computePlatformCeilings`, `setComputePlatformCeilings`) | ck-exec code is bounded by its manifest limits within the platform's; there is nothing to call |
34
+ | `client.kit(appId)` blueprints, `kit.deploy`, engines, `kit.inventory` … `kit.minigames`, `kit.features` | Hubs; the starters for NPCs and mobs, sessions and matchmaking. `kit.social` stays; `kit/wire.ts` codecs and `runOptimisticAction` stay |
35
+ | `createWorldSession({ model })` (`ContainerMirror`) | Subscribe to the hub's topic |
36
+ | `client.grid(...).sessions`, `.model`, `.compute` | A mod on the grid (`client.exec.mod*`) |
37
+ | `PlayerCodeBroker` / `startGridMod` without `engine` (a legacy CLIENT module: unmetered, with the whole client catalog), `ALLOWED_HOST_CALLS` | A CLIENT half, the only kind of player module: `artifactHash`, `fuelPerDispatch` and `consentedHostCalls` are required, the allowlist is `EXEC_CLIENT_HOST_CALLS`, and the module must carry the `ck_fuel` meter |
38
+ | `MODEL_LINT_QUERY`, `modelLintDiagnostics`, `CrowdyModelLintLog`, the `'model-lint'` diagnostic source | The Rust compiler's diagnostics from the build |
39
+
40
+ - **The player runtime runs CLIENT halves only.** `PlayerCodeBroker`'s `artifactHash` (the
41
+ served `digest`), `fuelPerDispatch` and `consentedHostCalls` are required, and `engine` is
42
+ `'ck-exec'` or absent; a broker without them, or asked for another engine, does not start.
43
+ The glue offers exactly `EXEC_CLIENT_ABI_IMPORTS` and refuses a module without the `ck_fuel`
44
+ meter; its inert wasi stubs and the `wasi_unstable` alias are gone. `ALLOWED_HOST_CALLS` is
45
+ gone, and `GLUE_HOST_FUNCTIONS` names the CLIENT allowlist. `startGridMod`'s wasm spec needs
46
+ the same three values.
47
+ - **CLIENT host calls the legacy engines answered are refused** by the broker as not allowed:
48
+ the Game Model group (`container_*`, `containers_list`, `property_set`, `edge_*`,
49
+ `model_invoke`), `sessions_list`, and `grid_state_get` / `grid_state_set`. A mod's server
50
+ half, a hub keyed by the grid, holds grid state now. `createGridHostCalls` / `startGridMod`
51
+ lost `allowModelInvoke` and the client's `gameModel`.
52
+ - **What a CLIENT half says and answers, on the page** (new):
53
+ - `onLog`: its `crowdy::log` lines (crowdy-client-sdk levels 0 debug, 1 info, 2 warn,
54
+ 3 error), at most `PLAYER_CODE_LOG_LINES_PER_SECOND` (20) a second and
55
+ `PLAYER_CODE_LOG_MAX_CHARS` (1,000) characters each, then a `warn` counting what was
56
+ dropped. On `PlayerCodeBroker`, `ExecClientHalves` (with the mod) and `startGridMod`. The
57
+ text is the mod author's: render it as text. Crowdy Studio shows its preview's lines in
58
+ Logs.
59
+ - `invoke(payload)`: the module's `handle_invoke` export, called by the page:
60
+ `PlayerCodeBroker.invoke`, `ExecClientHalves.invoke(modId, payload)` and
61
+ `RunningGridMod.invoke`, up to `PLAYER_CODE_INVOKE_MAX_BYTES` (256 KiB) each way. The reply
62
+ is the module's: treat it as untrusted input.
63
+ - `createGridHostCalls` answers `avatar_state_get` and `grid_permission_check` as the host
64
+ catalog scopes them: an avatar whose live actor the game places inside the grid
65
+ (`local.avatarChunk`, then the public `avatarAppState`), and the visiting player
66
+ (`userId`) on this grid, from the permission keys the game knows
67
+ (`local.gridPermissionKeys`). Without those they are refused as not offered, as
68
+ `actors_list` is without `local.actorsInChunk`.
69
+ - **Crowdy Studio runs on ck-exec only.** Drop `serverEngine` from the embed, the controller
70
+ and `mountCrowdyStudio`, and `playerCompute` from the embed's services and the controller's
71
+ and `mountCrowdyStudio`'s options (`CrowdyStudioPlayerCompute` is gone); they require
72
+ `mods: client.exec`, and the embed requires `client.exec`. `CrowdyStudioState` loses
73
+ `serverEngine`, `runs` (the Runs panel went) and `usage` (`CrowdyStudioUsageSnapshot`:
74
+ nothing on ck-exec spends player compute quota, and the `'usage'` surface reads the
75
+ wallet); `logs` are `CrowdyStudioLogLine`s (`id`, `source` `'mod' | 'preview'`,
76
+ `moduleName`, `level`, `at`, `text`); `CrowdyStudioInvokeResult` is
77
+ `{ resultJson, durationUs }`. `createCrowdyStudioStarterProject` needs `modStarter` for a
78
+ kind with a SERVER target and has no `engine`: a CLIENT target is a `crowdy-client-sdk`
79
+ CLIENT half. The pairing control went: a mod has no pairing.
80
+ - A CLIENT crate still on `crowdy-compute-sdk` is refused before any build, with what to
81
+ change: `crowdy-client-sdk = "0.1.0"` in `Cargo.toml` and `crowdy_client_sdk` in place of
82
+ `crowdy_compute_sdk` in `src/`. Its host calls are the same less the Game Model, sessions and
83
+ grid state (`grid_state_get` / `grid_state_set`).
84
+ - `ENGINE_SWITCHED_OFF` left `CrowdyFaultCode`: nothing raises it now.
85
+ - The kit's type-98 parser is `parseZoneChangeEvent` beside the other wire parsers.
86
+
87
+ ## Platform administration is not in the SDK
88
+
89
+ The SDK is for normal clients and designed for production: it carries what players,
90
+ developers and org-admins call, and nothing only a super-admin or a platform operator can
91
+ call. **18.0.1** removes the wrappers that were left (18.0.0 still had them). The API still has every one of these
92
+ fields; **use the API directly from your own tooling** (a GraphQL request with an operator's or
93
+ super-admin's session). There is no SDK replacement.
94
+
95
+ | Removed | Root field |
96
+ | --- | --- |
97
+ | `client.users.paginated`, `client.users.listConnection` | `usersPaginated`, `usersConnection` |
98
+ | `client.users.setSuperAdmin` | `setSuperAdmin` |
99
+ | `client.users.setOperator` | `setOperator` |
100
+ | `client.users.setEarlyAccessOverride` | `setEarlyAccessOverride` |
101
+ | `client.users.updateType` | `updateUserType` |
102
+ | `client.users.forceLogout` | `forceLogoutUser` |
103
+ | `client.payments.all`, `allConnection` (also `client.admin.payments`) | `checkouts`, `checkoutsConnection` |
104
+ | `client.payments.events`, `eventsConnection` | `paymentEvents`, `paymentEventsConnection` |
105
+ | `client.organizations.setStatus` | `setOrgStatus` |
106
+ | `client.apps.setVisibility` | `setAppVisibility` |
107
+ | `client.hosting.all` | `allHostedGames` |
108
+ | `client.hosting.setListing` | `setHostedGameListing` |
109
+ | `client.hosting.takeDown` | `takeDownHostedGame` |
110
+
111
+ - `client.quotas.set` takes a `ScopedSetQuotaInput`: an `appId` or an `orgId` (and optionally a
112
+ `tierId`) is required, and it refuses a platform-global rule before any request.
113
+ `client.quotas.remove` is unchanged; it removes a rule on an org or app the caller manages.
114
+ - `client.users.get` and `client.users.updateState` stay: any session can call them
115
+ (`updateState` writes only the caller); their docs had said super-admin only.
116
+ - The generated types and documents for those operations are gone from
117
+ `@crowdedkingdoms/crowdyjs/generated` as well.
118
+
119
+ `schema.gql` and the generated types follow the game API: the release carries cks-game-api
120
+ `dev`'s SDL after #417 merged (`npm run schema:sync:paths -- --schema <that schema.gql>`, then
121
+ `npm run codegen`).
122
+
1
123
  # 17.14.0 ck-exec CLIENT halves
2
124
 
3
125
  Dev-tier preview (cks-game-api #422, P3 W1). **The release needs a game API that has #422:**
@@ -65,9 +187,15 @@ trust its author. It replaces the legacy grid-attached client mods, which keep w
65
187
  Existing CLIENT projects keep their files: a CLIENT crate on `crowdy-compute-sdk` is refused on
66
188
  ck-exec before any build, with what to change (the SDK line becomes
67
189
  `crowdy-client-sdk = "0.1.0"`, `crowdy_compute_sdk` becomes `crowdy_client_sdk`; the host
68
- calls are the same less the Game Model and sessions). `serverEngine: 'player-compute'` keeps
190
+ calls are the same less the Game Model, sessions and grid state, `grid_state_get` /
191
+ `grid_state_set`, which a mod's server half holds now). `serverEngine: 'player-compute'` keeps
69
192
  both targets on legacy player compute until 18.0.
70
193
 
194
+ **Studio's CLIENT target on ck-exec needs ck-api `v2.25.1` or later.** `v2.24.0` and
195
+ `v2.25.0` refuse to save a `crowdy-client-sdk` crate in a Studio project
196
+ (`CROWDY_STUDIO_MANIFEST_INVALID`, cks-game-api #425), so a CLIENT project cannot start there;
197
+ the SDK calls themselves need only `v2.24.0`.
198
+
71
199
  # 17.13.0 ck-exec observability
72
200
 
73
201
  Additive (dev-tier preview; ck-api `v2.22.0`).
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  The official browser-first TypeScript SDK for **Crowded Kingdoms**. CrowdyJS
4
4
  gives you typed clients for the whole platform: identity and
5
- studio administration (the Management surface), world data and the abstract
6
- game model (the Game surface), and the UDP proxy realtime stream — all over
7
- one unified GraphQL API.
5
+ studio administration (the Management surface), world data (the Game surface),
6
+ the UDP proxy realtime stream, and ck-exec, where an app's server code runs —
7
+ all behind one unified GraphQL API.
8
8
 
9
9
  Authentication follows a two-token model: an identity **session token** for
10
10
  account and admin operations, and short-lived **app-scoped tokens** for
@@ -221,27 +221,23 @@ never told about, so a native refresh without it is a re-placement.
221
221
  | `client.users` | `me`, `updateGamertag`, profile reads. |
222
222
  | `client.session` | Token store, `restore()`, `getToken()`, manual `setToken()`. |
223
223
  | `client.portal` | App-scoped token minting (`mintAppToken`) and the cross-origin PKCE entry flow (`beginEntry` / `handleAuthorizeRequest` / `completeEntry` / `refresh`). |
224
- | `client.hosting` | Third-party hosting on Crowdy Games (17.2.0): `claim` a slug for an app, `beginPublish` / `completePublish` / `abandonPublish` a built bundle, `setEnabled`; public `game(slug)` / `listed()`; operator `all` / `setListing` / `takeDown`. Mutations need an identity session with `manage_apps`. `@crowdedkingdoms/crowdyjs/hosting` exports `publishDirectory(client, { dir, slug })`, the Node helper that does the whole publish for a `dist/`. |
224
+ | `client.hosting` | Third-party hosting on Crowdy Games (17.2.0): `claim` a slug for an app, `beginPublish` / `completePublish` / `abandonPublish` a built bundle, `setEnabled`; public `game(slug)` / `listed()`. Mutations need an identity session with `manage_apps`. `@crowdedkingdoms/crowdyjs/hosting` exports `publishDirectory(client, { dir, slug })`, the Node helper that does the whole publish for a `dist/`. |
225
225
  | `client.platform` | Public platform configuration (`config()`). |
226
226
  | `client.serverStatus` | `gameClientBootstrap(appId)` — per-app version info, UDP status, spatial limits. |
227
227
  | `client.chunks`, `client.voxels`, `client.actors`, `client.avatars`, `client.state` | World data reads + writes: terrain/LODs, voxel edit + history/rollback, durable actors, avatars, per-user app state blobs. |
228
- | `client.host` | Game-host election (`get`, `amIHost`) + actor liveness `heartbeat`. `amIHost` is UI convenience only — authoritative host gating uses `gameModelInvoke`'s `is_host` policy. |
228
+ | `client.host` | Game-host election (`get`, `amIHost`) + actor liveness `heartbeat`. `amIHost` is UI convenience only — a hub decides host-only actions from its caller. |
229
229
  | `client.teleport` | Teleport requests. |
230
230
  | `client.channels`, `client.teams` | Messaging channels and app-scoped player teams (membership + roles). |
231
- | `client.gameModel` | Abstract game model: containers, properties, functions (incl. model-driven `notify_*` effects), sessions, app-scoped active-session counts (`activePlayerCount`, `activePlayerCountChanged`), container-change push (`containerChanged`), flow-correlation timelines (`flow`), automations / NPCs (`upsertAutomation`, `runAutomation`, `automationRuns`, `automationStats`, …), and one-shot timers (`scheduleInvoke`, `cancelTimer`, `timers`). |
232
- | `client.compute` | Compute Modules — server-side Rust/WASM logic: author + deploy source (`upsertModule`, `deployVersion`, `deployTemplate`, `waitForCompile`), triggers + policy, synchronous `invoke`, and monitoring (`moduleRuns`, `moduleStats`, `moduleLogs`, `appDiagnostics`). See [Compute Modules](https://docs.crowdedkingdoms.com/game-api/compute-modules). |
233
- | `client.exec` | **ck-exec (dev-tier preview, 17.9.0):** `connect(appId, { nodeType, key })` opens a player's connection to an execution host; the `ExecConnection` it returns has `call`, `callRaw`, `subscribe`, `ping`, `onReconnect` and `close`, with MessagePack payloads, and it reconnects and renews subscriptions by itself. `deploy({ appId, root, types })` deploys an app's hubs and spokes (`manage_compute`). Players' mods (`modBuild`, `modDeploy`, ...) and, since 17.14.0, their CLIENT halves (`modClientBuild`, `modClientDeploy`, `gridClientMods`, `consentClientMod`, `trustAuthor`, `modClientArtifactBytes`). See [ck-exec](#ck-exec-dev-tier-preview). |
234
- | `client.playerCompute` | Player-authored SERVER/CLIENT Rust/WASM bound to player-owned grids: deploy source, activate/deactivate, list modules/versions, delete self-authored modules. |
235
- | `client.playerModel` | Player-owned flexible model containers and grid-confined automations (`containers`, `createContainer`, `setProperty`, `automations`, `createAutomation`, …). |
236
- | `client.playerWallet` | Player spend: balance, spend caps, card setup, policy, charges. |
237
- | `client.marketplace` | Player-code store/install/consent flows plus player-authorized grid claims (`claimGridOwnership`, `claimGridChunk`, `releaseClaimedGrid`) and client-mod artifact fetches. The grid-attached client mods (`gridClientMods`, `consentGridClientMod`, `trustGridAuthor`, `clientArtifact(Bytes)`) are superseded by ck-exec CLIENT halves and go in 18.0. |
231
+ | `client.exec` | **ck-exec (dev-tier preview):** an app's server code as hubs and spokes. `connect(appId, { nodeType, key })` opens a player's connection to an execution host; the `ExecConnection` it returns has `call`, `callRaw`, `subscribe`, `ping`, `onReconnect` and `close`, with MessagePack payloads, and it reconnects and renews subscriptions by itself. `starters` / `build` / `deploy` build and deploy an app (`manage_compute`); `logs`, `instances`, `versions`, `activateVersion` and `setEnabled` operate it; `mod*` are players' mods on grids they own, and `modClient*`, `gridClientMods`, `consentClientMod` and `trustAuthor` their CLIENT halves. See [ck-exec](#ck-exec-dev-tier-preview). |
232
+ | `client.playerWallet` | Player spend: balance, ledger, hourly charges, spend caps, card setup, auto-recharge. A ck-exec mod's compute is billed here, to its owner. |
233
+ | `client.marketplace` | Player-authorized grid claims (`claimGridOwnership`, `claimGridChunk`, `releaseClaimedGrid`, requests and invites) and studio moderation of player code (admission queue, listing administration, claim policy). Mods publish and install through `client.exec`. |
238
234
  | `client.crowdyStudio` | Cloud project, personal-library, and common-file APIs for Crowdy Studio: target-scoped files, metadata/module names, optimistic revisions, copy-by-value imports, atomic saves. |
239
235
  | `client.crowdyStudioGitHub` | Optional GitHub repository for a Crowdy Studio project: status, `bind` (push the project in, or take the repository), `unbind`, `refresh`, `layout`, `tree`, `getFile`, commit-guarded `putFile` / `deleteFile`. While bound the repository is the working tree and every Studio save commits; the project's `files` are the server's mirror at `github.sha`. Never required. |
240
236
  | `client.udp` | UDP proxy subscriptions + spatial mutations (`sendActorUpdate`, `sendVoxelUpdate`, `sendAudioPacket`, `sendVideoPacket` / `sendVideoFrame`, `sendTextPacket`, `sendClientEvent`, `sendSingleActorMessage`, `sendChannelMessage`). |
241
237
  | `client.realtime` | Connection status, manual `connect()` / `disconnect()`, `onStatus()` listener. |
242
238
  | `client.refreshGameplayToken()` | Safely rotates an active game client's app token (see [Token refresh](#token-refresh-during-gameplay)). |
243
239
  | `client.world(appId)` | Higher-level helpers for browser games (`actor.join`, `actor.sendState`, `actor.sendText`, `actor.sendToActor`). |
244
- | `client.kit(appId)` | Game Kit: ready-made mappings of game concepts onto the game model — see [Game Kit](#game-kit). |
240
+ | `client.kit(appId)` | Game Kit: parties, guilds and chat over teams and channels (`kit.social`) — see [Game Kit](#game-kit). |
245
241
  | `createWorldSession(client, appId, config)` | World Stores: opt-in, SDK-managed game state from the `@crowdedkingdoms/crowdyjs/stores` subpath — see [World Stores](#world-stores). |
246
242
 
247
243
  **Studio-admin surface** (privileged; drive with a server-side / studio token,
@@ -251,7 +247,7 @@ grouped under `client.admin` and mirrored at the top level):
251
247
  |---|---|
252
248
  | `client.organizations` | Orgs, members, RBAC roles, org API tokens. |
253
249
  | `client.apps` | App registry, discovery + routing (`create`, `routeFor`, `marketplace`), visibility, and player-code admission mode / allow-list administration. |
254
- | `client.appAccess` | Access tiers + per-user grants. |
250
+ | `client.appAccess` | Access tiers + per-user grants, and the feature keys a tier grants (`defineFeature`, `grantTierFeature`, `tierFeatures`, …), which a hub checks with the node API's `players.features`. |
255
251
  | `client.billing` | Org wallet + per-app spend budgets. |
256
252
  | `client.payments` | Payment checkouts (wallet top-ups, plan purchases). |
257
253
  | `client.quotas` | Usage quotas at the org/app scope. |
@@ -259,15 +255,15 @@ grouped under `client.admin` and mirrored at the top level):
259
255
  | `client.sharedEnvironment` | Publish to shared, runtime gating, spend caps, auto-billing. |
260
256
  | `client.gameApps` | App grids (`createGrid` / `deleteGrid`), first-class grid ownership (`ownership` / `assignOwnership` / `transferOwnership`), and grid runtime-permission administration. |
261
257
 
262
- **Operator surface** (platform operations; requires `is_operator`):
258
+ **The SDK is for normal clients, and designed for production.** It carries what players,
259
+ developers and org-admins call, and nothing only a super-admin or a platform operator can
260
+ call: those fields are in the API, and platform tooling calls them directly (18.0.1 removed
261
+ the last wrappers; see [MIGRATION.md](MIGRATION.md)). There is no `client.operator`, and
262
+ infrastructure operations live in the separate infra-control-plane service.
263
263
 
264
- | Sub-client | What it does |
265
- |---|---|
266
- | `client.operator` | Platform compute ceilings (`computePlatformCeilings`, `setComputePlatformCeilings`). Infrastructure operations live in the separate infra-control-plane service, not this SDK. |
267
-
268
- Auth, user reads and the studio-admin / operator surfaces use the **identity
269
- session token**; the world/UDP surfaces require an **app-scoped token** for that
270
- app. Both go to the same endpoint.
264
+ Auth, user reads and the studio-admin surface use the **identity session token**; the
265
+ world/UDP surfaces require an **app-scoped token** for that app. Both go to the same
266
+ endpoint.
271
267
 
272
268
  CrowdyJS wraps the full public API surface — every
273
269
  non-deprecated public root field has a typed method, with Relay `*Connection`
@@ -485,16 +481,14 @@ pre-bound — convenient for browser games. Advanced callers can always use
485
481
 
486
482
  ## Grids: player code inside one grid
487
483
 
488
- A grid is a box of chunks a player can own. Everything an app-scoped Studio
489
- module can do, code running in a grid can do too, confined to that grid:
490
- spatial messages that originate in it, the grid's own channels, a grid event
491
- bus, sessions hosted in it, and the player-tier Game Model.
484
+ A grid is a box of chunks a player can own. Code running in a grid is confined
485
+ to it: spatial messages that originate in it, the grid's own channels, and a
486
+ grid event bus. Its server side is a ck-exec mod (`client.exec.mod*`).
492
487
 
493
488
  ```ts
494
489
  const plot = client.grid(appId, gridId);
495
490
  await plot.mintToken(); // learns the box; a grid-scoped token
496
491
  await plot.channels.create('plot-chat'); // a grid channel (owner only)
497
- await plot.sessions.create({ name: 'race' }); // a game within the game
498
492
  await plot.send.text({ chunk: { x: 4, y: 0, z: 0 }, uuid, text: 'hi', distance: 2 });
499
493
  plot.send.text({ chunk: { x: 9, y: 0, z: 0 }, uuid, text: 'x' }); // throws GridScopeError
500
494
  ```
@@ -512,11 +506,17 @@ import { hostGridProgram } from '@crowdedkingdoms/crowdyjs/grid-program';
512
506
  await hostGridProgram({ port, scope: client.grid(appId, gridId), graphqlUrl, graphqlWsUrl });
513
507
  ```
514
508
 
515
- `startGridMod` runs either a Rust CLIENT mod (WASM) or a JS grid program
516
- behind one interface; `createGridHostCalls` answers every CLIENT host call in
517
- the platform catalog through CrowdyJS for a mod's broker. A ck-exec mod's
518
- CLIENT half is `engine: 'ck-exec'`, and `ExecClientHalves` runs a whole grid's
519
- (see [A mod's CLIENT half](#a-mods-client-half)).
509
+ `startGridMod` runs either a mod's CLIENT half (WASM) or a JS grid program
510
+ behind one interface, and `ExecClientHalves` runs a whole grid's CLIENT halves
511
+ (see [A mod's CLIENT half](#a-mods-client-half)). `createGridHostCalls` answers
512
+ a CLIENT half's host calls through CrowdyJS confined to the grid. The ones only
513
+ the game can answer need its knowledge: `local.actorsInChunk` for
514
+ `actors_list*`, `local.avatarChunk` (where an avatar's live actor is) for
515
+ `avatar_state_get`, `local.gridPermissionKeys` with the visiting player's
516
+ `userId` for `grid_permission_check`, and `local.drainPointerClicks` for
517
+ `pointer_clicks`; without its hook such a call is refused as not offered. The
518
+ Game Model, sessions and grid state calls went with the legacy engines in
519
+ 18.0.0: the broker refuses them.
520
520
 
521
521
  ## World Stores
522
522
 
@@ -573,8 +573,8 @@ The available stores are `self` (your actor + send loop), `actors` (remote
573
573
  actor registry with lanes/history/staleness), `errors` (attributed send
574
574
  errors), `chunks` (chunk/voxel cache with realtime merge + worldgen
575
575
  write-back), `channelInbox` / `actorInbox` (message inboxes), `events` (typed
576
- event router), `host` (host tracking), `save` / `avatar` (typed durable
577
- state), and `model` (game-model container mirror).
576
+ event router), `host` (host tracking), and `save` / `avatar` (typed durable
577
+ state).
578
578
 
579
579
  Every store is **opt-in twice over**: only configured stores are constructed
580
580
  (and only they exist on the session's TYPE — `session.host` without
@@ -588,101 +588,25 @@ keep timer-driven sends at full rate while hidden. See the
588
588
 
589
589
  ## Game Kit
590
590
 
591
- `client.kit(appId)` maps traditional game concepts onto the abstract game
592
- model + automations API. Studios **deploy blueprints** (the admin "load the
593
- state/rules" step, requires `manage_apps`); game clients then use the typed
594
- runtime helpers. Everything composes `client.gameModel` — no new server
595
- surface.
596
-
597
- ```ts
598
- // Studio setup (admin context):
599
- import { inventoryBlueprint, lockBlueprint, npcBlueprint } from '@crowdedkingdoms/crowdyjs';
600
-
601
- await admin.kit(appId).deploy([
602
- inventoryBlueprint(),
603
- lockBlueprint({ objectTypeName: 'Door', authority: { kind: 'key' } }),
604
- npcBlueprint({
605
- behaviors: [{
606
- name: 'npc-wander',
607
- role: 'wanderer',
608
- trigger: { intervalMs: 60000 },
609
- mutations: [
610
- { target: 'self', property: 'x', expression: 'self.x + rand_int(-2, 2)' },
611
- { target: 'self', property: 'z', expression: 'self.z + rand_int(-2, 2)' },
612
- ],
613
- }],
614
- }),
615
- ]);
616
-
617
- // Game client (player token):
618
- const kit = game.kit(appId);
619
- const bag = await kit.inventory.ensure(me.userId);
620
- const result = await kit.objects.open(doorId, { keyId });
621
- if (!result.success) console.warn('locked:', result.errorMessage);
622
- ```
623
-
624
- Land sale closes the permission loop end to end:
591
+ `client.kit(appId).social` gives parties, guilds and chat rooms in familiar
592
+ words over teams (membership and roles) and channels (messaging), with
593
+ realtime delivery on the UDP notification subscription:
625
594
 
626
595
  ```ts
627
- // Studio: sell a plot over a grid; doors on it honor the purchase automatically.
628
- await admin.kit(appId).deploy([
629
- plotBlueprint({ rentable: true }),
630
- lockBlueprint({ objectTypeName: 'PlotDoor',
631
- authority: { kind: 'chunkPermission', key: 'access', mode: 'smallest' } }),
632
- ]);
633
-
634
- // Game client: buying spends gold AND grants enforced grid access atomically.
635
- const buy = await kit.plots.buy(plotId, walletId);
636
- if (buy.success) await kit.objects.open(doorId); // has_chunk_permission passes now
596
+ const kit = game.kit(appId, { social: { actorUuid: me.uuid } });
597
+ const party = await kit.social.party.create('raid'); // team + paired channel
598
+ const room = await kit.social.chat.room('lobby');
599
+ kit.social.chat.onMessage(room.groupId, (m) => log(m.senderUuid, m.text));
637
600
  ```
638
601
 
639
- NPC blueprints can target by permissions too — e.g. a guard automation whose
640
- selector has `candidatePermissionWhere: [{ userFrom: { property: 'owner_user_id' },
641
- op: 'lacks', key: 'access', grid: { property: 'grid_id' } }]` reacts only to
642
- intruders.
643
-
644
- The kit covers the common genre staples end to end — each layer is a blueprint
645
- builder plus a typed runtime helper:
646
-
647
- | Layer | Builder → helper | Highlights |
648
- | --- | --- | --- |
649
- | Inventory | `inventoryBlueprint` → `kit.inventory` | bags/stacks, grant/consume/transfer, craft, barter |
650
- | Objects | `lockBlueprint` → `kit.objects` | lockable doors/chests with key or permission authority |
651
- | NPCs | `npcBlueprint` → `kit.npcs` | automation-driven NPC instances (spawn, runNow, enable) |
652
- | Plots | `plotBlueprint` → `kit.plots` | buy/rent land with transactional, replication-enforced grid grants |
653
- | Economy | `economyBlueprint` → `kit.economy` | multi-currency wallets, atomic shop buys, escrow trades, player market, escrowed order book (`kit.economy.orderBook`) |
654
- | Progression | `progressionBlueprint` → `kit.progression` | xp/levels via the `fn:` curve helper, skill prerequisite chains, achievements, host-gated rating |
655
- | Loot | `lootBlueprint` → `kit.loot` | weighted tables unrolled into seed-driven expressions, atomic single-claim, event-triggered drops |
656
- | Quests | `questsBlueprint` → `kit.quests` | event-automation progress, atomic claim into stack+wallet, cron daily resets, tutorial sequencing |
657
- | Combat | `combatBlueprint` → `kit.combat` | server-side damage/death, status-effect tick automation, `turnBased`/`hostSynced`, routed attacks |
658
- | Matches | `matchesBlueprint` → `kit.matches` | session lobbies/rounds/turns/scores, per-match channel + `onMatchChanged` (notify-to-pull) |
659
- | Decks | `decksBlueprint` → `kit.decks` | hidden hands via owner-visibility `card_id`, shuffle-by-position automation |
660
- | World sim | `worldsimBlueprint` → `kit.worldsim` | day/night clock with spatial notify, node regen + atomic gather, crops, wave counters, forecasts |
661
- | Social | `guildBlueprint` → `kit.social` | parties/guilds/chat over teams+channels, grid territory grants, guild hall + bank composite |
662
- | Leaderboards | `leaderboardsBlueprint` → `kit.leaderboards` | trusted keep-best submits, client-side ranking, cron seasons |
663
- | Live ops | `liveopsBlueprint` → `kit.liveops` | timed event windows and seasons |
664
- | Moderation | `moderationBlueprint` → `kit.moderation` | reports, queues, mutes |
665
- | Telemetry | `telemetryBlueprint` → `kit.telemetry` | counters and lightweight event tracking |
666
- | Monetization | `featureGate` → `kit.features` | feature keys, tier grants, `*policyExtra` gating on builders |
667
- | Abilities | — → `kit.abilities` | ability definitions, casts, loadouts |
668
- | Movement | — → `kit.movement` | movement warden configs + violation parsing |
669
- | Territory | — → `kit.territory` | control points, factions, enrollment |
670
- | Racing | — → `kit.racing` | courses, entries, possession (claim/pass/shoot) |
671
-
672
- Engine-aware layers talk to compute-module game engines when they are
673
- deployed, and degrade gracefully on model-only apps via capability detection
674
- (`kit.engines`): `kit.mobs` (refereed attacks, defs/slots, contact-damage
675
- parsing), `kit.pets` (adopt/summon/dismiss/rename), `kit.instances` (private
676
- world slices, seeded runs), `kit.director` (encounter runs),
677
- `kit.matchmaking` (queues/proposals/rating), `kit.minigames` (invoke-loop
678
- wrapper), plus engine paths on `kit.matches` / `kit.decks` /
679
- `kit.leaderboards` and the `kit/wire` pose codec + event parsers. Deploy
680
- engines alongside blueprints with `kit.deploy(blueprints, { engines })`.
681
-
682
- See the docs guides [Modeling game concepts](https://docs.crowdedkingdoms.com/game-api/modeling-game-concepts)
683
- (the underlying model + genre map) and [Game Kit](https://docs.crowdedkingdoms.com/crowdyjs/game-kit)
684
- (the SDK surface + the simulation-tier / notify-to-pull / timer / hidden-info
685
- / anti-cheat patterns).
602
+ Game rules and state are ck-exec hubs (`client.exec`, below). Two kit pieces
603
+ stand alone: the wire codecs (`encodeEnginePose` / `decodeEnginePose`, the
604
+ 48-byte engine pose, `engineLanes`, and `parseEngineEvent` with the typed
605
+ parsers for server events 77 and 90-98) for games whose hubs keep that wire,
606
+ and `runOptimisticAction`, which applies an action locally, asks a referee
607
+ (a hub endpoint, say) and rolls back on a denial. The blueprints,
608
+ `kit.deploy`, the engines and the model-backed helpers went with the game
609
+ model in 18.0.0; see [MIGRATION.md](MIGRATION.md).
686
610
 
687
611
  ## ck-exec (dev-tier preview)
688
612
 
@@ -742,7 +666,8 @@ Integers above 2^53 decode as `number` and lose precision unless you pass
742
666
  A mod (a player's code on a grid they own: `modBuild`, `modDeploy`) can carry a **CLIENT
743
667
  half** (17.14.0): browser WASM from one `crowdy-client-sdk` crate, which the mod's grid serves
744
668
  to visitors who consent to it or trust its author. It runs in the visitor's
745
- `PlayerCodeBroker`, sandboxed like a legacy CLIENT module.
669
+ `PlayerCodeBroker`, in a worker with no DOM, token or network, and it is the only kind of
670
+ player module the broker runs since 18.0.0.
746
671
 
747
672
  ```ts
748
673
  // The mod's owner builds one crowdy-client-sdk crate and attaches it to the mod.
@@ -770,24 +695,30 @@ const halves = new ExecClientHalves({
770
695
  workerUrl, // the platform glue worker, same origin
771
696
  onHostCall: (call) => hostCalls(call), // e.g. createGridHostCalls({ scope, client })
772
697
  onPresentation: (p, mod) => hud.set({ source: mod.modId, label: mod.name, payload: p.payload }),
698
+ onLog: (line, mod) => devConsole.append(mod.name, line.level, line.message), // text, never HTML
773
699
  confirm: (prompt) => window.confirm(describe(prompt)), // once per author; ask: 'mod' for each
774
700
  onStopped: (mod) => hud.remove(mod.modId),
775
701
  });
776
702
  halves.enterGrid({ gridId, low, high }); // the grid the player stands in; null to leave
777
703
  setInterval(() => void halves.refresh().catch(console.warn), 10_000);
704
+
705
+ // The page calls a running CLIENT half's handle_invoke; the reply is the module's bytes.
706
+ const reply = await halves.invoke(modId, new TextEncoder().encode('{"ask":"score"}'));
778
707
  ```
779
708
 
780
709
  Each refresh stops the CLIENT halves whose mod is gone or whose digest, capability hash or
781
- tick interval changed, asks about the rest, and starts the consented ones in a broker with
782
- `engine: 'ck-exec'`. That engine allows exactly the host calls crowdy-client-sdk makes
783
- (`EXEC_CLIENT_HOST_CALLS`: no Game Model, sessions or `grid_state_*`), offers exactly the CLIENT
784
- ABI imports (`EXEC_CLIENT_ABI_IMPORTS`) and runs a module only with its digest, its fuel budget
785
- and `consentedHostCalls`, the host calls of the summary the player consented to: a call outside
786
- them is refused, even one whose name the module assembled at run time.
787
- `NOT_FOUND` holds a CLIENT half back 15 s and `RATE_LIMITED` 60 s. The grid's owner is asked
788
- about their own CLIENT halves like anyone; answer yes in `confirm` when `prompt.authorId` is
789
- the player. The legacy grid-attached client mods (`marketplace.gridClientMods` and the rest)
790
- keep working until 18.0.
710
+ tick interval changed, asks about the rest, and starts the consented ones in a broker. The
711
+ broker allows at most the host calls crowdy-client-sdk makes (`EXEC_CLIENT_HOST_CALLS`: no Game
712
+ Model, sessions or `grid_state_*`), offers exactly the CLIENT ABI imports
713
+ (`EXEC_CLIENT_ABI_IMPORTS`) and runs a module only with its digest, its fuel budget and
714
+ `consentedHostCalls`, the host calls of the summary the player consented to: a call outside them
715
+ is refused, even one whose name the module assembled at run time. A CLIENT half's
716
+ `crowdy::log` lines reach `onLog` at most 20 a second and 1,000 characters each (then a `warn`
717
+ counts what was dropped); `invoke` sends at most 256 KiB each way and is refused while the
718
+ module is not running. `NOT_FOUND` holds a CLIENT half back 15 s and `RATE_LIMITED` 60 s. The
719
+ grid's owner is asked about their own CLIENT halves like anyone; answer yes in `confirm` when
720
+ `prompt.authorId` is the player. See
721
+ [CLIENT halves](https://docs.dev.crowdedkingdoms.com/exec/client-halves).
791
722
 
792
723
  ## Hosting a game on Crowdy Games
793
724
 
@@ -818,7 +749,7 @@ uploads with the exact signed headers, and `completeGamePublish` verifies every
818
749
  object, promotes it and invalidates the CDN. The slug is a DNS label, global on the
819
750
  tier, and first-party names are reserved (`HOSTED_SLUG_UNAVAILABLE`); a tier without
820
751
  a content CDN answers `CONTENT_HOSTING_DISABLED`. Being *listed* in the lobby is an
821
- operator decision (`setListing`); publishing is self-serve. `the-construct`'s
752
+ operator decision, made outside the SDK; publishing is self-serve. `the-construct`'s
822
753
  `npm run publish` is this section as a command.
823
754
 
824
755
  ## Crowdy Studio
@@ -827,28 +758,32 @@ Crowdy Studio is the in-game SERVER/CLIENT Rust authoring surface for player
827
758
  code: cloud projects with target-scoped files, optimistic-concurrency
828
759
  autosave, draft/live/stop orchestration, and a Monaco editor backed by a local
829
760
  Rust language worker. The worker receives source files and the embedded
830
- platform index only — never a credential and never a server connection.
831
- Compiled CLIENT artifacts run through `PlayerCodeBroker`, which keeps tokens
832
- on the page, allow-lists host calls, and locally clamps chunk-targeted effects
833
- to the owned grid before the normal SDK path reaches server authorization.
834
- The host only ticks a CLIENT mod when `tickIntervalMs` is set (omit or `0`
835
- is invoke-only):
761
+ platform index (the `ckx-sdk` and `crowdy-client-sdk` symbols) only — never a
762
+ credential and never a server connection. A CLIENT half runs through
763
+ `PlayerCodeBroker`, which keeps tokens on the page, allow-lists host calls
764
+ (narrowed to what the player consented to), and locally clamps chunk-targeted
765
+ effects to the owned grid before the normal SDK path reaches server
766
+ authorization. It takes what the platform served with the module, and ticks it
767
+ only when `tickIntervalMs` is set (omit or `0` is invoke-only):
836
768
 
837
769
  ```ts
838
770
  import { PlayerCodeBroker } from '@crowdedkingdoms/crowdyjs';
839
771
 
772
+ const half = await client.exec.modClientArtifactBytes(appId, modId);
840
773
  const broker = new PlayerCodeBroker({
841
774
  workerUrl,
842
775
  grid,
843
776
  onHostCall,
844
- tickIntervalMs: 1000, // required for on_tick; omit for invoke-only
777
+ moduleName: half.name,
778
+ artifactHash: half.digest,
779
+ fuelPerDispatch: half.fuelPerDispatch,
780
+ consentedHostCalls: half.capabilitySummary.hostFunctions,
781
+ tickIntervalMs: half.tickIntervalMs, // omit for invoke-only
782
+ onLog: (line) => console.log(`[${line.moduleName}] ${line.level}: ${line.message}`),
845
783
  });
846
- await broker.start(artifactBytes);
784
+ await broker.start(half.bytes);
847
785
  ```
848
786
 
849
- The Studio embed defaults `clientTickIntervalMs` to `1000` when you do not
850
- pass one; a raw `PlayerCodeBroker` does not.
851
-
852
787
  Most games embed the ready-made shell rather than hand-rolling window chrome
853
788
  around `mountCrowdyStudio`:
854
789
 
@@ -859,7 +794,7 @@ import { createCrowdyStudioEmbed } from '@crowdedkingdoms/crowdyjs/crowdy-studio
859
794
  import workerUrl from '@crowdedkingdoms/crowdyjs/player-glue-worker?worker&url';
860
795
 
861
796
  const studio = createCrowdyStudioEmbed({
862
- client: game, // CrowdyClient: crowdyStudio, exec, playerCompute, playerWallet, crowdyStudioGitHub
797
+ client: game, // CrowdyClient: crowdyStudio, exec, playerWallet, crowdyStudioGitHub
863
798
  appId,
864
799
  gameName: 'My Game',
865
800
  suppressGameplayInput: () => pauseInput(),
@@ -882,29 +817,27 @@ fullscreen modal on narrow screens. For custom chrome, call
882
817
  `new CrowdyStudioController(options)`. New games should start SERVER-only.
883
818
  Untrusted HUD payloads always render as text, never HTML.
884
819
 
885
- **The SERVER target runs as a ck-exec mod.** The embed's `serverEngine` defaults to
886
- `'ck-exec'` when the client has `exec` (a `CrowdyClient` always does): a new project's
887
- SERVER target starts from the platform's mod starter (`client.exec.modStarter(appId)`, a
888
- `ckx-sdk` crate), Test draft and Deploy live build it with `modBuild` and deploy it to the
889
- grid as the mod `mod:<server module name>`, Invoke calls one of its endpoints (`state` by
890
- default) over an exec connection, and Logs shows its `ctx.log` lines.
820
+ **The SERVER target runs as a ck-exec mod.** A new project's SERVER target starts from
821
+ the platform's mod starter (`client.exec.modStarter(appId)`, a `ckx-sdk` crate), Test draft
822
+ and Deploy live build it with `modBuild` and deploy it to the grid as the mod
823
+ `mod:<server module name>`, Invoke calls one of its endpoints (`state` by default) over an
824
+ exec connection, and Logs shows its `ctx.log` lines.
891
825
 
892
826
  **The CLIENT target is that mod's CLIENT half** (17.14.0). A new CLIENT target starts from a
893
827
  `crowdy-client-sdk` crate; Test draft and Deploy live build it with `modClientBuild`, attach
894
828
  it to the project's mod with `modClientDeploy`, consent to it as its author (the API serves a
895
829
  CLIENT half only to players who consented, its author too) and preview the served module in
896
- the HUD layer. A CLIENT-only project's CLIENT half rides the mod named for its CLIENT module:
830
+ the HUD layer; the preview's `crowdy::log` lines show in Logs beside the mod's own. A
831
+ CLIENT-only project's CLIENT half rides the mod named for its CLIENT module:
897
832
  when the player has no mod of that name on the grid, Studio deploys the mod starter's server
898
833
  half under it first and says so in the build log, and Stop switches that mod off. The
899
- preview loads only while the player stands in the grid with `run_client_code`. A CLIENT crate
900
- still on the legacy `crowdy-compute-sdk` is refused with what to change.
901
-
902
- `mountCrowdyStudio` and the controller take the same `serverEngine` with
903
- `mods: client.exec`; without `mods` they stay on legacy player compute, and
904
- `serverEngine: 'player-compute'` keeps it explicitly for both targets. The platform is
905
- switching legacy player compute off, so that option lasts only until 18.0 removes it.
834
+ preview loads only while the player stands in the grid with `run_client_code`, and saving a
835
+ CLIENT project needs ck-api `v2.25.1` or later. A CLIENT crate still on the legacy
836
+ `crowdy-compute-sdk` is refused with what to change. The embed takes `exec` from the client;
837
+ `mountCrowdyStudio` and the controller take `mods: client.exec`. Crowdy Studio runs nothing
838
+ on legacy player compute since 18.0.0.
906
839
 
907
- See [Crowdy Studio & player client mods](https://docs.crowdedkingdoms.com/crowdyjs/player-client-mods)
840
+ See [CLIENT halves](https://docs.dev.crowdedkingdoms.com/exec/client-halves), [mods](https://docs.dev.crowdedkingdoms.com/exec/mods)
908
841
  and [Embed Crowdy Studio in your game](https://docs.crowdedkingdoms.com/crowdyjs/crowdy-studio-embed).
909
842
 
910
843
  ### The Studio agent (DeepSeek Harness in the browser)