@nextsparkjs/core 0.1.0-beta.185 → 0.1.0-beta.186

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 (386) hide show
  1. package/dist/components/app/guards/DeveloperGuard.d.ts.map +1 -1
  2. package/dist/components/app/guards/SuperAdminGuard.d.ts.map +1 -1
  3. package/dist/components/app/layouts/PublicFooter.d.ts.map +1 -1
  4. package/dist/components/app/layouts/PublicFooter.js +2 -2
  5. package/dist/components/app/layouts/PublicNavbar.d.ts.map +1 -1
  6. package/dist/components/app/layouts/PublicNavbar.js +2 -2
  7. package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
  8. package/dist/components/app/misc/ThemeToggle.js +4 -1
  9. package/dist/components/auth/DevKeyring.d.ts.map +1 -1
  10. package/dist/components/auth/DevKeyring.js +10 -2
  11. package/dist/components/auth/SessionCookieRefresher.d.ts +21 -0
  12. package/dist/components/auth/SessionCookieRefresher.d.ts.map +1 -0
  13. package/dist/components/auth/SessionCookieRefresher.js +11 -0
  14. package/dist/components/auth/forms/LoginForm.d.ts.map +1 -1
  15. package/dist/components/auth/forms/LoginForm.js +300 -6
  16. package/dist/components/auth/index.d.ts +1 -0
  17. package/dist/components/auth/index.d.ts.map +1 -1
  18. package/dist/components/auth/index.js +2 -0
  19. package/dist/components/billing/InvoicesTable.d.ts.map +1 -1
  20. package/dist/components/billing/InvoicesTable.js +4 -3
  21. package/dist/components/dashboard/block-editor/dynamic-form.d.ts.map +1 -1
  22. package/dist/components/dashboard/layouts/AuthGuard.d.ts.map +1 -1
  23. package/dist/components/dashboard/layouts/AuthGuard.js +2 -2
  24. package/dist/components/dashboard/layouts/DashboardAuthLayout.d.ts.map +1 -1
  25. package/dist/components/dashboard/layouts/DashboardAuthLayout.js +2 -2
  26. package/dist/components/dashboard/layouts/DashboardAuthSkeleton.d.ts +17 -0
  27. package/dist/components/dashboard/layouts/DashboardAuthSkeleton.d.ts.map +1 -0
  28. package/dist/components/dashboard/layouts/DashboardAuthSkeleton.js +52 -0
  29. package/dist/components/dashboard/layouts/Sidebar.d.ts.map +1 -1
  30. package/dist/components/dashboard/layouts/Sidebar.js +2 -3
  31. package/dist/components/dashboard/layouts/TopNavbar.js +2 -2
  32. package/dist/components/dashboard/layouts/index.d.ts +1 -0
  33. package/dist/components/dashboard/layouts/index.d.ts.map +1 -1
  34. package/dist/components/dashboard/layouts/index.js +2 -0
  35. package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
  36. package/dist/components/entities/EntityFieldRenderer.js +3 -0
  37. package/dist/components/entities/EntityTable.d.ts.map +1 -1
  38. package/dist/components/entities/EntityTable.js +2 -1
  39. package/dist/components/entities/wrappers/EntityFormWrapper.d.ts.map +1 -1
  40. package/dist/components/entities/wrappers/EntityFormWrapper.js +7 -2
  41. package/dist/components/ui/combobox.d.ts +8 -1
  42. package/dist/components/ui/combobox.d.ts.map +1 -1
  43. package/dist/components/ui/combobox.js +37 -44
  44. package/dist/components/ui/country-select.d.ts +3 -1
  45. package/dist/components/ui/country-select.d.ts.map +1 -1
  46. package/dist/components/ui/country-select.js +3 -1
  47. package/dist/components/ui/currency-select.d.ts +3 -1
  48. package/dist/components/ui/currency-select.d.ts.map +1 -1
  49. package/dist/components/ui/currency-select.js +3 -1
  50. package/dist/components/ui/sheet.d.ts +5 -0
  51. package/dist/components/ui/sheet.d.ts.map +1 -1
  52. package/dist/components/ui/sheet.js +46 -26
  53. package/dist/components/ui/timezone-select.d.ts +3 -1
  54. package/dist/components/ui/timezone-select.d.ts.map +1 -1
  55. package/dist/components/ui/timezone-select.js +3 -1
  56. package/dist/contexts/TeamContext.d.ts +6 -0
  57. package/dist/contexts/TeamContext.d.ts.map +1 -1
  58. package/dist/contexts/TeamContext.js +8 -1
  59. package/dist/emails/otp-verification.d.ts.map +1 -1
  60. package/dist/emails/reset-password.d.ts.map +1 -1
  61. package/dist/emails/team-invitation.d.ts.map +1 -1
  62. package/dist/emails/team-invitation.js +3 -2
  63. package/dist/emails/verify-email.d.ts.map +1 -1
  64. package/dist/hooks/index.d.ts +1 -0
  65. package/dist/hooks/index.d.ts.map +1 -1
  66. package/dist/hooks/index.js +1 -0
  67. package/dist/hooks/useAuth.d.ts +29 -0
  68. package/dist/hooks/useAuth.d.ts.map +1 -1
  69. package/dist/hooks/useAuth.js +24 -0
  70. package/dist/hooks/useEnsureUserMetadata.d.ts +22 -0
  71. package/dist/hooks/useEnsureUserMetadata.d.ts.map +1 -1
  72. package/dist/hooks/useEnsureUserMetadata.js +18 -5
  73. package/dist/hooks/useSessionCookieRefresh.d.ts +35 -0
  74. package/dist/hooks/useSessionCookieRefresh.d.ts.map +1 -0
  75. package/dist/hooks/useSessionCookieRefresh.js +49 -0
  76. package/dist/lib/api/api-error.d.ts +3 -1
  77. package/dist/lib/api/api-error.d.ts.map +1 -1
  78. package/dist/lib/api/api-error.js +4 -2
  79. package/dist/lib/api/auth/dual-auth.d.ts +38 -3
  80. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  81. package/dist/lib/api/auth/dual-auth.js +42 -7
  82. package/dist/lib/api/auth/permissions.d.ts +7 -2
  83. package/dist/lib/api/auth/permissions.d.ts.map +1 -1
  84. package/dist/lib/api/auth/permissions.js +2 -2
  85. package/dist/lib/api/auth/scope-policy.d.ts +71 -0
  86. package/dist/lib/api/auth/scope-policy.d.ts.map +1 -0
  87. package/dist/lib/api/auth/scope-policy.js +53 -0
  88. package/dist/lib/api/auth.d.ts +15 -0
  89. package/dist/lib/api/auth.d.ts.map +1 -1
  90. package/dist/lib/api/auth.js +17 -4
  91. package/dist/lib/api/entity/audit-log.d.ts +35 -0
  92. package/dist/lib/api/entity/audit-log.d.ts.map +1 -0
  93. package/dist/lib/api/entity/audit-log.js +35 -0
  94. package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
  95. package/dist/lib/api/entity/generic-handler.js +315 -134
  96. package/dist/lib/api/helpers.d.ts +29 -4
  97. package/dist/lib/api/helpers.d.ts.map +1 -1
  98. package/dist/lib/api/helpers.js +30 -6
  99. package/dist/lib/api/keys.d.ts +16 -0
  100. package/dist/lib/api/keys.d.ts.map +1 -1
  101. package/dist/lib/api/keys.js +19 -1
  102. package/dist/lib/api/routes/patterns-usages.d.ts.map +1 -1
  103. package/dist/lib/api/routes/patterns-usages.js +3 -11
  104. package/dist/lib/auth/auth-methods.d.ts +52 -0
  105. package/dist/lib/auth/auth-methods.d.ts.map +1 -0
  106. package/dist/lib/auth/auth-methods.js +63 -0
  107. package/dist/lib/auth/registration-guard-plugin.d.ts.map +1 -1
  108. package/dist/lib/auth/registration-helpers.d.ts +9 -0
  109. package/dist/lib/auth/registration-helpers.d.ts.map +1 -1
  110. package/dist/lib/auth/registration-helpers.js +8 -2
  111. package/dist/lib/auth/security-notifications/device-fingerprint.d.ts +52 -0
  112. package/dist/lib/auth/security-notifications/device-fingerprint.d.ts.map +1 -0
  113. package/dist/lib/auth/security-notifications/device-fingerprint.js +42 -0
  114. package/dist/lib/auth/security-notifications/dispatcher.d.ts +37 -0
  115. package/dist/lib/auth/security-notifications/dispatcher.d.ts.map +1 -0
  116. package/dist/lib/auth/security-notifications/dispatcher.js +157 -0
  117. package/dist/lib/auth/security-notifications/index.d.ts +20 -0
  118. package/dist/lib/auth/security-notifications/index.d.ts.map +1 -0
  119. package/dist/lib/auth/security-notifications/index.js +22 -0
  120. package/dist/lib/auth/security-notifications/registry.d.ts +36 -0
  121. package/dist/lib/auth/security-notifications/registry.d.ts.map +1 -0
  122. package/dist/lib/auth/security-notifications/registry.js +26 -0
  123. package/dist/lib/auth/security-notifications/templates/email-changed.d.ts +12 -0
  124. package/dist/lib/auth/security-notifications/templates/email-changed.d.ts.map +1 -0
  125. package/dist/lib/auth/security-notifications/templates/email-changed.js +43 -0
  126. package/dist/lib/auth/security-notifications/templates/new-device-login.d.ts +7 -0
  127. package/dist/lib/auth/security-notifications/templates/new-device-login.d.ts.map +1 -0
  128. package/dist/lib/auth/security-notifications/templates/new-device-login.js +46 -0
  129. package/dist/lib/auth/security-notifications/templates/password-changed.d.ts +7 -0
  130. package/dist/lib/auth/security-notifications/templates/password-changed.d.ts.map +1 -0
  131. package/dist/lib/auth/security-notifications/templates/password-changed.js +35 -0
  132. package/dist/lib/auth/security-notifications/templates/shared.d.ts +36 -0
  133. package/dist/lib/auth/security-notifications/templates/shared.d.ts.map +1 -0
  134. package/dist/lib/auth/security-notifications/templates/shared.js +68 -0
  135. package/dist/lib/auth/security-notifications/types.d.ts +74 -0
  136. package/dist/lib/auth/security-notifications/types.d.ts.map +1 -0
  137. package/dist/lib/auth/security-notifications/types.js +0 -0
  138. package/dist/lib/auth/session-config.d.ts +37 -0
  139. package/dist/lib/auth/session-config.d.ts.map +1 -0
  140. package/dist/lib/auth/session-config.js +59 -0
  141. package/dist/lib/auth/session-refresh.d.ts +46 -0
  142. package/dist/lib/auth/session-refresh.d.ts.map +1 -0
  143. package/dist/lib/auth/session-refresh.js +11 -0
  144. package/dist/lib/auth-client.d.ts +1639 -0
  145. package/dist/lib/auth-client.d.ts.map +1 -0
  146. package/dist/lib/auth-client.js +4 -0
  147. package/dist/lib/auth.d.ts.map +1 -1
  148. package/dist/lib/auth.js +21 -8
  149. package/dist/lib/billing/gateways/factory.d.ts +8 -3
  150. package/dist/lib/billing/gateways/factory.d.ts.map +1 -1
  151. package/dist/lib/billing/gateways/factory.js +37 -23
  152. package/dist/lib/billing/stripe-webhook.d.ts.map +1 -1
  153. package/dist/lib/billing/stripe-webhook.js +2 -1
  154. package/dist/lib/config/app.config.d.ts.map +1 -1
  155. package/dist/lib/config/app.config.js +71 -0
  156. package/dist/lib/config/config-sync.d.ts +1 -4
  157. package/dist/lib/config/config-sync.d.ts.map +1 -1
  158. package/dist/lib/config/config-sync.js +6 -2
  159. package/dist/lib/config/types.d.ts +130 -0
  160. package/dist/lib/config/types.d.ts.map +1 -1
  161. package/dist/lib/entities/entity-hooks.d.ts +9 -1
  162. package/dist/lib/entities/entity-hooks.d.ts.map +1 -1
  163. package/dist/lib/entities/entity-hooks.js +77 -4
  164. package/dist/lib/entities/schema-generator.d.ts.map +1 -1
  165. package/dist/lib/entities/schema-generator.js +20 -4
  166. package/dist/lib/entities/serialization.d.ts +2 -2
  167. package/dist/lib/entities/serialization.d.ts.map +1 -1
  168. package/dist/lib/entities/serialization.js +3 -2
  169. package/dist/lib/entities/types.d.ts +8 -0
  170. package/dist/lib/entities/types.d.ts.map +1 -1
  171. package/dist/lib/locale.d.ts.map +1 -1
  172. package/dist/lib/locale.js +4 -1
  173. package/dist/lib/mcp/audit.d.ts +8 -4
  174. package/dist/lib/mcp/audit.d.ts.map +1 -1
  175. package/dist/lib/plugins/hook-system.d.ts +13 -0
  176. package/dist/lib/plugins/hook-system.d.ts.map +1 -1
  177. package/dist/lib/plugins/hook-system.js +32 -2
  178. package/dist/lib/scheduled-actions/handlers/index.d.ts +1 -0
  179. package/dist/lib/scheduled-actions/handlers/index.d.ts.map +1 -1
  180. package/dist/lib/scheduled-actions/handlers/index.js +3 -1
  181. package/dist/lib/scheduled-actions/handlers/security-notification.d.ts +26 -0
  182. package/dist/lib/scheduled-actions/handlers/security-notification.d.ts.map +1 -0
  183. package/dist/lib/scheduled-actions/handlers/security-notification.js +54 -0
  184. package/dist/lib/selectors/core-selectors.d.ts +12 -0
  185. package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
  186. package/dist/lib/selectors/domains/auth.selectors.d.ts +12 -0
  187. package/dist/lib/selectors/domains/auth.selectors.d.ts.map +1 -1
  188. package/dist/lib/selectors/domains/auth.selectors.js +14 -1
  189. package/dist/lib/selectors/selectors.d.ts +24 -0
  190. package/dist/lib/selectors/selectors.d.ts.map +1 -1
  191. package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
  192. package/dist/lib/services/generic-entity.service.js +16 -32
  193. package/dist/lib/services/membership.service.d.ts +10 -2
  194. package/dist/lib/services/membership.service.d.ts.map +1 -1
  195. package/dist/lib/services/membership.service.js +37 -16
  196. package/dist/lib/services/subscription.service.d.ts.map +1 -1
  197. package/dist/lib/services/subscription.service.js +2 -1
  198. package/dist/lib/services/team-member.service.d.ts +15 -3
  199. package/dist/lib/services/team-member.service.d.ts.map +1 -1
  200. package/dist/lib/services/team-member.service.js +27 -6
  201. package/dist/lib/services/team.service.d.ts.map +1 -1
  202. package/dist/lib/teams/permissions.d.ts +3 -1
  203. package/dist/lib/teams/permissions.d.ts.map +1 -1
  204. package/dist/lib/teams/permissions.js +6 -0
  205. package/dist/lib/teams/schema.d.ts.map +1 -1
  206. package/dist/lib/teams/schema.js +3 -0
  207. package/dist/lib/theme/forced-theme.d.ts +34 -0
  208. package/dist/lib/theme/forced-theme.d.ts.map +1 -0
  209. package/dist/lib/theme/forced-theme.js +27 -0
  210. package/dist/lib/theme/get-default-theme-mode.d.ts +3 -0
  211. package/dist/lib/theme/get-default-theme-mode.d.ts.map +1 -1
  212. package/dist/lib/theme/get-default-theme-mode.js +5 -3
  213. package/dist/messages/de/auth.json +25 -2
  214. package/dist/messages/de/index.d.ts +81 -0
  215. package/dist/messages/de/index.d.ts.map +1 -1
  216. package/dist/messages/de/index.js +2 -0
  217. package/dist/messages/de/index.ts +2 -0
  218. package/dist/messages/en/auth.json +25 -2
  219. package/dist/messages/en/index.d.ts +81 -0
  220. package/dist/messages/en/index.d.ts.map +1 -1
  221. package/dist/messages/en/index.js +2 -0
  222. package/dist/messages/en/index.ts +2 -0
  223. package/dist/messages/es/auth.json +25 -2
  224. package/dist/messages/es/index.d.ts +81 -0
  225. package/dist/messages/es/index.d.ts.map +1 -1
  226. package/dist/messages/es/index.js +2 -0
  227. package/dist/messages/es/index.ts +2 -0
  228. package/dist/messages/fr/auth.json +25 -2
  229. package/dist/messages/fr/index.d.ts +81 -0
  230. package/dist/messages/fr/index.d.ts.map +1 -1
  231. package/dist/messages/fr/index.js +2 -0
  232. package/dist/messages/fr/index.ts +2 -0
  233. package/dist/messages/it/auth.json +25 -2
  234. package/dist/messages/it/index.d.ts +81 -0
  235. package/dist/messages/it/index.d.ts.map +1 -1
  236. package/dist/messages/it/index.js +2 -0
  237. package/dist/messages/it/index.ts +2 -0
  238. package/dist/messages/pt/auth.json +25 -2
  239. package/dist/messages/pt/index.d.ts +81 -0
  240. package/dist/messages/pt/index.d.ts.map +1 -1
  241. package/dist/messages/pt/index.js +2 -0
  242. package/dist/messages/pt/index.ts +2 -0
  243. package/dist/migrations/005_api_audit_log.sql +2 -1
  244. package/dist/migrations/025_api_audit_log_nullable_api_key.sql +12 -0
  245. package/dist/migrations/026_login_events.sql +91 -0
  246. package/dist/migrations/027_rls_bypass_developer_and_system_admin_team.sql +197 -0
  247. package/dist/providers/DashboardProviders.d.ts +12 -3
  248. package/dist/providers/DashboardProviders.d.ts.map +1 -1
  249. package/dist/providers/DashboardProviders.js +6 -2
  250. package/dist/providers/theme-provider.d.ts +19 -2
  251. package/dist/providers/theme-provider.d.ts.map +1 -1
  252. package/dist/providers/theme-provider.js +6 -2
  253. package/dist/templates/app/(auth)/signup/page.tsx +8 -0
  254. package/dist/templates/app/(public)/[...slug]/page.tsx +9 -14
  255. package/dist/templates/app/api/auth/[...all]/route.ts +23 -1
  256. package/dist/templates/app/api/health/route.ts +4 -2
  257. package/dist/templates/app/api/internal/user-metadata/route.ts +5 -3
  258. package/dist/templates/app/api/mcp/route.ts +4 -1
  259. package/dist/templates/app/api/superadmin/subscriptions/route.ts +2 -1
  260. package/dist/templates/app/api/superadmin/teams/[teamId]/route.ts +4 -3
  261. package/dist/templates/app/api/superadmin/users/[userId]/route.ts +10 -3
  262. package/dist/templates/app/api/v1/api-keys/[id]/route.ts +50 -71
  263. package/dist/templates/app/api/v1/api-keys/route.ts +21 -43
  264. package/dist/templates/app/api/v1/auth/signup-with-invite/route.ts +14 -14
  265. package/dist/templates/app/api/v1/billing/cancel/route.ts +7 -6
  266. package/dist/templates/app/api/v1/billing/change-plan/route.ts +5 -4
  267. package/dist/templates/app/api/v1/billing/check-action/route.ts +6 -4
  268. package/dist/templates/app/api/v1/billing/checkout/route.ts +7 -5
  269. package/dist/templates/app/api/v1/billing/plans/route.ts +8 -12
  270. package/dist/templates/app/api/v1/billing/portal/route.ts +7 -5
  271. package/dist/templates/app/api/v1/billing/webhooks/polar/route.ts +1 -1
  272. package/dist/templates/app/api/v1/devtools/blocks/route.ts +5 -4
  273. package/dist/templates/app/api/v1/devtools/features/route.ts +5 -4
  274. package/dist/templates/app/api/v1/devtools/flows/route.ts +5 -4
  275. package/dist/templates/app/api/v1/devtools/scheduled-actions/route.ts +9 -7
  276. package/dist/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +5 -4
  277. package/dist/templates/app/api/v1/devtools/testing/route.ts +5 -4
  278. package/dist/templates/app/api/v1/media/[id]/route.ts +13 -25
  279. package/dist/templates/app/api/v1/media/[id]/tags/route.ts +17 -25
  280. package/dist/templates/app/api/v1/media/check-duplicates/route.ts +5 -7
  281. package/dist/templates/app/api/v1/media/route.ts +5 -9
  282. package/dist/templates/app/api/v1/media/upload/route.ts +9 -21
  283. package/dist/templates/app/api/v1/media-tags/route.ts +9 -13
  284. package/dist/templates/app/api/v1/patterns/[id]/usages/route.ts +11 -19
  285. package/dist/templates/app/api/v1/post-categories/[id]/route.ts +9 -7
  286. package/dist/templates/app/api/v1/post-categories/route.ts +5 -4
  287. package/dist/templates/app/api/v1/team-invitations/[token]/accept/route.ts +16 -18
  288. package/dist/templates/app/api/v1/team-invitations/[token]/decline/route.ts +15 -17
  289. package/dist/templates/app/api/v1/team-invitations/[token]/route.ts +8 -8
  290. package/dist/templates/app/api/v1/team-invitations/route.ts +9 -11
  291. package/dist/templates/app/api/v1/teams/[teamId]/invitations/route.ts +41 -32
  292. package/dist/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +15 -16
  293. package/dist/templates/app/api/v1/teams/[teamId]/invoices/route.ts +14 -15
  294. package/dist/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +32 -36
  295. package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +33 -33
  296. package/dist/templates/app/api/v1/teams/[teamId]/route.ts +35 -41
  297. package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +5 -3
  298. package/dist/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +10 -6
  299. package/dist/templates/app/api/v1/teams/route.ts +33 -27
  300. package/dist/templates/app/api/v1/teams/switch/route.ts +11 -13
  301. package/dist/templates/app/api/v1/theme/[...path]/route.ts +23 -2
  302. package/dist/templates/app/api/v1/users/[id]/meta/[key]/route.ts +32 -77
  303. package/dist/templates/app/api/v1/users/[id]/route.ts +35 -68
  304. package/dist/templates/app/api/v1/users/route.ts +21 -25
  305. package/dist/templates/app/dashboard/layout.tsx +2 -6
  306. package/dist/templates/app/layout.ppr.tsx +9 -14
  307. package/dist/templates/app/layout.tsx +37 -20
  308. package/dist/templates/contents/themes/starter/config/app.config.ts +19 -0
  309. package/dist/templates/contents/themes/starter/config/theme.config.ts +6 -0
  310. package/dist/templates/contents/themes/starter/styles/globals.css +6 -2
  311. package/dist/templates/proxy.ts +46 -10
  312. package/dist/templates/tsconfig.json +4 -0
  313. package/dist/types/theme.d.ts +9 -0
  314. package/dist/types/theme.d.ts.map +1 -1
  315. package/migrations/005_api_audit_log.sql +2 -1
  316. package/migrations/025_api_audit_log_nullable_api_key.sql +12 -0
  317. package/migrations/026_login_events.sql +91 -0
  318. package/migrations/027_rls_bypass_developer_and_system_admin_team.sql +197 -0
  319. package/package.json +14 -11
  320. package/scripts/build/registry/__tests__/scope-registry.test.mjs +18 -0
  321. package/scripts/build/registry/generators/scope-registry.mjs +9 -2
  322. package/templates/app/(auth)/signup/page.tsx +8 -0
  323. package/templates/app/(public)/[...slug]/page.tsx +9 -14
  324. package/templates/app/api/auth/[...all]/route.ts +23 -1
  325. package/templates/app/api/health/route.ts +4 -2
  326. package/templates/app/api/internal/user-metadata/route.ts +5 -3
  327. package/templates/app/api/mcp/route.ts +4 -1
  328. package/templates/app/api/superadmin/subscriptions/route.ts +2 -1
  329. package/templates/app/api/superadmin/teams/[teamId]/route.ts +4 -3
  330. package/templates/app/api/superadmin/users/[userId]/route.ts +10 -3
  331. package/templates/app/api/v1/api-keys/[id]/route.ts +50 -71
  332. package/templates/app/api/v1/api-keys/route.ts +21 -43
  333. package/templates/app/api/v1/auth/signup-with-invite/route.ts +14 -14
  334. package/templates/app/api/v1/billing/cancel/route.ts +7 -6
  335. package/templates/app/api/v1/billing/change-plan/route.ts +5 -4
  336. package/templates/app/api/v1/billing/check-action/route.ts +6 -4
  337. package/templates/app/api/v1/billing/checkout/route.ts +7 -5
  338. package/templates/app/api/v1/billing/plans/route.ts +8 -12
  339. package/templates/app/api/v1/billing/portal/route.ts +7 -5
  340. package/templates/app/api/v1/billing/webhooks/polar/route.ts +1 -1
  341. package/templates/app/api/v1/devtools/blocks/route.ts +5 -4
  342. package/templates/app/api/v1/devtools/features/route.ts +5 -4
  343. package/templates/app/api/v1/devtools/flows/route.ts +5 -4
  344. package/templates/app/api/v1/devtools/scheduled-actions/route.ts +9 -7
  345. package/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +5 -4
  346. package/templates/app/api/v1/devtools/testing/route.ts +5 -4
  347. package/templates/app/api/v1/media/[id]/route.ts +13 -25
  348. package/templates/app/api/v1/media/[id]/tags/route.ts +17 -25
  349. package/templates/app/api/v1/media/check-duplicates/route.ts +5 -7
  350. package/templates/app/api/v1/media/route.ts +5 -9
  351. package/templates/app/api/v1/media/upload/route.ts +9 -21
  352. package/templates/app/api/v1/media-tags/route.ts +9 -13
  353. package/templates/app/api/v1/patterns/[id]/usages/route.ts +11 -19
  354. package/templates/app/api/v1/post-categories/[id]/route.ts +9 -7
  355. package/templates/app/api/v1/post-categories/route.ts +5 -4
  356. package/templates/app/api/v1/team-invitations/[token]/accept/route.ts +16 -18
  357. package/templates/app/api/v1/team-invitations/[token]/decline/route.ts +15 -17
  358. package/templates/app/api/v1/team-invitations/[token]/route.ts +8 -8
  359. package/templates/app/api/v1/team-invitations/route.ts +9 -11
  360. package/templates/app/api/v1/teams/[teamId]/invitations/route.ts +41 -32
  361. package/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +15 -16
  362. package/templates/app/api/v1/teams/[teamId]/invoices/route.ts +14 -15
  363. package/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +32 -36
  364. package/templates/app/api/v1/teams/[teamId]/members/route.ts +33 -33
  365. package/templates/app/api/v1/teams/[teamId]/route.ts +35 -41
  366. package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +5 -3
  367. package/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +10 -6
  368. package/templates/app/api/v1/teams/route.ts +33 -27
  369. package/templates/app/api/v1/teams/switch/route.ts +11 -13
  370. package/templates/app/api/v1/theme/[...path]/route.ts +23 -2
  371. package/templates/app/api/v1/users/[id]/meta/[key]/route.ts +32 -77
  372. package/templates/app/api/v1/users/[id]/route.ts +35 -68
  373. package/templates/app/api/v1/users/route.ts +21 -25
  374. package/templates/app/dashboard/layout.tsx +2 -6
  375. package/templates/app/layout.ppr.tsx +9 -14
  376. package/templates/app/layout.tsx +37 -20
  377. package/templates/contents/themes/starter/config/app.config.ts +19 -0
  378. package/templates/contents/themes/starter/config/theme.config.ts +6 -0
  379. package/templates/contents/themes/starter/styles/globals.css +6 -2
  380. package/templates/proxy.ts +46 -10
  381. package/templates/tsconfig.json +4 -0
  382. package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +23 -0
  383. package/tests/jest/__mocks__/next-server.js +24 -0
  384. package/dist/styles/classes.json +0 -1093
  385. package/dist/styles/ui.css +0 -2
  386. package/scripts/build/build-ui-css.mjs +0 -351
@@ -9,8 +9,8 @@ function hasAdminPermission(authResult, requiredScope) {
9
9
  if (!isSuperAdmin(authResult)) {
10
10
  return false;
11
11
  }
12
- if (authResult.type === "api-key" && requiredScope) {
13
- return hasRequiredScope(authResult, requiredScope);
12
+ if (authResult.type === "api-key") {
13
+ return requiredScope !== void 0 && hasRequiredScope(authResult, requiredScope);
14
14
  }
15
15
  return true;
16
16
  }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * API-key scope policy (#93)
3
+ *
4
+ * Shared by both auth entry points — `authenticateRequest` (dual-auth.ts) and
5
+ * `validateAndAuthenticateRequest` (helpers.ts) — so the rule cannot drift
6
+ * between them. Pure: no I/O, no framework imports.
7
+ *
8
+ * The rule, applied only to API-key authentication (sessions carry no scopes
9
+ * and are never gated here):
10
+ *
11
+ * 1. The route declared `{ requiredScope }` → the key must hold one of the
12
+ * listed scopes (or the wildcard `*`). Otherwise `INSUFFICIENT_SCOPE`.
13
+ * 2. The route declared `{ allowAnyScope: true }` → any valid key passes.
14
+ * This is the explicit, self-documenting opt-out for routes that are
15
+ * genuinely scope-agnostic (a public route that only *enriches* its
16
+ * answer for authenticated callers, an MCP transport whose tools enforce
17
+ * scopes themselves, ...).
18
+ * 3. The route declared nothing → the key is rejected with
19
+ * `SCOPE_NOT_DECLARED` and the route is named in the server log.
20
+ *
21
+ * Rule 3 is the point of the change: forgetting a declaration now produces a
22
+ * visible 403 on an integration instead of a silently over-privileged
23
+ * credential. Before, `scopes` were populated and nobody was obliged to look.
24
+ */
25
+ export type DualAuthFailureCode = 'AUTHENTICATION_FAILED' | 'INSUFFICIENT_SCOPE' | 'SCOPE_NOT_DECLARED';
26
+ export interface DualAuthFailure {
27
+ code: DualAuthFailureCode;
28
+ /** 401 when no usable credential was presented, 403 when a valid key was rejected on scope. */
29
+ status: 401 | 403;
30
+ message: string;
31
+ }
32
+ export interface AuthenticateOptions {
33
+ /**
34
+ * Scope(s) an API key must hold to use this route. A string requires that
35
+ * scope; an array is satisfied by any one of its entries. Ignored for
36
+ * session auth. An empty array counts as "nothing declared".
37
+ */
38
+ requiredScope?: string | string[];
39
+ /**
40
+ * Accept any valid API key regardless of its scopes. Explicit opt-out of
41
+ * fail-closed enforcement — say why in a comment at the call site.
42
+ * A declared `requiredScope` still wins if both are set.
43
+ */
44
+ allowAnyScope?: boolean;
45
+ }
46
+ /** Failure attached to a result that carried no usable credential at all. */
47
+ export declare function authenticationFailed(): DualAuthFailure;
48
+ export declare function normalizeRequiredScopes(requiredScope: AuthenticateOptions['requiredScope']): string[];
49
+ /**
50
+ * True when `scopes` (an API key's stored scopes) satisfy `requiredScope`:
51
+ * holds one of the required scopes, or the wildcard `*`. An empty requirement
52
+ * is never satisfied — "no scope needed" must be said with `allowAnyScope`,
53
+ * not with an empty list.
54
+ */
55
+ export declare function scopesSatisfy(scopes: readonly string[] | undefined, requiredScope: string | string[]): boolean;
56
+ /** Minimal request shape needed to name a route in logs (works for mocks too). */
57
+ export interface RouteDescribable {
58
+ method?: string;
59
+ url?: string;
60
+ nextUrl?: {
61
+ pathname: string;
62
+ };
63
+ }
64
+ export declare function describeRoute(request: RouteDescribable): string;
65
+ /**
66
+ * Apply the policy to an already-authenticated API key.
67
+ *
68
+ * @returns null when the key may proceed, otherwise the failure to report.
69
+ */
70
+ export declare function resolveApiKeyScopeFailure(scopes: readonly string[] | undefined, options: AuthenticateOptions, route: string): DualAuthFailure | null;
71
+ //# sourceMappingURL=scope-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-policy.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/scope-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,MAAM,mBAAmB,GAC3B,uBAAuB,GACvB,oBAAoB,GACpB,oBAAoB,CAAA;AAExB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAA;IACzB,+FAA+F;IAC/F,MAAM,EAAE,GAAG,GAAG,GAAG,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,eAAe,CAEtD;AAED,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC,GAAG,MAAM,EAAE,CAKrG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACrC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAC/B,OAAO,CAIT;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAU/D;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACrC,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,MAAM,GACZ,eAAe,GAAG,IAAI,CAuBxB"}
@@ -0,0 +1,53 @@
1
+ function authenticationFailed() {
2
+ return { code: "AUTHENTICATION_FAILED", status: 401, message: "Authentication required" };
3
+ }
4
+ function normalizeRequiredScopes(requiredScope) {
5
+ if (requiredScope === void 0) return [];
6
+ return (Array.isArray(requiredScope) ? requiredScope : [requiredScope]).filter(
7
+ (scope) => typeof scope === "string" && scope.length > 0
8
+ );
9
+ }
10
+ function scopesSatisfy(scopes, requiredScope) {
11
+ const required = normalizeRequiredScopes(requiredScope);
12
+ if (required.length === 0 || !scopes) return false;
13
+ return scopes.includes("*") || required.some((scope) => scopes.includes(scope));
14
+ }
15
+ function describeRoute(request) {
16
+ var _a;
17
+ let pathname = (_a = request.nextUrl) == null ? void 0 : _a.pathname;
18
+ if (!pathname && request.url) {
19
+ try {
20
+ pathname = new URL(request.url).pathname;
21
+ } catch {
22
+ pathname = request.url;
23
+ }
24
+ }
25
+ return `${request.method ?? "GET"} ${pathname ?? "<unknown route>"}`;
26
+ }
27
+ function resolveApiKeyScopeFailure(scopes, options, route) {
28
+ const required = normalizeRequiredScopes(options.requiredScope);
29
+ if (required.length > 0) {
30
+ if (scopesSatisfy(scopes, required)) return null;
31
+ return {
32
+ code: "INSUFFICIENT_SCOPE",
33
+ status: 403,
34
+ message: `API key lacks required scope '${required.join("' or '")}'`
35
+ };
36
+ }
37
+ if (options.allowAnyScope) return null;
38
+ console.error(
39
+ `[auth] ${route} did not declare a required API key scope; rejecting the API-key request (fail closed). Pass { requiredScope } \u2014 or { allowAnyScope: true } if any valid key is really acceptable \u2014 to the auth entry point.`
40
+ );
41
+ return {
42
+ code: "SCOPE_NOT_DECLARED",
43
+ status: 403,
44
+ message: "API key access is not enabled for this route: it declares no required scope"
45
+ };
46
+ }
47
+ export {
48
+ authenticationFailed,
49
+ describeRoute,
50
+ normalizeRequiredScopes,
51
+ resolveApiKeyScopeFailure,
52
+ scopesSatisfy
53
+ };
@@ -25,6 +25,21 @@ export interface ApiKeyValidationResult {
25
25
  * Valida una API Key desde el header Authorization o x-api-key
26
26
  */
27
27
  export declare function validateApiKey(request: NextRequest): Promise<ApiKeyAuth | null>;
28
+ /**
29
+ * Elimina del cache la entrada de una API key (indexada por keyHash).
30
+ *
31
+ * Debe llamarse cada vez que cambia el `status` de una key (revocación,
32
+ * desactivación, expiración): validateApiKey() consulta el cache ANTES que la
33
+ * base de datos, así que sin esta invalidación una key revocada sigue
34
+ * autenticando hasta que vence el TTL (5 min). Ver #92.
35
+ */
36
+ export declare function invalidateApiKeyCache(keyHash: string): void;
37
+ /**
38
+ * Variante por id para los call sites que no tienen el hash a mano.
39
+ * Hace una lectura extra; preferí invalidateApiKeyCache(keyHash) cuando el
40
+ * hash ya viene en la fila (por ejemplo vía RETURNING "keyHash").
41
+ */
42
+ export declare function invalidateApiKeyCacheById(keyId: string): Promise<void>;
28
43
  /**
29
44
  * Verifica si una autenticación tiene alguno de los scopes requeridos
30
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/lib/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAoHrF;AAiDD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAM/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAMhF;AAiBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU;QAG1C,MAAM;WACH,MAAM;eACF,MAAM,GAAG,IAAI;cACd,MAAM,GAAG,IAAI;UACjB,MAAM;GAWjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC,CAyED"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/lib/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAoHrF;AA8CD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E;AAID;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAM/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAMhF;AAiBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU;QAG1C,MAAM;WACH,MAAM;eACF,MAAM,GAAG,IAAI;cACd,MAAM,GAAG,IAAI;UACjB,MAAM;GAWjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC,CAyED"}
@@ -62,7 +62,7 @@ async function validateApiKey(request) {
62
62
  return null;
63
63
  }
64
64
  if (keyData.expiresAt && new Date(keyData.expiresAt) < /* @__PURE__ */ new Date()) {
65
- markAsExpired(keyData.id).catch(console.error);
65
+ markAsExpired(keyData.id, keyHash).catch(console.error);
66
66
  await constantTimeDelay(startTime);
67
67
  return null;
68
68
  }
@@ -101,18 +101,29 @@ async function resetFailedAttempts(keyId) {
101
101
  console.error("Failed to reset failed attempts:", error);
102
102
  }
103
103
  }
104
- async function markAsExpired(keyId) {
104
+ async function markAsExpired(keyId, keyHash) {
105
105
  try {
106
106
  await queryOne(
107
107
  'UPDATE "api_key" SET status = $1 WHERE id = $2',
108
108
  ["expired", keyId]
109
109
  );
110
- const cacheKey = getCacheKey("api_key", keyId);
111
- apiKeyCache.delete(cacheKey);
110
+ invalidateApiKeyCache(keyHash);
112
111
  } catch (error) {
113
112
  console.error("Failed to mark API key as expired:", error);
114
113
  }
115
114
  }
115
+ function invalidateApiKeyCache(keyHash) {
116
+ apiKeyCache.delete(getCacheKey("api_key", keyHash));
117
+ }
118
+ async function invalidateApiKeyCacheById(keyId) {
119
+ const row = await queryOne(
120
+ 'SELECT "keyHash" FROM "api_key" WHERE id = $1',
121
+ [keyId]
122
+ );
123
+ if (row == null ? void 0 : row.keyHash) {
124
+ invalidateApiKeyCache(row.keyHash);
125
+ }
126
+ }
116
127
  function hasAnyScope(auth, requiredScopes) {
117
128
  if (auth.scopes.includes("*")) {
118
129
  return true;
@@ -237,6 +248,8 @@ export {
237
248
  hasAllScopes,
238
249
  hasAnyScope,
239
250
  hasScope,
251
+ invalidateApiKeyCache,
252
+ invalidateApiKeyCacheById,
240
253
  validateApiKey,
241
254
  validateScopesForUser
242
255
  };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Audit logging for the generic entity routes (#105).
3
+ *
4
+ * `logApiUsage` (lib/api/helpers.ts) is hard-typed to `ApiKeyAuth` and is
5
+ * only triggered by the legacy `withApiLogging` wrapper, whose header-based
6
+ * `getApiAuth` never sees the dual-auth flow the generic handlers use — so
7
+ * neither session nor API-key activity on `/api/v1/[entity]` was ever
8
+ * written to `api_audit_log`.
9
+ *
10
+ * This module accepts the real `DualAuthResult` the handlers already hold and
11
+ * writes one row per REQUEST WITH AN IDENTIFIABLE PRINCIPAL (`apiKeyId` is
12
+ * NULL for sessions; migration 025 dropped the NOT NULL) — a real session or
13
+ * a real API key, whether the request was ultimately allowed or denied for
14
+ * scope/permission reasons (#128). A request with no usable credential at all
15
+ * (anonymous, missing, or invalid) is still never logged: there is no "who"
16
+ * to attribute it to, and logging it would mostly capture bot/scanner noise
17
+ * rather than anything actionable. It is invoked fire-and-forget from
18
+ * `runWithAuditLog` in generic-handler.ts, so a logging failure can never turn
19
+ * a successful response into an error.
20
+ *
21
+ * The request body is deliberately NOT stored: entity payloads routinely
22
+ * carry personal data, and endpoint + method + status already identify what
23
+ * was touched (the record id is part of the path for read/update/delete).
24
+ */
25
+ import type { NextRequest } from 'next/server';
26
+ import type { DualAuthResult } from '../auth/dual-auth';
27
+ /**
28
+ * Mutable slot a handler fills in once it has authenticated the request, so
29
+ * the wrapper can attribute the response to a user / API key.
30
+ */
31
+ export interface AuditContext {
32
+ auth: DualAuthResult | null;
33
+ }
34
+ export declare function logGenericHandlerUsage(auth: DualAuthResult | null, request: NextRequest, statusCode: number, responseTime?: number): Promise<void>;
35
+ //# sourceMappingURL=audit-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/audit-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,GAAG,IAAI,EAC3B,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAuCf"}
@@ -0,0 +1,35 @@
1
+ import { mutateWithRLS } from "../../db.js";
2
+ async function logGenericHandlerUsage(auth, request, statusCode, responseTime) {
3
+ var _a;
4
+ const userId = (_a = auth == null ? void 0 : auth.user) == null ? void 0 : _a.id;
5
+ if (!userId) return;
6
+ const apiKeyId = (auth == null ? void 0 : auth.type) === "api-key" ? auth.keyId ?? null : null;
7
+ try {
8
+ const endpoint = request.nextUrl.pathname;
9
+ const method = request.method;
10
+ const ipAddress = request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip") || "unknown";
11
+ const userAgent = request.headers.get("user-agent");
12
+ await mutateWithRLS(
13
+ `INSERT INTO "api_audit_log"
14
+ ("apiKeyId", "userId", endpoint, method, "statusCode", "ipAddress", "userAgent", "requestBody", "responseTime")
15
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
16
+ [
17
+ apiKeyId,
18
+ userId,
19
+ endpoint,
20
+ method,
21
+ statusCode,
22
+ ipAddress,
23
+ userAgent,
24
+ null,
25
+ typeof responseTime === "number" ? Math.round(responseTime) : null
26
+ ],
27
+ userId
28
+ );
29
+ } catch (error) {
30
+ console.error("[generic-handler:audit] failed to write api_audit_log entry:", error);
31
+ }
32
+ }
33
+ export {
34
+ logGenericHandlerUsage
35
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAmjBvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAwgBnF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAoZrF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CA0MpJ;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CA2XtJ;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAyJtJ;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtF"}
1
+ {"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AA4wBvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEnF;AA4kBD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAErF;AAyaD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEpJ;AAgND;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AA+YD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AAwKD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtF"}