@superblocksteam/shared 0.9607.2 → 0.9608.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 (294) hide show
  1. package/dist/database-lifecycle/appDatabaseCompatibility.d.ts +49 -0
  2. package/dist/database-lifecycle/appDatabaseCompatibility.d.ts.map +1 -0
  3. package/dist/database-lifecycle/appDatabaseCompatibility.js +32 -0
  4. package/dist/database-lifecycle/appDatabaseCompatibility.js.map +1 -0
  5. package/dist/database-lifecycle/appDatabaseCompatibility.test.d.ts +2 -0
  6. package/dist/database-lifecycle/appDatabaseCompatibility.test.d.ts.map +1 -0
  7. package/dist/database-lifecycle/appDatabaseCompatibility.test.js +47 -0
  8. package/dist/database-lifecycle/appDatabaseCompatibility.test.js.map +1 -0
  9. package/dist/database-lifecycle/destructiveMigrations.d.ts +12 -0
  10. package/dist/database-lifecycle/destructiveMigrations.d.ts.map +1 -1
  11. package/dist/database-lifecycle/destructiveMigrations.js +114 -0
  12. package/dist/database-lifecycle/destructiveMigrations.js.map +1 -1
  13. package/dist/database-lifecycle/destructiveMigrations.test.js +79 -0
  14. package/dist/database-lifecycle/destructiveMigrations.test.js.map +1 -1
  15. package/dist/database-lifecycle/index.d.ts +46 -2
  16. package/dist/database-lifecycle/index.d.ts.map +1 -1
  17. package/dist/database-lifecycle/index.js +127 -1
  18. package/dist/database-lifecycle/index.js.map +1 -1
  19. package/dist/database-lifecycle/providerDiagnostics.test.d.ts +2 -0
  20. package/dist/database-lifecycle/providerDiagnostics.test.d.ts.map +1 -0
  21. package/dist/database-lifecycle/providerDiagnostics.test.js +119 -0
  22. package/dist/database-lifecycle/providerDiagnostics.test.js.map +1 -0
  23. package/dist/environment-compatibility/appEnvironmentCompatibility.d.ts +65 -0
  24. package/dist/environment-compatibility/appEnvironmentCompatibility.d.ts.map +1 -0
  25. package/dist/environment-compatibility/appEnvironmentCompatibility.js +87 -0
  26. package/dist/environment-compatibility/appEnvironmentCompatibility.js.map +1 -0
  27. package/dist/environment-compatibility/appEnvironmentCompatibility.test.d.ts +2 -0
  28. package/dist/environment-compatibility/appEnvironmentCompatibility.test.d.ts.map +1 -0
  29. package/dist/environment-compatibility/appEnvironmentCompatibility.test.js +285 -0
  30. package/dist/environment-compatibility/appEnvironmentCompatibility.test.js.map +1 -0
  31. package/dist/errors/http.d.ts +15 -4
  32. package/dist/errors/http.d.ts.map +1 -1
  33. package/dist/errors/http.js +25 -7
  34. package/dist/errors/http.js.map +1 -1
  35. package/dist/errors/http.test.d.ts +2 -0
  36. package/dist/errors/http.test.d.ts.map +1 -0
  37. package/dist/errors/http.test.js +28 -0
  38. package/dist/errors/http.test.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +2 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/plugins/templates/restApiIntegration.d.ts.map +1 -1
  44. package/dist/plugins/templates/restApiIntegration.js +2 -0
  45. package/dist/plugins/templates/restApiIntegration.js.map +1 -1
  46. package/dist/plugins/templates/shared/auth.d.ts +3 -1
  47. package/dist/plugins/templates/shared/auth.d.ts.map +1 -1
  48. package/dist/plugins/templates/shared/auth.js +129 -17
  49. package/dist/plugins/templates/shared/auth.js.map +1 -1
  50. package/dist/plugins/templates/shared/auth.test.d.ts +2 -0
  51. package/dist/plugins/templates/shared/auth.test.d.ts.map +1 -0
  52. package/dist/plugins/templates/shared/auth.test.js +116 -0
  53. package/dist/plugins/templates/shared/auth.test.js.map +1 -0
  54. package/dist/plugins/templates/shared/restapiintegration.d.ts +2 -0
  55. package/dist/plugins/templates/shared/restapiintegration.d.ts.map +1 -1
  56. package/dist/plugins/templates/shared/restapiintegration.js +3 -1
  57. package/dist/plugins/templates/shared/restapiintegration.js.map +1 -1
  58. package/dist/socket/dist-entry.test.d.ts +2 -0
  59. package/dist/socket/dist-entry.test.d.ts.map +1 -0
  60. package/dist/socket/dist-entry.test.js +34 -0
  61. package/dist/socket/dist-entry.test.js.map +1 -0
  62. package/dist/socket/heartbeat.d.ts +258 -0
  63. package/dist/socket/heartbeat.d.ts.map +1 -0
  64. package/dist/socket/heartbeat.js +307 -0
  65. package/dist/socket/heartbeat.js.map +1 -0
  66. package/dist/socket/heartbeat.test.d.ts +2 -0
  67. package/dist/socket/heartbeat.test.d.ts.map +1 -0
  68. package/dist/socket/heartbeat.test.js +431 -0
  69. package/dist/socket/heartbeat.test.js.map +1 -0
  70. package/dist/socket/index.d.ts +1 -0
  71. package/dist/socket/index.d.ts.map +1 -1
  72. package/dist/socket/index.js +1 -0
  73. package/dist/socket/index.js.map +1 -1
  74. package/dist/socket/util.d.ts.map +1 -1
  75. package/dist/socket/util.js +15 -1
  76. package/dist/socket/util.js.map +1 -1
  77. package/dist/socket/util.test.js +12 -2
  78. package/dist/socket/util.test.js.map +1 -1
  79. package/dist/types/ai/index.d.ts +3 -0
  80. package/dist/types/ai/index.d.ts.map +1 -1
  81. package/dist/types/ai/index.js +3 -0
  82. package/dist/types/ai/index.js.map +1 -1
  83. package/dist/types/application/index.d.ts +12 -0
  84. package/dist/types/application/index.d.ts.map +1 -1
  85. package/dist/types/application/index.js.map +1 -1
  86. package/dist/types/codeSecurity/index.d.ts +55 -1
  87. package/dist/types/codeSecurity/index.d.ts.map +1 -1
  88. package/dist/types/codeSecurity/index.js +21 -1
  89. package/dist/types/codeSecurity/index.js.map +1 -1
  90. package/dist/types/codeSecurity/index.test.d.ts +2 -0
  91. package/dist/types/codeSecurity/index.test.d.ts.map +1 -0
  92. package/dist/types/codeSecurity/index.test.js +19 -0
  93. package/dist/types/codeSecurity/index.test.js.map +1 -0
  94. package/dist/types/datasource/auth.d.ts +12 -1
  95. package/dist/types/datasource/auth.d.ts.map +1 -1
  96. package/dist/types/datasource/auth.js +20 -2
  97. package/dist/types/datasource/auth.js.map +1 -1
  98. package/dist/types/datasource/auth.test.js +3 -1
  99. package/dist/types/datasource/auth.test.js.map +1 -1
  100. package/dist/types/group/index.d.ts +1 -3
  101. package/dist/types/group/index.d.ts.map +1 -1
  102. package/dist/types/group/index.js +1 -3
  103. package/dist/types/group/index.js.map +1 -1
  104. package/dist/types/integration/index.d.ts +11 -1
  105. package/dist/types/integration/index.d.ts.map +1 -1
  106. package/dist/types/integration/index.js +11 -1
  107. package/dist/types/integration/index.js.map +1 -1
  108. package/dist/types/plugin/form.d.ts +32 -0
  109. package/dist/types/plugin/form.d.ts.map +1 -1
  110. package/dist/types/plugin/form.js +73 -1
  111. package/dist/types/plugin/form.js.map +1 -1
  112. package/dist/types/plugin/form.test.js +128 -0
  113. package/dist/types/plugin/form.test.js.map +1 -1
  114. package/dist/types/profile/index.d.ts +16 -1
  115. package/dist/types/profile/index.d.ts.map +1 -1
  116. package/dist/types/profile/index.js +7 -1
  117. package/dist/types/profile/index.js.map +1 -1
  118. package/dist/types/rbac/index.d.ts +2 -0
  119. package/dist/types/rbac/index.d.ts.map +1 -1
  120. package/dist/types/rbac/index.js +2 -0
  121. package/dist/types/rbac/index.js.map +1 -1
  122. package/dist/types/response/GetRecentApplicationsResponseBody.d.ts +4 -0
  123. package/dist/types/response/GetRecentApplicationsResponseBody.d.ts.map +1 -0
  124. package/dist/types/response/GetRecentApplicationsResponseBody.js +3 -0
  125. package/dist/types/response/GetRecentApplicationsResponseBody.js.map +1 -0
  126. package/dist/types/response/index.d.ts +1 -0
  127. package/dist/types/response/index.d.ts.map +1 -1
  128. package/dist/types/response/index.js +1 -0
  129. package/dist/types/response/index.js.map +1 -1
  130. package/dist-esm/database-lifecycle/appDatabaseCompatibility.d.ts +49 -0
  131. package/dist-esm/database-lifecycle/appDatabaseCompatibility.d.ts.map +1 -0
  132. package/dist-esm/database-lifecycle/appDatabaseCompatibility.js +28 -0
  133. package/dist-esm/database-lifecycle/appDatabaseCompatibility.js.map +1 -0
  134. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.d.ts +2 -0
  135. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.d.ts.map +1 -0
  136. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.js +45 -0
  137. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.js.map +1 -0
  138. package/dist-esm/database-lifecycle/destructiveMigrations.d.ts +12 -0
  139. package/dist-esm/database-lifecycle/destructiveMigrations.d.ts.map +1 -1
  140. package/dist-esm/database-lifecycle/destructiveMigrations.js +113 -0
  141. package/dist-esm/database-lifecycle/destructiveMigrations.js.map +1 -1
  142. package/dist-esm/database-lifecycle/destructiveMigrations.test.js +80 -1
  143. package/dist-esm/database-lifecycle/destructiveMigrations.test.js.map +1 -1
  144. package/dist-esm/database-lifecycle/index.d.ts +46 -2
  145. package/dist-esm/database-lifecycle/index.d.ts.map +1 -1
  146. package/dist-esm/database-lifecycle/index.js +123 -1
  147. package/dist-esm/database-lifecycle/index.js.map +1 -1
  148. package/dist-esm/database-lifecycle/providerDiagnostics.test.d.ts +2 -0
  149. package/dist-esm/database-lifecycle/providerDiagnostics.test.d.ts.map +1 -0
  150. package/dist-esm/database-lifecycle/providerDiagnostics.test.js +117 -0
  151. package/dist-esm/database-lifecycle/providerDiagnostics.test.js.map +1 -0
  152. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.d.ts +65 -0
  153. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.d.ts.map +1 -0
  154. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.js +79 -0
  155. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.js.map +1 -0
  156. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.d.ts +2 -0
  157. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.d.ts.map +1 -0
  158. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.js +283 -0
  159. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.js.map +1 -0
  160. package/dist-esm/errors/http.d.ts +15 -4
  161. package/dist-esm/errors/http.d.ts.map +1 -1
  162. package/dist-esm/errors/http.js +22 -6
  163. package/dist-esm/errors/http.js.map +1 -1
  164. package/dist-esm/errors/http.test.d.ts +2 -0
  165. package/dist-esm/errors/http.test.d.ts.map +1 -0
  166. package/dist-esm/errors/http.test.js +26 -0
  167. package/dist-esm/errors/http.test.js.map +1 -0
  168. package/dist-esm/index.d.ts +2 -0
  169. package/dist-esm/index.d.ts.map +1 -1
  170. package/dist-esm/index.js +2 -0
  171. package/dist-esm/index.js.map +1 -1
  172. package/dist-esm/plugins/templates/restApiIntegration.d.ts.map +1 -1
  173. package/dist-esm/plugins/templates/restApiIntegration.js +2 -0
  174. package/dist-esm/plugins/templates/restApiIntegration.js.map +1 -1
  175. package/dist-esm/plugins/templates/shared/auth.d.ts +3 -1
  176. package/dist-esm/plugins/templates/shared/auth.d.ts.map +1 -1
  177. package/dist-esm/plugins/templates/shared/auth.js +129 -17
  178. package/dist-esm/plugins/templates/shared/auth.js.map +1 -1
  179. package/dist-esm/plugins/templates/shared/auth.test.d.ts +2 -0
  180. package/dist-esm/plugins/templates/shared/auth.test.d.ts.map +1 -0
  181. package/dist-esm/plugins/templates/shared/auth.test.js +114 -0
  182. package/dist-esm/plugins/templates/shared/auth.test.js.map +1 -0
  183. package/dist-esm/plugins/templates/shared/restapiintegration.d.ts +2 -0
  184. package/dist-esm/plugins/templates/shared/restapiintegration.d.ts.map +1 -1
  185. package/dist-esm/plugins/templates/shared/restapiintegration.js +3 -1
  186. package/dist-esm/plugins/templates/shared/restapiintegration.js.map +1 -1
  187. package/dist-esm/socket/dist-entry.test.d.ts +2 -0
  188. package/dist-esm/socket/dist-entry.test.d.ts.map +1 -0
  189. package/dist-esm/socket/dist-entry.test.js +29 -0
  190. package/dist-esm/socket/dist-entry.test.js.map +1 -0
  191. package/dist-esm/socket/heartbeat.d.ts +258 -0
  192. package/dist-esm/socket/heartbeat.d.ts.map +1 -0
  193. package/dist-esm/socket/heartbeat.js +303 -0
  194. package/dist-esm/socket/heartbeat.js.map +1 -0
  195. package/dist-esm/socket/heartbeat.test.d.ts +2 -0
  196. package/dist-esm/socket/heartbeat.test.d.ts.map +1 -0
  197. package/dist-esm/socket/heartbeat.test.js +429 -0
  198. package/dist-esm/socket/heartbeat.test.js.map +1 -0
  199. package/dist-esm/socket/index.d.ts +1 -0
  200. package/dist-esm/socket/index.d.ts.map +1 -1
  201. package/dist-esm/socket/index.js +1 -0
  202. package/dist-esm/socket/index.js.map +1 -1
  203. package/dist-esm/socket/util.d.ts.map +1 -1
  204. package/dist-esm/socket/util.js +15 -1
  205. package/dist-esm/socket/util.js.map +1 -1
  206. package/dist-esm/socket/util.test.js +12 -2
  207. package/dist-esm/socket/util.test.js.map +1 -1
  208. package/dist-esm/types/ai/index.d.ts +3 -0
  209. package/dist-esm/types/ai/index.d.ts.map +1 -1
  210. package/dist-esm/types/ai/index.js +3 -0
  211. package/dist-esm/types/ai/index.js.map +1 -1
  212. package/dist-esm/types/application/index.d.ts +12 -0
  213. package/dist-esm/types/application/index.d.ts.map +1 -1
  214. package/dist-esm/types/application/index.js.map +1 -1
  215. package/dist-esm/types/codeSecurity/index.d.ts +55 -1
  216. package/dist-esm/types/codeSecurity/index.d.ts.map +1 -1
  217. package/dist-esm/types/codeSecurity/index.js +17 -1
  218. package/dist-esm/types/codeSecurity/index.js.map +1 -1
  219. package/dist-esm/types/codeSecurity/index.test.d.ts +2 -0
  220. package/dist-esm/types/codeSecurity/index.test.d.ts.map +1 -0
  221. package/dist-esm/types/codeSecurity/index.test.js +17 -0
  222. package/dist-esm/types/codeSecurity/index.test.js.map +1 -0
  223. package/dist-esm/types/datasource/auth.d.ts +12 -1
  224. package/dist-esm/types/datasource/auth.d.ts.map +1 -1
  225. package/dist-esm/types/datasource/auth.js +19 -2
  226. package/dist-esm/types/datasource/auth.js.map +1 -1
  227. package/dist-esm/types/datasource/auth.test.js +3 -1
  228. package/dist-esm/types/datasource/auth.test.js.map +1 -1
  229. package/dist-esm/types/group/index.d.ts +1 -3
  230. package/dist-esm/types/group/index.d.ts.map +1 -1
  231. package/dist-esm/types/group/index.js +1 -3
  232. package/dist-esm/types/group/index.js.map +1 -1
  233. package/dist-esm/types/integration/index.d.ts +11 -1
  234. package/dist-esm/types/integration/index.d.ts.map +1 -1
  235. package/dist-esm/types/integration/index.js +11 -1
  236. package/dist-esm/types/integration/index.js.map +1 -1
  237. package/dist-esm/types/plugin/form.d.ts +32 -0
  238. package/dist-esm/types/plugin/form.d.ts.map +1 -1
  239. package/dist-esm/types/plugin/form.js +68 -0
  240. package/dist-esm/types/plugin/form.js.map +1 -1
  241. package/dist-esm/types/plugin/form.test.js +129 -1
  242. package/dist-esm/types/plugin/form.test.js.map +1 -1
  243. package/dist-esm/types/profile/index.d.ts +16 -1
  244. package/dist-esm/types/profile/index.d.ts.map +1 -1
  245. package/dist-esm/types/profile/index.js +7 -1
  246. package/dist-esm/types/profile/index.js.map +1 -1
  247. package/dist-esm/types/rbac/index.d.ts +2 -0
  248. package/dist-esm/types/rbac/index.d.ts.map +1 -1
  249. package/dist-esm/types/rbac/index.js +2 -0
  250. package/dist-esm/types/rbac/index.js.map +1 -1
  251. package/dist-esm/types/response/GetRecentApplicationsResponseBody.d.ts +4 -0
  252. package/dist-esm/types/response/GetRecentApplicationsResponseBody.d.ts.map +1 -0
  253. package/dist-esm/types/response/GetRecentApplicationsResponseBody.js +2 -0
  254. package/dist-esm/types/response/GetRecentApplicationsResponseBody.js.map +1 -0
  255. package/dist-esm/types/response/index.d.ts +1 -0
  256. package/dist-esm/types/response/index.d.ts.map +1 -1
  257. package/dist-esm/types/response/index.js +1 -0
  258. package/dist-esm/types/response/index.js.map +1 -1
  259. package/package.json +1 -1
  260. package/src/database-lifecycle/appDatabaseCompatibility.test.ts +55 -0
  261. package/src/database-lifecycle/appDatabaseCompatibility.ts +62 -0
  262. package/src/database-lifecycle/destructiveMigrations.test.ts +108 -1
  263. package/src/database-lifecycle/destructiveMigrations.ts +129 -0
  264. package/src/database-lifecycle/index.ts +173 -0
  265. package/src/database-lifecycle/providerDiagnostics.test.ts +134 -0
  266. package/src/environment-compatibility/appEnvironmentCompatibility.test.ts +326 -0
  267. package/src/environment-compatibility/appEnvironmentCompatibility.ts +173 -0
  268. package/src/errors/http.test.ts +32 -0
  269. package/src/errors/http.ts +24 -6
  270. package/src/index.ts +2 -0
  271. package/src/plugins/templates/restApiIntegration.ts +2 -0
  272. package/src/plugins/templates/shared/auth.test.ts +162 -0
  273. package/src/plugins/templates/shared/auth.ts +135 -18
  274. package/src/plugins/templates/shared/restapiintegration.ts +3 -1
  275. package/src/socket/dist-entry.test.ts +29 -0
  276. package/src/socket/heartbeat.test.ts +538 -0
  277. package/src/socket/heartbeat.ts +469 -0
  278. package/src/socket/index.ts +1 -0
  279. package/src/socket/util.test.ts +14 -2
  280. package/src/socket/util.ts +15 -1
  281. package/src/types/ai/index.ts +3 -0
  282. package/src/types/application/index.ts +14 -0
  283. package/src/types/codeSecurity/index.test.ts +21 -0
  284. package/src/types/codeSecurity/index.ts +83 -1
  285. package/src/types/datasource/auth.test.ts +3 -1
  286. package/src/types/datasource/auth.ts +24 -3
  287. package/src/types/group/index.ts +1 -3
  288. package/src/types/integration/index.ts +14 -0
  289. package/src/types/plugin/form.test.ts +174 -1
  290. package/src/types/plugin/form.ts +100 -2
  291. package/src/types/profile/index.ts +19 -1
  292. package/src/types/rbac/index.ts +2 -0
  293. package/src/types/response/GetRecentApplicationsResponseBody.ts +4 -0
  294. package/src/types/response/index.ts +1 -0
@@ -2,6 +2,8 @@
2
2
  // server handlers and the UI so the two can't drift. The taxonomy below is
3
3
  // mirrored by the PackageVulnerability DB entity (its columns import these).
4
4
 
5
+ import semver from 'semver';
6
+
5
7
  export type Ecosystem = 'npm';
6
8
  export type VulnerabilitySource = 'osv';
7
9
  export type AdvisoryKind = 'vulnerability' | 'malware';
@@ -13,7 +15,7 @@ export type SeverityLevel = (typeof SEVERITY_LEVELS)[number];
13
15
 
14
16
  // needs_review: version couldn't be pinned, so a "clear" verdict would be unearned.
15
17
  export type DependencyScanStatus = 'clear' | 'needs_review' | 'unresolved';
16
- export const DEPENDENCY_SCAN_DATE_FILTERS = ['all', 'today', '-7d', '-30d', 'ytd'] as const;
18
+ export const DEPENDENCY_SCAN_DATE_FILTERS = ['all', 'none', 'today', '-7d', '-30d', 'ytd'] as const;
17
19
  export type DependencyScanDateFilter = (typeof DEPENDENCY_SCAN_DATE_FILTERS)[number];
18
20
  export type DependencyScanOrder = 'asc' | 'desc';
19
21
  export const DEPENDENCY_SCAN_SORTS = ['severity', 'last_updated', 'last_published'] as const;
@@ -26,6 +28,21 @@ export function parseDependencyScanDateFilter(value: string | null | undefined):
26
28
  return 'all';
27
29
  }
28
30
 
31
+ // Pins a package usage row to the single version the org scan evaluates it
32
+ // against: the resolved version when we have one, otherwise the minimum
33
+ // version satisfying the declared range. Shared between the server (which
34
+ // produces AdvisoryDetail.currentVersion this way) and the UI (which must key
35
+ // its own package rows identically to look advisories back up) so the two
36
+ // can't drift into looking up different version strings for the same package.
37
+ export function resolveScannedPackageVersion(declared: string, resolved: string | null | undefined): string | null {
38
+ const source = resolved && resolved.length > 0 ? resolved : declared;
39
+ try {
40
+ return semver.minVersion(source)?.version ?? null;
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+
29
46
  export interface AdvisoryDetail {
30
47
  advisoryId: string;
31
48
  source: VulnerabilitySource;
@@ -63,3 +80,68 @@ export interface DependencyScanSummary {
63
80
  publishedWithVulns: number;
64
81
  totalProjects: number;
65
82
  }
83
+
84
+ // Wire contract for GET /api/v2/applications/package-usage, backed by the
85
+ // application_package_usage table: one row per (application, commit,
86
+ // package). Shared so the server handler and the UI's SBOM view can't drift.
87
+ export interface AppPackageUsageItem {
88
+ application_id: string;
89
+ application_name: string;
90
+ commit_id: string;
91
+ commit_message: string | null;
92
+ is_deployed: boolean;
93
+ package_name: string;
94
+ package_version_declared: string;
95
+ package_version_resolved: string | null;
96
+ dependency_source: string | null;
97
+ indexed_at: string;
98
+ }
99
+
100
+ export interface AppPackageUsageResponse {
101
+ source: 'all' | 'deployed' | 'not_deployed';
102
+ deployed_filter: boolean | null;
103
+ package_name: string | null;
104
+ application_id: string | null;
105
+ commit_id: string | null;
106
+ package_version_declared: string | null;
107
+ package_version_resolved: string | null;
108
+ dependency_source: string | null;
109
+ limit: number;
110
+ offset: number;
111
+ total: number;
112
+ items: AppPackageUsageItem[];
113
+ }
114
+
115
+ // Minimal CycloneDX 1.5 JSON document, hand-built server-side from
116
+ // application_package_usage rows for one (application, commit) — see
117
+ // service/codeSecurity/sbom.ts. Only the fields this feature populates are
118
+ // modeled; CycloneDX defines many more optional fields we don't emit.
119
+ export interface CycloneDxProperty {
120
+ name: string;
121
+ value: string;
122
+ }
123
+
124
+ export interface CycloneDxComponent {
125
+ type: 'library';
126
+ name: string;
127
+ version: string;
128
+ purl: string;
129
+ properties: CycloneDxProperty[];
130
+ }
131
+
132
+ export interface CycloneDxBom {
133
+ bomFormat: 'CycloneDX';
134
+ specVersion: '1.5';
135
+ serialNumber: string;
136
+ version: 1;
137
+ metadata: {
138
+ timestamp: string;
139
+ component: {
140
+ type: 'application';
141
+ name: string;
142
+ version: string;
143
+ 'bom-ref': string;
144
+ };
145
+ };
146
+ components: CycloneDxComponent[];
147
+ }
@@ -148,10 +148,12 @@ describe('extractPublic normalizes boolean tokenScope for OAUTH2_CODE', () => {
148
148
  test('preserves the PKCE marker', () => {
149
149
  const result = extractPublic(IntegrationAuthType.OAUTH2_CODE, {
150
150
  clientId: 'public-client',
151
- usePkce: true
151
+ usePkce: true,
152
+ usePkceClientSecret: 'true'
152
153
  });
153
154
 
154
155
  expect(result.usePkce).toBe(true);
156
+ expect(result.usePkceClientSecret).toBe(true);
155
157
  });
156
158
 
157
159
  test('normalizes boolean true tokenScope to TokenScope.DATASOURCE', () => {
@@ -18,6 +18,23 @@ export function getOAuthCodeVerifierStorageKey(oneTimeCode: string): string {
18
18
  return `${LS_OAUTH_CODE_VERIFIER_PREFIX}:${oneTimeCode}`;
19
19
  }
20
20
 
21
+ /**
22
+ * Persisted integration configuration stores some booleans as strings or
23
+ * numbers, because form controls and older writers coerced them on the way in
24
+ * (hence the `FakeBoolean` fields below). Returns the boolean such a value
25
+ * stands for, or `undefined` when it stands for neither and the caller has to
26
+ * decide what an unrecognized value means.
27
+ */
28
+ export function asFakeBoolean(value: unknown): boolean | undefined {
29
+ if (value === true || value === 'true' || value === 1 || value === '1') {
30
+ return true;
31
+ }
32
+ if (value === false || value === 'false' || value === 0 || value === '0' || value === '' || value === null || value === undefined) {
33
+ return false;
34
+ }
35
+ return undefined;
36
+ }
37
+
21
38
  /**
22
39
  * `usePkce` is typed as a boolean but reaches us from persisted integration
23
40
  * configuration, where a form checkbox can store it as the string `'true'`.
@@ -25,7 +42,7 @@ export function getOAuthCodeVerifierStorageKey(oneTimeCode: string): string {
25
42
  * sites disagree about whether PKCE is on.
26
43
  */
27
44
  export function isPkceEnabled(usePkce: unknown): boolean {
28
- return usePkce === true || usePkce === 'true' || usePkce === 1 || usePkce === '1';
45
+ return asFakeBoolean(usePkce) === true;
29
46
  }
30
47
 
31
48
  export type AuthId = string;
@@ -344,13 +361,15 @@ type PublicOAuthCodeConfig = {
344
361
  userEmail?: string; // Used by integrations that need user identity (e.g., Lakebase Token Federation)
345
362
  sendOAuthState?: boolean;
346
363
  usePkce?: boolean;
364
+ usePkceClientSecret?: boolean;
347
365
  };
348
366
 
349
367
  // Persisted configuration can hold the PKCE marker as a string, so the stored
350
368
  // shape is wider than the public one that `extractPublic` normalizes it into.
351
- type OAuthCodeConfig = Omit<PublicOAuthCodeConfig, 'usePkce'> & {
369
+ type OAuthCodeConfig = Omit<PublicOAuthCodeConfig, 'usePkce' | 'usePkceClientSecret'> & {
352
370
  clientSecret?: string;
353
371
  usePkce?: FakeBoolean;
372
+ usePkceClientSecret?: FakeBoolean;
354
373
  };
355
374
 
356
375
  export enum TokenScope {
@@ -444,7 +463,8 @@ export const extractPublic = (authType: AuthType | undefined, authConfig: AuthCo
444
463
  tokenScope: normalizeTokenScope(authConfig?.tokenScope),
445
464
  promptType: authConfig?.promptType,
446
465
  sendOAuthState: authConfig?.sendOAuthState,
447
- usePkce: isPkceEnabled(authConfig?.usePkce)
466
+ usePkce: isPkceEnabled(authConfig?.usePkce),
467
+ usePkceClientSecret: isPkceEnabled(authConfig?.usePkceClientSecret)
448
468
  };
449
469
  case IntegrationAuthType.OAUTH2_IMPLICIT:
450
470
  return {
@@ -609,6 +629,7 @@ export type DatasourceAuthState = DatasourceOneTimeState & {
609
629
  scope: string | undefined;
610
630
  clientAuthMethod?: ClientAuthMethod;
611
631
  usePkce?: boolean;
632
+ usePkceClientSecret?: boolean;
612
633
  };
613
634
  origin: string;
614
635
  };
@@ -1,9 +1,7 @@
1
1
  import { AssignmentDto } from '../rbac/index.js';
2
2
 
3
3
  /**
4
- * This enum is used in DB. DO NOT CHANGE the existing values. It is also
5
- * indirectly referenced in the authorization.polar file, so references there
6
- * need to be updated if this changes.
4
+ * This enum is used in DB. DO NOT CHANGE the existing values.
7
5
  */
8
6
  export enum GroupType {
9
7
  ALL_USERS = 0,
@@ -104,6 +104,14 @@ export class SupersetIntegrationDto extends IntegrationBaseDto {
104
104
  created?: Date;
105
105
  updated?: Date;
106
106
  configurations: IntegrationConfigurationDto[];
107
+ /**
108
+ * Which data tags this integration is configured for, and whether it has a default
109
+ * configuration that covers any other tag. Reported separately from `configurations` because
110
+ * those bodies hold secrets and are withheld from callers who cannot edit the integration,
111
+ * while the coverage itself is not sensitive.
112
+ */
113
+ configuredProfileKeys: string[];
114
+ hasDefaultConfiguration: boolean;
107
115
  slug?: string;
108
116
  ownerEmail?: string;
109
117
  readOnly: boolean;
@@ -123,7 +131,9 @@ export class SupersetIntegrationDto extends IntegrationBaseDto {
123
131
  kind,
124
132
  organizationId,
125
133
  configurations,
134
+ configuredProfileKeys,
126
135
  demoIntegrationId,
136
+ hasDefaultConfiguration,
127
137
  isUserConfigured,
128
138
  ownerEmail,
129
139
  slug,
@@ -145,6 +155,8 @@ export class SupersetIntegrationDto extends IntegrationBaseDto {
145
155
  kind: IntegrationKind;
146
156
  organizationId: string;
147
157
  configurations: IntegrationConfigurationDto[];
158
+ configuredProfileKeys?: string[];
159
+ hasDefaultConfiguration?: boolean;
148
160
  demoIntegrationId?: string;
149
161
  isUserConfigured: boolean;
150
162
  ownerEmail?: string;
@@ -168,6 +180,8 @@ export class SupersetIntegrationDto extends IntegrationBaseDto {
168
180
  this.organizationId = organizationId;
169
181
  this.applicationId = applicationId;
170
182
  this.configurations = configurations;
183
+ this.configuredProfileKeys = configuredProfileKeys ?? [];
184
+ this.hasDefaultConfiguration = hasDefaultConfiguration ?? false;
171
185
  this.demoIntegrationId = demoIntegrationId;
172
186
  this.isUserConfigured = isUserConfigured;
173
187
  this.managedBy = managedBy;
@@ -1,6 +1,13 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { FormComponentType, getDisplayOnlyFieldNames } from './form.js';
3
+ import { IntegrationAuthType } from '../datasource/index.js';
4
+ import {
5
+ FormComponentType,
6
+ assertPkcePrerequisites,
7
+ assertSelectedDropdownOptionsSupported,
8
+ getDisplayOnlyFieldNames,
9
+ isDropdownOptionSupported
10
+ } from './form.js';
4
11
  import type { FormTemplate } from './form.js';
5
12
 
6
13
  describe('getDisplayOnlyFieldNames', () => {
@@ -159,3 +166,169 @@ describe('getDisplayOnlyFieldNames', () => {
159
166
  expect(result.has('path')).toBe(false);
160
167
  });
161
168
  });
169
+
170
+ describe('isDropdownOptionSupported', () => {
171
+ it('includes versioned options only within their supported range', () => {
172
+ const option = {
173
+ key: 'versioned',
174
+ value: 'versioned',
175
+ startVersion: '0.0.16',
176
+ endVersion: '0.0.20'
177
+ };
178
+
179
+ expect(isDropdownOptionSupported(option, '0.0.15')).toBe(false);
180
+ expect(isDropdownOptionSupported(option, '0.0.16')).toBe(true);
181
+ expect(isDropdownOptionSupported(option, '0.0.20')).toBe(true);
182
+ expect(isDropdownOptionSupported(option, '0.0.21')).toBe(false);
183
+ });
184
+ });
185
+
186
+ describe('assertPkcePrerequisites', () => {
187
+ const authCode = { authType: IntegrationAuthType.OAUTH2_CODE };
188
+
189
+ it('rejects PKCE with the OAuth state parameter turned off', () => {
190
+ expect(() => assertPkcePrerequisites({ ...authCode, 'authConfig.usePkce': true, 'authConfig.sendOAuthState': false })).toThrow(
191
+ 'PKCE requires the OAuth state parameter to be enabled.'
192
+ );
193
+ });
194
+
195
+ it('rejects a stringified PKCE marker with the state parameter turned off', () => {
196
+ expect(() => assertPkcePrerequisites({ ...authCode, 'authConfig.usePkce': 'true' })).toThrow(
197
+ 'PKCE requires the OAuth state parameter to be enabled.'
198
+ );
199
+ });
200
+
201
+ it('rejects a stringified state parameter that stands for false', () => {
202
+ // Checkboxes persist booleans as strings in older configs. The string
203
+ // 'false' is truthy, so a plain truthiness check would let this through
204
+ // at save time only for the login flow to refuse it later.
205
+ expect(() => assertPkcePrerequisites({ ...authCode, 'authConfig.usePkce': true, 'authConfig.sendOAuthState': 'false' })).toThrow(
206
+ 'PKCE requires the OAuth state parameter to be enabled.'
207
+ );
208
+ });
209
+
210
+ it('accepts PKCE with the state parameter on', () => {
211
+ expect(() => assertPkcePrerequisites({ ...authCode, 'authConfig.usePkce': true, 'authConfig.sendOAuthState': true })).not.toThrow();
212
+ });
213
+
214
+ it('accepts a stringified state parameter that stands for true', () => {
215
+ expect(() => assertPkcePrerequisites({ ...authCode, 'authConfig.usePkce': true, 'authConfig.sendOAuthState': 'true' })).not.toThrow();
216
+ });
217
+
218
+ it('leaves ordinary OAuth alone', () => {
219
+ expect(() => assertPkcePrerequisites({ ...authCode, 'authConfig.sendOAuthState': false })).not.toThrow();
220
+ });
221
+
222
+ it('ignores a leftover PKCE marker on another auth type', () => {
223
+ // The guard runs on raw form values before dependency clearing, so a
224
+ // stale usePkce from an earlier authorization-code setup must not block
225
+ // saving an integration that switched to a different auth type.
226
+ expect(() =>
227
+ assertPkcePrerequisites({ authType: 'basic', 'authConfig.usePkce': true, 'authConfig.sendOAuthState': false })
228
+ ).not.toThrow();
229
+ });
230
+ });
231
+
232
+ describe('assertSelectedDropdownOptionsSupported', () => {
233
+ const template: FormTemplate = {
234
+ sections: [
235
+ {
236
+ name: 'auth',
237
+ items: [
238
+ {
239
+ name: 'authType',
240
+ secondaryName: 'usePkce',
241
+ label: 'Authentication method',
242
+ startVersion: '0.0.1',
243
+ componentType: FormComponentType.DROPDOWN,
244
+ options: [
245
+ { key: 'basic', value: 'basic' },
246
+ { key: 'oauth', value: 'oauth' },
247
+ { key: 'pkce', value: 'oauth', secondaryValue: true, startVersion: '0.0.16' }
248
+ ]
249
+ }
250
+ ]
251
+ }
252
+ ]
253
+ };
254
+
255
+ it('rejects an unrecognized secondary value instead of skipping version validation', () => {
256
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce: 'maybe' }, template, '0.0.15')).toThrow(
257
+ 'The selected authentication method is invalid.'
258
+ );
259
+ });
260
+
261
+ it.each([
262
+ ['undefined', undefined],
263
+ ['null', null],
264
+ ['false', false],
265
+ ['empty string', ''],
266
+ ['the string false', 'false'],
267
+ ['zero', 0],
268
+ ['the string zero', '0']
269
+ ] as const)('accepts the plain option when the secondary marker is %s', (_label, usePkce) => {
270
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce }, template, '0.0.15')).not.toThrow();
271
+ });
272
+
273
+ // A marker that round-tripped through a form control comes back as a string
274
+ // or a number. The runtime reads it as PKCE on, so the form has to agree:
275
+ // it is the same selection, and the same version gate applies to it.
276
+ it.each([
277
+ ['the string true', 'true'],
278
+ ['one', 1],
279
+ ['the string one', '1']
280
+ ] as const)('gates the secondary option on version when the marker is %s', (_label, usePkce) => {
281
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce }, template, '0.0.15')).toThrow(
282
+ 'The selected authentication method requires a newer agent version.'
283
+ );
284
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce }, template, '0.0.16')).not.toThrow();
285
+ });
286
+
287
+ it('accepts the plain option when the secondary marker is absent', () => {
288
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth' }, template, '0.0.15')).not.toThrow();
289
+ });
290
+
291
+ it('ignores a stale secondary marker for a primary option that does not use it', () => {
292
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'basic', usePkce: true }, template, '0.0.15')).not.toThrow();
293
+ });
294
+
295
+ it('rejects the secondary option when the plugin version is too old', () => {
296
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce: true }, template, '0.0.15')).toThrow(
297
+ 'The selected authentication method requires a newer agent version.'
298
+ );
299
+ });
300
+
301
+ it('rejects the secondary option when agent support is unreported', () => {
302
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce: true }, template, '0.0.1')).toThrow(
303
+ 'Cannot verify that the connected agent supports the selected authentication method.'
304
+ );
305
+ });
306
+
307
+ it('rejects a version-gated option when its minimum equals the unreported fallback', () => {
308
+ const fallbackGatedTemplate: FormTemplate = {
309
+ sections: [
310
+ {
311
+ name: 'auth',
312
+ items: [
313
+ {
314
+ name: 'authType',
315
+ secondaryName: 'usePkce',
316
+ label: 'Authentication method',
317
+ startVersion: '0.0.1',
318
+ componentType: FormComponentType.DROPDOWN,
319
+ options: [{ key: 'pkce', value: 'oauth', secondaryValue: true, startVersion: '0.0.1' }]
320
+ }
321
+ ]
322
+ }
323
+ ]
324
+ };
325
+
326
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce: true }, fallbackGatedTemplate, '0.0.1')).toThrow(
327
+ 'Cannot verify that the connected agent supports the selected authentication method.'
328
+ );
329
+ });
330
+
331
+ it('accepts the secondary option once the plugin version supports it', () => {
332
+ expect(() => assertSelectedDropdownOptionsSupported({ authType: 'oauth', usePkce: true }, template, '0.0.16')).not.toThrow();
333
+ });
334
+ });
@@ -1,6 +1,15 @@
1
1
  import { AuthorizationExtraParams, AuthorizationStateConfig, ClientAuthMethod } from '../../plugins/index.js';
2
- import { AuthConfig, AuthType, DynamicWorkflowConfig, TokenScope } from '../datasource/index.js';
3
- import { AgentType } from '../organization/index.js';
2
+ import {
3
+ asFakeBoolean,
4
+ AuthConfig,
5
+ AuthType,
6
+ DynamicWorkflowConfig,
7
+ IntegrationAuthType,
8
+ isPkceEnabled,
9
+ TokenScope
10
+ } from '../datasource/index.js';
11
+ import { AgentType, compareSemVer } from '../organization/index.js';
12
+ import { VERSION_INITIAL } from './index.js';
4
13
 
5
14
  export interface FormTemplate {
6
15
  sections: FormSection[];
@@ -372,6 +381,7 @@ type ConnectOAuthPayload = {
372
381
  tokenScope: TokenScope;
373
382
  clientAuthMethod?: ClientAuthMethod;
374
383
  usePkce?: boolean;
384
+ usePkceClientSecret?: boolean;
375
385
  };
376
386
  dynamicWorkflowConfiguration?: DynamicWorkflowConfig;
377
387
  };
@@ -465,6 +475,10 @@ export const getDisplayOnlyFieldNames = (template: FormTemplate): Set<string> =>
465
475
  export interface DropdownOption {
466
476
  key: string;
467
477
  value: string;
478
+ disabled?: boolean;
479
+ startVersion?: string;
480
+ endVersion?: string;
481
+ secondaryValue?: InitialValue;
468
482
  enumValue?: number;
469
483
  displayName?: string;
470
484
  subText?: string;
@@ -479,3 +493,87 @@ export interface DropdownOption {
479
493
  prefixWidth?: number;
480
494
  hasDivider?: boolean;
481
495
  }
496
+
497
+ export const isDropdownOptionSupported = (option: DropdownOption, pluginVersion: string): boolean =>
498
+ (!option.startVersion || compareSemVer(option.startVersion, pluginVersion) <= 0) &&
499
+ (!option.endVersion || compareSemVer(option.endVersion, pluginVersion) >= 0);
500
+
501
+ /**
502
+ * Options carry their marker as a real boolean, but the same marker can come
503
+ * back from persisted configuration as a string or a number. Both sides go
504
+ * through the coercion the runtime reads use (`isPkceEnabled`) so the form and
505
+ * the runtime cannot disagree about which option is selected. A value that
506
+ * stands for neither boolean is compared as-is, so an unrecognized marker
507
+ * still fails validation instead of matching the option that leaves the
508
+ * marker unset.
509
+ */
510
+ const normalizeSecondaryValue = (value: unknown): unknown => asFakeBoolean(value) ?? value;
511
+
512
+ /**
513
+ * Find the option a dropdown currently has selected. Options can share a value
514
+ * and differ only by the secondary marker they set (ordinary versus PKCE
515
+ * authorization code), so both have to be compared to tell them apart.
516
+ */
517
+ export function findSelectedDropdownOption(
518
+ item: { name: string; options: DropdownOption[]; secondaryName?: string },
519
+ formValues: Record<string, unknown>
520
+ ): DropdownOption | undefined {
521
+ const optionsForValue = item.options.filter((option) => option.value === formValues[item.name]);
522
+ const usesSecondaryValue = optionsForValue.some((option) => option.secondaryValue !== undefined);
523
+
524
+ return optionsForValue.find(
525
+ (option) =>
526
+ !item.secondaryName ||
527
+ !usesSecondaryValue ||
528
+ normalizeSecondaryValue(option.secondaryValue) === normalizeSecondaryValue(formValues[item.secondaryName])
529
+ );
530
+ }
531
+
532
+ export const PKCE_STATE_PARAMETER_REQUIRED_MESSAGE = 'PKCE requires the OAuth state parameter to be enabled.';
533
+
534
+ /**
535
+ * PKCE correlates its verifier through the OAuth state parameter, so a PKCE
536
+ * integration with state turned off cannot log in at all. The login modal
537
+ * refuses that combination with the same wording; refusing it at save means it
538
+ * never gets persisted and the user learns about it while they can still fix
539
+ * it.
540
+ *
541
+ * Runs on raw form values before dependency clearing, so the auth type has to
542
+ * be checked here: a leftover PKCE marker from an earlier authorization-code
543
+ * setup must not block saving under a different auth type. The state value is
544
+ * read through asFakeBoolean because older configs persist it as a string,
545
+ * where a plain truthiness check reads 'false' as on.
546
+ */
547
+ export function assertPkcePrerequisites(formValues: Record<string, unknown>): void {
548
+ if (
549
+ formValues['authType'] === IntegrationAuthType.OAUTH2_CODE &&
550
+ isPkceEnabled(formValues['authConfig.usePkce']) &&
551
+ asFakeBoolean(formValues['authConfig.sendOAuthState']) !== true
552
+ ) {
553
+ throw new Error(PKCE_STATE_PARAMETER_REQUIRED_MESSAGE);
554
+ }
555
+ }
556
+
557
+ export function assertSelectedDropdownOptionsSupported(
558
+ formValues: Record<string, unknown>,
559
+ template: FormTemplate | undefined,
560
+ pluginVersion: string
561
+ ): void {
562
+ for (const section of template?.sections ?? []) {
563
+ for (const sectionItem of section.items) {
564
+ for (const item of getRowItemsFromSectionItem(sectionItem)) {
565
+ if (!('options' in item)) continue;
566
+ const selectedOption = findSelectedDropdownOption(item, formValues);
567
+ if (!selectedOption && item.options.some((option) => option.value === formValues[item.name])) {
568
+ throw new Error('The selected authentication method is invalid.');
569
+ }
570
+ if (selectedOption?.startVersion && pluginVersion === VERSION_INITIAL) {
571
+ throw new Error('Cannot verify that the connected agent supports the selected authentication method.');
572
+ }
573
+ if (selectedOption && !isDropdownOptionSupported(selectedOption, pluginVersion)) {
574
+ throw new Error('The selected authentication method requires a newer agent version.');
575
+ }
576
+ }
577
+ }
578
+ }
579
+ }
@@ -14,6 +14,9 @@ export class Profile {
14
14
  allowedInEditor?: boolean;
15
15
  allowedInPreview?: boolean;
16
16
  allowedInDeployed?: boolean;
17
+ defaultInEditor?: boolean;
18
+ defaultInPreview?: boolean;
19
+ defaultInDeployed?: boolean;
17
20
 
18
21
  constructor({
19
22
  id,
@@ -23,7 +26,10 @@ export class Profile {
23
26
  type,
24
27
  allowedInEditor,
25
28
  allowedInPreview,
26
- allowedInDeployed
29
+ allowedInDeployed,
30
+ defaultInEditor,
31
+ defaultInPreview,
32
+ defaultInDeployed
27
33
  }: {
28
34
  id: string;
29
35
  key: string;
@@ -33,6 +39,9 @@ export class Profile {
33
39
  allowedInEditor?: boolean;
34
40
  allowedInPreview?: boolean;
35
41
  allowedInDeployed?: boolean;
42
+ defaultInEditor?: boolean;
43
+ defaultInPreview?: boolean;
44
+ defaultInDeployed?: boolean;
36
45
  }) {
37
46
  this.id = id;
38
47
  this.key = key;
@@ -42,6 +51,9 @@ export class Profile {
42
51
  this.allowedInEditor = allowedInEditor;
43
52
  this.allowedInPreview = allowedInPreview;
44
53
  this.allowedInDeployed = allowedInDeployed;
54
+ this.defaultInEditor = defaultInEditor;
55
+ this.defaultInPreview = defaultInPreview;
56
+ this.defaultInDeployed = defaultInDeployed;
45
57
  }
46
58
  }
47
59
 
@@ -57,3 +69,9 @@ export type EntityProfileSettings = {
57
69
  [ViewMode.DEPLOYED]: EntityModeProfileSettings;
58
70
  };
59
71
  };
72
+
73
+ export type ApplicationEnvironmentSettings = EntityProfileSettings & {
74
+ removedProfiles: Record<string, Array<{ id: string; key: string; displayName: string }>>;
75
+ needsAttention: Record<ViewMode, boolean>;
76
+ updated: number;
77
+ };
@@ -180,6 +180,7 @@ export enum ActionTypeEnum {
180
180
  DELETE = 'delete',
181
181
  DEPLOY = 'deploy',
182
182
  MANAGE = 'manage',
183
+ MANAGE_ENVIRONMENTS = 'manage_environments',
183
184
  MANAGE_SCHEDULE = 'manage_schedule',
184
185
  MANAGE_VISIBILITY = 'manage_visibility',
185
186
  PREVIEW = 'preview',
@@ -262,6 +263,7 @@ export const ActionTypeByResourceType = {
262
263
  CREATE: ActionTypeEnum.CREATE,
263
264
  DELETE: ActionTypeEnum.DELETE,
264
265
  DEPLOY: ActionTypeEnum.DEPLOY,
266
+ MANAGE_ENVIRONMENTS: ActionTypeEnum.MANAGE_ENVIRONMENTS,
265
267
  MANAGE_VISIBILITY: ActionTypeEnum.MANAGE_VISIBILITY,
266
268
  PREVIEW: ActionTypeEnum.PREVIEW,
267
269
  SHARE: ActionTypeEnum.SHARE,
@@ -0,0 +1,4 @@
1
+ import type { IRecentApplicationDto } from '../application/index.js';
2
+ import type { Pagination } from '../pagination/index.js';
3
+
4
+ export type GetRecentApplicationsResponseBody = Pagination<IRecentApplicationDto>;
@@ -41,6 +41,7 @@ export * from './GetPublicApiResponseBody.js';
41
41
  export * from './GetPublicOrganizationSummaryResponseBody.js';
42
42
  export * from './IssueSuperblocksResponseBody.js';
43
43
  export * from './GetAllApplicationsResponseBody.js';
44
+ export * from './GetRecentApplicationsResponseBody.js';
44
45
  export * from './PatchApplicationResponseBody.js';
45
46
  export * from './PatchHomePageItemsResponseBody.js';
46
47
  export * from './ListApplicationBuildsResponseBody.js';