@rovela-ai/sdk 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/dist/admin/api/accept-invite.d.ts +65 -0
  2. package/dist/admin/api/accept-invite.d.ts.map +1 -0
  3. package/dist/admin/api/accept-invite.js +115 -0
  4. package/dist/admin/api/accept-invite.js.map +1 -0
  5. package/dist/admin/api/categories.d.ts.map +1 -1
  6. package/dist/admin/api/categories.js +21 -28
  7. package/dist/admin/api/categories.js.map +1 -1
  8. package/dist/admin/api/customers.d.ts.map +1 -1
  9. package/dist/admin/api/customers.js +17 -25
  10. package/dist/admin/api/customers.js.map +1 -1
  11. package/dist/admin/api/forgot-password.d.ts +39 -0
  12. package/dist/admin/api/forgot-password.d.ts.map +1 -0
  13. package/dist/admin/api/forgot-password.js +66 -0
  14. package/dist/admin/api/forgot-password.js.map +1 -0
  15. package/dist/admin/api/index.d.ts +6 -0
  16. package/dist/admin/api/index.d.ts.map +1 -1
  17. package/dist/admin/api/index.js +9 -0
  18. package/dist/admin/api/index.js.map +1 -1
  19. package/dist/admin/api/me.d.ts +72 -0
  20. package/dist/admin/api/me.d.ts.map +1 -0
  21. package/dist/admin/api/me.js +177 -0
  22. package/dist/admin/api/me.js.map +1 -0
  23. package/dist/admin/api/orders.d.ts.map +1 -1
  24. package/dist/admin/api/orders.js +21 -28
  25. package/dist/admin/api/orders.js.map +1 -1
  26. package/dist/admin/api/products.d.ts.map +1 -1
  27. package/dist/admin/api/products.js +33 -37
  28. package/dist/admin/api/products.js.map +1 -1
  29. package/dist/admin/api/refund.d.ts.map +1 -1
  30. package/dist/admin/api/refund.js +5 -7
  31. package/dist/admin/api/refund.js.map +1 -1
  32. package/dist/admin/api/reset-password.d.ts +49 -0
  33. package/dist/admin/api/reset-password.d.ts.map +1 -0
  34. package/dist/admin/api/reset-password.js +99 -0
  35. package/dist/admin/api/reset-password.js.map +1 -0
  36. package/dist/admin/api/return.d.ts.map +1 -1
  37. package/dist/admin/api/return.js +9 -12
  38. package/dist/admin/api/return.js.map +1 -1
  39. package/dist/admin/api/settings.d.ts.map +1 -1
  40. package/dist/admin/api/settings.js +9 -12
  41. package/dist/admin/api/settings.js.map +1 -1
  42. package/dist/admin/api/shipping.d.ts.map +1 -1
  43. package/dist/admin/api/shipping.js +65 -61
  44. package/dist/admin/api/shipping.js.map +1 -1
  45. package/dist/admin/api/stats.d.ts.map +1 -1
  46. package/dist/admin/api/stats.js +5 -7
  47. package/dist/admin/api/stats.js.map +1 -1
  48. package/dist/admin/api/stripe-status.d.ts.map +1 -1
  49. package/dist/admin/api/stripe-status.js +5 -7
  50. package/dist/admin/api/stripe-status.js.map +1 -1
  51. package/dist/admin/api/tax-zones.d.ts.map +1 -1
  52. package/dist/admin/api/tax-zones.js +21 -28
  53. package/dist/admin/api/tax-zones.js.map +1 -1
  54. package/dist/admin/api/users.d.ts +142 -0
  55. package/dist/admin/api/users.d.ts.map +1 -0
  56. package/dist/admin/api/users.js +356 -0
  57. package/dist/admin/api/users.js.map +1 -0
  58. package/dist/admin/components/AdminAcceptInviteForm.d.ts +3 -0
  59. package/dist/admin/components/AdminAcceptInviteForm.d.ts.map +1 -0
  60. package/dist/admin/components/AdminAcceptInviteForm.js +137 -0
  61. package/dist/admin/components/AdminAcceptInviteForm.js.map +1 -0
  62. package/dist/admin/components/AdminAccountPage.d.ts +10 -0
  63. package/dist/admin/components/AdminAccountPage.d.ts.map +1 -0
  64. package/dist/admin/components/AdminAccountPage.js +123 -0
  65. package/dist/admin/components/AdminAccountPage.js.map +1 -0
  66. package/dist/admin/components/AdminForgotPasswordForm.d.ts +8 -0
  67. package/dist/admin/components/AdminForgotPasswordForm.d.ts.map +1 -0
  68. package/dist/admin/components/AdminForgotPasswordForm.js +59 -0
  69. package/dist/admin/components/AdminForgotPasswordForm.js.map +1 -0
  70. package/dist/admin/components/AdminNav.d.ts.map +1 -1
  71. package/dist/admin/components/AdminNav.js +32 -4
  72. package/dist/admin/components/AdminNav.js.map +1 -1
  73. package/dist/admin/components/AdminResetPasswordForm.d.ts +12 -0
  74. package/dist/admin/components/AdminResetPasswordForm.d.ts.map +1 -0
  75. package/dist/admin/components/AdminResetPasswordForm.js +134 -0
  76. package/dist/admin/components/AdminResetPasswordForm.js.map +1 -0
  77. package/dist/admin/components/AdminUserMenu.d.ts.map +1 -1
  78. package/dist/admin/components/AdminUserMenu.js +2 -2
  79. package/dist/admin/components/AdminUserMenu.js.map +1 -1
  80. package/dist/admin/components/InviteUserDialog.d.ts +3 -0
  81. package/dist/admin/components/InviteUserDialog.d.ts.map +1 -0
  82. package/dist/admin/components/InviteUserDialog.js +127 -0
  83. package/dist/admin/components/InviteUserDialog.js.map +1 -0
  84. package/dist/admin/components/UsersTable.d.ts +3 -0
  85. package/dist/admin/components/UsersTable.d.ts.map +1 -0
  86. package/dist/admin/components/UsersTable.js +399 -0
  87. package/dist/admin/components/UsersTable.js.map +1 -0
  88. package/dist/admin/components/index.d.ts +9 -0
  89. package/dist/admin/components/index.d.ts.map +1 -1
  90. package/dist/admin/components/index.js +9 -0
  91. package/dist/admin/components/index.js.map +1 -1
  92. package/dist/admin/config.d.ts +15 -10
  93. package/dist/admin/config.d.ts.map +1 -1
  94. package/dist/admin/config.js +38 -11
  95. package/dist/admin/config.js.map +1 -1
  96. package/dist/admin/hooks/index.d.ts +4 -0
  97. package/dist/admin/hooks/index.d.ts.map +1 -1
  98. package/dist/admin/hooks/index.js +3 -0
  99. package/dist/admin/hooks/index.js.map +1 -1
  100. package/dist/admin/hooks/useAdminMe.d.ts +31 -0
  101. package/dist/admin/hooks/useAdminMe.d.ts.map +1 -0
  102. package/dist/admin/hooks/useAdminMe.js +103 -0
  103. package/dist/admin/hooks/useAdminMe.js.map +1 -0
  104. package/dist/admin/hooks/useAdminPermissions.d.ts +3 -0
  105. package/dist/admin/hooks/useAdminPermissions.d.ts.map +1 -0
  106. package/dist/admin/hooks/useAdminPermissions.js +51 -0
  107. package/dist/admin/hooks/useAdminPermissions.js.map +1 -0
  108. package/dist/admin/hooks/useAdminUsers.d.ts +3 -0
  109. package/dist/admin/hooks/useAdminUsers.d.ts.map +1 -0
  110. package/dist/admin/hooks/useAdminUsers.js +240 -0
  111. package/dist/admin/hooks/useAdminUsers.js.map +1 -0
  112. package/dist/admin/index.d.ts +4 -4
  113. package/dist/admin/index.d.ts.map +1 -1
  114. package/dist/admin/index.js +20 -2
  115. package/dist/admin/index.js.map +1 -1
  116. package/dist/admin/permissions.d.ts +92 -0
  117. package/dist/admin/permissions.d.ts.map +1 -0
  118. package/dist/admin/permissions.js +201 -0
  119. package/dist/admin/permissions.js.map +1 -0
  120. package/dist/admin/server/admin-invite.d.ts +122 -0
  121. package/dist/admin/server/admin-invite.d.ts.map +1 -0
  122. package/dist/admin/server/admin-invite.js +235 -0
  123. package/dist/admin/server/admin-invite.js.map +1 -0
  124. package/dist/admin/server/admin-password-reset.d.ts +87 -0
  125. package/dist/admin/server/admin-password-reset.d.ts.map +1 -0
  126. package/dist/admin/server/admin-password-reset.js +220 -0
  127. package/dist/admin/server/admin-password-reset.js.map +1 -0
  128. package/dist/admin/server/admin-self-service.d.ts +86 -0
  129. package/dist/admin/server/admin-self-service.d.ts.map +1 -0
  130. package/dist/admin/server/admin-self-service.js +188 -0
  131. package/dist/admin/server/admin-self-service.js.map +1 -0
  132. package/dist/admin/server/admin-service.d.ts.map +1 -1
  133. package/dist/admin/server/admin-service.js +21 -2
  134. package/dist/admin/server/admin-service.js.map +1 -1
  135. package/dist/admin/server/admin-session.d.ts +137 -0
  136. package/dist/admin/server/admin-session.d.ts.map +1 -0
  137. package/dist/admin/server/admin-session.js +229 -0
  138. package/dist/admin/server/admin-session.js.map +1 -0
  139. package/dist/admin/server/index.d.ts +7 -0
  140. package/dist/admin/server/index.d.ts.map +1 -1
  141. package/dist/admin/server/index.js +20 -0
  142. package/dist/admin/server/index.js.map +1 -1
  143. package/dist/admin/server/user-management.d.ts +223 -0
  144. package/dist/admin/server/user-management.d.ts.map +1 -0
  145. package/dist/admin/server/user-management.js +846 -0
  146. package/dist/admin/server/user-management.js.map +1 -0
  147. package/dist/admin/types.d.ts +153 -2
  148. package/dist/admin/types.d.ts.map +1 -1
  149. package/dist/auth/config.d.ts.map +1 -1
  150. package/dist/auth/config.js +11 -2
  151. package/dist/auth/config.js.map +1 -1
  152. package/dist/core/db/queries.d.ts +19 -13
  153. package/dist/core/db/queries.d.ts.map +1 -1
  154. package/dist/core/db/schema.d.ts +327 -9
  155. package/dist/core/db/schema.d.ts.map +1 -1
  156. package/dist/core/db/schema.js +80 -3
  157. package/dist/core/db/schema.js.map +1 -1
  158. package/dist/core/types.d.ts +19 -3
  159. package/dist/core/types.d.ts.map +1 -1
  160. package/dist/emails/index.d.ts +2 -2
  161. package/dist/emails/index.d.ts.map +1 -1
  162. package/dist/emails/index.js +3 -1
  163. package/dist/emails/index.js.map +1 -1
  164. package/dist/emails/send/admin-auth.d.ts +94 -0
  165. package/dist/emails/send/admin-auth.d.ts.map +1 -0
  166. package/dist/emails/send/admin-auth.js +118 -0
  167. package/dist/emails/send/admin-auth.js.map +1 -0
  168. package/dist/emails/send/index.d.ts +2 -0
  169. package/dist/emails/send/index.d.ts.map +1 -1
  170. package/dist/emails/send/index.js +4 -0
  171. package/dist/emails/send/index.js.map +1 -1
  172. package/dist/emails/templates/admin-invite.d.ts +40 -0
  173. package/dist/emails/templates/admin-invite.d.ts.map +1 -0
  174. package/dist/emails/templates/admin-invite.js +62 -0
  175. package/dist/emails/templates/admin-invite.js.map +1 -0
  176. package/dist/emails/templates/index.d.ts +1 -0
  177. package/dist/emails/templates/index.d.ts.map +1 -1
  178. package/dist/emails/templates/index.js +4 -0
  179. package/dist/emails/templates/index.js.map +1 -1
  180. package/dist/emails/types.d.ts +22 -1
  181. package/dist/emails/types.d.ts.map +1 -1
  182. package/package.json +21 -1
@@ -5,4 +5,11 @@
5
5
  * Re-exports from admin-service for cleaner imports.
6
6
  */
7
7
  export { authenticateAdmin, createAdmin, findAdminForSession, findAdminByEmail, findAdminById, updateAdmin, updateAdminPassword, adminEmailExists, countAdmins, type CreateAdminResult, type AuthenticateAdminResult, type AuthenticateAdminError, } from './admin-service';
8
+ export { requestAdminPasswordReset, validateAdminResetToken, resetAdminPassword, deleteAdminPasswordResetTokens, cleanupExpiredAdminResetTokens, } from './admin-password-reset';
9
+ export { listAdmins, countActiveOwners, deactivateAdmin, reactivateAdmin, hardDeleteAdmin, statusCodeFor, inviteAdmin, resendAdminInvite, cancelAdminInvite, changeAdminRole, } from './user-management';
10
+ export type { Actor, AdminListOptions, UserManagementError, UserManagementResult, InviteAdminRequest, InviteAdminSuccess, InviteAdminResult, ResendInviteSuccess, ResendInviteResult, } from './user-management';
11
+ export { validateInviteToken, acceptAdminInvite, deleteAdminInviteTokens, cleanupExpiredInviteTokens, createInviteToken, INVITE_EXPIRY_HOURS, } from './admin-invite';
12
+ export type { AdminInviteSnapshot, ValidateInviteResult, AcceptInviteResult, } from './admin-invite';
13
+ export { changeOwnPassword, updateOwnProfile, } from './admin-self-service';
14
+ export type { SelfServiceError, ChangeOwnPasswordResult, UpdateOwnProfileResult, } from './admin-self-service';
8
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/admin/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAEL,iBAAiB,EAEjB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EAEX,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/admin/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAEL,iBAAiB,EAEjB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EAEX,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,iBAAiB,CAAA;AAMxB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAA;AAM/B,OAAO,EAEL,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,aAAa,EAEb,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAE1B,YAAY,EACV,KAAK,EACL,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EAEpB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAM1B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAMvB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,sBAAsB,CAAA"}
@@ -12,4 +12,24 @@ export {
12
12
  authenticateAdmin,
13
13
  // CRUD
14
14
  createAdmin, findAdminForSession, findAdminByEmail, findAdminById, updateAdmin, updateAdminPassword, adminEmailExists, countAdmins, } from './admin-service';
15
+ // =============================================================================
16
+ // Admin Password Reset Service
17
+ // =============================================================================
18
+ export { requestAdminPasswordReset, validateAdminResetToken, resetAdminPassword, deleteAdminPasswordResetTokens, cleanupExpiredAdminResetTokens, } from './admin-password-reset';
19
+ // =============================================================================
20
+ // User Management (Phase 2 + Phase 3)
21
+ // =============================================================================
22
+ export {
23
+ // Phase 2
24
+ listAdmins, countActiveOwners, deactivateAdmin, reactivateAdmin, hardDeleteAdmin, statusCodeFor,
25
+ // Phase 3
26
+ inviteAdmin, resendAdminInvite, cancelAdminInvite, changeAdminRole, } from './user-management';
27
+ // =============================================================================
28
+ // Admin Invite Token Service (Phase 3)
29
+ // =============================================================================
30
+ export { validateInviteToken, acceptAdminInvite, deleteAdminInviteTokens, cleanupExpiredInviteTokens, createInviteToken, INVITE_EXPIRY_HOURS, } from './admin-invite';
31
+ // =============================================================================
32
+ // Self-Service (Phase 4)
33
+ // =============================================================================
34
+ export { changeOwnPassword, updateOwnProfile, } from './admin-self-service';
15
35
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/admin/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF,OAAO;AACL,iBAAiB;AACjB,iBAAiB;AACjB,OAAO;AACP,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,GAKZ,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/admin/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF,OAAO;AACL,iBAAiB;AACjB,iBAAiB;AACjB,OAAO;AACP,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,GAKZ,MAAM,iBAAiB,CAAA;AAExB,gFAAgF;AAChF,+BAA+B;AAC/B,gFAAgF;AAEhF,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAA;AAE/B,gFAAgF;AAChF,sCAAsC;AACtC,gFAAgF;AAEhF,OAAO;AACL,UAAU;AACV,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,aAAa;AACb,UAAU;AACV,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAe1B,gFAAgF;AAChF,uCAAuC;AACvC,gFAAgF;AAEhF,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAQvB,gFAAgF;AAChF,yBAAyB;AACzB,gFAAgF;AAEhF,OAAO,EACL,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * @rovela/sdk/admin/server/user-management
3
+ *
4
+ * User lifecycle management for store admins — list, deactivate, reactivate,
5
+ * and hard-delete operations, with all invariants enforced at the service
6
+ * layer so every future caller inherits them automatically.
7
+ *
8
+ * # Invariants (enforced in every mutation)
9
+ *
10
+ * 1. Self-protection: actor cannot act on themselves via these helpers.
11
+ * Self-service flows (password change, profile update) go through
12
+ * dedicated `/api/admin/me/*` endpoints (Phase 4).
13
+ *
14
+ * 2. Last-owner protection: there must ALWAYS be at least one admin with
15
+ * role='owner' AND status='active'. Deactivating, demoting, or deleting
16
+ * the last active owner is rejected. This is enforced via an atomic
17
+ * conditional UPDATE (or a pre-check for hard delete), not a
18
+ * check-then-act pattern — no TOCTOU race window.
19
+ *
20
+ * 3. Lateral-escalation protection: administrators can only touch managers
21
+ * and users. They cannot modify owners or other administrators.
22
+ * Enforced via `canManageUser(actor, target)` from `permissions.ts`.
23
+ *
24
+ * 4. Hard delete requires prior deactivation: you cannot DELETE an admin
25
+ * whose status is 'active' or 'invited'. Must call `deactivateAdmin`
26
+ * first. This creates a two-step safety rail for irreversible actions.
27
+ *
28
+ * 5. Audit trail on deactivate: `deactivated_at` and `deactivated_by` are
29
+ * populated from the service layer. Reactivate clears them.
30
+ *
31
+ * 6. Reactivate only applies to 'deactivated' admins, not 'invited'.
32
+ * Invited admins must accept their invite (Phase 3) to become active.
33
+ *
34
+ * # Session cache invalidation
35
+ *
36
+ * Every mutation ends with `invalidateAdminSession(targetId)` so the 30-second
37
+ * per-admin status cache in `requireAdmin()` sees the new state on the very
38
+ * next request. Without this call, a deactivated admin could continue making
39
+ * authenticated requests for up to 30 seconds.
40
+ *
41
+ * # This module never throws on invariant failures — it returns a typed
42
+ * discriminated union `{ ok: true }` or `{ ok: false, error: {...} }`.
43
+ * Unexpected runtime errors (DB connectivity, etc.) still throw and bubble
44
+ * up to the API route's try/catch.
45
+ */
46
+ import type { AdminRole } from '../../core/types';
47
+ import type { StoreAdmin } from '../../core/db/schema';
48
+ export interface AdminListOptions {
49
+ /** Case-insensitive substring match against name OR email. */
50
+ search?: string;
51
+ /** Filter by status. 'all' (default) returns every admin regardless of status. */
52
+ status?: 'all' | 'active' | 'invited' | 'deactivated';
53
+ /** Filter by role. 'all' (default) returns every admin regardless of role. */
54
+ role?: 'all' | AdminRole;
55
+ /** Max rows to return. Clamped to 1..100 at the API layer. */
56
+ limit?: number;
57
+ /** Offset for pagination (0-indexed). */
58
+ offset?: number;
59
+ }
60
+ export interface UserManagementError {
61
+ code: 'NOT_FOUND' | 'FORBIDDEN' | 'SELF_ACTION_FORBIDDEN' | 'LAST_OWNER_PROTECTED' | 'MUST_DEACTIVATE_FIRST' | 'INVALID_STATE' | 'VALIDATION_ERROR' | 'EMAIL_ALREADY_EXISTS' | 'EMAIL_ALREADY_INVITED' | 'EMAIL_DEACTIVATED_EXISTS';
62
+ message: string;
63
+ }
64
+ export type UserManagementResult = {
65
+ ok: true;
66
+ } | {
67
+ ok: false;
68
+ error: UserManagementError;
69
+ };
70
+ export interface Actor {
71
+ id: string;
72
+ role: AdminRole;
73
+ }
74
+ /**
75
+ * List admins with filters and pagination.
76
+ *
77
+ * Returns the raw `StoreAdmin` rows — the caller is responsible for stripping
78
+ * sensitive fields (`passwordHash`) before serializing to JSON. The API
79
+ * handler does this mapping.
80
+ */
81
+ export declare function listAdmins(opts?: AdminListOptions): Promise<{
82
+ admins: StoreAdmin[];
83
+ total: number;
84
+ }>;
85
+ /**
86
+ * Count admins with role='owner' and status='active'.
87
+ *
88
+ * The single source of truth for the last-owner invariant. Always queried
89
+ * fresh — it's a one-row COUNT, trivially fast, and caching would introduce
90
+ * staleness risk for a safety-critical check.
91
+ */
92
+ export declare function countActiveOwners(): Promise<number>;
93
+ /**
94
+ * Soft-delete an admin: set status='deactivated' and stamp audit fields.
95
+ *
96
+ * Rejects on any invariant violation. Never throws on business errors;
97
+ * returns a typed result the caller can branch on.
98
+ *
99
+ * Uses an atomic conditional UPDATE to enforce the last-owner invariant —
100
+ * no check-then-act race window. If another request deactivates the second-
101
+ * to-last owner between our check and our update, our UPDATE's WHERE clause
102
+ * will match zero rows and we return LAST_OWNER_PROTECTED.
103
+ */
104
+ export declare function deactivateAdmin(actor: Actor, targetId: string): Promise<UserManagementResult>;
105
+ /**
106
+ * Reactivate a previously-deactivated admin: set status='active', clear
107
+ * audit fields. Does NOT apply to 'invited' admins — they must accept
108
+ * their invite (Phase 3) to become active.
109
+ */
110
+ export declare function reactivateAdmin(actor: Actor, targetId: string): Promise<UserManagementResult>;
111
+ /**
112
+ * Permanently delete an admin row. Cascades to `admin_password_reset_tokens`
113
+ * and `admin_invite_tokens` via the `ON DELETE CASCADE` foreign keys defined
114
+ * in the Phase 0 schema.
115
+ *
116
+ * Requires the target to already be 'deactivated' — this is a two-step
117
+ * irreversible action. The API route additionally gates on `users.delete`
118
+ * permission (owner-only), but we re-check here for defense-in-depth.
119
+ *
120
+ * Dangling `deactivated_by` / `created_by` references on other admin rows
121
+ * are intentionally left as dangling UUIDs. The UI renders them as
122
+ * "Unknown user". Phase 4 may revisit.
123
+ */
124
+ export declare function hardDeleteAdmin(actor: Actor, targetId: string): Promise<UserManagementResult>;
125
+ /**
126
+ * Map a `UserManagementError.code` to the HTTP status the API handler
127
+ * should respond with. Exported so both the API handlers and any future
128
+ * caller use the same mapping.
129
+ */
130
+ export declare function statusCodeFor(code: UserManagementError['code']): number;
131
+ export interface InviteAdminRequest {
132
+ email: string;
133
+ name: string;
134
+ role: AdminRole;
135
+ }
136
+ export interface InviteAdminSuccess {
137
+ ok: true;
138
+ adminId: string;
139
+ token: string;
140
+ inviteUrl: string;
141
+ }
142
+ export type InviteAdminResult = InviteAdminSuccess | {
143
+ ok: false;
144
+ error: UserManagementError;
145
+ };
146
+ /**
147
+ * Invite a new admin to manage the store.
148
+ *
149
+ * Creates a `store_admins` row in `invited` status with no password,
150
+ * issues an invite token (72h expiry), and sends the invite email. The
151
+ * caller receives both the token AND the fully-qualified invite URL — so
152
+ * if email delivery fails, the UI can show a "copy link manually"
153
+ * fallback instead of silently losing the invite.
154
+ *
155
+ * # Invariants (in order)
156
+ *
157
+ * 1. `canManageUser(actor, {role})` — actor can grant the requested role.
158
+ * Administrators cannot invite owners or other administrators.
159
+ * 2. Valid email format + name length ≥ 2.
160
+ * 3. Email uniqueness — rejects with a distinct error code depending on
161
+ * the existing row's status (active / invited / deactivated) so the
162
+ * UI can show actionable messages.
163
+ * 4. Legal role: must be one of 'owner' | 'administrator' | 'manager' | 'user'.
164
+ * The legacy 'admin' value is never chosen by the caller here — new
165
+ * invites always use the canonical names.
166
+ *
167
+ * Email send failures are logged but NOT propagated — the invite row +
168
+ * token are already persisted, the caller gets the URL, and the UI
169
+ * handles fallback display.
170
+ */
171
+ export declare function inviteAdmin(actor: Actor, request: InviteAdminRequest): Promise<InviteAdminResult>;
172
+ export interface ResendInviteSuccess {
173
+ ok: true;
174
+ token: string;
175
+ inviteUrl: string;
176
+ }
177
+ export type ResendInviteResult = ResendInviteSuccess | {
178
+ ok: false;
179
+ error: UserManagementError;
180
+ };
181
+ /**
182
+ * Resend an invite to an admin who is still in `invited` status.
183
+ *
184
+ * Generates a fresh token (invalidating any previous ones) and resends
185
+ * the email. Preserves the single-active-token policy — older tokens
186
+ * are deleted before the new one is created.
187
+ */
188
+ export declare function resendAdminInvite(actor: Actor, targetId: string): Promise<ResendInviteResult>;
189
+ /**
190
+ * Cancel a pending invite. Hard-deletes the `store_admins` row — which
191
+ * cascades via FK to delete all `admin_invite_tokens` rows for that
192
+ * admin. Only valid for `invited` status (not `active` / `deactivated`).
193
+ *
194
+ * Uses `users.write` permission (administrators + owners), unlike the
195
+ * DELETE endpoint which is owner-only. Canceling an invite for a manager
196
+ * or user is a normal administrator action, not a destructive one.
197
+ */
198
+ export declare function cancelAdminInvite(actor: Actor, targetId: string): Promise<UserManagementResult>;
199
+ /**
200
+ * Change an admin's role.
201
+ *
202
+ * Invariants (in strict order):
203
+ *
204
+ * 1. Target exists (→ NOT_FOUND).
205
+ * 2. Self-protection — actor cannot change their own role (→
206
+ * SELF_ACTION_FORBIDDEN). A solo owner needing to demote themselves
207
+ * must either invite another owner first, or use a future Phase 4
208
+ * emergency-reset flow.
209
+ * 3. canManageUser at CURRENT role — actor must be allowed to manage
210
+ * the target at their current role (administrator cannot touch
211
+ * owners or other administrators).
212
+ * 4. canManageUser at NEW role — actor must be allowed to grant the
213
+ * new role (administrator cannot promote to administrator/owner).
214
+ * 5. No-op fast path — if newRole === current role, return success
215
+ * without touching the DB.
216
+ * 6. Last-owner protection — if target is currently 'owner' and the
217
+ * new role is not 'owner', require `countActiveOwners() > 1`.
218
+ * Enforced atomically via a conditional UPDATE so there's no
219
+ * check-then-act race window.
220
+ * 7. Update; invalidate session cache.
221
+ */
222
+ export declare function changeAdminRole(actor: Actor, targetId: string, newRole: AdminRole): Promise<UserManagementResult>;
223
+ //# sourceMappingURL=user-management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-management.d.ts","sourceRoot":"","sources":["../../../src/admin/server/user-management.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAetD,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kFAAkF;IAClF,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAA;IACrD,8EAA8E;IAC9E,IAAI,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;IACxB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EACA,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,sBAAsB,GACtB,uBAAuB,GACvB,eAAe,GAEf,kBAAkB,GAClB,sBAAsB,GACtB,uBAAuB,GACvB,0BAA0B,CAAA;IAC9B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,CAAA;AAE7C,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,SAAS,CAAA;CAChB;AAMD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC;IACrE,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd,CAAC,CA0DD;AAMD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAYzD;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,CAAC,CAmH/B;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,CAAC,CAqE/B;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,CAAC,CAgG/B;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,MAAM,CAqBvE;AAMD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,IAAI,CAAA;IACR,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,iBAAiB,GACzB,kBAAkB,GAClB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CA2J5B;AAMD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,kBAAkB,GAC1B,mBAAmB,GACnB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,CAAA;AAE7C;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CA8D7B;AAMD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,CAAC,CAgE/B;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,oBAAoB,CAAC,CAsH/B"}