@playcademy/sandbox 0.3.8 → 0.3.9

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 (3) hide show
  1. package/dist/cli.js +483 -344
  2. package/dist/server.js +483 -344
  3. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -1223,7 +1223,7 @@ var package_default;
1223
1223
  var init_package = __esm(() => {
1224
1224
  package_default = {
1225
1225
  name: "@playcademy/sandbox",
1226
- version: "0.3.8",
1226
+ version: "0.3.9",
1227
1227
  description: "Local development server for Playcademy game development",
1228
1228
  type: "module",
1229
1229
  exports: {
@@ -14979,6 +14979,62 @@ var init_level_service = __esm(() => {
14979
14979
  logger15 = log.scope("LevelService");
14980
14980
  });
14981
14981
 
14982
+ // ../api-core/src/services/logs.service.ts
14983
+ class LogsService {
14984
+ ctx;
14985
+ constructor(ctx) {
14986
+ this.ctx = ctx;
14987
+ }
14988
+ async generateToken(user, slug2, environment) {
14989
+ const db2 = this.ctx.db;
14990
+ if (user.role === "admin") {
14991
+ const game = await db2.query.games.findFirst({
14992
+ where: eq(games.slug, slug2),
14993
+ columns: { id: true }
14994
+ });
14995
+ if (!game) {
14996
+ throw new NotFoundError("Game", slug2);
14997
+ }
14998
+ logger16.info("Admin accessing game logs", { adminId: user.id, slug: slug2, environment });
14999
+ } else {
15000
+ const isApprovedDev = user.developerStatus === "approved";
15001
+ if (!isApprovedDev) {
15002
+ logger16.warn("Unapproved developer attempted log access", { userId: user.id, slug: slug2 });
15003
+ throw new AccessDeniedError("Must be an approved developer");
15004
+ }
15005
+ const game = await db2.query.games.findFirst({
15006
+ where: and(eq(games.slug, slug2), eq(games.developerId, user.id)),
15007
+ columns: { id: true }
15008
+ });
15009
+ if (!game) {
15010
+ logger16.warn("Developer attempted access to unowned game logs", {
15011
+ userId: user.id,
15012
+ slug: slug2
15013
+ });
15014
+ throw new NotFoundError("Game", slug2);
15015
+ }
15016
+ }
15017
+ const isProduction3 = environment === "production";
15018
+ const workerId = getDeploymentId(slug2, isProduction3);
15019
+ const token = await this.ctx.providers.auth.mintLogStreamToken(user.id, workerId);
15020
+ logger16.debug("Generated log stream token", {
15021
+ userId: user.id,
15022
+ slug: slug2,
15023
+ workerId
15024
+ });
15025
+ return { token, workerId };
15026
+ }
15027
+ }
15028
+ var logger16;
15029
+ var init_logs_service = __esm(() => {
15030
+ init_drizzle_orm();
15031
+ init_tables_index();
15032
+ init_src2();
15033
+ init_errors();
15034
+ init_deployment_util();
15035
+ logger16 = log.scope("LogsService");
15036
+ });
15037
+
14982
15038
  // ../../node_modules/aws-jwt-verify/dist/esm/error.js
14983
15039
  var JwtBaseError, FailedAssertionError, JwtParseError, ParameterValidationError, JwtInvalidSignatureError, JwtInvalidSignatureAlgorithmError, JwtInvalidClaimError, JwtInvalidIssuerError, JwtInvalidAudienceError, JwtInvalidScopeError, JwtExpiredError, JwtNotBeforeError, CognitoJwtInvalidGroupError, CognitoJwtInvalidTokenUseError, CognitoJwtInvalidClientIdError, JwksValidationError, JwkValidationError, JwtWithoutValidKidError, KidNotFoundInJwksError, WaitPeriodNotYetEndedJwkError, JwksNotAvailableInCacheError, JwkInvalidUseError, JwkInvalidKtyError, FetchError, NonRetryableFetchError;
14984
15040
  var init_error = __esm(() => {
@@ -15988,7 +16044,7 @@ class LtiService {
15988
16044
  }
15989
16045
  getConfig() {
15990
16046
  if (!this.ctx.config.lti) {
15991
- logger16.error("LTI configuration not available");
16047
+ logger17.error("LTI configuration not available");
15992
16048
  throw new ValidationError("LTI is not configured");
15993
16049
  }
15994
16050
  return this.ctx.config.lti;
@@ -16019,14 +16075,14 @@ class LtiService {
16019
16075
  try {
16020
16076
  const verifier = this.getVerifier();
16021
16077
  const claims = await verifier.verify(idToken);
16022
- logger16.info("Verified token", {
16078
+ logger17.info("Verified token", {
16023
16079
  sub: claims.sub,
16024
16080
  email: claims.email,
16025
16081
  roles: claims["https://purl.imsglobal.org/spec/lti/claim/roles"]
16026
16082
  });
16027
16083
  return claims;
16028
16084
  } catch (error) {
16029
- logger16.error("Token verification failed", {
16085
+ logger17.error("Token verification failed", {
16030
16086
  error: error instanceof Error ? error.message : String(error)
16031
16087
  });
16032
16088
  throw new ValidationError("Invalid LTI token");
@@ -16036,14 +16092,14 @@ class LtiService {
16036
16092
  const claims = await this.verifyToken(idToken);
16037
16093
  const validationError = validateLtiClaims(claims);
16038
16094
  if (validationError) {
16039
- logger16.warn("LTI claims validation failed", {
16095
+ logger17.warn("LTI claims validation failed", {
16040
16096
  error: validationError,
16041
16097
  sub: claims.sub
16042
16098
  });
16043
16099
  throw new ValidationError(validationError);
16044
16100
  }
16045
16101
  const user = await this.provisionUser(claims);
16046
- logger16.info("Processed launch roles", {
16102
+ logger17.info("Processed launch roles", {
16047
16103
  userId: user.id,
16048
16104
  isLearner: LtiRoleChecks.isLearner(claims),
16049
16105
  isInstructor: LtiRoleChecks.isInstructor(claims),
@@ -16053,7 +16109,7 @@ class LtiService {
16053
16109
  const sessionToken = await this.createSession(user.id);
16054
16110
  const targetUri = claims["https://purl.imsglobal.org/spec/lti/claim/target_link_uri"];
16055
16111
  const redirectPath = extractRedirectPath(targetUri, currentHost);
16056
- logger16.info("Launch processed", { userId: user.id, redirectPath });
16112
+ logger17.info("Launch processed", { userId: user.id, redirectPath });
16057
16113
  const userInfo = {
16058
16114
  sub: user.id,
16059
16115
  email: user.email,
@@ -16099,10 +16155,10 @@ class LtiService {
16099
16155
  updatedAt: new Date
16100
16156
  }).returning({ id: sessions.id });
16101
16157
  if (!session2) {
16102
- logger16.error("Session insert returned no rows", { userId });
16158
+ logger17.error("Session insert returned no rows", { userId });
16103
16159
  throw new InternalError("Failed to create session");
16104
16160
  }
16105
- logger16.info("Created session", {
16161
+ logger17.info("Created session", {
16106
16162
  userId,
16107
16163
  providerId: AUTH_PROVIDER_IDS.TIMEBACK_LTI
16108
16164
  });
@@ -16124,7 +16180,7 @@ class LtiService {
16124
16180
  where: eq(users.id, existingAccount.userId)
16125
16181
  });
16126
16182
  if (user) {
16127
- logger16.info("Found user by account", {
16183
+ logger17.info("Found user by account", {
16128
16184
  userId: user.id,
16129
16185
  ltiTimebackId
16130
16186
  });
@@ -16153,13 +16209,13 @@ class LtiService {
16153
16209
  updatedAt: new Date
16154
16210
  }).returning({ id: accounts.id });
16155
16211
  if (!account) {
16156
- logger16.error("LTI account link insert returned no rows", {
16212
+ logger17.error("LTI account link insert returned no rows", {
16157
16213
  userId: existingUser.id,
16158
16214
  ltiTimebackId
16159
16215
  });
16160
16216
  throw new InternalError("Failed to link LTI account");
16161
16217
  }
16162
- logger16.info("Linked existing user", {
16218
+ logger17.info("Linked existing user", {
16163
16219
  userId: existingUser.id,
16164
16220
  ltiTimebackId
16165
16221
  });
@@ -16180,7 +16236,7 @@ class LtiService {
16180
16236
  updatedAt: new Date
16181
16237
  }).returning();
16182
16238
  if (!insertedUser) {
16183
- logger16.error("LTI user insert returned no rows", { email, ltiTimebackId });
16239
+ logger17.error("LTI user insert returned no rows", { email, ltiTimebackId });
16184
16240
  throw new InternalError("Failed to create user");
16185
16241
  }
16186
16242
  await tx.insert(accounts).values({
@@ -16195,7 +16251,7 @@ class LtiService {
16195
16251
  createdAt: new Date,
16196
16252
  updatedAt: new Date
16197
16253
  });
16198
- logger16.info("Provisioned user", {
16254
+ logger17.info("Provisioned user", {
16199
16255
  userId: insertedUser.id,
16200
16256
  ltiTimebackId
16201
16257
  });
@@ -16204,7 +16260,7 @@ class LtiService {
16204
16260
  return createdUser;
16205
16261
  }
16206
16262
  }
16207
- var logger16;
16263
+ var logger17;
16208
16264
  var init_lti_service = __esm(() => {
16209
16265
  init_esm2();
16210
16266
  init_drizzle_orm();
@@ -16213,7 +16269,7 @@ var init_lti_service = __esm(() => {
16213
16269
  init_src2();
16214
16270
  init_errors();
16215
16271
  init_lti_util();
16216
- logger16 = log.scope("LtiService");
16272
+ logger17 = log.scope("LtiService");
16217
16273
  });
16218
16274
 
16219
16275
  // ../api-core/src/services/map.service.ts
@@ -16230,7 +16286,7 @@ class MapService {
16230
16286
  if (!mapDetails) {
16231
16287
  throw new NotFoundError("Map", identifier);
16232
16288
  }
16233
- logger17.debug("Retrieved map", { identifier });
16289
+ logger18.debug("Retrieved map", { identifier });
16234
16290
  return mapDetails;
16235
16291
  }
16236
16292
  async getElements(mapId) {
@@ -16246,7 +16302,7 @@ class MapService {
16246
16302
  }
16247
16303
  }
16248
16304
  });
16249
- logger17.debug("Retrieved elements", { mapId, count: elements.length });
16305
+ logger18.debug("Retrieved elements", { mapId, count: elements.length });
16250
16306
  return elements;
16251
16307
  }
16252
16308
  async getObjects(mapId, userId) {
@@ -16267,7 +16323,7 @@ class MapService {
16267
16323
  }
16268
16324
  }
16269
16325
  });
16270
- logger17.debug("Retrieved objects", { mapId, userId, count: objects.length });
16326
+ logger18.debug("Retrieved objects", { mapId, userId, count: objects.length });
16271
16327
  return objects.map((object) => this.formatMapObjectWithItem(object));
16272
16328
  }
16273
16329
  async createObject(mapId, data, user) {
@@ -16294,7 +16350,7 @@ class MapService {
16294
16350
  throw new NotFoundError("Item", data.itemId);
16295
16351
  }
16296
16352
  if (!item.isPlaceable) {
16297
- logger17.warn("Attempted to place non-placeable item", {
16353
+ logger18.warn("Attempted to place non-placeable item", {
16298
16354
  userId: user.id,
16299
16355
  itemId: data.itemId,
16300
16356
  mapId
@@ -16308,7 +16364,7 @@ class MapService {
16308
16364
  };
16309
16365
  const [createdObject] = await db2.insert(mapObjects).values(objectData).returning();
16310
16366
  if (!createdObject) {
16311
- logger17.error("Map object insert returned no rows", {
16367
+ logger18.error("Map object insert returned no rows", {
16312
16368
  userId: user.id,
16313
16369
  mapId,
16314
16370
  itemId: data.itemId
@@ -16332,12 +16388,12 @@ class MapService {
16332
16388
  }
16333
16389
  });
16334
16390
  if (!objectWithItem) {
16335
- logger17.error("Map object query after insert returned no rows", {
16391
+ logger18.error("Map object query after insert returned no rows", {
16336
16392
  objectId: createdObject.id
16337
16393
  });
16338
16394
  throw new InternalError("Failed to retrieve created object");
16339
16395
  }
16340
- logger17.info("Created object", {
16396
+ logger18.info("Created object", {
16341
16397
  userId: user.id,
16342
16398
  mapId,
16343
16399
  objectId: createdObject.id,
@@ -16361,7 +16417,7 @@ class MapService {
16361
16417
  if (result.length === 0) {
16362
16418
  throw new NotFoundError("MapObject", objectId);
16363
16419
  }
16364
- logger17.info("Deleted object", {
16420
+ logger18.info("Deleted object", {
16365
16421
  userId: user.id,
16366
16422
  mapId,
16367
16423
  objectId
@@ -16390,13 +16446,13 @@ class MapService {
16390
16446
  };
16391
16447
  }
16392
16448
  }
16393
- var logger17;
16449
+ var logger18;
16394
16450
  var init_map_service = __esm(() => {
16395
16451
  init_drizzle_orm();
16396
16452
  init_tables_index();
16397
16453
  init_src2();
16398
16454
  init_errors();
16399
- logger17 = log.scope("MapService");
16455
+ logger18 = log.scope("MapService");
16400
16456
  });
16401
16457
 
16402
16458
  // ../realtime/src/server/domain/events.ts
@@ -16417,13 +16473,13 @@ async function publishToUser(baseUrl, secret, userId, type, payload) {
16417
16473
  });
16418
16474
  if (!res.ok) {
16419
16475
  const text3 = await res.text().catch(() => "");
16420
- logger18.warn("Failed to publish to user", {
16476
+ logger19.warn("Failed to publish to user", {
16421
16477
  status: res.status,
16422
16478
  body: text3
16423
16479
  });
16424
16480
  }
16425
16481
  } catch (error) {
16426
- logger18.error("Publish to user error", { error });
16482
+ logger19.error("Publish to user error", { error });
16427
16483
  }
16428
16484
  }
16429
16485
 
@@ -16443,7 +16499,7 @@ class NotificationService {
16443
16499
  if (type)
16444
16500
  conditions2.push(eq(notifications.type, type));
16445
16501
  const results = await this.ctx.db.select().from(notifications).where(and(...conditions2)).orderBy(desc(notifications.createdAt)).limit(limit).offset(offset);
16446
- logger18.debug("Listed notifications", { userId: user.id, count: results.length });
16502
+ logger19.debug("Listed notifications", { userId: user.id, count: results.length });
16447
16503
  return results;
16448
16504
  }
16449
16505
  async updateStatus(notificationId, status, method) {
@@ -16461,7 +16517,7 @@ class NotificationService {
16461
16517
  if (!updated) {
16462
16518
  throw new NotFoundError("Notification", notificationId);
16463
16519
  }
16464
- logger18.debug("Updated status", { notificationId, status });
16520
+ logger19.debug("Updated status", { notificationId, status });
16465
16521
  return updated;
16466
16522
  }
16467
16523
  async getStats(user, options) {
@@ -16485,7 +16541,7 @@ class NotificationService {
16485
16541
  const clicked = statsMap.clicked || 0;
16486
16542
  const dismissed = statsMap.dismissed || 0;
16487
16543
  const expired = statsMap.expired || 0;
16488
- logger18.debug("Retrieved stats", { userId: user.id, total });
16544
+ logger19.debug("Retrieved stats", { userId: user.id, total });
16489
16545
  return {
16490
16546
  total,
16491
16547
  delivered,
@@ -16531,7 +16587,7 @@ class NotificationService {
16531
16587
  metadata: metadata2
16532
16588
  });
16533
16589
  }
16534
- logger18.debug("Created notification", {
16590
+ logger19.debug("Created notification", {
16535
16591
  userId,
16536
16592
  type,
16537
16593
  id: notificationId,
@@ -16539,14 +16595,14 @@ class NotificationService {
16539
16595
  });
16540
16596
  return notificationId;
16541
16597
  } catch (error) {
16542
- logger18.error("Failed to create notification", { userId, type, error });
16598
+ logger19.error("Failed to create notification", { userId, type, error });
16543
16599
  return null;
16544
16600
  }
16545
16601
  }
16546
16602
  async publish(userId, notificationId, type, title, message, options) {
16547
16603
  const realtimeConfig = this.ctx.config.realtime;
16548
16604
  if (!realtimeConfig) {
16549
- logger18.warn("No realtime config for publish");
16605
+ logger19.warn("No realtime config for publish");
16550
16606
  return;
16551
16607
  }
16552
16608
  const { relayUrl, publishSecret } = realtimeConfig;
@@ -16588,13 +16644,13 @@ class NotificationService {
16588
16644
  metadata: data.metadata || {}
16589
16645
  }).returning();
16590
16646
  if (!notification) {
16591
- logger18.error("Notification insert returned no rows", {
16647
+ logger19.error("Notification insert returned no rows", {
16592
16648
  userId: data.userId,
16593
16649
  type: data.type
16594
16650
  });
16595
16651
  throw new InternalError("Failed to create notification");
16596
16652
  }
16597
- logger18.info("Inserted notification", {
16653
+ logger19.info("Inserted notification", {
16598
16654
  notificationId: notification.id,
16599
16655
  userId: notification.userId,
16600
16656
  type: notification.type
@@ -16604,7 +16660,7 @@ class NotificationService {
16604
16660
  async deliverPending(userId) {
16605
16661
  const realtimeConfig = this.ctx.config.realtime;
16606
16662
  if (!realtimeConfig) {
16607
- logger18.warn("No realtime config for delivery");
16663
+ logger19.warn("No realtime config for delivery");
16608
16664
  return;
16609
16665
  }
16610
16666
  const { relayUrl, publishSecret } = realtimeConfig;
@@ -16631,13 +16687,13 @@ class NotificationService {
16631
16687
  metadata: notification.metadata,
16632
16688
  clickUrl: notification.clickUrl
16633
16689
  });
16634
- logger18.info("Delivered notification", {
16690
+ logger19.info("Delivered notification", {
16635
16691
  notificationId: notification.id,
16636
16692
  userId,
16637
16693
  type: notification.type
16638
16694
  });
16639
16695
  } catch (error) {
16640
- logger18.warn("Failed to deliver", {
16696
+ logger19.warn("Failed to deliver", {
16641
16697
  notificationId: notification.id,
16642
16698
  error
16643
16699
  });
@@ -16645,7 +16701,7 @@ class NotificationService {
16645
16701
  }
16646
16702
  }
16647
16703
  }
16648
- var logger18;
16704
+ var logger19;
16649
16705
  var init_notification_service = __esm(() => {
16650
16706
  init_drizzle_orm();
16651
16707
  init_src();
@@ -16654,7 +16710,7 @@ var init_notification_service = __esm(() => {
16654
16710
  init_events();
16655
16711
  init_notification();
16656
16712
  init_errors();
16657
- logger18 = log.scope("NotificationService");
16713
+ logger19 = log.scope("NotificationService");
16658
16714
  });
16659
16715
 
16660
16716
  // ../api-core/src/services/realtime.service.ts
@@ -16689,20 +16745,20 @@ class RealtimeService {
16689
16745
  }
16690
16746
  const displayName = user.username || (user.name ? user.name.split(" ")[0] : undefined) || undefined;
16691
16747
  const token = await this.ctx.providers.auth.mintRealtimeToken(user.id, resolvedGameId, displayName, user.role);
16692
- logger19.info("Generated token", {
16748
+ logger20.info("Generated token", {
16693
16749
  userId: user.id,
16694
16750
  gameId: resolvedGameId || "global"
16695
16751
  });
16696
16752
  return { token };
16697
16753
  }
16698
16754
  }
16699
- var logger19;
16755
+ var logger20;
16700
16756
  var init_realtime_service = __esm(() => {
16701
16757
  init_drizzle_orm();
16702
16758
  init_tables_index();
16703
16759
  init_src2();
16704
16760
  init_errors();
16705
- logger19 = log.scope("RealtimeService");
16761
+ logger20 = log.scope("RealtimeService");
16706
16762
  });
16707
16763
 
16708
16764
  // ../api-core/src/services/secrets.service.ts
@@ -16715,7 +16771,7 @@ class SecretsService {
16715
16771
  const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
16716
16772
  const secrets = await this.ctx.providers.secrets.readSecrets(game.id);
16717
16773
  const keys = secrets ? Object.keys(secrets).filter((k) => !INTERNAL_SECRET_KEYS.includes(k)) : [];
16718
- logger20.debug("Listed secret keys", { gameId: game.id, slug: slug2, keyCount: keys.length });
16774
+ logger21.debug("Listed secret keys", { gameId: game.id, slug: slug2, keyCount: keys.length });
16719
16775
  return keys;
16720
16776
  }
16721
16777
  async getValues(slug2, user) {
@@ -16730,7 +16786,7 @@ class SecretsService {
16730
16786
  filtered[key] = value;
16731
16787
  }
16732
16788
  }
16733
- logger20.debug("Retrieved secret values", { gameId: game.id, slug: slug2 });
16789
+ logger21.debug("Retrieved secret values", { gameId: game.id, slug: slug2 });
16734
16790
  return filtered;
16735
16791
  }
16736
16792
  async setSecrets(slug2, newSecrets, user) {
@@ -16744,7 +16800,7 @@ class SecretsService {
16744
16800
  throw new ValidationError(`Secret value for "${key}" must be a string`);
16745
16801
  }
16746
16802
  if (INTERNAL_SECRET_KEYS.includes(key)) {
16747
- logger20.warn("Attempted to set reserved secret", {
16803
+ logger21.warn("Attempted to set reserved secret", {
16748
16804
  userId: user.id,
16749
16805
  gameId: game.id,
16750
16806
  key
@@ -16755,7 +16811,7 @@ class SecretsService {
16755
16811
  const existingSecrets = await this.ctx.providers.secrets.readSecrets(game.id) || {};
16756
16812
  const updatedSecrets = { ...existingSecrets, ...newSecrets };
16757
16813
  await this.ctx.providers.secrets.writeSecrets(game.id, updatedSecrets);
16758
- logger20.info("Set secrets", {
16814
+ logger21.info("Set secrets", {
16759
16815
  gameId: game.id,
16760
16816
  slug: slug2,
16761
16817
  addedKeys: secretKeys
@@ -16764,7 +16820,7 @@ class SecretsService {
16764
16820
  }
16765
16821
  async deleteSecret(slug2, key, user) {
16766
16822
  if (INTERNAL_SECRET_KEYS.includes(key)) {
16767
- logger20.warn("Attempted to delete reserved secret", {
16823
+ logger21.warn("Attempted to delete reserved secret", {
16768
16824
  userId: user.id,
16769
16825
  slug: slug2,
16770
16826
  key
@@ -16782,14 +16838,14 @@ class SecretsService {
16782
16838
  } else {
16783
16839
  await this.ctx.providers.secrets.deleteSecrets(game.id);
16784
16840
  }
16785
- logger20.info("Deleted secret", { gameId: game.id, slug: slug2, key });
16841
+ logger21.info("Deleted secret", { gameId: game.id, slug: slug2, key });
16786
16842
  }
16787
16843
  }
16788
- var logger20, INTERNAL_SECRET_KEYS;
16844
+ var logger21, INTERNAL_SECRET_KEYS;
16789
16845
  var init_secrets_service = __esm(() => {
16790
16846
  init_src2();
16791
16847
  init_errors();
16792
- logger20 = log.scope("SecretsService");
16848
+ logger21 = log.scope("SecretsService");
16793
16849
  INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY"];
16794
16850
  });
16795
16851
 
@@ -16802,7 +16858,7 @@ class SeedService {
16802
16858
  getCloudflare() {
16803
16859
  const cf = this.ctx.cloudflare;
16804
16860
  if (!cf) {
16805
- logger21.error("Cloudflare provider not available for seeding");
16861
+ logger22.error("Cloudflare provider not available for seeding");
16806
16862
  throw new ValidationError("Cloudflare provider not configured");
16807
16863
  }
16808
16864
  return cf;
@@ -16814,7 +16870,7 @@ class SeedService {
16814
16870
  const deploymentId = getDeploymentId(slug2, isProd);
16815
16871
  const uniqueSuffix = Date.now().toString(36);
16816
16872
  const seedDeploymentId = `seed-${deploymentId}-${uniqueSuffix}`;
16817
- logger21.debug("Seeding database", {
16873
+ logger22.debug("Seeding database", {
16818
16874
  userId: user.id,
16819
16875
  gameId: game.id,
16820
16876
  slug: slug2,
@@ -16823,7 +16879,7 @@ class SeedService {
16823
16879
  });
16824
16880
  try {
16825
16881
  const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code);
16826
- logger21.info("Seed completed", {
16882
+ logger22.info("Seed completed", {
16827
16883
  gameId: game.id,
16828
16884
  slug: slug2,
16829
16885
  deploymentId,
@@ -16839,7 +16895,7 @@ class SeedService {
16839
16895
  };
16840
16896
  } catch (error) {
16841
16897
  const errorMessage = error instanceof Error ? error.message : String(error);
16842
- logger21.error("Seed failed", {
16898
+ logger22.error("Seed failed", {
16843
16899
  slug: slug2,
16844
16900
  error: errorMessage
16845
16901
  });
@@ -16849,7 +16905,7 @@ class SeedService {
16849
16905
  error: errorMessage,
16850
16906
  developer: { id: user.id, email: user.email }
16851
16907
  }).catch((err2) => {
16852
- logger21.warn("Failed to send failure alert", { error: err2 });
16908
+ logger22.warn("Failed to send failure alert", { error: err2 });
16853
16909
  });
16854
16910
  if (error instanceof Error) {
16855
16911
  if (error.message.includes("timed out") || error.message.includes("AbortError")) {
@@ -16903,7 +16959,7 @@ class SeedService {
16903
16959
  bindings: { d1: [deploymentId], r2: [], kv: [] },
16904
16960
  keepAssets: false
16905
16961
  });
16906
- logger21.info("Worker deployed", { seedDeploymentId, url: result.url });
16962
+ logger22.info("Worker deployed", { seedDeploymentId, url: result.url });
16907
16963
  return await this.executeSeedWorker(result.url, seedDeploymentId);
16908
16964
  } finally {
16909
16965
  await this.cleanupSeedWorker(cf, seedDeploymentId);
@@ -16919,7 +16975,7 @@ class SeedService {
16919
16975
  await new Promise((resolve) => setTimeout(resolve, INITIAL_DELAY));
16920
16976
  for (let attempt = 0;attempt < MAX_RETRIES; attempt++) {
16921
16977
  if (attempt > 0) {
16922
- logger21.debug("Retrying seed execution", {
16978
+ logger22.debug("Retrying seed execution", {
16923
16979
  attempt: attempt + 1,
16924
16980
  maxRetries: MAX_RETRIES,
16925
16981
  nextRetryIn: `${RETRY_INTERVAL / 1000}s`
@@ -16939,14 +16995,14 @@ class SeedService {
16939
16995
  const isRetryable = response.status === 404 || response.status >= 500;
16940
16996
  if (isRetryable && attempt < MAX_RETRIES - 1) {
16941
16997
  lastError = new Error(`Worker returned ${response.status}`);
16942
- logger21.debug("Worker not ready, will retry", {
16998
+ logger22.debug("Worker not ready, will retry", {
16943
16999
  status: response.status,
16944
17000
  attempt: attempt + 1,
16945
17001
  errorBody: errorBody?.substring(0, 500)
16946
17002
  });
16947
17003
  continue;
16948
17004
  }
16949
- logger21.error("Worker returned error", {
17005
+ logger22.error("Worker returned error", {
16950
17006
  status: response.status,
16951
17007
  statusText: response.statusText,
16952
17008
  errorBody
@@ -16956,7 +17012,7 @@ class SeedService {
16956
17012
  const data = await response.json();
16957
17013
  if (!data.success) {
16958
17014
  const error = data.error || "Seed execution failed";
16959
- logger21.error("Seed execution failed", {
17015
+ logger22.error("Seed execution failed", {
16960
17016
  error,
16961
17017
  stack: data.stack,
16962
17018
  details: data.details,
@@ -16977,7 +17033,7 @@ class SeedService {
16977
17033
  };
16978
17034
  throw new InternalError(detailedMessage, errorDetails);
16979
17035
  }
16980
- logger21.info("Seed executed successfully", {
17036
+ logger22.info("Seed executed successfully", {
16981
17037
  seedDeploymentId,
16982
17038
  duration: data.duration,
16983
17039
  logCount: data.logs?.length ?? 0
@@ -16987,7 +17043,7 @@ class SeedService {
16987
17043
  clearTimeout(timeout);
16988
17044
  if (error instanceof Error && error.name === "AbortError") {
16989
17045
  lastError = new Error("Seed execution timed out");
16990
- logger21.debug("Seed execution timed out, will retry", {
17046
+ logger22.debug("Seed execution timed out, will retry", {
16991
17047
  attempt: attempt + 1
16992
17048
  });
16993
17049
  if (attempt < MAX_RETRIES - 1)
@@ -16998,7 +17054,7 @@ class SeedService {
16998
17054
  }
16999
17055
  lastError = error instanceof Error ? error : new Error(String(error));
17000
17056
  if (attempt < MAX_RETRIES - 1) {
17001
- logger21.debug("Network error, will retry", {
17057
+ logger22.debug("Network error, will retry", {
17002
17058
  error: lastError.message,
17003
17059
  attempt: attempt + 1
17004
17060
  });
@@ -17011,19 +17067,19 @@ class SeedService {
17011
17067
  async cleanupSeedWorker(cf, seedDeploymentId) {
17012
17068
  try {
17013
17069
  await cf.delete(seedDeploymentId);
17014
- logger21.info("Worker deleted", { seedDeploymentId });
17070
+ logger22.info("Worker deleted", { seedDeploymentId });
17015
17071
  } catch (error) {
17016
- logger21.warn("Failed to cleanup worker", { seedDeploymentId, error });
17072
+ logger22.warn("Failed to cleanup worker", { seedDeploymentId, error });
17017
17073
  }
17018
17074
  }
17019
17075
  }
17020
- var logger21;
17076
+ var logger22;
17021
17077
  var init_seed_service = __esm(() => {
17022
17078
  init_src2();
17023
17079
  init_config2();
17024
17080
  init_errors();
17025
17081
  init_deployment_util();
17026
- logger21 = log.scope("SeedService");
17082
+ logger22 = log.scope("SeedService");
17027
17083
  });
17028
17084
 
17029
17085
  // ../api-core/src/services/session.service.ts
@@ -17058,10 +17114,10 @@ class SessionService {
17058
17114
  };
17059
17115
  const [newSession] = await db2.insert(gameSessions).values(sessionToInsert).returning({ sessionId: gameSessions.id });
17060
17116
  if (!newSession?.sessionId) {
17061
- logger22.error("Game session insert returned no rows", { userId, gameId });
17117
+ logger23.error("Game session insert returned no rows", { userId, gameId });
17062
17118
  throw new InternalError("Failed to create game session");
17063
17119
  }
17064
- logger22.info("Started new session", {
17120
+ logger23.info("Started new session", {
17065
17121
  sessionId: newSession.sessionId,
17066
17122
  gameId,
17067
17123
  userId
@@ -17082,23 +17138,23 @@ class SessionService {
17082
17138
  return { success: true, message: "Session already ended" };
17083
17139
  }
17084
17140
  await db2.update(gameSessions).set({ endedAt: new Date }).where(eq(gameSessions.id, sessionId));
17085
- logger22.info("Ended session", { sessionId, gameId, userId });
17141
+ logger23.info("Ended session", { sessionId, gameId, userId });
17086
17142
  return { success: true };
17087
17143
  }
17088
17144
  async mintToken(gameIdOrSlug, userId) {
17089
17145
  const gameId = await this.resolveGameId(gameIdOrSlug);
17090
17146
  const result = await this.ctx.providers.auth.mintGameToken(gameId, userId);
17091
- logger22.debug("Minted game token", { gameId, userId });
17147
+ logger23.debug("Minted game token", { gameId, userId });
17092
17148
  return result;
17093
17149
  }
17094
17150
  }
17095
- var logger22;
17151
+ var logger23;
17096
17152
  var init_session_service = __esm(() => {
17097
17153
  init_drizzle_orm();
17098
17154
  init_tables_index();
17099
17155
  init_src2();
17100
17156
  init_errors();
17101
- logger22 = log.scope("SessionService");
17157
+ logger23 = log.scope("SessionService");
17102
17158
  });
17103
17159
 
17104
17160
  // ../api-core/src/services/shop-listing.service.ts
@@ -17110,7 +17166,7 @@ class ShopListingService {
17110
17166
  async list() {
17111
17167
  const db2 = this.ctx.db;
17112
17168
  const allListings = await db2.query.shopListings.findMany();
17113
- logger23.debug("Listed shop listings", { count: allListings.length });
17169
+ logger24.debug("Listed shop listings", { count: allListings.length });
17114
17170
  return allListings;
17115
17171
  }
17116
17172
  async getById(listingId) {
@@ -17121,7 +17177,7 @@ class ShopListingService {
17121
17177
  if (!listing) {
17122
17178
  throw new NotFoundError("ShopListing", listingId);
17123
17179
  }
17124
- logger23.debug("Retrieved listing", { listingId });
17180
+ logger24.debug("Retrieved listing", { listingId });
17125
17181
  return listing;
17126
17182
  }
17127
17183
  async create(data) {
@@ -17132,13 +17188,13 @@ class ShopListingService {
17132
17188
  price: data.price
17133
17189
  }).returning();
17134
17190
  if (!newListing) {
17135
- logger23.error("Shop listing insert returned no rows", {
17191
+ logger24.error("Shop listing insert returned no rows", {
17136
17192
  itemId: data.itemId,
17137
17193
  currencyId: data.currencyId
17138
17194
  });
17139
17195
  throw new InternalError("Failed to create shop listing");
17140
17196
  }
17141
- logger23.info("Created listing", {
17197
+ logger24.info("Created listing", {
17142
17198
  listingId: newListing.id,
17143
17199
  itemId: newListing.itemId,
17144
17200
  currencyId: newListing.currencyId,
@@ -17181,7 +17237,7 @@ class ShopListingService {
17181
17237
  if (!updatedListing) {
17182
17238
  throw new NotFoundError("ShopListing", listingId);
17183
17239
  }
17184
- logger23.info("Updated listing", {
17240
+ logger24.info("Updated listing", {
17185
17241
  listingId: updatedListing.id,
17186
17242
  updatedFields: Object.keys(updateData)
17187
17243
  });
@@ -17211,7 +17267,7 @@ class ShopListingService {
17211
17267
  if (result.length === 0) {
17212
17268
  throw new NotFoundError("ShopListing", listingId);
17213
17269
  }
17214
- logger23.info("Deleted listing", { listingId });
17270
+ logger24.info("Deleted listing", { listingId });
17215
17271
  }
17216
17272
  async listByGame(gameId, user) {
17217
17273
  await this.ctx.services.game.validateOwnership(user, gameId);
@@ -17229,7 +17285,7 @@ class ShopListingService {
17229
17285
  item: true
17230
17286
  }
17231
17287
  });
17232
- logger23.debug("Listed game listings", {
17288
+ logger24.debug("Listed game listings", {
17233
17289
  gameId,
17234
17290
  count: listings.length
17235
17291
  });
@@ -17259,14 +17315,14 @@ class ShopListingService {
17259
17315
  currencyId: currency.id
17260
17316
  }).returning();
17261
17317
  if (!newListing) {
17262
- logger23.error("Game item listing insert returned no rows", {
17318
+ logger24.error("Game item listing insert returned no rows", {
17263
17319
  gameId,
17264
17320
  itemId,
17265
17321
  currencyId: currency.id
17266
17322
  });
17267
17323
  throw new InternalError("Failed to create shop listing");
17268
17324
  }
17269
- logger23.info("Created game item listing", {
17325
+ logger24.info("Created game item listing", {
17270
17326
  listingId: newListing.id,
17271
17327
  gameId,
17272
17328
  itemId,
@@ -17307,7 +17363,7 @@ class ShopListingService {
17307
17363
  if (!updatedListing) {
17308
17364
  throw new NotFoundError("ShopListing", `for item ${itemId}`);
17309
17365
  }
17310
- logger23.info("Updated game item listing", {
17366
+ logger24.info("Updated game item listing", {
17311
17367
  listingId: updatedListing.id,
17312
17368
  gameId,
17313
17369
  itemId,
@@ -17332,7 +17388,7 @@ class ShopListingService {
17332
17388
  if (result.length === 0) {
17333
17389
  throw new NotFoundError("ShopListing", `for item ${itemId}`);
17334
17390
  }
17335
- logger23.info("Deleted game item listing", {
17391
+ logger24.info("Deleted game item listing", {
17336
17392
  listingId: result[0].id,
17337
17393
  gameId,
17338
17394
  itemId
@@ -17349,13 +17405,13 @@ class ShopListingService {
17349
17405
  }
17350
17406
  }
17351
17407
  }
17352
- var logger23;
17408
+ var logger24;
17353
17409
  var init_shop_listing_service = __esm(() => {
17354
17410
  init_drizzle_orm();
17355
17411
  init_tables_index();
17356
17412
  init_src2();
17357
17413
  init_errors();
17358
- logger23 = log.scope("ShopListingService");
17414
+ logger24 = log.scope("ShopListingService");
17359
17415
  });
17360
17416
 
17361
17417
  // ../api-core/src/services/shop.service.ts
@@ -17401,7 +17457,7 @@ class ShopService {
17401
17457
  const shopItems = [];
17402
17458
  for (const listing of listingsWithRelations) {
17403
17459
  if (!listing.item || !listing.currency) {
17404
- logger24.warn("Listing missing item or currency, skipping", {
17460
+ logger25.warn("Listing missing item or currency, skipping", {
17405
17461
  listingId: listing.id
17406
17462
  });
17407
17463
  continue;
@@ -17418,7 +17474,7 @@ class ShopService {
17418
17474
  sellBackPercentage: listing.sellBackPercentage
17419
17475
  });
17420
17476
  }
17421
- logger24.debug("Retrieved shop view", {
17477
+ logger25.debug("Retrieved shop view", {
17422
17478
  userId: user.id,
17423
17479
  itemCount: shopItems.length,
17424
17480
  currencyCount: shopCurrencies.length
@@ -17429,12 +17485,12 @@ class ShopService {
17429
17485
  };
17430
17486
  }
17431
17487
  }
17432
- var logger24;
17488
+ var logger25;
17433
17489
  var init_shop_service = __esm(() => {
17434
17490
  init_drizzle_orm();
17435
17491
  init_tables_index();
17436
17492
  init_src2();
17437
- logger24 = log.scope("ShopService");
17493
+ logger25 = log.scope("ShopService");
17438
17494
  });
17439
17495
 
17440
17496
  // ../api-core/src/services/sprite.service.ts
@@ -17451,17 +17507,17 @@ class SpriteService {
17451
17507
  if (!template) {
17452
17508
  throw new NotFoundError("SpriteTemplate", slug2);
17453
17509
  }
17454
- logger25.debug("Retrieved sprite", { slug: slug2 });
17510
+ logger26.debug("Retrieved sprite", { slug: slug2 });
17455
17511
  return template;
17456
17512
  }
17457
17513
  }
17458
- var logger25;
17514
+ var logger26;
17459
17515
  var init_sprite_service = __esm(() => {
17460
17516
  init_drizzle_orm();
17461
17517
  init_tables_index();
17462
17518
  init_src2();
17463
17519
  init_errors();
17464
- logger25 = log.scope("SpriteService");
17520
+ logger26 = log.scope("SpriteService");
17465
17521
  });
17466
17522
 
17467
17523
  // ../timeback/dist/types.js
@@ -17904,7 +17960,7 @@ class TimebackService {
17904
17960
  }
17905
17961
  requireClient() {
17906
17962
  if (!this.ctx.timeback) {
17907
- logger26.error("Timeback client not available in context");
17963
+ logger27.error("Timeback client not available in context");
17908
17964
  throw new ValidationError("Timeback integration not available in this environment");
17909
17965
  }
17910
17966
  return this.ctx.timeback;
@@ -17957,7 +18013,7 @@ class TimebackService {
17957
18013
  set: { xp: sql`excluded.xp`, updatedAt: new Date }
17958
18014
  }).returning({ xp: timebackDailyXp.xp, date: timebackDailyXp.date });
17959
18015
  if (!result) {
17960
- logger26.error("Daily XP upsert returned no rows", { userId, date: targetDate });
18016
+ logger27.error("Daily XP upsert returned no rows", { userId, date: targetDate });
17961
18017
  throw new InternalError("Failed to update daily XP record");
17962
18018
  }
17963
18019
  return { xp: result.xp, date: result.date.toISOString() };
@@ -17988,7 +18044,7 @@ class TimebackService {
17988
18044
  columns: { id: true, timebackId: true }
17989
18045
  });
17990
18046
  if (dbUser?.timebackId) {
17991
- logger26.info("Student already onboarded", { userId: user.id });
18047
+ logger27.info("Student already onboarded", { userId: user.id });
17992
18048
  return { status: "already_populated" };
17993
18049
  }
17994
18050
  let timebackId;
@@ -17997,7 +18053,7 @@ class TimebackService {
17997
18053
  const existingUser = await client.oneroster.users.findByEmail(user.email);
17998
18054
  timebackId = existingUser.sourcedId;
17999
18055
  name3 = `${existingUser.givenName} ${existingUser.familyName}`;
18000
- logger26.info("Found existing student in OneRoster", {
18056
+ logger27.info("Found existing student in OneRoster", {
18001
18057
  userId: user.id,
18002
18058
  timebackId
18003
18059
  });
@@ -18026,7 +18082,7 @@ class TimebackService {
18026
18082
  }
18027
18083
  timebackId = response.sourcedIdPairs.allocatedSourcedId;
18028
18084
  name3 = `${providedNames.firstName} ${providedNames.lastName}`;
18029
- logger26.info("Created student in OneRoster", { userId: user.id, timebackId });
18085
+ logger27.info("Created student in OneRoster", { userId: user.id, timebackId });
18030
18086
  }
18031
18087
  const assessments = await this.fetchAssessments(timebackId);
18032
18088
  await db2.transaction(async (tx) => {
@@ -18060,7 +18116,7 @@ class TimebackService {
18060
18116
  }
18061
18117
  const [updated] = await tx.update(users).set({ timebackId, name: name3 }).where(eq(users.id, user.id)).returning({ id: users.id });
18062
18118
  if (!updated) {
18063
- logger26.error("User Timeback ID update returned no rows", {
18119
+ logger27.error("User Timeback ID update returned no rows", {
18064
18120
  userId: user.id,
18065
18121
  timebackId
18066
18122
  });
@@ -18083,13 +18139,13 @@ class TimebackService {
18083
18139
  break;
18084
18140
  offset += limit;
18085
18141
  }
18086
- logger26.debug("Fetched assessments", {
18142
+ logger27.debug("Fetched assessments", {
18087
18143
  studentSourcedId,
18088
18144
  totalCount: allAssessments.length
18089
18145
  });
18090
18146
  return allAssessments;
18091
18147
  } catch (error) {
18092
- logger26.warn("Failed to fetch assessments", { studentSourcedId, error });
18148
+ logger27.warn("Failed to fetch assessments", { studentSourcedId, error });
18093
18149
  return [];
18094
18150
  }
18095
18151
  }
@@ -18196,7 +18252,7 @@ class TimebackService {
18196
18252
  masterableUnits: derivedMasterableUnits
18197
18253
  } = courseConfig;
18198
18254
  if (!isTimebackSubject(subjectInput)) {
18199
- logger26.warn("Invalid Timeback subject in course config", {
18255
+ logger27.warn("Invalid Timeback subject in course config", {
18200
18256
  subject: subjectInput,
18201
18257
  courseCode,
18202
18258
  title
@@ -18204,7 +18260,7 @@ class TimebackService {
18204
18260
  throw new ValidationError(`Invalid subject "${subjectInput}"`);
18205
18261
  }
18206
18262
  if (!isTimebackGrade(grade)) {
18207
- logger26.warn("Invalid Timeback grade in course config", {
18263
+ logger27.warn("Invalid Timeback grade in course config", {
18208
18264
  grade,
18209
18265
  courseCode,
18210
18266
  title
@@ -18216,7 +18272,7 @@ class TimebackService {
18216
18272
  const totalXp = derivedTotalXp ?? courseMetadata?.metrics?.totalXp;
18217
18273
  const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
18218
18274
  if (typeof totalXp !== "number") {
18219
- logger26.warn("Course missing totalXp in Timeback config", {
18275
+ logger27.warn("Course missing totalXp in Timeback config", {
18220
18276
  courseCode,
18221
18277
  title
18222
18278
  });
@@ -18387,7 +18443,7 @@ class TimebackService {
18387
18443
  courseName: activityData.courseName,
18388
18444
  studentEmail: activityData.studentEmail
18389
18445
  });
18390
- logger26.info("Recorded activity completion", {
18446
+ logger27.info("Recorded activity completion", {
18391
18447
  gameId,
18392
18448
  courseId: integration.courseId,
18393
18449
  studentId,
@@ -18404,7 +18460,7 @@ class TimebackService {
18404
18460
  };
18405
18461
  }
18406
18462
  }
18407
- var logger26;
18463
+ var logger27;
18408
18464
  var init_timeback_service = __esm(() => {
18409
18465
  init_drizzle_orm();
18410
18466
  init_src();
@@ -18414,7 +18470,7 @@ var init_timeback_service = __esm(() => {
18414
18470
  init_src4();
18415
18471
  init_errors();
18416
18472
  init_timeback_util();
18417
- logger26 = log.scope("TimebackService");
18473
+ logger27 = log.scope("TimebackService");
18418
18474
  });
18419
18475
 
18420
18476
  // ../api-core/src/services/upload.service.ts
@@ -18427,15 +18483,15 @@ class UploadService {
18427
18483
  const { fileName, gameId } = request2;
18428
18484
  const bucketName = this.ctx.config.uploadBucket;
18429
18485
  if (!bucketName) {
18430
- logger27.error("Upload bucket not configured in environment");
18486
+ logger28.error("Upload bucket not configured in environment");
18431
18487
  throw new ValidationError("Upload bucket not configured");
18432
18488
  }
18433
18489
  await this.ctx.services.game.validateDeveloperAccess(user, gameId);
18434
18490
  const version2 = ulid();
18435
18491
  const tempS3Key = `uploads-temp/${gameId}/${version2}/${fileName}`;
18436
- logger27.debug("Initiating upload", { userId: user.id, gameId, fileName, version: version2 });
18492
+ logger28.debug("Initiating upload", { userId: user.id, gameId, fileName, version: version2 });
18437
18493
  const presignedUrl = await this.ctx.providers.storage.generatePresignedPutUrl(bucketName, tempS3Key, "application/zip");
18438
- logger27.info("Presigned URL generated", {
18494
+ logger28.info("Presigned URL generated", {
18439
18495
  userId: user.id,
18440
18496
  gameId,
18441
18497
  version: version2
@@ -18448,12 +18504,12 @@ class UploadService {
18448
18504
  };
18449
18505
  }
18450
18506
  }
18451
- var logger27;
18507
+ var logger28;
18452
18508
  var init_upload_service = __esm(() => {
18453
18509
  init_node();
18454
18510
  init_src2();
18455
18511
  init_errors();
18456
- logger27 = log.scope("UploadService");
18512
+ logger28 = log.scope("UploadService");
18457
18513
  });
18458
18514
 
18459
18515
  // ../api-core/src/services/user.service.ts
@@ -18468,12 +18524,12 @@ class UserService {
18468
18524
  where: eq(users.id, user.id)
18469
18525
  });
18470
18526
  if (!userData) {
18471
- logger28.error("User not found", { userId: user.id });
18527
+ logger29.error("User not found", { userId: user.id });
18472
18528
  throw new NotFoundError("User", user.id);
18473
18529
  }
18474
18530
  const timeback2 = userData.timebackId ? await this.fetchTimebackData(userData.timebackId, gameId) : undefined;
18475
18531
  if (gameId) {
18476
- logger28.debug("Fetched user profile (game context)", { userId: user.id, gameId });
18532
+ logger29.debug("Fetched user profile (game context)", { userId: user.id, gameId });
18477
18533
  return {
18478
18534
  id: userData.id,
18479
18535
  name: userData.name,
@@ -18486,7 +18542,7 @@ class UserService {
18486
18542
  const timebackAccount = await db2.query.accounts.findFirst({
18487
18543
  where: and(eq(accounts.userId, user.id), eq(accounts.providerId, "timeback"))
18488
18544
  });
18489
- logger28.debug("Fetched user profile (platform context)", { userId: user.id });
18545
+ logger29.debug("Fetched user profile (platform context)", { userId: user.id });
18490
18546
  return {
18491
18547
  id: userData.id,
18492
18548
  name: userData.name,
@@ -18510,7 +18566,7 @@ class UserService {
18510
18566
  ]);
18511
18567
  const enrollments = gameId ? this.filterEnrollmentsByGame(allEnrollments, gameId) : allEnrollments;
18512
18568
  const organizations = gameId ? this.filterOrganizationsByEnrollments(allOrganizations, enrollments) : allOrganizations;
18513
- logger28.debug("Fetched Timeback data", {
18569
+ logger29.debug("Fetched Timeback data", {
18514
18570
  timebackId,
18515
18571
  role,
18516
18572
  enrollmentCount: enrollments.length,
@@ -18519,9 +18575,9 @@ class UserService {
18519
18575
  return { id: timebackId, role, enrollments, organizations };
18520
18576
  }
18521
18577
  async fetchStudentProfile(timebackId) {
18522
- logger28.debug("Fetching student profile", { timebackId });
18578
+ logger29.debug("Fetching student profile", { timebackId });
18523
18579
  if (!this.ctx.timeback) {
18524
- logger28.warn("Timeback client not available");
18580
+ logger29.warn("Timeback client not available");
18525
18581
  return { role: "student", organizations: [] };
18526
18582
  }
18527
18583
  try {
@@ -18549,14 +18605,14 @@ class UserService {
18549
18605
  }
18550
18606
  return { role, organizations: Array.from(orgMap.values()) };
18551
18607
  } catch (error) {
18552
- logger28.warn("Failed to fetch student profile", { error, timebackId });
18608
+ logger29.warn("Failed to fetch student profile", { error, timebackId });
18553
18609
  return { role: "student", organizations: [] };
18554
18610
  }
18555
18611
  }
18556
18612
  async fetchEnrollments(timebackId) {
18557
- logger28.debug("Fetching enrollments", { timebackId });
18613
+ logger29.debug("Fetching enrollments", { timebackId });
18558
18614
  if (!this.ctx.timeback) {
18559
- logger28.warn("Timeback client not available");
18615
+ logger29.warn("Timeback client not available");
18560
18616
  return [];
18561
18617
  }
18562
18618
  try {
@@ -18576,7 +18632,7 @@ class UserService {
18576
18632
  orgId: courseToSchool.get(i2.courseId)
18577
18633
  }));
18578
18634
  } catch (error) {
18579
- logger28.warn("Failed to fetch enrollments", { error, timebackId });
18635
+ logger29.warn("Failed to fetch enrollments", { error, timebackId });
18580
18636
  return [];
18581
18637
  }
18582
18638
  }
@@ -18590,13 +18646,13 @@ class UserService {
18590
18646
  return organizations.filter((o) => enrollmentOrgIds.has(o.id));
18591
18647
  }
18592
18648
  }
18593
- var logger28;
18649
+ var logger29;
18594
18650
  var init_user_service = __esm(() => {
18595
18651
  init_drizzle_orm();
18596
18652
  init_tables_index();
18597
18653
  init_src2();
18598
18654
  init_errors();
18599
- logger28 = log.scope("UserService");
18655
+ logger29 = log.scope("UserService");
18600
18656
  });
18601
18657
 
18602
18658
  // ../api-core/src/services/verify.service.ts
@@ -18606,16 +18662,16 @@ class VerifyService {
18606
18662
  this.ctx = ctx;
18607
18663
  }
18608
18664
  async verifyGameToken(token) {
18609
- logger29.debug("Verifying game token");
18665
+ logger30.debug("Verifying game token");
18610
18666
  const payload = await this.ctx.providers.auth.validateGameToken(token);
18611
18667
  if (!payload) {
18612
- logger29.warn("Invalid or expired game token presented");
18668
+ logger30.warn("Invalid or expired game token presented");
18613
18669
  throw new ValidationError("Invalid or expired token");
18614
18670
  }
18615
18671
  const gameId = payload.sub;
18616
18672
  const userId = payload.uid;
18617
18673
  if (typeof gameId !== "string" || typeof userId !== "string") {
18618
- logger29.warn("Game token missing required claims", {
18674
+ logger30.warn("Game token missing required claims", {
18619
18675
  hasGameId: typeof gameId === "string",
18620
18676
  hasUserId: typeof userId === "string"
18621
18677
  });
@@ -18626,7 +18682,7 @@ class VerifyService {
18626
18682
  where: eq(users.id, userId)
18627
18683
  });
18628
18684
  if (!userData) {
18629
- logger29.error("User not found for valid token", {
18685
+ logger30.error("User not found for valid token", {
18630
18686
  userId
18631
18687
  });
18632
18688
  throw new NotFoundError("User", userId);
@@ -18640,7 +18696,7 @@ class VerifyService {
18640
18696
  family_name: undefined,
18641
18697
  timeback_id: userData.timebackId || undefined
18642
18698
  };
18643
- logger29.info("Token verified", { gameId, userId });
18699
+ logger30.info("Token verified", { gameId, userId });
18644
18700
  return {
18645
18701
  claims: payload,
18646
18702
  gameId,
@@ -18648,13 +18704,13 @@ class VerifyService {
18648
18704
  };
18649
18705
  }
18650
18706
  }
18651
- var logger29;
18707
+ var logger30;
18652
18708
  var init_verify_service = __esm(() => {
18653
18709
  init_drizzle_orm();
18654
18710
  init_tables_index();
18655
18711
  init_src2();
18656
18712
  init_errors();
18657
- logger29 = log.scope("VerifyService");
18713
+ logger30 = log.scope("VerifyService");
18658
18714
  });
18659
18715
 
18660
18716
  // ../api-core/src/services/index.ts
@@ -18674,6 +18730,7 @@ function createServices(ctx) {
18674
18730
  item: new ItemService(ctx),
18675
18731
  leaderboard: new LeaderboardService(ctx),
18676
18732
  level: new LevelService(ctx),
18733
+ logs: new LogsService(ctx),
18677
18734
  lti: new LtiService(ctx),
18678
18735
  map: new MapService(ctx),
18679
18736
  notification: new NotificationService(ctx),
@@ -18705,6 +18762,7 @@ var init_services = __esm(() => {
18705
18762
  init_item_service();
18706
18763
  init_leaderboard_service();
18707
18764
  init_level_service();
18765
+ init_logs_service();
18708
18766
  init_lti_service();
18709
18767
  init_map_service();
18710
18768
  init_notification_service();
@@ -18801,6 +18859,38 @@ function createSandboxAuthProvider() {
18801
18859
  const header = btoa(JSON.stringify({ alg: "none", typ: "sandbox" }));
18802
18860
  const payloadStr = btoa(JSON.stringify(payload));
18803
18861
  return `${header}.${payloadStr}.sandbox`;
18862
+ },
18863
+ async mintLogStreamToken(userId, workerId) {
18864
+ const jti = crypto.randomUUID();
18865
+ const payload = {
18866
+ sub: userId,
18867
+ game: workerId,
18868
+ jti,
18869
+ exp: Date.now() + 60 * 1000
18870
+ };
18871
+ const header = btoa(JSON.stringify({ alg: "none", typ: "sandbox" }));
18872
+ const payloadStr = btoa(JSON.stringify(payload));
18873
+ return `${header}.${payloadStr}.sandbox`;
18874
+ },
18875
+ async validateLogStreamToken(token) {
18876
+ try {
18877
+ const parts2 = token.split(".");
18878
+ if (parts2.length !== 3)
18879
+ return null;
18880
+ if (parts2[2] === "sandbox") {
18881
+ const payload = JSON.parse(atob(parts2[1]));
18882
+ if (payload.jti && payload.sub && payload.game) {
18883
+ if (payload.exp && payload.exp < Date.now()) {
18884
+ log.debug("[SandboxAuthProvider] Log stream token expired");
18885
+ return null;
18886
+ }
18887
+ return { jti: payload.jti, sub: payload.sub, game: payload.game };
18888
+ }
18889
+ }
18890
+ return null;
18891
+ } catch {
18892
+ return null;
18893
+ }
18804
18894
  }
18805
18895
  };
18806
18896
  }
@@ -20783,7 +20873,7 @@ var humanize = (times) => {
20783
20873
  }
20784
20874
  }
20785
20875
  return `${status}`;
20786
- }, logger30 = (fn = console.log) => {
20876
+ }, logger31 = (fn = console.log) => {
20787
20877
  return async function logger2(c, next) {
20788
20878
  const { method, url } = c.req;
20789
20879
  const path = url.slice(url.indexOf("/", 8));
@@ -20960,7 +21050,7 @@ function createApp(db2, options) {
20960
21050
  const app = new Hono2;
20961
21051
  app.use("*", cors({ origin: "*", credentials: true }));
20962
21052
  if (options.verbose && !options.quiet) {
20963
- app.use("*", logger30());
21053
+ app.use("*", logger31());
20964
21054
  }
20965
21055
  app.use("/api/*", async (c, next) => {
20966
21056
  c.set("db", db2);
@@ -27433,12 +27523,12 @@ var init_session2 = __esm(() => {
27433
27523
  init_utils();
27434
27524
  init_dist4();
27435
27525
  PglitePreparedQuery = class PglitePreparedQuery extends PgPreparedQuery {
27436
- constructor(client, queryString, params, logger31, fields, name3, _isResponseInArrayMode, customResultMapper) {
27526
+ constructor(client, queryString, params, logger32, fields, name3, _isResponseInArrayMode, customResultMapper) {
27437
27527
  super({ sql: queryString, params });
27438
27528
  this.client = client;
27439
27529
  this.queryString = queryString;
27440
27530
  this.params = params;
27441
- this.logger = logger31;
27531
+ this.logger = logger32;
27442
27532
  this.fields = fields;
27443
27533
  this._isResponseInArrayMode = _isResponseInArrayMode;
27444
27534
  this.customResultMapper = customResultMapper;
@@ -27542,11 +27632,11 @@ var init_session2 = __esm(() => {
27542
27632
  // ../../node_modules/drizzle-orm/pglite/driver.js
27543
27633
  function construct(client, config2 = {}) {
27544
27634
  const dialect2 = new PgDialect({ casing: config2.casing });
27545
- let logger31;
27635
+ let logger32;
27546
27636
  if (config2.logger === true) {
27547
- logger31 = new DefaultLogger;
27637
+ logger32 = new DefaultLogger;
27548
27638
  } else if (config2.logger !== false) {
27549
- logger31 = config2.logger;
27639
+ logger32 = config2.logger;
27550
27640
  }
27551
27641
  let schema2;
27552
27642
  if (config2.schema) {
@@ -27557,7 +27647,7 @@ function construct(client, config2 = {}) {
27557
27647
  tableNamesMap: tablesConfig.tableNamesMap
27558
27648
  };
27559
27649
  }
27560
- const driver = new PgliteDriver(client, dialect2, { logger: logger31 });
27650
+ const driver = new PgliteDriver(client, dialect2, { logger: logger32 });
27561
27651
  const session2 = driver.createSession(schema2);
27562
27652
  const db2 = new PgliteDatabase(dialect2, session2, schema2);
27563
27653
  db2.$client = client;
@@ -76138,8 +76228,8 @@ var init_currencies = __esm(() => {
76138
76228
  });
76139
76229
 
76140
76230
  // src/lib/logging/adapter.ts
76141
- function setLogger(logger31) {
76142
- customLogger = logger31;
76231
+ function setLogger(logger32) {
76232
+ customLogger = logger32;
76143
76233
  }
76144
76234
  function getLogger() {
76145
76235
  if (customLogger) {
@@ -76151,10 +76241,10 @@ function getLogger() {
76151
76241
  error: (msg) => console.error(msg)
76152
76242
  };
76153
76243
  }
76154
- var customLogger, logger31;
76244
+ var customLogger, logger32;
76155
76245
  var init_adapter = __esm(() => {
76156
76246
  init_config();
76157
- logger31 = {
76247
+ logger32 = {
76158
76248
  info: (msg) => {
76159
76249
  if (customLogger || !config.embedded) {
76160
76250
  getLogger().info(msg);
@@ -76241,7 +76331,7 @@ async function seedCoreGames(db2) {
76241
76331
  try {
76242
76332
  await db2.insert(games).values(gameData).onConflictDoNothing();
76243
76333
  } catch (error2) {
76244
- logger31.error(`Error seeding core game '${gameData.slug}': ${error2}`);
76334
+ logger32.error(`Error seeding core game '${gameData.slug}': ${error2}`);
76245
76335
  }
76246
76336
  }
76247
76337
  }
@@ -76282,7 +76372,7 @@ async function seedCurrentProjectGame(db2, project) {
76282
76372
  }
76283
76373
  return newGame;
76284
76374
  } catch (error2) {
76285
- logger31.error(`❌ Error seeding project game: ${error2}`);
76375
+ logger32.error(`❌ Error seeding project game: ${error2}`);
76286
76376
  throw error2;
76287
76377
  }
76288
76378
  }
@@ -77721,21 +77811,21 @@ var init_utils11 = __esm(() => {
77721
77811
  });
77722
77812
 
77723
77813
  // ../api-core/src/controllers/achievement.controller.ts
77724
- var logger32, listCurrent, listHistory, postProgress, achievements3;
77814
+ var logger33, listCurrent, listHistory, postProgress, achievements3;
77725
77815
  var init_achievement_controller = __esm(() => {
77726
77816
  init_esm();
77727
77817
  init_schemas_index();
77728
77818
  init_src2();
77729
77819
  init_errors();
77730
77820
  init_utils11();
77731
- logger32 = log.scope("AchievementController");
77821
+ logger33 = log.scope("AchievementController");
77732
77822
  listCurrent = requireAuth(async (ctx) => {
77733
- logger32.debug("Listing current achievements", { userId: ctx.user.id, gameId: ctx.gameId });
77823
+ logger33.debug("Listing current achievements", { userId: ctx.user.id, gameId: ctx.gameId });
77734
77824
  return ctx.services.achievement.listCurrent(ctx.user, ctx.gameId);
77735
77825
  });
77736
77826
  listHistory = requireAuth(async (ctx) => {
77737
77827
  const limit = Math.max(1, Math.min(100, Number(ctx.url.searchParams.get("limit")) || 20));
77738
- logger32.debug("Listing achievement history", { userId: ctx.user.id, limit });
77828
+ logger33.debug("Listing achievement history", { userId: ctx.user.id, limit });
77739
77829
  return ctx.services.achievement.listHistory(ctx.user, limit);
77740
77830
  });
77741
77831
  postProgress = requireAuth(async (ctx) => {
@@ -77746,12 +77836,12 @@ var init_achievement_controller = __esm(() => {
77746
77836
  } catch (error2) {
77747
77837
  if (error2 instanceof exports_external.ZodError) {
77748
77838
  const details = formatZodError(error2);
77749
- logger32.warn("Submit achievement progress validation failed", { details });
77839
+ logger33.warn("Submit achievement progress validation failed", { details });
77750
77840
  throw ApiError.unprocessableEntity("Invalid request body", details);
77751
77841
  }
77752
77842
  throw ApiError.badRequest("Invalid JSON body");
77753
77843
  }
77754
- logger32.debug("Submitting progress", {
77844
+ logger33.debug("Submitting progress", {
77755
77845
  userId: ctx.user.id,
77756
77846
  achievementId: body2.achievementId
77757
77847
  });
@@ -77765,14 +77855,14 @@ var init_achievement_controller = __esm(() => {
77765
77855
  });
77766
77856
 
77767
77857
  // ../api-core/src/controllers/admin.controller.ts
77768
- var logger33, getAllowedOrigins;
77858
+ var logger34, getAllowedOrigins;
77769
77859
  var init_admin_controller = __esm(() => {
77770
77860
  init_src2();
77771
77861
  init_utils11();
77772
- logger33 = log.scope("AdminController");
77862
+ logger34 = log.scope("AdminController");
77773
77863
  getAllowedOrigins = requireAdmin(async (ctx) => {
77774
77864
  const shouldRefresh = ctx.url.searchParams.get("refresh") === "true";
77775
- logger33.debug("Getting allowed origins", { userId: ctx.user.id, refresh: shouldRefresh });
77865
+ logger34.debug("Getting allowed origins", { userId: ctx.user.id, refresh: shouldRefresh });
77776
77866
  if (shouldRefresh) {
77777
77867
  await ctx.providers.cache.refreshGameOrigins();
77778
77868
  }
@@ -77787,14 +77877,14 @@ var init_admin_controller = __esm(() => {
77787
77877
  });
77788
77878
 
77789
77879
  // ../api-core/src/controllers/bucket.controller.ts
77790
- var logger34, listFiles, getFile, putFile, deleteFile, initiateUpload;
77880
+ var logger35, listFiles, getFile, putFile, deleteFile, initiateUpload;
77791
77881
  var init_bucket_controller = __esm(() => {
77792
77882
  init_esm();
77793
77883
  init_schemas_index();
77794
77884
  init_src2();
77795
77885
  init_errors();
77796
77886
  init_utils11();
77797
- logger34 = log.scope("BucketController");
77887
+ logger35 = log.scope("BucketController");
77798
77888
  listFiles = requireDeveloper(async (ctx) => {
77799
77889
  const slug2 = ctx.params.slug;
77800
77890
  if (!slug2) {
@@ -77802,7 +77892,7 @@ var init_bucket_controller = __esm(() => {
77802
77892
  }
77803
77893
  const url = ctx.url;
77804
77894
  const prefix2 = url.searchParams.get("prefix") || undefined;
77805
- logger34.debug("Listing files", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
77895
+ logger35.debug("Listing files", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
77806
77896
  const files = await ctx.services.bucket.listFiles(slug2, ctx.user, prefix2);
77807
77897
  return { files };
77808
77898
  });
@@ -77812,7 +77902,7 @@ var init_bucket_controller = __esm(() => {
77812
77902
  if (!slug2 || !key) {
77813
77903
  throw ApiError.badRequest("Missing game slug or file key");
77814
77904
  }
77815
- logger34.debug("Getting file", { userId: ctx.user.id, slug: slug2, key });
77905
+ logger35.debug("Getting file", { userId: ctx.user.id, slug: slug2, key });
77816
77906
  const object = await ctx.services.bucket.getFile(slug2, key, ctx.user);
77817
77907
  return new Response(Buffer.from(object.body), {
77818
77908
  status: 200,
@@ -77831,7 +77921,7 @@ var init_bucket_controller = __esm(() => {
77831
77921
  const arrayBuffer = await ctx.request.arrayBuffer();
77832
77922
  const body2 = new Uint8Array(arrayBuffer);
77833
77923
  const contentType = ctx.request.headers.get("content-type") || undefined;
77834
- logger34.debug("Uploading file", {
77924
+ logger35.debug("Uploading file", {
77835
77925
  userId: ctx.user.id,
77836
77926
  slug: slug2,
77837
77927
  key,
@@ -77847,7 +77937,7 @@ var init_bucket_controller = __esm(() => {
77847
77937
  if (!slug2 || !key) {
77848
77938
  throw ApiError.badRequest("Missing game slug or file key");
77849
77939
  }
77850
- logger34.debug("Deleting file", { userId: ctx.user.id, slug: slug2, key });
77940
+ logger35.debug("Deleting file", { userId: ctx.user.id, slug: slug2, key });
77851
77941
  await ctx.services.bucket.deleteFile(slug2, key, ctx.user);
77852
77942
  return { success: true, key };
77853
77943
  });
@@ -77859,12 +77949,12 @@ var init_bucket_controller = __esm(() => {
77859
77949
  } catch (error2) {
77860
77950
  if (error2 instanceof exports_external.ZodError) {
77861
77951
  const details = formatZodError(error2);
77862
- logger34.warn("Initiate upload validation failed", { details });
77952
+ logger35.warn("Initiate upload validation failed", { details });
77863
77953
  throw ApiError.unprocessableEntity("Validation failed", details);
77864
77954
  }
77865
77955
  throw ApiError.badRequest("Invalid JSON body");
77866
77956
  }
77867
- logger34.debug("Initiating multipart upload", {
77957
+ logger35.debug("Initiating multipart upload", {
77868
77958
  userId: ctx.user.id,
77869
77959
  gameId: body2.gameId,
77870
77960
  fileName: body2.fileName
@@ -77881,19 +77971,19 @@ async function listComponents(ctx) {
77881
77971
  if (!isNaN(parsed) && isFinite(parsed)) {
77882
77972
  level = Math.floor(Math.max(0, parsed));
77883
77973
  }
77884
- logger35.debug("Listing components", { level });
77974
+ logger36.debug("Listing components", { level });
77885
77975
  return ctx.services.character.listAvailableComponents(level);
77886
77976
  }
77887
- var logger35, get, getByUserId, create, update2, equipAccessory, removeAccessory, character2;
77977
+ var logger36, get, getByUserId, create, update2, equipAccessory, removeAccessory, character2;
77888
77978
  var init_character_controller = __esm(() => {
77889
77979
  init_esm();
77890
77980
  init_schemas_index();
77891
77981
  init_src2();
77892
77982
  init_errors();
77893
77983
  init_utils11();
77894
- logger35 = log.scope("CharacterController");
77984
+ logger36 = log.scope("CharacterController");
77895
77985
  get = requireAuth(async (ctx) => {
77896
- logger35.debug("Getting character", { userId: ctx.user.id });
77986
+ logger36.debug("Getting character", { userId: ctx.user.id });
77897
77987
  return ctx.services.character.getByUser(ctx.user);
77898
77988
  });
77899
77989
  getByUserId = requireAuth(async (ctx) => {
@@ -77901,7 +77991,7 @@ var init_character_controller = __esm(() => {
77901
77991
  if (!userId) {
77902
77992
  throw ApiError.badRequest("User ID is required in the URL path");
77903
77993
  }
77904
- logger35.debug("Getting character by user ID", { requestedUserId: userId });
77994
+ logger36.debug("Getting character by user ID", { requestedUserId: userId });
77905
77995
  return ctx.services.character.getByUserId(userId);
77906
77996
  });
77907
77997
  create = requireAuth(async (ctx) => {
@@ -77912,12 +78002,12 @@ var init_character_controller = __esm(() => {
77912
78002
  } catch (error2) {
77913
78003
  if (error2 instanceof exports_external.ZodError) {
77914
78004
  const details = formatZodError(error2);
77915
- logger35.warn("Create character validation failed", { details });
78005
+ logger36.warn("Create character validation failed", { details });
77916
78006
  throw ApiError.unprocessableEntity("Invalid request body", details);
77917
78007
  }
77918
78008
  throw ApiError.badRequest("Invalid JSON body");
77919
78009
  }
77920
- logger35.debug("Creating character", {
78010
+ logger36.debug("Creating character", {
77921
78011
  userId: ctx.user.id,
77922
78012
  bodyComponentId: body2.bodyComponentId,
77923
78013
  hairstyleComponentId: body2.hairstyleComponentId
@@ -77932,12 +78022,12 @@ var init_character_controller = __esm(() => {
77932
78022
  } catch (error2) {
77933
78023
  if (error2 instanceof exports_external.ZodError) {
77934
78024
  const details = formatZodError(error2);
77935
- logger35.warn("Update character validation failed", { details });
78025
+ logger36.warn("Update character validation failed", { details });
77936
78026
  throw ApiError.unprocessableEntity("Invalid request body", details);
77937
78027
  }
77938
78028
  throw ApiError.badRequest("Invalid JSON body");
77939
78029
  }
77940
- logger35.debug("Updating character", {
78030
+ logger36.debug("Updating character", {
77941
78031
  userId: ctx.user.id,
77942
78032
  bodyComponentId: body2.bodyComponentId,
77943
78033
  hairstyleComponentId: body2.hairstyleComponentId,
@@ -77953,12 +78043,12 @@ var init_character_controller = __esm(() => {
77953
78043
  } catch (error2) {
77954
78044
  if (error2 instanceof exports_external.ZodError) {
77955
78045
  const details = formatZodError(error2);
77956
- logger35.warn("Equip accessory validation failed", { details });
78046
+ logger36.warn("Equip accessory validation failed", { details });
77957
78047
  throw ApiError.unprocessableEntity("Invalid request body", details);
77958
78048
  }
77959
78049
  throw ApiError.badRequest("Invalid JSON body");
77960
78050
  }
77961
- logger35.debug("Equipping accessory", {
78051
+ logger36.debug("Equipping accessory", {
77962
78052
  userId: ctx.user.id,
77963
78053
  slot: body2.slot,
77964
78054
  accessoryComponentId: body2.accessoryComponentId
@@ -77970,7 +78060,7 @@ var init_character_controller = __esm(() => {
77970
78060
  if (!slot) {
77971
78061
  throw ApiError.badRequest("Slot is required in the URL path");
77972
78062
  }
77973
- logger35.debug("Removing accessory", { userId: ctx.user.id, slot });
78063
+ logger36.debug("Removing accessory", { userId: ctx.user.id, slot });
77974
78064
  await ctx.services.character.removeAccessory(slot, ctx.user);
77975
78065
  return { success: true };
77976
78066
  });
@@ -77986,7 +78076,7 @@ var init_character_controller = __esm(() => {
77986
78076
  });
77987
78077
 
77988
78078
  // ../api-core/src/controllers/currency.controller.ts
77989
- var logger36, list, getById, create2, update3, remove, currencyController;
78079
+ var logger37, list, getById, create2, update3, remove, currencyController;
77990
78080
  var init_currency_controller = __esm(() => {
77991
78081
  init_esm();
77992
78082
  init_schemas_index();
@@ -77994,9 +78084,9 @@ var init_currency_controller = __esm(() => {
77994
78084
  init_src4();
77995
78085
  init_errors();
77996
78086
  init_utils11();
77997
- logger36 = log.scope("CurrencyController");
78087
+ logger37 = log.scope("CurrencyController");
77998
78088
  list = requireAuth(async (ctx) => {
77999
- logger36.debug("Listing currencies", { userId: ctx.user.id });
78089
+ logger37.debug("Listing currencies", { userId: ctx.user.id });
78000
78090
  return ctx.services.currency.list();
78001
78091
  });
78002
78092
  getById = requireAuth(async (ctx) => {
@@ -78007,7 +78097,7 @@ var init_currency_controller = __esm(() => {
78007
78097
  if (!isValidUUID(currencyId)) {
78008
78098
  throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
78009
78099
  }
78010
- logger36.debug("Getting currency", { userId: ctx.user.id, currencyId });
78100
+ logger37.debug("Getting currency", { userId: ctx.user.id, currencyId });
78011
78101
  return ctx.services.currency.getById(currencyId);
78012
78102
  });
78013
78103
  create2 = requireAdmin(async (ctx) => {
@@ -78018,12 +78108,12 @@ var init_currency_controller = __esm(() => {
78018
78108
  } catch (error2) {
78019
78109
  if (error2 instanceof exports_external.ZodError) {
78020
78110
  const details = formatZodError(error2);
78021
- logger36.warn("Create currency validation failed", { details });
78111
+ logger37.warn("Create currency validation failed", { details });
78022
78112
  throw ApiError.unprocessableEntity("Validation failed", details);
78023
78113
  }
78024
78114
  throw ApiError.badRequest("Invalid JSON body");
78025
78115
  }
78026
- logger36.debug("Creating currency", {
78116
+ logger37.debug("Creating currency", {
78027
78117
  userId: ctx.user.id,
78028
78118
  symbol: body2.symbol,
78029
78119
  itemId: body2.itemId,
@@ -78046,12 +78136,12 @@ var init_currency_controller = __esm(() => {
78046
78136
  } catch (error2) {
78047
78137
  if (error2 instanceof exports_external.ZodError) {
78048
78138
  const details = formatZodError(error2);
78049
- logger36.warn("Update currency validation failed", { details });
78139
+ logger37.warn("Update currency validation failed", { details });
78050
78140
  throw ApiError.unprocessableEntity("Validation failed", details);
78051
78141
  }
78052
78142
  throw ApiError.badRequest("Invalid JSON body");
78053
78143
  }
78054
- logger36.debug("Updating currency", {
78144
+ logger37.debug("Updating currency", {
78055
78145
  userId: ctx.user.id,
78056
78146
  currencyId,
78057
78147
  symbol: body2.symbol,
@@ -78068,7 +78158,7 @@ var init_currency_controller = __esm(() => {
78068
78158
  if (!isValidUUID(currencyId)) {
78069
78159
  throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
78070
78160
  }
78071
- logger36.debug("Deleting currency", { userId: ctx.user.id, currencyId });
78161
+ logger37.debug("Deleting currency", { userId: ctx.user.id, currencyId });
78072
78162
  await ctx.services.currency.delete(currencyId);
78073
78163
  });
78074
78164
  currencyController = {
@@ -78081,14 +78171,14 @@ var init_currency_controller = __esm(() => {
78081
78171
  });
78082
78172
 
78083
78173
  // ../api-core/src/controllers/database.controller.ts
78084
- var logger37, reset;
78174
+ var logger38, reset;
78085
78175
  var init_database_controller = __esm(() => {
78086
78176
  init_esm();
78087
78177
  init_schemas_index();
78088
78178
  init_src2();
78089
78179
  init_errors();
78090
78180
  init_utils11();
78091
- logger37 = log.scope("DatabaseController");
78181
+ logger38 = log.scope("DatabaseController");
78092
78182
  reset = requireDeveloper(async (ctx) => {
78093
78183
  const slug2 = ctx.params.slug;
78094
78184
  if (!slug2) {
@@ -78101,11 +78191,11 @@ var init_database_controller = __esm(() => {
78101
78191
  } catch (error2) {
78102
78192
  if (error2 instanceof exports_external.ZodError) {
78103
78193
  const details = formatZodError(error2);
78104
- logger37.warn("Database reset validation failed", { details });
78194
+ logger38.warn("Database reset validation failed", { details });
78105
78195
  throw ApiError.unprocessableEntity("Validation failed", details);
78106
78196
  }
78107
78197
  }
78108
- logger37.debug("Resetting database", {
78198
+ logger38.debug("Resetting database", {
78109
78199
  userId: ctx.user.id,
78110
78200
  slug: slug2,
78111
78201
  hasSchema: !!body2.schema
@@ -87201,28 +87291,28 @@ var init_zip = __esm(() => {
87201
87291
  });
87202
87292
 
87203
87293
  // ../api-core/src/controllers/deploy.controller.ts
87204
- var logger38;
87294
+ var logger39;
87205
87295
  var init_deploy_controller = __esm(() => {
87206
87296
  init_schemas_index();
87207
87297
  init_src2();
87208
87298
  init_zip();
87209
87299
  init_errors();
87210
87300
  init_utils11();
87211
- logger38 = log.scope("DeployController");
87301
+ logger39 = log.scope("DeployController");
87212
87302
  });
87213
87303
 
87214
87304
  // ../api-core/src/controllers/developer.controller.ts
87215
- var logger39, apply, getStatus, developer;
87305
+ var logger40, apply, getStatus, developer;
87216
87306
  var init_developer_controller = __esm(() => {
87217
87307
  init_src2();
87218
87308
  init_utils11();
87219
- logger39 = log.scope("DeveloperController");
87309
+ logger40 = log.scope("DeveloperController");
87220
87310
  apply = requireAuth(async (ctx) => {
87221
- logger39.debug("Applying for developer status", { userId: ctx.user.id });
87311
+ logger40.debug("Applying for developer status", { userId: ctx.user.id });
87222
87312
  await ctx.services.developer.apply(ctx.user);
87223
87313
  });
87224
87314
  getStatus = requireAuth(async (ctx) => {
87225
- logger39.debug("Getting developer status", { userId: ctx.user.id });
87315
+ logger40.debug("Getting developer status", { userId: ctx.user.id });
87226
87316
  const status = await ctx.services.developer.getStatus(ctx.user.id);
87227
87317
  return { status };
87228
87318
  });
@@ -87233,7 +87323,7 @@ var init_developer_controller = __esm(() => {
87233
87323
  });
87234
87324
 
87235
87325
  // ../api-core/src/controllers/domain.controller.ts
87236
- var logger40, add, list2, getStatus2, remove2, domains2;
87326
+ var logger41, add, list2, getStatus2, remove2, domains2;
87237
87327
  var init_domain_controller = __esm(() => {
87238
87328
  init_esm();
87239
87329
  init_schemas_index();
@@ -87241,7 +87331,7 @@ var init_domain_controller = __esm(() => {
87241
87331
  init_config2();
87242
87332
  init_errors();
87243
87333
  init_utils11();
87244
- logger40 = log.scope("DomainController");
87334
+ logger41 = log.scope("DomainController");
87245
87335
  add = requireDeveloper(async (ctx) => {
87246
87336
  const slug2 = ctx.params.slug;
87247
87337
  if (!slug2) {
@@ -87254,12 +87344,12 @@ var init_domain_controller = __esm(() => {
87254
87344
  } catch (error2) {
87255
87345
  if (error2 instanceof exports_external.ZodError) {
87256
87346
  const details = formatZodError(error2);
87257
- logger40.warn("Add domain validation failed", { details });
87347
+ logger41.warn("Add domain validation failed", { details });
87258
87348
  throw ApiError.unprocessableEntity("Validation failed", details);
87259
87349
  }
87260
87350
  throw ApiError.badRequest("Invalid JSON body");
87261
87351
  }
87262
- logger40.debug("Adding domain", { userId: ctx.user.id, slug: slug2, hostname: body2.hostname });
87352
+ logger41.debug("Adding domain", { userId: ctx.user.id, slug: slug2, hostname: body2.hostname });
87263
87353
  return ctx.services.domain.add(slug2, body2.hostname, body2.environment, ctx.user);
87264
87354
  });
87265
87355
  list2 = requireDeveloper(async (ctx) => {
@@ -87268,7 +87358,7 @@ var init_domain_controller = __esm(() => {
87268
87358
  throw ApiError.badRequest("Missing game slug");
87269
87359
  }
87270
87360
  const environment = getPlatformEnvironment(ctx.config);
87271
- logger40.debug("Listing domains", { userId: ctx.user.id, slug: slug2, environment });
87361
+ logger41.debug("Listing domains", { userId: ctx.user.id, slug: slug2, environment });
87272
87362
  const domains2 = await ctx.services.domain.list(slug2, environment, ctx.user);
87273
87363
  return { domains: domains2 };
87274
87364
  });
@@ -87283,7 +87373,7 @@ var init_domain_controller = __esm(() => {
87283
87373
  }
87284
87374
  const refresh = ctx.url.searchParams.get("refresh") === "true";
87285
87375
  const environment = getPlatformEnvironment(ctx.config);
87286
- logger40.debug("Getting domain status", { userId: ctx.user.id, slug: slug2, hostname, refresh });
87376
+ logger41.debug("Getting domain status", { userId: ctx.user.id, slug: slug2, hostname, refresh });
87287
87377
  return ctx.services.domain.getStatus(slug2, hostname, environment, ctx.user, refresh);
87288
87378
  });
87289
87379
  remove2 = requireDeveloper(async (ctx) => {
@@ -87296,7 +87386,7 @@ var init_domain_controller = __esm(() => {
87296
87386
  throw ApiError.badRequest("Missing hostname");
87297
87387
  }
87298
87388
  const environment = ctx.config.stage === "production" ? "production" : "staging";
87299
- logger40.debug("Removing domain", { userId: ctx.user.id, slug: slug2, hostname, environment });
87389
+ logger41.debug("Removing domain", { userId: ctx.user.id, slug: slug2, hostname, environment });
87300
87390
  await ctx.services.domain.delete(slug2, hostname, environment, ctx.user);
87301
87391
  });
87302
87392
  domains2 = {
@@ -87308,7 +87398,7 @@ var init_domain_controller = __esm(() => {
87308
87398
  });
87309
87399
 
87310
87400
  // ../api-core/src/controllers/game.controller.ts
87311
- var logger41, list3, getById2, getBySlug, upsertBySlug, remove3, games2;
87401
+ var logger42, list3, getById2, getBySlug, upsertBySlug, remove3, games2;
87312
87402
  var init_game_controller = __esm(() => {
87313
87403
  init_esm();
87314
87404
  init_schemas_index();
@@ -87316,9 +87406,9 @@ var init_game_controller = __esm(() => {
87316
87406
  init_src4();
87317
87407
  init_errors();
87318
87408
  init_utils11();
87319
- logger41 = log.scope("GameController");
87409
+ logger42 = log.scope("GameController");
87320
87410
  list3 = requireAuth(async (ctx) => {
87321
- logger41.debug("Listing games", { userId: ctx.user.id });
87411
+ logger42.debug("Listing games", { userId: ctx.user.id });
87322
87412
  return ctx.services.game.list();
87323
87413
  });
87324
87414
  getById2 = requireAuth(async (ctx) => {
@@ -87329,7 +87419,7 @@ var init_game_controller = __esm(() => {
87329
87419
  if (!isValidUUID(gameId)) {
87330
87420
  throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
87331
87421
  }
87332
- logger41.debug("Getting game by ID", { userId: ctx.user.id, gameId });
87422
+ logger42.debug("Getting game by ID", { userId: ctx.user.id, gameId });
87333
87423
  return ctx.services.game.getById(gameId);
87334
87424
  });
87335
87425
  getBySlug = requireAuth(async (ctx) => {
@@ -87337,7 +87427,7 @@ var init_game_controller = __esm(() => {
87337
87427
  if (!slug2) {
87338
87428
  throw ApiError.badRequest("Missing game slug");
87339
87429
  }
87340
- logger41.debug("Getting game by slug", { userId: ctx.user.id, slug: slug2 });
87430
+ logger42.debug("Getting game by slug", { userId: ctx.user.id, slug: slug2 });
87341
87431
  return ctx.services.game.getBySlug(slug2);
87342
87432
  });
87343
87433
  upsertBySlug = requireAuth(async (ctx) => {
@@ -87352,12 +87442,12 @@ var init_game_controller = __esm(() => {
87352
87442
  } catch (error2) {
87353
87443
  if (error2 instanceof exports_external.ZodError) {
87354
87444
  const details = formatZodError(error2);
87355
- logger41.warn("Upsert game validation failed", { details });
87445
+ logger42.warn("Upsert game validation failed", { details });
87356
87446
  throw ApiError.unprocessableEntity("Validation failed", details);
87357
87447
  }
87358
87448
  throw ApiError.badRequest("Invalid JSON body");
87359
87449
  }
87360
- logger41.debug("Upserting game", { userId: ctx.user.id, slug: slug2, displayName: body2.displayName });
87450
+ logger42.debug("Upserting game", { userId: ctx.user.id, slug: slug2, displayName: body2.displayName });
87361
87451
  return ctx.services.game.upsertBySlug(slug2, body2, ctx.user);
87362
87452
  });
87363
87453
  remove3 = requireAuth(async (ctx) => {
@@ -87368,7 +87458,7 @@ var init_game_controller = __esm(() => {
87368
87458
  if (!isValidUUID(gameId)) {
87369
87459
  throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
87370
87460
  }
87371
- logger41.debug("Deleting game", { userId: ctx.user.id, gameId });
87461
+ logger42.debug("Deleting game", { userId: ctx.user.id, gameId });
87372
87462
  await ctx.services.game.delete(gameId, ctx.user);
87373
87463
  });
87374
87464
  games2 = {
@@ -87381,16 +87471,16 @@ var init_game_controller = __esm(() => {
87381
87471
  });
87382
87472
 
87383
87473
  // ../api-core/src/controllers/inventory.controller.ts
87384
- var logger42, list4, addItem, removeItem, inventory;
87474
+ var logger43, list4, addItem, removeItem, inventory;
87385
87475
  var init_inventory_controller = __esm(() => {
87386
87476
  init_esm();
87387
87477
  init_schemas_index();
87388
87478
  init_src2();
87389
87479
  init_errors();
87390
87480
  init_utils11();
87391
- logger42 = log.scope("InventoryController");
87481
+ logger43 = log.scope("InventoryController");
87392
87482
  list4 = requireAuth(async (ctx) => {
87393
- logger42.debug("Listing inventory", { userId: ctx.user.id });
87483
+ logger43.debug("Listing inventory", { userId: ctx.user.id });
87394
87484
  return ctx.services.inventory.list(ctx.user);
87395
87485
  });
87396
87486
  addItem = requireAuth(async (ctx) => {
@@ -87401,12 +87491,12 @@ var init_inventory_controller = __esm(() => {
87401
87491
  } catch (error2) {
87402
87492
  if (error2 instanceof exports_external.ZodError) {
87403
87493
  const details = formatZodError(error2);
87404
- logger42.warn("Add inventory item validation failed", { details });
87494
+ logger43.warn("Add inventory item validation failed", { details });
87405
87495
  throw ApiError.unprocessableEntity("Invalid request body", details);
87406
87496
  }
87407
87497
  throw ApiError.badRequest("Invalid JSON body");
87408
87498
  }
87409
- logger42.debug("Adding item", {
87499
+ logger43.debug("Adding item", {
87410
87500
  userId: ctx.user.id,
87411
87501
  itemId: body2.itemId,
87412
87502
  qty: body2.qty
@@ -87421,12 +87511,12 @@ var init_inventory_controller = __esm(() => {
87421
87511
  } catch (error2) {
87422
87512
  if (error2 instanceof exports_external.ZodError) {
87423
87513
  const details = formatZodError(error2);
87424
- logger42.warn("Remove inventory item validation failed", { details });
87514
+ logger43.warn("Remove inventory item validation failed", { details });
87425
87515
  throw ApiError.unprocessableEntity("Invalid request body", details);
87426
87516
  }
87427
87517
  throw ApiError.badRequest("Invalid JSON body");
87428
87518
  }
87429
- logger42.debug("Removing item", {
87519
+ logger43.debug("Removing item", {
87430
87520
  userId: ctx.user.id,
87431
87521
  itemId: body2.itemId,
87432
87522
  qty: body2.qty
@@ -87441,7 +87531,7 @@ var init_inventory_controller = __esm(() => {
87441
87531
  });
87442
87532
 
87443
87533
  // ../api-core/src/controllers/item.controller.ts
87444
- var logger43, list5, getById3, resolve2, create3, update4, remove4, listByGame, createForGame, updateForGame, deleteForGame, items2;
87534
+ var logger44, list5, getById3, resolve2, create3, update4, remove4, listByGame, createForGame, updateForGame, deleteForGame, items2;
87445
87535
  var init_item_controller = __esm(() => {
87446
87536
  init_esm();
87447
87537
  init_schemas_index();
@@ -87449,10 +87539,10 @@ var init_item_controller = __esm(() => {
87449
87539
  init_src4();
87450
87540
  init_errors();
87451
87541
  init_utils11();
87452
- logger43 = log.scope("ItemController");
87542
+ logger44 = log.scope("ItemController");
87453
87543
  list5 = requireAuth(async (ctx) => {
87454
87544
  const gameId = ctx.url.searchParams.get("gameId") || undefined;
87455
- logger43.debug("Listing items", { userId: ctx.user.id, gameId });
87545
+ logger44.debug("Listing items", { userId: ctx.user.id, gameId });
87456
87546
  return ctx.services.item.list(gameId);
87457
87547
  });
87458
87548
  getById3 = requireAuth(async (ctx) => {
@@ -87463,7 +87553,7 @@ var init_item_controller = __esm(() => {
87463
87553
  if (!isValidUUID(itemId)) {
87464
87554
  throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
87465
87555
  }
87466
- logger43.debug("Getting item", { userId: ctx.user.id, itemId });
87556
+ logger44.debug("Getting item", { userId: ctx.user.id, itemId });
87467
87557
  return ctx.services.item.getById(itemId);
87468
87558
  });
87469
87559
  resolve2 = requireAuth(async (ctx) => {
@@ -87475,7 +87565,7 @@ var init_item_controller = __esm(() => {
87475
87565
  if (gameId && !isValidUUID(gameId)) {
87476
87566
  throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
87477
87567
  }
87478
- logger43.debug("Resolving item", { userId: ctx.user.id, slug: slug2, gameId });
87568
+ logger44.debug("Resolving item", { userId: ctx.user.id, slug: slug2, gameId });
87479
87569
  return ctx.services.item.resolveBySlug(slug2, gameId);
87480
87570
  });
87481
87571
  create3 = requireRole(["admin"], async (ctx) => {
@@ -87486,12 +87576,12 @@ var init_item_controller = __esm(() => {
87486
87576
  } catch (error2) {
87487
87577
  if (error2 instanceof exports_external.ZodError) {
87488
87578
  const details = formatZodError(error2);
87489
- logger43.warn("Create item validation failed", { details });
87579
+ logger44.warn("Create item validation failed", { details });
87490
87580
  throw ApiError.unprocessableEntity("Validation failed", details);
87491
87581
  }
87492
87582
  throw ApiError.badRequest("Invalid JSON body");
87493
87583
  }
87494
- logger43.debug("Creating item", {
87584
+ logger44.debug("Creating item", {
87495
87585
  userId: ctx.user.id,
87496
87586
  slug: body2.slug,
87497
87587
  displayName: body2.displayName
@@ -87513,7 +87603,7 @@ var init_item_controller = __esm(() => {
87513
87603
  } catch (error2) {
87514
87604
  if (error2 instanceof exports_external.ZodError) {
87515
87605
  const details = formatZodError(error2);
87516
- logger43.warn("Update item validation failed", { details });
87606
+ logger44.warn("Update item validation failed", { details });
87517
87607
  throw ApiError.unprocessableEntity("Validation failed", details);
87518
87608
  }
87519
87609
  throw ApiError.badRequest("Invalid JSON body");
@@ -87521,7 +87611,7 @@ var init_item_controller = __esm(() => {
87521
87611
  if (Object.keys(body2).length === 0) {
87522
87612
  throw ApiError.badRequest("No update data provided");
87523
87613
  }
87524
- logger43.debug("Updating item", {
87614
+ logger44.debug("Updating item", {
87525
87615
  userId: ctx.user.id,
87526
87616
  itemId,
87527
87617
  slug: body2.slug,
@@ -87538,7 +87628,7 @@ var init_item_controller = __esm(() => {
87538
87628
  if (!isValidUUID(itemId)) {
87539
87629
  throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
87540
87630
  }
87541
- logger43.debug("Deleting item", { userId: ctx.user.id, itemId });
87631
+ logger44.debug("Deleting item", { userId: ctx.user.id, itemId });
87542
87632
  await ctx.services.item.delete(itemId);
87543
87633
  });
87544
87634
  listByGame = requireAuth(async (ctx) => {
@@ -87549,7 +87639,7 @@ var init_item_controller = __esm(() => {
87549
87639
  if (!isValidUUID(gameId)) {
87550
87640
  throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
87551
87641
  }
87552
- logger43.debug("Listing game items", { userId: ctx.user.id, gameId });
87642
+ logger44.debug("Listing game items", { userId: ctx.user.id, gameId });
87553
87643
  return ctx.services.item.listByGame(gameId);
87554
87644
  });
87555
87645
  createForGame = requireAuth(async (ctx) => {
@@ -87567,12 +87657,12 @@ var init_item_controller = __esm(() => {
87567
87657
  } catch (error2) {
87568
87658
  if (error2 instanceof exports_external.ZodError) {
87569
87659
  const details = formatZodError(error2);
87570
- logger43.warn("Create game item validation failed", { details });
87660
+ logger44.warn("Create game item validation failed", { details });
87571
87661
  throw ApiError.unprocessableEntity("Validation failed", details);
87572
87662
  }
87573
87663
  throw ApiError.badRequest("Invalid JSON body");
87574
87664
  }
87575
- logger43.debug("Creating game item", {
87665
+ logger44.debug("Creating game item", {
87576
87666
  userId: ctx.user.id,
87577
87667
  gameId,
87578
87668
  slug: body2.slug,
@@ -87599,7 +87689,7 @@ var init_item_controller = __esm(() => {
87599
87689
  } catch (error2) {
87600
87690
  if (error2 instanceof exports_external.ZodError) {
87601
87691
  const details = formatZodError(error2);
87602
- logger43.warn("Update game item validation failed", { details });
87692
+ logger44.warn("Update game item validation failed", { details });
87603
87693
  throw ApiError.unprocessableEntity("Validation failed", details);
87604
87694
  }
87605
87695
  throw ApiError.badRequest("Invalid JSON body");
@@ -87607,7 +87697,7 @@ var init_item_controller = __esm(() => {
87607
87697
  if (Object.keys(body2).length === 0) {
87608
87698
  throw ApiError.badRequest("No update data provided");
87609
87699
  }
87610
- logger43.debug("Updating game item", {
87700
+ logger44.debug("Updating game item", {
87611
87701
  userId: ctx.user.id,
87612
87702
  gameId,
87613
87703
  itemId,
@@ -87629,7 +87719,7 @@ var init_item_controller = __esm(() => {
87629
87719
  if (!isValidUUID(itemId)) {
87630
87720
  throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
87631
87721
  }
87632
- logger43.debug("Deleting game item", { userId: ctx.user.id, gameId, itemId });
87722
+ logger44.debug("Deleting game item", { userId: ctx.user.id, gameId, itemId });
87633
87723
  await ctx.services.item.deleteForGame(gameId, itemId, ctx.user);
87634
87724
  });
87635
87725
  items2 = {
@@ -87647,7 +87737,7 @@ var init_item_controller = __esm(() => {
87647
87737
  });
87648
87738
 
87649
87739
  // ../api-core/src/controllers/leaderboard.controller.ts
87650
- var logger44, submitScore, getGlobalLeaderboard, getLeaderboard, getUserRank, getUserAllScores, getUserScores, leaderboard;
87740
+ var logger45, submitScore, getGlobalLeaderboard, getLeaderboard, getUserRank, getUserAllScores, getUserScores, leaderboard;
87651
87741
  var init_leaderboard_controller = __esm(() => {
87652
87742
  init_esm();
87653
87743
  init_schemas_index();
@@ -87655,7 +87745,7 @@ var init_leaderboard_controller = __esm(() => {
87655
87745
  init_src4();
87656
87746
  init_errors();
87657
87747
  init_utils11();
87658
- logger44 = log.scope("LeaderboardController");
87748
+ logger45 = log.scope("LeaderboardController");
87659
87749
  submitScore = requireAuth(async (ctx) => {
87660
87750
  const gameId = ctx.params.gameId;
87661
87751
  if (!gameId) {
@@ -87668,12 +87758,12 @@ var init_leaderboard_controller = __esm(() => {
87668
87758
  } catch (error2) {
87669
87759
  if (error2 instanceof exports_external.ZodError) {
87670
87760
  const details = formatZodError(error2);
87671
- logger44.warn("Submit score validation failed", { details });
87761
+ logger45.warn("Submit score validation failed", { details });
87672
87762
  throw ApiError.unprocessableEntity("Validation failed", details);
87673
87763
  }
87674
87764
  throw ApiError.badRequest("Invalid JSON body");
87675
87765
  }
87676
- logger44.debug("Submitting score", {
87766
+ logger45.debug("Submitting score", {
87677
87767
  userId: ctx.user.id,
87678
87768
  gameId,
87679
87769
  score: body2.score
@@ -87696,12 +87786,12 @@ var init_leaderboard_controller = __esm(() => {
87696
87786
  } catch (error2) {
87697
87787
  if (error2 instanceof exports_external.ZodError) {
87698
87788
  const details = formatZodError(error2);
87699
- logger44.warn("Get global leaderboard query validation failed", { details });
87789
+ logger45.warn("Get global leaderboard query validation failed", { details });
87700
87790
  throw ApiError.badRequest("Invalid query parameters", details);
87701
87791
  }
87702
87792
  throw ApiError.badRequest("Invalid query parameters");
87703
87793
  }
87704
- logger44.debug("Getting global leaderboard", {
87794
+ logger45.debug("Getting global leaderboard", {
87705
87795
  userId: ctx.user.id,
87706
87796
  gameId,
87707
87797
  ...query
@@ -87724,12 +87814,12 @@ var init_leaderboard_controller = __esm(() => {
87724
87814
  } catch (error2) {
87725
87815
  if (error2 instanceof exports_external.ZodError) {
87726
87816
  const details = formatZodError(error2);
87727
- logger44.warn("Get leaderboard query validation failed", { details });
87817
+ logger45.warn("Get leaderboard query validation failed", { details });
87728
87818
  throw ApiError.badRequest("Invalid query parameters", details);
87729
87819
  }
87730
87820
  throw ApiError.badRequest("Invalid query parameters");
87731
87821
  }
87732
- logger44.debug("Getting leaderboard", {
87822
+ logger45.debug("Getting leaderboard", {
87733
87823
  userId: ctx.user.id,
87734
87824
  gameId,
87735
87825
  ...query
@@ -87744,7 +87834,7 @@ var init_leaderboard_controller = __esm(() => {
87744
87834
  if (!isValidUUID(userId)) {
87745
87835
  throw ApiError.unprocessableEntity("userId must be a valid UUID format");
87746
87836
  }
87747
- logger44.debug("Getting user rank", {
87837
+ logger45.debug("Getting user rank", {
87748
87838
  requesterId: ctx.user.id,
87749
87839
  gameId,
87750
87840
  targetUserId: userId
@@ -87762,7 +87852,7 @@ var init_leaderboard_controller = __esm(() => {
87762
87852
  const url = ctx.url;
87763
87853
  const limit = Math.min(Number(url.searchParams.get("limit") || "50"), 100);
87764
87854
  const gameId = url.searchParams.get("gameId") || undefined;
87765
- logger44.debug("Getting user all scores", {
87855
+ logger45.debug("Getting user all scores", {
87766
87856
  requesterId: ctx.user.id,
87767
87857
  targetUserId: userId,
87768
87858
  gameId,
@@ -87780,7 +87870,7 @@ var init_leaderboard_controller = __esm(() => {
87780
87870
  }
87781
87871
  const url = ctx.url;
87782
87872
  const limit = Math.min(Number(url.searchParams.get("limit") || "10"), 100);
87783
- logger44.debug("Getting user scores", {
87873
+ logger45.debug("Getting user scores", {
87784
87874
  requesterId: ctx.user.id,
87785
87875
  gameId,
87786
87876
  targetUserId: userId,
@@ -87800,7 +87890,7 @@ var init_leaderboard_controller = __esm(() => {
87800
87890
 
87801
87891
  // ../api-core/src/controllers/level.controller.ts
87802
87892
  async function listConfigs(ctx) {
87803
- logger45.debug("Listing level configs");
87893
+ logger46.debug("Listing level configs");
87804
87894
  return ctx.services.level.listConfigs();
87805
87895
  }
87806
87896
  async function getConfig(ctx) {
@@ -87812,21 +87902,21 @@ async function getConfig(ctx) {
87812
87902
  if (isNaN(level) || level < 1) {
87813
87903
  throw ApiError.badRequest("Level must be a positive integer");
87814
87904
  }
87815
- logger45.debug("Getting level config", { level });
87905
+ logger46.debug("Getting level config", { level });
87816
87906
  return ctx.services.level.getConfig(level);
87817
87907
  }
87818
- var logger45, getByUser, getProgress, levels;
87908
+ var logger46, getByUser, getProgress, levels;
87819
87909
  var init_level_controller = __esm(() => {
87820
87910
  init_src2();
87821
87911
  init_errors();
87822
87912
  init_utils11();
87823
- logger45 = log.scope("LevelController");
87913
+ logger46 = log.scope("LevelController");
87824
87914
  getByUser = requireAuth(async (ctx) => {
87825
- logger45.debug("Getting user level", { userId: ctx.user.id });
87915
+ logger46.debug("Getting user level", { userId: ctx.user.id });
87826
87916
  return ctx.services.level.getByUser(ctx.user);
87827
87917
  });
87828
87918
  getProgress = requireAuth(async (ctx) => {
87829
- logger45.debug("Getting level progress", { userId: ctx.user.id });
87919
+ logger46.debug("Getting level progress", { userId: ctx.user.id });
87830
87920
  return ctx.services.level.getProgress(ctx.user);
87831
87921
  });
87832
87922
  levels = {
@@ -87837,6 +87927,42 @@ var init_level_controller = __esm(() => {
87837
87927
  };
87838
87928
  });
87839
87929
 
87930
+ // ../api-core/src/controllers/logs.controller.ts
87931
+ var logger47, generateToken, logs;
87932
+ var init_logs_controller = __esm(() => {
87933
+ init_src2();
87934
+ init_errors();
87935
+ init_utils11();
87936
+ logger47 = log.scope("LogsController");
87937
+ generateToken = requireDeveloper(async (ctx) => {
87938
+ const slug2 = ctx.params.slug;
87939
+ if (!slug2) {
87940
+ throw ApiError.badRequest("Missing game slug");
87941
+ }
87942
+ let body2;
87943
+ try {
87944
+ const json4 = await ctx.request.json();
87945
+ if (json4.environment !== "staging" && json4.environment !== "production") {
87946
+ throw ApiError.badRequest('Invalid environment. Must be "staging" or "production".');
87947
+ }
87948
+ body2 = json4;
87949
+ } catch (error2) {
87950
+ if (error2 instanceof ApiError)
87951
+ throw error2;
87952
+ throw ApiError.badRequest("Invalid JSON body");
87953
+ }
87954
+ logger47.debug("Generating log stream token", {
87955
+ userId: ctx.user.id,
87956
+ slug: slug2,
87957
+ environment: body2.environment
87958
+ });
87959
+ return ctx.services.logs.generateToken(ctx.user, slug2, body2.environment);
87960
+ });
87961
+ logs = {
87962
+ generateToken
87963
+ };
87964
+ });
87965
+
87840
87966
  // ../api-core/src/controllers/lti.controller.ts
87841
87967
  async function launch(ctx) {
87842
87968
  const formData = await ctx.request.formData();
@@ -87845,17 +87971,17 @@ async function launch(ctx) {
87845
87971
  throw ApiError.badRequest("Missing or invalid id_token");
87846
87972
  }
87847
87973
  const currentHost = ctx.url.hostname;
87848
- logger46.debug("Processing launch", { host: currentHost });
87974
+ logger48.debug("Processing launch", { host: currentHost });
87849
87975
  return ctx.services.lti.processLaunch(idToken, currentHost);
87850
87976
  }
87851
- var logger46, getStatus3, lti;
87977
+ var logger48, getStatus3, lti;
87852
87978
  var init_lti_controller = __esm(() => {
87853
87979
  init_src2();
87854
87980
  init_errors();
87855
87981
  init_utils11();
87856
- logger46 = log.scope("LtiController");
87982
+ logger48 = log.scope("LtiController");
87857
87983
  getStatus3 = requireAuth(async (ctx) => {
87858
- logger46.debug("Getting status", { userId: ctx.user.id });
87984
+ logger48.debug("Getting status", { userId: ctx.user.id });
87859
87985
  return ctx.services.lti.getStatus(ctx.user);
87860
87986
  });
87861
87987
  lti = {
@@ -87865,7 +87991,7 @@ var init_lti_controller = __esm(() => {
87865
87991
  });
87866
87992
 
87867
87993
  // ../api-core/src/controllers/map.controller.ts
87868
- var logger47, getByIdentifier, getElements, getObjects, createObject, deleteObject, maps2;
87994
+ var logger49, getByIdentifier, getElements, getObjects, createObject, deleteObject, maps2;
87869
87995
  var init_map_controller = __esm(() => {
87870
87996
  init_esm();
87871
87997
  init_schemas_index();
@@ -87873,13 +87999,13 @@ var init_map_controller = __esm(() => {
87873
87999
  init_src4();
87874
88000
  init_errors();
87875
88001
  init_utils11();
87876
- logger47 = log.scope("MapController");
88002
+ logger49 = log.scope("MapController");
87877
88003
  getByIdentifier = requireAuth(async (ctx) => {
87878
88004
  const identifier = ctx.params.identifier;
87879
88005
  if (!identifier) {
87880
88006
  throw ApiError.badRequest("Missing map identifier");
87881
88007
  }
87882
- logger47.debug("Getting map", { userId: ctx.user.id, identifier });
88008
+ logger49.debug("Getting map", { userId: ctx.user.id, identifier });
87883
88009
  return ctx.services.map.getByIdentifier(identifier);
87884
88010
  });
87885
88011
  getElements = requireAuth(async (ctx) => {
@@ -87890,7 +88016,7 @@ var init_map_controller = __esm(() => {
87890
88016
  if (!isValidUUID(mapId)) {
87891
88017
  throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
87892
88018
  }
87893
- logger47.debug("Getting map elements", { userId: ctx.user.id, mapId });
88019
+ logger49.debug("Getting map elements", { userId: ctx.user.id, mapId });
87894
88020
  return ctx.services.map.getElements(mapId);
87895
88021
  });
87896
88022
  getObjects = requireAuth(async (ctx) => {
@@ -87901,7 +88027,7 @@ var init_map_controller = __esm(() => {
87901
88027
  if (!isValidUUID(mapId)) {
87902
88028
  throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
87903
88029
  }
87904
- logger47.debug("Getting map objects", { userId: ctx.user.id, mapId });
88030
+ logger49.debug("Getting map objects", { userId: ctx.user.id, mapId });
87905
88031
  return ctx.services.map.getObjects(mapId, ctx.user.id);
87906
88032
  });
87907
88033
  createObject = requireAuth(async (ctx) => {
@@ -87923,12 +88049,12 @@ var init_map_controller = __esm(() => {
87923
88049
  } catch (error2) {
87924
88050
  if (error2 instanceof exports_external.ZodError) {
87925
88051
  const details = formatZodError(error2);
87926
- logger47.warn("Create map object validation failed", { details });
88052
+ logger49.warn("Create map object validation failed", { details });
87927
88053
  throw ApiError.unprocessableEntity("Validation failed", details);
87928
88054
  }
87929
88055
  throw ApiError.badRequest("Invalid JSON body");
87930
88056
  }
87931
- logger47.debug("Creating map object", {
88057
+ logger49.debug("Creating map object", {
87932
88058
  userId: ctx.user.id,
87933
88059
  mapId,
87934
88060
  itemId: body2.itemId,
@@ -87952,7 +88078,7 @@ var init_map_controller = __esm(() => {
87952
88078
  if (!isValidUUID(objectId)) {
87953
88079
  throw ApiError.unprocessableEntity("objectId must be a valid UUID format");
87954
88080
  }
87955
- logger47.debug("Deleting map object", { userId: ctx.user.id, mapId, objectId });
88081
+ logger49.debug("Deleting map object", { userId: ctx.user.id, mapId, objectId });
87956
88082
  await ctx.services.map.deleteObject(mapId, objectId, ctx.user);
87957
88083
  });
87958
88084
  maps2 = {
@@ -87965,14 +88091,14 @@ var init_map_controller = __esm(() => {
87965
88091
  });
87966
88092
 
87967
88093
  // ../api-core/src/controllers/notification.controller.ts
87968
- var logger48, list6, updateStatus, getStats, create4, deliver, notifications2;
88094
+ var logger50, list6, updateStatus, getStats, create4, deliver, notifications2;
87969
88095
  var init_notification_controller = __esm(() => {
87970
88096
  init_esm();
87971
88097
  init_schemas_index();
87972
88098
  init_src2();
87973
88099
  init_errors();
87974
88100
  init_utils11();
87975
- logger48 = log.scope("NotificationController");
88101
+ logger50 = log.scope("NotificationController");
87976
88102
  list6 = requireAuth(async (ctx) => {
87977
88103
  const query = {
87978
88104
  status: ctx.url.searchParams.get("status") || undefined,
@@ -87983,10 +88109,10 @@ var init_notification_controller = __esm(() => {
87983
88109
  const result = NotificationListQuerySchema.omit({ userId: true }).safeParse(query);
87984
88110
  if (!result.success) {
87985
88111
  const details = formatZodError(result.error);
87986
- logger48.warn("List notifications query validation failed", { details });
88112
+ logger50.warn("List notifications query validation failed", { details });
87987
88113
  throw ApiError.badRequest("Invalid query parameters", details);
87988
88114
  }
87989
- logger48.debug("Listing notifications", { userId: ctx.user.id, ...result.data });
88115
+ logger50.debug("Listing notifications", { userId: ctx.user.id, ...result.data });
87990
88116
  return ctx.services.notification.list(ctx.user, result.data);
87991
88117
  });
87992
88118
  updateStatus = requireAuth(async (ctx) => {
@@ -88001,12 +88127,12 @@ var init_notification_controller = __esm(() => {
88001
88127
  } catch (error2) {
88002
88128
  if (error2 instanceof exports_external.ZodError) {
88003
88129
  const details = formatZodError(error2);
88004
- logger48.warn("Update notification status validation failed", { details });
88130
+ logger50.warn("Update notification status validation failed", { details });
88005
88131
  throw ApiError.unprocessableEntity("Invalid request body", details);
88006
88132
  }
88007
88133
  throw ApiError.badRequest("Invalid JSON body");
88008
88134
  }
88009
- logger48.debug("Updating status", {
88135
+ logger50.debug("Updating status", {
88010
88136
  userId: ctx.user.id,
88011
88137
  notificationId,
88012
88138
  status: body2.status
@@ -88016,7 +88142,7 @@ var init_notification_controller = __esm(() => {
88016
88142
  getStats = requireAuth(async (ctx) => {
88017
88143
  const startDate = ctx.url.searchParams.get("startDate");
88018
88144
  const endDate = ctx.url.searchParams.get("endDate");
88019
- logger48.debug("Getting stats", { userId: ctx.user.id, startDate, endDate });
88145
+ logger50.debug("Getting stats", { userId: ctx.user.id, startDate, endDate });
88020
88146
  return ctx.services.notification.getStats(ctx.user, {
88021
88147
  startDate: startDate ? new Date(startDate) : undefined,
88022
88148
  endDate: endDate ? new Date(endDate) : undefined
@@ -88030,12 +88156,12 @@ var init_notification_controller = __esm(() => {
88030
88156
  } catch (error2) {
88031
88157
  if (error2 instanceof exports_external.ZodError) {
88032
88158
  const details = formatZodError(error2);
88033
- logger48.warn("Create notification validation failed", { details });
88159
+ logger50.warn("Create notification validation failed", { details });
88034
88160
  throw ApiError.unprocessableEntity("Invalid request body", details);
88035
88161
  }
88036
88162
  throw ApiError.badRequest("Invalid JSON body");
88037
88163
  }
88038
- logger48.debug("Creating notification", {
88164
+ logger50.debug("Creating notification", {
88039
88165
  userId: ctx.user.id,
88040
88166
  targetUserId: body2.userId,
88041
88167
  type: body2.type
@@ -88053,12 +88179,12 @@ var init_notification_controller = __esm(() => {
88053
88179
  });
88054
88180
  });
88055
88181
  deliver = requireAuth(async (ctx) => {
88056
- logger48.debug("Delivering notifications", { userId: ctx.user.id });
88182
+ logger50.debug("Delivering notifications", { userId: ctx.user.id });
88057
88183
  try {
88058
88184
  await ctx.services.notification.deliverPending(ctx.user.id);
88059
88185
  return { success: true };
88060
88186
  } catch (error2) {
88061
- logger48.error("Failed to deliver notifications", { error: error2 });
88187
+ logger50.error("Failed to deliver notifications", { error: error2 });
88062
88188
  throw ApiError.internal("Failed to deliver notifications");
88063
88189
  }
88064
88190
  });
@@ -88072,39 +88198,39 @@ var init_notification_controller = __esm(() => {
88072
88198
  });
88073
88199
 
88074
88200
  // ../api-core/src/controllers/realtime.controller.ts
88075
- var logger49, generateToken, realtime;
88201
+ var logger51, generateToken2, realtime;
88076
88202
  var init_realtime_controller = __esm(() => {
88077
88203
  init_src2();
88078
88204
  init_utils11();
88079
- logger49 = log.scope("RealtimeController");
88080
- generateToken = requireAuth(async (ctx) => {
88205
+ logger51 = log.scope("RealtimeController");
88206
+ generateToken2 = requireAuth(async (ctx) => {
88081
88207
  const gameIdOrSlug = ctx.params.gameId;
88082
- logger49.debug("Generating token", {
88208
+ logger51.debug("Generating token", {
88083
88209
  userId: ctx.user.id,
88084
88210
  gameId: gameIdOrSlug || "global"
88085
88211
  });
88086
88212
  return ctx.services.realtime.generateToken(ctx.user, gameIdOrSlug);
88087
88213
  });
88088
88214
  realtime = {
88089
- generateToken
88215
+ generateToken: generateToken2
88090
88216
  };
88091
88217
  });
88092
88218
 
88093
88219
  // ../api-core/src/controllers/secrets.controller.ts
88094
- var logger50, listKeys, getValues, setSecrets, deleteSecret, secrets;
88220
+ var logger52, listKeys, getValues, setSecrets, deleteSecret, secrets;
88095
88221
  var init_secrets_controller = __esm(() => {
88096
88222
  init_esm();
88097
88223
  init_schemas_index();
88098
88224
  init_src2();
88099
88225
  init_errors();
88100
88226
  init_utils11();
88101
- logger50 = log.scope("SecretsController");
88227
+ logger52 = log.scope("SecretsController");
88102
88228
  listKeys = requireDeveloper(async (ctx) => {
88103
88229
  const slug2 = ctx.params.slug;
88104
88230
  if (!slug2) {
88105
88231
  throw ApiError.badRequest("Missing game slug");
88106
88232
  }
88107
- logger50.debug("Listing secret keys", { userId: ctx.user.id, slug: slug2 });
88233
+ logger52.debug("Listing secret keys", { userId: ctx.user.id, slug: slug2 });
88108
88234
  const keys = await ctx.services.secrets.listKeys(slug2, ctx.user);
88109
88235
  return { keys };
88110
88236
  });
@@ -88113,7 +88239,7 @@ var init_secrets_controller = __esm(() => {
88113
88239
  if (!slug2) {
88114
88240
  throw ApiError.badRequest("Missing game slug");
88115
88241
  }
88116
- logger50.debug("Getting secret values", { userId: ctx.user.id, slug: slug2 });
88242
+ logger52.debug("Getting secret values", { userId: ctx.user.id, slug: slug2 });
88117
88243
  const secrets = await ctx.services.secrets.getValues(slug2, ctx.user);
88118
88244
  return { secrets };
88119
88245
  });
@@ -88129,12 +88255,12 @@ var init_secrets_controller = __esm(() => {
88129
88255
  } catch (error2) {
88130
88256
  if (error2 instanceof exports_external.ZodError) {
88131
88257
  const details = formatZodError(error2);
88132
- logger50.warn("Set secrets validation failed", { details });
88258
+ logger52.warn("Set secrets validation failed", { details });
88133
88259
  throw ApiError.unprocessableEntity("Validation failed", details);
88134
88260
  }
88135
88261
  throw ApiError.badRequest("Invalid JSON body");
88136
88262
  }
88137
- logger50.debug("Setting secrets", {
88263
+ logger52.debug("Setting secrets", {
88138
88264
  userId: ctx.user.id,
88139
88265
  slug: slug2,
88140
88266
  keyCount: Object.keys(body2).length
@@ -88151,7 +88277,7 @@ var init_secrets_controller = __esm(() => {
88151
88277
  if (!key) {
88152
88278
  throw ApiError.badRequest("Missing secret key");
88153
88279
  }
88154
- logger50.debug("Deleting secret", { userId: ctx.user.id, slug: slug2, key });
88280
+ logger52.debug("Deleting secret", { userId: ctx.user.id, slug: slug2, key });
88155
88281
  await ctx.services.secrets.deleteSecret(slug2, key, ctx.user);
88156
88282
  return { success: true };
88157
88283
  });
@@ -88164,14 +88290,14 @@ var init_secrets_controller = __esm(() => {
88164
88290
  });
88165
88291
 
88166
88292
  // ../api-core/src/controllers/seed.controller.ts
88167
- var logger51, seed;
88293
+ var logger53, seed;
88168
88294
  var init_seed_controller = __esm(() => {
88169
88295
  init_esm();
88170
88296
  init_schemas_index();
88171
88297
  init_src2();
88172
88298
  init_errors();
88173
88299
  init_utils11();
88174
- logger51 = log.scope("SeedController");
88300
+ logger53 = log.scope("SeedController");
88175
88301
  seed = requireDeveloper(async (ctx) => {
88176
88302
  const slug2 = ctx.params.slug;
88177
88303
  if (!slug2) {
@@ -88184,29 +88310,29 @@ var init_seed_controller = __esm(() => {
88184
88310
  } catch (error2) {
88185
88311
  if (error2 instanceof exports_external.ZodError) {
88186
88312
  const details = formatZodError(error2);
88187
- logger51.warn("Seed database validation failed", { details });
88313
+ logger53.warn("Seed database validation failed", { details });
88188
88314
  throw ApiError.unprocessableEntity("Validation failed", details);
88189
88315
  }
88190
88316
  throw ApiError.badRequest("Invalid JSON body");
88191
88317
  }
88192
- logger51.debug("Seeding database", { userId: ctx.user.id, slug: slug2, codeLength: body2.code.length });
88318
+ logger53.debug("Seeding database", { userId: ctx.user.id, slug: slug2, codeLength: body2.code.length });
88193
88319
  return ctx.services.seed.seed(slug2, body2.code, ctx.user);
88194
88320
  });
88195
88321
  });
88196
88322
 
88197
88323
  // ../api-core/src/controllers/session.controller.ts
88198
- var logger52, start2, end, mintToken, sessions2;
88324
+ var logger54, start2, end, mintToken, sessions2;
88199
88325
  var init_session_controller = __esm(() => {
88200
88326
  init_src2();
88201
88327
  init_errors();
88202
88328
  init_utils11();
88203
- logger52 = log.scope("SessionController");
88329
+ logger54 = log.scope("SessionController");
88204
88330
  start2 = requireAuth(async (ctx) => {
88205
88331
  const gameIdOrSlug = ctx.params.gameId;
88206
88332
  if (!gameIdOrSlug) {
88207
88333
  throw ApiError.badRequest("Missing game ID or slug");
88208
88334
  }
88209
- logger52.debug("Starting session", { userId: ctx.user.id, gameIdOrSlug });
88335
+ logger54.debug("Starting session", { userId: ctx.user.id, gameIdOrSlug });
88210
88336
  return ctx.services.session.start(gameIdOrSlug, ctx.user.id);
88211
88337
  });
88212
88338
  end = requireAuth(async (ctx) => {
@@ -88218,7 +88344,7 @@ var init_session_controller = __esm(() => {
88218
88344
  if (!sessionId) {
88219
88345
  throw ApiError.badRequest("Missing session ID");
88220
88346
  }
88221
- logger52.debug("Ending session", { userId: ctx.user.id, gameIdOrSlug, sessionId });
88347
+ logger54.debug("Ending session", { userId: ctx.user.id, gameIdOrSlug, sessionId });
88222
88348
  return ctx.services.session.end(gameIdOrSlug, sessionId, ctx.user.id);
88223
88349
  });
88224
88350
  mintToken = requireAuth(async (ctx) => {
@@ -88226,7 +88352,7 @@ var init_session_controller = __esm(() => {
88226
88352
  if (!gameIdOrSlug) {
88227
88353
  throw ApiError.badRequest("Missing game ID or slug");
88228
88354
  }
88229
- logger52.debug("Minting token", { userId: ctx.user.id, gameIdOrSlug });
88355
+ logger54.debug("Minting token", { userId: ctx.user.id, gameIdOrSlug });
88230
88356
  return ctx.services.session.mintToken(gameIdOrSlug, ctx.user.id);
88231
88357
  });
88232
88358
  sessions2 = {
@@ -88237,13 +88363,13 @@ var init_session_controller = __esm(() => {
88237
88363
  });
88238
88364
 
88239
88365
  // ../api-core/src/controllers/shop.controller.ts
88240
- var logger53, getShopView, shop;
88366
+ var logger55, getShopView, shop;
88241
88367
  var init_shop_controller = __esm(() => {
88242
88368
  init_src2();
88243
88369
  init_utils11();
88244
- logger53 = log.scope("ShopController");
88370
+ logger55 = log.scope("ShopController");
88245
88371
  getShopView = requireAuth(async (ctx) => {
88246
- logger53.debug("Getting shop view", { userId: ctx.user.id });
88372
+ logger55.debug("Getting shop view", { userId: ctx.user.id });
88247
88373
  return ctx.services.shop.getShopView(ctx.user);
88248
88374
  });
88249
88375
  shop = {
@@ -88252,7 +88378,7 @@ var init_shop_controller = __esm(() => {
88252
88378
  });
88253
88379
 
88254
88380
  // ../api-core/src/controllers/shop-listing.controller.ts
88255
- var logger54, list7, getById4, create5, update5, remove5, listByGame2, getByGameItem, createForGameItem, updateForGameItem, deleteForGameItem, shopListings2;
88381
+ var logger56, list7, getById4, create5, update5, remove5, listByGame2, getByGameItem, createForGameItem, updateForGameItem, deleteForGameItem, shopListings2;
88256
88382
  var init_shop_listing_controller = __esm(() => {
88257
88383
  init_esm();
88258
88384
  init_schemas_index();
@@ -88260,9 +88386,9 @@ var init_shop_listing_controller = __esm(() => {
88260
88386
  init_src4();
88261
88387
  init_errors();
88262
88388
  init_utils11();
88263
- logger54 = log.scope("ShopListingController");
88389
+ logger56 = log.scope("ShopListingController");
88264
88390
  list7 = requireAdmin(async (ctx) => {
88265
- logger54.debug("Listing shop listings", { userId: ctx.user.id });
88391
+ logger56.debug("Listing shop listings", { userId: ctx.user.id });
88266
88392
  return ctx.services.shopListing.list();
88267
88393
  });
88268
88394
  getById4 = requireAdmin(async (ctx) => {
@@ -88273,7 +88399,7 @@ var init_shop_listing_controller = __esm(() => {
88273
88399
  if (!isValidUUID(listingId)) {
88274
88400
  throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
88275
88401
  }
88276
- logger54.debug("Getting listing", { userId: ctx.user.id, listingId });
88402
+ logger56.debug("Getting listing", { userId: ctx.user.id, listingId });
88277
88403
  return ctx.services.shopListing.getById(listingId);
88278
88404
  });
88279
88405
  create5 = requireAdmin(async (ctx) => {
@@ -88284,12 +88410,12 @@ var init_shop_listing_controller = __esm(() => {
88284
88410
  } catch (error2) {
88285
88411
  if (error2 instanceof exports_external.ZodError) {
88286
88412
  const details = formatZodError(error2);
88287
- logger54.warn("Create shop listing validation failed", { details });
88413
+ logger56.warn("Create shop listing validation failed", { details });
88288
88414
  throw ApiError.unprocessableEntity("Validation failed", details);
88289
88415
  }
88290
88416
  throw ApiError.badRequest("Invalid JSON body");
88291
88417
  }
88292
- logger54.debug("Creating listing", {
88418
+ logger56.debug("Creating listing", {
88293
88419
  userId: ctx.user.id,
88294
88420
  itemId: body2.itemId,
88295
88421
  currencyId: body2.currencyId,
@@ -88312,12 +88438,12 @@ var init_shop_listing_controller = __esm(() => {
88312
88438
  } catch (error2) {
88313
88439
  if (error2 instanceof exports_external.ZodError) {
88314
88440
  const details = formatZodError(error2);
88315
- logger54.warn("Update shop listing validation failed", { details });
88441
+ logger56.warn("Update shop listing validation failed", { details });
88316
88442
  throw ApiError.unprocessableEntity("Validation failed", details);
88317
88443
  }
88318
88444
  throw ApiError.badRequest("Invalid JSON body");
88319
88445
  }
88320
- logger54.debug("Updating listing", {
88446
+ logger56.debug("Updating listing", {
88321
88447
  userId: ctx.user.id,
88322
88448
  listingId,
88323
88449
  price: body2.price,
@@ -88334,7 +88460,7 @@ var init_shop_listing_controller = __esm(() => {
88334
88460
  if (!isValidUUID(listingId)) {
88335
88461
  throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
88336
88462
  }
88337
- logger54.debug("Deleting listing", { userId: ctx.user.id, listingId });
88463
+ logger56.debug("Deleting listing", { userId: ctx.user.id, listingId });
88338
88464
  await ctx.services.shopListing.delete(listingId);
88339
88465
  });
88340
88466
  listByGame2 = requireAuth(async (ctx) => {
@@ -88345,7 +88471,7 @@ var init_shop_listing_controller = __esm(() => {
88345
88471
  if (!isValidUUID(gameId)) {
88346
88472
  throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
88347
88473
  }
88348
- logger54.debug("Listing game listings", { userId: ctx.user.id, gameId });
88474
+ logger56.debug("Listing game listings", { userId: ctx.user.id, gameId });
88349
88475
  return ctx.services.shopListing.listByGame(gameId, ctx.user);
88350
88476
  });
88351
88477
  getByGameItem = requireAuth(async (ctx) => {
@@ -88360,7 +88486,7 @@ var init_shop_listing_controller = __esm(() => {
88360
88486
  if (!isValidUUID(itemId)) {
88361
88487
  throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
88362
88488
  }
88363
- logger54.debug("Getting game item listing", { userId: ctx.user.id, gameId, itemId });
88489
+ logger56.debug("Getting game item listing", { userId: ctx.user.id, gameId, itemId });
88364
88490
  return ctx.services.shopListing.getByGameItem(gameId, itemId, ctx.user);
88365
88491
  });
88366
88492
  createForGameItem = requireAuth(async (ctx) => {
@@ -88382,12 +88508,12 @@ var init_shop_listing_controller = __esm(() => {
88382
88508
  } catch (error2) {
88383
88509
  if (error2 instanceof exports_external.ZodError) {
88384
88510
  const details = formatZodError(error2);
88385
- logger54.warn("Create game item listing validation failed", { details });
88511
+ logger56.warn("Create game item listing validation failed", { details });
88386
88512
  throw ApiError.unprocessableEntity("Validation failed", details);
88387
88513
  }
88388
88514
  throw ApiError.badRequest("Invalid JSON body");
88389
88515
  }
88390
- logger54.debug("Creating game item listing", {
88516
+ logger56.debug("Creating game item listing", {
88391
88517
  userId: ctx.user.id,
88392
88518
  gameId,
88393
88519
  itemId,
@@ -88415,12 +88541,12 @@ var init_shop_listing_controller = __esm(() => {
88415
88541
  } catch (error2) {
88416
88542
  if (error2 instanceof exports_external.ZodError) {
88417
88543
  const details = formatZodError(error2);
88418
- logger54.warn("Update game item listing validation failed", { details });
88544
+ logger56.warn("Update game item listing validation failed", { details });
88419
88545
  throw ApiError.unprocessableEntity("Validation failed", details);
88420
88546
  }
88421
88547
  throw ApiError.badRequest("Invalid JSON body");
88422
88548
  }
88423
- logger54.debug("Updating game item listing", {
88549
+ logger56.debug("Updating game item listing", {
88424
88550
  userId: ctx.user.id,
88425
88551
  gameId,
88426
88552
  itemId,
@@ -88442,7 +88568,7 @@ var init_shop_listing_controller = __esm(() => {
88442
88568
  if (!isValidUUID(itemId)) {
88443
88569
  throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
88444
88570
  }
88445
- logger54.debug("Deleting game item listing", {
88571
+ logger56.debug("Deleting game item listing", {
88446
88572
  userId: ctx.user.id,
88447
88573
  gameId,
88448
88574
  itemId
@@ -88469,21 +88595,21 @@ async function getBySlug2(ctx) {
88469
88595
  if (!slug2) {
88470
88596
  throw ApiError.badRequest("Template slug is required");
88471
88597
  }
88472
- logger55.debug("Getting sprite by slug", { slug: slug2 });
88598
+ logger57.debug("Getting sprite by slug", { slug: slug2 });
88473
88599
  return ctx.services.sprite.getBySlug(slug2);
88474
88600
  }
88475
- var logger55, sprites;
88601
+ var logger57, sprites;
88476
88602
  var init_sprite_controller = __esm(() => {
88477
88603
  init_src2();
88478
88604
  init_errors();
88479
- logger55 = log.scope("SpriteController");
88605
+ logger57 = log.scope("SpriteController");
88480
88606
  sprites = {
88481
88607
  getBySlug: getBySlug2
88482
88608
  };
88483
88609
  });
88484
88610
 
88485
88611
  // ../api-core/src/controllers/timeback.controller.ts
88486
- var logger56, getTodayXp, getTotalXp, updateTodayXp, getXpHistory, populateStudent, getUser, getUserById, setupIntegration, getIntegrations, verifyIntegration, getConfig2, deleteIntegrations, endActivity, timeback2;
88612
+ var logger58, getTodayXp, getTotalXp, updateTodayXp, getXpHistory, populateStudent, getUser, getUserById, setupIntegration, getIntegrations, verifyIntegration, getConfig2, deleteIntegrations, endActivity, timeback2;
88487
88613
  var init_timeback_controller = __esm(() => {
88488
88614
  init_esm();
88489
88615
  init_schemas_index();
@@ -88491,15 +88617,15 @@ var init_timeback_controller = __esm(() => {
88491
88617
  init_src4();
88492
88618
  init_errors();
88493
88619
  init_utils11();
88494
- logger56 = log.scope("TimebackController");
88620
+ logger58 = log.scope("TimebackController");
88495
88621
  getTodayXp = requireAuth(async (ctx) => {
88496
88622
  const date4 = ctx.url.searchParams.get("date") || undefined;
88497
88623
  const tz = ctx.url.searchParams.get("tz") || undefined;
88498
- logger56.debug("Getting today XP", { userId: ctx.user.id, date: date4, tz });
88624
+ logger58.debug("Getting today XP", { userId: ctx.user.id, date: date4, tz });
88499
88625
  return ctx.services.timeback.getTodayXp(ctx.user.id, date4, tz);
88500
88626
  });
88501
88627
  getTotalXp = requireAuth(async (ctx) => {
88502
- logger56.debug("Getting total XP", { userId: ctx.user.id });
88628
+ logger58.debug("Getting total XP", { userId: ctx.user.id });
88503
88629
  return ctx.services.timeback.getTotalXp(ctx.user.id);
88504
88630
  });
88505
88631
  updateTodayXp = requireAuth(async (ctx) => {
@@ -88510,18 +88636,18 @@ var init_timeback_controller = __esm(() => {
88510
88636
  } catch (error2) {
88511
88637
  if (error2 instanceof exports_external.ZodError) {
88512
88638
  const details = formatZodError(error2);
88513
- logger56.warn("Update today XP validation failed", { details });
88639
+ logger58.warn("Update today XP validation failed", { details });
88514
88640
  throw ApiError.unprocessableEntity("Validation failed", details);
88515
88641
  }
88516
88642
  throw ApiError.badRequest("Invalid JSON body");
88517
88643
  }
88518
- logger56.debug("Updating today XP", { userId: ctx.user.id, xp: body2.xp });
88644
+ logger58.debug("Updating today XP", { userId: ctx.user.id, xp: body2.xp });
88519
88645
  return ctx.services.timeback.updateTodayXp(ctx.user.id, body2);
88520
88646
  });
88521
88647
  getXpHistory = requireAuth(async (ctx) => {
88522
88648
  const startDate = ctx.url.searchParams.get("startDate") || undefined;
88523
88649
  const endDate = ctx.url.searchParams.get("endDate") || undefined;
88524
- logger56.debug("Getting XP history", { userId: ctx.user.id, startDate, endDate });
88650
+ logger58.debug("Getting XP history", { userId: ctx.user.id, startDate, endDate });
88525
88651
  return ctx.services.timeback.getXpHistory(ctx.user.id, startDate, endDate);
88526
88652
  });
88527
88653
  populateStudent = requireAuth(async (ctx) => {
@@ -88532,18 +88658,18 @@ var init_timeback_controller = __esm(() => {
88532
88658
  } catch (error2) {
88533
88659
  if (error2 instanceof exports_external.ZodError) {
88534
88660
  const details = formatZodError(error2);
88535
- logger56.warn("Populate student validation failed", { details });
88661
+ logger58.warn("Populate student validation failed", { details });
88536
88662
  throw ApiError.unprocessableEntity("Validation failed", details);
88537
88663
  }
88538
88664
  }
88539
- logger56.debug("Populating student", {
88665
+ logger58.debug("Populating student", {
88540
88666
  userId: ctx.user.id,
88541
88667
  hasProvidedNames: !!providedNames
88542
88668
  });
88543
88669
  return ctx.services.timeback.populateStudent(ctx.user, providedNames);
88544
88670
  });
88545
88671
  getUser = requireAuth(async (ctx) => {
88546
- logger56.debug("Getting user", { userId: ctx.user.id, gameId: ctx.gameId });
88672
+ logger58.debug("Getting user", { userId: ctx.user.id, gameId: ctx.gameId });
88547
88673
  return ctx.services.timeback.getUserData(ctx.user.id, ctx.gameId);
88548
88674
  });
88549
88675
  getUserById = requireAuth(async (ctx) => {
@@ -88551,7 +88677,7 @@ var init_timeback_controller = __esm(() => {
88551
88677
  if (!timebackId) {
88552
88678
  throw ApiError.badRequest("Missing timebackId parameter");
88553
88679
  }
88554
- logger56.debug("Getting user by ID", { requesterId: ctx.user.id, timebackId });
88680
+ logger58.debug("Getting user by ID", { requesterId: ctx.user.id, timebackId });
88555
88681
  return ctx.services.timeback.getUserDataByTimebackId(timebackId);
88556
88682
  });
88557
88683
  setupIntegration = requireDeveloper(async (ctx) => {
@@ -88562,12 +88688,12 @@ var init_timeback_controller = __esm(() => {
88562
88688
  } catch (error2) {
88563
88689
  if (error2 instanceof exports_external.ZodError) {
88564
88690
  const details = formatZodError(error2);
88565
- logger56.warn("Setup integration validation failed", { details });
88691
+ logger58.warn("Setup integration validation failed", { details });
88566
88692
  throw ApiError.unprocessableEntity("Validation failed", details);
88567
88693
  }
88568
88694
  throw ApiError.badRequest("Invalid JSON body");
88569
88695
  }
88570
- logger56.debug("Setting up integration", {
88696
+ logger58.debug("Setting up integration", {
88571
88697
  userId: ctx.user.id,
88572
88698
  gameId: body2.gameId
88573
88699
  });
@@ -88579,7 +88705,7 @@ var init_timeback_controller = __esm(() => {
88579
88705
  throw ApiError.badRequest("Missing gameId");
88580
88706
  if (!isValidUUID(gameId))
88581
88707
  throw ApiError.unprocessableEntity("Invalid gameId format");
88582
- logger56.debug("Getting integrations", { userId: ctx.user.id, gameId });
88708
+ logger58.debug("Getting integrations", { userId: ctx.user.id, gameId });
88583
88709
  return ctx.services.timeback.getIntegrations(gameId, ctx.user);
88584
88710
  });
88585
88711
  verifyIntegration = requireDeveloper(async (ctx) => {
@@ -88588,7 +88714,7 @@ var init_timeback_controller = __esm(() => {
88588
88714
  throw ApiError.badRequest("Missing gameId");
88589
88715
  if (!isValidUUID(gameId))
88590
88716
  throw ApiError.unprocessableEntity("Invalid gameId format");
88591
- logger56.debug("Verifying integration", { userId: ctx.user.id, gameId });
88717
+ logger58.debug("Verifying integration", { userId: ctx.user.id, gameId });
88592
88718
  return ctx.services.timeback.verifyIntegration(gameId, ctx.user);
88593
88719
  });
88594
88720
  getConfig2 = requireDeveloper(async (ctx) => {
@@ -88597,7 +88723,7 @@ var init_timeback_controller = __esm(() => {
88597
88723
  throw ApiError.badRequest("Missing gameId");
88598
88724
  if (!isValidUUID(gameId))
88599
88725
  throw ApiError.unprocessableEntity("Invalid gameId format");
88600
- logger56.debug("Getting config", { userId: ctx.user.id, gameId });
88726
+ logger58.debug("Getting config", { userId: ctx.user.id, gameId });
88601
88727
  return ctx.services.timeback.getConfig(gameId, ctx.user);
88602
88728
  });
88603
88729
  deleteIntegrations = requireDeveloper(async (ctx) => {
@@ -88606,7 +88732,7 @@ var init_timeback_controller = __esm(() => {
88606
88732
  throw ApiError.badRequest("Missing gameId");
88607
88733
  if (!isValidUUID(gameId))
88608
88734
  throw ApiError.unprocessableEntity("Invalid gameId format");
88609
- logger56.debug("Deleting integrations", { userId: ctx.user.id, gameId });
88735
+ logger58.debug("Deleting integrations", { userId: ctx.user.id, gameId });
88610
88736
  await ctx.services.timeback.deleteIntegrations(gameId, ctx.user);
88611
88737
  });
88612
88738
  endActivity = requireDeveloper(async (ctx) => {
@@ -88617,13 +88743,13 @@ var init_timeback_controller = __esm(() => {
88617
88743
  } catch (error2) {
88618
88744
  if (error2 instanceof exports_external.ZodError) {
88619
88745
  const details = formatZodError(error2);
88620
- logger56.warn("End activity validation failed", { details });
88746
+ logger58.warn("End activity validation failed", { details });
88621
88747
  throw ApiError.unprocessableEntity("Validation failed", details);
88622
88748
  }
88623
88749
  throw ApiError.badRequest("Invalid JSON body");
88624
88750
  }
88625
88751
  const { gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits } = body2;
88626
- logger56.debug("Ending activity", { userId: ctx.user.id, gameId });
88752
+ logger58.debug("Ending activity", { userId: ctx.user.id, gameId });
88627
88753
  return ctx.services.timeback.endActivity(gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits, ctx.user);
88628
88754
  });
88629
88755
  timeback2 = {
@@ -88644,14 +88770,14 @@ var init_timeback_controller = __esm(() => {
88644
88770
  });
88645
88771
 
88646
88772
  // ../api-core/src/controllers/upload.controller.ts
88647
- var logger57, initiate;
88773
+ var logger59, initiate;
88648
88774
  var init_upload_controller = __esm(() => {
88649
88775
  init_esm();
88650
88776
  init_schemas_index();
88651
88777
  init_src2();
88652
88778
  init_errors();
88653
88779
  init_utils11();
88654
- logger57 = log.scope("UploadController");
88780
+ logger59 = log.scope("UploadController");
88655
88781
  initiate = requireDeveloper(async (ctx) => {
88656
88782
  let body2;
88657
88783
  try {
@@ -88660,24 +88786,24 @@ var init_upload_controller = __esm(() => {
88660
88786
  } catch (error2) {
88661
88787
  if (error2 instanceof exports_external.ZodError) {
88662
88788
  const details = formatZodError(error2);
88663
- logger57.warn("Initiate upload validation failed", { details });
88789
+ logger59.warn("Initiate upload validation failed", { details });
88664
88790
  throw ApiError.unprocessableEntity("Validation failed", details);
88665
88791
  }
88666
88792
  throw ApiError.badRequest("Invalid JSON body");
88667
88793
  }
88668
- logger57.debug("Initiating upload", { userId: ctx.user.id, gameId: body2.gameId });
88794
+ logger59.debug("Initiating upload", { userId: ctx.user.id, gameId: body2.gameId });
88669
88795
  return ctx.services.upload.initiate(body2, ctx.user);
88670
88796
  });
88671
88797
  });
88672
88798
 
88673
88799
  // ../api-core/src/controllers/user.controller.ts
88674
- var logger58, getMe, users2;
88800
+ var logger60, getMe, users2;
88675
88801
  var init_user_controller = __esm(() => {
88676
88802
  init_src2();
88677
88803
  init_utils11();
88678
- logger58 = log.scope("UserController");
88804
+ logger60 = log.scope("UserController");
88679
88805
  getMe = requireAuth(async (ctx) => {
88680
- logger58.debug("Getting current user", { userId: ctx.user.id, gameId: ctx.gameId });
88806
+ logger60.debug("Getting current user", { userId: ctx.user.id, gameId: ctx.gameId });
88681
88807
  return ctx.services.user.getMe(ctx.user, ctx.gameId);
88682
88808
  });
88683
88809
  users2 = {
@@ -88686,13 +88812,13 @@ var init_user_controller = __esm(() => {
88686
88812
  });
88687
88813
 
88688
88814
  // ../api-core/src/controllers/verify.controller.ts
88689
- var logger59;
88815
+ var logger61;
88690
88816
  var init_verify_controller = __esm(() => {
88691
88817
  init_schemas_index();
88692
88818
  init_src2();
88693
88819
  init_errors();
88694
88820
  init_utils11();
88695
- logger59 = log.scope("VerifyController");
88821
+ logger61 = log.scope("VerifyController");
88696
88822
  });
88697
88823
 
88698
88824
  // ../api-core/src/controllers/index.ts
@@ -88711,6 +88837,7 @@ var init_controllers = __esm(() => {
88711
88837
  init_item_controller();
88712
88838
  init_leaderboard_controller();
88713
88839
  init_level_controller();
88840
+ init_logs_controller();
88714
88841
  init_lti_controller();
88715
88842
  init_map_controller();
88716
88843
  init_notification_controller();
@@ -89227,6 +89354,16 @@ var init_items = __esm(() => {
89227
89354
  gameItemsRouter.delete("/:gameId/items/:itemId", handle2(items2.deleteForGame, { status: 204 }));
89228
89355
  });
89229
89356
 
89357
+ // src/routes/platform/games/logs.ts
89358
+ var gameLogsRouter;
89359
+ var init_logs = __esm(() => {
89360
+ init_dist3();
89361
+ init_controllers();
89362
+ init_api();
89363
+ gameLogsRouter = new Hono2;
89364
+ gameLogsRouter.post("/:slug/logs/token", handle2(logs.generateToken));
89365
+ });
89366
+
89230
89367
  // src/routes/platform/games/scores.ts
89231
89368
  var gameScoresRouter;
89232
89369
  var init_scores = __esm(() => {
@@ -89542,6 +89679,7 @@ var init_games2 = __esm(() => {
89542
89679
  init_deploy();
89543
89680
  init_domains3();
89544
89681
  init_items();
89682
+ init_logs();
89545
89683
  init_scores();
89546
89684
  init_secrets();
89547
89685
  init_seed2();
@@ -89557,6 +89695,7 @@ var init_games2 = __esm(() => {
89557
89695
  gamesRouter.route("/", gameDeployRouter);
89558
89696
  gamesRouter.route("/", gameDomainsRouter);
89559
89697
  gamesRouter.route("/", gameItemsRouter);
89698
+ gamesRouter.route("/", gameLogsRouter);
89560
89699
  gamesRouter.route("/", gameShopRouter);
89561
89700
  gamesRouter.route("/", gameScoresRouter);
89562
89701
  gamesRouter.route("/", gameSecretsRouter);