@xenon-device-management/xenon 1.29.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +11 -2
  2. package/lib/package.json +1 -1
  3. package/lib/public/assets/{AnnotationOverlay-Ne9IA8t9.js → AnnotationOverlay-BmTPCAds.js} +1 -1
  4. package/lib/public/assets/{ApiKeyGate-CwXbDjtR.js → ApiKeyGate-B5eB7f8B.js} +1 -1
  5. package/lib/public/assets/{BugReportButton-D8694Ndn.js → BugReportButton-DKYsOdGV.js} +1 -1
  6. package/lib/public/assets/{DeviceMosaicView-vqKa_a7b.js → DeviceMosaicView-9DUoZnQi.js} +1 -1
  7. package/lib/public/assets/{EmptyState-DqbEejWx.js → EmptyState-lvyNiXev.js} +1 -1
  8. package/lib/public/assets/{FieldGroup-BNKuUsHt.js → FieldGroup-BduMPM9K.js} +1 -1
  9. package/lib/public/assets/{FilterMenu-CLqoSOsz.js → FilterMenu-BSqX6I94.js} +1 -1
  10. package/lib/public/assets/{Menu-CU57vgsd.js → Menu-Ba5cT7jZ.js} +1 -1
  11. package/lib/public/assets/{Modal-Dt2whV22.js → Modal-CceoMY7D.js} +1 -1
  12. package/lib/public/assets/{RecordingPage-BipS3IoG.js → RecordingPage-6T9dOidc.js} +1 -1
  13. package/lib/public/assets/{RecordingsPage-DORtXeH5.js → RecordingsPage-qj6FdZXR.js} +1 -1
  14. package/lib/public/assets/{SegmentedControl-IX6aSFFO.js → SegmentedControl-CSRuZ8TR.js} +1 -1
  15. package/lib/public/assets/{SettingCard-DDp2N5zA.js → SettingCard-Bp1kz4By.js} +1 -1
  16. package/lib/public/assets/{Table-CiaA4Dni.js → Table-LV7zFyZg.js} +1 -1
  17. package/lib/public/assets/{activity-DzhwJvJO.js → activity-D17TUloi.js} +1 -1
  18. package/lib/public/assets/{ai-settings-BllB4M52.js → ai-settings-qvbhY89P.js} +1 -1
  19. package/lib/public/assets/api-keys-BfpvdG7G.js +1 -0
  20. package/lib/public/assets/apps-DMhpZuKd.css +1 -0
  21. package/lib/public/assets/apps-Dbnzd0fW.js +26 -0
  22. package/lib/public/assets/{arrow-left-poHDsOnw.js → arrow-left-DD1VjtC7.js} +1 -1
  23. package/lib/public/assets/{arrow-right-Bt8ka8uH.js → arrow-right-D0pnM3ma.js} +1 -1
  24. package/lib/public/assets/{arrow-up-right-C7zjEfIX.js → arrow-up-right-BIC8JOV6.js} +1 -1
  25. package/lib/public/assets/{auth-shell-DqNP66nv.js → auth-shell-DWHPXSnI.js} +2 -2
  26. package/lib/public/assets/{builds-page-BmoSSMe1.js → builds-page-ClCNBUv_.js} +1 -1
  27. package/lib/public/assets/{button-DujkWRKD.js → button-xtAhYR-f.js} +1 -1
  28. package/lib/public/assets/{calendar-3xj_SfAt.js → calendar-CupwJ7Bm.js} +1 -1
  29. package/lib/public/assets/{check-DAtcemi7.js → check-CyuEoKkd.js} +1 -1
  30. package/lib/public/assets/{chevron-left-BODVavmZ.js → chevron-left-DgX-F9xK.js} +1 -1
  31. package/lib/public/assets/{chevron-right-BtzJa9CV.js → chevron-right-BKJgJnU9.js} +1 -1
  32. package/lib/public/assets/{circle-check-CNLy00dn.js → circle-check-CZdg8mMa.js} +1 -1
  33. package/lib/public/assets/{circle-x-DwlxOXJV.js → circle-x-CZH6t9z-.js} +1 -1
  34. package/lib/public/assets/{clock-CthJSgmT.js → clock-Cd-t7xpe.js} +1 -1
  35. package/lib/public/assets/{copy-o_vwnvDl.js → copy-C6zerX3I.js} +1 -1
  36. package/lib/public/assets/{device-explorer-BGwZQSit.js → device-explorer-B1pI6b_M.js} +2 -2
  37. package/lib/public/assets/device-explorer-DV8rWRxL.css +1 -0
  38. package/lib/public/assets/{download-CH7KYHQ6.js → download-x9WP7mcL.js} +1 -1
  39. package/lib/public/assets/{forgot-password-Fo0NoMuQ.js → forgot-password-B0TEH4N-.js} +1 -1
  40. package/lib/public/assets/{funnel-DLq7lVeF.js → funnel-Cb40MfFN.js} +1 -1
  41. package/lib/public/assets/{index-SVMaJ9rC.js → index-BR1wTIPC.js} +9 -9
  42. package/lib/public/assets/{index-tbOE1tW_.js → index-BvH_ekRy.js} +1 -1
  43. package/lib/public/assets/{index-Fa91L6sA.css → index-hymrhlEZ.css} +1 -1
  44. package/lib/public/assets/{input-Cn9aCi1V.js → input-DejcCiTI.js} +1 -1
  45. package/lib/public/assets/{keycodes-DVNcuy4F.js → keycodes-Mavx5iGg.js} +1 -1
  46. package/lib/public/assets/{layers-DFA4vIXT.js → layers-BKqYLiHE.js} +1 -1
  47. package/lib/public/assets/{lock-DbVuQMlE.js → lock-LFsFhc17.js} +1 -1
  48. package/lib/public/assets/{login-kvBEtLEI.js → login-x2pkzt-t.js} +1 -1
  49. package/lib/public/assets/{maintenance-settings-9MSQd7-h.js → maintenance-settings-CYafcoV-.js} +1 -1
  50. package/lib/public/assets/{monitor-C2wiQCzm.js → monitor-_7_uJ8d9.js} +1 -1
  51. package/lib/public/assets/{mouse-pointer-2-BxOt4PTR.js → mouse-pointer-2-BfLuURKN.js} +1 -1
  52. package/lib/public/assets/{network-VOsv-B1C.js → network-Z_zBhpsD.js} +1 -1
  53. package/lib/public/assets/{overview-BxRv07jX.js → overview-BY5uv08S.js} +1 -1
  54. package/lib/public/assets/{page-header-DRYmsZ55.js → page-header-CP2UkykG.js} +1 -1
  55. package/lib/public/assets/{plus-BY8JP9c5.js → plus-BTD0dnQ0.js} +1 -1
  56. package/lib/public/assets/{profile-page-C0IMKJRO.js → profile-page-BhJZuCS7.js} +1 -1
  57. package/lib/public/assets/{reset-password-2OxcQdve.js → reset-password-CMN0SO81.js} +1 -1
  58. package/lib/public/assets/{runbook-page-ChzDYLnk.js → runbook-page-CBpPX9_5.js} +1 -1
  59. package/lib/public/assets/{select-DkLtE2T3.js → select-Uc9E5pye.js} +1 -1
  60. package/lib/public/assets/{selector-detail-page-9XKCgLLk.js → selector-detail-page-BSyBnRuU.js} +1 -1
  61. package/lib/public/assets/{selector-health-CZb7lL82.js → selector-health-DzqxNkzm.js} +1 -1
  62. package/lib/public/assets/{selector-health-page-CgNkXERq.js → selector-health-page-CyPLjoD1.js} +1 -1
  63. package/lib/public/assets/{session-detail-page-V68omLzd.js → session-detail-page-BZQZN1P-.js} +1 -1
  64. package/lib/public/assets/{settings-BTO5_h8Z.js → settings-CkSWiZq8.js} +1 -1
  65. package/lib/public/assets/{status-pill-outline-DteJiQpj.js → status-pill-outline-BFYni2qo.js} +1 -1
  66. package/lib/public/assets/{tablet-BvW2cqBO.js → tablet-BSd-xSZK.js} +1 -1
  67. package/lib/public/assets/teams-PpoEQz31.js +1 -0
  68. package/lib/public/assets/{trash-2-Ck4Hj9AT.js → trash-2-BorJv5_u.js} +1 -1
  69. package/lib/public/assets/{upload-DOZwUk1H.js → upload-C3i7sAZl.js} +1 -1
  70. package/lib/public/assets/{use-password-reset-mode-BkBlX2qd.js → use-password-reset-mode-CeZQ3EsH.js} +1 -1
  71. package/lib/public/assets/{users-yoXht7X_.js → users-CEJ3fC78.js} +1 -1
  72. package/lib/public/assets/{users-CkggsUeX.js → users-Drd7ifJx.js} +1 -1
  73. package/lib/public/assets/{video-off-DZG2o_Gl.js → video-off-CNzn6bPE.js} +1 -1
  74. package/lib/public/assets/{webhook-settings-D31jQ3yC.js → webhook-settings-BFqX6QXV.js} +1 -1
  75. package/lib/public/assets/{zap-nAiJWOGv.js → zap-4yN8Jdfw.js} +1 -1
  76. package/lib/public/index.html +2 -2
  77. package/lib/schema.json +1 -1
  78. package/lib/src/XenonCapabilityManager.js +21 -50
  79. package/lib/src/app/index.js +14 -9
  80. package/lib/src/app/insertBeforeRoutes.js +57 -0
  81. package/lib/src/app/registerCommandAuth.js +67 -0
  82. package/lib/src/app/routers/apps.js +83 -5
  83. package/lib/src/app/routers/auth.js +1 -1
  84. package/lib/src/app/routers/bug-report.js +12 -0
  85. package/lib/src/app/routers/capabilities.js +4 -0
  86. package/lib/src/app/routers/control.js +6 -1
  87. package/lib/src/app/routers/dashboard.js +116 -66
  88. package/lib/src/app/routers/grid.js +38 -57
  89. package/lib/src/app/routers/recordings.js +3 -1
  90. package/lib/src/app/swagger-docs.js +7 -4
  91. package/lib/src/app/swagger.js +3 -0
  92. package/lib/src/dashboard/event-manager.js +18 -21
  93. package/lib/src/dashboard/services/app-service.js +24 -2
  94. package/lib/src/data-service/device-service.js +2 -1
  95. package/lib/src/data-service/queue-service.js +4 -3
  96. package/lib/src/device-utils.js +1 -1
  97. package/lib/src/generated/client/edge.js +5 -4
  98. package/lib/src/generated/client/index-browser.js +2 -1
  99. package/lib/src/generated/client/index.d.ts +413 -7
  100. package/lib/src/generated/client/index.js +5 -4
  101. package/lib/src/generated/client/package.json +1 -1
  102. package/lib/src/generated/client/schema.prisma +7 -0
  103. package/lib/src/generated/client/wasm.js +2 -1
  104. package/lib/src/interceptors/CommandInterceptor.js +5 -5
  105. package/lib/src/middleware/authMiddleware.js +44 -36
  106. package/lib/src/middleware/commandAuth.js +146 -0
  107. package/lib/src/middleware/commandCaller.js +142 -0
  108. package/lib/src/middleware/verifyCredential.js +124 -0
  109. package/lib/src/services/ServerManager.js +7 -0
  110. package/lib/src/services/SessionLifecycleService.js +143 -73
  111. package/lib/src/services/TeamService.js +6 -3
  112. package/lib/src/services/device-access/appVisibility.js +27 -0
  113. package/lib/src/services/device-access/queueVisibility.js +118 -0
  114. package/lib/src/services/device-access/sessionVisibility.js +65 -0
  115. package/lib/src/services/healing/HealingOrchestrator.js +11 -3
  116. package/lib/src/services/lease/LeaseService.js +13 -4
  117. package/lib/src/services/lease/buildCapabilityBag.js +4 -1
  118. package/lib/src/services/lease/leaseSessionCaps.js +13 -69
  119. package/lib/src/services/recording/annotation-render.js +33 -1
  120. package/lib/src/services/recording/recordingSummary.js +6 -5
  121. package/lib/src/services/recording/recordingTiming.js +19 -5
  122. package/lib/src/services/session/appCapability.js +50 -0
  123. package/lib/src/services/session/sessionCredentials.js +105 -0
  124. package/lib/src/services/session/xenonOptions.js +71 -0
  125. package/lib/src/services/sessionTokenGate.js +19 -9
  126. package/lib/src/services/token/AppDownloadTicketService.js +73 -0
  127. package/lib/src/services/token/StreamTicketService.js +7 -17
  128. package/lib/src/services/token/singleUseLedger.js +41 -0
  129. package/lib/src/sessions/XenonSession.js +2 -2
  130. package/lib/test/helpers/loopbackServer.js +48 -0
  131. package/lib/test/integration/sdk-leases-router.spec.js +1 -1
  132. package/lib/test/integration/team-visibility-apps.spec.js +181 -0
  133. package/lib/test/integration/team-visibility-recordings.spec.js +4 -0
  134. package/lib/test/integration/team-visibility-sessions.spec.js +274 -0
  135. package/lib/test/unit/AppDownloadTicketService.spec.js +101 -0
  136. package/lib/test/unit/CapabilitiesRouter.spec.js +10 -0
  137. package/lib/test/unit/SessionTokenGate.spec.js +7 -2
  138. package/lib/test/unit/TeamService.test.js +22 -0
  139. package/lib/test/unit/XenonCapabilityManager.spec.js +11 -1
  140. package/lib/test/unit/aggregate-hotspots-session-scope.spec.js +202 -0
  141. package/lib/test/unit/annotation-render.spec.js +90 -0
  142. package/lib/test/unit/apps-team-visibility.spec.js +305 -0
  143. package/lib/test/unit/authMiddleware.appTicket.spec.js +201 -0
  144. package/lib/test/unit/bug-report/route.spec.js +49 -2
  145. package/lib/test/unit/cliargs-admin-only.spec.js +182 -0
  146. package/lib/test/unit/command-auth-appium-server.spec.js +184 -0
  147. package/lib/test/unit/command-auth.spec.js +410 -0
  148. package/lib/test/unit/command-caller.spec.js +254 -0
  149. package/lib/test/unit/event-manager-regression-hook.spec.js +7 -1
  150. package/lib/test/unit/extract-access-key-token-pair.test.js +47 -4
  151. package/lib/test/unit/grid-admin-only.spec.js +55 -0
  152. package/lib/test/unit/healing-tier-gate.spec.js +24 -1
  153. package/lib/test/unit/insert-before-routes.spec.js +167 -0
  154. package/lib/test/unit/install-repository-app-team.spec.js +116 -0
  155. package/lib/test/unit/lease/LeaseService.spec.js +3 -1
  156. package/lib/test/unit/lease/allocate-lease-branch.spec.js +2 -2
  157. package/lib/test/unit/lease/buildCapabilityBag.spec.js +3 -2
  158. package/lib/test/unit/lease/lease-override.spec.js +1 -1
  159. package/lib/test/unit/lease/lease-session-ownership.spec.js +4 -4
  160. package/lib/test/unit/lease/lease-team-visibility.spec.js +1 -1
  161. package/lib/test/unit/lease/lease-token-log-filter.spec.js +1 -1
  162. package/lib/test/unit/lease/lease-token-oracle.spec.js +207 -0
  163. package/lib/test/unit/lease/session-lease-proof.spec.js +42 -26
  164. package/lib/test/unit/logcat-ws.spec.js +7 -4
  165. package/lib/test/unit/queue-requester.spec.js +211 -0
  166. package/lib/test/unit/queue-team-scope-routes.spec.js +209 -0
  167. package/lib/test/unit/queue-visibility.spec.js +179 -0
  168. package/lib/test/unit/recording-summary.spec.js +22 -0
  169. package/lib/test/unit/recording-timing.spec.js +27 -0
  170. package/lib/test/unit/recordings-library-routes.spec.js +25 -0
  171. package/lib/test/unit/session-app-resolution.spec.js +331 -0
  172. package/lib/test/unit/session-assets.spec.js +167 -0
  173. package/lib/test/unit/session-attribution-wiring.spec.js +134 -24
  174. package/lib/test/unit/session-credential-strip.spec.js +277 -0
  175. package/lib/test/unit/session-credentials.spec.js +149 -0
  176. package/lib/test/unit/session-identity.spec.js +2 -2
  177. package/lib/test/unit/session-visibility.spec.js +109 -0
  178. package/lib/test/unit/stored-session-capabilities.spec.js +54 -0
  179. package/lib/test/unit/verify-credential.spec.js +138 -0
  180. package/lib/test/unit/xenon-options.spec.js +95 -0
  181. package/lib/tsconfig.tsbuildinfo +1 -1
  182. package/package.json +1 -1
  183. package/prisma/migrations/20260928120000_app_team/migration.sql +26 -0
  184. package/prisma/schema.prisma +7 -0
  185. package/schema.json +1 -1
  186. package/lib/public/assets/api-keys-bjXg97iu.js +0 -1
  187. package/lib/public/assets/apps-CQEjt22I.js +0 -21
  188. package/lib/public/assets/apps-DJMD5JOy.css +0 -1
  189. package/lib/public/assets/device-explorer-DTH5oU54.css +0 -1
  190. package/lib/public/assets/teams-8Qo7HmUv.js +0 -1
@@ -21,6 +21,7 @@ const appium_adb_1 = require("appium-adb");
21
21
  const logger_1 = __importDefault(require("../../logger"));
22
22
  const uuid_1 = require("uuid");
23
23
  const crypto_1 = __importDefault(require("crypto"));
24
+ const appVisibility_1 = require("../../services/device-access/appVisibility");
24
25
  class AppService {
25
26
  constructor() {
26
27
  this.ensureAppDir();
@@ -35,9 +36,15 @@ class AppService {
35
36
  }
36
37
  });
37
38
  }
38
- getApps() {
39
+ /**
40
+ * The apps a caller may see (`teamIds` as on req.auth: undefined is an
41
+ * admin), newest first, each with its team's name for the Team column.
42
+ */
43
+ getApps(teamIds) {
39
44
  return __awaiter(this, void 0, void 0, function* () {
40
45
  return yield prisma_1.prisma.app.findMany({
46
+ where: (0, appVisibility_1.visibleAppWhere)(teamIds),
47
+ include: { team: { select: { id: true, name: true } } },
41
48
  orderBy: { createdAt: 'desc' },
42
49
  });
43
50
  });
@@ -77,8 +84,22 @@ class AppService {
77
84
  }
78
85
  });
79
86
  }
80
- uploadApp(file) {
87
+ /** Moves an app to a team, or to the shared pool with null. Returns rows changed (0 or 1). */
88
+ setAppTeam(id, teamId) {
81
89
  return __awaiter(this, void 0, void 0, function* () {
90
+ const result = yield prisma_1.prisma.app.updateMany({ where: { id }, data: { teamId } });
91
+ return result.count;
92
+ });
93
+ }
94
+ /**
95
+ * Stores an uploaded app in `teamId`'s team, or shared when null.
96
+ *
97
+ * The same bytes (by md5, which is unique) are stored once: re-uploading
98
+ * them returns the existing app unchanged, in whatever team it is already
99
+ * in. An admin who wants it elsewhere moves it with PUT /apps/:id/team.
100
+ */
101
+ uploadApp(file_1) {
102
+ return __awaiter(this, arguments, void 0, function* (file, teamId = null) {
82
103
  var _a;
83
104
  yield this.ensureAppDir();
84
105
  // Calculate MD5 to check for duplicates
@@ -125,6 +146,7 @@ class AppService {
125
146
  version,
126
147
  platform,
127
148
  md5,
149
+ teamId,
128
150
  },
129
151
  });
130
152
  });
@@ -184,8 +184,9 @@ function filterRowsByVisibleDevice(rows, teamIds, udidField) {
184
184
  if (teamIds === undefined)
185
185
  return rows;
186
186
  const udids = Array.from(new Set(rows.map((r) => String(r[udidField])).filter(Boolean)));
187
+ // A row with no udid has no phone to be visible through (fail closed).
187
188
  if (udids.length === 0)
188
- return rows;
189
+ return [];
189
190
  const devices = yield prisma_1.prisma.device.findMany({
190
191
  where: { udid: { in: udids } },
191
192
  select: { udid: true, teamId: true },
@@ -118,12 +118,13 @@ let QueueService = class QueueService {
118
118
  });
119
119
  }
120
120
  /**
121
- * Returns a high-level summary of the entire queue
121
+ * Returns a high-level summary of the entire queue. Pass the pending rows
122
+ * already read, so a caller's other counts come from the same read.
122
123
  */
123
- getQueueSummary() {
124
+ getQueueSummary(pending) {
124
125
  return __awaiter(this, void 0, void 0, function* () {
125
126
  logger_1.default.info('[QueueService] Calculating global queue summary');
126
- const allPending = yield this.pendingStore.getAllPendingSessions();
127
+ const allPending = pending !== null && pending !== void 0 ? pending : (yield this.pendingStore.getAllPendingSessions());
127
128
  const platforms = [
128
129
  ...new Set(allPending.map((s) => { var _a; return (((_a = s.alwaysMatch) === null || _a === void 0 ? void 0 : _a.platformName) || s.platformName || 'any').toLowerCase(); })),
129
130
  ];
@@ -159,7 +159,7 @@ const NO_LEASE_PROOF = {
159
159
  * and update the capability json with required device informations
160
160
  * @param capability
161
161
  * @param leaseProof who the session is, and the lease token it sent; only a
162
- * session naming a lease in `xenon:options.leaseId` reads it
162
+ * session naming a lease in `xe:options.leaseId` reads it
163
163
  * @returns
164
164
  */
165
165
  function allocateDeviceForSession(capability_1, deviceTimeOutMs_1, deviceQueryIntervalMs_1, pluginArgs_1, callerTeamIds_1) {