@de-otio/trellis 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/dist/env.d.ts +21 -0
  2. package/dist/env.d.ts.map +1 -1
  3. package/dist/env.js +12 -0
  4. package/dist/env.js.map +1 -1
  5. package/dist/lambda/nightly-cron.d.ts.map +1 -1
  6. package/dist/lambda/nightly-cron.js +5 -2
  7. package/dist/lambda/nightly-cron.js.map +1 -1
  8. package/dist/lambda/post-confirmation.d.ts +30 -0
  9. package/dist/lambda/post-confirmation.d.ts.map +1 -1
  10. package/dist/lambda/post-confirmation.js +333 -29
  11. package/dist/lambda/post-confirmation.js.map +1 -1
  12. package/dist/lambda/pre-token-generation.d.ts +20 -0
  13. package/dist/lambda/pre-token-generation.d.ts.map +1 -1
  14. package/dist/lambda/pre-token-generation.js +233 -48
  15. package/dist/lambda/pre-token-generation.js.map +1 -1
  16. package/dist/lib/activitypub/activity-processor.d.ts.map +1 -1
  17. package/dist/lib/activitypub/activity-processor.js +2 -1
  18. package/dist/lib/activitypub/activity-processor.js.map +1 -1
  19. package/dist/lib/activitypub/group-service.d.ts +2 -2
  20. package/dist/lib/activitypub/group-service.d.ts.map +1 -1
  21. package/dist/lib/activitypub/group-service.js +5 -2
  22. package/dist/lib/activitypub/group-service.js.map +1 -1
  23. package/dist/lib/age-tier-transition.d.ts.map +1 -1
  24. package/dist/lib/age-tier-transition.js +19 -10
  25. package/dist/lib/age-tier-transition.js.map +1 -1
  26. package/dist/lib/audit/csv-export.d.ts +25 -0
  27. package/dist/lib/audit/csv-export.d.ts.map +1 -0
  28. package/dist/lib/audit/csv-export.js +54 -0
  29. package/dist/lib/audit/csv-export.js.map +1 -0
  30. package/dist/lib/audit/emit.d.ts +56 -0
  31. package/dist/lib/audit/emit.d.ts.map +1 -0
  32. package/dist/lib/audit/emit.js +124 -0
  33. package/dist/lib/audit/emit.js.map +1 -0
  34. package/dist/lib/audit/event-types.d.ts +36 -0
  35. package/dist/lib/audit/event-types.d.ts.map +1 -0
  36. package/dist/lib/audit/event-types.js +69 -0
  37. package/dist/lib/audit/event-types.js.map +1 -0
  38. package/dist/lib/audit/pii-filter.d.ts +22 -0
  39. package/dist/lib/audit/pii-filter.d.ts.map +1 -0
  40. package/dist/lib/audit/pii-filter.js +51 -0
  41. package/dist/lib/audit/pii-filter.js.map +1 -0
  42. package/dist/lib/audit-logger.js +1 -1
  43. package/dist/lib/audit-logger.js.map +1 -1
  44. package/dist/lib/auth/auth-context.d.ts +34 -0
  45. package/dist/lib/auth/auth-context.d.ts.map +1 -0
  46. package/dist/lib/auth/auth-context.js +10 -0
  47. package/dist/lib/auth/auth-context.js.map +1 -0
  48. package/dist/lib/auth/auth-middleware.d.ts +50 -0
  49. package/dist/lib/auth/auth-middleware.d.ts.map +1 -0
  50. package/dist/lib/auth/auth-middleware.js +153 -0
  51. package/dist/lib/auth/auth-middleware.js.map +1 -0
  52. package/dist/lib/auth/capabilities.d.ts +40 -0
  53. package/dist/lib/auth/capabilities.d.ts.map +1 -0
  54. package/dist/lib/auth/capabilities.js +44 -0
  55. package/dist/lib/auth/capabilities.js.map +1 -0
  56. package/dist/lib/auth/claims-cache.d.ts +70 -0
  57. package/dist/lib/auth/claims-cache.d.ts.map +1 -0
  58. package/dist/lib/auth/claims-cache.js +139 -0
  59. package/dist/lib/auth/claims-cache.js.map +1 -0
  60. package/dist/lib/auth/cognito-jwt.d.ts +6 -0
  61. package/dist/lib/auth/cognito-jwt.d.ts.map +1 -1
  62. package/dist/lib/auth/cognito-jwt.js.map +1 -1
  63. package/dist/lib/auth/idp-redirect-builder.d.ts +43 -0
  64. package/dist/lib/auth/idp-redirect-builder.d.ts.map +1 -0
  65. package/dist/lib/auth/idp-redirect-builder.js +48 -0
  66. package/dist/lib/auth/idp-redirect-builder.js.map +1 -0
  67. package/dist/lib/auth/require.d.ts +51 -0
  68. package/dist/lib/auth/require.d.ts.map +1 -0
  69. package/dist/lib/auth/require.js +99 -0
  70. package/dist/lib/auth/require.js.map +1 -0
  71. package/dist/lib/auth/role-grants.d.ts +18 -0
  72. package/dist/lib/auth/role-grants.d.ts.map +1 -0
  73. package/dist/lib/auth/role-grants.js +62 -0
  74. package/dist/lib/auth/role-grants.js.map +1 -0
  75. package/dist/lib/cognito/idp-sdk.d.ts +80 -0
  76. package/dist/lib/cognito/idp-sdk.d.ts.map +1 -0
  77. package/dist/lib/cognito/idp-sdk.js +186 -0
  78. package/dist/lib/cognito/idp-sdk.js.map +1 -0
  79. package/dist/lib/cognito/issuer-probe.d.ts +47 -0
  80. package/dist/lib/cognito/issuer-probe.d.ts.map +1 -0
  81. package/dist/lib/cognito/issuer-probe.js +319 -0
  82. package/dist/lib/cognito/issuer-probe.js.map +1 -0
  83. package/dist/lib/comment-handler.d.ts +7 -7
  84. package/dist/lib/comment-handler.d.ts.map +1 -1
  85. package/dist/lib/comment-handler.js +23 -20
  86. package/dist/lib/comment-handler.js.map +1 -1
  87. package/dist/lib/compliance/baseline.d.ts +15 -0
  88. package/dist/lib/compliance/baseline.d.ts.map +1 -0
  89. package/dist/lib/compliance/baseline.js +205 -0
  90. package/dist/lib/compliance/baseline.js.map +1 -0
  91. package/dist/lib/compliance/tenant-merge.d.ts +35 -0
  92. package/dist/lib/compliance/tenant-merge.d.ts.map +1 -0
  93. package/dist/lib/compliance/tenant-merge.js +80 -0
  94. package/dist/lib/compliance/tenant-merge.js.map +1 -0
  95. package/dist/lib/compliance/types.d.ts +135 -0
  96. package/dist/lib/compliance/types.d.ts.map +1 -0
  97. package/dist/lib/compliance/types.js +9 -0
  98. package/dist/lib/compliance/types.js.map +1 -0
  99. package/dist/lib/connection-code-handler.d.ts +4 -4
  100. package/dist/lib/connection-code-handler.d.ts.map +1 -1
  101. package/dist/lib/connection-code-handler.js +21 -11
  102. package/dist/lib/connection-code-handler.js.map +1 -1
  103. package/dist/lib/feed-handler.d.ts +2 -2
  104. package/dist/lib/feed-handler.d.ts.map +1 -1
  105. package/dist/lib/feed-handler.js +5 -9
  106. package/dist/lib/feed-handler.js.map +1 -1
  107. package/dist/lib/middleware/idempotency-store.d.ts +86 -0
  108. package/dist/lib/middleware/idempotency-store.d.ts.map +1 -0
  109. package/dist/lib/middleware/idempotency-store.js +109 -0
  110. package/dist/lib/middleware/idempotency-store.js.map +1 -0
  111. package/dist/lib/middleware/idempotency.d.ts +37 -0
  112. package/dist/lib/middleware/idempotency.d.ts.map +1 -0
  113. package/dist/lib/middleware/idempotency.js +358 -0
  114. package/dist/lib/middleware/idempotency.js.map +1 -0
  115. package/dist/lib/net/trusted-client-ip.d.ts +39 -0
  116. package/dist/lib/net/trusted-client-ip.d.ts.map +1 -0
  117. package/dist/lib/net/trusted-client-ip.js +100 -0
  118. package/dist/lib/net/trusted-client-ip.js.map +1 -0
  119. package/dist/lib/notification-handler.d.ts +5 -5
  120. package/dist/lib/notification-handler.d.ts.map +1 -1
  121. package/dist/lib/notification-handler.js +11 -9
  122. package/dist/lib/notification-handler.js.map +1 -1
  123. package/dist/lib/oauth/cognito-issuer.d.ts +34 -0
  124. package/dist/lib/oauth/cognito-issuer.d.ts.map +1 -0
  125. package/dist/lib/oauth/cognito-issuer.js +53 -0
  126. package/dist/lib/oauth/cognito-issuer.js.map +1 -0
  127. package/dist/lib/oauth/device-authorization.d.ts +145 -0
  128. package/dist/lib/oauth/device-authorization.d.ts.map +1 -0
  129. package/dist/lib/oauth/device-authorization.js +312 -0
  130. package/dist/lib/oauth/device-authorization.js.map +1 -0
  131. package/dist/lib/oauth/envelope-crypto.d.ts +101 -0
  132. package/dist/lib/oauth/envelope-crypto.d.ts.map +1 -0
  133. package/dist/lib/oauth/envelope-crypto.js +223 -0
  134. package/dist/lib/oauth/envelope-crypto.js.map +1 -0
  135. package/dist/lib/oauth/refresh-detection.d.ts +126 -0
  136. package/dist/lib/oauth/refresh-detection.d.ts.map +1 -0
  137. package/dist/lib/oauth/refresh-detection.js +248 -0
  138. package/dist/lib/oauth/refresh-detection.js.map +1 -0
  139. package/dist/lib/openapi/generator.d.ts +78 -0
  140. package/dist/lib/openapi/generator.d.ts.map +1 -0
  141. package/dist/lib/openapi/generator.js +201 -0
  142. package/dist/lib/openapi/generator.js.map +1 -0
  143. package/dist/lib/post-handler.d.ts +1 -1
  144. package/dist/lib/post-handler.d.ts.map +1 -1
  145. package/dist/lib/post-handler.js +4 -15
  146. package/dist/lib/post-handler.js.map +1 -1
  147. package/dist/lib/rate-limit.d.ts.map +1 -1
  148. package/dist/lib/rate-limit.js +11 -3
  149. package/dist/lib/rate-limit.js.map +1 -1
  150. package/dist/lib/routes/agent-authorize.d.ts +32 -0
  151. package/dist/lib/routes/agent-authorize.d.ts.map +1 -0
  152. package/dist/lib/routes/agent-authorize.js +479 -0
  153. package/dist/lib/routes/agent-authorize.js.map +1 -0
  154. package/dist/lib/routes/agent-sessions.d.ts +20 -0
  155. package/dist/lib/routes/agent-sessions.d.ts.map +1 -0
  156. package/dist/lib/routes/agent-sessions.js +124 -0
  157. package/dist/lib/routes/agent-sessions.js.map +1 -0
  158. package/dist/lib/routes/agent-surface.d.ts +37 -0
  159. package/dist/lib/routes/agent-surface.d.ts.map +1 -0
  160. package/dist/lib/routes/agent-surface.js +208 -0
  161. package/dist/lib/routes/agent-surface.js.map +1 -0
  162. package/dist/lib/routes/auth-discover.d.ts +18 -0
  163. package/dist/lib/routes/auth-discover.d.ts.map +1 -0
  164. package/dist/lib/routes/auth-discover.js +177 -0
  165. package/dist/lib/routes/auth-discover.js.map +1 -0
  166. package/dist/lib/routes/comments.d.ts.map +1 -1
  167. package/dist/lib/routes/comments.js +36 -7
  168. package/dist/lib/routes/comments.js.map +1 -1
  169. package/dist/lib/routes/connection-codes.d.ts.map +1 -1
  170. package/dist/lib/routes/connection-codes.js +21 -4
  171. package/dist/lib/routes/connection-codes.js.map +1 -1
  172. package/dist/lib/routes/content-discovery.d.ts.map +1 -1
  173. package/dist/lib/routes/content-discovery.js +18 -13
  174. package/dist/lib/routes/content-discovery.js.map +1 -1
  175. package/dist/lib/routes/dashboard.js +1 -1
  176. package/dist/lib/routes/dashboard.js.map +1 -1
  177. package/dist/lib/routes/employees.d.ts.map +1 -1
  178. package/dist/lib/routes/employees.js +57 -15
  179. package/dist/lib/routes/employees.js.map +1 -1
  180. package/dist/lib/routes/entities.d.ts.map +1 -1
  181. package/dist/lib/routes/entities.js +35 -19
  182. package/dist/lib/routes/entities.js.map +1 -1
  183. package/dist/lib/routes/errors.d.ts +34 -0
  184. package/dist/lib/routes/errors.d.ts.map +1 -0
  185. package/dist/lib/routes/errors.js +57 -0
  186. package/dist/lib/routes/errors.js.map +1 -0
  187. package/dist/lib/routes/feeds.d.ts.map +1 -1
  188. package/dist/lib/routes/feeds.js +12 -2
  189. package/dist/lib/routes/feeds.js.map +1 -1
  190. package/dist/lib/routes/index.d.ts.map +1 -1
  191. package/dist/lib/routes/index.js +50 -0
  192. package/dist/lib/routes/index.js.map +1 -1
  193. package/dist/lib/routes/mfa.d.ts.map +1 -1
  194. package/dist/lib/routes/mfa.js +1 -0
  195. package/dist/lib/routes/mfa.js.map +1 -1
  196. package/dist/lib/routes/notifications.d.ts.map +1 -1
  197. package/dist/lib/routes/notifications.js +21 -4
  198. package/dist/lib/routes/notifications.js.map +1 -1
  199. package/dist/lib/routes/oauth.d.ts +15 -0
  200. package/dist/lib/routes/oauth.d.ts.map +1 -0
  201. package/dist/lib/routes/oauth.js +139 -0
  202. package/dist/lib/routes/oauth.js.map +1 -0
  203. package/dist/lib/routes/posts.d.ts.map +1 -1
  204. package/dist/lib/routes/posts.js +30 -19
  205. package/dist/lib/routes/posts.js.map +1 -1
  206. package/dist/lib/routes/products.d.ts.map +1 -1
  207. package/dist/lib/routes/products.js +19 -22
  208. package/dist/lib/routes/products.js.map +1 -1
  209. package/dist/lib/routes/setup-status.d.ts +34 -0
  210. package/dist/lib/routes/setup-status.d.ts.map +1 -0
  211. package/dist/lib/routes/setup-status.js +87 -0
  212. package/dist/lib/routes/setup-status.js.map +1 -0
  213. package/dist/lib/routes/taxonomy-analytics.d.ts.map +1 -1
  214. package/dist/lib/routes/taxonomy-analytics.js +15 -14
  215. package/dist/lib/routes/taxonomy-analytics.js.map +1 -1
  216. package/dist/lib/routes/taxonomy.d.ts.map +1 -1
  217. package/dist/lib/routes/taxonomy.js +19 -16
  218. package/dist/lib/routes/taxonomy.js.map +1 -1
  219. package/dist/lib/routes/tenant-audit.d.ts +19 -0
  220. package/dist/lib/routes/tenant-audit.d.ts.map +1 -0
  221. package/dist/lib/routes/tenant-audit.js +244 -0
  222. package/dist/lib/routes/tenant-audit.js.map +1 -0
  223. package/dist/lib/routes/tenant-compliance.d.ts +21 -0
  224. package/dist/lib/routes/tenant-compliance.d.ts.map +1 -0
  225. package/dist/lib/routes/tenant-compliance.js +122 -0
  226. package/dist/lib/routes/tenant-compliance.js.map +1 -0
  227. package/dist/lib/routes/tenant-domains.d.ts +11 -0
  228. package/dist/lib/routes/tenant-domains.d.ts.map +1 -0
  229. package/dist/lib/routes/tenant-domains.js +95 -0
  230. package/dist/lib/routes/tenant-domains.js.map +1 -0
  231. package/dist/lib/routes/tenant-idp.d.ts +3 -0
  232. package/dist/lib/routes/tenant-idp.d.ts.map +1 -0
  233. package/dist/lib/routes/tenant-idp.js +89 -0
  234. package/dist/lib/routes/tenant-idp.js.map +1 -0
  235. package/dist/lib/routes/tenant-members.d.ts +13 -0
  236. package/dist/lib/routes/tenant-members.d.ts.map +1 -0
  237. package/dist/lib/routes/tenant-members.js +75 -0
  238. package/dist/lib/routes/tenant-members.js.map +1 -0
  239. package/dist/lib/routes/tenant-role-mappings.d.ts +11 -0
  240. package/dist/lib/routes/tenant-role-mappings.d.ts.map +1 -0
  241. package/dist/lib/routes/tenant-role-mappings.js +90 -0
  242. package/dist/lib/routes/tenant-role-mappings.js.map +1 -0
  243. package/dist/lib/routes/tenants.d.ts +13 -0
  244. package/dist/lib/routes/tenants.d.ts.map +1 -0
  245. package/dist/lib/routes/tenants.js +121 -0
  246. package/dist/lib/routes/tenants.js.map +1 -0
  247. package/dist/lib/routes/types.d.ts +9 -0
  248. package/dist/lib/routes/types.d.ts.map +1 -1
  249. package/dist/lib/schemas.d.ts +2 -2
  250. package/dist/lib/secrets/idp-secrets.d.ts +51 -0
  251. package/dist/lib/secrets/idp-secrets.d.ts.map +1 -0
  252. package/dist/lib/secrets/idp-secrets.js +111 -0
  253. package/dist/lib/secrets/idp-secrets.js.map +1 -0
  254. package/dist/lib/security-monitor.d.ts.map +1 -1
  255. package/dist/lib/security-monitor.js +6 -1
  256. package/dist/lib/security-monitor.js.map +1 -1
  257. package/dist/lib/session-manager.d.ts +1 -0
  258. package/dist/lib/session-manager.d.ts.map +1 -1
  259. package/dist/lib/session-manager.js.map +1 -1
  260. package/dist/lib/taxonomy-handler-factory.d.ts +4 -2
  261. package/dist/lib/taxonomy-handler-factory.d.ts.map +1 -1
  262. package/dist/lib/taxonomy-handler-factory.js +8 -7
  263. package/dist/lib/taxonomy-handler-factory.js.map +1 -1
  264. package/dist/lib/tenant/audit-emit.d.ts +18 -0
  265. package/dist/lib/tenant/audit-emit.d.ts.map +1 -0
  266. package/dist/lib/tenant/audit-emit.js +16 -0
  267. package/dist/lib/tenant/audit-emit.js.map +1 -0
  268. package/dist/lib/tenant/derive-domain.d.ts +19 -0
  269. package/dist/lib/tenant/derive-domain.d.ts.map +1 -0
  270. package/dist/lib/tenant/derive-domain.js +38 -0
  271. package/dist/lib/tenant/derive-domain.js.map +1 -0
  272. package/dist/lib/tenant/domain-handler.d.ts +42 -0
  273. package/dist/lib/tenant/domain-handler.d.ts.map +1 -0
  274. package/dist/lib/tenant/domain-handler.js +344 -0
  275. package/dist/lib/tenant/domain-handler.js.map +1 -0
  276. package/dist/lib/tenant/domain-validator.d.ts +28 -0
  277. package/dist/lib/tenant/domain-validator.d.ts.map +1 -0
  278. package/dist/lib/tenant/domain-validator.js +145 -0
  279. package/dist/lib/tenant/domain-validator.js.map +1 -0
  280. package/dist/lib/tenant/domain-verifier.d.ts +30 -0
  281. package/dist/lib/tenant/domain-verifier.d.ts.map +1 -0
  282. package/dist/lib/tenant/domain-verifier.js +53 -0
  283. package/dist/lib/tenant/domain-verifier.js.map +1 -0
  284. package/dist/lib/tenant/idp-handler.d.ts +29 -0
  285. package/dist/lib/tenant/idp-handler.d.ts.map +1 -0
  286. package/dist/lib/tenant/idp-handler.js +693 -0
  287. package/dist/lib/tenant/idp-handler.js.map +1 -0
  288. package/dist/lib/tenant/idp-name.d.ts +2 -0
  289. package/dist/lib/tenant/idp-name.d.ts.map +1 -0
  290. package/dist/lib/tenant/idp-name.js +20 -0
  291. package/dist/lib/tenant/idp-name.js.map +1 -0
  292. package/dist/lib/tenant/member-handler.d.ts +31 -0
  293. package/dist/lib/tenant/member-handler.d.ts.map +1 -0
  294. package/dist/lib/tenant/member-handler.js +343 -0
  295. package/dist/lib/tenant/member-handler.js.map +1 -0
  296. package/dist/lib/tenant/reserved-slugs.d.ts +37 -0
  297. package/dist/lib/tenant/reserved-slugs.d.ts.map +1 -0
  298. package/dist/lib/tenant/reserved-slugs.js +116 -0
  299. package/dist/lib/tenant/reserved-slugs.js.map +1 -0
  300. package/dist/lib/tenant/resolve-role.d.ts +39 -0
  301. package/dist/lib/tenant/resolve-role.d.ts.map +1 -0
  302. package/dist/lib/tenant/resolve-role.js +60 -0
  303. package/dist/lib/tenant/resolve-role.js.map +1 -0
  304. package/dist/lib/tenant/role-mapping-handler.d.ts +26 -0
  305. package/dist/lib/tenant/role-mapping-handler.d.ts.map +1 -0
  306. package/dist/lib/tenant/role-mapping-handler.js +260 -0
  307. package/dist/lib/tenant/role-mapping-handler.js.map +1 -0
  308. package/dist/lib/tenant/setup-status.d.ts +83 -0
  309. package/dist/lib/tenant/setup-status.d.ts.map +1 -0
  310. package/dist/lib/tenant/setup-status.js +201 -0
  311. package/dist/lib/tenant/setup-status.js.map +1 -0
  312. package/dist/lib/tenant/slug-validator.d.ts +31 -0
  313. package/dist/lib/tenant/slug-validator.d.ts.map +1 -0
  314. package/dist/lib/tenant/slug-validator.js +42 -0
  315. package/dist/lib/tenant/slug-validator.js.map +1 -0
  316. package/dist/lib/tenant/tenant-handler.d.ts +49 -0
  317. package/dist/lib/tenant/tenant-handler.d.ts.map +1 -0
  318. package/dist/lib/tenant/tenant-handler.js +377 -0
  319. package/dist/lib/tenant/tenant-handler.js.map +1 -0
  320. package/dist/lib/tenant/transfer-ownership.d.ts +39 -0
  321. package/dist/lib/tenant/transfer-ownership.d.ts.map +1 -0
  322. package/dist/lib/tenant/transfer-ownership.js +66 -0
  323. package/dist/lib/tenant/transfer-ownership.js.map +1 -0
  324. package/dist/lib/user/derive-handle.d.ts +29 -0
  325. package/dist/lib/user/derive-handle.d.ts.map +1 -0
  326. package/dist/lib/user/derive-handle.js +65 -0
  327. package/dist/lib/user/derive-handle.js.map +1 -0
  328. package/dist/lib/user-deprovisioning.d.ts +11 -1
  329. package/dist/lib/user-deprovisioning.d.ts.map +1 -1
  330. package/dist/lib/user-deprovisioning.js +46 -2
  331. package/dist/lib/user-deprovisioning.js.map +1 -1
  332. package/dist/lib/validation/feature-toggle-schemas.d.ts +10 -10
  333. package/package.json +7 -5
  334. package/prisma/migrations/20260502094501_add_tenancy_model/migration.sql +334 -0
  335. package/prisma/migrations/20260503000000_add_tenant_region/migration.sql +4 -0
  336. package/prisma/schema.prisma +324 -74
  337. package/src/lambda/nightly-cron.ts +4 -1
  338. package/src/lambda/post-confirmation.ts +405 -29
  339. package/src/lambda/pre-token-generation.ts +300 -59
@@ -0,0 +1,479 @@
1
+ "use strict";
2
+ /**
3
+ * Interactive agent-authorization page (T9b-d).
4
+ *
5
+ * GET /agents/authorize?user_code=XXXX-XXXX
6
+ * POST /agents/authorize/approve
7
+ *
8
+ * The GET renders a minimal HTML approval form. The POST verifies the
9
+ * admin's session, enforces:
10
+ * - tenant ManageAgentSessions capability
11
+ * - MFA in the last hour (step-up if missing)
12
+ * - per-IP rate limit (5/min)
13
+ * - per-device_code lockout (10 failed lookups)
14
+ * and on success calls Cognito AdminInitiateAuth to mint tokens, seals
15
+ * them under the device_code, and writes the agent-session row.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.agentAuthorizeRoutes = void 0;
19
+ exports._setAgentAuthorizeDepsForTest = _setAgentAuthorizeDepsForTest;
20
+ exports._resetAgentAuthorizeDepsForTest = _resetAgentAuthorizeDepsForTest;
21
+ const zod_1 = require("zod");
22
+ const node_crypto_1 = require("node:crypto");
23
+ const db_1 = require("../../db");
24
+ const capabilities_1 = require("../auth/capabilities");
25
+ const require_1 = require("../auth/require");
26
+ const device_authorization_1 = require("../oauth/device-authorization");
27
+ const emit_1 = require("../audit/emit");
28
+ const event_types_1 = require("../audit/event-types");
29
+ const client_cognito_identity_provider_1 = require("@aws-sdk/client-cognito-identity-provider");
30
+ const cognito_issuer_1 = require("../oauth/cognito-issuer");
31
+ const refresh_detection_1 = require("../oauth/refresh-detection");
32
+ const middleware_1 = require("../middleware");
33
+ const trusted_client_ip_1 = require("../net/trusted-client-ip");
34
+ const rate_limit_1 = require("../rate-limit");
35
+ const secret_resolver_1 = require("../secret-resolver");
36
+ const security_headers_1 = require("../security-headers");
37
+ const session_manager_1 = require("../session-manager");
38
+ const errors_1 = require("./errors");
39
+ /** Per-IP ceiling on approvals (G4 CRITICAL-3). */
40
+ const APPROVE_RATE_LIMIT = 5;
41
+ const APPROVE_RATE_WINDOW_SECONDS = 60;
42
+ /**
43
+ * Global, IP-independent ceiling on `/agents/authorize` lookups (G4
44
+ * CRITICAL-3, MEDIUM-2). Even when XFF parsing is bypassed or a single
45
+ * IP can spoof many sources via cloud-supplied headers, this bucket
46
+ * caps the surface system-wide.
47
+ */
48
+ const APPROVE_GLOBAL_LIMIT = 200;
49
+ const APPROVE_GLOBAL_WINDOW_SECONDS = 60;
50
+ /** Per-IP ceiling on user_code → device_code resolution misses (MEDIUM-2). */
51
+ const VERIFY_MISS_LIMIT = 30;
52
+ const VERIFY_MISS_WINDOW_SECONDS = 60;
53
+ const MFA_FRESHNESS_MS = 60 * 60 * 1000; // 1 hour
54
+ const ApproveSchema = zod_1.z
55
+ .object({
56
+ user_code: zod_1.z.string().min(4).max(32),
57
+ })
58
+ .strict();
59
+ /** Module-level deps; tests can override. */
60
+ let deps = {};
61
+ function _setAgentAuthorizeDepsForTest(d) {
62
+ deps = d;
63
+ }
64
+ function _resetAgentAuthorizeDepsForTest() {
65
+ deps = {};
66
+ }
67
+ function getIssuer() {
68
+ if (deps.issuer)
69
+ return deps.issuer;
70
+ return new cognito_issuer_1.AwsCognitoIssuer(new client_cognito_identity_provider_1.CognitoIdentityProviderClient({
71
+ region: process.env.COGNITO_REGION || process.env.AWS_REGION || "us-east-1",
72
+ }));
73
+ }
74
+ function getAudit() {
75
+ return deps.auditEmitter ?? new emit_1.AuditEventEmitter();
76
+ }
77
+ function getRateLimiter() {
78
+ return deps.rateLimiter ?? new rate_limit_1.RateLimiter();
79
+ }
80
+ function htmlResponse(body, status = 200) {
81
+ return new Response(body, {
82
+ status,
83
+ headers: {
84
+ "content-type": "text/html; charset=utf-8",
85
+ "cache-control": "no-store",
86
+ "x-content-type-options": "nosniff",
87
+ },
88
+ });
89
+ }
90
+ function jsonError(env, body, status) {
91
+ const sec = new security_headers_1.SecurityHeaders(env);
92
+ return sec.createSecureResponse(JSON.stringify(body), {
93
+ status,
94
+ headers: { "content-type": "application/json", "cache-control": "no-store" },
95
+ });
96
+ }
97
+ function escape(input) {
98
+ return input
99
+ .replace(/&/g, "&")
100
+ .replace(/</g, "&lt;")
101
+ .replace(/>/g, "&gt;")
102
+ .replace(/"/g, "&quot;")
103
+ .replace(/'/g, "&#39;");
104
+ }
105
+ function renderApprovalPage(input) {
106
+ const heading = input.mfaRequired
107
+ ? "Verify a fresh MFA code, then approve"
108
+ : "Approve agent session";
109
+ const mfaNotice = input.mfaRequired
110
+ ? `<p class="warn">Your most recent MFA verification is older than 1 hour.
111
+ Verify with a TOTP code at <a href="/api/mfa/verify">/api/mfa/verify</a>
112
+ and reload this page.</p>`
113
+ : "";
114
+ // HIGH-4: agentLabel is supplied by the polling agent and is not a
115
+ // value the platform has authenticated. Render it inside a code block
116
+ // and warn the operator that the label is untrusted before they approve.
117
+ return `<!doctype html>
118
+ <html lang="en">
119
+ <head>
120
+ <meta charset="utf-8" />
121
+ <title>Approve agent session</title>
122
+ <style>
123
+ body { font-family: system-ui, sans-serif; max-width: 32em; margin: 4em auto; }
124
+ .code { font-family: monospace; font-size: 1.4em; }
125
+ .label-block { display: block; margin: 0.5em 0; padding: 0.5em 0.75em;
126
+ background: #f4f4f4; border-left: 3px solid #888;
127
+ font-family: monospace; word-break: break-all; }
128
+ .caveat { background: #fff8e1; border: 1px solid #f0c36d;
129
+ padding: 0.75em 1em; margin: 1em 0; border-radius: 4px; }
130
+ .warn { color: #b00; }
131
+ button[disabled] { opacity: 0.5; cursor: not-allowed; }
132
+ </style>
133
+ </head>
134
+ <body>
135
+ <h1>${escape(heading)}</h1>
136
+ <p>An agent identifying itself as:</p>
137
+ <code class="label-block">${escape(input.agentLabel ?? "(unknown client)")}</code>
138
+ <p>has requested access to your tenant from this address:</p>
139
+ <p>Source IP: <span class="code">${escape(input.sourceIp)}</span></p>
140
+ <div class="caveat">
141
+ The agent name above is supplied by the agent and is not verified by
142
+ Skybber. Verify with the person who initiated this flow before
143
+ approving.
144
+ </div>
145
+ <p>Code:
146
+ <span class="code">${escape(input.userCode)}</span></p>
147
+ ${mfaNotice}
148
+ <form method="POST" action="/agents/authorize/approve">
149
+ <input type="hidden" name="user_code" value="${escape(input.userCode)}" />
150
+ ${input.csrfToken ? `<input type="hidden" name="csrf_token" value="${escape(input.csrfToken)}" />` : ""}
151
+ <button type="submit"${input.mfaRequired ? " disabled" : ""}>Approve</button>
152
+ </form>
153
+ </body>
154
+ </html>`;
155
+ }
156
+ async function buildAuthContext(session, env) {
157
+ // Minimal AuthContext from the cookie session — the agent-approval flow
158
+ // only needs userId/tenantId/role for capability check and audit. The
159
+ // real Cognito JWT auth-middleware path is for token-bearing API calls;
160
+ // here the admin is using the web session.
161
+ if (!session.userId)
162
+ return null;
163
+ // We need tenantRole. Look up via Prisma.
164
+ const prisma = (0, db_1.createPrisma)(env);
165
+ const memberWithTenant = await prisma.tenantMember.findFirst({
166
+ where: { userId: session.userId, status: "ACTIVE" },
167
+ orderBy: { joinedAt: "asc" },
168
+ include: { tenant: true },
169
+ });
170
+ if (!memberWithTenant)
171
+ return null;
172
+ // HIGH-5: resolve the real Cognito sub from the User row. We previously
173
+ // used session.userId (the trellis user id) as the cognitoSub fallback,
174
+ // which would have caused AdminUserGlobalSignOut to be called against
175
+ // the wrong identifier. Block agent approval if the sub cannot be
176
+ // resolved rather than silently writing a value that won't revoke.
177
+ const userRow = await prisma.user.findUnique({
178
+ where: { id: session.userId },
179
+ select: { cognitoSub: true },
180
+ });
181
+ if (!userRow?.cognitoSub) {
182
+ return null;
183
+ }
184
+ // Use globalRole from session.role if present; fallback to END_USER.
185
+ const globalRole = session.role ?? "END_USER";
186
+ return {
187
+ cognitoSub: userRow.cognitoSub,
188
+ userId: session.userId,
189
+ globalRole,
190
+ activeTenantId: memberWithTenant.tenantId,
191
+ tenantSlug: memberWithTenant.tenant.slug,
192
+ tenantRole: memberWithTenant.role,
193
+ handle: session.email,
194
+ membershipsLoader: async () => [memberWithTenant],
195
+ };
196
+ }
197
+ exports.agentAuthorizeRoutes = [
198
+ {
199
+ path: "/agents/authorize",
200
+ method: "GET",
201
+ handler: async (request, env) => {
202
+ const url = new URL(request.url);
203
+ const rawUserCode = url.searchParams.get("user_code");
204
+ if (!rawUserCode) {
205
+ return htmlResponse("<p>Missing user_code parameter</p>", 400);
206
+ }
207
+ const sessionManager = new session_manager_1.SessionManager();
208
+ const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
209
+ if (!session) {
210
+ const returnTo = encodeURIComponent(`/agents/authorize?user_code=${rawUserCode}`);
211
+ return new Response(null, {
212
+ status: 302,
213
+ headers: { Location: `/auth/login?return=${returnTo}` },
214
+ });
215
+ }
216
+ // Capability check — admins only.
217
+ const auth = await buildAuthContext(session, env);
218
+ if (!auth) {
219
+ return htmlResponse("<p>Active tenant membership required.</p>", 403);
220
+ }
221
+ const denied = (0, require_1.requireCapability)(auth, capabilities_1.Capability.ManageAgentSessions);
222
+ if (denied) {
223
+ return htmlResponse("<p>You are not permitted to approve agents for this tenant.</p>", 403);
224
+ }
225
+ // CRITICAL-3: enforce a global ceiling on resolution attempts so
226
+ // the surface stays bounded even when per-IP keys are spoofable.
227
+ const rl = getRateLimiter();
228
+ const globalLimited = await rl.applyRateLimitKV(env, request, "/agents/authorize:global", APPROVE_GLOBAL_LIMIT, APPROVE_GLOBAL_WINDOW_SECONDS,
229
+ // Keying on a fixed userId forces the limiter to a single bucket
230
+ // shared by all callers regardless of headers.
231
+ undefined, undefined, "global");
232
+ if (globalLimited)
233
+ return globalLimited;
234
+ // Resolve the user_code → device_code lookup. Don't reveal whether
235
+ // the code is valid in the page body to avoid easy brute-force —
236
+ // but we can still tell the user the page renders.
237
+ const userCode = (0, device_authorization_1.normaliseUserCode)(rawUserCode);
238
+ const deviceCode = await (0, device_authorization_1.lookupDeviceCodeByUserCode)(userCode);
239
+ const record = deviceCode ? await (0, device_authorization_1.loadByDeviceCode)(deviceCode) : null;
240
+ // MEDIUM-2: charge a miss against the per-IP miss bucket whenever
241
+ // the user_code did not resolve. Combined with the global ceiling
242
+ // above, a single source cannot enumerate user_codes by spamming
243
+ // GETs without hitting either bucket first.
244
+ if (!deviceCode) {
245
+ await rl
246
+ .applyRateLimitKV(env, request, "/agents/authorize:miss", VERIFY_MISS_LIMIT, VERIFY_MISS_WINDOW_SECONDS)
247
+ .catch(() => null);
248
+ }
249
+ // LOW-2: use abs() so future clock skew (mfaVerifiedAt > now) does
250
+ // not bypass the freshness gate. The tolerance window is symmetric;
251
+ // anything outside ±MFA_FRESHNESS_MS counts as stale.
252
+ const mfaFresh = Boolean(session.mfaVerified) &&
253
+ typeof session.mfaVerifiedAt === "number" &&
254
+ Math.abs(Date.now() - session.mfaVerifiedAt) < MFA_FRESHNESS_MS;
255
+ return htmlResponse(renderApprovalPage({
256
+ userCode: rawUserCode,
257
+ agentLabel: record?.agentLabel,
258
+ sourceIp: (0, trusted_client_ip_1.trustedClientIp)(request, env),
259
+ mfaRequired: !mfaFresh,
260
+ csrfToken: session.csrfToken,
261
+ }));
262
+ },
263
+ middleware: [(0, middleware_1.corsMiddleware)()],
264
+ description: "Render the agent-approval page",
265
+ },
266
+ {
267
+ path: "/agents/authorize/approve",
268
+ method: "POST",
269
+ handler: async (request, env) => {
270
+ const rl = getRateLimiter();
271
+ // CRITICAL-3: global, IP-independent ceiling first. Even if the
272
+ // per-IP limiter below is bypassable via spoofed proxy headers,
273
+ // this bucket caps the surface system-wide.
274
+ const globalLimited = await rl.applyRateLimitKV(env, request, "/agents/authorize/approve:global", APPROVE_GLOBAL_LIMIT, APPROVE_GLOBAL_WINDOW_SECONDS, undefined, undefined, "global");
275
+ if (globalLimited)
276
+ return globalLimited;
277
+ // Per-IP rate limit on the approval surface.
278
+ const limited = await rl.applyRateLimitKV(env, request, "/agents/authorize/approve", APPROVE_RATE_LIMIT, APPROVE_RATE_WINDOW_SECONDS);
279
+ if (limited)
280
+ return limited;
281
+ const sessionManager = new session_manager_1.SessionManager();
282
+ const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
283
+ if (!session) {
284
+ return (0, errors_1.structuredError)(401, {
285
+ error: "UNAUTHORIZED",
286
+ message: "Authentication required.",
287
+ remediation: "Sign in at /auth/login and retry.",
288
+ });
289
+ }
290
+ // MFA freshness gate — refuse if MFA wasn't recently verified.
291
+ // LOW-2: use abs() so future clock skew (mfaVerifiedAt > now)
292
+ // cannot satisfy the freshness check.
293
+ const mfaFresh = Boolean(session.mfaVerified) &&
294
+ typeof session.mfaVerifiedAt === "number" &&
295
+ Math.abs(Date.now() - session.mfaVerifiedAt) < MFA_FRESHNESS_MS;
296
+ if (!mfaFresh) {
297
+ return (0, errors_1.structuredError)(401, {
298
+ error: "MFA_REQUIRED",
299
+ message: "Step up with a fresh MFA verification before approving an agent.",
300
+ remediation: "POST /api/mfa/verify with a TOTP code, then retry this approval.",
301
+ });
302
+ }
303
+ const auth = await buildAuthContext(session, env);
304
+ if (!auth) {
305
+ return (0, errors_1.structuredError)(401, {
306
+ error: "UNAUTHORIZED",
307
+ message: "Authentication required.",
308
+ remediation: "Sign in at /auth/login with an active tenant membership and retry.",
309
+ });
310
+ }
311
+ const denied = (0, require_1.requireCapability)(auth, capabilities_1.Capability.ManageAgentSessions);
312
+ if (denied)
313
+ return denied;
314
+ // Read form / json body.
315
+ const ct = request.headers.get("content-type") || "";
316
+ let body;
317
+ if (ct.includes("application/x-www-form-urlencoded")) {
318
+ const text = await request.text();
319
+ body = Object.fromEntries(new URLSearchParams(text).entries());
320
+ }
321
+ else if (ct.includes("application/json")) {
322
+ body = (await request.json());
323
+ }
324
+ else {
325
+ return (0, errors_1.structuredError)(400, {
326
+ error: "INVALID_REQUEST",
327
+ message: "Request body must be form-encoded or JSON.",
328
+ remediation: "Set Content-Type to application/x-www-form-urlencoded or application/json.",
329
+ });
330
+ }
331
+ const parsed = ApproveSchema.safeParse(body);
332
+ if (!parsed.success) {
333
+ return (0, errors_1.structuredError)(400, {
334
+ error: "INVALID_REQUEST",
335
+ message: "user_code is required.",
336
+ remediation: "Include the user_code displayed on the agent device.",
337
+ field: "user_code",
338
+ });
339
+ }
340
+ const userCode = (0, device_authorization_1.normaliseUserCode)(parsed.data.user_code);
341
+ const deviceCode = await (0, device_authorization_1.lookupDeviceCodeByUserCode)(userCode);
342
+ if (!deviceCode) {
343
+ // MEDIUM-2: charge the per-IP miss bucket on every unresolved
344
+ // user_code so enumeration is bounded even when the device-code
345
+ // table holds no row to attach the failed-lookup counter to.
346
+ await rl
347
+ .applyRateLimitKV(env, request, "/agents/authorize:miss", VERIFY_MISS_LIMIT, VERIFY_MISS_WINDOW_SECONDS)
348
+ .catch(() => null);
349
+ return (0, errors_1.structuredError)(404, {
350
+ error: "INVALID_USER_CODE",
351
+ message: "User code not found or expired.",
352
+ remediation: "Verify the code displayed on the agent device and try again.",
353
+ field: "user_code",
354
+ });
355
+ }
356
+ const record = await (0, device_authorization_1.loadByDeviceCode)(deviceCode);
357
+ if (!record) {
358
+ await rl
359
+ .applyRateLimitKV(env, request, "/agents/authorize:miss", VERIFY_MISS_LIMIT, VERIFY_MISS_WINDOW_SECONDS)
360
+ .catch(() => null);
361
+ return (0, errors_1.structuredError)(404, {
362
+ error: "INVALID_USER_CODE",
363
+ message: "User code not found or expired.",
364
+ remediation: "Verify the code displayed on the agent device and try again.",
365
+ field: "user_code",
366
+ });
367
+ }
368
+ // Verify the supplied user_code actually matches the record's hash.
369
+ const expected = (0, device_authorization_1.hashUserCode)(userCode);
370
+ if (expected !== record.userCodeHash) {
371
+ const after = await (0, device_authorization_1.incrementFailedLookup)(deviceCode);
372
+ if (after >= device_authorization_1.USER_CODE_FAILURE_LIMIT) {
373
+ return (0, errors_1.structuredError)(410, {
374
+ error: "DEVICE_CODE_LOCKED",
375
+ message: "Too many failed attempts. This device code has been locked.",
376
+ remediation: "Restart the agent authorization flow to get a new code.",
377
+ });
378
+ }
379
+ return (0, errors_1.structuredError)(404, {
380
+ error: "INVALID_USER_CODE",
381
+ message: "User code not found or expired.",
382
+ remediation: "Verify the code displayed on the agent device and try again.",
383
+ field: "user_code",
384
+ });
385
+ }
386
+ if (record.failedLookups >= device_authorization_1.USER_CODE_FAILURE_LIMIT) {
387
+ return (0, errors_1.structuredError)(410, {
388
+ error: "DEVICE_CODE_LOCKED",
389
+ message: "Too many failed attempts. This device code has been locked.",
390
+ remediation: "Restart the agent authorization flow to get a new code.",
391
+ });
392
+ }
393
+ const userPoolId = env.COGNITO_USER_POOL_ID;
394
+ const agentClientId = env.COGNITO_AGENT_CLIENT_ID;
395
+ if (!userPoolId || !agentClientId) {
396
+ return jsonError(env, { error: "not_configured" }, 503);
397
+ }
398
+ // Pull the admin's refresh token off the cookie session — it's the
399
+ // input to AdminInitiateAuth(REFRESH_TOKEN_AUTH).
400
+ const refreshToken = session.refreshToken;
401
+ if (!refreshToken) {
402
+ return (0, errors_1.structuredError)(400, {
403
+ error: "SESSION_MISSING_REFRESH_TOKEN",
404
+ message: "This session has no Cognito refresh token.",
405
+ remediation: "Sign in via the agent client and retry.",
406
+ });
407
+ }
408
+ const issuer = getIssuer();
409
+ const tokens = await issuer.issueForAgent({
410
+ userPoolId,
411
+ clientId: agentClientId,
412
+ username: auth.cognitoSub,
413
+ refreshToken,
414
+ });
415
+ const sessionId = `s_${(0, node_crypto_1.randomBytes)(16).toString("base64url")}`;
416
+ // Naive jti extraction from the new refresh token — Cognito refresh
417
+ // tokens are opaque, so we derive a jti from the token bytes via
418
+ // a stable hash.
419
+ const initialJti = `j_${(0, node_crypto_1.randomBytes)(16).toString("base64url")}`;
420
+ await (0, device_authorization_1.approveDeviceAuth)({
421
+ deviceCode,
422
+ approvedByUserId: auth.userId,
423
+ cognitoSub: auth.cognitoSub,
424
+ tenantId: auth.activeTenantId,
425
+ tokens,
426
+ sessionId,
427
+ });
428
+ const requestIp = (0, trusted_client_ip_1.trustedClientIp)(request, env);
429
+ const sessionRow = {
430
+ sessionId,
431
+ userId: auth.userId,
432
+ cognitoSub: auth.cognitoSub,
433
+ tenantId: auth.activeTenantId,
434
+ currentJti: initialJti,
435
+ status: "active",
436
+ agentLabel: record.agentLabel,
437
+ sourceIp: requestIp,
438
+ createdAt: Math.floor(Date.now() / 1000),
439
+ lastUsedAt: Math.floor(Date.now() / 1000),
440
+ };
441
+ await (0, refresh_detection_1.recordAgentSession)({ session: sessionRow, initialJti });
442
+ // Audit: agent session approved.
443
+ try {
444
+ const audit = getAudit();
445
+ const prisma = (0, db_1.createPrisma)(env);
446
+ // MEDIUM-6: do not include a hash of the device_code in the audit
447
+ // payload — it can be replayed against a stolen device_code as a
448
+ // confirmation oracle. Use agentSessionId as the correlator and
449
+ // generate a fresh UUID for any further cross-event linking.
450
+ await audit.emit({
451
+ type: event_types_1.AuditEventType.AUTH_AGENT_SESSION_APPROVED,
452
+ tenantId: auth.activeTenantId,
453
+ actorUserId: auth.userId,
454
+ payload: {
455
+ agentLabel: record.agentLabel ?? "(unknown)",
456
+ // G4 N1: cap raw User-Agent in the audit payload to match
457
+ // the 256-byte agent-label cap applied at oauth.ts:36.
458
+ userAgent: (request.headers.get("user-agent") ?? "(unknown)").slice(0, 256),
459
+ correlationId: (0, node_crypto_1.randomUUID)(),
460
+ },
461
+ sourceIp: requestIp,
462
+ agentSessionId: sessionId,
463
+ }, prisma);
464
+ }
465
+ catch {
466
+ // Audit failures don't block approval — the AuditEventEmitter
467
+ // logs an audit-fallback line itself.
468
+ }
469
+ const sec = new security_headers_1.SecurityHeaders(env);
470
+ return sec.createSecureResponse(JSON.stringify({ status: "approved" }), {
471
+ status: 200,
472
+ headers: { "content-type": "application/json", "cache-control": "no-store" },
473
+ });
474
+ },
475
+ middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
476
+ description: "Approve a pending agent session",
477
+ },
478
+ ];
479
+ //# sourceMappingURL=agent-authorize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-authorize.js","sourceRoot":"","sources":["../../../src/lib/routes/agent-authorize.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAuEH,sEAEC;AAED,0EAEC;AA3ED,6BAAwB;AACxB,6CAAsD;AACtD,iCAAwC;AACxC,uDAAkD;AAClD,6CAAoD;AAEpD,wEAQuC;AACvC,wCAAkD;AAClD,sDAAsD;AACtD,gGAA0F;AAC1F,4DAGiC;AACjC,kEAGoC;AACpC,8CAA+D;AAC/D,gEAA2D;AAC3D,8CAA4C;AAC5C,wDAA6C;AAC7C,0DAAsD;AACtD,wDAAkE;AAClE,qCAA2C;AAG3C,mDAAmD;AACnD,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,2BAA2B,GAAG,EAAE,CAAC;AACvC;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AACzC,8EAA8E;AAC9E,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,0BAA0B,GAAG,EAAE,CAAC;AACtC,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAElD,MAAM,aAAa,GAAG,OAAC;KACpB,MAAM,CAAC;IACN,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CACrC,CAAC;KACD,MAAM,EAAE,CAAC;AAWZ,6CAA6C;AAC7C,IAAI,IAAI,GAAuB,EAAE,CAAC;AAElC,SAAgB,6BAA6B,CAAC,CAAqB;IACjE,IAAI,GAAG,CAAC,CAAC;AACX,CAAC;AAED,SAAgB,+BAA+B;IAC7C,IAAI,GAAG,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC;IACpC,OAAO,IAAI,iCAAgB,CACzB,IAAI,gEAA6B,CAAC;QAChC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW;KAC5E,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,YAAY,IAAI,IAAI,wBAAiB,EAAE,CAAC;AACtD,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,WAAW,IAAI,IAAI,wBAAW,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,MAAM,GAAG,GAAG;IAC9C,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,0BAA0B;YAC1C,eAAe,EAAE,UAAU;YAC3B,wBAAwB,EAAE,SAAS;SACpC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,GAAY,EAAE,IAAa,EAAE,MAAc;IAC5D,MAAM,GAAG,GAAG,IAAI,kCAAe,CAAC,GAAY,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QACpD,MAAM;QACN,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE;KAC7E,CAAC,CAAC;AACL,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,kBAAkB,CAAC,KAM3B;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW;QAC/B,CAAC,CAAC,uCAAuC;QACzC,CAAC,CAAC,uBAAuB,CAAC;IAE5B,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW;QACjC,CAAC,CAAC;;kCAE4B;QAC9B,CAAC,CAAC,EAAE,CAAC;IAEP,mEAAmE;IACnE,sEAAsE;IACtE,yEAAyE;IACzE,OAAO;;;;;;;;;;;;;;;;;;QAkBD,MAAM,CAAC,OAAO,CAAC;;8BAEO,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,kBAAkB,CAAC;;qCAEvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;;;;;;;0BAOjC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC5C,SAAS;;mDAEsC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;MACnE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,iDAAiD,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;2BAChF,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;;;QAGvD,CAAC;AACT,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,OAAgB,EAChB,GAAY;IAEZ,wEAAwE;IACxE,sEAAsE;IACtE,wEAAwE;IACxE,2CAA2C;IAC3C,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,0CAA0C;IAC1C,MAAM,MAAM,GAAG,IAAA,iBAAY,EAAC,GAAY,CAAC,CAAC;IAC1C,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC;QAC3D,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE;QACnD,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5B,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;KAC1B,CAAC,CAAC;IACH,IAAI,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC;IAEnC,wEAAwE;IACxE,wEAAwE;IACxE,sEAAsE;IACtE,kEAAkE;IAClE,mEAAmE;IACnE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;QAC3C,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE;QAC7B,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qEAAqE;IACrE,MAAM,UAAU,GAAI,OAAO,CAAC,IAAkC,IAAI,UAAU,CAAC;IAE7E,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU;QACV,cAAc,EAAE,gBAAgB,CAAC,QAAQ;QACzC,UAAU,EAAE,gBAAgB,CAAC,MAAM,CAAC,IAAI;QACxC,UAAU,EAAE,gBAAgB,CAAC,IAAI;QACjC,MAAM,EAAE,OAAO,CAAC,KAAK;QACrB,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,gBAAyB,CAAC;KAC3D,CAAC;AACJ,CAAC;AAEY,QAAA,oBAAoB,GAAY;IAC3C;QACE,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;YAC9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACtD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO,YAAY,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,cAAc,GAAG,IAAI,gCAAc,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAC7C,OAAO,EACP,yBAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAC7B,GAAG,CACJ,CAAC;YACF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,QAAQ,GAAG,kBAAkB,CAAC,+BAA+B,WAAW,EAAE,CAAC,CAAC;gBAClF,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;oBACxB,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE,EAAE,QAAQ,EAAE,sBAAsB,QAAQ,EAAE,EAAE;iBACxD,CAAC,CAAC;YACL,CAAC;YAED,kCAAkC;YAClC,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,YAAY,CAAC,2CAA2C,EAAE,GAAG,CAAC,CAAC;YACxE,CAAC;YACD,MAAM,MAAM,GAAG,IAAA,2BAAiB,EAAC,IAAI,EAAE,yBAAU,CAAC,mBAAmB,CAAC,CAAC;YACvE,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,YAAY,CAAC,iEAAiE,EAAE,GAAG,CAAC,CAAC;YAC9F,CAAC;YAED,iEAAiE;YACjE,iEAAiE;YACjE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;YAC5B,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,gBAAgB,CAC7C,GAAG,EACH,OAAO,EACP,0BAA0B,EAC1B,oBAAoB,EACpB,6BAA6B;YAC7B,iEAAiE;YACjE,+CAA+C;YAC/C,SAAS,EACT,SAAS,EACT,QAAQ,CACT,CAAC;YACF,IAAI,aAAa;gBAAE,OAAO,aAAa,CAAC;YAExC,mEAAmE;YACnE,iEAAiE;YACjE,mDAAmD;YACnD,MAAM,QAAQ,GAAG,IAAA,wCAAiB,EAAC,WAAW,CAAC,CAAC;YAChD,MAAM,UAAU,GAAG,MAAM,IAAA,iDAA0B,EAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,IAAA,uCAAgB,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEtE,kEAAkE;YAClE,kEAAkE;YAClE,iEAAiE;YACjE,4CAA4C;YAC5C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,EAAE;qBACL,gBAAgB,CACf,GAAG,EACH,OAAO,EACP,wBAAwB,EACxB,iBAAiB,EACjB,0BAA0B,CAC3B;qBACA,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;YAED,mEAAmE;YACnE,oEAAoE;YACpE,sDAAsD;YACtD,MAAM,QAAQ,GACZ,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC5B,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ;gBACzC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,gBAAgB,CAAC;YAElE,OAAO,YAAY,CACjB,kBAAkB,CAAC;gBACjB,QAAQ,EAAE,WAAW;gBACrB,UAAU,EAAE,MAAM,EAAE,UAAU;gBAC9B,QAAQ,EAAE,IAAA,mCAAe,EAAC,OAAO,EAAE,GAAG,CAAC;gBACvC,WAAW,EAAE,CAAC,QAAQ;gBACtB,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CACH,CAAC;QACJ,CAAC;QACD,UAAU,EAAE,CAAC,IAAA,2BAAc,GAAE,CAAC;QAC9B,WAAW,EAAE,gCAAgC;KAC9C;IAED;QACE,IAAI,EAAE,2BAA2B;QACjC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;YAC9B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;YAE5B,gEAAgE;YAChE,gEAAgE;YAChE,4CAA4C;YAC5C,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,gBAAgB,CAC7C,GAAG,EACH,OAAO,EACP,kCAAkC,EAClC,oBAAoB,EACpB,6BAA6B,EAC7B,SAAS,EACT,SAAS,EACT,QAAQ,CACT,CAAC;YACF,IAAI,aAAa;gBAAE,OAAO,aAAa,CAAC;YAExC,6CAA6C;YAC7C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,gBAAgB,CACvC,GAAG,EACH,OAAO,EACP,2BAA2B,EAC3B,kBAAkB,EAClB,2BAA2B,CAC5B,CAAC;YACF,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;YAE5B,MAAM,cAAc,GAAG,IAAI,gCAAc,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAC7C,OAAO,EACP,yBAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAC7B,GAAG,CACJ,CAAC;YACF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,0BAA0B;oBACnC,WAAW,EAAE,mCAAmC;iBACjD,CAAC,CAAC;YACL,CAAC;YAED,+DAA+D;YAC/D,8DAA8D;YAC9D,sCAAsC;YACtC,MAAM,QAAQ,GACZ,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC5B,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ;gBACzC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,gBAAgB,CAAC;YAClE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,kEAAkE;oBAC3E,WAAW,EAAE,kEAAkE;iBAChF,CAAC,CAAC;YACL,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,0BAA0B;oBACnC,WAAW,EAAE,oEAAoE;iBAClF,CAAC,CAAC;YACL,CAAC;YACD,MAAM,MAAM,GAAG,IAAA,2BAAiB,EAAC,IAAI,EAAE,yBAAU,CAAC,mBAAmB,CAAC,CAAC;YACvE,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;YAE1B,yBAAyB;YACzB,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YACrD,IAAI,IAA4B,CAAC;YACjC,IAAI,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC,EAAE,CAAC;gBACrD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YACjE,CAAC;iBAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC3C,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAA2B,CAAC;YAC1D,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,iBAAiB;oBACxB,OAAO,EAAE,4CAA4C;oBACrD,WAAW,EAAE,4EAA4E;iBAC1F,CAAC,CAAC;YACL,CAAC;YAED,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,iBAAiB;oBACxB,OAAO,EAAE,wBAAwB;oBACjC,WAAW,EAAE,sDAAsD;oBACnE,KAAK,EAAE,WAAW;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,QAAQ,GAAG,IAAA,wCAAiB,EAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1D,MAAM,UAAU,GAAG,MAAM,IAAA,iDAA0B,EAAC,QAAQ,CAAC,CAAC;YAC9D,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,8DAA8D;gBAC9D,gEAAgE;gBAChE,6DAA6D;gBAC7D,MAAM,EAAE;qBACL,gBAAgB,CACf,GAAG,EACH,OAAO,EACP,wBAAwB,EACxB,iBAAiB,EACjB,0BAA0B,CAC3B;qBACA,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBACrB,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,mBAAmB;oBAC1B,OAAO,EAAE,iCAAiC;oBAC1C,WAAW,EAAE,8DAA8D;oBAC3E,KAAK,EAAE,WAAW;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAA,uCAAgB,EAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,EAAE;qBACL,gBAAgB,CACf,GAAG,EACH,OAAO,EACP,wBAAwB,EACxB,iBAAiB,EACjB,0BAA0B,CAC3B;qBACA,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBACrB,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,mBAAmB;oBAC1B,OAAO,EAAE,iCAAiC;oBAC1C,WAAW,EAAE,8DAA8D;oBAC3E,KAAK,EAAE,WAAW;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,oEAAoE;YACpE,MAAM,QAAQ,GAAG,IAAA,mCAAY,EAAC,QAAQ,CAAC,CAAC;YACxC,IAAI,QAAQ,KAAK,MAAM,CAAC,YAAY,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,MAAM,IAAA,4CAAqB,EAAC,UAAU,CAAC,CAAC;gBACtD,IAAI,KAAK,IAAI,8CAAuB,EAAE,CAAC;oBACrC,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;wBAC1B,KAAK,EAAE,oBAAoB;wBAC3B,OAAO,EAAE,6DAA6D;wBACtE,WAAW,EAAE,yDAAyD;qBACvE,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,mBAAmB;oBAC1B,OAAO,EAAE,iCAAiC;oBAC1C,WAAW,EAAE,8DAA8D;oBAC3E,KAAK,EAAE,WAAW;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,IAAI,MAAM,CAAC,aAAa,IAAI,8CAAuB,EAAE,CAAC;gBACpD,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,oBAAoB;oBAC3B,OAAO,EAAE,6DAA6D;oBACtE,WAAW,EAAE,yDAAyD;iBACvE,CAAC,CAAC;YACL,CAAC;YAED,MAAM,UAAU,GAAG,GAAG,CAAC,oBAAoB,CAAC;YAC5C,MAAM,aAAa,GAAG,GAAG,CAAC,uBAAuB,CAAC;YAClD,IAAI,CAAC,UAAU,IAAI,CAAC,aAAa,EAAE,CAAC;gBAClC,OAAO,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC;YAED,mEAAmE;YACnE,kDAAkD;YAClD,MAAM,YAAY,GAAI,OAA+C,CAAC,YAAY,CAAC;YACnF,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,IAAA,wBAAe,EAAC,GAAG,EAAE;oBAC1B,KAAK,EAAE,+BAA+B;oBACtC,OAAO,EAAE,4CAA4C;oBACrD,WAAW,EAAE,yCAAyC;iBACvD,CAAC,CAAC;YACL,CAAC;YAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;gBACxC,UAAU;gBACV,QAAQ,EAAE,aAAa;gBACvB,QAAQ,EAAE,IAAI,CAAC,UAAU;gBACzB,YAAY;aACb,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,KAAK,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/D,oEAAoE;YACpE,iEAAiE;YACjE,iBAAiB;YACjB,MAAM,UAAU,GAAG,KAAK,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAEhE,MAAM,IAAA,wCAAiB,EAAC;gBACtB,UAAU;gBACV,gBAAgB,EAAE,IAAI,CAAC,MAAM;gBAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,QAAQ,EAAE,IAAI,CAAC,cAAc;gBAC7B,MAAM;gBACN,SAAS;aACV,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAA,mCAAe,EAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,UAAU,GAAuB;gBACrC,SAAS;gBACT,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,QAAQ,EAAE,IAAI,CAAC,cAAc;gBAC7B,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,QAAQ;gBAChB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,QAAQ,EAAE,SAAS;gBACnB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;gBACxC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;aAC1C,CAAC;YACF,MAAM,IAAA,sCAAkB,EAAC,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;YAE9D,iCAAiC;YACjC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,IAAA,iBAAY,EAAC,GAAY,CAAC,CAAC;gBAC1C,kEAAkE;gBAClE,iEAAiE;gBACjE,gEAAgE;gBAChE,6DAA6D;gBAC7D,MAAM,KAAK,CAAC,IAAI,CACd;oBACE,IAAI,EAAE,4BAAc,CAAC,2BAA2B;oBAChD,QAAQ,EAAE,IAAI,CAAC,cAAc;oBAC7B,WAAW,EAAE,IAAI,CAAC,MAAM;oBACxB,OAAO,EAAE;wBACP,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,WAAW;wBAC5C,0DAA0D;wBAC1D,uDAAuD;wBACvD,SAAS,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC3E,aAAa,EAAE,IAAA,wBAAU,GAAE;qBAC5B;oBACD,QAAQ,EAAE,SAAS;oBACnB,cAAc,EAAE,SAAS;iBAC1B,EACD,MAAe,CAChB,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,8DAA8D;gBAC9D,sCAAsC;YACxC,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,kCAAe,CAAC,GAAY,CAAC,CAAC;YAC9C,OAAO,GAAG,CAAC,oBAAoB,CAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EACtC;gBACE,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE;aAC7E,CACF,CAAC;QACJ,CAAC;QACD,UAAU,EAAE,CAAC,IAAA,2BAAc,GAAE,EAAE,IAAA,2BAAc,GAAE,CAAC;QAChD,WAAW,EAAE,iCAAiC;KAC/C;CACF,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * User-facing agent session management (T9b-d).
3
+ *
4
+ * GET /api/users/me/agent-sessions
5
+ * POST /api/users/me/agent-sessions/{id}/revoke
6
+ *
7
+ * Backed by the AGENT_REFRESH_TABLE rows written by the device-auth flow.
8
+ */
9
+ import { type CognitoRevoker } from "../oauth/refresh-detection";
10
+ import { AuditEventEmitter } from "../audit/emit";
11
+ import type { Route } from "./types";
12
+ interface AgentSessionDeps {
13
+ cognito?: CognitoRevoker;
14
+ auditEmitter?: AuditEventEmitter;
15
+ }
16
+ export declare function _setAgentSessionDepsForTest(d: AgentSessionDeps): void;
17
+ export declare function _resetAgentSessionDepsForTest(): void;
18
+ export declare const agentSessionsRoutes: Route[];
19
+ export {};
20
+ //# sourceMappingURL=agent-sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sessions.d.ts","sourceRoot":"","sources":["../../../src/lib/routes/agent-sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAUlD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,UAAU,gBAAgB;IACxB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAID,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAErE;AAED,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AAmCD,eAAO,MAAM,mBAAmB,EAAE,KAAK,EAgFtC,CAAC"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * User-facing agent session management (T9b-d).
4
+ *
5
+ * GET /api/users/me/agent-sessions
6
+ * POST /api/users/me/agent-sessions/{id}/revoke
7
+ *
8
+ * Backed by the AGENT_REFRESH_TABLE rows written by the device-auth flow.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.agentSessionsRoutes = void 0;
12
+ exports._setAgentSessionDepsForTest = _setAgentSessionDepsForTest;
13
+ exports._resetAgentSessionDepsForTest = _resetAgentSessionDepsForTest;
14
+ const refresh_detection_1 = require("../oauth/refresh-detection");
15
+ const auth_middleware_1 = require("../auth/auth-middleware");
16
+ const emit_1 = require("../audit/emit");
17
+ const client_cognito_identity_provider_1 = require("@aws-sdk/client-cognito-identity-provider");
18
+ const db_1 = require("../../db");
19
+ const middleware_1 = require("../middleware");
20
+ const trusted_client_ip_1 = require("../net/trusted-client-ip");
21
+ const security_headers_1 = require("../security-headers");
22
+ const errors_1 = require("./errors");
23
+ let deps = {};
24
+ function _setAgentSessionDepsForTest(d) {
25
+ deps = d;
26
+ }
27
+ function _resetAgentSessionDepsForTest() {
28
+ deps = {};
29
+ }
30
+ function getCognito() {
31
+ if (deps.cognito)
32
+ return deps.cognito;
33
+ const region = process.env.COGNITO_REGION || process.env.AWS_REGION || "us-east-1";
34
+ const client = new client_cognito_identity_provider_1.CognitoIdentityProviderClient({ region });
35
+ return {
36
+ async globalSignOut(input) {
37
+ await client.send(new client_cognito_identity_provider_1.AdminUserGlobalSignOutCommand({
38
+ UserPoolId: input.userPoolId,
39
+ Username: input.cognitoUsername,
40
+ }));
41
+ },
42
+ };
43
+ }
44
+ function getAudit() {
45
+ return deps.auditEmitter ?? new emit_1.AuditEventEmitter();
46
+ }
47
+ function publicShape(rec) {
48
+ return {
49
+ id: rec.sessionId,
50
+ agentLabel: rec.agentLabel ?? null,
51
+ sourceIp: rec.sourceIp ?? null,
52
+ createdAt: new Date(rec.createdAt * 1000).toISOString(),
53
+ lastUsedAt: new Date(rec.lastUsedAt * 1000).toISOString(),
54
+ status: rec.status,
55
+ };
56
+ }
57
+ const REVOKE_RE = /^\/api\/users\/me\/agent-sessions\/([^/]+)\/revoke$/;
58
+ exports.agentSessionsRoutes = [
59
+ {
60
+ path: "/api/users/me/agent-sessions",
61
+ method: "GET",
62
+ handler: async (request, env) => {
63
+ const sec = new security_headers_1.SecurityHeaders(env);
64
+ const auth = await (0, auth_middleware_1.authMiddleware)(request, env);
65
+ if (!auth)
66
+ return (0, errors_1.unauthorizedError)(sec);
67
+ const sessions = await (0, refresh_detection_1.listAgentSessions)(auth.userId);
68
+ return sec.createSecureResponse(JSON.stringify({ sessions: sessions.map(publicShape) }), { status: 200, headers: { "content-type": "application/json" } });
69
+ },
70
+ middleware: [(0, middleware_1.corsMiddleware)()],
71
+ description: "List active agent sessions for the current user",
72
+ },
73
+ {
74
+ path: REVOKE_RE,
75
+ method: "POST",
76
+ handler: async (request, env, { pathname }) => {
77
+ const sec = new security_headers_1.SecurityHeaders(env);
78
+ const auth = await (0, auth_middleware_1.authMiddleware)(request, env);
79
+ if (!auth)
80
+ return (0, errors_1.unauthorizedError)(sec);
81
+ const sessionId = pathname.match(REVOKE_RE)?.[1];
82
+ if (!sessionId) {
83
+ return (0, errors_1.structuredError)(400, {
84
+ error: "INVALID_REQUEST",
85
+ message: "Session ID is required.",
86
+ remediation: "Ensure the session ID is included in the URL path.",
87
+ }, sec);
88
+ }
89
+ const session = await (0, refresh_detection_1.getAgentSession)(sessionId);
90
+ if (!session || session.userId !== auth.userId) {
91
+ // 404 — don't reveal cross-user existence.
92
+ return (0, errors_1.structuredError)(404, {
93
+ error: "NOT_FOUND",
94
+ message: "Agent session not found.",
95
+ remediation: "Verify the session ID and ensure it belongs to your account.",
96
+ }, sec);
97
+ }
98
+ const userPoolId = env.COGNITO_USER_POOL_ID;
99
+ if (!userPoolId) {
100
+ return sec.createSecureResponse(JSON.stringify({ error: "not_configured" }), { status: 503, headers: { "content-type": "application/json" } });
101
+ }
102
+ const cognito = getCognito();
103
+ const audit = getAudit();
104
+ // Audit emitter wants a Prisma client — supply the standard shape.
105
+ const prisma = (0, db_1.createPrisma)(env);
106
+ await (0, refresh_detection_1.revokeAgentSession)({
107
+ sessionId,
108
+ userPoolId,
109
+ cognitoUsername: session.cognitoSub,
110
+ cognito,
111
+ audit: {
112
+ emit: async (input) => audit.emit(input, prisma),
113
+ },
114
+ tenantId: session.tenantId,
115
+ actorUserId: auth.userId,
116
+ sourceIp: (0, trusted_client_ip_1.trustedClientIp)(request, env),
117
+ });
118
+ return sec.createSecureResponse(JSON.stringify({ status: "revoked" }), { status: 200, headers: { "content-type": "application/json" } });
119
+ },
120
+ middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
121
+ description: "Revoke an agent session",
122
+ },
123
+ ];
124
+ //# sourceMappingURL=agent-sessions.js.map