@simple-auth-kit/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (820) hide show
  1. package/README.md +88 -0
  2. package/bin/simple-auth-kit.mjs +18 -0
  3. package/lib/copy.ts +190 -0
  4. package/lib/rename-native.ts +173 -0
  5. package/package.json +31 -0
  6. package/registry/README.md +312 -0
  7. package/registry/admin-apps/README.md +71 -0
  8. package/registry/admin-apps/nextjs/shared/components.json +25 -0
  9. package/registry/admin-apps/nextjs/shared/next.config.ts +9 -0
  10. package/registry/admin-apps/nextjs/shared/postcss.config.mjs +7 -0
  11. package/registry/admin-apps/nextjs/shared/src/app/globals.css +159 -0
  12. package/registry/admin-apps/nextjs/shared/src/app/signup/page.tsx +72 -0
  13. package/registry/admin-apps/nextjs/shared/src/components/alert-modal.tsx +32 -0
  14. package/registry/admin-apps/nextjs/shared/src/components/breadcrumb.tsx +48 -0
  15. package/registry/admin-apps/nextjs/shared/src/components/form-error-alert.tsx +24 -0
  16. package/registry/admin-apps/nextjs/shared/src/components/loader/skeleton.tsx +39 -0
  17. package/registry/admin-apps/nextjs/shared/src/components/loader/table-skeleton-loader.tsx +57 -0
  18. package/registry/admin-apps/nextjs/shared/src/components/permission-group-select.tsx +101 -0
  19. package/registry/admin-apps/nextjs/shared/src/components/permission-group-view.tsx +53 -0
  20. package/registry/admin-apps/nextjs/shared/src/components/role-multi-select.tsx +71 -0
  21. package/registry/admin-apps/nextjs/shared/src/components/theme-toggle.tsx +26 -0
  22. package/registry/admin-apps/nextjs/shared/src/components/ui/alert.tsx +78 -0
  23. package/registry/admin-apps/nextjs/shared/src/components/ui/avatar.tsx +53 -0
  24. package/registry/admin-apps/nextjs/shared/src/components/ui/badge.tsx +51 -0
  25. package/registry/admin-apps/nextjs/shared/src/components/ui/breadcrumb.tsx +109 -0
  26. package/registry/admin-apps/nextjs/shared/src/components/ui/button.tsx +67 -0
  27. package/registry/admin-apps/nextjs/shared/src/components/ui/card.tsx +103 -0
  28. package/registry/admin-apps/nextjs/shared/src/components/ui/checkbox.tsx +32 -0
  29. package/registry/admin-apps/nextjs/shared/src/components/ui/collapsible.tsx +33 -0
  30. package/registry/admin-apps/nextjs/shared/src/components/ui/data-table.tsx +107 -0
  31. package/registry/admin-apps/nextjs/shared/src/components/ui/dialog.tsx +143 -0
  32. package/registry/admin-apps/nextjs/shared/src/components/ui/dropdown-menu.tsx +234 -0
  33. package/registry/admin-apps/nextjs/shared/src/components/ui/heading.tsx +16 -0
  34. package/registry/admin-apps/nextjs/shared/src/components/ui/input.tsx +19 -0
  35. package/registry/admin-apps/nextjs/shared/src/components/ui/label.tsx +24 -0
  36. package/registry/admin-apps/nextjs/shared/src/components/ui/modal.tsx +29 -0
  37. package/registry/admin-apps/nextjs/shared/src/components/ui/select.tsx +192 -0
  38. package/registry/admin-apps/nextjs/shared/src/components/ui/separator.tsx +28 -0
  39. package/registry/admin-apps/nextjs/shared/src/components/ui/sheet.tsx +135 -0
  40. package/registry/admin-apps/nextjs/shared/src/components/ui/sidebar.tsx +567 -0
  41. package/registry/admin-apps/nextjs/shared/src/components/ui/skeleton.tsx +13 -0
  42. package/registry/admin-apps/nextjs/shared/src/components/ui/sonner.tsx +34 -0
  43. package/registry/admin-apps/nextjs/shared/src/components/ui/table.tsx +116 -0
  44. package/registry/admin-apps/nextjs/shared/src/components/ui/tooltip.tsx +61 -0
  45. package/registry/admin-apps/nextjs/shared/src/hooks/use-live-audit-feed.ts +51 -0
  46. package/registry/admin-apps/nextjs/shared/src/hooks/use-mobile.ts +17 -0
  47. package/registry/admin-apps/nextjs/shared/src/lib/error.ts +23 -0
  48. package/registry/admin-apps/nextjs/shared/src/lib/query-client.tsx +10 -0
  49. package/registry/admin-apps/nextjs/shared/src/lib/token-storage.ts +36 -0
  50. package/registry/admin-apps/nextjs/shared/src/lib/utils.ts +6 -0
  51. package/registry/admin-apps/nextjs/shared/tsconfig.json +41 -0
  52. package/registry/admin-apps/nextjs/variants/base/.env.example +9 -0
  53. package/registry/admin-apps/nextjs/variants/base/Dockerfile +32 -0
  54. package/registry/admin-apps/nextjs/variants/base/package.json +58 -0
  55. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/account/change-password/page.tsx +163 -0
  56. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/account/page.tsx +569 -0
  57. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/audit-log/page.tsx +180 -0
  58. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/[id]/edit/page.tsx +357 -0
  59. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/[id]/page.tsx +191 -0
  60. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/country-schema.ts +18 -0
  61. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/new/page.tsx +305 -0
  62. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/page.tsx +367 -0
  63. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/edit/page.tsx +386 -0
  64. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/page.tsx +213 -0
  65. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/customer-schema.ts +35 -0
  66. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/new/page.tsx +334 -0
  67. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/page.tsx +400 -0
  68. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/dashboard/page.tsx +263 -0
  69. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/edit/page.tsx +275 -0
  70. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/page.tsx +183 -0
  71. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/language-schema.ts +20 -0
  72. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/new/page.tsx +226 -0
  73. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/page.tsx +342 -0
  74. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/layout.tsx +50 -0
  75. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/edit/page.tsx +309 -0
  76. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/page.tsx +119 -0
  77. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/new/page.tsx +275 -0
  78. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/page.tsx +311 -0
  79. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/permission-schema.ts +44 -0
  80. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/edit/page.tsx +276 -0
  81. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/page.tsx +179 -0
  82. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/new/page.tsx +241 -0
  83. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/page.tsx +325 -0
  84. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/role-schema.ts +20 -0
  85. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/edit/page.tsx +411 -0
  86. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/page.tsx +253 -0
  87. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/new/page.tsx +444 -0
  88. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/page.tsx +410 -0
  89. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/user-schema.ts +37 -0
  90. package/registry/admin-apps/nextjs/variants/base/src/app/api/auth/[...nextauth]/route.ts +3 -0
  91. package/registry/admin-apps/nextjs/variants/base/src/app/icon.svg +5 -0
  92. package/registry/admin-apps/nextjs/variants/base/src/app/layout.tsx +31 -0
  93. package/registry/admin-apps/nextjs/variants/base/src/app/login/page.tsx +162 -0
  94. package/registry/admin-apps/nextjs/variants/base/src/app/page.tsx +22 -0
  95. package/registry/admin-apps/nextjs/variants/base/src/auth.ts +105 -0
  96. package/registry/admin-apps/nextjs/variants/base/src/components/app-sidebar.tsx +182 -0
  97. package/registry/admin-apps/nextjs/variants/base/src/components/nav-user.tsx +99 -0
  98. package/registry/admin-apps/nextjs/variants/base/src/components/permission-required.tsx +32 -0
  99. package/registry/admin-apps/nextjs/variants/base/src/components/photo-upload.tsx +203 -0
  100. package/registry/admin-apps/nextjs/variants/base/src/components/ui/accordion.tsx +66 -0
  101. package/registry/admin-apps/nextjs/variants/base/src/components/ui/alert-dialog.tsx +157 -0
  102. package/registry/admin-apps/nextjs/variants/base/src/components/ui/button-group.tsx +83 -0
  103. package/registry/admin-apps/nextjs/variants/base/src/components/ui/calendar.tsx +218 -0
  104. package/registry/admin-apps/nextjs/variants/base/src/components/ui/carousel.tsx +241 -0
  105. package/registry/admin-apps/nextjs/variants/base/src/components/ui/combobox.tsx +243 -0
  106. package/registry/admin-apps/nextjs/variants/base/src/components/ui/command.tsx +184 -0
  107. package/registry/admin-apps/nextjs/variants/base/src/components/ui/context-menu.tsx +252 -0
  108. package/registry/admin-apps/nextjs/variants/base/src/components/ui/date-picker.tsx +323 -0
  109. package/registry/admin-apps/nextjs/variants/base/src/components/ui/datetime-picker.tsx +896 -0
  110. package/registry/admin-apps/nextjs/variants/base/src/components/ui/drawer.tsx +135 -0
  111. package/registry/admin-apps/nextjs/variants/base/src/components/ui/empty.tsx +104 -0
  112. package/registry/admin-apps/nextjs/variants/base/src/components/ui/field.tsx +248 -0
  113. package/registry/admin-apps/nextjs/variants/base/src/components/ui/form.tsx +168 -0
  114. package/registry/admin-apps/nextjs/variants/base/src/components/ui/hover-card.tsx +44 -0
  115. package/registry/admin-apps/nextjs/variants/base/src/components/ui/input-group.tsx +170 -0
  116. package/registry/admin-apps/nextjs/variants/base/src/components/ui/input-otp.tsx +77 -0
  117. package/registry/admin-apps/nextjs/variants/base/src/components/ui/item.tsx +193 -0
  118. package/registry/admin-apps/nextjs/variants/base/src/components/ui/kbd.tsx +28 -0
  119. package/registry/admin-apps/nextjs/variants/base/src/components/ui/menubar.tsx +276 -0
  120. package/registry/admin-apps/nextjs/variants/base/src/components/ui/multi-select.tsx +381 -0
  121. package/registry/admin-apps/nextjs/variants/base/src/components/ui/multi-selector.tsx +641 -0
  122. package/registry/admin-apps/nextjs/variants/base/src/components/ui/native-select.tsx +48 -0
  123. package/registry/admin-apps/nextjs/variants/base/src/components/ui/navigation-menu.tsx +168 -0
  124. package/registry/admin-apps/nextjs/variants/base/src/components/ui/pagination.tsx +127 -0
  125. package/registry/admin-apps/nextjs/variants/base/src/components/ui/popover.tsx +48 -0
  126. package/registry/admin-apps/nextjs/variants/base/src/components/ui/progress.tsx +31 -0
  127. package/registry/admin-apps/nextjs/variants/base/src/components/ui/radio-group.tsx +45 -0
  128. package/registry/admin-apps/nextjs/variants/base/src/components/ui/resizable.tsx +55 -0
  129. package/registry/admin-apps/nextjs/variants/base/src/components/ui/scroll-area.tsx +58 -0
  130. package/registry/admin-apps/nextjs/variants/base/src/components/ui/spinner.tsx +27 -0
  131. package/registry/admin-apps/nextjs/variants/base/src/components/ui/switch.tsx +31 -0
  132. package/registry/admin-apps/nextjs/variants/base/src/components/ui/tabs.tsx +66 -0
  133. package/registry/admin-apps/nextjs/variants/base/src/components/ui/textarea.tsx +18 -0
  134. package/registry/admin-apps/nextjs/variants/base/src/components/ui/toggle-group.tsx +83 -0
  135. package/registry/admin-apps/nextjs/variants/base/src/components/ui/toggle.tsx +47 -0
  136. package/registry/admin-apps/nextjs/variants/base/src/components/user-menu.tsx +61 -0
  137. package/registry/admin-apps/nextjs/variants/base/src/lib/ability.ts +90 -0
  138. package/registry/admin-apps/nextjs/variants/base/src/lib/auth-client.ts +10 -0
  139. package/registry/admin-apps/nextjs/variants/base/src/lib/env.ts +10 -0
  140. package/registry/admin-apps/nextjs/variants/base/src/lib/server-token-storage.ts +33 -0
  141. package/registry/admin-apps/nextjs/variants/base/src/lib/stores/auth-store.ts +117 -0
  142. package/registry/admin-apps/nextjs/variants/base/src/lib/stores/store-context.tsx +50 -0
  143. package/registry/admin-apps/nextjs/variants/base/src/proxy.ts +81 -0
  144. package/registry/admin-apps/nextjs/variants/base/src/routes.ts +7 -0
  145. package/registry/admin-apps/nextjs/variants/workspaces/.env.example +7 -0
  146. package/registry/admin-apps/nextjs/variants/workspaces/Dockerfile +32 -0
  147. package/registry/admin-apps/nextjs/variants/workspaces/package.json +48 -0
  148. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/account/page.tsx +360 -0
  149. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/audit-log/page.tsx +185 -0
  150. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/[id]/edit/page.tsx +296 -0
  151. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/[id]/page.tsx +194 -0
  152. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/country-schema.ts +27 -0
  153. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/new/page.tsx +242 -0
  154. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/page.tsx +373 -0
  155. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/[id]/edit/page.tsx +306 -0
  156. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/[id]/page.tsx +219 -0
  157. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/customer-schema.ts +36 -0
  158. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/new/page.tsx +251 -0
  159. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/page.tsx +406 -0
  160. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/dashboard/page.tsx +146 -0
  161. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/[id]/edit/page.tsx +240 -0
  162. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/[id]/page.tsx +186 -0
  163. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/language-schema.ts +26 -0
  164. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/new/page.tsx +189 -0
  165. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/page.tsx +348 -0
  166. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/layout.tsx +96 -0
  167. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/members/page.tsx +263 -0
  168. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/[id]/edit/page.tsx +264 -0
  169. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/[id]/page.tsx +126 -0
  170. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/new/page.tsx +238 -0
  171. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/page.tsx +294 -0
  172. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/permission-schema.ts +46 -0
  173. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/[id]/edit/page.tsx +248 -0
  174. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/[id]/page.tsx +186 -0
  175. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/new/page.tsx +205 -0
  176. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/page.tsx +485 -0
  177. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/role-schema.ts +23 -0
  178. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/[id]/page.tsx +521 -0
  179. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/new/page.tsx +342 -0
  180. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/page.tsx +414 -0
  181. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/user-schema.ts +44 -0
  182. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/workspaces/new/page.tsx +66 -0
  183. package/registry/admin-apps/nextjs/variants/workspaces/src/app/layout.tsx +31 -0
  184. package/registry/admin-apps/nextjs/variants/workspaces/src/app/login/page.tsx +110 -0
  185. package/registry/admin-apps/nextjs/variants/workspaces/src/app/page.tsx +33 -0
  186. package/registry/admin-apps/nextjs/variants/workspaces/src/components/app-sidebar.tsx +180 -0
  187. package/registry/admin-apps/nextjs/variants/workspaces/src/components/change-password-dialog.tsx +119 -0
  188. package/registry/admin-apps/nextjs/variants/workspaces/src/components/nav-user.tsx +105 -0
  189. package/registry/admin-apps/nextjs/variants/workspaces/src/components/permission-required.tsx +32 -0
  190. package/registry/admin-apps/nextjs/variants/workspaces/src/components/photo-upload.tsx +226 -0
  191. package/registry/admin-apps/nextjs/variants/workspaces/src/components/ui/calendar.tsx +218 -0
  192. package/registry/admin-apps/nextjs/variants/workspaces/src/components/ui/datetime-picker.tsx +896 -0
  193. package/registry/admin-apps/nextjs/variants/workspaces/src/components/ui/popover.tsx +48 -0
  194. package/registry/admin-apps/nextjs/variants/workspaces/src/components/user-menu.tsx +67 -0
  195. package/registry/admin-apps/nextjs/variants/workspaces/src/components/workspace-switcher.tsx +57 -0
  196. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/ability.ts +101 -0
  197. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/active-workspace.ts +38 -0
  198. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/auth-client.ts +17 -0
  199. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/env.ts +4 -0
  200. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/stores/auth-store.ts +139 -0
  201. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/stores/store-context.tsx +66 -0
  202. package/registry/admin-apps/nextjs/variants/workspaces/src/lib/stores/workspace-store.ts +89 -0
  203. package/registry/admin-apps/react/shared/components.json +25 -0
  204. package/registry/admin-apps/react/shared/postcss.config.js +5 -0
  205. package/registry/admin-apps/react/shared/src/components/alert-modal.tsx +30 -0
  206. package/registry/admin-apps/react/shared/src/components/loader/skeleton.tsx +39 -0
  207. package/registry/admin-apps/react/shared/src/components/loader/table-skeleton-loader.tsx +57 -0
  208. package/registry/admin-apps/react/shared/src/components/nav-user.tsx +103 -0
  209. package/registry/admin-apps/react/shared/src/components/role-multi-select.tsx +69 -0
  210. package/registry/admin-apps/react/shared/src/components/theme-toggle.tsx +24 -0
  211. package/registry/admin-apps/react/shared/src/components/ui/accordion.tsx +66 -0
  212. package/registry/admin-apps/react/shared/src/components/ui/alert-dialog.tsx +157 -0
  213. package/registry/admin-apps/react/shared/src/components/ui/alert.tsx +78 -0
  214. package/registry/admin-apps/react/shared/src/components/ui/avatar.tsx +53 -0
  215. package/registry/admin-apps/react/shared/src/components/ui/badge.tsx +51 -0
  216. package/registry/admin-apps/react/shared/src/components/ui/breadcrumb.tsx +109 -0
  217. package/registry/admin-apps/react/shared/src/components/ui/button-group.tsx +83 -0
  218. package/registry/admin-apps/react/shared/src/components/ui/button.tsx +67 -0
  219. package/registry/admin-apps/react/shared/src/components/ui/calendar.tsx +218 -0
  220. package/registry/admin-apps/react/shared/src/components/ui/card.tsx +103 -0
  221. package/registry/admin-apps/react/shared/src/components/ui/carousel.tsx +241 -0
  222. package/registry/admin-apps/react/shared/src/components/ui/checkbox.tsx +32 -0
  223. package/registry/admin-apps/react/shared/src/components/ui/collapsible.tsx +33 -0
  224. package/registry/admin-apps/react/shared/src/components/ui/context-menu.tsx +252 -0
  225. package/registry/admin-apps/react/shared/src/components/ui/data-table.tsx +107 -0
  226. package/registry/admin-apps/react/shared/src/components/ui/datetime-picker.tsx +896 -0
  227. package/registry/admin-apps/react/shared/src/components/ui/dialog.tsx +143 -0
  228. package/registry/admin-apps/react/shared/src/components/ui/drawer.tsx +135 -0
  229. package/registry/admin-apps/react/shared/src/components/ui/dropdown-menu.tsx +234 -0
  230. package/registry/admin-apps/react/shared/src/components/ui/empty.tsx +104 -0
  231. package/registry/admin-apps/react/shared/src/components/ui/field.tsx +248 -0
  232. package/registry/admin-apps/react/shared/src/components/ui/form.tsx +168 -0
  233. package/registry/admin-apps/react/shared/src/components/ui/heading.tsx +16 -0
  234. package/registry/admin-apps/react/shared/src/components/ui/hover-card.tsx +44 -0
  235. package/registry/admin-apps/react/shared/src/components/ui/input-group.tsx +170 -0
  236. package/registry/admin-apps/react/shared/src/components/ui/input-otp.tsx +77 -0
  237. package/registry/admin-apps/react/shared/src/components/ui/input.tsx +19 -0
  238. package/registry/admin-apps/react/shared/src/components/ui/item.tsx +193 -0
  239. package/registry/admin-apps/react/shared/src/components/ui/kbd.tsx +28 -0
  240. package/registry/admin-apps/react/shared/src/components/ui/label.tsx +24 -0
  241. package/registry/admin-apps/react/shared/src/components/ui/menubar.tsx +276 -0
  242. package/registry/admin-apps/react/shared/src/components/ui/modal.tsx +29 -0
  243. package/registry/admin-apps/react/shared/src/components/ui/multi-select.tsx +381 -0
  244. package/registry/admin-apps/react/shared/src/components/ui/multi-selector.tsx +641 -0
  245. package/registry/admin-apps/react/shared/src/components/ui/native-select.tsx +48 -0
  246. package/registry/admin-apps/react/shared/src/components/ui/navigation-menu.tsx +168 -0
  247. package/registry/admin-apps/react/shared/src/components/ui/pagination.tsx +127 -0
  248. package/registry/admin-apps/react/shared/src/components/ui/popover.tsx +48 -0
  249. package/registry/admin-apps/react/shared/src/components/ui/progress.tsx +31 -0
  250. package/registry/admin-apps/react/shared/src/components/ui/radio-group.tsx +45 -0
  251. package/registry/admin-apps/react/shared/src/components/ui/resizable.tsx +55 -0
  252. package/registry/admin-apps/react/shared/src/components/ui/scroll-area.tsx +58 -0
  253. package/registry/admin-apps/react/shared/src/components/ui/select.tsx +192 -0
  254. package/registry/admin-apps/react/shared/src/components/ui/separator.tsx +28 -0
  255. package/registry/admin-apps/react/shared/src/components/ui/sheet.tsx +135 -0
  256. package/registry/admin-apps/react/shared/src/components/ui/sidebar.tsx +567 -0
  257. package/registry/admin-apps/react/shared/src/components/ui/skeleton.tsx +13 -0
  258. package/registry/admin-apps/react/shared/src/components/ui/spinner.tsx +27 -0
  259. package/registry/admin-apps/react/shared/src/components/ui/switch.tsx +31 -0
  260. package/registry/admin-apps/react/shared/src/components/ui/table.tsx +116 -0
  261. package/registry/admin-apps/react/shared/src/components/ui/tabs.tsx +66 -0
  262. package/registry/admin-apps/react/shared/src/components/ui/textarea.tsx +18 -0
  263. package/registry/admin-apps/react/shared/src/components/ui/toggle-group.tsx +83 -0
  264. package/registry/admin-apps/react/shared/src/components/ui/toggle.tsx +47 -0
  265. package/registry/admin-apps/react/shared/src/components/ui/tooltip.tsx +61 -0
  266. package/registry/admin-apps/react/shared/src/hooks/use-mobile.ts +17 -0
  267. package/registry/admin-apps/react/shared/src/lib/cn.ts +6 -0
  268. package/registry/admin-apps/react/shared/src/lib/error.ts +23 -0
  269. package/registry/admin-apps/react/shared/src/lib/query-client.tsx +8 -0
  270. package/registry/admin-apps/react/shared/src/lib/utils.ts +1 -0
  271. package/registry/admin-apps/react/shared/src/vite-env.d.ts +9 -0
  272. package/registry/admin-apps/react/shared/tsconfig.json +24 -0
  273. package/registry/admin-apps/react/variants/base/.env.example +3 -0
  274. package/registry/admin-apps/react/variants/base/Dockerfile +32 -0
  275. package/registry/admin-apps/react/variants/base/index.html +12 -0
  276. package/registry/admin-apps/react/variants/base/package.json +61 -0
  277. package/registry/admin-apps/react/variants/base/src/App.tsx +103 -0
  278. package/registry/admin-apps/react/variants/base/src/components/app-sidebar.tsx +181 -0
  279. package/registry/admin-apps/react/variants/base/src/components/breadcrumb.tsx +47 -0
  280. package/registry/admin-apps/react/variants/base/src/components/change-password-dialog.tsx +102 -0
  281. package/registry/admin-apps/react/variants/base/src/components/form-error-alert.tsx +23 -0
  282. package/registry/admin-apps/react/variants/base/src/components/layout/AppShell.tsx +36 -0
  283. package/registry/admin-apps/react/variants/base/src/components/layout/RequireAuth.tsx +66 -0
  284. package/registry/admin-apps/react/variants/base/src/components/permission-group-select.tsx +99 -0
  285. package/registry/admin-apps/react/variants/base/src/components/permission-group-view.tsx +53 -0
  286. package/registry/admin-apps/react/variants/base/src/components/photo-upload.tsx +221 -0
  287. package/registry/admin-apps/react/variants/base/src/components/ui/combobox.tsx +243 -0
  288. package/registry/admin-apps/react/variants/base/src/components/ui/command.tsx +177 -0
  289. package/registry/admin-apps/react/variants/base/src/components/ui/date-picker.tsx +322 -0
  290. package/registry/admin-apps/react/variants/base/src/components/ui/sonner.tsx +34 -0
  291. package/registry/admin-apps/react/variants/base/src/components/user-menu.tsx +65 -0
  292. package/registry/admin-apps/react/variants/base/src/hooks/use-live-audit-feed.ts +50 -0
  293. package/registry/admin-apps/react/variants/base/src/index.css +161 -0
  294. package/registry/admin-apps/react/variants/base/src/lib/ability.ts +72 -0
  295. package/registry/admin-apps/react/variants/base/src/lib/auth-client.ts +9 -0
  296. package/registry/admin-apps/react/variants/base/src/lib/theme.tsx +64 -0
  297. package/registry/admin-apps/react/variants/base/src/lib/token-storage.ts +34 -0
  298. package/registry/admin-apps/react/variants/base/src/main.tsx +24 -0
  299. package/registry/admin-apps/react/variants/base/src/pages/AccountPage.tsx +368 -0
  300. package/registry/admin-apps/react/variants/base/src/pages/AddCountryPage.tsx +227 -0
  301. package/registry/admin-apps/react/variants/base/src/pages/AddCustomerPage.tsx +220 -0
  302. package/registry/admin-apps/react/variants/base/src/pages/AddLanguagePage.tsx +167 -0
  303. package/registry/admin-apps/react/variants/base/src/pages/AddRolePage.tsx +187 -0
  304. package/registry/admin-apps/react/variants/base/src/pages/AddUserPage.tsx +328 -0
  305. package/registry/admin-apps/react/variants/base/src/pages/AuditLogPage.tsx +180 -0
  306. package/registry/admin-apps/react/variants/base/src/pages/CountriesPage.tsx +371 -0
  307. package/registry/admin-apps/react/variants/base/src/pages/CountryDetailPage.tsx +209 -0
  308. package/registry/admin-apps/react/variants/base/src/pages/CustomerDetailPage.tsx +231 -0
  309. package/registry/admin-apps/react/variants/base/src/pages/CustomersPage.tsx +404 -0
  310. package/registry/admin-apps/react/variants/base/src/pages/DashboardPage.tsx +190 -0
  311. package/registry/admin-apps/react/variants/base/src/pages/EditCountryPage.tsx +279 -0
  312. package/registry/admin-apps/react/variants/base/src/pages/EditCustomerPage.tsx +272 -0
  313. package/registry/admin-apps/react/variants/base/src/pages/EditLanguagePage.tsx +216 -0
  314. package/registry/admin-apps/react/variants/base/src/pages/EditRolePage.tsx +232 -0
  315. package/registry/admin-apps/react/variants/base/src/pages/EditUserPage.tsx +308 -0
  316. package/registry/admin-apps/react/variants/base/src/pages/LanguageDetailPage.tsx +201 -0
  317. package/registry/admin-apps/react/variants/base/src/pages/LanguagesPage.tsx +346 -0
  318. package/registry/admin-apps/react/variants/base/src/pages/LoginPage.tsx +149 -0
  319. package/registry/admin-apps/react/variants/base/src/pages/PermissionDetailPage.tsx +135 -0
  320. package/registry/admin-apps/react/variants/base/src/pages/PermissionsPage.tsx +331 -0
  321. package/registry/admin-apps/react/variants/base/src/pages/RoleDetailPage.tsx +167 -0
  322. package/registry/admin-apps/react/variants/base/src/pages/RolesPage.tsx +613 -0
  323. package/registry/admin-apps/react/variants/base/src/pages/UserDetailPage.tsx +268 -0
  324. package/registry/admin-apps/react/variants/base/src/pages/UsersPage.tsx +423 -0
  325. package/registry/admin-apps/react/variants/base/src/pages/country-schema.ts +29 -0
  326. package/registry/admin-apps/react/variants/base/src/pages/customer-schema.ts +37 -0
  327. package/registry/admin-apps/react/variants/base/src/pages/language-schema.ts +28 -0
  328. package/registry/admin-apps/react/variants/base/src/pages/user-schema.ts +36 -0
  329. package/registry/admin-apps/react/variants/base/src/stores/auth-store.ts +144 -0
  330. package/registry/admin-apps/react/variants/base/src/stores/store-context.tsx +15 -0
  331. package/registry/admin-apps/react/variants/base/vite.config.ts +15 -0
  332. package/registry/admin-apps/react/variants/workspaces/.env.example +5 -0
  333. package/registry/admin-apps/react/variants/workspaces/Dockerfile +32 -0
  334. package/registry/admin-apps/react/variants/workspaces/index.html +12 -0
  335. package/registry/admin-apps/react/variants/workspaces/package.json +61 -0
  336. package/registry/admin-apps/react/variants/workspaces/src/App.tsx +118 -0
  337. package/registry/admin-apps/react/variants/workspaces/src/components/app-sidebar.tsx +186 -0
  338. package/registry/admin-apps/react/variants/workspaces/src/components/breadcrumb.tsx +39 -0
  339. package/registry/admin-apps/react/variants/workspaces/src/components/change-password-dialog.tsx +111 -0
  340. package/registry/admin-apps/react/variants/workspaces/src/components/form-error-alert.tsx +23 -0
  341. package/registry/admin-apps/react/variants/workspaces/src/components/layout/AppShell.tsx +37 -0
  342. package/registry/admin-apps/react/variants/workspaces/src/components/layout/CreateWorkspaceDialog.tsx +66 -0
  343. package/registry/admin-apps/react/variants/workspaces/src/components/layout/RequireAuth.tsx +107 -0
  344. package/registry/admin-apps/react/variants/workspaces/src/components/layout/WorkspaceSwitcher.tsx +52 -0
  345. package/registry/admin-apps/react/variants/workspaces/src/components/permission-group-select.tsx +99 -0
  346. package/registry/admin-apps/react/variants/workspaces/src/components/permission-group-view.tsx +53 -0
  347. package/registry/admin-apps/react/variants/workspaces/src/components/photo-upload.tsx +223 -0
  348. package/registry/admin-apps/react/variants/workspaces/src/components/ui/combobox.tsx +243 -0
  349. package/registry/admin-apps/react/variants/workspaces/src/components/ui/command.tsx +184 -0
  350. package/registry/admin-apps/react/variants/workspaces/src/components/ui/date-picker.tsx +323 -0
  351. package/registry/admin-apps/react/variants/workspaces/src/components/ui/sonner.tsx +34 -0
  352. package/registry/admin-apps/react/variants/workspaces/src/components/user-menu.tsx +66 -0
  353. package/registry/admin-apps/react/variants/workspaces/src/hooks/use-live-audit-feed.ts +50 -0
  354. package/registry/admin-apps/react/variants/workspaces/src/index.css +162 -0
  355. package/registry/admin-apps/react/variants/workspaces/src/lib/ability.ts +78 -0
  356. package/registry/admin-apps/react/variants/workspaces/src/lib/auth-client.ts +27 -0
  357. package/registry/admin-apps/react/variants/workspaces/src/lib/permission-groups.ts +22 -0
  358. package/registry/admin-apps/react/variants/workspaces/src/lib/theme.tsx +64 -0
  359. package/registry/admin-apps/react/variants/workspaces/src/lib/token-storage.ts +37 -0
  360. package/registry/admin-apps/react/variants/workspaces/src/lib/user-fields.ts +13 -0
  361. package/registry/admin-apps/react/variants/workspaces/src/main.tsx +24 -0
  362. package/registry/admin-apps/react/variants/workspaces/src/pages/AccountPage.tsx +351 -0
  363. package/registry/admin-apps/react/variants/workspaces/src/pages/AddCountryPage.tsx +230 -0
  364. package/registry/admin-apps/react/variants/workspaces/src/pages/AddCustomerPage.tsx +224 -0
  365. package/registry/admin-apps/react/variants/workspaces/src/pages/AddLanguagePage.tsx +170 -0
  366. package/registry/admin-apps/react/variants/workspaces/src/pages/AddUserPage.tsx +297 -0
  367. package/registry/admin-apps/react/variants/workspaces/src/pages/AuditLogPage.tsx +195 -0
  368. package/registry/admin-apps/react/variants/workspaces/src/pages/CountriesPage.tsx +378 -0
  369. package/registry/admin-apps/react/variants/workspaces/src/pages/CountryDetailPage.tsx +215 -0
  370. package/registry/admin-apps/react/variants/workspaces/src/pages/CustomerDetailPage.tsx +237 -0
  371. package/registry/admin-apps/react/variants/workspaces/src/pages/CustomersPage.tsx +411 -0
  372. package/registry/admin-apps/react/variants/workspaces/src/pages/DashboardPage.tsx +191 -0
  373. package/registry/admin-apps/react/variants/workspaces/src/pages/EditCountryPage.tsx +285 -0
  374. package/registry/admin-apps/react/variants/workspaces/src/pages/EditCustomerPage.tsx +279 -0
  375. package/registry/admin-apps/react/variants/workspaces/src/pages/EditLanguagePage.tsx +222 -0
  376. package/registry/admin-apps/react/variants/workspaces/src/pages/LanguageDetailPage.tsx +207 -0
  377. package/registry/admin-apps/react/variants/workspaces/src/pages/LanguagesPage.tsx +353 -0
  378. package/registry/admin-apps/react/variants/workspaces/src/pages/LoginPage.tsx +149 -0
  379. package/registry/admin-apps/react/variants/workspaces/src/pages/MembersPage.tsx +349 -0
  380. package/registry/admin-apps/react/variants/workspaces/src/pages/PermissionDetailPage.tsx +123 -0
  381. package/registry/admin-apps/react/variants/workspaces/src/pages/PermissionsPage.tsx +317 -0
  382. package/registry/admin-apps/react/variants/workspaces/src/pages/RoleDetailPage.tsx +207 -0
  383. package/registry/admin-apps/react/variants/workspaces/src/pages/RolesPage.tsx +617 -0
  384. package/registry/admin-apps/react/variants/workspaces/src/pages/UserDetailPage.tsx +405 -0
  385. package/registry/admin-apps/react/variants/workspaces/src/pages/UsersPage.tsx +425 -0
  386. package/registry/admin-apps/react/variants/workspaces/src/pages/country-schema.ts +29 -0
  387. package/registry/admin-apps/react/variants/workspaces/src/pages/customer-schema.ts +34 -0
  388. package/registry/admin-apps/react/variants/workspaces/src/pages/language-schema.ts +27 -0
  389. package/registry/admin-apps/react/variants/workspaces/src/stores/auth-store.ts +169 -0
  390. package/registry/admin-apps/react/variants/workspaces/src/stores/store-context.tsx +43 -0
  391. package/registry/admin-apps/react/variants/workspaces/src/stores/workspace-store.ts +120 -0
  392. package/registry/admin-apps/react/variants/workspaces/vite.config.ts +15 -0
  393. package/registry/combos/express-drizzle/package.json +32 -0
  394. package/registry/combos/express-drizzle/scripts/materialize.mjs +104 -0
  395. package/registry/combos/express-drizzle/scripts/migrate.mjs +41 -0
  396. package/registry/combos/express-drizzle/scripts/prove-cycle.mjs +29 -0
  397. package/registry/combos/express-drizzle/scripts/seed.mjs +25 -0
  398. package/registry/combos/express-drizzle/shared/drizzle.config.ts +67 -0
  399. package/registry/combos/express-drizzle/shared/src/ability.ts +44 -0
  400. package/registry/combos/express-drizzle/shared/src/auth-core-error.middleware.ts +31 -0
  401. package/registry/combos/express-drizzle/shared/src/auth.config.ts +63 -0
  402. package/registry/combos/express-drizzle/shared/src/auth.middleware.ts +38 -0
  403. package/registry/combos/express-drizzle/shared/src/auth.router.ts +266 -0
  404. package/registry/combos/express-drizzle/shared/src/db.ts +12 -0
  405. package/registry/combos/express-drizzle/shared/src/http-error.ts +18 -0
  406. package/registry/combos/express-drizzle/shared/src/id.helper.ts +22 -0
  407. package/registry/combos/express-drizzle/shared/src/key-provider.ts +52 -0
  408. package/registry/combos/express-drizzle/shared/src/oauth.repository.ts +47 -0
  409. package/registry/combos/express-drizzle/shared/src/openapi-fragment.ts +49 -0
  410. package/registry/combos/express-drizzle/shared/src/openapi-spec.ts +493 -0
  411. package/registry/combos/express-drizzle/shared/src/pagination.ts +30 -0
  412. package/registry/combos/express-drizzle/shared/src/password-reset.repository.ts +35 -0
  413. package/registry/combos/express-drizzle/shared/src/permission-cache.ts +191 -0
  414. package/registry/combos/express-drizzle/shared/src/rate-limit.store.ts +24 -0
  415. package/registry/combos/express-drizzle/shared/src/request-context.ts +35 -0
  416. package/registry/combos/express-drizzle/shared/src/response-envelope.middleware.ts +46 -0
  417. package/registry/combos/express-drizzle/shared/src/route-tiers.ts +148 -0
  418. package/registry/combos/express-drizzle/shared/src/session.repository.ts +130 -0
  419. package/registry/combos/express-drizzle/shared/src/two-factor.repository.ts +38 -0
  420. package/registry/combos/express-drizzle/test/bootstrap.ts +40 -0
  421. package/registry/combos/express-drizzle/test/harness.ts +187 -0
  422. package/registry/combos/express-drizzle/test/prove-cycle.ts +789 -0
  423. package/registry/combos/express-drizzle/tsconfig.json +20 -0
  424. package/registry/combos/express-drizzle/variants/base/.env.example +25 -0
  425. package/registry/combos/express-drizzle/variants/base/drizzle/0000_init.sql +219 -0
  426. package/registry/combos/express-drizzle/variants/base/drizzle/0001_add_is_active_field.sql +1 -0
  427. package/registry/combos/express-drizzle/variants/base/drizzle/meta/0000_snapshot.json +1861 -0
  428. package/registry/combos/express-drizzle/variants/base/drizzle/meta/0001_snapshot.json +1868 -0
  429. package/registry/combos/express-drizzle/variants/base/drizzle/meta/_journal.json +20 -0
  430. package/registry/combos/express-drizzle/variants/base/src/admin.router.ts +307 -0
  431. package/registry/combos/express-drizzle/variants/base/src/audit-log.repository.ts +93 -0
  432. package/registry/combos/express-drizzle/variants/base/src/auth.service.ts +528 -0
  433. package/registry/combos/express-drizzle/variants/base/src/authz.middleware.ts +58 -0
  434. package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +78 -0
  435. package/registry/combos/express-drizzle/variants/base/src/openapi-admin.ts +565 -0
  436. package/registry/combos/express-drizzle/variants/base/src/rbac.defaults.ts +218 -0
  437. package/registry/combos/express-drizzle/variants/base/src/rbac.repository.ts +606 -0
  438. package/registry/combos/express-drizzle/variants/base/src/schema.ts +425 -0
  439. package/registry/combos/express-drizzle/variants/base/src/seed.ts +138 -0
  440. package/registry/combos/express-drizzle/variants/base/test/variant-hooks.ts +179 -0
  441. package/registry/combos/express-drizzle/variants/workspaces/.env.example +30 -0
  442. package/registry/combos/express-drizzle/variants/workspaces/drizzle/0000_init.sql +251 -0
  443. package/registry/combos/express-drizzle/variants/workspaces/drizzle/0001_add_is_active_field.sql +1 -0
  444. package/registry/combos/express-drizzle/variants/workspaces/drizzle/meta/0000_snapshot.json +2155 -0
  445. package/registry/combos/express-drizzle/variants/workspaces/drizzle/meta/0001_snapshot.json +2162 -0
  446. package/registry/combos/express-drizzle/variants/workspaces/drizzle/meta/_journal.json +20 -0
  447. package/registry/combos/express-drizzle/variants/workspaces/src/admin.router.ts +323 -0
  448. package/registry/combos/express-drizzle/variants/workspaces/src/audit-log.repository.ts +105 -0
  449. package/registry/combos/express-drizzle/variants/workspaces/src/auth.service.ts +545 -0
  450. package/registry/combos/express-drizzle/variants/workspaces/src/authz.middleware.ts +94 -0
  451. package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +87 -0
  452. package/registry/combos/express-drizzle/variants/workspaces/src/openapi-admin.ts +596 -0
  453. package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +183 -0
  454. package/registry/combos/express-drizzle/variants/workspaces/src/rbac.defaults.ts +248 -0
  455. package/registry/combos/express-drizzle/variants/workspaces/src/rbac.repository.ts +698 -0
  456. package/registry/combos/express-drizzle/variants/workspaces/src/schema.ts +487 -0
  457. package/registry/combos/express-drizzle/variants/workspaces/src/seed.ts +173 -0
  458. package/registry/combos/express-drizzle/variants/workspaces/src/workspace.repository.ts +254 -0
  459. package/registry/combos/express-drizzle/variants/workspaces/src/workspace.router.ts +123 -0
  460. package/registry/combos/express-drizzle/variants/workspaces/test/variant-hooks.ts +370 -0
  461. package/registry/combos/express-prisma/package.json +32 -0
  462. package/registry/combos/express-prisma/scripts/materialize.mjs +84 -0
  463. package/registry/combos/express-prisma/scripts/migrate.mjs +32 -0
  464. package/registry/combos/express-prisma/scripts/prove-cycle.mjs +30 -0
  465. package/registry/combos/express-prisma/scripts/seed.mjs +24 -0
  466. package/registry/combos/express-prisma/shared/prisma.config.ts +38 -0
  467. package/registry/combos/express-prisma/shared/src/ability.ts +44 -0
  468. package/registry/combos/express-prisma/shared/src/auth-core-error.middleware.ts +31 -0
  469. package/registry/combos/express-prisma/shared/src/auth.config.ts +63 -0
  470. package/registry/combos/express-prisma/shared/src/auth.middleware.ts +44 -0
  471. package/registry/combos/express-prisma/shared/src/auth.router.ts +269 -0
  472. package/registry/combos/express-prisma/shared/src/http-error.ts +18 -0
  473. package/registry/combos/express-prisma/shared/src/id.helper.ts +22 -0
  474. package/registry/combos/express-prisma/shared/src/key-provider.ts +52 -0
  475. package/registry/combos/express-prisma/shared/src/oauth.repository.ts +33 -0
  476. package/registry/combos/express-prisma/shared/src/openapi-fragment.ts +49 -0
  477. package/registry/combos/express-prisma/shared/src/openapi-spec.ts +487 -0
  478. package/registry/combos/express-prisma/shared/src/pagination.ts +30 -0
  479. package/registry/combos/express-prisma/shared/src/password-reset.repository.ts +29 -0
  480. package/registry/combos/express-prisma/shared/src/permission-cache.ts +191 -0
  481. package/registry/combos/express-prisma/shared/src/rate-limit.store.ts +21 -0
  482. package/registry/combos/express-prisma/shared/src/request-context.ts +35 -0
  483. package/registry/combos/express-prisma/shared/src/response-envelope.middleware.ts +46 -0
  484. package/registry/combos/express-prisma/shared/src/route-tiers.ts +148 -0
  485. package/registry/combos/express-prisma/shared/src/session.repository.ts +140 -0
  486. package/registry/combos/express-prisma/shared/src/two-factor.repository.ts +30 -0
  487. package/registry/combos/express-prisma/test/bootstrap.ts +45 -0
  488. package/registry/combos/express-prisma/test/harness.ts +187 -0
  489. package/registry/combos/express-prisma/test/prove-cycle.ts +793 -0
  490. package/registry/combos/express-prisma/tsconfig.json +21 -0
  491. package/registry/combos/express-prisma/variants/base/.env.example +25 -0
  492. package/registry/combos/express-prisma/variants/base/prisma/migrations/20260810165456_init/migration.sql +370 -0
  493. package/registry/combos/express-prisma/variants/base/prisma/migrations/20260811151048_add_is_active_field/migration.sql +2 -0
  494. package/registry/combos/express-prisma/variants/base/prisma/migrations/migration_lock.toml +3 -0
  495. package/registry/combos/express-prisma/variants/base/prisma/schema/simple-auth-kit.prisma +332 -0
  496. package/registry/combos/express-prisma/variants/base/src/admin.router.ts +314 -0
  497. package/registry/combos/express-prisma/variants/base/src/audit-log.repository.ts +91 -0
  498. package/registry/combos/express-prisma/variants/base/src/auth.service.ts +521 -0
  499. package/registry/combos/express-prisma/variants/base/src/authz.middleware.ts +58 -0
  500. package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +93 -0
  501. package/registry/combos/express-prisma/variants/base/src/openapi-admin.ts +569 -0
  502. package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +195 -0
  503. package/registry/combos/express-prisma/variants/base/src/rbac.repository.ts +484 -0
  504. package/registry/combos/express-prisma/variants/base/src/seed.ts +115 -0
  505. package/registry/combos/express-prisma/variants/base/test/variant-hooks.ts +159 -0
  506. package/registry/combos/express-prisma/variants/workspaces/.env.example +30 -0
  507. package/registry/combos/express-prisma/variants/workspaces/prisma/migrations/20260810165502_init/migration.sql +443 -0
  508. package/registry/combos/express-prisma/variants/workspaces/prisma/migrations/20260811151051_add_is_active_field/migration.sql +2 -0
  509. package/registry/combos/express-prisma/variants/workspaces/prisma/migrations/migration_lock.toml +3 -0
  510. package/registry/combos/express-prisma/variants/workspaces/prisma/schema/simple-auth-kit.prisma +394 -0
  511. package/registry/combos/express-prisma/variants/workspaces/src/admin.router.ts +330 -0
  512. package/registry/combos/express-prisma/variants/workspaces/src/audit-log.repository.ts +102 -0
  513. package/registry/combos/express-prisma/variants/workspaces/src/auth.service.ts +542 -0
  514. package/registry/combos/express-prisma/variants/workspaces/src/authz.middleware.ts +94 -0
  515. package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +99 -0
  516. package/registry/combos/express-prisma/variants/workspaces/src/openapi-admin.ts +601 -0
  517. package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +183 -0
  518. package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +222 -0
  519. package/registry/combos/express-prisma/variants/workspaces/src/rbac.repository.ts +527 -0
  520. package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +147 -0
  521. package/registry/combos/express-prisma/variants/workspaces/src/workspace.repository.ts +188 -0
  522. package/registry/combos/express-prisma/variants/workspaces/src/workspace.router.ts +123 -0
  523. package/registry/combos/express-prisma/variants/workspaces/test/variant-hooks.ts +358 -0
  524. package/registry/combos/nestjs-drizzle/package.json +36 -0
  525. package/registry/combos/nestjs-drizzle/scripts/materialize.mjs +104 -0
  526. package/registry/combos/nestjs-drizzle/scripts/migrate.mjs +34 -0
  527. package/registry/combos/nestjs-drizzle/scripts/prove-cycle.mjs +29 -0
  528. package/registry/combos/nestjs-drizzle/scripts/seed.mjs +24 -0
  529. package/registry/combos/nestjs-drizzle/shared/drizzle.config.ts +67 -0
  530. package/registry/combos/nestjs-drizzle/shared/src/ability.guard.ts +46 -0
  531. package/registry/combos/nestjs-drizzle/shared/src/ability.ts +44 -0
  532. package/registry/combos/nestjs-drizzle/shared/src/auth-core-error.filter.ts +32 -0
  533. package/registry/combos/nestjs-drizzle/shared/src/auth.config.ts +65 -0
  534. package/registry/combos/nestjs-drizzle/shared/src/auth.controller.ts +299 -0
  535. package/registry/combos/nestjs-drizzle/shared/src/auth.guard.ts +34 -0
  536. package/registry/combos/nestjs-drizzle/shared/src/db.ts +12 -0
  537. package/registry/combos/nestjs-drizzle/shared/src/dto/auth.dto.ts +429 -0
  538. package/registry/combos/nestjs-drizzle/shared/src/id.helper.ts +22 -0
  539. package/registry/combos/nestjs-drizzle/shared/src/key-provider.ts +51 -0
  540. package/registry/combos/nestjs-drizzle/shared/src/oauth.repository.ts +36 -0
  541. package/registry/combos/nestjs-drizzle/shared/src/pagination.ts +30 -0
  542. package/registry/combos/nestjs-drizzle/shared/src/password-reset.repository.ts +29 -0
  543. package/registry/combos/nestjs-drizzle/shared/src/permission-cache.ts +196 -0
  544. package/registry/combos/nestjs-drizzle/shared/src/rate-limit.store.ts +26 -0
  545. package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +25 -0
  546. package/registry/combos/nestjs-drizzle/shared/src/response.interceptor.ts +48 -0
  547. package/registry/combos/nestjs-drizzle/shared/src/route-tiers.ts +144 -0
  548. package/registry/combos/nestjs-drizzle/shared/src/session.repository.ts +132 -0
  549. package/registry/combos/nestjs-drizzle/shared/src/two-factor.repository.ts +35 -0
  550. package/registry/combos/nestjs-drizzle/test/bootstrap.ts +49 -0
  551. package/registry/combos/nestjs-drizzle/test/harness.ts +187 -0
  552. package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +795 -0
  553. package/registry/combos/nestjs-drizzle/tsconfig.json +20 -0
  554. package/registry/combos/nestjs-drizzle/variants/base/.env.example +25 -0
  555. package/registry/combos/nestjs-drizzle/variants/base/drizzle/0000_init.sql +219 -0
  556. package/registry/combos/nestjs-drizzle/variants/base/drizzle/0001_add_is_active_field.sql +1 -0
  557. package/registry/combos/nestjs-drizzle/variants/base/drizzle/0002_colossal_true_believers.sql +3 -0
  558. package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/0000_snapshot.json +1861 -0
  559. package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/0001_snapshot.json +1868 -0
  560. package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/0002_snapshot.json +1887 -0
  561. package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/_journal.json +27 -0
  562. package/registry/combos/nestjs-drizzle/variants/base/src/admin.controller.ts +361 -0
  563. package/registry/combos/nestjs-drizzle/variants/base/src/audit-log.repository.ts +90 -0
  564. package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +83 -0
  565. package/registry/combos/nestjs-drizzle/variants/base/src/auth.service.ts +544 -0
  566. package/registry/combos/nestjs-drizzle/variants/base/src/authz.guard.ts +53 -0
  567. package/registry/combos/nestjs-drizzle/variants/base/src/dto/admin.dto.ts +130 -0
  568. package/registry/combos/nestjs-drizzle/variants/base/src/rbac.defaults.ts +218 -0
  569. package/registry/combos/nestjs-drizzle/variants/base/src/rbac.repository.ts +633 -0
  570. package/registry/combos/nestjs-drizzle/variants/base/src/schema.ts +427 -0
  571. package/registry/combos/nestjs-drizzle/variants/base/src/seed.ts +138 -0
  572. package/registry/combos/nestjs-drizzle/variants/base/test/variant-hooks.ts +179 -0
  573. package/registry/combos/nestjs-drizzle/variants/workspaces/.env.example +30 -0
  574. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/0000_init.sql +251 -0
  575. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/0001_add_is_active_field.sql +1 -0
  576. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/0002_calm_tyger_tiger.sql +3 -0
  577. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/0000_snapshot.json +2155 -0
  578. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/0001_snapshot.json +2162 -0
  579. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/0002_snapshot.json +2181 -0
  580. package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/_journal.json +27 -0
  581. package/registry/combos/nestjs-drizzle/variants/workspaces/src/admin.controller.ts +383 -0
  582. package/registry/combos/nestjs-drizzle/variants/workspaces/src/audit-log.repository.ts +102 -0
  583. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +87 -0
  584. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.service.ts +553 -0
  585. package/registry/combos/nestjs-drizzle/variants/workspaces/src/authz.guard.ts +87 -0
  586. package/registry/combos/nestjs-drizzle/variants/workspaces/src/dto/admin.dto.ts +137 -0
  587. package/registry/combos/nestjs-drizzle/variants/workspaces/src/dto/workspace.dto.ts +60 -0
  588. package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.defaults.ts +248 -0
  589. package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.repository.ts +719 -0
  590. package/registry/combos/nestjs-drizzle/variants/workspaces/src/schema.ts +489 -0
  591. package/registry/combos/nestjs-drizzle/variants/workspaces/src/seed.ts +174 -0
  592. package/registry/combos/nestjs-drizzle/variants/workspaces/src/workspace.controller.ts +123 -0
  593. package/registry/combos/nestjs-drizzle/variants/workspaces/src/workspace.repository.ts +255 -0
  594. package/registry/combos/nestjs-drizzle/variants/workspaces/test/variant-hooks.ts +370 -0
  595. package/registry/combos/nestjs-prisma/package.json +41 -0
  596. package/registry/combos/nestjs-prisma/scripts/materialize.mjs +84 -0
  597. package/registry/combos/nestjs-prisma/scripts/migrate.mjs +32 -0
  598. package/registry/combos/nestjs-prisma/scripts/prove-cycle.mjs +30 -0
  599. package/registry/combos/nestjs-prisma/scripts/seed.mjs +24 -0
  600. package/registry/combos/nestjs-prisma/shared/prisma.config.ts +38 -0
  601. package/registry/combos/nestjs-prisma/shared/src/ability.guard.ts +29 -0
  602. package/registry/combos/nestjs-prisma/shared/src/ability.ts +23 -0
  603. package/registry/combos/nestjs-prisma/shared/src/auth-core-error.filter.ts +32 -0
  604. package/registry/combos/nestjs-prisma/shared/src/auth.config.ts +71 -0
  605. package/registry/combos/nestjs-prisma/shared/src/auth.controller.ts +303 -0
  606. package/registry/combos/nestjs-prisma/shared/src/auth.guard.ts +31 -0
  607. package/registry/combos/nestjs-prisma/shared/src/dto/auth.dto.ts +438 -0
  608. package/registry/combos/nestjs-prisma/shared/src/id.helper.ts +22 -0
  609. package/registry/combos/nestjs-prisma/shared/src/key-provider.ts +42 -0
  610. package/registry/combos/nestjs-prisma/shared/src/oauth.repository.ts +32 -0
  611. package/registry/combos/nestjs-prisma/shared/src/pagination.ts +30 -0
  612. package/registry/combos/nestjs-prisma/shared/src/password-reset.repository.ts +29 -0
  613. package/registry/combos/nestjs-prisma/shared/src/permission-cache.ts +140 -0
  614. package/registry/combos/nestjs-prisma/shared/src/rate-limit.store.ts +26 -0
  615. package/registry/combos/nestjs-prisma/shared/src/request-context.ts +19 -0
  616. package/registry/combos/nestjs-prisma/shared/src/response.interceptor.ts +48 -0
  617. package/registry/combos/nestjs-prisma/shared/src/route-tiers.ts +102 -0
  618. package/registry/combos/nestjs-prisma/shared/src/session.repository.ts +129 -0
  619. package/registry/combos/nestjs-prisma/shared/src/two-factor.repository.ts +29 -0
  620. package/registry/combos/nestjs-prisma/test/bootstrap.ts +54 -0
  621. package/registry/combos/nestjs-prisma/test/harness.ts +186 -0
  622. package/registry/combos/nestjs-prisma/test/prove-cycle.ts +795 -0
  623. package/registry/combos/nestjs-prisma/tsconfig.json +21 -0
  624. package/registry/combos/nestjs-prisma/variants/base/.env.example +31 -0
  625. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810084937_init/migration.sql +269 -0
  626. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810122546_add_profile_audit_soft_delete/migration.sql +96 -0
  627. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810123620_add_display_name/migration.sql +3 -0
  628. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810131421_drop_signing_keys/migration.sql +3 -0
  629. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810161515_bigint_ids/migration.sql +305 -0
  630. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810162120_drop_name_unique/migration.sql +6 -0
  631. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260811145755_add_is_active_field/migration.sql +2 -0
  632. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260811183529_add_countries_languages_customers/migration.sql +146 -0
  633. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260812121128_add_user_profile_details/migration.sql +4 -0
  634. package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/migration_lock.toml +3 -0
  635. package/registry/combos/nestjs-prisma/variants/base/prisma/schema/simple-auth-kit.prisma +437 -0
  636. package/registry/combos/nestjs-prisma/variants/base/src/admin.controller.ts +684 -0
  637. package/registry/combos/nestjs-prisma/variants/base/src/audit-log.gateway.ts +51 -0
  638. package/registry/combos/nestjs-prisma/variants/base/src/audit-log.repository.ts +111 -0
  639. package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +87 -0
  640. package/registry/combos/nestjs-prisma/variants/base/src/auth.service.ts +618 -0
  641. package/registry/combos/nestjs-prisma/variants/base/src/authz.guard.ts +34 -0
  642. package/registry/combos/nestjs-prisma/variants/base/src/country.repository.ts +149 -0
  643. package/registry/combos/nestjs-prisma/variants/base/src/customer.repository.ts +169 -0
  644. package/registry/combos/nestjs-prisma/variants/base/src/docs.ts +60 -0
  645. package/registry/combos/nestjs-prisma/variants/base/src/dto/admin.dto.ts +130 -0
  646. package/registry/combos/nestjs-prisma/variants/base/src/dto/country.dto.ts +120 -0
  647. package/registry/combos/nestjs-prisma/variants/base/src/dto/customer.dto.ts +147 -0
  648. package/registry/combos/nestjs-prisma/variants/base/src/dto/language.dto.ts +93 -0
  649. package/registry/combos/nestjs-prisma/variants/base/src/language.repository.ts +135 -0
  650. package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +193 -0
  651. package/registry/combos/nestjs-prisma/variants/base/src/rbac.repository.ts +514 -0
  652. package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +89 -0
  653. package/registry/combos/nestjs-prisma/variants/base/test/variant-hooks.ts +135 -0
  654. package/registry/combos/nestjs-prisma/variants/workspaces/.env.example +30 -0
  655. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810084938_init/migration.sql +308 -0
  656. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810123450_add_profile_audit_soft_delete/migration.sql +96 -0
  657. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810123632_add_display_name/migration.sql +3 -0
  658. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810124243_workspace_audit_soft_delete/migration.sql +25 -0
  659. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810131432_drop_signing_keys/migration.sql +3 -0
  660. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810161551_bigint_ids/migration.sql +393 -0
  661. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810162131_drop_name_unique/migration.sql +3 -0
  662. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260811145805_add_is_active_field/migration.sql +2 -0
  663. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260813120000_add_countries_languages_customers/migration.sql +158 -0
  664. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/migration_lock.toml +3 -0
  665. package/registry/combos/nestjs-prisma/variants/workspaces/prisma/schema/simple-auth-kit.prisma +521 -0
  666. package/registry/combos/nestjs-prisma/variants/workspaces/src/admin.controller.ts +733 -0
  667. package/registry/combos/nestjs-prisma/variants/workspaces/src/audit-log.repository.ts +98 -0
  668. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +83 -0
  669. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.service.ts +509 -0
  670. package/registry/combos/nestjs-prisma/variants/workspaces/src/authz.guard.ts +69 -0
  671. package/registry/combos/nestjs-prisma/variants/workspaces/src/country.repository.ts +158 -0
  672. package/registry/combos/nestjs-prisma/variants/workspaces/src/customer.repository.ts +179 -0
  673. package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/admin.dto.ts +128 -0
  674. package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/country.dto.ts +120 -0
  675. package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/customer.dto.ts +147 -0
  676. package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/language.dto.ts +93 -0
  677. package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/workspace.dto.ts +60 -0
  678. package/registry/combos/nestjs-prisma/variants/workspaces/src/language.repository.ts +143 -0
  679. package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +211 -0
  680. package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.repository.ts +505 -0
  681. package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +122 -0
  682. package/registry/combos/nestjs-prisma/variants/workspaces/src/workspace.controller.ts +111 -0
  683. package/registry/combos/nestjs-prisma/variants/workspaces/src/workspace.repository.ts +177 -0
  684. package/registry/combos/nestjs-prisma/variants/workspaces/test/variant-hooks.ts +333 -0
  685. package/registry/core/crypto.ts +43 -0
  686. package/registry/core/oauth.ts +159 -0
  687. package/registry/core/package.json +20 -0
  688. package/registry/core/password-reset.ts +42 -0
  689. package/registry/core/rate-limit.ts +33 -0
  690. package/registry/core/rbac.ts +4 -0
  691. package/registry/core/session-policy.ts +96 -0
  692. package/registry/core/test/crypto.test.ts +25 -0
  693. package/registry/core/test/oauth.test.ts +213 -0
  694. package/registry/core/test/password-reset.test.ts +77 -0
  695. package/registry/core/test/rate-limit.test.ts +41 -0
  696. package/registry/core/test/rbac.test.ts +20 -0
  697. package/registry/core/test/session-policy.test.ts +209 -0
  698. package/registry/core/test/test-keys.ts +6 -0
  699. package/registry/core/test/token-service.test.ts +81 -0
  700. package/registry/core/test/two-factor.test.ts +72 -0
  701. package/registry/core/token-service.ts +143 -0
  702. package/registry/core/tsconfig.json +5 -0
  703. package/registry/core/two-factor.ts +108 -0
  704. package/registry/core/types.ts +127 -0
  705. package/registry/mobile-apps/README.md +65 -0
  706. package/registry/mobile-apps/bare-rn/shared/.bundle/config +2 -0
  707. package/registry/mobile-apps/bare-rn/shared/.eslintrc.js +4 -0
  708. package/registry/mobile-apps/bare-rn/shared/.prettierrc.js +5 -0
  709. package/registry/mobile-apps/bare-rn/shared/.watchmanconfig +1 -0
  710. package/registry/mobile-apps/bare-rn/shared/App.tsx +28 -0
  711. package/registry/mobile-apps/bare-rn/shared/Gemfile +17 -0
  712. package/registry/mobile-apps/bare-rn/shared/README.md +97 -0
  713. package/registry/mobile-apps/bare-rn/shared/__mocks__/reactNativeConfigMock.js +3 -0
  714. package/registry/mobile-apps/bare-rn/shared/__mocks__/styleMock.js +1 -0
  715. package/registry/mobile-apps/bare-rn/shared/__tests__/App.test.tsx +13 -0
  716. package/registry/mobile-apps/bare-rn/shared/android/app/build.gradle +121 -0
  717. package/registry/mobile-apps/bare-rn/shared/android/app/debug.keystore +0 -0
  718. package/registry/mobile-apps/bare-rn/shared/android/app/proguard-rules.pro +10 -0
  719. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/AndroidManifest.xml +27 -0
  720. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/java/com/mobilebarern/MainActivity.kt +22 -0
  721. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/java/com/mobilebarern/MainApplication.kt +27 -0
  722. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  723. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  724. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  725. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  726. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  727. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  728. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  729. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  730. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  731. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  732. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  733. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/values/strings.xml +3 -0
  734. package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/values/styles.xml +9 -0
  735. package/registry/mobile-apps/bare-rn/shared/android/build.gradle +21 -0
  736. package/registry/mobile-apps/bare-rn/shared/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  737. package/registry/mobile-apps/bare-rn/shared/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  738. package/registry/mobile-apps/bare-rn/shared/android/gradle.properties +44 -0
  739. package/registry/mobile-apps/bare-rn/shared/android/gradlew +248 -0
  740. package/registry/mobile-apps/bare-rn/shared/android/gradlew.bat +98 -0
  741. package/registry/mobile-apps/bare-rn/shared/android/settings.gradle +6 -0
  742. package/registry/mobile-apps/bare-rn/shared/app.json +4 -0
  743. package/registry/mobile-apps/bare-rn/shared/babel.config.js +6 -0
  744. package/registry/mobile-apps/bare-rn/shared/global.css +2 -0
  745. package/registry/mobile-apps/bare-rn/shared/index.js +10 -0
  746. package/registry/mobile-apps/bare-rn/shared/ios/.xcode.env +11 -0
  747. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/AppDelegate.swift +48 -0
  748. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  749. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/Images.xcassets/Contents.json +6 -0
  750. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/Info.plist +59 -0
  751. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/LaunchScreen.storyboard +47 -0
  752. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/PrivacyInfo.xcprivacy +37 -0
  753. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn.xcodeproj/project.pbxproj +475 -0
  754. package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn.xcodeproj/xcshareddata/xcschemes/MobileBareRn.xcscheme +88 -0
  755. package/registry/mobile-apps/bare-rn/shared/ios/Podfile +34 -0
  756. package/registry/mobile-apps/bare-rn/shared/jest.config.js +17 -0
  757. package/registry/mobile-apps/bare-rn/shared/metro.config.js +55 -0
  758. package/registry/mobile-apps/bare-rn/shared/nativewind-env.d.ts +1 -0
  759. package/registry/mobile-apps/bare-rn/shared/src/api/tokenStorage.ts +29 -0
  760. package/registry/mobile-apps/bare-rn/shared/src/components/FormInput.tsx +21 -0
  761. package/registry/mobile-apps/bare-rn/shared/src/components/PrimaryButton.tsx +47 -0
  762. package/registry/mobile-apps/bare-rn/shared/src/screens/LoginScreen.tsx +58 -0
  763. package/registry/mobile-apps/bare-rn/shared/src/screens/SessionsScreen.tsx +77 -0
  764. package/registry/mobile-apps/bare-rn/shared/src/screens/SignupScreen.tsx +54 -0
  765. package/registry/mobile-apps/bare-rn/shared/src/screens/TwoFactorScreen.tsx +59 -0
  766. package/registry/mobile-apps/bare-rn/shared/tailwind.config.js +9 -0
  767. package/registry/mobile-apps/bare-rn/shared/tsconfig.json +17 -0
  768. package/registry/mobile-apps/bare-rn/variants/base/package.json +58 -0
  769. package/registry/mobile-apps/bare-rn/variants/base/src/api/authClient.ts +14 -0
  770. package/registry/mobile-apps/bare-rn/variants/base/src/navigation/RootNavigator.tsx +58 -0
  771. package/registry/mobile-apps/bare-rn/variants/base/src/navigation/types.ts +15 -0
  772. package/registry/mobile-apps/bare-rn/variants/base/src/screens/HomeScreen.tsx +64 -0
  773. package/registry/mobile-apps/bare-rn/variants/base/src/store/authStore.ts +143 -0
  774. package/registry/mobile-apps/bare-rn/variants/workspaces/package.json +58 -0
  775. package/registry/mobile-apps/bare-rn/variants/workspaces/src/api/authClient.ts +22 -0
  776. package/registry/mobile-apps/bare-rn/variants/workspaces/src/navigation/RootNavigator.tsx +72 -0
  777. package/registry/mobile-apps/bare-rn/variants/workspaces/src/navigation/types.ts +18 -0
  778. package/registry/mobile-apps/bare-rn/variants/workspaces/src/screens/HomeScreen.tsx +85 -0
  779. package/registry/mobile-apps/bare-rn/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +165 -0
  780. package/registry/mobile-apps/bare-rn/variants/workspaces/src/store/authStore.ts +177 -0
  781. package/registry/mobile-apps/bare-rn/variants/workspaces/src/store/workspaceStore.ts +90 -0
  782. package/registry/mobile-apps/bare-rn/variants/workspaces/src/workspace/activeWorkspace.ts +55 -0
  783. package/registry/mobile-apps/expo/shared/App.tsx +15 -0
  784. package/registry/mobile-apps/expo/shared/assets/android-icon-background.png +0 -0
  785. package/registry/mobile-apps/expo/shared/assets/android-icon-foreground.png +0 -0
  786. package/registry/mobile-apps/expo/shared/assets/android-icon-monochrome.png +0 -0
  787. package/registry/mobile-apps/expo/shared/assets/favicon.png +0 -0
  788. package/registry/mobile-apps/expo/shared/assets/icon.png +0 -0
  789. package/registry/mobile-apps/expo/shared/assets/splash-icon.png +0 -0
  790. package/registry/mobile-apps/expo/shared/babel.config.js +6 -0
  791. package/registry/mobile-apps/expo/shared/global.css +2 -0
  792. package/registry/mobile-apps/expo/shared/index.ts +8 -0
  793. package/registry/mobile-apps/expo/shared/metro.config.js +6 -0
  794. package/registry/mobile-apps/expo/shared/nativewind-env.d.ts +3 -0
  795. package/registry/mobile-apps/expo/shared/postcss.config.mjs +5 -0
  796. package/registry/mobile-apps/expo/shared/src/screens/LoginScreen.tsx +81 -0
  797. package/registry/mobile-apps/expo/shared/src/screens/SessionsScreen.tsx +77 -0
  798. package/registry/mobile-apps/expo/shared/src/screens/SignupScreen.tsx +77 -0
  799. package/registry/mobile-apps/expo/shared/src/screens/TwoFactorScreen.tsx +59 -0
  800. package/registry/mobile-apps/expo/shared/src/storage/asyncStorageTokenStorage.ts +32 -0
  801. package/registry/mobile-apps/expo/shared/tsconfig.json +6 -0
  802. package/registry/mobile-apps/expo/variants/base/app.json +25 -0
  803. package/registry/mobile-apps/expo/variants/base/package.json +35 -0
  804. package/registry/mobile-apps/expo/variants/base/src/api/authClient.ts +17 -0
  805. package/registry/mobile-apps/expo/variants/base/src/navigation/RootNavigator.tsx +58 -0
  806. package/registry/mobile-apps/expo/variants/base/src/navigation/types.ts +10 -0
  807. package/registry/mobile-apps/expo/variants/base/src/screens/HomeScreen.tsx +75 -0
  808. package/registry/mobile-apps/expo/variants/base/src/store/authStore.ts +146 -0
  809. package/registry/mobile-apps/expo/variants/workspaces/app.json +25 -0
  810. package/registry/mobile-apps/expo/variants/workspaces/package.json +35 -0
  811. package/registry/mobile-apps/expo/variants/workspaces/src/api/authClient.ts +21 -0
  812. package/registry/mobile-apps/expo/variants/workspaces/src/navigation/RootNavigator.tsx +82 -0
  813. package/registry/mobile-apps/expo/variants/workspaces/src/navigation/types.ts +20 -0
  814. package/registry/mobile-apps/expo/variants/workspaces/src/screens/HomeScreen.tsx +94 -0
  815. package/registry/mobile-apps/expo/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +175 -0
  816. package/registry/mobile-apps/expo/variants/workspaces/src/store/authStore.ts +179 -0
  817. package/registry/mobile-apps/expo/variants/workspaces/src/store/workspaceStore.ts +90 -0
  818. package/registry/mobile-apps/expo/variants/workspaces/src/workspace/activeWorkspace.ts +55 -0
  819. package/registry.json +263 -0
  820. package/simple-auth-kit.ts +715 -0
@@ -0,0 +1,733 @@
1
+ import { BadRequestException, Body, Controller, Delete, ForbiddenException, Get, Inject, Ip, Param, Patch, Post, Query, Req, UseGuards } from "@nestjs/common";
2
+ import { ApiBearerAuth, ApiBody, ApiHeader, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags } from "@nestjs/swagger";
3
+ import type { Request } from "express";
4
+ import { AbilityGuard } from "./ability.guard.js";
5
+ import { AuthGuard } from "./auth.guard.js";
6
+ import { AuthService } from "./auth.service.js";
7
+ import { WORKSPACE_HEADER, WorkspaceGuard } from "./authz.guard.js";
8
+ import { CheckAbility } from "./route-tiers.js";
9
+ import { WorkspaceRepository } from "./workspace.repository.js";
10
+ import { hashPassword } from "@/lib/auth/core/crypto.js";
11
+ import {
12
+ AssignRoleDto,
13
+ AttachPermissionDto,
14
+ CreateRoleDto,
15
+ CreateUserDto,
16
+ DefinePermissionDto,
17
+ DeleteReasonDto,
18
+ GrantPermissionDto,
19
+ OkResponseDto,
20
+ PermissionListResponseDto,
21
+ PermissionSummaryDto,
22
+ RoleListResponseDto,
23
+ RoleSummaryDto,
24
+ UpdateRoleDto,
25
+ UpdateUserDto,
26
+ } from "./dto/auth.dto.js";
27
+ import { AuditLogListResponseDto, UserListResponseDto, UserSummaryDto } from "./dto/admin.dto.js";
28
+ import { CountryListResponseDto, CountrySummaryDto, CreateCountryDto, UpdateCountryDto } from "./dto/country.dto.js";
29
+ import { CreateCustomerDto, CustomerListResponseDto, CustomerSummaryDto, UpdateCustomerDto } from "./dto/customer.dto.js";
30
+ import { CreateLanguageDto, LanguageListResponseDto, LanguageSummaryDto, UpdateLanguageDto } from "./dto/language.dto.js";
31
+ import { CountryRepository } from "./country.repository.js";
32
+ import { CustomerRepository } from "./customer.repository.js";
33
+ import { LanguageRepository } from "./language.repository.js";
34
+
35
+ function requireString(value: unknown, field: string): string {
36
+ if (typeof value !== "string" || value.length === 0) throw new BadRequestException(`${field} is required`);
37
+ return value;
38
+ }
39
+
40
+ const optionalString = (value: unknown): string | undefined => (typeof value === "string" ? value : undefined);
41
+
42
+ const optionalBoolean = (value: unknown): boolean | undefined => (typeof value === "boolean" ? value : undefined);
43
+
44
+ // Administration *of one workspace*, and nothing else. `WorkspaceGuard` resolves the caller's
45
+ // membership of the workspace named by the `X-Workspace-Id` header into the roles/permissions
46
+ // that membership carries there, and every handler passes that resolved context down, so the
47
+ // query itself is scoped too. An admin of workspace A calling with workspace B's id is rejected
48
+ // because the context resolved is B's membership — scoped by construction, not a second check.
49
+ @ApiTags("auth")
50
+ @Controller("auth/admin")
51
+ @ApiBearerAuth()
52
+ @ApiHeader({ name: WORKSPACE_HEADER, required: true, description: "The workspace this request administers. The caller must be an admin member of it." })
53
+ @UseGuards(AuthGuard, WorkspaceGuard, AbilityGuard)
54
+ export class AdminController {
55
+ constructor(
56
+ @Inject(AuthService) private readonly auth: AuthService,
57
+ @Inject(WorkspaceRepository) private readonly workspaces: WorkspaceRepository,
58
+ @Inject(CountryRepository) private readonly countries: CountryRepository,
59
+ @Inject(LanguageRepository) private readonly languages: LanguageRepository,
60
+ @Inject(CustomerRepository) private readonly customers: CustomerRepository,
61
+ ) {}
62
+
63
+ @Get("users")
64
+ @CheckAbility("users:read")
65
+ @ApiOperation({ summary: "[admin] List the members of this workspace" })
66
+ @ApiQuery({ name: "search", required: false, description: "Email substring match" })
67
+ @ApiQuery({ name: "page", required: false, description: "1-indexed. Defaults to 1." })
68
+ @ApiQuery({ name: "limit", required: false, description: "Defaults to 25, capped at 100." })
69
+ @ApiResponse({ status: 200, type: UserListResponseDto })
70
+ async listUsers(@Req() req: Request, @Query("search") search?: string, @Query("page") page?: string, @Query("limit") limit?: string) {
71
+ return this.auth.listUsers(req.authz!, { search, page: page ? Number(page) : undefined, limit: limit ? Number(limit) : undefined });
72
+ }
73
+
74
+ @Post("users")
75
+ @CheckAbility("users:manage")
76
+ @ApiOperation({
77
+ summary: "[admin] Create a user and add them to this workspace",
78
+ description: "No invitation email — the account is usable immediately with the password given here.",
79
+ })
80
+ @ApiBody({ type: CreateUserDto })
81
+ @ApiResponse({ status: 201, type: UserSummaryDto })
82
+ async createUser(@Body() body: Record<string, unknown>, @Req() req: Request) {
83
+ const passwordHash = await hashPassword(requireString(body.password, "password"));
84
+ const member = await this.workspaces.createMember(
85
+ req.authz!.workspaceId,
86
+ {
87
+ email: requireString(body.email, "email"),
88
+ passwordHash,
89
+ firstName: optionalString(body.firstName),
90
+ lastName: optionalString(body.lastName),
91
+ displayName: optionalString(body.displayName),
92
+ phone: optionalString(body.phone),
93
+ username: optionalString(body.username),
94
+ photo: optionalString(body.photo),
95
+ roles: Array.isArray(body.roles) ? body.roles.filter((role): role is string => typeof role === "string") : undefined,
96
+ },
97
+ req.auth!.sub,
98
+ );
99
+ return this.auth.getUser(req.authz!, member.userId);
100
+ }
101
+
102
+ @Get("users/:userId")
103
+ @CheckAbility("users:read")
104
+ @ApiOperation({ summary: "[admin] Fetch a single member's profile" })
105
+ @ApiParam({ name: "userId" })
106
+ @ApiResponse({ status: 200, type: UserSummaryDto })
107
+ async getUser(@Param("userId") userId: string, @Req() req: Request) {
108
+ return this.auth.getUser(req.authz!, userId);
109
+ }
110
+
111
+ @Patch("users/:userId")
112
+ @CheckAbility("users:manage")
113
+ @ApiOperation({ summary: "[admin] Edit a member's profile", description: "Profile fields only — email is the login identifier and is not editable here." })
114
+ @ApiParam({ name: "userId" })
115
+ @ApiBody({ type: UpdateUserDto })
116
+ @ApiResponse({ status: 200, type: UserSummaryDto })
117
+ async updateUser(@Param("userId") userId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
118
+ return this.auth.updateUser(
119
+ req.authz!,
120
+ userId,
121
+ {
122
+ firstName: body.firstName === null ? null : optionalString(body.firstName),
123
+ lastName: body.lastName === null ? null : optionalString(body.lastName),
124
+ displayName: body.displayName === null ? null : optionalString(body.displayName),
125
+ phone: body.phone === null ? null : optionalString(body.phone),
126
+ username: body.username === null ? null : optionalString(body.username),
127
+ photo: body.photo === null ? null : optionalString(body.photo),
128
+ },
129
+ req.auth!.sub,
130
+ );
131
+ }
132
+
133
+ @Delete("users/:userId")
134
+ @CheckAbility("users:manage")
135
+ @ApiOperation({
136
+ summary: "[admin] Delete a member's account",
137
+ description:
138
+ "Soft-delete: the row survives for audit purposes, stops appearing in listings, and can no longer authenticate. " +
139
+ "This disables the account across every workspace it belongs to, not just this one — the same reach `block` already has.",
140
+ })
141
+ @ApiParam({ name: "userId" })
142
+ @ApiBody({ type: DeleteReasonDto, required: false })
143
+ @ApiResponse({ status: 200, type: OkResponseDto })
144
+ async deleteUser(@Param("userId") userId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
145
+ if (userId === req.auth!.sub) throw new ForbiddenException("cannot delete your own account");
146
+ await this.auth.deleteUser(req.authz!, userId, req.auth!.sub, optionalString(body?.reason));
147
+ return { ok: true };
148
+ }
149
+
150
+ @Get("audit-log")
151
+ @CheckAbility("audit-log:read")
152
+ @ApiOperation({ summary: "[admin] List this workspace's audit log entries, newest first" })
153
+ @ApiQuery({ name: "userId", required: false })
154
+ @ApiQuery({ name: "action", required: false, description: "AuditEvent discriminant, e.g. 'role_assigned'" })
155
+ @ApiQuery({ name: "since", required: false, description: "ISO 8601 timestamp" })
156
+ @ApiQuery({ name: "until", required: false, description: "ISO 8601 timestamp" })
157
+ @ApiQuery({ name: "page", required: false, description: "1-indexed. Defaults to 1." })
158
+ @ApiQuery({ name: "limit", required: false, description: "Defaults to 25, capped at 100." })
159
+ @ApiResponse({ status: 200, type: AuditLogListResponseDto })
160
+ async listAuditLog(
161
+ @Req() req: Request,
162
+ @Query("userId") userId?: string,
163
+ @Query("action") action?: string,
164
+ @Query("since") since?: string,
165
+ @Query("until") until?: string,
166
+ @Query("page") page?: string,
167
+ @Query("limit") limit?: string,
168
+ ) {
169
+ return this.auth.listAuditLog(req.authz!, {
170
+ userId,
171
+ action,
172
+ since,
173
+ until,
174
+ page: page ? Number(page) : undefined,
175
+ limit: limit ? Number(limit) : undefined,
176
+ });
177
+ }
178
+
179
+ @Get("permissions")
180
+ @CheckAbility("permissions:read")
181
+ @ApiOperation({
182
+ summary: "[admin] List the permission catalog",
183
+ description:
184
+ "Grouped and ordered for a permission matrix. The catalog is global, like the Permission table: what is scoped to this workspace is which of its roles and memberships point at each row.",
185
+ })
186
+ @ApiQuery({ name: "activeOnly", required: false, type: Boolean, description: "Pass true for a picker/dropdown — false or omitted returns everything, active or not." })
187
+ @ApiResponse({ status: 200, type: PermissionListResponseDto })
188
+ async listPermissions(@Query("activeOnly") activeOnly?: string) {
189
+ return this.auth.listPermissions(activeOnly === "true");
190
+ }
191
+
192
+ @Post("permissions")
193
+ @CheckAbility("permissions:define")
194
+ @ApiOperation({
195
+ summary: "[admin] Define or edit a permission",
196
+ description:
197
+ "Upserted on `slug`, which is the stable identifier grants and revocations use — renaming the display name never breaks a grant. " +
198
+ "`isActive: false` takes the permission out of every ability that carries it, in one write, effective on the next request — in every workspace.",
199
+ })
200
+ @ApiBody({ type: DefinePermissionDto })
201
+ @ApiResponse({ status: 201, type: PermissionSummaryDto })
202
+ async definePermission(@Body() body: Record<string, unknown>, @Req() req: Request) {
203
+ return this.auth.definePermission(
204
+ {
205
+ slug: requireString(body.slug, "slug"),
206
+ name: optionalString(body.name),
207
+ displayName: optionalString(body.displayName),
208
+ description: body.description === null ? null : optionalString(body.description),
209
+ group: optionalString(body.group),
210
+ groupOrder: typeof body.groupOrder === "number" ? body.groupOrder : undefined,
211
+ order: typeof body.order === "number" ? body.order : undefined,
212
+ isActive: typeof body.isActive === "boolean" ? body.isActive : undefined,
213
+ },
214
+ req.auth!.sub,
215
+ );
216
+ }
217
+
218
+ @Get("roles")
219
+ @CheckAbility("roles:manage")
220
+ @ApiOperation({ summary: "[admin] List the roles this workspace defines" })
221
+ @ApiQuery({ name: "activeOnly", required: false, type: Boolean, description: "Pass true for a picker/dropdown — false or omitted returns everything, active or not." })
222
+ @ApiResponse({ status: 200, type: RoleListResponseDto })
223
+ async listRoles(@Req() req: Request, @Query("activeOnly") activeOnly?: string) {
224
+ return this.auth.listRoles(req.authz!, activeOnly === "true");
225
+ }
226
+
227
+ @Post("roles")
228
+ @CheckAbility("roles:manage")
229
+ @ApiOperation({ summary: "[admin] Create a role in this workspace" })
230
+ @ApiBody({ type: CreateRoleDto })
231
+ @ApiResponse({ status: 201, type: RoleSummaryDto })
232
+ async createRole(@Body() body: Record<string, unknown>, @Req() req: Request) {
233
+ return this.auth.createRole(
234
+ req.authz!,
235
+ {
236
+ slug: requireString(body.slug, "slug"),
237
+ name: optionalString(body.name),
238
+ displayName: optionalString(body.displayName),
239
+ description: optionalString(body.description) ?? null,
240
+ },
241
+ req.auth!.sub,
242
+ );
243
+ }
244
+
245
+ @Patch("roles/:roleId")
246
+ @CheckAbility("roles:manage")
247
+ @ApiOperation({ summary: "[admin] Edit one of this workspace's roles" })
248
+ @ApiParam({ name: "roleId" })
249
+ @ApiBody({ type: UpdateRoleDto })
250
+ @ApiResponse({ status: 200, type: RoleSummaryDto })
251
+ async updateRole(@Param("roleId") roleId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
252
+ return this.auth.updateRole(
253
+ req.authz!,
254
+ roleId,
255
+ {
256
+ name: optionalString(body.name),
257
+ displayName: optionalString(body.displayName),
258
+ description: body.description === null ? null : optionalString(body.description),
259
+ isActive: typeof body.isActive === "boolean" ? body.isActive : undefined,
260
+ },
261
+ req.auth!.sub,
262
+ );
263
+ }
264
+
265
+ @Delete("roles/:roleId")
266
+ @CheckAbility("roles:manage")
267
+ @ApiOperation({
268
+ summary: "[admin] Delete one of this workspace's roles",
269
+ description: "Soft-delete: existing assignments are left in place rather than cascade-deleted, and the role simply stops being resolved.",
270
+ })
271
+ @ApiParam({ name: "roleId" })
272
+ @ApiBody({ type: DeleteReasonDto, required: false })
273
+ @ApiResponse({ status: 200, type: OkResponseDto })
274
+ async deleteRole(@Param("roleId") roleId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
275
+ await this.auth.deleteRole(req.authz!, roleId, req.auth!.sub, optionalString(body?.reason));
276
+ return { ok: true };
277
+ }
278
+
279
+ @Post("roles/:roleId/permissions")
280
+ @CheckAbility("roles:manage")
281
+ @ApiOperation({ summary: "[admin] Attach a permission to one of this workspace's roles" })
282
+ @ApiParam({ name: "roleId" })
283
+ @ApiBody({ type: AttachPermissionDto })
284
+ @ApiResponse({ status: 201, type: OkResponseDto })
285
+ async attachPermissionToRole(@Param("roleId") roleId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
286
+ await this.auth.attachPermissionToRole(req.authz!, roleId, requireString(body.permission, "permission"), req.auth!.sub);
287
+ return { ok: true };
288
+ }
289
+
290
+ @Post("roles/:roleId/permissions/:permissionSlug/revoke")
291
+ @CheckAbility("roles:manage")
292
+ @ApiOperation({ summary: "[admin] Detach a permission from one of this workspace's roles" })
293
+ @ApiParam({ name: "roleId" })
294
+ @ApiParam({ name: "permissionSlug" })
295
+ @ApiResponse({ status: 201, type: OkResponseDto })
296
+ async detachPermissionFromRole(@Param("roleId") roleId: string, @Param("permissionSlug") permissionSlug: string, @Req() req: Request) {
297
+ await this.auth.detachPermissionFromRole(req.authz!, roleId, permissionSlug);
298
+ return { ok: true };
299
+ }
300
+
301
+ @Post("users/:userId/roles")
302
+ @CheckAbility("roles:assign")
303
+ @ApiOperation({ summary: "[admin] Assign a role to a member of this workspace" })
304
+ @ApiParam({ name: "userId" })
305
+ @ApiBody({ type: AssignRoleDto })
306
+ @ApiResponse({ status: 201, type: OkResponseDto })
307
+ async assignRole(@Param("userId") userId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
308
+ await this.auth.assignRole(req.authz!, userId, requireString(body.role, "role"));
309
+ return { ok: true };
310
+ }
311
+
312
+ @Post("users/:userId/roles/:roleSlug/revoke")
313
+ @CheckAbility("roles:assign")
314
+ @ApiOperation({ summary: "[admin] Revoke a role from a member of this workspace" })
315
+ @ApiParam({ name: "userId" })
316
+ @ApiParam({ name: "roleSlug" })
317
+ @ApiResponse({ status: 201, type: OkResponseDto })
318
+ async revokeRole(@Param("userId") userId: string, @Param("roleSlug") roleSlug: string, @Req() req: Request) {
319
+ // Revoking your own admin role would strip the very permission that authorized the call,
320
+ // with no way back in. Assigning to yourself is fine; it can't lock anyone out.
321
+ if (userId === req.auth!.sub) throw new ForbiddenException("cannot change your own roles");
322
+ await this.auth.revokeRole(req.authz!, userId, roleSlug);
323
+ return { ok: true };
324
+ }
325
+
326
+ @Post("users/:userId/permissions")
327
+ @CheckAbility("permissions:grant")
328
+ @ApiOperation({ summary: "[admin] Grant a permission directly to a member, bypassing roles", description: "The grant is scoped to this workspace." })
329
+ @ApiParam({ name: "userId" })
330
+ @ApiBody({ type: GrantPermissionDto })
331
+ @ApiResponse({ status: 201, type: OkResponseDto })
332
+ async grantPermission(@Param("userId") userId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
333
+ await this.auth.grantPermission(req.authz!, userId, requireString(body.permission, "permission"), req.auth!.sub);
334
+ return { ok: true };
335
+ }
336
+
337
+ @Post("users/:userId/permissions/:permissionSlug/revoke")
338
+ @CheckAbility("permissions:grant")
339
+ @ApiOperation({ summary: "[admin] Revoke a direct permission grant from a member" })
340
+ @ApiParam({ name: "userId" })
341
+ @ApiParam({ name: "permissionSlug" })
342
+ @ApiResponse({ status: 201, type: OkResponseDto })
343
+ async revokePermission(@Param("userId") userId: string, @Param("permissionSlug") permissionSlug: string, @Req() req: Request) {
344
+ await this.auth.revokePermission(req.authz!, userId, permissionSlug);
345
+ return { ok: true };
346
+ }
347
+
348
+ @Post("users/:userId/block")
349
+ @CheckAbility("users:block")
350
+ @ApiOperation({ summary: "[admin] Block a member, revoking all their sessions immediately",
351
+ description: "Blocking disables the whole account, so it is only allowed against a member of the workspace you administer." })
352
+ @ApiParam({ name: "userId" })
353
+ @ApiResponse({ status: 201, type: OkResponseDto })
354
+ async block(@Param("userId") userId: string, @Req() req: Request, @Ip() ip: string) {
355
+ if (userId === req.auth!.sub) throw new ForbiddenException("cannot block your own account");
356
+ await this.auth.block(req.authz!, userId, { userId: req.auth!.sub, ip });
357
+ return { ok: true };
358
+ }
359
+
360
+ @Post("users/:userId/unblock")
361
+ @CheckAbility("users:block")
362
+ @ApiOperation({ summary: "[admin] Unblock a member" })
363
+ @ApiParam({ name: "userId" })
364
+ @ApiResponse({ status: 201, type: OkResponseDto })
365
+ async unblock(@Param("userId") userId: string, @Req() req: Request, @Ip() ip: string) {
366
+ await this.auth.unblock(req.authz!, userId, { userId: req.auth!.sub, ip });
367
+ return { ok: true };
368
+ }
369
+
370
+ @Post("users/:userId/deactivate")
371
+ @CheckAbility("users:block")
372
+ @ApiOperation({
373
+ summary: "[admin] Deactivate a member, revoking all their sessions immediately",
374
+ description: "Distinct from block/unblock — a routine administrative toggle, not a security action. Both independently deny login.",
375
+ })
376
+ @ApiParam({ name: "userId" })
377
+ @ApiResponse({ status: 201, type: OkResponseDto })
378
+ async deactivate(@Param("userId") userId: string, @Req() req: Request, @Ip() ip: string) {
379
+ if (userId === req.auth!.sub) throw new ForbiddenException("cannot deactivate your own account");
380
+ await this.auth.deactivate(req.authz!, userId, { userId: req.auth!.sub, ip });
381
+ return { ok: true };
382
+ }
383
+
384
+ @Post("users/:userId/activate")
385
+ @CheckAbility("users:block")
386
+ @ApiOperation({ summary: "[admin] Reactivate a member" })
387
+ @ApiParam({ name: "userId" })
388
+ @ApiResponse({ status: 201, type: OkResponseDto })
389
+ async activate(@Param("userId") userId: string, @Req() req: Request, @Ip() ip: string) {
390
+ await this.auth.activate(req.authz!, userId, { userId: req.auth!.sub, ip });
391
+ return { ok: true };
392
+ }
393
+
394
+ // ---- countries ----
395
+
396
+ @Get("countries")
397
+ @CheckAbility("countries:read")
398
+ @ApiOperation({ summary: "[admin] List this workspace's countries" })
399
+ @ApiQuery({ name: "search", required: false, description: "Matches name/code/isoCode" })
400
+ @ApiQuery({ name: "page", required: false, description: "1-indexed. Defaults to 1." })
401
+ @ApiQuery({ name: "limit", required: false, description: "Defaults to 25, capped at 100." })
402
+ @ApiQuery({ name: "activeOnly", required: false, type: Boolean, description: "Pass true for a picker/dropdown — false or omitted returns everything, active or not." })
403
+ @ApiResponse({ status: 200, type: CountryListResponseDto })
404
+ async listCountries(
405
+ @Req() req: Request,
406
+ @Query("search") search?: string,
407
+ @Query("page") page?: string,
408
+ @Query("limit") limit?: string,
409
+ @Query("activeOnly") activeOnly?: string,
410
+ ) {
411
+ return this.countries.list(req.authz!.workspaceId, {
412
+ search,
413
+ page: page ? Number(page) : undefined,
414
+ limit: limit ? Number(limit) : undefined,
415
+ activeOnly: activeOnly === "true",
416
+ });
417
+ }
418
+
419
+ @Post("countries")
420
+ @CheckAbility("countries:manage")
421
+ @ApiOperation({ summary: "[admin] Create a country in this workspace" })
422
+ @ApiBody({ type: CreateCountryDto })
423
+ @ApiResponse({ status: 201, type: CountrySummaryDto })
424
+ async createCountry(@Body() body: Record<string, unknown>, @Req() req: Request) {
425
+ return this.countries.create(
426
+ req.authz!.workspaceId,
427
+ {
428
+ code: requireString(body.code, "code"),
429
+ name: requireString(body.name, "name"),
430
+ emoji: requireString(body.emoji, "emoji"),
431
+ phoneCode: requireString(body.phoneCode, "phoneCode"),
432
+ currency: requireString(body.currency, "currency"),
433
+ currencyName: requireString(body.currencyName, "currencyName"),
434
+ isoCode: requireString(body.isoCode, "isoCode"),
435
+ flag: optionalString(body.flag),
436
+ isActive: optionalBoolean(body.isActive),
437
+ },
438
+ req.auth!.sub,
439
+ );
440
+ }
441
+
442
+ @Get("countries/:countryId")
443
+ @CheckAbility("countries:read")
444
+ @ApiOperation({ summary: "[admin] Fetch a single country from this workspace" })
445
+ @ApiParam({ name: "countryId" })
446
+ @ApiResponse({ status: 200, type: CountrySummaryDto })
447
+ async getCountry(@Param("countryId") countryId: string, @Req() req: Request) {
448
+ return this.countries.get(req.authz!.workspaceId, countryId);
449
+ }
450
+
451
+ @Patch("countries/:countryId")
452
+ @CheckAbility("countries:manage")
453
+ @ApiOperation({ summary: "[admin] Edit a country in this workspace" })
454
+ @ApiParam({ name: "countryId" })
455
+ @ApiBody({ type: UpdateCountryDto })
456
+ @ApiResponse({ status: 200, type: CountrySummaryDto })
457
+ async updateCountry(@Param("countryId") countryId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
458
+ return this.countries.update(
459
+ req.authz!.workspaceId,
460
+ countryId,
461
+ {
462
+ code: optionalString(body.code),
463
+ name: optionalString(body.name),
464
+ emoji: optionalString(body.emoji),
465
+ phoneCode: optionalString(body.phoneCode),
466
+ currency: optionalString(body.currency),
467
+ currencyName: optionalString(body.currencyName),
468
+ isoCode: optionalString(body.isoCode),
469
+ flag: body.flag === null ? null : optionalString(body.flag),
470
+ isActive: optionalBoolean(body.isActive),
471
+ },
472
+ req.auth!.sub,
473
+ );
474
+ }
475
+
476
+ @Delete("countries/:countryId")
477
+ @CheckAbility("countries:manage")
478
+ @ApiOperation({ summary: "[admin] Delete a country from this workspace", description: "Soft-delete: the row survives for audit purposes and stops appearing in listings." })
479
+ @ApiParam({ name: "countryId" })
480
+ @ApiBody({ type: DeleteReasonDto, required: false })
481
+ @ApiResponse({ status: 200, type: OkResponseDto })
482
+ async deleteCountry(@Param("countryId") countryId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
483
+ await this.countries.delete(req.authz!.workspaceId, countryId, req.auth!.sub, optionalString(body?.reason));
484
+ return { ok: true };
485
+ }
486
+
487
+ @Post("countries/:countryId/activate")
488
+ @CheckAbility("countries:status")
489
+ @ApiOperation({ summary: "[admin] Reactivate a country" })
490
+ @ApiParam({ name: "countryId" })
491
+ @ApiResponse({ status: 201, type: OkResponseDto })
492
+ async activateCountry(@Param("countryId") countryId: string, @Req() req: Request) {
493
+ await this.countries.setActive(req.authz!.workspaceId, countryId, true, req.auth!.sub);
494
+ return { ok: true };
495
+ }
496
+
497
+ @Post("countries/:countryId/deactivate")
498
+ @CheckAbility("countries:status")
499
+ @ApiOperation({ summary: "[admin] Deactivate a country" })
500
+ @ApiParam({ name: "countryId" })
501
+ @ApiResponse({ status: 201, type: OkResponseDto })
502
+ async deactivateCountry(@Param("countryId") countryId: string, @Req() req: Request) {
503
+ await this.countries.setActive(req.authz!.workspaceId, countryId, false, req.auth!.sub);
504
+ return { ok: true };
505
+ }
506
+
507
+ // ---- languages ----
508
+
509
+ @Get("languages")
510
+ @CheckAbility("languages:read")
511
+ @ApiOperation({ summary: "[admin] List this workspace's languages" })
512
+ @ApiQuery({ name: "search", required: false, description: "Matches name/code/nativeName" })
513
+ @ApiQuery({ name: "page", required: false, description: "1-indexed. Defaults to 1." })
514
+ @ApiQuery({ name: "limit", required: false, description: "Defaults to 25, capped at 100." })
515
+ @ApiQuery({ name: "activeOnly", required: false, type: Boolean, description: "Pass true for a picker/dropdown — false or omitted returns everything, active or not." })
516
+ @ApiResponse({ status: 200, type: LanguageListResponseDto })
517
+ async listLanguages(
518
+ @Req() req: Request,
519
+ @Query("search") search?: string,
520
+ @Query("page") page?: string,
521
+ @Query("limit") limit?: string,
522
+ @Query("activeOnly") activeOnly?: string,
523
+ ) {
524
+ return this.languages.list(req.authz!.workspaceId, {
525
+ search,
526
+ page: page ? Number(page) : undefined,
527
+ limit: limit ? Number(limit) : undefined,
528
+ activeOnly: activeOnly === "true",
529
+ });
530
+ }
531
+
532
+ @Post("languages")
533
+ @CheckAbility("languages:manage")
534
+ @ApiOperation({ summary: "[admin] Create a language in this workspace" })
535
+ @ApiBody({ type: CreateLanguageDto })
536
+ @ApiResponse({ status: 201, type: LanguageSummaryDto })
537
+ async createLanguage(@Body() body: Record<string, unknown>, @Req() req: Request) {
538
+ return this.languages.create(
539
+ req.authz!.workspaceId,
540
+ {
541
+ code: requireString(body.code, "code"),
542
+ name: requireString(body.name, "name"),
543
+ nativeName: requireString(body.nativeName, "nativeName"),
544
+ direction: optionalString(body.direction),
545
+ isDefault: optionalBoolean(body.isDefault),
546
+ isActive: optionalBoolean(body.isActive),
547
+ },
548
+ req.auth!.sub,
549
+ );
550
+ }
551
+
552
+ @Get("languages/:languageId")
553
+ @CheckAbility("languages:read")
554
+ @ApiOperation({ summary: "[admin] Fetch a single language from this workspace" })
555
+ @ApiParam({ name: "languageId" })
556
+ @ApiResponse({ status: 200, type: LanguageSummaryDto })
557
+ async getLanguage(@Param("languageId") languageId: string, @Req() req: Request) {
558
+ return this.languages.get(req.authz!.workspaceId, languageId);
559
+ }
560
+
561
+ @Patch("languages/:languageId")
562
+ @CheckAbility("languages:manage")
563
+ @ApiOperation({ summary: "[admin] Edit a language in this workspace" })
564
+ @ApiParam({ name: "languageId" })
565
+ @ApiBody({ type: UpdateLanguageDto })
566
+ @ApiResponse({ status: 200, type: LanguageSummaryDto })
567
+ async updateLanguage(@Param("languageId") languageId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
568
+ return this.languages.update(
569
+ req.authz!.workspaceId,
570
+ languageId,
571
+ {
572
+ code: optionalString(body.code),
573
+ name: optionalString(body.name),
574
+ nativeName: optionalString(body.nativeName),
575
+ direction: optionalString(body.direction),
576
+ isDefault: optionalBoolean(body.isDefault),
577
+ isActive: optionalBoolean(body.isActive),
578
+ },
579
+ req.auth!.sub,
580
+ );
581
+ }
582
+
583
+ @Delete("languages/:languageId")
584
+ @CheckAbility("languages:manage")
585
+ @ApiOperation({ summary: "[admin] Delete a language from this workspace", description: "Soft-delete: the row survives for audit purposes and stops appearing in listings." })
586
+ @ApiParam({ name: "languageId" })
587
+ @ApiBody({ type: DeleteReasonDto, required: false })
588
+ @ApiResponse({ status: 200, type: OkResponseDto })
589
+ async deleteLanguage(@Param("languageId") languageId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
590
+ await this.languages.delete(req.authz!.workspaceId, languageId, req.auth!.sub, optionalString(body?.reason));
591
+ return { ok: true };
592
+ }
593
+
594
+ @Post("languages/:languageId/activate")
595
+ @CheckAbility("languages:status")
596
+ @ApiOperation({ summary: "[admin] Reactivate a language" })
597
+ @ApiParam({ name: "languageId" })
598
+ @ApiResponse({ status: 201, type: OkResponseDto })
599
+ async activateLanguage(@Param("languageId") languageId: string, @Req() req: Request) {
600
+ await this.languages.setActive(req.authz!.workspaceId, languageId, true, req.auth!.sub);
601
+ return { ok: true };
602
+ }
603
+
604
+ @Post("languages/:languageId/deactivate")
605
+ @CheckAbility("languages:status")
606
+ @ApiOperation({ summary: "[admin] Deactivate a language" })
607
+ @ApiParam({ name: "languageId" })
608
+ @ApiResponse({ status: 201, type: OkResponseDto })
609
+ async deactivateLanguage(@Param("languageId") languageId: string, @Req() req: Request) {
610
+ await this.languages.setActive(req.authz!.workspaceId, languageId, false, req.auth!.sub);
611
+ return { ok: true };
612
+ }
613
+
614
+ // ---- customers ----
615
+ // End-users managed by admins — no login capability, not related to the RBAC User model above.
616
+
617
+ @Get("customers")
618
+ @CheckAbility("customers:read")
619
+ @ApiOperation({ summary: "[admin] List this workspace's customers" })
620
+ @ApiQuery({ name: "search", required: false, description: "Matches name/email/username/phone" })
621
+ @ApiQuery({ name: "page", required: false, description: "1-indexed. Defaults to 1." })
622
+ @ApiQuery({ name: "limit", required: false, description: "Defaults to 25, capped at 100." })
623
+ @ApiQuery({ name: "activeOnly", required: false, type: Boolean, description: "Pass true for a picker/dropdown — false or omitted returns everything, active or not." })
624
+ @ApiResponse({ status: 200, type: CustomerListResponseDto })
625
+ async listCustomers(
626
+ @Req() req: Request,
627
+ @Query("search") search?: string,
628
+ @Query("page") page?: string,
629
+ @Query("limit") limit?: string,
630
+ @Query("activeOnly") activeOnly?: string,
631
+ ) {
632
+ return this.customers.list(req.authz!.workspaceId, {
633
+ search,
634
+ page: page ? Number(page) : undefined,
635
+ limit: limit ? Number(limit) : undefined,
636
+ activeOnly: activeOnly === "true",
637
+ });
638
+ }
639
+
640
+ @Post("customers")
641
+ @CheckAbility("customers:manage")
642
+ @ApiOperation({ summary: "[admin] Create a customer in this workspace" })
643
+ @ApiBody({ type: CreateCustomerDto })
644
+ @ApiResponse({ status: 201, type: CustomerSummaryDto })
645
+ async createCustomer(@Body() body: Record<string, unknown>, @Req() req: Request) {
646
+ return this.customers.create(
647
+ req.authz!.workspaceId,
648
+ {
649
+ email: requireString(body.email, "email"),
650
+ firstName: optionalString(body.firstName),
651
+ lastName: optionalString(body.lastName),
652
+ username: optionalString(body.username),
653
+ phone: optionalString(body.phone),
654
+ dob: optionalString(body.dob),
655
+ gender: optionalString(body.gender),
656
+ joinedDate: optionalString(body.joinedDate),
657
+ photo: optionalString(body.photo),
658
+ isEmailVerified: optionalBoolean(body.isEmailVerified),
659
+ isPhoneVerified: optionalBoolean(body.isPhoneVerified),
660
+ isActive: optionalBoolean(body.isActive),
661
+ },
662
+ req.auth!.sub,
663
+ );
664
+ }
665
+
666
+ @Get("customers/:customerId")
667
+ @CheckAbility("customers:read")
668
+ @ApiOperation({ summary: "[admin] Fetch a single customer from this workspace" })
669
+ @ApiParam({ name: "customerId" })
670
+ @ApiResponse({ status: 200, type: CustomerSummaryDto })
671
+ async getCustomer(@Param("customerId") customerId: string, @Req() req: Request) {
672
+ return this.customers.get(req.authz!.workspaceId, customerId);
673
+ }
674
+
675
+ @Patch("customers/:customerId")
676
+ @CheckAbility("customers:manage")
677
+ @ApiOperation({ summary: "[admin] Edit a customer in this workspace" })
678
+ @ApiParam({ name: "customerId" })
679
+ @ApiBody({ type: UpdateCustomerDto })
680
+ @ApiResponse({ status: 200, type: CustomerSummaryDto })
681
+ async updateCustomer(@Param("customerId") customerId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
682
+ return this.customers.update(
683
+ req.authz!.workspaceId,
684
+ customerId,
685
+ {
686
+ email: optionalString(body.email),
687
+ firstName: body.firstName === null ? null : optionalString(body.firstName),
688
+ lastName: body.lastName === null ? null : optionalString(body.lastName),
689
+ username: body.username === null ? null : optionalString(body.username),
690
+ phone: body.phone === null ? null : optionalString(body.phone),
691
+ dob: body.dob === null ? null : optionalString(body.dob),
692
+ gender: body.gender === null ? null : optionalString(body.gender),
693
+ joinedDate: optionalString(body.joinedDate),
694
+ photo: body.photo === null ? null : optionalString(body.photo),
695
+ isEmailVerified: optionalBoolean(body.isEmailVerified),
696
+ isPhoneVerified: optionalBoolean(body.isPhoneVerified),
697
+ isActive: optionalBoolean(body.isActive),
698
+ },
699
+ req.auth!.sub,
700
+ );
701
+ }
702
+
703
+ @Delete("customers/:customerId")
704
+ @CheckAbility("customers:manage")
705
+ @ApiOperation({ summary: "[admin] Delete a customer from this workspace", description: "Soft-delete: the row survives for audit purposes and stops appearing in listings." })
706
+ @ApiParam({ name: "customerId" })
707
+ @ApiBody({ type: DeleteReasonDto, required: false })
708
+ @ApiResponse({ status: 200, type: OkResponseDto })
709
+ async deleteCustomer(@Param("customerId") customerId: string, @Body() body: Record<string, unknown>, @Req() req: Request) {
710
+ await this.customers.delete(req.authz!.workspaceId, customerId, req.auth!.sub, optionalString(body?.reason));
711
+ return { ok: true };
712
+ }
713
+
714
+ @Post("customers/:customerId/activate")
715
+ @CheckAbility("customers:status")
716
+ @ApiOperation({ summary: "[admin] Reactivate a customer" })
717
+ @ApiParam({ name: "customerId" })
718
+ @ApiResponse({ status: 201, type: OkResponseDto })
719
+ async activateCustomer(@Param("customerId") customerId: string, @Req() req: Request) {
720
+ await this.customers.setActive(req.authz!.workspaceId, customerId, true, req.auth!.sub);
721
+ return { ok: true };
722
+ }
723
+
724
+ @Post("customers/:customerId/deactivate")
725
+ @CheckAbility("customers:status")
726
+ @ApiOperation({ summary: "[admin] Deactivate a customer" })
727
+ @ApiParam({ name: "customerId" })
728
+ @ApiResponse({ status: 201, type: OkResponseDto })
729
+ async deactivateCustomer(@Param("customerId") customerId: string, @Req() req: Request) {
730
+ await this.customers.setActive(req.authz!.workspaceId, customerId, false, req.auth!.sub);
731
+ return { ok: true };
732
+ }
733
+ }