@de-otio/trellis 0.6.0 → 0.7.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 (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 +6 -3
  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,50 @@
1
+ /**
2
+ * Auth Middleware
3
+ *
4
+ * Resolves an authenticated request's Cognito JWT into a typed AuthContext.
5
+ * Returns null if the token is absent or invalid — callers treat null as 401.
6
+ *
7
+ * Requires COGNITO_USER_POOL_ID and COGNITO_APP_CLIENT_ID in env.
8
+ */
9
+ import type { Env } from "../../env";
10
+ import type { AuthContext } from "./auth-context";
11
+ /**
12
+ * Extract and verify the Bearer token from the request, then assemble an
13
+ * AuthContext from the JWT claims written by the pre-token-generation Lambda.
14
+ *
15
+ * Returns null when:
16
+ * - No Authorization header is present.
17
+ * - The token fails verification (expired, bad signature, wrong pool/client).
18
+ * - Required claims are missing (userId, activeTenantId).
19
+ */
20
+ export declare function authMiddleware(request: Request, env: Env): Promise<AuthContext | null>;
21
+ /**
22
+ * Assert that the caller's active tenant matches the tenant referenced by
23
+ * the path parameter.
24
+ *
25
+ * Returns a 403 Response when the tenants don't match (unless the caller
26
+ * is a SUPER_ADMIN, who bypasses tenant scope by design).
27
+ * Returns null when the check passes.
28
+ *
29
+ * Use this for ADMIN endpoints (POST/PATCH/DELETE on /api/tenants/:id/...
30
+ * where the attacker already knows the ID and 403 is acceptable per
31
+ * security-and-isolation §"Privilege boundary at the API").
32
+ *
33
+ * G4 MEDIUM-4: this helper deliberately returns 403 (not 404) when the
34
+ * caller is authenticated but acting on a tenant other than their own.
35
+ * That makes the response distinguishable from "tenant does not exist"
36
+ * (which surfaces as 404). The federation onboarding flow depends on
37
+ * that distinction — a caller scripting setup needs to be able to tell
38
+ * whether their target id is unused vs out of reach. Data-side cross-
39
+ * tenant reads should use `requireOwnTenant` (404 for both conditions)
40
+ * instead.
41
+ */
42
+ export declare function requireActiveTenant(auth: AuthContext, tenantIdFromPath: string): Response | null;
43
+ /**
44
+ * Same as requireActiveTenant but returns 404 instead of 403, so the response
45
+ * does not distinguish "tenant exists but you can't see it" from "tenant
46
+ * does not exist". Use this for DATA endpoints (GET /api/tenants/:id and
47
+ * any cross-tenant resource lookup) where existence-leak is the concern.
48
+ */
49
+ export declare function requireOwnTenant(auth: AuthContext, tenantIdFromPath: string): Response | null;
50
+ //# sourceMappingURL=auth-middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-middleware.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/auth-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAsD7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,WAAW,EACjB,gBAAgB,EAAE,MAAM,GACvB,QAAQ,GAAG,IAAI,CAOjB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,gBAAgB,EAAE,MAAM,GACvB,QAAQ,GAAG,IAAI,CAOjB"}
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /**
3
+ * Auth Middleware
4
+ *
5
+ * Resolves an authenticated request's Cognito JWT into a typed AuthContext.
6
+ * Returns null if the token is absent or invalid — callers treat null as 401.
7
+ *
8
+ * Requires COGNITO_USER_POOL_ID and COGNITO_APP_CLIENT_ID in env.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.authMiddleware = authMiddleware;
45
+ exports.requireActiveTenant = requireActiveTenant;
46
+ exports.requireOwnTenant = requireOwnTenant;
47
+ const cognito_jwt_1 = require("./cognito-jwt");
48
+ // cuid v1 is `c[a-z0-9]{24}`. Allow up to 40 chars to absorb future widening
49
+ // and any cuid v2 / nanoid variants without re-issuing every JWT.
50
+ const CUID_RE = /^c[a-z0-9]{24,40}$/;
51
+ /**
52
+ * Extract and verify the Bearer token from the request, then assemble an
53
+ * AuthContext from the JWT claims written by the pre-token-generation Lambda.
54
+ *
55
+ * Returns null when:
56
+ * - No Authorization header is present.
57
+ * - The token fails verification (expired, bad signature, wrong pool/client).
58
+ * - Required claims are missing (userId, activeTenantId).
59
+ */
60
+ async function authMiddleware(request, env) {
61
+ const token = (0, cognito_jwt_1.extractBearerToken)(request.headers.get("Authorization"));
62
+ if (!token)
63
+ return null;
64
+ let claims;
65
+ try {
66
+ claims = await (0, cognito_jwt_1.verifyCognitoJwt)(token);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ const userId = claims["custom:userId"];
72
+ const activeTenantId = claims["custom:activeTenantId"];
73
+ // Both are non-negotiable — pre-token-gen Lambda always writes them.
74
+ if (!userId || !activeTenantId)
75
+ return null;
76
+ // Reject malformed claim values: cuid v1 is c[a-z0-9]{24}. We accept up
77
+ // to 40 chars to leave headroom for the slug-max widening done in T3.
78
+ if (!CUID_RE.test(userId) || !CUID_RE.test(activeTenantId))
79
+ return null;
80
+ // Support both the T2-era single "custom:role" and the T3+ "custom:globalRole".
81
+ const globalRole = (claims["custom:globalRole"] ?? claims["custom:role"] ?? "END_USER");
82
+ // Default to GUEST (least privilege) when the tenantRole claim is missing,
83
+ // so a malformed token never silently confers MEMBER capabilities.
84
+ const tenantRole = (claims["custom:tenantRole"] ?? "GUEST");
85
+ const tenantSlug = claims["custom:tenantSlug"] ?? "";
86
+ const handle = claims["custom:handle"] ?? "";
87
+ const cognitoSub = claims.sub;
88
+ // Memberships are loaded lazily — most requests don't need the full list.
89
+ let membershipsCache = null;
90
+ const membershipsLoader = async () => {
91
+ if (membershipsCache)
92
+ return membershipsCache;
93
+ const { createPrisma } = await Promise.resolve().then(() => __importStar(require("../../db")));
94
+ const db = createPrisma(env);
95
+ membershipsCache = await db.tenantMember.findMany({
96
+ where: { userId, status: "ACTIVE" },
97
+ include: { tenant: true },
98
+ });
99
+ return membershipsCache;
100
+ };
101
+ return {
102
+ cognitoSub,
103
+ userId,
104
+ globalRole,
105
+ activeTenantId,
106
+ tenantSlug,
107
+ tenantRole,
108
+ handle,
109
+ membershipsLoader,
110
+ };
111
+ }
112
+ /**
113
+ * Assert that the caller's active tenant matches the tenant referenced by
114
+ * the path parameter.
115
+ *
116
+ * Returns a 403 Response when the tenants don't match (unless the caller
117
+ * is a SUPER_ADMIN, who bypasses tenant scope by design).
118
+ * Returns null when the check passes.
119
+ *
120
+ * Use this for ADMIN endpoints (POST/PATCH/DELETE on /api/tenants/:id/...
121
+ * where the attacker already knows the ID and 403 is acceptable per
122
+ * security-and-isolation §"Privilege boundary at the API").
123
+ *
124
+ * G4 MEDIUM-4: this helper deliberately returns 403 (not 404) when the
125
+ * caller is authenticated but acting on a tenant other than their own.
126
+ * That makes the response distinguishable from "tenant does not exist"
127
+ * (which surfaces as 404). The federation onboarding flow depends on
128
+ * that distinction — a caller scripting setup needs to be able to tell
129
+ * whether their target id is unused vs out of reach. Data-side cross-
130
+ * tenant reads should use `requireOwnTenant` (404 for both conditions)
131
+ * instead.
132
+ */
133
+ function requireActiveTenant(auth, tenantIdFromPath) {
134
+ if (auth.globalRole === "SUPER_ADMIN")
135
+ return null;
136
+ if (auth.activeTenantId === tenantIdFromPath)
137
+ return null;
138
+ return new Response(JSON.stringify({ error: "FORBIDDEN", message: "Active tenant does not match requested resource" }), { status: 403, headers: { "content-type": "application/json" } });
139
+ }
140
+ /**
141
+ * Same as requireActiveTenant but returns 404 instead of 403, so the response
142
+ * does not distinguish "tenant exists but you can't see it" from "tenant
143
+ * does not exist". Use this for DATA endpoints (GET /api/tenants/:id and
144
+ * any cross-tenant resource lookup) where existence-leak is the concern.
145
+ */
146
+ function requireOwnTenant(auth, tenantIdFromPath) {
147
+ if (auth.globalRole === "SUPER_ADMIN")
148
+ return null;
149
+ if (auth.activeTenantId === tenantIdFromPath)
150
+ return null;
151
+ return new Response(JSON.stringify({ error: "NOT_FOUND", message: "Tenant not found" }), { status: 404, headers: { "content-type": "application/json" } });
152
+ }
153
+ //# sourceMappingURL=auth-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-middleware.js","sourceRoot":"","sources":["../../../src/lib/auth/auth-middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Capability catalog — every action a tenant member can be authorized to do.
3
+ *
4
+ * Naming: `<resource>.<verb>`, lowercase, dot-separated, no abbreviations.
5
+ * Capabilities are tenant-scoped unless prefixed `platform.` (none in MVP).
6
+ *
7
+ * Source of truth: doc/02-technical/identity-federation/05-roles-and-permissions.md.
8
+ */
9
+ export declare const Capability: {
10
+ readonly TenantUpdate: "tenant.update";
11
+ readonly TenantDelete: "tenant.delete";
12
+ readonly TenantSuspend: "tenant.suspend";
13
+ readonly MemberInvite: "member.invite";
14
+ readonly MemberRemove: "member.remove";
15
+ readonly MemberChangeRole: "member.change_role";
16
+ readonly MemberSuspend: "member.suspend";
17
+ readonly MemberView: "member.view";
18
+ readonly IdpConfigure: "idp.configure";
19
+ readonly IdpView: "idp.view";
20
+ readonly RoleMappingEdit: "role_mapping.edit";
21
+ readonly DomainAdd: "domain.add";
22
+ readonly DomainVerify: "domain.verify";
23
+ readonly DomainRemove: "domain.remove";
24
+ readonly DomainView: "domain.view";
25
+ readonly EntityCreate: "entity.create";
26
+ readonly EntityUpdate: "entity.update";
27
+ readonly EntityDelete: "entity.delete";
28
+ readonly EntityView: "entity.view";
29
+ readonly PostCreate: "post.create";
30
+ readonly PostUpdate: "post.update";
31
+ readonly PostDelete: "post.delete";
32
+ readonly PostModerate: "post.moderate";
33
+ readonly PostView: "post.view";
34
+ readonly AuditView: "audit.view";
35
+ readonly ManageAgentSessions: "manage:agent_sessions";
36
+ };
37
+ export type CapabilityValue = (typeof Capability)[keyof typeof Capability];
38
+ /** All capabilities, used by tests + reflection helpers. */
39
+ export declare const ALL_CAPABILITIES: ReadonlyArray<CapabilityValue>;
40
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCb,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAE3E,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,EAAE,aAAa,CAAC,eAAe,CACC,CAAC"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ /**
3
+ * Capability catalog — every action a tenant member can be authorized to do.
4
+ *
5
+ * Naming: `<resource>.<verb>`, lowercase, dot-separated, no abbreviations.
6
+ * Capabilities are tenant-scoped unless prefixed `platform.` (none in MVP).
7
+ *
8
+ * Source of truth: doc/02-technical/identity-federation/05-roles-and-permissions.md.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ALL_CAPABILITIES = exports.Capability = void 0;
12
+ exports.Capability = {
13
+ TenantUpdate: "tenant.update",
14
+ TenantDelete: "tenant.delete",
15
+ TenantSuspend: "tenant.suspend",
16
+ MemberInvite: "member.invite",
17
+ MemberRemove: "member.remove",
18
+ MemberChangeRole: "member.change_role",
19
+ MemberSuspend: "member.suspend",
20
+ MemberView: "member.view",
21
+ IdpConfigure: "idp.configure",
22
+ IdpView: "idp.view",
23
+ RoleMappingEdit: "role_mapping.edit",
24
+ DomainAdd: "domain.add",
25
+ DomainVerify: "domain.verify",
26
+ DomainRemove: "domain.remove",
27
+ DomainView: "domain.view",
28
+ EntityCreate: "entity.create",
29
+ EntityUpdate: "entity.update",
30
+ EntityDelete: "entity.delete",
31
+ EntityView: "entity.view",
32
+ PostCreate: "post.create",
33
+ PostUpdate: "post.update",
34
+ PostDelete: "post.delete",
35
+ PostModerate: "post.moderate",
36
+ PostView: "post.view",
37
+ AuditView: "audit.view",
38
+ // Agent session management (T9b-d) — approve, list, revoke device-auth
39
+ // sessions on behalf of the tenant. Granted to ADMIN/OWNER.
40
+ ManageAgentSessions: "manage:agent_sessions",
41
+ };
42
+ /** All capabilities, used by tests + reflection helpers. */
43
+ exports.ALL_CAPABILITIES = Object.values(exports.Capability);
44
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../../src/lib/auth/capabilities.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEU,QAAA,UAAU,GAAG;IACxB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,aAAa,EAAE,gBAAgB;IAE/B,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,gBAAgB,EAAE,oBAAoB;IACtC,aAAa,EAAE,gBAAgB;IAC/B,UAAU,EAAE,aAAa;IAEzB,YAAY,EAAE,eAAe;IAC7B,OAAO,EAAE,UAAU;IACnB,eAAe,EAAE,mBAAmB;IAEpC,SAAS,EAAE,YAAY;IACvB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,aAAa;IAEzB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,aAAa;IAEzB,UAAU,EAAE,aAAa;IACzB,UAAU,EAAE,aAAa;IACzB,UAAU,EAAE,aAAa;IACzB,YAAY,EAAE,eAAe;IAC7B,QAAQ,EAAE,WAAW;IAErB,SAAS,EAAE,YAAY;IAEvB,uEAAuE;IACvE,4DAA4D;IAC5D,mBAAmB,EAAE,uBAAuB;CACpC,CAAC;AAIX,4DAA4D;AAC/C,QAAA,gBAAgB,GAC3B,MAAM,CAAC,MAAM,CAAC,kBAAU,CAAmC,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * DynamoDB-backed claims cache for the pre-token-generation Lambda
3
+ * (T2 — JIT provisioning).
4
+ *
5
+ * Storage layout (single-table on the existing `{stage}-skybber` table):
6
+ * pk = `claims:{cognitoSub}`
7
+ * sk = `meta`
8
+ * ttl = epoch seconds; DynamoDB-managed expiry plus a manual check on read
9
+ * (DDB TTL deletes lag by up to 48h, so we never trust the row's
10
+ * existence alone)
11
+ *
12
+ * Concurrency: writes use a `ConditionExpression` that the existing row's
13
+ * `ttl` is missing or older than the incoming `ttl`. Two simultaneous
14
+ * pre-token-gen invocations for the same user (rare, but possible during a
15
+ * burst of token refreshes) cannot stale-overwrite a fresh entry.
16
+ */
17
+ import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
18
+ export interface CachedClaims {
19
+ /** Skybber `User.id` (cuid). May be empty string for drift sentinel. */
20
+ userId: string;
21
+ /** Global `UserRole` enum value. May be empty string for drift sentinel. */
22
+ globalRole: string;
23
+ /** `Tenant.id` of the user's currently-active tenant. */
24
+ activeTenantId: string;
25
+ /** `Tenant.slug` of the active tenant. */
26
+ tenantSlug: string;
27
+ /** `TenantRole` enum value within the active tenant. May be empty. */
28
+ tenantRole: string;
29
+ /** ActivityPub-style handle. May be empty. */
30
+ handle: string;
31
+ }
32
+ export declare const DEFAULT_CACHE_TTL_SECONDS = 3600;
33
+ export declare class ClaimsCache {
34
+ private readonly client;
35
+ private readonly tableName;
36
+ constructor(client: DynamoDBClient, tableName: string);
37
+ /**
38
+ * Returns cached claims if a fresh entry exists, else null. Stale rows
39
+ * (ttl in the past) are treated as a miss; we let DDB's own TTL sweep
40
+ * eventually delete them.
41
+ */
42
+ get(cognitoSub: string): Promise<CachedClaims | null>;
43
+ /**
44
+ * Returns the user's last-known activeTenantId, regardless of TTL. Used by
45
+ * the pre-token-generation Lambda on cache miss so a user's explicit
46
+ * tenant-switch survives cache expiry rather than reverting to the
47
+ * first-org-tenant heuristic.
48
+ */
49
+ getActiveTenantPreference(cognitoSub: string): Promise<string | null>;
50
+ /**
51
+ * Writes a cache entry. Uses a `ConditionExpression` so a stale write
52
+ * (e.g., one that started before a newer entry was written) cannot
53
+ * overwrite a fresher row. On collision we silently swallow the
54
+ * conditional-check failure — the cache still holds an acceptable value.
55
+ */
56
+ put(cognitoSub: string, claims: CachedClaims, ttlSeconds?: number): Promise<void>;
57
+ /**
58
+ * Forcibly remove a cache entry — used by admin paths (member-remove,
59
+ * role change, OWNER transfer) to make sure the next token refresh hits
60
+ * RDS rather than serving a stale role.
61
+ */
62
+ invalidate(cognitoSub: string): Promise<void>;
63
+ }
64
+ /**
65
+ * Convenience constructor used by the Lambda handler. Reads the table name
66
+ * from `DYNAMODB_TABLE` and the region from `AWS_REGION`. Tests construct
67
+ * a `ClaimsCache` directly with a mock client.
68
+ */
69
+ export declare function createClaimsCacheFromEnv(): ClaimsCache;
70
+ //# sourceMappingURL=claims-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims-cache.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/claims-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,cAAc,EAIf,MAAM,0BAA0B,CAAC;AAGlC,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAU9C,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM;IAGpC;;;;OAIG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAqB3D;;;;;OAKG;IACG,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa3E;;;;;OAKG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,EACpB,UAAU,GAAE,MAAkC,GAC7C,OAAO,CAAC,IAAI,CAAC;IA6BhB;;;;OAIG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQpD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,WAAW,CAOtD"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ /**
3
+ * DynamoDB-backed claims cache for the pre-token-generation Lambda
4
+ * (T2 — JIT provisioning).
5
+ *
6
+ * Storage layout (single-table on the existing `{stage}-skybber` table):
7
+ * pk = `claims:{cognitoSub}`
8
+ * sk = `meta`
9
+ * ttl = epoch seconds; DynamoDB-managed expiry plus a manual check on read
10
+ * (DDB TTL deletes lag by up to 48h, so we never trust the row's
11
+ * existence alone)
12
+ *
13
+ * Concurrency: writes use a `ConditionExpression` that the existing row's
14
+ * `ttl` is missing or older than the incoming `ttl`. Two simultaneous
15
+ * pre-token-gen invocations for the same user (rare, but possible during a
16
+ * burst of token refreshes) cannot stale-overwrite a fresh entry.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.ClaimsCache = exports.DEFAULT_CACHE_TTL_SECONDS = void 0;
20
+ exports.createClaimsCacheFromEnv = createClaimsCacheFromEnv;
21
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
22
+ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
23
+ exports.DEFAULT_CACHE_TTL_SECONDS = 3600;
24
+ function pkFor(cognitoSub) {
25
+ return `claims:${cognitoSub}`;
26
+ }
27
+ function nowSeconds() {
28
+ return Math.floor(Date.now() / 1000);
29
+ }
30
+ class ClaimsCache {
31
+ client;
32
+ tableName;
33
+ constructor(client, tableName) {
34
+ this.client = client;
35
+ this.tableName = tableName;
36
+ }
37
+ /**
38
+ * Returns cached claims if a fresh entry exists, else null. Stale rows
39
+ * (ttl in the past) are treated as a miss; we let DDB's own TTL sweep
40
+ * eventually delete them.
41
+ */
42
+ async get(cognitoSub) {
43
+ const result = await this.client.send(new client_dynamodb_1.GetItemCommand({
44
+ TableName: this.tableName,
45
+ Key: (0, util_dynamodb_1.marshall)({ pk: pkFor(cognitoSub), sk: "meta" }),
46
+ }));
47
+ if (!result.Item)
48
+ return null;
49
+ const item = (0, util_dynamodb_1.unmarshall)(result.Item);
50
+ const ttl = typeof item.ttl === "number" ? item.ttl : 0;
51
+ if (!ttl || ttl <= nowSeconds())
52
+ return null;
53
+ return {
54
+ userId: item.userId ?? "",
55
+ globalRole: item.globalRole ?? "",
56
+ activeTenantId: item.activeTenantId ?? "",
57
+ tenantSlug: item.tenantSlug ?? "",
58
+ tenantRole: item.tenantRole ?? "",
59
+ handle: item.handle ?? "",
60
+ };
61
+ }
62
+ /**
63
+ * Returns the user's last-known activeTenantId, regardless of TTL. Used by
64
+ * the pre-token-generation Lambda on cache miss so a user's explicit
65
+ * tenant-switch survives cache expiry rather than reverting to the
66
+ * first-org-tenant heuristic.
67
+ */
68
+ async getActiveTenantPreference(cognitoSub) {
69
+ const result = await this.client.send(new client_dynamodb_1.GetItemCommand({
70
+ TableName: this.tableName,
71
+ Key: (0, util_dynamodb_1.marshall)({ pk: pkFor(cognitoSub), sk: "meta" }),
72
+ }));
73
+ if (!result.Item)
74
+ return null;
75
+ const item = (0, util_dynamodb_1.unmarshall)(result.Item);
76
+ const activeTenantId = item.activeTenantId ?? "";
77
+ return activeTenantId || null;
78
+ }
79
+ /**
80
+ * Writes a cache entry. Uses a `ConditionExpression` so a stale write
81
+ * (e.g., one that started before a newer entry was written) cannot
82
+ * overwrite a fresher row. On collision we silently swallow the
83
+ * conditional-check failure — the cache still holds an acceptable value.
84
+ */
85
+ async put(cognitoSub, claims, ttlSeconds = exports.DEFAULT_CACHE_TTL_SECONDS) {
86
+ const expiresAt = nowSeconds() + ttlSeconds;
87
+ try {
88
+ await this.client.send(new client_dynamodb_1.PutItemCommand({
89
+ TableName: this.tableName,
90
+ Item: (0, util_dynamodb_1.marshall)({
91
+ pk: pkFor(cognitoSub),
92
+ sk: "meta",
93
+ userId: claims.userId,
94
+ globalRole: claims.globalRole,
95
+ activeTenantId: claims.activeTenantId,
96
+ tenantSlug: claims.tenantSlug,
97
+ tenantRole: claims.tenantRole,
98
+ handle: claims.handle,
99
+ ttl: expiresAt,
100
+ }),
101
+ ConditionExpression: "attribute_not_exists(#ttl) OR #ttl < :incomingTtl",
102
+ ExpressionAttributeNames: { "#ttl": "ttl" },
103
+ ExpressionAttributeValues: (0, util_dynamodb_1.marshall)({ ":incomingTtl": expiresAt }),
104
+ }));
105
+ }
106
+ catch (err) {
107
+ const name = err.name;
108
+ if (name === "ConditionalCheckFailedException")
109
+ return;
110
+ throw err;
111
+ }
112
+ }
113
+ /**
114
+ * Forcibly remove a cache entry — used by admin paths (member-remove,
115
+ * role change, OWNER transfer) to make sure the next token refresh hits
116
+ * RDS rather than serving a stale role.
117
+ */
118
+ async invalidate(cognitoSub) {
119
+ await this.client.send(new client_dynamodb_1.DeleteItemCommand({
120
+ TableName: this.tableName,
121
+ Key: (0, util_dynamodb_1.marshall)({ pk: pkFor(cognitoSub), sk: "meta" }),
122
+ }));
123
+ }
124
+ }
125
+ exports.ClaimsCache = ClaimsCache;
126
+ /**
127
+ * Convenience constructor used by the Lambda handler. Reads the table name
128
+ * from `DYNAMODB_TABLE` and the region from `AWS_REGION`. Tests construct
129
+ * a `ClaimsCache` directly with a mock client.
130
+ */
131
+ function createClaimsCacheFromEnv() {
132
+ const tableName = process.env.DYNAMODB_TABLE;
133
+ if (!tableName) {
134
+ throw new Error("DYNAMODB_TABLE env var is required for ClaimsCache");
135
+ }
136
+ const client = new client_dynamodb_1.DynamoDBClient({ region: process.env.AWS_REGION });
137
+ return new ClaimsCache(client, tableName);
138
+ }
139
+ //# sourceMappingURL=claims-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims-cache.js","sourceRoot":"","sources":["../../../src/lib/auth/claims-cache.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,13 @@ export interface CognitoJwtClaims {
11
11
  username: string;
12
12
  email?: string;
13
13
  "custom:userId"?: string;
14
+ /** Pre-T3 legacy claim — single global role. */
14
15
  "custom:role"?: string;
16
+ /** T3+ global UserRole claim. */
17
+ "custom:globalRole"?: string;
18
+ "custom:activeTenantId"?: string;
19
+ "custom:tenantSlug"?: string;
20
+ "custom:tenantRole"?: string;
15
21
  "custom:handle"?: string;
16
22
  "custom:dataRegion"?: string;
17
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cognito-jwt.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2BH,4DAA4D;AAC5D,wBAAgB,aAAa,SAG5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU/E;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG3E"}
1
+ {"version":3,"file":"cognito-jwt.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2BH,4DAA4D;AAC5D,wBAAgB,aAAa,SAG5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU/E;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"cognito-jwt.js","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AA4BH,sCAGC;AAYD,4CAUC;AAED,gDAGC;AAxDD,mDAAoD;AAEpD,IAAI,QAAQ,GAAwD,IAAI,CAAC;AACzE,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAE5D,SAAS,WAAW;IAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,kEAAkE;IAClE,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,GAAG,WAAW,GAAG,mBAAmB,CAAC,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACnD,IAAI,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QACD,QAAQ,GAAG,mCAAkB,CAAC,MAAM,CAAC;YACnC,UAAU;YACV,QAAQ,EAAE,IAAI;YACd,QAAQ;SACT,CAAC,CAAC;QACH,WAAW,GAAG,GAAG,CAAC;IACpB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4DAA4D;AAC5D,SAAgB,aAAa;IAC3B,QAAQ,GAAG,IAAI,CAAC;IAChB,WAAW,GAAG,CAAC,CAAC;AAClB,CAAC;AAYM,KAAK,UAAU,gBAAgB,CAAC,KAAa;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAsC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gFAAgF;QAChF,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAsC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAyB;IAC1D,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"cognito-jwt.js","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AA4BH,sCAGC;AAkBD,4CAUC;AAED,gDAGC;AA9DD,mDAAoD;AAEpD,IAAI,QAAQ,GAAwD,IAAI,CAAC;AACzE,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAE5D,SAAS,WAAW;IAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,kEAAkE;IAClE,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,GAAG,WAAW,GAAG,mBAAmB,CAAC,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACnD,IAAI,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QACD,QAAQ,GAAG,mCAAkB,CAAC,MAAM,CAAC;YACnC,UAAU;YACV,QAAQ,EAAE,IAAI;YACd,QAAQ;SACT,CAAC,CAAC;QACH,WAAW,GAAG,GAAG,CAAC;IACpB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4DAA4D;AAC5D,SAAgB,aAAa;IAC3B,QAAQ,GAAG,IAAI,CAAC;IAChB,WAAW,GAAG,CAAC,CAAC;AAClB,CAAC;AAkBM,KAAK,UAAU,gBAAgB,CAAC,KAAa;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAsC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gFAAgF;QAChF,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAsC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAyB;IAC1D,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Builds the Cognito Hosted UI OAuth2 authorization URL for federated sign-in.
3
+ *
4
+ * The IdP name in Cognito follows the convention `tenant-{cuid}` (using the
5
+ * full tenant cuid, truncated to 25 chars to fit Cognito's 32-char provider-
6
+ * name quota). Sign-in discovery routes by the same convention, so the value
7
+ * passed in is what T5 provisioned.
8
+ *
9
+ * All URL parameters are server-derived; callers supply only the Prisma-loaded
10
+ * cognitoIdpName — no arbitrary IdP names accepted from request input.
11
+ */
12
+ export { cognitoIdpName } from "../tenant/idp-name";
13
+ export interface IdpRedirectConfig {
14
+ hostedUiDomain: string;
15
+ clientId: string;
16
+ redirectUri: string;
17
+ }
18
+ export interface IdpRedirectParams {
19
+ cognitoIdpName: string;
20
+ tenantSlug: string;
21
+ }
22
+ export interface IdpRedirectResult {
23
+ idpRedirect: string;
24
+ tenantSlug: string;
25
+ }
26
+ /**
27
+ * Builds the Cognito Hosted UI authorization URL.
28
+ *
29
+ * Scope is always `openid email profile` — no caller-supplied scope to prevent
30
+ * privilege escalation via scope injection.
31
+ */
32
+ export declare function buildIdpRedirectUrl(config: IdpRedirectConfig, params: IdpRedirectParams): string;
33
+ /**
34
+ * Reads IdP redirect config from the environment.
35
+ * Env vars read here are defined in src/env.ts and must come from there —
36
+ * no direct process.env access outside buildEnv().
37
+ */
38
+ export declare function getIdpRedirectConfig(env: {
39
+ COGNITO_HOSTED_UI_DOMAIN?: string;
40
+ COGNITO_APP_CLIENT_ID?: string;
41
+ COGNITO_REDIRECT_URI?: string;
42
+ }): IdpRedirectConfig;
43
+ //# sourceMappingURL=idp-redirect-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idp-redirect-builder.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/idp-redirect-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAUR;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IACxC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,GAAG,iBAAiB,CAMpB"}