@babylonjs-toolkit/server 0.0.0-stage → 9.35.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 (236) hide show
  1. package/CUSTOM.md +1690 -0
  2. package/DEPLOY.md +2012 -0
  3. package/README.md +1081 -2
  4. package/lib/AbuseLimits.d.ts +64 -0
  5. package/lib/AbuseLimits.js +121 -0
  6. package/lib/Authentication.d.ts +86 -0
  7. package/lib/Authentication.js +272 -0
  8. package/lib/BootSessionOwner.d.ts +86 -0
  9. package/lib/BootSessionOwner.js +116 -0
  10. package/lib/ColyseusLoggerAdapter.d.ts +32 -0
  11. package/lib/ColyseusLoggerAdapter.js +73 -0
  12. package/lib/DedicatedSceneRegistry.d.ts +52 -0
  13. package/lib/DedicatedSceneRegistry.js +74 -0
  14. package/lib/DedicatedSession.d.ts +152 -0
  15. package/lib/DedicatedSession.js +173 -0
  16. package/lib/DualTransport.d.ts +112 -0
  17. package/lib/DualTransport.js +197 -0
  18. package/lib/GameServer.d.ts +64 -0
  19. package/lib/GameServer.js +647 -0
  20. package/lib/GameServerConfig.d.ts +387 -0
  21. package/lib/GameServerConfig.js +1059 -0
  22. package/lib/GameServerLobbyRoom.d.ts +33 -0
  23. package/lib/GameServerLobbyRoom.js +56 -0
  24. package/lib/GameServerLogger.d.ts +111 -0
  25. package/lib/GameServerLogger.js +190 -0
  26. package/lib/GameServerMetrics.d.ts +158 -0
  27. package/lib/GameServerMetrics.js +276 -0
  28. package/lib/GameServerState.d.ts +164 -0
  29. package/lib/GameServerState.js +26 -0
  30. package/lib/HeadlessRuntime.d.ts +316 -0
  31. package/lib/HeadlessRuntime.js +380 -0
  32. package/lib/JoinGate.d.ts +34 -0
  33. package/lib/JoinGate.js +221 -0
  34. package/lib/NetworkAddresses.d.ts +33 -0
  35. package/lib/NetworkAddresses.js +90 -0
  36. package/lib/PlayerTokens.d.ts +17 -0
  37. package/lib/PlayerTokens.js +24 -0
  38. package/lib/RoomServerTransport.d.ts +73 -0
  39. package/lib/RoomServerTransport.js +90 -0
  40. package/lib/ServerEndpoints.d.ts +133 -0
  41. package/lib/ServerEndpoints.js +247 -0
  42. package/lib/ServerInit.d.ts +28 -0
  43. package/lib/ServerInit.js +113 -0
  44. package/lib/SessionRoom.d.ts +391 -0
  45. package/lib/SessionRoom.js +930 -0
  46. package/lib/TlsCertificates.d.ts +35 -0
  47. package/lib/TlsCertificates.js +130 -0
  48. package/lib/admin/AccountRoutes.d.ts +8 -0
  49. package/lib/admin/AccountRoutes.js +502 -0
  50. package/lib/admin/AdminAccounts.d.ts +329 -0
  51. package/lib/admin/AdminAccounts.js +607 -0
  52. package/lib/admin/AdminApiRouter.d.ts +202 -0
  53. package/lib/admin/AdminApiRouter.js +465 -0
  54. package/lib/admin/AdminApiTypes.d.ts +1782 -0
  55. package/lib/admin/AdminApiTypes.js +4 -0
  56. package/lib/admin/AdminAudit.d.ts +113 -0
  57. package/lib/admin/AdminAudit.js +266 -0
  58. package/lib/admin/AdminCli.d.ts +7 -0
  59. package/lib/admin/AdminCli.js +351 -0
  60. package/lib/admin/AdminClock.d.ts +51 -0
  61. package/lib/admin/AdminClock.js +10 -0
  62. package/lib/admin/AdminConsole.d.ts +39 -0
  63. package/lib/admin/AdminConsole.js +325 -0
  64. package/lib/admin/AdminConstants.d.ts +147 -0
  65. package/lib/admin/AdminConstants.js +167 -0
  66. package/lib/admin/AdminCrypto.d.ts +19 -0
  67. package/lib/admin/AdminCrypto.js +29 -0
  68. package/lib/admin/AdminExtensionsHost.d.ts +176 -0
  69. package/lib/admin/AdminExtensionsHost.js +307 -0
  70. package/lib/admin/AdminPasswords.d.ts +33 -0
  71. package/lib/admin/AdminPasswords.js +92 -0
  72. package/lib/admin/AdminPermissions.d.ts +28 -0
  73. package/lib/admin/AdminPermissions.js +74 -0
  74. package/lib/admin/AdminRecords.d.ts +196 -0
  75. package/lib/admin/AdminRecords.js +3 -0
  76. package/lib/admin/AdminRequestBodies.d.ts +47 -0
  77. package/lib/admin/AdminRequestBodies.js +84 -0
  78. package/lib/admin/AdminRequestGate.d.ts +38 -0
  79. package/lib/admin/AdminRequestGate.js +59 -0
  80. package/lib/admin/AdminResponses.d.ts +103 -0
  81. package/lib/admin/AdminResponses.js +164 -0
  82. package/lib/admin/AdminServices.d.ts +99 -0
  83. package/lib/admin/AdminServices.js +4 -0
  84. package/lib/admin/AdminStaticFiles.d.ts +29 -0
  85. package/lib/admin/AdminStaticFiles.js +97 -0
  86. package/lib/admin/AdminStore.d.ts +152 -0
  87. package/lib/admin/AdminStore.js +46 -0
  88. package/lib/admin/AlertChannels.d.ts +43 -0
  89. package/lib/admin/AlertChannels.js +120 -0
  90. package/lib/admin/AlertEngine.d.ts +231 -0
  91. package/lib/admin/AlertEngine.js +681 -0
  92. package/lib/admin/AlertRoutes.d.ts +8 -0
  93. package/lib/admin/AlertRoutes.js +180 -0
  94. package/lib/admin/ApiKeyRoutes.d.ts +8 -0
  95. package/lib/admin/ApiKeyRoutes.js +53 -0
  96. package/lib/admin/ApiKeys.d.ts +63 -0
  97. package/lib/admin/ApiKeys.js +167 -0
  98. package/lib/admin/AuditRoutes.d.ts +8 -0
  99. package/lib/admin/AuditRoutes.js +106 -0
  100. package/lib/admin/AuthToolRoutes.d.ts +13 -0
  101. package/lib/admin/AuthToolRoutes.js +164 -0
  102. package/lib/admin/BanList.d.ts +87 -0
  103. package/lib/admin/BanList.js +152 -0
  104. package/lib/admin/CborDecoder.d.ts +18 -0
  105. package/lib/admin/CborDecoder.js +201 -0
  106. package/lib/admin/ColyseusCloudClient.d.ts +313 -0
  107. package/lib/admin/ColyseusCloudClient.js +272 -0
  108. package/lib/admin/ColyseusCloudRoutes.d.ts +8 -0
  109. package/lib/admin/ColyseusCloudRoutes.js +91 -0
  110. package/lib/admin/ColyseusCloudService.d.ts +180 -0
  111. package/lib/admin/ColyseusCloudService.js +476 -0
  112. package/lib/admin/ColyseusCloudSettings.d.ts +16 -0
  113. package/lib/admin/ColyseusCloudSettings.js +29 -0
  114. package/lib/admin/ColyseusCloudViews.d.ts +105 -0
  115. package/lib/admin/ColyseusCloudViews.js +371 -0
  116. package/lib/admin/CommonPasswords.d.ts +6 -0
  117. package/lib/admin/CommonPasswords.js +19 -0
  118. package/lib/admin/ConfigOverrides.d.ts +174 -0
  119. package/lib/admin/ConfigOverrides.js +406 -0
  120. package/lib/admin/ConfigRoutes.d.ts +8 -0
  121. package/lib/admin/ConfigRoutes.js +91 -0
  122. package/lib/admin/ConsoleSessions.d.ts +112 -0
  123. package/lib/admin/ConsoleSessions.js +201 -0
  124. package/lib/admin/DedicatedRoutes.d.ts +21 -0
  125. package/lib/admin/DedicatedRoutes.js +254 -0
  126. package/lib/admin/ExtensionRoutes.d.ts +8 -0
  127. package/lib/admin/ExtensionRoutes.js +145 -0
  128. package/lib/admin/FileAdminStore.d.ts +157 -0
  129. package/lib/admin/FileAdminStore.js +349 -0
  130. package/lib/admin/FleetDirectory.d.ts +323 -0
  131. package/lib/admin/FleetDirectory.js +489 -0
  132. package/lib/admin/FleetLeader.d.ts +43 -0
  133. package/lib/admin/FleetLeader.js +89 -0
  134. package/lib/admin/FleetRoutes.d.ts +55 -0
  135. package/lib/admin/FleetRoutes.js +465 -0
  136. package/lib/admin/HealthWarnings.d.ts +10 -0
  137. package/lib/admin/HealthWarnings.js +95 -0
  138. package/lib/admin/LeaderboardRoutes.d.ts +8 -0
  139. package/lib/admin/LeaderboardRoutes.js +569 -0
  140. package/lib/admin/LogBuffer.d.ts +60 -0
  141. package/lib/admin/LogBuffer.js +92 -0
  142. package/lib/admin/LogRedaction.d.ts +15 -0
  143. package/lib/admin/LogRedaction.js +72 -0
  144. package/lib/admin/LogRoutes.d.ts +45 -0
  145. package/lib/admin/LogRoutes.js +307 -0
  146. package/lib/admin/MaintenanceMode.d.ts +41 -0
  147. package/lib/admin/MaintenanceMode.js +74 -0
  148. package/lib/admin/MaintenanceWindows.d.ts +91 -0
  149. package/lib/admin/MaintenanceWindows.js +207 -0
  150. package/lib/admin/MetricsRoutes.d.ts +8 -0
  151. package/lib/admin/MetricsRoutes.js +209 -0
  152. package/lib/admin/MetricsSampler.d.ts +124 -0
  153. package/lib/admin/MetricsSampler.js +211 -0
  154. package/lib/admin/OneTimeCodes.d.ts +60 -0
  155. package/lib/admin/OneTimeCodes.js +162 -0
  156. package/lib/admin/OpenIdConnect.d.ts +146 -0
  157. package/lib/admin/OpenIdConnect.js +335 -0
  158. package/lib/admin/Passkeys.d.ts +130 -0
  159. package/lib/admin/Passkeys.js +432 -0
  160. package/lib/admin/PlayerRoutes.d.ts +20 -0
  161. package/lib/admin/PlayerRoutes.js +676 -0
  162. package/lib/admin/RedisAdminStore.d.ts +114 -0
  163. package/lib/admin/RedisAdminStore.js +258 -0
  164. package/lib/admin/RolloutCoordinator.d.ts +99 -0
  165. package/lib/admin/RolloutCoordinator.js +321 -0
  166. package/lib/admin/ServerEvents.d.ts +57 -0
  167. package/lib/admin/ServerEvents.js +89 -0
  168. package/lib/admin/SessionRoutes.d.ts +113 -0
  169. package/lib/admin/SessionRoutes.js +386 -0
  170. package/lib/admin/UserRoutes.d.ts +8 -0
  171. package/lib/admin/UserRoutes.js +214 -0
  172. package/lib/cli.d.ts +2 -0
  173. package/lib/cli.js +221 -0
  174. package/lib/console/assets/index-CI5N7c-T.js +21 -0
  175. package/lib/console/assets/index-DPitvzLp.css +1 -0
  176. package/lib/console/favicon.svg +1 -0
  177. package/lib/console/index.html +16 -0
  178. package/lib/discord/DiscordOAuth.d.ts +57 -0
  179. package/lib/discord/DiscordOAuth.js +127 -0
  180. package/lib/discord/DiscordSessions.d.ts +79 -0
  181. package/lib/discord/DiscordSessions.js +135 -0
  182. package/lib/discord/DiscordSignInConstants.d.ts +54 -0
  183. package/lib/discord/DiscordSignInConstants.js +55 -0
  184. package/lib/discord/DiscordSignInRoutes.d.ts +51 -0
  185. package/lib/discord/DiscordSignInRoutes.js +359 -0
  186. package/lib/index.d.ts +24 -0
  187. package/lib/index.js +18 -0
  188. package/lib/leaderboards/FileLeaderboardRankStore.d.ts +293 -0
  189. package/lib/leaderboards/FileLeaderboardRankStore.js +808 -0
  190. package/lib/leaderboards/LeaderboardConstants.d.ts +63 -0
  191. package/lib/leaderboards/LeaderboardConstants.js +70 -0
  192. package/lib/leaderboards/LeaderboardError.d.ts +15 -0
  193. package/lib/leaderboards/LeaderboardError.js +20 -0
  194. package/lib/leaderboards/LeaderboardIdentity.d.ts +44 -0
  195. package/lib/leaderboards/LeaderboardIdentity.js +72 -0
  196. package/lib/leaderboards/LeaderboardPublicApi.d.ts +17 -0
  197. package/lib/leaderboards/LeaderboardPublicApi.js +389 -0
  198. package/lib/leaderboards/LeaderboardRankStore.d.ts +296 -0
  199. package/lib/leaderboards/LeaderboardRankStore.js +18 -0
  200. package/lib/leaderboards/LeaderboardRules.d.ts +122 -0
  201. package/lib/leaderboards/LeaderboardRules.js +472 -0
  202. package/lib/leaderboards/LeaderboardScheduler.d.ts +43 -0
  203. package/lib/leaderboards/LeaderboardScheduler.js +103 -0
  204. package/lib/leaderboards/LeaderboardService.d.ts +669 -0
  205. package/lib/leaderboards/LeaderboardService.js +1667 -0
  206. package/lib/leaderboards/LeaderboardTransfer.d.ts +35 -0
  207. package/lib/leaderboards/LeaderboardTransfer.js +580 -0
  208. package/lib/leaderboards/RedisLeaderboardRankStore.d.ts +282 -0
  209. package/lib/leaderboards/RedisLeaderboardRankStore.js +691 -0
  210. package/package.json +64 -4
  211. package/templates/init/Caddyfile +6 -0
  212. package/templates/init/DEPLOY.md +233 -0
  213. package/templates/init/Dockerfile +12 -0
  214. package/templates/init/app.json +21 -0
  215. package/templates/init/aws/README.md +118 -0
  216. package/templates/init/aws/ecs-fargate-alb.yml +207 -0
  217. package/templates/init/aws/ecs-fargate-nlb-quic.yml +210 -0
  218. package/templates/init/babylon-game-server.config.mjs +158 -0
  219. package/templates/init/colyseus-cloud/README.md +133 -0
  220. package/templates/init/colyseus-cloud/babylon-game-server.config.mjs +36 -0
  221. package/templates/init/colyseus-cloud/ecosystem.config.cjs +35 -0
  222. package/templates/init/colyseus-cloud/gitignore +6 -0
  223. package/templates/init/colyseus-cloud/package.json +15 -0
  224. package/templates/init/digitalocean-app.yaml +30 -0
  225. package/templates/init/docker-compose.full.yml +45 -0
  226. package/templates/init/docker-compose.websocket.yml +41 -0
  227. package/templates/init/fly.toml +56 -0
  228. package/templates/init/heroku.yml +11 -0
  229. package/templates/init/kubernetes/deployment.yaml +71 -0
  230. package/templates/init/kubernetes/redis.yaml +73 -0
  231. package/templates/init/kubernetes/service.yaml +24 -0
  232. package/templates/init/monitoring/grafana-dashboard.json +539 -0
  233. package/templates/init/monitoring/prometheus-alerts.yml +51 -0
  234. package/templates/init/monitoring/prometheus-scrape.yml +17 -0
  235. package/templates/init/railway.json +13 -0
  236. package/templates/init/render.yaml +19 -0
@@ -0,0 +1,1782 @@
1
+ /** One permission the console and API check (D17); AdminPermissions.ts lists them in this order. */
2
+ export type AdminPermission = "fleet.view" | "fleet.manage" | "sessions.view" | "sessions.manage" | "sessions.inspect" | "players.view" | "players.viewAddresses" | "players.manage" | "bans.view" | "bans.manage" | "dedicated.view" | "dedicated.manage" | "metrics.view" | "logs.view" | "logs.manage" | "config.view" | "config.manage" | "auth.view" | "auth.manage" | "alerts.view" | "alerts.manage" | "audit.view" | "audit.retention" | "users.view" | "users.manage" | "apiKeys.manage" | "players.notes" | "extensions.run" | "extensions.runDeveloper" | "cloud.view" | "cloud.billing" | "leaderboards.view" | "leaderboards.manage" | "leaderboards.submit";
3
+ /** One fixed admin role (D17), highest first in AdminPermissions.ADMIN_ROLES. */
4
+ export type AdminRole = "owner" | "admin" | "operator" | "moderator" | "developer" | "viewer";
5
+ /** Log levels, most severe first (structurally equal to the server's GameServerLogLevel). */
6
+ export type AdminLogLevel = "error" | "warn" | "info" | "debug";
7
+ /** How player tokens are verified (the server's AuthMode). */
8
+ export type AdminAuthMode = "shared-secret" | "jwt" | "webhook" | "custom";
9
+ /** Who made an admin call. */
10
+ export type AdminCallerKind = "user" | "apiKey" | "legacyToken" | "cli" | "system";
11
+ /** How prominent a notice to players is (the runtime's NetworkNoticeSeverity). */
12
+ export type AdminNoticeSeverity = "info" | "warning" | "critical";
13
+ /** Severity of an alert (spec 11). */
14
+ export type AdminAlertSeverity = "info" | "warning" | "critical";
15
+ /** What a ban matches. */
16
+ export type BanKind = "user" | "address" | "network";
17
+ /** Who started a dedicated session. */
18
+ export type DedicatedStartedBy = "boot" | "admin" | "onDemand" | "code";
19
+ /** A player's connection. */
20
+ export type PlayerTransport = "websocket" | "webtransport";
21
+ /** The chart ranges of the metrics page. */
22
+ export type MetricsRange = "15m" | "1h" | "6h" | "24h";
23
+ /** A page of a server-side list (ADMIN_PAGE_SIZE rows). */
24
+ export interface PageView<Item> {
25
+ /** The rows of this page. */
26
+ items: Item[];
27
+ /** Rows matching the filters, on every page. */
28
+ total: number;
29
+ }
30
+ /** The answer of an action with nothing else to say. */
31
+ export interface OkView {
32
+ /** Always true. */
33
+ ok: true;
34
+ }
35
+ /** The error body of every refused or failed call. */
36
+ export interface AdminErrorView {
37
+ /** One sentence for the admin. */
38
+ error: string;
39
+ /** Extra detail, e.g. the missing permission or "stepUp". */
40
+ detail?: string;
41
+ /** The current document of a 409 conflict. */
42
+ current?: unknown;
43
+ }
44
+ /** Per-admin console preferences. */
45
+ export interface AdminPreferences {
46
+ /** Colour theme. */
47
+ theme: "system" | "light" | "dark";
48
+ /** How times are shown. */
49
+ timeZone: "local" | "utc";
50
+ }
51
+ /** Maintenance in force on one instance (D14). */
52
+ export interface MaintenanceState {
53
+ /** Shown to refused players. */
54
+ message: string;
55
+ /** User ids still admitted. */
56
+ allowUserIds: string[];
57
+ /** Addresses still admitted. */
58
+ allowAddresses: string[];
59
+ /** True when readiness reports "maintenance". */
60
+ leaveReadiness: boolean;
61
+ /** "fleet" when it comes from the stored fleet setting, "instance" when set for this instance only. */
62
+ scope: "fleet" | "instance";
63
+ /** ISO time it ends by itself (scheduled windows), or null. */
64
+ endsAt: string | null;
65
+ }
66
+ /** The stored fleet maintenance setting (settings/maintenance). */
67
+ export interface MaintenanceSettings extends Omit<MaintenanceState, "scope" | "endsAt"> {
68
+ /** False when fleet maintenance is off. */
69
+ enabled: boolean;
70
+ }
71
+ /** What each instance publishes every FLEET_HEARTBEAT_INTERVAL_MS (D16). */
72
+ export interface InstanceHeartbeat {
73
+ processId: string;
74
+ publicAddress: string | null;
75
+ hostName: string;
76
+ instanceLabel: string | null;
77
+ serverVersion: string;
78
+ protocolVersion: number;
79
+ startedAt: string;
80
+ sentAt: string;
81
+ ready: boolean;
82
+ readinessReasons: string[];
83
+ draining: boolean;
84
+ drainDeadline: string | null;
85
+ maintenance: MaintenanceState | null;
86
+ players: number;
87
+ sessions: number;
88
+ dedicatedSessions: number;
89
+ cpuPercent: number;
90
+ residentMemoryBytes: number;
91
+ heapUsedBytes: number;
92
+ eventLoopLagMilliseconds: number;
93
+ certificateDaysLeft: number | null;
94
+ logLevel: AdminLogLevel;
95
+ /** Counter totals since start (0 when metrics are off). */
96
+ joinsAccepted: number;
97
+ joinsRefused: number;
98
+ refusalsByReason: Record<string, number>;
99
+ authFailures: number;
100
+ framesWebsocket: number;
101
+ framesWebtransport: number;
102
+ }
103
+ /** One captured log entry (redacted at capture, D21). */
104
+ export interface LogEntry {
105
+ /** Grows by one per entry on its instance. */
106
+ sequence: number;
107
+ time: string;
108
+ level: AdminLogLevel;
109
+ message: string;
110
+ fields: Record<string, unknown>;
111
+ }
112
+ /** A notice to players (the runtime's NetworkNoticePayload, DR §6.9). */
113
+ export interface AdminNoticePayload {
114
+ /** Unique per notice. */
115
+ noticeId: string;
116
+ /** At most NOTICE_TEXT_MAX_LENGTH characters. */
117
+ text: string;
118
+ severity: AdminNoticeSeverity;
119
+ /** Seconds until the announced event, or null. */
120
+ countdownSeconds: number | null;
121
+ /** Server time it was sent, in milliseconds since the epoch. */
122
+ sentAtMilliseconds: number;
123
+ }
124
+ /** A typed input of a custom admin action (D25). */
125
+ export interface AdminActionField {
126
+ name: string;
127
+ label: string;
128
+ type: "text" | "number" | "boolean" | "select" | "secret";
129
+ required: boolean;
130
+ /** The choices of a "select". */
131
+ options?: string[];
132
+ defaultValue?: string | number | boolean;
133
+ }
134
+ /** What a custom action targets; the console shows it on that page. */
135
+ export type AdminActionTarget = "server" | "instance" | "session" | "player";
136
+ /** The target ids of a custom action or panel: instance processId, session roomId, or a player. */
137
+ export interface AdminActionTargetIds {
138
+ processId?: string;
139
+ roomId?: string;
140
+ playerId?: number;
141
+ userId?: string | null;
142
+ }
143
+ /** What a custom action returns. */
144
+ export interface AdminActionResult {
145
+ ok: boolean;
146
+ message: string;
147
+ data?: Record<string, string | number | boolean | null>;
148
+ }
149
+ /** Where a custom panel is shown. */
150
+ export type AdminPanelPlacement = "overview" | "session" | "player";
151
+ /** Content of a custom panel. */
152
+ export type AdminPanelContent = {
153
+ kind: "table";
154
+ columns: string[];
155
+ rows: (string | number | boolean | null)[][];
156
+ } | {
157
+ kind: "values";
158
+ values: {
159
+ label: string;
160
+ value: string | number | boolean | null;
161
+ }[];
162
+ };
163
+ /** GET auth/methods: what the sign-in page offers. */
164
+ export interface SignInMethodsView {
165
+ local: boolean;
166
+ oidc: {
167
+ label: string;
168
+ } | null;
169
+ passkeys: boolean;
170
+ /** True while a first-owner setup link is pending. */
171
+ needsSetup: boolean;
172
+ }
173
+ /** POST setup/owner. */
174
+ export interface SetupOwnerRequest {
175
+ setupToken: string;
176
+ username: string;
177
+ displayName: string;
178
+ password: string;
179
+ }
180
+ /** POST auth/sign-in. */
181
+ export interface SignInRequest {
182
+ username: string;
183
+ password: string;
184
+ }
185
+ /** The next step of a sign-in. */
186
+ export interface SignInStepView {
187
+ stage: "secondFactor" | "enrolSecondFactor";
188
+ /** Names the half-finished sign-in in the next call. */
189
+ pendingToken: string;
190
+ }
191
+ /** POST auth/enrol. */
192
+ export interface AuthEnrolRequest {
193
+ pendingToken: string;
194
+ }
195
+ /** The authenticator secret to enrol (the only answer that shows it). */
196
+ export interface TotpEnrolmentView {
197
+ /** Base32 secret. */
198
+ secret: string;
199
+ /** otpauth:// URI for the QR code. */
200
+ otpauthUri: string;
201
+ }
202
+ /** POST auth/enrol/confirm. */
203
+ export interface AuthEnrolConfirmRequest {
204
+ pendingToken: string;
205
+ code: string;
206
+ }
207
+ /** POST auth/second-factor: a code or a recovery code. */
208
+ export interface AuthSecondFactorRequest {
209
+ pendingToken: string;
210
+ code?: string;
211
+ recoveryCode?: string;
212
+ }
213
+ /** A finished sign-in (the cookie comes with it). */
214
+ export interface SignedInView {
215
+ session: ConsoleSessionView;
216
+ /** New recovery codes after enrolment; empty otherwise. */
217
+ recoveryCodes: string[];
218
+ }
219
+ /** Whether the console's Colyseus Cloud page applies to this server (colyseus-cloud-console D8). */
220
+ export type ColyseusCloudFeature = "configured" | "setupNeeded" | "off";
221
+ /** Server features the console adapts its navigation to. */
222
+ export interface ConsoleFeaturesView {
223
+ /** "configured": a Cloud API token is set; "setupNeeded": on Colyseus Cloud without one; "off": the page is hidden. */
224
+ colyseusCloud: ColyseusCloudFeature;
225
+ }
226
+ /** GET auth/session: the signed-in admin. */
227
+ export interface ConsoleSessionView {
228
+ user: AdminUserView;
229
+ permissions: AdminPermission[];
230
+ /** Sent back as x-admin-csrf on POST, PUT and DELETE. */
231
+ csrfToken: string;
232
+ secondFactorAt: string;
233
+ /** When the session ends at the latest (absolute timeout). */
234
+ expiresAt: string;
235
+ /** Server features the console adapts its navigation to (colyseus-cloud-console D8). */
236
+ features: ConsoleFeaturesView;
237
+ }
238
+ /** POST auth/step-up: a code or a recovery code. */
239
+ export interface AuthStepUpRequest {
240
+ code?: string;
241
+ recoveryCode?: string;
242
+ }
243
+ /** GET account/sessions: one of the caller's console sessions. */
244
+ export interface AccountSessionView {
245
+ sessionId: string;
246
+ createdAt: string;
247
+ lastSeenAt: string;
248
+ clientAddress: string;
249
+ userAgent: string;
250
+ /** True for the session making the call. */
251
+ current: boolean;
252
+ }
253
+ /** PUT account/password. */
254
+ export interface AccountPasswordRequest {
255
+ currentPassword: string;
256
+ newPassword: string;
257
+ }
258
+ /** POST account/recovery-codes. */
259
+ export interface AccountRecoveryCodesView {
260
+ recoveryCodes: string[];
261
+ }
262
+ /** An admin account as the console shows it (never its secrets). */
263
+ export interface AdminUserView {
264
+ userId: string;
265
+ username: string;
266
+ displayName: string;
267
+ email: string | null;
268
+ role: AdminRole;
269
+ disabled: boolean;
270
+ locked: boolean;
271
+ hasSecondFactor: boolean;
272
+ createdAt: string;
273
+ lastSignInAt: string | null;
274
+ preferences: AdminPreferences;
275
+ /** The stored revision, for UpdateUserRequest.expectedRevision. */
276
+ revision: number;
277
+ }
278
+ /** POST users. */
279
+ export interface CreateUserRequest {
280
+ username: string;
281
+ displayName: string;
282
+ email: string | null;
283
+ role: AdminRole;
284
+ temporaryPassword: string;
285
+ }
286
+ /** PUT users/:userId. */
287
+ export interface UpdateUserRequest {
288
+ displayName?: string;
289
+ email?: string | null;
290
+ role?: AdminRole;
291
+ disabled?: boolean;
292
+ expectedRevision: number;
293
+ }
294
+ /** POST users/:userId/end-sessions. */
295
+ export interface UsersEndSessionsView {
296
+ ended: number;
297
+ }
298
+ /** An API key as the console shows it (never its secret). */
299
+ export interface ApiKeyView {
300
+ keyId: string;
301
+ name: string;
302
+ permissions: AdminPermission[];
303
+ expiresAt: string | null;
304
+ allowedNetworks: string[];
305
+ createdBy: string;
306
+ createdAt: string;
307
+ lastUsedAt: string | null;
308
+ revoked: boolean;
309
+ }
310
+ /** POST api-keys. */
311
+ export interface CreateApiKeyRequest {
312
+ name: string;
313
+ permissions: AdminPermission[];
314
+ expiresAt: string | null;
315
+ allowedNetworks: string[];
316
+ }
317
+ /** A new API key: its secret is shown this once. */
318
+ export interface CreatedApiKeyView {
319
+ key: ApiKeyView;
320
+ /** The full bearer value, bgsk_<keyId>_<secret>. */
321
+ secret: string;
322
+ }
323
+ /** The fleet at a glance (spec 2). */
324
+ export interface OverviewView {
325
+ instancesUp: number;
326
+ instancesLost: number;
327
+ players: number;
328
+ sessions: number;
329
+ playersByGameMode: Record<string, number>;
330
+ sessionsByGameMode: Record<string, number>;
331
+ dedicatedSessions: number;
332
+ joinsPerMinute: number;
333
+ refusalsPerMinute: number;
334
+ topRefusalReasons: {
335
+ reason: string;
336
+ perMinute: number;
337
+ }[];
338
+ authFailuresPerMinute: number;
339
+ transportShare: {
340
+ websocket: number;
341
+ webtransport: number;
342
+ };
343
+ versions: {
344
+ serverVersion: string;
345
+ protocolVersion: number;
346
+ instances: number;
347
+ }[];
348
+ certificateDaysLeft: number | null;
349
+ redis: "reachable" | "unreachable" | "not configured";
350
+ maintenance: "off" | "fleet" | "some instances";
351
+ draining: number;
352
+ scaledOut: boolean;
353
+ warnings: HealthWarningView[];
354
+ customPanels: AdminPanelView[];
355
+ activity: ActivityItemView[];
356
+ }
357
+ /** One health warning with the page that fixes it (spec 2). */
358
+ export interface HealthWarningView {
359
+ code: "authOffInProduction" | "originsOpen" | "metricsUnprotected" | "consoleOverHttp" | "certificateExpiring" | "mixedVersions" | "instanceLost" | "storeNotPersistent" | "fleetWithoutRedis";
360
+ severity: "info" | "warning" | "critical";
361
+ message: string;
362
+ /** Console hash route of the fix, e.g. "#/config?path=auth.enabled". */
363
+ fixRoute: string;
364
+ }
365
+ /** An instance row (spec 3). */
366
+ export interface InstanceView extends InstanceHeartbeat {
367
+ status: "up" | "lost";
368
+ isThisInstance: boolean;
369
+ }
370
+ /** An instance page. */
371
+ export interface InstanceDetailView {
372
+ instance: InstanceView;
373
+ sessions: SessionSummaryView[];
374
+ dedicated: DedicatedSessionView[];
375
+ }
376
+ /** POST instances/:processId/drain. */
377
+ export interface InstancesDrainRequest {
378
+ noticeText: string | null;
379
+ noticeLeadSeconds: number;
380
+ }
381
+ /** The answer of a drain. */
382
+ export interface DrainStartedView {
383
+ drainDeadline: string;
384
+ }
385
+ /** GET maintenance. */
386
+ export interface MaintenanceView {
387
+ fleet: MaintenanceSettings | null;
388
+ instances: {
389
+ processId: string;
390
+ maintenance: MaintenanceState | null;
391
+ }[];
392
+ windows: MaintenanceWindowView[];
393
+ }
394
+ /** PUT maintenance. */
395
+ export interface SetMaintenanceRequest {
396
+ /** "fleet" or a process id. */
397
+ scope: "fleet" | string;
398
+ enabled: boolean;
399
+ message: string;
400
+ allowUserIds: string[];
401
+ allowAddresses: string[];
402
+ leaveReadiness: boolean;
403
+ /** Seconds of warning notice sent first, or null. */
404
+ noticeSeconds: number | null;
405
+ }
406
+ /** A session row (spec 4). */
407
+ export interface SessionSummaryView {
408
+ roomId: string;
409
+ sessionName: string;
410
+ gameMode: string;
411
+ players: number;
412
+ maxPlayers: number;
413
+ processId: string;
414
+ publicAddress: string | null;
415
+ createdAt: string | null;
416
+ dedicatedScene: string | null;
417
+ hostPlayerId: number | null;
418
+ isOpen: boolean;
419
+ isVisible: boolean;
420
+ locked: boolean;
421
+ bytesPerSecond: number;
422
+ }
423
+ /** A session page (spec 4). */
424
+ export interface SessionDetailView extends SessionSummaryView {
425
+ properties: Record<string, string | number | boolean>;
426
+ tickRate: number | null;
427
+ players: number;
428
+ playerList: SessionPlayerView[];
429
+ traffic: {
430
+ framesIn: number;
431
+ framesOut: number;
432
+ bytesIn: number;
433
+ bytesOut: number;
434
+ };
435
+ /** The dedicated runner's scene, who started it and its frame history; null for a session without one. */
436
+ dedicated: {
437
+ sceneName: string;
438
+ startedBy: DedicatedStartedBy;
439
+ frameStatistics: DedicatedFrameBucketView[];
440
+ } | null;
441
+ hostMigrations: {
442
+ at: string;
443
+ fromPlayerId: number;
444
+ toPlayerId: number;
445
+ }[];
446
+ logLines: LogEntryView[];
447
+ }
448
+ /** One player of a session. */
449
+ export interface SessionPlayerView {
450
+ playerId: number;
451
+ userId: string | null;
452
+ /** claims.name ?? claims.preferred_username ?? null. */
453
+ displayName: string | null;
454
+ /** Null without players.viewAddresses. */
455
+ clientAddress: string | null;
456
+ transport: PlayerTransport;
457
+ joinedAt: string;
458
+ connected: boolean;
459
+ isHost: boolean;
460
+ isMasterClient: boolean;
461
+ }
462
+ /** The session inspector (spec 4, Should). */
463
+ export interface SessionInspectorView {
464
+ available: boolean;
465
+ reason: string | null;
466
+ objects: {
467
+ networkId: string;
468
+ kind: "prefab" | "scene";
469
+ name: string;
470
+ stateAuthorityPlayerId: number | null;
471
+ lastChangedTick: number | null;
472
+ stateWordCount: number;
473
+ }[];
474
+ }
475
+ /** POST sessions/:roomId/close. */
476
+ export interface SessionsCloseRequest {
477
+ message: string;
478
+ }
479
+ /** POST sessions/close-all. */
480
+ export interface SessionsCloseAllRequest {
481
+ message: string;
482
+ /** Must be exactly "close all sessions". */
483
+ confirmText: "close all sessions";
484
+ }
485
+ /** The answer of close-all. */
486
+ export interface SessionsCloseAllView {
487
+ closed: number;
488
+ }
489
+ /** POST sessions/:roomId/lock. */
490
+ export interface SessionsLockRequest {
491
+ locked: boolean;
492
+ }
493
+ /** POST notices. */
494
+ export interface SendNoticeRequest {
495
+ scope: "fleet" | "instance" | "session" | "player";
496
+ processId?: string;
497
+ roomId?: string;
498
+ playerId?: number;
499
+ text: string;
500
+ severity: AdminNoticeSeverity;
501
+ countdownSeconds: number | null;
502
+ }
503
+ /** The answer of a notice. */
504
+ export interface NoticeSentView {
505
+ targetedPlayers: number;
506
+ }
507
+ /** A player search row. */
508
+ export interface PlayerSummaryView {
509
+ roomId: string;
510
+ sessionName: string;
511
+ processId: string;
512
+ playerId: number;
513
+ userId: string | null;
514
+ displayName: string | null;
515
+ clientAddress: string | null;
516
+ transport: PlayerTransport;
517
+ joinedAt: string;
518
+ }
519
+ /** A player page. */
520
+ export interface PlayerDetailView {
521
+ userId: string | null;
522
+ address: string | null;
523
+ /** Values of claims named like secrets show "[hidden]". */
524
+ claims: Record<string, unknown> | null;
525
+ online: PlayerSummaryView[];
526
+ recentSessions: PlayerSessionHistoryView[];
527
+ bans: BanView[];
528
+ /** Empty without players.notes. */
529
+ notes: PlayerNoteView[];
530
+ /** Empty without players.notes. */
531
+ kicks: AuditRecordView[];
532
+ }
533
+ /** A past session of a player (stream playerHistory). */
534
+ export interface PlayerSessionHistoryView {
535
+ roomId: string;
536
+ sessionName: string;
537
+ processId: string;
538
+ playerId: number;
539
+ joinedAt: string;
540
+ leftAt: string | null;
541
+ }
542
+ /** A note on a player. */
543
+ export interface PlayerNoteView {
544
+ noteId: string;
545
+ subject: string;
546
+ text: string;
547
+ by: string;
548
+ at: string;
549
+ }
550
+ /** POST players/kick. */
551
+ export interface KickPlayerRequest {
552
+ roomId: string;
553
+ playerId: number;
554
+ message: string;
555
+ allowRejoin: boolean;
556
+ }
557
+ /** POST players/notes. */
558
+ export interface PlayersNotesRequest {
559
+ /** A user id or an address. */
560
+ subject: string;
561
+ text: string;
562
+ }
563
+ /** POST lobby/kick. */
564
+ export interface LobbyKickRequest {
565
+ userId: string | null;
566
+ address: string | null;
567
+ }
568
+ /** The answer of a lobby kick. */
569
+ export interface LobbyKickView {
570
+ disconnected: number;
571
+ }
572
+ /** One change in a ban's history. */
573
+ export interface BanHistoryEntry {
574
+ at: string;
575
+ by: string;
576
+ change: string;
577
+ }
578
+ /** A ban as the console shows it. */
579
+ export interface BanView {
580
+ banId: string;
581
+ kind: BanKind;
582
+ /** User id, address, or CIDR range. */
583
+ value: string;
584
+ reason: string;
585
+ note: string;
586
+ /** Null for a permanent ban. */
587
+ expiresAt: string | null;
588
+ createdBy: string;
589
+ createdAt: string;
590
+ active: boolean;
591
+ revision: number;
592
+ history: BanHistoryEntry[];
593
+ }
594
+ /** POST bans. */
595
+ export interface CreateBanRequest {
596
+ kind: BanKind;
597
+ value: string;
598
+ /** Null for a permanent ban. */
599
+ durationSeconds: number | null;
600
+ reason: string;
601
+ note: string;
602
+ /** Confirms a ban of an address many players may share. */
603
+ confirmSharedAddress: boolean;
604
+ }
605
+ /** PUT bans/:banId. */
606
+ export interface BansUpdateRequest {
607
+ expiresAt: string | null;
608
+ reason: string;
609
+ note: string;
610
+ expectedRevision: number;
611
+ }
612
+ /** The bans.json download and the bans/import body (R30). */
613
+ export interface BanExportFile {
614
+ version: 1;
615
+ exportedAt: string;
616
+ bans: {
617
+ kind: BanKind;
618
+ value: string;
619
+ reason: string;
620
+ note: string;
621
+ expiresAt: string | null;
622
+ }[];
623
+ }
624
+ /** POST bans/import. */
625
+ export type BansImportRequest = BanExportFile;
626
+ /** The answer of a ban import. */
627
+ export interface BansImportView {
628
+ imported: number;
629
+ skipped: number;
630
+ }
631
+ /** GET dedicated (spec 6). */
632
+ export interface DedicatedView {
633
+ scenes: DedicatedSceneView[];
634
+ sessions: DedicatedSessionView[];
635
+ }
636
+ /** A configured dedicated scene. */
637
+ export interface DedicatedSceneView {
638
+ name: string;
639
+ sceneRoot: string;
640
+ sceneFile: string;
641
+ projectScripts: string[];
642
+ maxPlayers: number;
643
+ onDemand: boolean;
644
+ idleSeconds: number;
645
+ source: "config";
646
+ }
647
+ /** A running dedicated session. */
648
+ export interface DedicatedSessionView {
649
+ roomId: string;
650
+ sessionName: string;
651
+ sceneName: string;
652
+ processId: string;
653
+ players: number;
654
+ maxPlayers: number;
655
+ startedBy: DedicatedStartedBy;
656
+ frameStatistics: DedicatedFrameBucketView[];
657
+ }
658
+ /** One DEDICATED_FRAME_BUCKET_SECONDS bucket of a dedicated runner's frames. */
659
+ export interface DedicatedFrameBucketView {
660
+ at: string;
661
+ averageFrameMilliseconds: number;
662
+ maximumFrameMilliseconds: number;
663
+ tickOverruns: number;
664
+ }
665
+ /** POST dedicated/start. */
666
+ export interface DedicatedStartRequest {
667
+ sceneName: string;
668
+ sessionName: string;
669
+ /** The instance to run it on, or null for this one. */
670
+ processId: string | null;
671
+ }
672
+ /** The answer of a dedicated start or restart. */
673
+ export interface DedicatedStartedView {
674
+ roomId: string;
675
+ }
676
+ /** POST dedicated/:roomId/stop. */
677
+ export interface DedicatedStopRequest {
678
+ message: string;
679
+ }
680
+ /** POST dedicated/:roomId/restart. */
681
+ export interface DedicatedRestartRequest {
682
+ message: string;
683
+ }
684
+ /** What a stopped dedicated session needs to start again under the same name (R17), returned before it disconnects. */
685
+ export interface DedicatedRestartOptions {
686
+ sceneName: string;
687
+ sessionName: string;
688
+ /** The instance that ran it. */
689
+ processId: string;
690
+ }
691
+ /** POST dedicated/scenes/:sceneName/check. */
692
+ export interface DedicatedScenesCheckRequest {
693
+ processId: string | null;
694
+ }
695
+ /** Whether a scene's files load. */
696
+ export interface SceneCheckView {
697
+ sceneName: string;
698
+ ok: boolean;
699
+ files: {
700
+ url: string;
701
+ ok: boolean;
702
+ status: number | null;
703
+ error: string | null;
704
+ }[];
705
+ }
706
+ /** One chart point: rates per second are computed from counter differences. */
707
+ export interface MetricsPointView {
708
+ at: string;
709
+ players: number;
710
+ sessions: number;
711
+ dedicatedSessions: number;
712
+ joinsPerSecond: number;
713
+ refusalsPerSecond: number;
714
+ authFailuresPerSecond: number;
715
+ bytesInPerSecond: number;
716
+ bytesOutPerSecond: number;
717
+ messagesInPerSecond: number;
718
+ cpuPercent: number;
719
+ residentMemoryBytes: number;
720
+ heapUsedBytes: number;
721
+ eventLoopLagMilliseconds: number;
722
+ gcMillisecondsPerSecond: number;
723
+ dedicatedFrameMillisecondsAverage: number;
724
+ dedicatedTickOverrunsPerSecond: number;
725
+ /** Accepted leaderboard scores per second (game-server-leaderboards D21). */
726
+ leaderboardAcceptedPerSecond: number;
727
+ /** Refused leaderboard scores per second (game-server-leaderboards D21). */
728
+ leaderboardRefusedPerSecond: number;
729
+ }
730
+ /** GET metrics (spec 7). */
731
+ export interface MetricsSeriesView {
732
+ /** "fleet" or a process id. */
733
+ processId: string;
734
+ range: MetricsRange;
735
+ points: MetricsPointView[];
736
+ grafanaUrl: string | null;
737
+ }
738
+ /** A log line (spec 8). */
739
+ export interface LogEntryView extends LogEntry {
740
+ processId: string;
741
+ }
742
+ /** GET logs. */
743
+ export interface LogPageView {
744
+ entries: LogEntryView[];
745
+ /** JSON cursor for the next ?after=. */
746
+ cursor: string;
747
+ }
748
+ /** PUT logs/level. */
749
+ export interface LogsLevelRequest {
750
+ /** "fleet" or a process id. */
751
+ scope: "fleet" | string;
752
+ level: AdminLogLevel;
753
+ revertAfterMinutes: number;
754
+ }
755
+ /** GET config (spec 9). */
756
+ export interface ConfigView {
757
+ processId: string;
758
+ /** The configOverrides document revision, or null when none is stored. */
759
+ revision: number | null;
760
+ options: ConfigOptionView[];
761
+ dedicatedScenes: DedicatedSceneView[];
762
+ }
763
+ /** One option of the config page. */
764
+ export interface ConfigOptionView {
765
+ path: string;
766
+ environmentVariable: string;
767
+ flag: string | null;
768
+ description: string;
769
+ isSecret: boolean;
770
+ /** The value, or "set" / "not set" for secrets. */
771
+ value: unknown;
772
+ source: "default" | "platform" | "file" | "environment" | "flag" | "code" | "override";
773
+ liveEditable: boolean;
774
+ locked: boolean;
775
+ needsRestart: boolean;
776
+ }
777
+ /** PUT config/overrides. */
778
+ export interface ConfigOverridesRequest {
779
+ /** "fleet" or a process id. */
780
+ scope: "fleet" | string;
781
+ path: string;
782
+ value: unknown;
783
+ expectedRevision: number | null;
784
+ }
785
+ /** One config change of the history. */
786
+ export interface ConfigChangeView {
787
+ at: string;
788
+ by: string;
789
+ scope: "fleet" | string;
790
+ path: string;
791
+ before: unknown;
792
+ after: unknown;
793
+ reverted: boolean;
794
+ }
795
+ /** GET auth-tools/status (spec 10). */
796
+ export interface AuthStatusView {
797
+ enabled: boolean;
798
+ mode: AdminAuthMode;
799
+ issuer: string | null;
800
+ audience: string | null;
801
+ jwksUrl: string | null;
802
+ jwksCacheAgeSeconds: number | null;
803
+ /** Shown as scheme://host/… only. */
804
+ webhookUrl: string | null;
805
+ webhookTimeoutMs: number;
806
+ sharedSecretTokens: "set" | "not set";
807
+ jwtSecret: "set" | "not set";
808
+ failuresLastHour: {
809
+ reason: string;
810
+ count: number;
811
+ }[];
812
+ topFailingAddresses: {
813
+ address: string;
814
+ count: number;
815
+ }[];
816
+ }
817
+ /** POST auth-tools/test-token. */
818
+ export interface AuthToolsTestTokenRequest {
819
+ token: string;
820
+ kind: "session" | "lobby";
821
+ sessionName: string | null;
822
+ }
823
+ /** The answer of a token test. */
824
+ export interface TokenTestView {
825
+ accepted: boolean;
826
+ /** The verified identity; userId is null for a token that names no user (shared-secret mode). */
827
+ identity: {
828
+ userId: string | null;
829
+ claims: Record<string, unknown>;
830
+ } | null;
831
+ refusal: string | null;
832
+ }
833
+ /** POST auth-tools/reload-keys. */
834
+ export interface AuthToolsReloadKeysView {
835
+ reloadedInstances: number;
836
+ failures: string[];
837
+ }
838
+ /** The alert rules (spec 11). */
839
+ export type AlertRuleId = "instanceLost" | "instanceNotReady" | "redisUnreachable" | "refusalSpike" | "authFailureSpike" | "eventLoopLag" | "memoryHigh" | "dedicatedOverruns" | "certificateExpiring" | "versionMismatch" | "nearLimits" | "newAdminAddress" | "accountLockout";
840
+ /** An alert rule with its settings. */
841
+ export interface AlertRuleView {
842
+ ruleId: AlertRuleId;
843
+ label: string;
844
+ enabled: boolean;
845
+ threshold: number | null;
846
+ thresholdUnit: string | null;
847
+ forMinutes: number;
848
+ severity: AdminAlertSeverity;
849
+ channelIds: string[];
850
+ silencedUntil: string | null;
851
+ revision: number;
852
+ }
853
+ /** PUT alerts/rules/:ruleId. */
854
+ export interface AlertsRulesRequest {
855
+ enabled: boolean;
856
+ threshold: number | null;
857
+ forMinutes: number;
858
+ severity: AdminAlertSeverity;
859
+ channelIds: string[];
860
+ }
861
+ /** POST alerts/rules/:ruleId/silence. */
862
+ export interface AlertsRulesSilenceRequest {
863
+ minutes: number;
864
+ }
865
+ /** The kinds of alert channel. */
866
+ export type AlertChannelKind = "webhook" | "slack" | "discord" | "teams" | "pagerduty";
867
+ /** An alert channel (secrets shown as set / not set). */
868
+ export interface AlertChannelView {
869
+ channelId: string;
870
+ kind: AlertChannelKind;
871
+ name: string;
872
+ /** Shown as scheme://host/… (path hidden). */
873
+ url: string | null;
874
+ routingKey: "set" | "not set";
875
+ }
876
+ /** POST alerts/channels. */
877
+ export interface CreateAlertChannelRequest {
878
+ kind: AlertChannelKind;
879
+ name: string;
880
+ url: string | null;
881
+ routingKey: string | null;
882
+ }
883
+ /** POST alerts/channels/:channelId/test. */
884
+ export interface AlertChannelTestView {
885
+ delivered: boolean;
886
+ error: string | null;
887
+ }
888
+ /** A fired alert. */
889
+ export interface AlertView {
890
+ alertId: string;
891
+ ruleId: AlertRuleId;
892
+ severity: AdminAlertSeverity;
893
+ summary: string;
894
+ processId: string | null;
895
+ state: "firing" | "resolved";
896
+ firedAt: string;
897
+ resolvedAt: string | null;
898
+ acknowledgedBy: string | null;
899
+ acknowledgedAt: string | null;
900
+ deliveries: {
901
+ channelId: string;
902
+ ok: boolean;
903
+ error: string | null;
904
+ at: string;
905
+ }[];
906
+ }
907
+ /** A scheduled maintenance window (spec 3, Should). */
908
+ export interface MaintenanceWindowView {
909
+ windowId: string;
910
+ startsAt: string;
911
+ endsAt: string;
912
+ message: string;
913
+ warningMinutes: number | null;
914
+ state: "scheduled" | "warning" | "active" | "done" | "cancelled";
915
+ createdBy: string;
916
+ }
917
+ /** POST maintenance/windows. */
918
+ export interface MaintenanceWindowsRequest {
919
+ startsAt: string;
920
+ endsAt: string;
921
+ message: string;
922
+ warningMinutes: number | null;
923
+ allowUserIds: string[];
924
+ allowAddresses: string[];
925
+ leaveReadiness: boolean;
926
+ }
927
+ /** One instance's step of a rolling update. */
928
+ export interface RolloutStepView {
929
+ processId: string;
930
+ state: "waiting" | "noticeSent" | "draining" | "replaced" | "failed";
931
+ replacementProcessId: string | null;
932
+ message: string | null;
933
+ }
934
+ /** A rolling update. */
935
+ export interface RolloutView {
936
+ rolloutId: string;
937
+ state: "running" | "paused" | "done" | "cancelled" | "failed";
938
+ startedAt: string;
939
+ startedBy: string;
940
+ steps: RolloutStepView[];
941
+ message: string | null;
942
+ }
943
+ /** POST rollouts. */
944
+ export interface RolloutsRequest {
945
+ noticeText: string | null;
946
+ noticeLeadSeconds: number;
947
+ perInstanceTimeoutMinutes: number;
948
+ }
949
+ /** One audit record (spec 12). */
950
+ export interface AuditRecordView {
951
+ sequence: number;
952
+ at: string;
953
+ actor: {
954
+ kind: AdminCallerKind;
955
+ id: string;
956
+ name: string;
957
+ };
958
+ clientAddress: string | null;
959
+ processId: string;
960
+ action: string;
961
+ target: string | null;
962
+ parameters: Record<string, unknown>;
963
+ result: {
964
+ ok: boolean;
965
+ detail: string | null;
966
+ };
967
+ previousHash: string;
968
+ hash: string;
969
+ }
970
+ /** GET audit/verify. */
971
+ export interface AuditVerifyView {
972
+ ok: boolean;
973
+ checked: number;
974
+ brokenAtSequence: number | null;
975
+ }
976
+ /** PUT audit/retention and its answer. */
977
+ export interface AuditRetentionRequest {
978
+ days: number;
979
+ }
980
+ /** An activity feed item (spec 2, Should). */
981
+ export interface ActivityItemView {
982
+ at: string;
983
+ kind: "admin" | "server";
984
+ text: string;
985
+ processId: string | null;
986
+ }
987
+ /** A custom action as the console sees it (spec 13). */
988
+ export interface AdminActionView {
989
+ name: string;
990
+ label: string;
991
+ description: string;
992
+ target: AdminActionTarget;
993
+ fields: AdminActionField[];
994
+ confirm: boolean;
995
+ }
996
+ /** A custom panel as the console sees it. */
997
+ export interface AdminPanelView {
998
+ name: string;
999
+ title: string;
1000
+ placement: AdminPanelPlacement;
1001
+ }
1002
+ /** GET extensions: the actions and panels the caller may use. */
1003
+ export interface ExtensionsView {
1004
+ actions: AdminActionView[];
1005
+ panels: AdminPanelView[];
1006
+ }
1007
+ /** POST extensions/actions/:actionName. */
1008
+ export interface ExtensionsActionsRequest {
1009
+ target: AdminActionTargetIds;
1010
+ inputs: Record<string, unknown>;
1011
+ }
1012
+ /** GET docs/:documentName. */
1013
+ export interface DocsView {
1014
+ markdown: string;
1015
+ }
1016
+ /** A COSE algorithm a passkey may use: ES256, RS256 or EdDSA. */
1017
+ export type PasskeyAlgorithm = -7 | -257 | -8;
1018
+ /** Options of navigator.credentials.create. */
1019
+ export interface PasskeyCreationOptionsView {
1020
+ challenge: string;
1021
+ rp: {
1022
+ id: string;
1023
+ name: string;
1024
+ };
1025
+ user: {
1026
+ id: string;
1027
+ name: string;
1028
+ displayName: string;
1029
+ };
1030
+ pubKeyCredParams: {
1031
+ type: "public-key";
1032
+ alg: PasskeyAlgorithm;
1033
+ }[];
1034
+ timeout: number;
1035
+ attestation: "none";
1036
+ authenticatorSelection: {
1037
+ residentKey: "preferred";
1038
+ userVerification: "preferred";
1039
+ };
1040
+ excludeCredentials: {
1041
+ type: "public-key";
1042
+ id: string;
1043
+ }[];
1044
+ }
1045
+ /** Options of navigator.credentials.get. */
1046
+ export interface PasskeyRequestOptionsView {
1047
+ challenge: string;
1048
+ rpId: string;
1049
+ timeout: number;
1050
+ userVerification: "preferred";
1051
+ allowCredentials: {
1052
+ type: "public-key";
1053
+ id: string;
1054
+ }[];
1055
+ }
1056
+ /** The result of navigator.credentials.create. */
1057
+ export interface PasskeyAttestationView {
1058
+ id: string;
1059
+ rawId: string;
1060
+ type: "public-key";
1061
+ response: {
1062
+ clientDataJSON: string;
1063
+ attestationObject: string;
1064
+ };
1065
+ }
1066
+ /** The result of navigator.credentials.get. */
1067
+ export interface PasskeyAssertionView {
1068
+ id: string;
1069
+ rawId: string;
1070
+ type: "public-key";
1071
+ response: {
1072
+ clientDataJSON: string;
1073
+ authenticatorData: string;
1074
+ signature: string;
1075
+ userHandle: string | null;
1076
+ };
1077
+ }
1078
+ /** A registered passkey. */
1079
+ export interface PasskeyView {
1080
+ passkeyId: string;
1081
+ name: string;
1082
+ createdAt: string;
1083
+ lastUsedAt: string | null;
1084
+ }
1085
+ /** POST auth/passkey/options. */
1086
+ export interface AuthPasskeyOptionsRequest {
1087
+ username: string | null;
1088
+ }
1089
+ /** POST auth/passkey/verify. */
1090
+ export interface AuthPasskeyVerifyRequest {
1091
+ pendingToken: string | null;
1092
+ credential: PasskeyAssertionView;
1093
+ }
1094
+ /** POST account/passkeys. */
1095
+ export interface AccountPasskeysRequest {
1096
+ name: string;
1097
+ credential: PasskeyAttestationView;
1098
+ }
1099
+ /** A cached Colyseus Cloud resource, refreshed by the fleet leader at Colyseus's own cadence (D3, D4). */
1100
+ export type CloudResourceName = "applications" | "metricsCurrent" | "metricsDay" | "egress" | "deploys" | "billing";
1101
+ /** Resolution of the Cloud load history. */
1102
+ export type CloudHistoryResolution = "minute" | "day";
1103
+ /** Which output stream of an instance's logs to read. */
1104
+ export type CloudLogStream = "all" | "out" | "err";
1105
+ /** How many log lines to read (Colyseus rounds to these). */
1106
+ export type CloudLogLines = 100 | 500;
1107
+ /** Why a Cloud part could not be refreshed or no application could be chosen. */
1108
+ export interface CloudProblemView {
1109
+ /** HTTP status Colyseus answered, or 0 when it did not answer or the problem is not an answer of Colyseus. */
1110
+ status: number;
1111
+ /** Colyseus's error code (e.g. "unauthenticated", "rate_limited") or one of ours ("unreachable", "unknown_application", "several_applications", "no_applications"). */
1112
+ code: string;
1113
+ /** Human-readable explanation. */
1114
+ message: string;
1115
+ }
1116
+ /** How current a Cloud part is. */
1117
+ export interface CloudFreshnessView {
1118
+ /** When the shown data was fetched (ISO), or null before the first success. */
1119
+ fetchedAt: string | null;
1120
+ /** When the last attempt ran (ISO), or null before the first. */
1121
+ attemptedAt: string | null;
1122
+ /** How often Colyseus refreshes this data, in seconds. */
1123
+ refreshSeconds: number;
1124
+ /** True when the last attempt failed or the data is older than twice its refresh interval plus a grace. */
1125
+ isStale: boolean;
1126
+ /** The last attempt's problem, or null when it succeeded. */
1127
+ problem: CloudProblemView | null;
1128
+ }
1129
+ /** One part of the Cloud page: its last good data and how current it is. */
1130
+ export interface CloudPart<Data> {
1131
+ /** The last good data, or null before the first success. */
1132
+ data: Data | null;
1133
+ /** How current the data is. */
1134
+ freshness: CloudFreshnessView;
1135
+ }
1136
+ /** A Cloud instance in the application overview. */
1137
+ export interface CloudInstanceView {
1138
+ /** Colyseus's instance id (used for logs). */
1139
+ id: number;
1140
+ /** Instance address, or null until it has one. */
1141
+ endpoint: string | null;
1142
+ /** pending, provisioning, installing, ready, error, destroying, resizing, unpaid or parked. */
1143
+ status: string;
1144
+ /** The deploy status values, or null. */
1145
+ deployStatus: string | null;
1146
+ /** When it was last deployed (ISO), or null. */
1147
+ deployedAt: string | null;
1148
+ /** True for the instance this console is served from (D11). */
1149
+ isThisInstance: boolean;
1150
+ }
1151
+ /** A location's plan. */
1152
+ export interface CloudPlanView {
1153
+ /** Virtual CPUs. */
1154
+ vcpus: number;
1155
+ /** Memory in megabytes. */
1156
+ ramMegabytes: number;
1157
+ /** Monthly transfer included per instance, in gigabytes. */
1158
+ transferGigabytes: number;
1159
+ }
1160
+ /** A Cloud location (region) of the application. */
1161
+ export interface CloudLocationView {
1162
+ /** Colyseus's location id. */
1163
+ id: number;
1164
+ /** Colyseus's region code, e.g. "fra". */
1165
+ regionCode: string;
1166
+ /** City of the region. */
1167
+ city: string;
1168
+ /** ISO country code, e.g. "DE". */
1169
+ country: string;
1170
+ /** Same values as an instance's status. */
1171
+ status: string;
1172
+ /** "vertical" (one instance) or "horizontal" (several behind a load balancer). */
1173
+ scaleStrategy: string;
1174
+ /** Location address, or null until it has one. */
1175
+ endpoint: string | null;
1176
+ /** The location's plan. */
1177
+ plan: CloudPlanView;
1178
+ /** The location's instances. */
1179
+ instances: CloudInstanceView[];
1180
+ }
1181
+ /** The application this console watches. */
1182
+ export interface CloudApplicationView {
1183
+ /** Colyseus's application id. */
1184
+ id: number;
1185
+ /** The slug that addresses it in the API, e.g. "1234-my-game". */
1186
+ slug: string;
1187
+ /** Display name. */
1188
+ name: string;
1189
+ /** True while maintenance mode is on in Colyseus's dashboard. */
1190
+ maintenanceMode: boolean;
1191
+ /** Creation time (ISO). */
1192
+ createdAt: string;
1193
+ /** The application's locations. */
1194
+ locations: CloudLocationView[];
1195
+ }
1196
+ /** Load totals: players and rooms summed, CPU and memory of the busiest instance (Colyseus's rule). */
1197
+ export interface CloudLoadTotalsView {
1198
+ /** Connected players (CCU). */
1199
+ players: number;
1200
+ /** Open rooms. */
1201
+ rooms: number;
1202
+ /** CPU use, 0–100. */
1203
+ cpuPercent: number;
1204
+ /** Memory use of the plan's RAM, 0–100. */
1205
+ memoryPercent: number;
1206
+ }
1207
+ /** A server process on a Cloud instance. */
1208
+ export interface CloudProcessView {
1209
+ /** The process manager's process number. */
1210
+ id: number;
1211
+ /** online, launching, stopping, stopped, waiting restart or errored. */
1212
+ status: string;
1213
+ /** Start time (ISO), or null. */
1214
+ startedAt: string | null;
1215
+ /** The process manager's restart counter. */
1216
+ restarts: number;
1217
+ /** CPU use, 0–100. */
1218
+ cpuPercent: number;
1219
+ /** Resident memory in megabytes. */
1220
+ memoryMegabytes: number;
1221
+ /** Connected players. */
1222
+ players: number;
1223
+ /** Open rooms. */
1224
+ rooms: number;
1225
+ /** Node.js version, e.g. "24.1.0". */
1226
+ nodeVersion: string;
1227
+ }
1228
+ /** A Cloud instance's latest sample. */
1229
+ export interface CloudInstanceLoadView {
1230
+ /** Colyseus's instance id. */
1231
+ id: number;
1232
+ /** When it reported (ISO), or null. */
1233
+ sampledAt: string | null;
1234
+ /** True when the instance has not reported within Colyseus's window (its values are null). */
1235
+ isSilent: boolean;
1236
+ /** Connected players, or null when silent. */
1237
+ players: number | null;
1238
+ /** Open rooms, or null when silent. */
1239
+ rooms: number | null;
1240
+ /** CPU use 0–100, or null when silent. */
1241
+ cpuPercent: number | null;
1242
+ /** Memory use 0–100, or null when silent. */
1243
+ memoryPercent: number | null;
1244
+ /** The instance's processes (empty when silent). */
1245
+ processes: CloudProcessView[];
1246
+ }
1247
+ /** One location's current load. */
1248
+ export interface CloudLocationLoadView {
1249
+ /** Colyseus's location id. */
1250
+ id: number;
1251
+ /** Colyseus's region code. */
1252
+ regionCode: string;
1253
+ /** Null when every instance of the location is silent. */
1254
+ totals: CloudLoadTotalsView | null;
1255
+ /** The location's instances. */
1256
+ instances: CloudInstanceLoadView[];
1257
+ }
1258
+ /** The application's current load. */
1259
+ export interface CloudLoadView {
1260
+ /** Minutes after which a silent instance's values become null. */
1261
+ windowMinutes: number;
1262
+ /** Per location. */
1263
+ locations: CloudLocationLoadView[];
1264
+ /** Every location together (same rule), or null when all are silent. */
1265
+ totals: CloudLoadTotalsView | null;
1266
+ }
1267
+ /** One history point of a location. */
1268
+ export interface CloudHistoryPointView {
1269
+ /** Point time (ISO). */
1270
+ time: string;
1271
+ /** Players (CCU). */
1272
+ players: number;
1273
+ /** Rooms. */
1274
+ rooms: number;
1275
+ /** CPU use, 0–100. */
1276
+ cpuPercent: number;
1277
+ /** Memory use, 0–100. */
1278
+ memoryPercent: number;
1279
+ }
1280
+ /** One location's history. */
1281
+ export interface CloudLocationHistoryView {
1282
+ /** Colyseus's location id. */
1283
+ id: number;
1284
+ /** Colyseus's region code. */
1285
+ regionCode: string;
1286
+ /** Points, oldest first. */
1287
+ points: CloudHistoryPointView[];
1288
+ }
1289
+ /** The application's load history at one resolution. */
1290
+ export interface CloudHistoryView {
1291
+ /** "minute" (last 24 h) or "day" (last 30 days). */
1292
+ resolution: CloudHistoryResolution;
1293
+ /** Window start (ISO). */
1294
+ from: string;
1295
+ /** Window end (ISO, inclusive). */
1296
+ to: string;
1297
+ /** Per location. */
1298
+ locations: CloudLocationHistoryView[];
1299
+ }
1300
+ /** One day of a location's traffic. */
1301
+ export interface CloudEgressDayView {
1302
+ /** YYYY-MM-DD. */
1303
+ date: string;
1304
+ /** Bytes sent. */
1305
+ outgoingBytes: number;
1306
+ /** Bytes received. */
1307
+ incomingBytes: number;
1308
+ }
1309
+ /** One location's traffic. */
1310
+ export interface CloudLocationEgressView {
1311
+ /** Colyseus's location id. */
1312
+ id: number;
1313
+ /** Colyseus's region code. */
1314
+ regionCode: string;
1315
+ /** Bytes sent in the window. */
1316
+ outgoingBytes: number;
1317
+ /** Bytes received in the window. */
1318
+ incomingBytes: number;
1319
+ /** Per day. */
1320
+ days: CloudEgressDayView[];
1321
+ }
1322
+ /** The application's traffic over the last 30 days. */
1323
+ export interface CloudEgressView {
1324
+ /** YYYY-MM-DD. */
1325
+ from: string;
1326
+ /** YYYY-MM-DD. */
1327
+ to: string;
1328
+ /** When Colyseus last copied the figures (ISO), or null before the first copy. */
1329
+ collectedAt: string | null;
1330
+ /** Per location. */
1331
+ locations: CloudLocationEgressView[];
1332
+ }
1333
+ /** A deploy of the application. */
1334
+ export interface CloudDeployView {
1335
+ /** Colyseus's deploy id. */
1336
+ id: number;
1337
+ /** none, enqueued, deploying, deployed or failed. */
1338
+ status: string;
1339
+ /** Deployed branch. */
1340
+ branch: string;
1341
+ /** Short commit hash, or null until the code is fetched. */
1342
+ commit: string | null;
1343
+ /** Commit message, or null until the code is fetched. */
1344
+ message: string | null;
1345
+ /** When it was triggered (ISO). */
1346
+ startedAt: string;
1347
+ /** When it ended (ISO), or null while running. */
1348
+ finishedAt: string | null;
1349
+ }
1350
+ /** GET cloud/deploys/:deployId: a deploy with its build output (D10). */
1351
+ export interface CloudDeployDetailView extends CloudDeployView {
1352
+ /** Build and deploy output as plain text, or null once Colyseus no longer keeps it. */
1353
+ output: string | null;
1354
+ }
1355
+ /** The application's subscription. */
1356
+ export interface CloudSubscriptionView {
1357
+ /** active, past_due, unpaid, incomplete, incomplete_expired, trialing or canceled. */
1358
+ status: string;
1359
+ /** List price per month, in the account currency's units (not cents). */
1360
+ monthlyPrice: number;
1361
+ /** End of the current period (ISO). */
1362
+ currentPeriodEnd: string;
1363
+ /** True when the subscription ends at the period end. */
1364
+ cancelAtPeriodEnd: boolean;
1365
+ }
1366
+ /** The team owner's billing account (shared with any other team they own). */
1367
+ export interface CloudAccountView {
1368
+ /** Lower-case ISO currency code, e.g. "usd". */
1369
+ currency: string;
1370
+ /** Prepaid credit that pays future invoices. */
1371
+ creditBalance: number;
1372
+ /** Owed, added to the next invoice. */
1373
+ balanceDue: number;
1374
+ /** Credit from downgrades and cancellations. */
1375
+ unusedTimeCredit: number;
1376
+ }
1377
+ /** GET cloud/billing data. */
1378
+ export interface CloudBillingView {
1379
+ /** Null when the team owner has no billing account yet. */
1380
+ account: CloudAccountView | null;
1381
+ /** Null when the application has no subscription. */
1382
+ subscription: CloudSubscriptionView | null;
1383
+ /** When Colyseus read the billing figures (ISO). */
1384
+ fetchedAt: string;
1385
+ }
1386
+ /** GET cloud: everything the page shows except history, billing, deploy output and logs. */
1387
+ export interface ColyseusCloudView {
1388
+ /** Whether the page applies (D8). */
1389
+ feature: ColyseusCloudFeature;
1390
+ /** The team's application slugs when several exist and none is configured (D9); otherwise empty. */
1391
+ applicationChoices: string[];
1392
+ /** Why no application is shown (token refused, unknown slug, several or no applications), or null. */
1393
+ setupProblem: CloudProblemView | null;
1394
+ /** The application and its locations. */
1395
+ overview: CloudPart<CloudApplicationView>;
1396
+ /** Current load. */
1397
+ load: CloudPart<CloudLoadView>;
1398
+ /** Recent deploys, newest first. */
1399
+ deploys: CloudPart<CloudDeployView[]>;
1400
+ /** Traffic of the last 30 days. */
1401
+ egress: CloudPart<CloudEgressView>;
1402
+ }
1403
+ /** GET cloud/instances/:instanceId/logs answer (D5, D10). */
1404
+ export interface CloudLogsView {
1405
+ /** Colyseus's instance id. */
1406
+ instanceId: number;
1407
+ /** The stream read. */
1408
+ stream: CloudLogStream;
1409
+ /** The number of lines asked for. */
1410
+ lines: CloudLogLines;
1411
+ /** The newest log lines, colour codes stripped by Colyseus. */
1412
+ text: string;
1413
+ /** When they were read (ISO). */
1414
+ fetchedAt: string;
1415
+ /** True when this answer is another request's from the last minute (the limit allowed no new one). */
1416
+ isShared: boolean;
1417
+ /** When the next log request is allowed (ISO). */
1418
+ nextAllowedAt: string;
1419
+ }
1420
+ /** Which scores rank first: "lowerIsBetter" for times, "higherIsBetter" for points and counters. */
1421
+ export type LeaderboardSortOrder = "higherIsBetter" | "lowerIsBetter";
1422
+ /** How a score is shown: a plain integer, milliseconds shown as a time, or points. Scores are integers (D12). */
1423
+ export type LeaderboardScoreFormat = "integer" | "timeMilliseconds" | "points";
1424
+ /** What a new score does to a player's entry: keep the best, keep the latest, or add to a running total (D14). */
1425
+ export type LeaderboardKeepPolicy = "best" | "latest" | "sum";
1426
+ /** How far a submission can be trusted (D9): signed by the game client, confirmed by session presence, or sent by a server API key. */
1427
+ export type LeaderboardTrustLevel = "client" | "session" | "server";
1428
+ /** Whether game clients can read and submit to a board. */
1429
+ export type LeaderboardVisibility = "public" | "hidden";
1430
+ /** When a board's season resets by itself (UTC, D17); "manual" resets only from the console, "never" not at all. */
1431
+ export type LeaderboardResetSchedule = "never" | "manual" | "daily" | "weekly" | "monthly";
1432
+ /** Why a request or one score was refused. */
1433
+ export type LeaderboardRefusalReason = "invalidRequest" | "authRequired" | "authRefused" | "banned" | "invalidPlayer" | "rateLimited" | "tooManyScores" | "unknownBoard" | "variantNotAllowed" | "scoreNotInteger" | "scoreOutOfRange" | "trustLevelNotAccepted" | "implausibleDuration" | "metadataTooLarge" | "nameInvalid" | "nameBlocked" | "nameManaged" | "signInRequired";
1434
+ /** What a write did to the player's stored entry (D14). */
1435
+ export type LeaderboardWriteOutcome = "created" | "improved" | "replaced" | "added" | "kept";
1436
+ /** A JSON value allowed in entry metadata (display-only details next to a score). */
1437
+ export type LeaderboardMetadataValue = string | number | boolean | null | LeaderboardMetadataValue[] | {
1438
+ [key: string]: LeaderboardMetadataValue;
1439
+ };
1440
+ /** Free-form, size-capped details stored with an entry; never ranked or queried. */
1441
+ export type LeaderboardMetadata = {
1442
+ [key: string]: LeaderboardMetadataValue;
1443
+ };
1444
+ /** One way a board's rankings are split (a "map", a "difficulty"), with the values a submission may use (D16). */
1445
+ export interface LeaderboardVariantDimension {
1446
+ /** Key in a submission's variant object. */
1447
+ name: string;
1448
+ /** Label shown in the console and in games. */
1449
+ label: string;
1450
+ /** Allowed values, in display order. */
1451
+ values: string[];
1452
+ }
1453
+ /** Everything an admin defines about a board. */
1454
+ export interface LeaderboardBoardDefinition {
1455
+ /** Stable id, `/^[a-z0-9][a-z0-9-]{0,63}$/`. */
1456
+ boardId: string;
1457
+ /** Name shown to players and admins (1–80 characters). */
1458
+ displayName: string;
1459
+ /** What the board ranks (0–500 characters). */
1460
+ description: string;
1461
+ sortOrder: LeaderboardSortOrder;
1462
+ scoreFormat: LeaderboardScoreFormat;
1463
+ keepPolicy: LeaderboardKeepPolicy;
1464
+ /** Smallest score one submission may carry, or null for no limit. */
1465
+ minimumScore: number | null;
1466
+ /** Largest score one submission may carry, or null for no limit. */
1467
+ maximumScore: number | null;
1468
+ /** Trust levels the board accepts (at least one). */
1469
+ acceptedTrustLevels: LeaderboardTrustLevel[];
1470
+ visibility: LeaderboardVisibility;
1471
+ resetSchedule: LeaderboardResetSchedule;
1472
+ /** Ranking splits; empty for a single ranking. */
1473
+ dimensions: LeaderboardVariantDimension[];
1474
+ }
1475
+ /** One season of a board. */
1476
+ export interface LeaderboardSeasonView {
1477
+ /** 1, 2, 3 … */
1478
+ seasonId: number;
1479
+ /** ISO start. */
1480
+ startedAt: string;
1481
+ /** ISO end, or null for the current season. */
1482
+ endedAt: string | null;
1483
+ isCurrent: boolean;
1484
+ }
1485
+ /** A board as game clients see it. */
1486
+ export interface LeaderboardPublicBoardView {
1487
+ boardId: string;
1488
+ displayName: string;
1489
+ description: string;
1490
+ sortOrder: LeaderboardSortOrder;
1491
+ scoreFormat: LeaderboardScoreFormat;
1492
+ keepPolicy: LeaderboardKeepPolicy;
1493
+ dimensions: LeaderboardVariantDimension[];
1494
+ currentSeasonId: number;
1495
+ currentSeasonStartedAt: string;
1496
+ /** ISO time of the next scheduled reset, or null. */
1497
+ nextResetAt: string | null;
1498
+ }
1499
+ /** One ranked entry. */
1500
+ export interface LeaderboardEntryView {
1501
+ /** 1-based rank in its ranking. */
1502
+ rank: number;
1503
+ playerId: string;
1504
+ /** The name the player had when the entry was written (console renames update it). */
1505
+ displayName: string;
1506
+ /** The player's avatar claim (a Discord avatar hash for user:discord: players), filled on public reads; absent or null otherwise. */
1507
+ avatar?: string | null;
1508
+ score: number;
1509
+ metadata: LeaderboardMetadata | null;
1510
+ trustLevel: LeaderboardTrustLevel;
1511
+ /** ISO time of the last accepted submission. */
1512
+ submittedAt: string;
1513
+ /** ISO time the stored score was reached (tie-break, D13). */
1514
+ achievedAt: string;
1515
+ }
1516
+ /** A page of one ranking. */
1517
+ export interface LeaderboardEntriesPage {
1518
+ boardId: string;
1519
+ seasonId: number;
1520
+ variantKey: string;
1521
+ /** Entries in the ranking. */
1522
+ total: number;
1523
+ /** Zero-based index of the first entry. */
1524
+ offset: number;
1525
+ entries: LeaderboardEntryView[];
1526
+ }
1527
+ /** A window around one player; `playerRank` is null when the player has no entry. */
1528
+ export interface LeaderboardAroundPage extends LeaderboardEntriesPage {
1529
+ playerRank: number | null;
1530
+ }
1531
+ /** A player as games see them. */
1532
+ export interface LeaderboardPlayerView {
1533
+ playerId: string;
1534
+ displayName: string;
1535
+ kind: "anonymous" | "user" | "manual";
1536
+ createdAt: string;
1537
+ }
1538
+ /** The answer to POST players: the player and, only when it was just created anonymously, its one-time key. */
1539
+ export interface LeaderboardPlayerSession {
1540
+ player: LeaderboardPlayerView;
1541
+ playerKey: string | null;
1542
+ }
1543
+ /** One score in a submission. */
1544
+ export interface LeaderboardScoreSubmission {
1545
+ boardId: string;
1546
+ /** Dimension values; null or {} for a board without dimensions. */
1547
+ variant: Record<string, string> | null;
1548
+ score: number;
1549
+ metadata: LeaderboardMetadata | null;
1550
+ }
1551
+ /** POST submissions: the envelope every game sends at a key stage (spec D13). */
1552
+ export interface LeaderboardSubmissionRequest {
1553
+ /** The anonymous player's key, or omitted for an auth user. */
1554
+ playerKey?: string;
1555
+ /** Client-made unique id, 8–64 of `[A-Za-z0-9-]` (exactly-once, D15). */
1556
+ submissionId: string;
1557
+ /** The game's mode name, at most 64 characters, or null. */
1558
+ gameMode: string | null;
1559
+ /** The game's build version, at most 64 characters, or null. */
1560
+ buildVersion: string | null;
1561
+ /** The network session name when the scores come from a network game, or null. */
1562
+ sessionName: string | null;
1563
+ /** How long the run lasted, in milliseconds, or null. */
1564
+ durationMs: number | null;
1565
+ /** The client's ISO clock (informational only; the server stamps its own time). */
1566
+ clientTime: string | null;
1567
+ /** 1–maximumScoresPerSubmission scores. */
1568
+ scores: LeaderboardScoreSubmission[];
1569
+ }
1570
+ /** What happened to one score. */
1571
+ export interface LeaderboardScoreResult {
1572
+ boardId: string;
1573
+ variantKey: string | null;
1574
+ status: "accepted" | "duplicate" | "refused";
1575
+ outcome: LeaderboardWriteOutcome | null;
1576
+ /** The stored score after the keep policy, or null when refused. */
1577
+ score: number | null;
1578
+ previousScore: number | null;
1579
+ /** True when this submission created or improved the player's entry (or changed a latest/sum entry). */
1580
+ isPersonalBest: boolean;
1581
+ rank: number | null;
1582
+ total: number | null;
1583
+ seasonId: number | null;
1584
+ trustLevel: LeaderboardTrustLevel | null;
1585
+ refusal: LeaderboardRefusalReason | null;
1586
+ }
1587
+ /** The answer to POST submissions. */
1588
+ export interface LeaderboardSubmissionResponse {
1589
+ submissionId: string;
1590
+ playerId: string;
1591
+ results: LeaderboardScoreResult[];
1592
+ }
1593
+ /** One ranking a player asks about. */
1594
+ export interface LeaderboardTarget {
1595
+ boardId: string;
1596
+ variant: Record<string, string> | null;
1597
+ /** A season, or omitted for the current one. */
1598
+ seasonId?: number;
1599
+ }
1600
+ /** A player's entry in one ranking (null when they have none). */
1601
+ export interface LeaderboardTargetEntry {
1602
+ boardId: string;
1603
+ variantKey: string;
1604
+ seasonId: number;
1605
+ total: number;
1606
+ entry: LeaderboardEntryView | null;
1607
+ }
1608
+ /** The error body of a refused public request. */
1609
+ export interface LeaderboardErrorBody {
1610
+ error: string;
1611
+ reason: LeaderboardRefusalReason;
1612
+ }
1613
+ /** Console-editable abuse limits and name rules (D19). */
1614
+ export interface LeaderboardRules {
1615
+ submissionsPerMinutePerPlayer: number;
1616
+ submissionsPerMinutePerAddress: number;
1617
+ readsPerMinutePerAddress: number;
1618
+ identitiesPerHourPerAddress: number;
1619
+ maximumScoresPerSubmission: number;
1620
+ metadataMaximumBytes: number;
1621
+ /** Lower-case words a display name may not contain. */
1622
+ blockedWords: string[];
1623
+ }
1624
+ /** GET leaderboards/rules. */
1625
+ export interface LeaderboardRulesView {
1626
+ rules: LeaderboardRules;
1627
+ defaults: LeaderboardRules;
1628
+ revision: number;
1629
+ }
1630
+ /** A board in the console's list. */
1631
+ export interface LeaderboardBoardSummaryView {
1632
+ definition: LeaderboardBoardDefinition;
1633
+ revision: number;
1634
+ currentSeasonId: number;
1635
+ seasons: LeaderboardSeasonView[];
1636
+ nextResetAt: string | null;
1637
+ /** Live entries of the current season, all variants. */
1638
+ entryCount: number;
1639
+ /** ISO time of the last accepted score, or null. */
1640
+ lastSubmissionAt: string | null;
1641
+ }
1642
+ /** One variant of a board in its detail view. */
1643
+ export interface LeaderboardVariantSummaryView {
1644
+ variantKey: string;
1645
+ values: Record<string, string>;
1646
+ entryCount: number;
1647
+ topEntry: LeaderboardEntryView | null;
1648
+ }
1649
+ /** GET leaderboards/boards/:boardId. */
1650
+ export interface LeaderboardBoardDetailView {
1651
+ summary: LeaderboardBoardSummaryView;
1652
+ seasonId: number;
1653
+ variants: LeaderboardVariantSummaryView[];
1654
+ }
1655
+ /** An entry a moderator removed or a hidden player's entry. */
1656
+ export interface LeaderboardRemovedEntryView {
1657
+ entry: LeaderboardEntryView;
1658
+ reason: string;
1659
+ removedBy: string;
1660
+ removedAt: string;
1661
+ }
1662
+ /** A player in the console. */
1663
+ export interface LeaderboardPlayerAdminView {
1664
+ playerId: string;
1665
+ displayName: string;
1666
+ kind: "anonymous" | "user" | "manual";
1667
+ hidden: boolean;
1668
+ createdAt: string;
1669
+ lastSeenAt: string;
1670
+ }
1671
+ /** One of a player's entries across boards. */
1672
+ export interface LeaderboardPlayerEntryView {
1673
+ boardId: string;
1674
+ boardName: string;
1675
+ scoreFormat: LeaderboardScoreFormat;
1676
+ seasonId: number;
1677
+ isCurrentSeason: boolean;
1678
+ variantKey: string;
1679
+ rank: number | null;
1680
+ total: number;
1681
+ score: number;
1682
+ removedReason: string | null;
1683
+ }
1684
+ /** GET leaderboards/players/:playerId. */
1685
+ export interface LeaderboardPlayerDetailView {
1686
+ player: LeaderboardPlayerAdminView;
1687
+ entries: LeaderboardPlayerEntryView[];
1688
+ }
1689
+ /** One activity record (D21). */
1690
+ export interface LeaderboardActivityView {
1691
+ sequence: number;
1692
+ at: string;
1693
+ kind: "accepted" | "duplicate" | "refused";
1694
+ boardId: string | null;
1695
+ variantKey: string | null;
1696
+ playerId: string | null;
1697
+ displayName: string | null;
1698
+ score: number | null;
1699
+ outcome: LeaderboardWriteOutcome | null;
1700
+ reason: LeaderboardRefusalReason | null;
1701
+ trustLevel: LeaderboardTrustLevel | null;
1702
+ gameMode: string | null;
1703
+ /** Empty unless the caller holds players.viewAddresses. */
1704
+ clientAddress: string;
1705
+ }
1706
+ /** GET leaderboards/status. */
1707
+ export interface LeaderboardStatusView {
1708
+ storage: "redis" | "files";
1709
+ durability: "durable" | "notDurable" | "unknown";
1710
+ /** What to configure when not durable or unknown, else null. */
1711
+ durabilityAdvice: string | null;
1712
+ /** The definitions-file problem found at start, or null. */
1713
+ definitionsProblem: string | null;
1714
+ boardCount: number;
1715
+ acceptedPerMinute: number;
1716
+ refusedPerMinute: number;
1717
+ }
1718
+ /** The startup definitions file (D11) and a console definitions import. */
1719
+ export interface LeaderboardDefinitionsFile {
1720
+ format: "babylon-game-server-leaderboard-definitions";
1721
+ version: 1;
1722
+ boards: LeaderboardBoardDefinition[];
1723
+ }
1724
+ /** One exported entry. */
1725
+ export interface LeaderboardExportEntry {
1726
+ seasonId: number;
1727
+ variantKey: string;
1728
+ playerId: string;
1729
+ displayName: string;
1730
+ score: number;
1731
+ metadata: LeaderboardMetadata | null;
1732
+ trustLevel: LeaderboardTrustLevel;
1733
+ sessionName: string | null;
1734
+ submittedAt: string;
1735
+ achievedAt: string;
1736
+ submissionCount: number;
1737
+ /** The removal reason, or null for a live entry. */
1738
+ removedReason: string | null;
1739
+ /** Who removed it, or null for a live entry. */
1740
+ removedBy: string | null;
1741
+ /** ISO time it was removed, or null for a live entry. */
1742
+ removedAt: string | null;
1743
+ }
1744
+ /** One exported player (keyHash keeps anonymous players' keys working after a restore). */
1745
+ export interface LeaderboardExportPlayer {
1746
+ playerId: string;
1747
+ displayName: string;
1748
+ kind: "anonymous" | "user" | "manual";
1749
+ keyHash: string | null;
1750
+ hidden: boolean;
1751
+ createdAt: string;
1752
+ }
1753
+ /** One exported board. */
1754
+ export interface LeaderboardExportBoard {
1755
+ definition: LeaderboardBoardDefinition;
1756
+ currentSeasonId: number;
1757
+ seasons: LeaderboardSeasonView[];
1758
+ entries: LeaderboardExportEntry[];
1759
+ }
1760
+ /** GET leaderboards/export?format=json: a full or partial backup. */
1761
+ export interface LeaderboardExportFile {
1762
+ format: "babylon-game-server-leaderboards";
1763
+ version: 1;
1764
+ exportedAt: string;
1765
+ boards: LeaderboardExportBoard[];
1766
+ players: LeaderboardExportPlayer[];
1767
+ }
1768
+ /** POST leaderboards/import body. */
1769
+ export interface LeaderboardImportRequest {
1770
+ file: LeaderboardExportFile | LeaderboardDefinitionsFile;
1771
+ conflictPolicy: "skip" | "replace";
1772
+ dryRun: boolean;
1773
+ }
1774
+ /** POST leaderboards/import answer (the preview when dryRun). */
1775
+ export interface LeaderboardImportResult {
1776
+ dryRun: boolean;
1777
+ boardsCreated: string[];
1778
+ boardsReplaced: string[];
1779
+ boardsSkipped: string[];
1780
+ entriesWritten: number;
1781
+ playersWritten: number;
1782
+ }