@cedros/login-react 0.0.43 → 0.0.45

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 (91) hide show
  1. package/README.md +216 -0
  2. package/dist/{AuthenticationSettings-Y40T1djV.cjs → AuthenticationSettings-BlYOmaEG.cjs} +1 -1
  3. package/dist/{AuthenticationSettings-Y40T1djV.cjs.map → AuthenticationSettings-BlYOmaEG.cjs.map} +1 -1
  4. package/dist/{AuthenticationSettings-CxAubcoz.js → AuthenticationSettings-BsuwWKbT.js} +1 -1
  5. package/dist/{AuthenticationSettings-CxAubcoz.js.map → AuthenticationSettings-BsuwWKbT.js.map} +1 -1
  6. package/dist/{AuthenticationSettings-aVBFKKZ-.js → AuthenticationSettings-DrHqtD7p.js} +1 -1
  7. package/dist/{AuthenticationSettings-aVBFKKZ-.js.map → AuthenticationSettings-DrHqtD7p.js.map} +1 -1
  8. package/dist/{AuthenticationSettings-DPr882lj.cjs → AuthenticationSettings-bNQiNQ9g.cjs} +1 -1
  9. package/dist/{AuthenticationSettings-DPr882lj.cjs.map → AuthenticationSettings-bNQiNQ9g.cjs.map} +1 -1
  10. package/dist/{AutosaveStatus-ByD01ENa.cjs → AutosaveStatus-CZSwtgrL.cjs} +1 -1
  11. package/dist/AutosaveStatus-CZSwtgrL.cjs.map +1 -0
  12. package/dist/{AutosaveStatus-DtF_58rC.js → AutosaveStatus-D-roPsRx.js} +280 -280
  13. package/dist/AutosaveStatus-D-roPsRx.js.map +1 -0
  14. package/dist/{CreditSystemSettings-DHG_jhz9.cjs → CreditSystemSettings-3R6crxvW.cjs} +1 -1
  15. package/dist/{CreditSystemSettings-DHG_jhz9.cjs.map → CreditSystemSettings-3R6crxvW.cjs.map} +1 -1
  16. package/dist/{CreditSystemSettings-BQek2Ux2.js → CreditSystemSettings-BTqZFn4K.js} +1 -1
  17. package/dist/{CreditSystemSettings-BQek2Ux2.js.map → CreditSystemSettings-BTqZFn4K.js.map} +1 -1
  18. package/dist/{CreditSystemSettings-CbuCce29.cjs → CreditSystemSettings-BskW_NKx.cjs} +1 -1
  19. package/dist/{CreditSystemSettings-CbuCce29.cjs.map → CreditSystemSettings-BskW_NKx.cjs.map} +1 -1
  20. package/dist/{CreditSystemSettings-GDKgYc7I.js → CreditSystemSettings-SL45GRH3.js} +1 -1
  21. package/dist/{CreditSystemSettings-GDKgYc7I.js.map → CreditSystemSettings-SL45GRH3.js.map} +1 -1
  22. package/dist/{EmailSettings-D2pCqTKC.js → EmailSettings-BUAQji4I.js} +1 -1
  23. package/dist/{EmailSettings-D2pCqTKC.js.map → EmailSettings-BUAQji4I.js.map} +1 -1
  24. package/dist/{EmailSettings-CjxBg0cE.cjs → EmailSettings-CEC1rhrm.cjs} +1 -1
  25. package/dist/{EmailSettings-CjxBg0cE.cjs.map → EmailSettings-CEC1rhrm.cjs.map} +1 -1
  26. package/dist/{EmailSettings-Cg4Z7139.cjs → EmailSettings-CihElRkc.cjs} +1 -1
  27. package/dist/{EmailSettings-Cg4Z7139.cjs.map → EmailSettings-CihElRkc.cjs.map} +1 -1
  28. package/dist/{EmailSettings-Ct6nFslP.js → EmailSettings-XETM8FdS.js} +1 -1
  29. package/dist/{EmailSettings-Ct6nFslP.js.map → EmailSettings-XETM8FdS.js.map} +1 -1
  30. package/dist/{EmbeddedWalletSettings-PwFgtGmK.js → EmbeddedWalletSettings-B-083zu6.js} +1 -1
  31. package/dist/{EmbeddedWalletSettings-PwFgtGmK.js.map → EmbeddedWalletSettings-B-083zu6.js.map} +1 -1
  32. package/dist/{EmbeddedWalletSettings-Bus7UyOX.js → EmbeddedWalletSettings-CCT9DwmL.js} +1 -1
  33. package/dist/{EmbeddedWalletSettings-Bus7UyOX.js.map → EmbeddedWalletSettings-CCT9DwmL.js.map} +1 -1
  34. package/dist/{EmbeddedWalletSettings-CfzvFYnn.cjs → EmbeddedWalletSettings-DXIjansC.cjs} +1 -1
  35. package/dist/{EmbeddedWalletSettings-CfzvFYnn.cjs.map → EmbeddedWalletSettings-DXIjansC.cjs.map} +1 -1
  36. package/dist/{EmbeddedWalletSettings-t0_5poBu.cjs → EmbeddedWalletSettings-MtwR81WH.cjs} +1 -1
  37. package/dist/{EmbeddedWalletSettings-t0_5poBu.cjs.map → EmbeddedWalletSettings-MtwR81WH.cjs.map} +1 -1
  38. package/dist/{PermissionsSection-CSB_Ikj9.cjs → PermissionsSection-4zcE9Zs9.cjs} +1 -1
  39. package/dist/PermissionsSection-4zcE9Zs9.cjs.map +1 -0
  40. package/dist/{PermissionsSection-BDDiEfho.js → PermissionsSection-mm9hfp-u.js} +94 -74
  41. package/dist/PermissionsSection-mm9hfp-u.js.map +1 -0
  42. package/dist/{ServerSettings-D7WJDTbZ.js → ServerSettings-24DA_BOI.js} +1 -1
  43. package/dist/{ServerSettings-D7WJDTbZ.js.map → ServerSettings-24DA_BOI.js.map} +1 -1
  44. package/dist/{ServerSettings-BjLFs_sb.cjs → ServerSettings-BNc4LEs4.cjs} +1 -1
  45. package/dist/{ServerSettings-BjLFs_sb.cjs.map → ServerSettings-BNc4LEs4.cjs.map} +1 -1
  46. package/dist/{ServerSettings-Dmw2rpFA.cjs → ServerSettings-BTEuzdrf.cjs} +1 -1
  47. package/dist/{ServerSettings-Dmw2rpFA.cjs.map → ServerSettings-BTEuzdrf.cjs.map} +1 -1
  48. package/dist/{ServerSettings-COkhan4u.js → ServerSettings-DBpbRihl.js} +1 -1
  49. package/dist/{ServerSettings-COkhan4u.js.map → ServerSettings-DBpbRihl.js.map} +1 -1
  50. package/dist/{TeamSection-BhsBEckR.js → TeamSection-C_eODdLU.js} +1 -1
  51. package/dist/{TeamSection-BhsBEckR.js.map → TeamSection-C_eODdLU.js.map} +1 -1
  52. package/dist/{TeamSection-DLxtRmta.cjs → TeamSection-Km7EwLWD.cjs} +1 -1
  53. package/dist/{TeamSection-DLxtRmta.cjs.map → TeamSection-Km7EwLWD.cjs.map} +1 -1
  54. package/dist/{UsersSection-BEKfbhQ4.cjs → UsersSection-C1Tt0ePx.cjs} +1 -1
  55. package/dist/{UsersSection-BEKfbhQ4.cjs.map → UsersSection-C1Tt0ePx.cjs.map} +1 -1
  56. package/dist/{UsersSection-DbGkmxty.js → UsersSection-Ct_E-MBF.js} +1 -1
  57. package/dist/{UsersSection-DbGkmxty.js.map → UsersSection-Ct_E-MBF.js.map} +1 -1
  58. package/dist/{WebhookSettings-DEHV2ptf.js → WebhookSettings-BhIwucKb.js} +1 -1
  59. package/dist/{WebhookSettings-DEHV2ptf.js.map → WebhookSettings-BhIwucKb.js.map} +1 -1
  60. package/dist/{WebhookSettings-Rq_nNJuw.cjs → WebhookSettings-C6X_JJcD.cjs} +1 -1
  61. package/dist/{WebhookSettings-Rq_nNJuw.cjs.map → WebhookSettings-C6X_JJcD.cjs.map} +1 -1
  62. package/dist/{WebhookSettings-CpPvGmV7.js → WebhookSettings-D9IsXZJN.js} +1 -1
  63. package/dist/{WebhookSettings-CpPvGmV7.js.map → WebhookSettings-D9IsXZJN.js.map} +1 -1
  64. package/dist/{WebhookSettings-DbyPJ8V2.cjs → WebhookSettings-H1x6IKOj.cjs} +1 -1
  65. package/dist/{WebhookSettings-DbyPJ8V2.cjs.map → WebhookSettings-H1x6IKOj.cjs.map} +1 -1
  66. package/dist/admin-only.cjs +1 -1
  67. package/dist/admin-only.js +1 -1
  68. package/dist/index.cjs +13 -13
  69. package/dist/index.cjs.map +1 -1
  70. package/dist/index.d.ts +128 -22
  71. package/dist/index.js +7352 -6482
  72. package/dist/index.js.map +1 -1
  73. package/dist/{plugin-C4bijrSr.cjs → plugin-BwwJh2cY.cjs} +1 -1
  74. package/dist/{plugin-C4bijrSr.cjs.map → plugin-BwwJh2cY.cjs.map} +1 -1
  75. package/dist/{plugin-Bwwe7_ZO.js → plugin-CetHtdLq.js} +1 -1
  76. package/dist/{plugin-Bwwe7_ZO.js.map → plugin-CetHtdLq.js.map} +1 -1
  77. package/dist/useUsersStatsSummary-BGeh3RnI.js +2025 -0
  78. package/dist/useUsersStatsSummary-BGeh3RnI.js.map +1 -0
  79. package/dist/useUsersStatsSummary-DnsYtFGX.cjs +1 -0
  80. package/dist/useUsersStatsSummary-DnsYtFGX.cjs.map +1 -0
  81. package/package.json +1 -1
  82. package/dist/AutosaveStatus-ByD01ENa.cjs.map +0 -1
  83. package/dist/AutosaveStatus-DtF_58rC.js.map +0 -1
  84. package/dist/PermissionsSection-BDDiEfho.js.map +0 -1
  85. package/dist/PermissionsSection-CSB_Ikj9.cjs.map +0 -1
  86. package/dist/assets/argon2Worker-Bi5TuQvD.js +0 -1
  87. package/dist/assets/argon2Worker-Bi5TuQvD.js.map +0 -1
  88. package/dist/useUsersStatsSummary-9HQDKBU5.js +0 -1879
  89. package/dist/useUsersStatsSummary-9HQDKBU5.js.map +0 -1
  90. package/dist/useUsersStatsSummary-DiRC8sGs.cjs +0 -1
  91. package/dist/useUsersStatsSummary-DiRC8sGs.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermissionsSection-4zcE9Zs9.cjs","sources":["../src/components/members/MemberList.tsx","../src/components/invites/InviteForm.tsx","../src/components/invites/InviteList.tsx","../src/utils/memberApi.ts","../src/hooks/useMembers.ts","../src/utils/inviteApi.ts","../src/hooks/useInvites.ts","../src/types/org.ts","../src/hooks/useDashboardPermissions.ts","../src/hooks/useServerFeatures.ts","../src/components/admin/PermissionsSection.tsx"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport type { Member, OrgRole, DisplayError } from '../../types';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\nimport { ErrorMessage } from '../shared/ErrorMessage';\nimport { sanitizeImageUrl } from '../../utils/sanitization';\n\ntype SortField = 'name' | 'role' | 'joinedAt';\ntype SortOrder = 'asc' | 'desc';\n\nexport interface MemberListProps {\n /** List of members to display */\n members: Member[];\n /** Current user's ID (to prevent self-actions) */\n currentUserId?: string;\n /** Loading state */\n isLoading?: boolean;\n /** Error message */\n error?: DisplayError;\n /** Whether the current user can manage members */\n canManage?: boolean;\n /** Whether the current user can change roles */\n canChangeRoles?: boolean;\n /** Callback when role is updated */\n onUpdateRole?: (userId: string, role: OrgRole) => Promise<void>;\n /** Callback when member is removed */\n onRemove?: (userId: string) => Promise<void>;\n /** Additional CSS class */\n className?: string;\n}\n\nconst ROLE_OPTIONS: OrgRole[] = ['owner', 'admin', 'member'];\n\n/**\n * Display and manage organization members.\n *\n * @example\n * ```tsx\n * function TeamMembers() {\n * const { activeOrg, hasPermission } = useOrgs();\n * const { members, isLoading, error, updateMemberRole, removeMember } = useMembers(activeOrg?.id);\n * const { user } = useAuth();\n *\n * return (\n * <MemberList\n * members={members}\n * currentUserId={user?.id}\n * isLoading={isLoading}\n * error={error?.message}\n * canManage={hasPermission('member:remove')}\n * canChangeRoles={hasPermission('member:role_change')}\n * onUpdateRole={updateMemberRole}\n * onRemove={removeMember}\n * />\n * );\n * }\n * ```\n */\nexport function MemberList({\n members,\n currentUserId,\n isLoading = false,\n error,\n canManage = false,\n canChangeRoles = false,\n onUpdateRole,\n onRemove,\n className = '',\n}: MemberListProps) {\n const [sortField, setSortField] = useState<SortField>('name');\n const [sortOrder, setSortOrder] = useState<SortOrder>('asc');\n\n const toggleSort = (field: SortField) => {\n if (sortField === field) {\n setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc');\n } else {\n setSortField(field);\n setSortOrder('asc');\n }\n };\n\n const sortedMembers = useMemo(() => {\n const roleOrder: Record<OrgRole, number> = { owner: 0, admin: 1, member: 2 };\n return [...members].sort((a, b) => {\n let aVal: string | number;\n let bVal: string | number;\n\n switch (sortField) {\n case 'name':\n aVal = (a.user.name || a.user.email || '').toLowerCase();\n bVal = (b.user.name || b.user.email || '').toLowerCase();\n break;\n case 'role':\n aVal = roleOrder[a.role] ?? 99;\n bVal = roleOrder[b.role] ?? 99;\n break;\n case 'joinedAt':\n aVal = new Date(a.joinedAt).getTime();\n bVal = new Date(b.joinedAt).getTime();\n break;\n default:\n return 0;\n }\n\n if (aVal < bVal) return sortOrder === 'asc' ? -1 : 1;\n if (aVal > bVal) return sortOrder === 'asc' ? 1 : -1;\n return 0;\n });\n }, [members, sortField, sortOrder]);\n\n if (isLoading && members.length === 0) {\n return (\n <div className={`cedros-member-list cedros-member-list-loading ${className}`}>\n <LoadingSpinner />\n <span>Loading members...</span>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className={`cedros-member-list ${className}`}>\n <ErrorMessage error={error} />\n </div>\n );\n }\n\n if (members.length === 0) {\n return (\n <div className={`cedros-member-list cedros-member-list-empty ${className}`}>\n <p>No members found.</p>\n </div>\n );\n }\n\n return (\n <div className={`cedros-member-list ${className}`}>\n <table className=\"cedros-member-table\">\n <thead>\n <tr>\n <th>\n <button\n type=\"button\"\n className={`cedros-admin-sort-button ${sortField === 'name' ? 'cedros-admin-sort-active' : ''}`}\n onClick={() => toggleSort('name')}\n >\n Member{' '}\n <span className=\"cedros-admin-sort-icon\">\n {sortField === 'name' ? (sortOrder === 'asc' ? '↑' : '↓') : '↕'}\n </span>\n </button>\n </th>\n <th>\n <button\n type=\"button\"\n className={`cedros-admin-sort-button ${sortField === 'role' ? 'cedros-admin-sort-active' : ''}`}\n onClick={() => toggleSort('role')}\n >\n Role{' '}\n <span className=\"cedros-admin-sort-icon\">\n {sortField === 'role' ? (sortOrder === 'asc' ? '↑' : '↓') : '↕'}\n </span>\n </button>\n </th>\n <th>\n <button\n type=\"button\"\n className={`cedros-admin-sort-button ${sortField === 'joinedAt' ? 'cedros-admin-sort-active' : ''}`}\n onClick={() => toggleSort('joinedAt')}\n >\n Joined{' '}\n <span className=\"cedros-admin-sort-icon\">\n {sortField === 'joinedAt' ? (sortOrder === 'asc' ? '↑' : '↓') : '↕'}\n </span>\n </button>\n </th>\n {(canManage || canChangeRoles) && <th>Actions</th>}\n </tr>\n </thead>\n <tbody>\n {sortedMembers.map((member) => (\n <MemberRow\n key={member.id}\n member={member}\n isCurrentUser={member.userId === currentUserId}\n canManage={canManage}\n canChangeRoles={canChangeRoles}\n onUpdateRole={onUpdateRole}\n onRemove={onRemove}\n />\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n// Member row component\ninterface MemberRowProps {\n member: Member;\n isCurrentUser: boolean;\n canManage: boolean;\n canChangeRoles: boolean;\n onUpdateRole?: (userId: string, role: OrgRole) => Promise<void>;\n onRemove?: (userId: string) => Promise<void>;\n}\n\nfunction MemberRow({\n member,\n isCurrentUser,\n canManage,\n canChangeRoles,\n onUpdateRole,\n onRemove,\n}: MemberRowProps) {\n const [isUpdating, setIsUpdating] = useState(false);\n const [selectedRole, setSelectedRole] = useState<OrgRole>(member.role);\n\n const handleRoleChange = useCallback(\n async (newRole: OrgRole) => {\n if (!onUpdateRole || newRole === member.role) return;\n\n setIsUpdating(true);\n try {\n await onUpdateRole(member.userId, newRole);\n setSelectedRole(newRole);\n } catch {\n // Revert on error\n setSelectedRole(member.role);\n } finally {\n setIsUpdating(false);\n }\n },\n [member.userId, member.role, onUpdateRole]\n );\n\n const handleRemove = useCallback(async () => {\n if (!onRemove) return;\n\n const confirmed = window.confirm(\n `Are you sure you want to remove ${member.user.name || member.user.email} from this organization?`\n );\n if (!confirmed) return;\n\n setIsUpdating(true);\n try {\n await onRemove(member.userId);\n } finally {\n setIsUpdating(false);\n }\n }, [member.userId, member.user.name, member.user.email, onRemove]);\n\n const isOwner = member.role === 'owner';\n const canModify = !isCurrentUser && !isOwner;\n\n return (\n <tr className={`cedros-member-row ${isCurrentUser ? 'cedros-member-row-current' : ''}`}>\n <td className=\"cedros-member-info\">\n <MemberAvatar user={member.user} />\n <div className=\"cedros-member-details\">\n <span className=\"cedros-member-name\">\n {member.user.name || 'Unknown'}\n {isCurrentUser && <span className=\"cedros-member-you\">(you)</span>}\n </span>\n <span className=\"cedros-member-email\">{member.user.email}</span>\n </div>\n </td>\n <td className=\"cedros-member-role\">\n {canChangeRoles && canModify && onUpdateRole ? (\n <select\n value={selectedRole}\n onChange={(e) => handleRoleChange(e.target.value as OrgRole)}\n disabled={isUpdating}\n className=\"cedros-role-select\"\n >\n {ROLE_OPTIONS.map((role) => (\n <option key={role} value={role}>\n {role.charAt(0).toUpperCase() + role.slice(1)}\n </option>\n ))}\n </select>\n ) : (\n <span className={`cedros-role-badge cedros-role-badge-${member.role}`}>\n {member.role.charAt(0).toUpperCase() + member.role.slice(1)}\n </span>\n )}\n </td>\n <td className=\"cedros-member-joined\">{formatDate(member.joinedAt)}</td>\n {(canManage || canChangeRoles) && (\n <td className=\"cedros-member-actions\">\n {canManage && canModify && onRemove && (\n <button\n type=\"button\"\n className=\"cedros-button cedros-button-danger cedros-button-sm\"\n onClick={handleRemove}\n disabled={isUpdating}\n aria-label={`Remove ${member.user.name || member.user.email}`}\n >\n {isUpdating ? <LoadingSpinner size=\"sm\" /> : 'Remove'}\n </button>\n )}\n </td>\n )}\n </tr>\n );\n}\n\n// Helper components\nfunction MemberAvatar({ user }: { user: Member['user'] }) {\n // COMP-06: Cache sanitized URL and verify before use (blocks dangerous protocols)\n const sanitizedPicture = sanitizeImageUrl(user.picture);\n if (sanitizedPicture) {\n return (\n <img\n src={sanitizedPicture}\n alt={user.name || user.email || 'Member'}\n className=\"cedros-member-avatar\"\n referrerPolicy=\"no-referrer\"\n />\n );\n }\n\n const initial = (user.name?.[0] || user.email?.[0] || '?').toUpperCase();\n return <div className=\"cedros-member-avatar-placeholder\">{initial}</div>;\n}\n\nfunction formatDate(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n}\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport type { OrgRole, DisplayError } from '../../types';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\nimport { ErrorMessage } from '../shared/ErrorMessage';\nimport { validateEmail } from '../../utils/validation';\n\ntype InviteRole = Exclude<OrgRole, 'owner'>;\n\nexport interface InviteFormProps {\n /** Callback when invite is submitted */\n onSubmit: (email: string, role: InviteRole) => Promise<void>;\n /** Loading state */\n isLoading?: boolean;\n /** Error message */\n error?: DisplayError;\n /** Available roles for invite (default: admin, member) */\n availableRoles?: InviteRole[];\n /** Default role for new invites */\n defaultRole?: InviteRole;\n /** Additional CSS class */\n className?: string;\n}\n\nconst DEFAULT_ROLES: InviteRole[] = ['admin', 'member'];\n\n/**\n * Form for inviting new members to an organization.\n *\n * @example\n * ```tsx\n * function InviteManager() {\n * const { activeOrg } = useOrgs();\n * const { createInvite, isLoading, error } = useInvites(activeOrg?.id);\n *\n * return (\n * <InviteForm\n * onSubmit={createInvite}\n * isLoading={isLoading}\n * error={error?.message}\n * defaultRole=\"member\"\n * />\n * );\n * }\n * ```\n */\nexport function InviteForm({\n onSubmit,\n isLoading = false,\n error,\n availableRoles = DEFAULT_ROLES,\n defaultRole = 'member',\n className = '',\n}: InviteFormProps) {\n const [email, setEmail] = useState('');\n const [role, setRole] = useState<InviteRole>(defaultRole);\n const [formError, setFormError] = useState<string | null>(null);\n const [success, setSuccess] = useState(false);\n const successTimerRef = useRef<number | null>(null);\n // UI-03: Track mounted state to prevent state updates after unmount\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n if (successTimerRef.current !== null) {\n window.clearTimeout(successTimerRef.current);\n successTimerRef.current = null;\n }\n };\n }, []);\n\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n setSuccess(false);\n\n const trimmedEmail = email.trim();\n\n if (!trimmedEmail) {\n setFormError('Email is required');\n return;\n }\n\n if (!validateEmail(trimmedEmail)) {\n setFormError('Please enter a valid email address');\n return;\n }\n\n try {\n await onSubmit(trimmedEmail, role);\n setEmail('');\n setRole(defaultRole);\n setSuccess(true);\n // Clear success message after 3 seconds\n if (successTimerRef.current !== null) {\n window.clearTimeout(successTimerRef.current);\n }\n successTimerRef.current = window.setTimeout(() => {\n // UI-03: Check mounted before state update to prevent memory leak warnings\n if (isMountedRef.current) {\n setSuccess(false);\n }\n successTimerRef.current = null;\n }, 3000);\n } catch {\n // H-05: Error handling is delegated to parent component.\n // Parent's onSubmit throws -> parent catches -> sets error prop -> ErrorMessage displays it.\n // This pattern allows the parent to control error display and retry logic.\n }\n },\n [email, role, defaultRole, onSubmit]\n );\n\n return (\n <form className={`cedros-invite-form ${className}`} onSubmit={handleSubmit}>\n {(error || formError) && <ErrorMessage error={formError ?? error ?? null} />}\n\n {success && (\n <div className=\"cedros-invite-success\" role=\"status\">\n <CheckIcon />\n <span>Invitation sent successfully!</span>\n </div>\n )}\n\n <div className=\"cedros-invite-form-row\">\n <div className=\"cedros-form-group cedros-invite-email-group\">\n <label htmlFor=\"invite-email\" className=\"cedros-form-label\">\n Email Address\n </label>\n <input\n id=\"invite-email\"\n type=\"email\"\n className=\"cedros-form-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"colleague@example.com\"\n disabled={isLoading}\n autoComplete=\"email\"\n />\n </div>\n\n <div className=\"cedros-form-group cedros-invite-role-group\">\n <label htmlFor=\"invite-role\" className=\"cedros-form-label\">\n Role\n </label>\n <select\n id=\"invite-role\"\n className=\"cedros-form-select\"\n value={role}\n onChange={(e) => setRole(e.target.value as InviteRole)}\n disabled={isLoading}\n >\n {availableRoles.map((r) => (\n <option key={r} value={r}>\n {r.charAt(0).toUpperCase() + r.slice(1)}\n </option>\n ))}\n </select>\n </div>\n\n <button\n type=\"submit\"\n className=\"cedros-button cedros-button-primary cedros-invite-submit\"\n disabled={isLoading || !email.trim()}\n >\n {isLoading ? <LoadingSpinner size=\"sm\" /> : 'Send Invite'}\n </button>\n </div>\n\n <p className=\"cedros-form-hint\">\n The invited user will receive an email with a link to join your organization.\n </p>\n </form>\n );\n}\n\nfunction CheckIcon() {\n return (\n <svg\n className=\"cedros-invite-check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M3 8L6 11L13 5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport type { Invite, DisplayError } from '../../types';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\nimport { ErrorMessage } from '../shared/ErrorMessage';\n\nexport interface InviteListProps {\n /** List of pending invites */\n invites: Invite[];\n /** Loading state */\n isLoading?: boolean;\n /** Error message */\n error?: DisplayError;\n /** Whether the current user can manage invites */\n canManage?: boolean;\n /** Callback when invite is cancelled */\n onCancel?: (inviteId: string) => Promise<void>;\n /** Callback when invite is resent */\n onResend?: (inviteId: string) => Promise<void>;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Display and manage pending organization invites.\n *\n * @example\n * ```tsx\n * function PendingInvites() {\n * const { activeOrg, hasPermission } = useOrgs();\n * const { invites, isLoading, error, cancelInvite, resendInvite } = useInvites(activeOrg?.id);\n *\n * return (\n * <InviteList\n * invites={invites}\n * isLoading={isLoading}\n * error={error?.message}\n * canManage={hasPermission('invite:cancel')}\n * onCancel={cancelInvite}\n * onResend={resendInvite}\n * />\n * );\n * }\n * ```\n */\nexport function InviteList({\n invites,\n isLoading = false,\n error,\n canManage = false,\n onCancel,\n onResend,\n className = '',\n}: InviteListProps) {\n if (isLoading && invites.length === 0) {\n return (\n <div className={`cedros-invite-list cedros-invite-list-loading ${className}`}>\n <LoadingSpinner />\n <span>Loading invites...</span>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className={`cedros-invite-list ${className}`}>\n <ErrorMessage error={error} />\n </div>\n );\n }\n\n if (invites.length === 0) {\n return (\n <div className={`cedros-invite-list cedros-invite-list-empty ${className}`}>\n <p>No pending invites.</p>\n </div>\n );\n }\n\n return (\n <div className={`cedros-invite-list ${className}`}>\n <ul className=\"cedros-invite-items\">\n {invites.map((invite) => (\n <InviteItem\n key={invite.id}\n invite={invite}\n canManage={canManage}\n onCancel={onCancel}\n onResend={onResend}\n />\n ))}\n </ul>\n </div>\n );\n}\n\n// Invite item component\ninterface InviteItemProps {\n invite: Invite;\n canManage: boolean;\n onCancel?: (inviteId: string) => Promise<void>;\n onResend?: (inviteId: string) => Promise<void>;\n}\n\nfunction InviteItem({ invite, canManage, onCancel, onResend }: InviteItemProps) {\n const [isUpdating, setIsUpdating] = useState(false);\n const [resendSuccess, setResendSuccess] = useState(false);\n const resendTimerRef = useRef<number | null>(null);\n\n const isExpired = new Date(invite.expiresAt) < new Date();\n\n const handleCancel = useCallback(async () => {\n if (!onCancel) return;\n\n const confirmed = window.confirm(\n `Are you sure you want to cancel the invite for ${invite.email}?`\n );\n if (!confirmed) return;\n\n setIsUpdating(true);\n try {\n await onCancel(invite.id);\n } finally {\n setIsUpdating(false);\n }\n }, [invite.id, invite.email, onCancel]);\n\n const handleResend = useCallback(async () => {\n if (!onResend) return;\n\n setIsUpdating(true);\n setResendSuccess(false);\n try {\n await onResend(invite.id);\n setResendSuccess(true);\n if (resendTimerRef.current !== null) {\n window.clearTimeout(resendTimerRef.current);\n }\n resendTimerRef.current = window.setTimeout(() => {\n setResendSuccess(false);\n resendTimerRef.current = null;\n }, 3000);\n } finally {\n setIsUpdating(false);\n }\n }, [invite.id, onResend]);\n\n useEffect(() => {\n return () => {\n if (resendTimerRef.current !== null) {\n window.clearTimeout(resendTimerRef.current);\n resendTimerRef.current = null;\n }\n };\n }, []);\n\n return (\n <li className={`cedros-invite-item ${isExpired ? 'cedros-invite-item-expired' : ''}`}>\n <div className=\"cedros-invite-item-info\">\n <div className=\"cedros-invite-item-main\">\n <span className=\"cedros-invite-item-email\">{invite.email}</span>\n <span className={`cedros-role-badge cedros-role-badge-${invite.role}`}>\n {invite.role.charAt(0).toUpperCase() + invite.role.slice(1)}\n </span>\n {isExpired && <span className=\"cedros-invite-expired-badge\">Expired</span>}\n </div>\n <div className=\"cedros-invite-item-meta\">\n <span className=\"cedros-invite-item-date\">\n {/* TYPE-05: invitedByName removed - backend doesn't populate it */}\n Invited {formatDate(invite.createdAt)}\n </span>\n {!isExpired && (\n <span className=\"cedros-invite-item-expires\">\n Expires {formatRelativeTime(invite.expiresAt)}\n </span>\n )}\n </div>\n </div>\n\n {canManage && (\n <div className=\"cedros-invite-item-actions\">\n {resendSuccess && <span className=\"cedros-invite-resend-success\">Sent!</span>}\n {onResend && !isExpired && (\n <button\n type=\"button\"\n className=\"cedros-button cedros-button-outline cedros-button-sm\"\n onClick={handleResend}\n disabled={isUpdating}\n aria-label={`Resend invite to ${invite.email}`}\n >\n {isUpdating ? <LoadingSpinner size=\"sm\" /> : 'Resend'}\n </button>\n )}\n {onCancel && (\n <button\n type=\"button\"\n className=\"cedros-button cedros-button-danger cedros-button-sm\"\n onClick={handleCancel}\n disabled={isUpdating}\n aria-label={`Cancel invite for ${invite.email}`}\n >\n Cancel\n </button>\n )}\n </div>\n )}\n </li>\n );\n}\n\n// Helper functions\nfunction formatDate(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n}\n\nfunction formatRelativeTime(dateString: string): string {\n const date = new Date(dateString);\n const now = new Date();\n const diffMs = date.getTime() - now.getTime();\n const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24));\n\n if (diffDays < 0) {\n return 'expired';\n } else if (diffDays === 0) {\n return 'today';\n } else if (diffDays === 1) {\n return 'tomorrow';\n } else if (diffDays < 7) {\n return `in ${diffDays} days`;\n } else {\n return formatDate(dateString);\n }\n}\n","import type {\n Member,\n MemberApiResponse,\n UpdateMemberRoleRequest,\n ListMembersResponse,\n} from '../types';\nimport { ApiClient, handleApiError } from './apiClient';\n\n/**\n * API client for member operations within an organization\n */\nexport class MemberApiClient {\n private client: ApiClient;\n\n constructor(\n baseUrl: string,\n timeoutMs?: number,\n retryAttempts?: number,\n getAccessToken?: () => string | null\n ) {\n this.client = new ApiClient({ baseUrl, timeoutMs, retryAttempts, getAccessToken });\n }\n\n /**\n * List all members of an organization\n */\n async listMembers(\n orgId: string,\n limit: number = 50,\n offset: number = 0\n ): Promise<{ members: Member[]; total: number }> {\n try {\n const response = await this.client.get<ListMembersResponse>(\n `/orgs/${orgId}/members?limit=${limit}&offset=${offset}`\n );\n return {\n members: response.members.map((member: MemberApiResponse) => ({\n id: member.id,\n userId: member.userId,\n orgId,\n role: member.role,\n joinedAt: member.joinedAt,\n user: {\n id: member.userId,\n email: member.email,\n name: member.name,\n },\n })),\n total: response.total,\n };\n } catch (error) {\n throw handleApiError(error, 'Failed to list members');\n }\n }\n\n /**\n * Update a member's role\n */\n async updateMemberRole(\n orgId: string,\n userId: string,\n data: UpdateMemberRoleRequest\n ): Promise<Member> {\n try {\n return await this.client.patch<Member>(`/orgs/${orgId}/members/${userId}`, data);\n } catch (error) {\n throw handleApiError(error, 'Failed to update member role');\n }\n }\n\n /**\n * Remove a member from the organization\n */\n async removeMember(orgId: string, userId: string): Promise<void> {\n try {\n await this.client.delete<void>(`/orgs/${orgId}/members/${userId}`);\n } catch (error) {\n throw handleApiError(error, 'Failed to remove member');\n }\n }\n}\n","import { useState, useCallback, useMemo, useEffect, useRef } from 'react';\nimport type { Member, OrgRole, AuthError } from '../types';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { MemberApiClient } from '../utils/memberApi';\n\nexport interface UseMembersReturn {\n /** List of members */\n members: Member[];\n /** Total members available on the server */\n total: number;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: AuthError | null;\n /** Fetch/refresh members list */\n fetchMembers: (options?: { limit?: number; offset?: number }) => Promise<void>;\n /** Update a member's role */\n updateMemberRole: (userId: string, role: OrgRole) => Promise<void>;\n /** Remove a member */\n removeMember: (userId: string) => Promise<void>;\n}\n\n/**\n * Hook for managing organization members.\n *\n * @param orgId - The organization ID to manage members for\n *\n * @example\n * ```tsx\n * function MembersList() {\n * const { activeOrg } = useOrgs();\n * const { members, isLoading, updateMemberRole, removeMember } = useMembers(activeOrg?.id);\n *\n * if (!activeOrg) return null;\n *\n * return (\n * <ul>\n * {members.map(member => (\n * <li key={member.id}>\n * {member.user.name} - {member.role}\n * <button onClick={() => updateMemberRole(member.userId, 'admin')}>\n * Make Admin\n * </button>\n * <button onClick={() => removeMember(member.userId)}>\n * Remove\n * </button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useMembers(orgId: string | undefined): UseMembersReturn {\n const { config, authState, _internal } = useCedrosLogin();\n\n const [members, setMembers] = useState<Member[]>([]);\n const [total, setTotal] = useState(0);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n // P-12: Track fetched orgId to prevent duplicate fetches on remount\n const fetchedOrgIdRef = useRef<string | undefined>(undefined);\n const requestIdRef = useRef(0);\n\n const apiClient = useMemo(\n () =>\n new MemberApiClient(\n config.serverUrl,\n config.requestTimeout,\n config.retryAttempts,\n _internal?.getAccessToken\n ),\n [config.serverUrl, config.requestTimeout, config.retryAttempts, _internal]\n );\n\n // C-02: Use ref to avoid apiClient in callback dependencies\n // Prevents infinite loop when apiClient identity changes\n const apiClientRef = useRef(apiClient);\n apiClientRef.current = apiClient;\n\n const fetchMembers = useCallback(\n async (options?: { limit?: number; offset?: number }) => {\n if (!orgId || authState !== 'authenticated') {\n setMembers([]);\n setTotal(0);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n const requestId = ++requestIdRef.current;\n\n try {\n const { limit = 50, offset = 0 } = options ?? {};\n const response = await apiClientRef.current.listMembers(orgId, limit, offset);\n if (requestId !== requestIdRef.current) return;\n setMembers(response.members);\n setTotal(response.total);\n } catch (err) {\n if (requestId !== requestIdRef.current) return;\n setError(err as AuthError);\n } finally {\n if (requestId === requestIdRef.current) {\n setIsLoading(false);\n }\n }\n },\n [orgId, authState]\n );\n\n // P-12: Auto-fetch when orgId changes, but not on every remount\n useEffect(() => {\n if (authState !== 'authenticated') {\n fetchedOrgIdRef.current = undefined;\n return;\n }\n\n if (orgId !== fetchedOrgIdRef.current) {\n fetchedOrgIdRef.current = orgId;\n fetchMembers();\n }\n }, [orgId, authState, fetchMembers]);\n\n const updateMemberRole = useCallback(\n async (userId: string, role: OrgRole): Promise<void> => {\n if (!orgId) {\n throw new Error('No organization selected');\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n await apiClientRef.current.updateMemberRole(orgId, userId, { role });\n // Refresh members list\n await fetchMembers();\n } catch (err) {\n setError(err as AuthError);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [orgId, fetchMembers]\n );\n\n const removeMember = useCallback(\n async (userId: string): Promise<void> => {\n if (!orgId) {\n throw new Error('No organization selected');\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n await apiClientRef.current.removeMember(orgId, userId);\n // Refresh members list\n await fetchMembers();\n } catch (err) {\n setError(err as AuthError);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [orgId, fetchMembers]\n );\n\n return {\n members,\n total,\n isLoading,\n error,\n fetchMembers,\n updateMemberRole,\n removeMember,\n };\n}\n","import type {\n Invite,\n InviteApiResponse,\n CreateInviteRequest,\n AcceptInviteRequest,\n ListInvitesResponse,\n CreateInviteResponse,\n AcceptInviteResponse,\n} from '../types';\nimport { ApiClient, handleApiError } from './apiClient';\n\n/**\n * API client for invite operations\n */\nexport class InviteApiClient {\n private client: ApiClient;\n\n constructor(\n baseUrl: string,\n timeoutMs?: number,\n retryAttempts?: number,\n getAccessToken?: () => string | null\n ) {\n this.client = new ApiClient({ baseUrl, timeoutMs, retryAttempts, getAccessToken });\n }\n\n /**\n * List all pending invites for an organization\n */\n async listInvites(\n orgId: string,\n limit: number = 50,\n offset: number = 0\n ): Promise<{ invites: Invite[]; total: number }> {\n try {\n const response = await this.client.get<ListInvitesResponse>(\n `/orgs/${orgId}/invites?limit=${limit}&offset=${offset}`\n );\n return {\n invites: response.invites.map((invite: InviteApiResponse) => ({\n id: invite.id,\n orgId: invite.orgId,\n email: invite.email,\n role: invite.role,\n invitedBy: invite.invitedBy,\n createdAt: invite.createdAt,\n expiresAt: invite.expiresAt,\n })),\n total: response.total,\n };\n } catch (error) {\n throw handleApiError(error, 'Failed to list invites');\n }\n }\n\n /**\n * Create a new invite\n */\n async createInvite(orgId: string, data: CreateInviteRequest): Promise<CreateInviteResponse> {\n try {\n return await this.client.post<CreateInviteResponse>(`/orgs/${orgId}/invites`, data);\n } catch (error) {\n throw handleApiError(error, 'Failed to create invite');\n }\n }\n\n /**\n * Cancel a pending invite\n */\n async cancelInvite(orgId: string, inviteId: string): Promise<void> {\n try {\n await this.client.delete<void>(`/orgs/${orgId}/invites/${inviteId}`);\n } catch (error) {\n throw handleApiError(error, 'Failed to cancel invite');\n }\n }\n\n /**\n * Resend an invite email\n */\n async resendInvite(orgId: string, inviteId: string): Promise<void> {\n try {\n await this.client.post<void>(`/orgs/${orgId}/invites/${inviteId}/resend`, {});\n } catch (error) {\n throw handleApiError(error, 'Failed to resend invite');\n }\n }\n\n /**\n * Accept an invite (public endpoint)\n */\n async acceptInvite(data: AcceptInviteRequest): Promise<AcceptInviteResponse> {\n try {\n return await this.client.post<AcceptInviteResponse>('/invites/accept', data);\n } catch (error) {\n throw handleApiError(error, 'Failed to accept invite');\n }\n }\n}\n","import { useState, useCallback, useMemo, useEffect, useRef } from 'react';\nimport type { Invite, OrgRole, AuthError, AcceptInviteResponse } from '../types';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { InviteApiClient } from '../utils/inviteApi';\n\nexport interface UseInvitesReturn {\n /** List of pending invites */\n invites: Invite[];\n /** Total pending invites available on the server */\n total: number;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: AuthError | null;\n /** Fetch/refresh invites list */\n fetchInvites: (options?: { limit?: number; offset?: number }) => Promise<void>;\n /** Create a new invite */\n createInvite: (email: string, role?: Exclude<OrgRole, 'owner'>) => Promise<void>;\n /** Cancel a pending invite */\n cancelInvite: (inviteId: string) => Promise<void>;\n /** Resend an invite email */\n resendInvite: (inviteId: string) => Promise<void>;\n /** Accept an invite (public) */\n acceptInvite: (token: string) => Promise<AcceptInviteResponse>;\n}\n\n/**\n * Hook for managing organization invites.\n *\n * @param orgId - The organization ID to manage invites for\n *\n * @example\n * ```tsx\n * function InviteManager() {\n * const { activeOrg } = useOrgs();\n * const { invites, createInvite, cancelInvite, resendInvite } = useInvites(activeOrg?.id);\n *\n * const handleInvite = async (email: string) => {\n * await createInvite(email, 'member');\n * };\n *\n * return (\n * <div>\n * <InviteForm onSubmit={handleInvite} />\n * <ul>\n * {invites.map(invite => (\n * <li key={invite.id}>\n * {invite.email} ({invite.role})\n * <button onClick={() => resendInvite(invite.id)}>Resend</button>\n * <button onClick={() => cancelInvite(invite.id)}>Cancel</button>\n * </li>\n * ))}\n * </ul>\n * </div>\n * );\n * }\n * ```\n */\nexport function useInvites(orgId: string | undefined): UseInvitesReturn {\n const { config, authState, _internal } = useCedrosLogin();\n\n const [invites, setInvites] = useState<Invite[]>([]);\n const [total, setTotal] = useState(0);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n // P-13: Track fetched orgId to prevent duplicate fetches on remount\n const fetchedOrgIdRef = useRef<string | undefined>(undefined);\n const requestIdRef = useRef(0);\n\n const apiClient = useMemo(\n () =>\n new InviteApiClient(\n config.serverUrl,\n config.requestTimeout,\n config.retryAttempts,\n _internal?.getAccessToken\n ),\n [config.serverUrl, config.requestTimeout, config.retryAttempts, _internal]\n );\n\n // H-02: Use ref to avoid apiClient in callback dependencies\n // Prevents infinite loop when apiClient identity changes\n const apiClientRef = useRef(apiClient);\n apiClientRef.current = apiClient;\n\n const fetchInvites = useCallback(\n async (options?: { limit?: number; offset?: number }) => {\n if (!orgId || authState !== 'authenticated') {\n setInvites([]);\n setTotal(0);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n const requestId = ++requestIdRef.current;\n\n try {\n const { limit = 50, offset = 0 } = options ?? {};\n const response = await apiClientRef.current.listInvites(orgId, limit, offset);\n if (requestId !== requestIdRef.current) return;\n setInvites(response.invites);\n setTotal(response.total);\n } catch (err) {\n if (requestId !== requestIdRef.current) return;\n setError(err as AuthError);\n } finally {\n if (requestId === requestIdRef.current) {\n setIsLoading(false);\n }\n }\n },\n [orgId, authState]\n );\n\n // P-13: Auto-fetch when orgId changes, but not on every remount\n useEffect(() => {\n if (authState !== 'authenticated') {\n fetchedOrgIdRef.current = undefined;\n return;\n }\n\n if (orgId !== fetchedOrgIdRef.current) {\n fetchedOrgIdRef.current = orgId;\n fetchInvites();\n }\n }, [orgId, authState, fetchInvites]);\n\n const createInvite = useCallback(\n async (email: string, role: Exclude<OrgRole, 'owner'> = 'member'): Promise<void> => {\n if (!orgId) {\n throw new Error('No organization selected');\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n await apiClientRef.current.createInvite(orgId, { email, role });\n // Refresh invites list\n await fetchInvites();\n } catch (err) {\n setError(err as AuthError);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [orgId, fetchInvites]\n );\n\n const cancelInvite = useCallback(\n async (inviteId: string): Promise<void> => {\n if (!orgId) {\n throw new Error('No organization selected');\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n await apiClientRef.current.cancelInvite(orgId, inviteId);\n // Refresh invites list\n await fetchInvites();\n } catch (err) {\n setError(err as AuthError);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [orgId, fetchInvites]\n );\n\n const resendInvite = useCallback(\n async (inviteId: string): Promise<void> => {\n if (!orgId) {\n throw new Error('No organization selected');\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n await apiClientRef.current.resendInvite(orgId, inviteId);\n } catch (err) {\n setError(err as AuthError);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [orgId]\n );\n\n const acceptInvite = useCallback(async (token: string): Promise<AcceptInviteResponse> => {\n setIsLoading(true);\n setError(null);\n\n try {\n return await apiClientRef.current.acceptInvite({ token });\n } catch (err) {\n setError(err as AuthError);\n throw err;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n return {\n invites,\n total,\n isLoading,\n error,\n fetchInvites,\n createInvite,\n cancelInvite,\n resendInvite,\n acceptInvite,\n };\n}\n","/**\n * Organization role in RBAC hierarchy\n * owner > admin > member\n */\nexport type OrgRole = 'owner' | 'admin' | 'member';\n\n/**\n * Organization entity\n */\nexport interface Organization {\n id: string;\n name: string;\n slug: string;\n logoUrl?: string;\n isPersonal: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Membership - user's relationship to an organization\n */\nexport interface Membership {\n id?: string;\n userId?: string;\n orgId?: string;\n role: OrgRole;\n joinedAt?: string;\n}\n\n/**\n * Organization with membership details for the current user\n */\nexport interface OrgWithMembership extends Organization {\n membership: Membership;\n}\n\n/**\n * Permission types for RBAC\n */\nexport type Permission =\n | 'org:delete'\n | 'org:update'\n | 'org:read'\n | 'member:invite'\n | 'member:remove'\n | 'member:role_change'\n | 'member:read'\n | 'invite:create'\n | 'invite:cancel'\n | 'invite:read'\n | 'audit:read';\n\n/**\n * Create organization request\n */\nexport interface CreateOrgRequest {\n name: string;\n slug?: string;\n}\n\n/**\n * Update organization request\n */\nexport interface UpdateOrgRequest {\n name?: string;\n slug?: string;\n logoUrl?: string;\n}\n\n/**\n * List organizations response\n */\nexport interface ListOrgsResponse {\n orgs: Array<Organization & { role: OrgRole }>;\n total?: number;\n limit?: number;\n offset?: number;\n}\n\n/**\n * Authorization check request\n */\nexport interface AuthorizeRequest {\n orgId: string;\n action: string;\n resource?: string;\n resourceId?: string;\n}\n\n/**\n * Authorization check response\n */\nexport interface AuthorizeResponse {\n allowed: boolean;\n reason?: string;\n}\n\n/**\n * Permissions response\n */\nexport interface PermissionsResponse {\n permissions: Permission[];\n role: OrgRole;\n}\n\n/**\n * Organization state for context\n */\nexport interface OrgState {\n /** Currently active organization */\n activeOrg: OrgWithMembership | null;\n /** All organizations the user belongs to */\n orgs: OrgWithMembership[];\n /** User's permissions in the active org */\n permissions: Permission[];\n /** User's role in the active org */\n role: OrgRole | null;\n /** Loading state for org operations */\n isLoading: boolean;\n}\n\n// =============================================================================\n// DASHBOARD PERMISSIONS\n// =============================================================================\n\n/**\n * Admin dashboard sections that can be permission-controlled\n */\nexport type DashboardSection =\n // Cedros Login sections\n | 'users'\n | 'team'\n | 'referrals'\n | 'deposits'\n | 'withdrawals'\n | 'compliance'\n | 'accreditation-queue'\n | 'sanctions'\n | 'settings-wallet'\n | 'settings-auth'\n | 'settings-messaging'\n | 'settings-credits'\n | 'settings-compliance'\n | 'settings-referrals'\n | 'settings-server'\n | 'settings-images'\n // Cedros Pay sections\n | 'pay-products'\n | 'pay-subscriptions'\n | 'pay-transactions'\n | 'pay-coupons'\n | 'pay-refunds'\n | 'pay-storefront'\n | 'pay-ai'\n | 'pay-payment'\n | 'pay-messaging'\n | 'pay-settings';\n\n/**\n * Cedros Login dashboard sections\n */\nexport const LOGIN_DASHBOARD_SECTIONS: DashboardSection[] = [\n 'users',\n 'team',\n 'referrals',\n 'deposits',\n 'withdrawals',\n 'compliance',\n 'accreditation-queue',\n 'sanctions',\n 'settings-wallet',\n 'settings-auth',\n 'settings-messaging',\n 'settings-credits',\n 'settings-compliance',\n 'settings-referrals',\n 'settings-server',\n 'settings-images',\n];\n\n/**\n * Cedros Pay dashboard sections\n */\nexport const PAY_DASHBOARD_SECTIONS: DashboardSection[] = [\n 'pay-products',\n 'pay-subscriptions',\n 'pay-transactions',\n 'pay-coupons',\n 'pay-refunds',\n 'pay-storefront',\n 'pay-ai',\n 'pay-payment',\n 'pay-messaging',\n 'pay-settings',\n];\n\n/**\n * All available dashboard sections\n */\nexport const ALL_DASHBOARD_SECTIONS: DashboardSection[] = [\n ...LOGIN_DASHBOARD_SECTIONS,\n ...PAY_DASHBOARD_SECTIONS,\n];\n\n/**\n * Human-readable labels for dashboard sections\n */\nexport const DASHBOARD_SECTION_LABELS: Record<DashboardSection, string> = {\n // Cedros Login\n users: 'Users',\n team: 'Team',\n referrals: 'Referrals',\n deposits: 'Deposits',\n withdrawals: 'Withdrawals',\n compliance: 'Compliance',\n 'accreditation-queue': 'Accreditation Queue',\n sanctions: 'Sanctions',\n 'settings-wallet': 'Wallet Settings',\n 'settings-auth': 'Auth Settings',\n 'settings-messaging': 'Messages Settings',\n 'settings-credits': 'Credits Settings',\n 'settings-compliance': 'Compliance & Gating',\n 'settings-referrals': 'Referrals & Rewards',\n 'settings-server': 'Server Settings',\n 'settings-images': 'Image Storage',\n // Cedros Pay\n 'pay-products': 'Products',\n 'pay-subscriptions': 'Subscriptions',\n 'pay-transactions': 'Transactions',\n 'pay-coupons': 'Coupons',\n 'pay-refunds': 'Refunds',\n 'pay-storefront': 'Storefront',\n 'pay-ai': 'Store AI',\n 'pay-payment': 'Payment Options',\n 'pay-messaging': 'Store Messages',\n 'pay-settings': 'Store Server',\n};\n\n/**\n * Dashboard permissions per role\n * Only admin and member are configurable - owner always has full access\n */\nexport interface DashboardPermissions {\n admin: Record<DashboardSection, boolean>;\n member: Record<DashboardSection, boolean>;\n}\n\n/**\n * Default dashboard permissions for new orgs\n */\nexport const DEFAULT_DASHBOARD_PERMISSIONS: DashboardPermissions = {\n admin: {\n // Cedros Login\n users: true,\n team: true,\n referrals: true,\n deposits: true,\n withdrawals: true,\n compliance: true,\n 'accreditation-queue': true,\n sanctions: true,\n 'settings-wallet': true,\n 'settings-auth': true,\n 'settings-messaging': true,\n 'settings-credits': true,\n 'settings-compliance': true,\n 'settings-referrals': true,\n 'settings-server': true,\n 'settings-images': true,\n // Cedros Pay\n 'pay-products': true,\n 'pay-subscriptions': true,\n 'pay-transactions': true,\n 'pay-coupons': true,\n 'pay-refunds': true,\n 'pay-storefront': true,\n 'pay-ai': true,\n 'pay-payment': true,\n 'pay-messaging': true,\n 'pay-settings': true,\n },\n member: {\n // Cedros Login\n users: false,\n team: true,\n referrals: false,\n deposits: false,\n withdrawals: false,\n compliance: false,\n 'accreditation-queue': false,\n sanctions: false,\n 'settings-wallet': false,\n 'settings-auth': false,\n 'settings-messaging': false,\n 'settings-credits': false,\n 'settings-compliance': false,\n 'settings-referrals': false,\n 'settings-server': false,\n 'settings-images': false,\n // Cedros Pay\n 'pay-products': false,\n 'pay-subscriptions': false,\n 'pay-transactions': false,\n 'pay-coupons': false,\n 'pay-refunds': false,\n 'pay-storefront': false,\n 'pay-ai': false,\n 'pay-payment': false,\n 'pay-messaging': false,\n 'pay-settings': false,\n },\n};\n","import { useState, useCallback, useMemo, useRef, useEffect } from 'react';\nimport type { DashboardSection, DashboardPermissions, AuthError } from '../types';\nimport { DEFAULT_DASHBOARD_PERMISSIONS } from '../types/org';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { useOrgs } from './useOrgs';\nimport { ApiClient } from '../utils/apiClient';\n\nexport interface UseDashboardPermissionsReturn {\n /** Current dashboard permissions config */\n permissions: DashboardPermissions;\n /** Whether the current user can access a specific section */\n canAccess: (section: DashboardSection) => boolean;\n /** Update permissions (owner only) */\n updatePermissions: (permissions: DashboardPermissions) => Promise<void>;\n /** Loading state */\n isLoading: boolean;\n /** Updating state */\n isUpdating: boolean;\n /** Error state */\n error: AuthError | null;\n /** Refresh permissions from server */\n fetchPermissions: () => Promise<void>;\n}\n\n/**\n * Hook for managing dashboard permissions per role.\n *\n * Allows org owners to configure which dashboard sections each role can access.\n * - Owner always has full access (not configurable)\n * - Admin and Member roles are configurable\n *\n * @example\n * ```tsx\n * function AdminDashboard() {\n * const { canAccess, permissions, updatePermissions } = useDashboardPermissions();\n *\n * // Check if current user can access a section\n * if (!canAccess('deposits')) {\n * return <div>You don't have access to deposits</div>;\n * }\n *\n * // Update permissions (owner only)\n * const toggleMemberDeposits = () => {\n * updatePermissions({\n * ...permissions,\n * member: { ...permissions.member, deposits: !permissions.member.deposits },\n * });\n * };\n * }\n * ```\n */\nexport function useDashboardPermissions(): UseDashboardPermissionsReturn {\n const { config, authState, _internal } = useCedrosLogin();\n const { activeOrg, role } = useOrgs();\n\n const [permissions, setPermissions] = useState<DashboardPermissions>(\n DEFAULT_DASHBOARD_PERMISSIONS\n );\n const [isLoading, setIsLoading] = useState(false);\n const [isUpdating, setIsUpdating] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n const requestIdRef = useRef(0);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n getAccessToken: _internal?.getAccessToken,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts, _internal]\n );\n\n // Use ref to avoid apiClient in callback dependencies\n const apiClientRef = useRef(apiClient);\n apiClientRef.current = apiClient;\n\n const fetchPermissions = useCallback(async () => {\n if (authState !== 'authenticated' || !activeOrg) {\n setPermissions(DEFAULT_DASHBOARD_PERMISSIONS);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n const requestId = ++requestIdRef.current;\n\n try {\n const response = await apiClientRef.current.get<{ permissions: DashboardPermissions }>(\n '/admin/dashboard-permissions'\n );\n if (requestId !== requestIdRef.current) return;\n setPermissions(response.permissions);\n } catch (err) {\n if (requestId !== requestIdRef.current) return;\n // If 404, use defaults (permissions not configured yet)\n if (err instanceof Error && err.message.includes('404')) {\n setPermissions(DEFAULT_DASHBOARD_PERMISSIONS);\n } else {\n const message = err instanceof Error ? err.message : 'Failed to fetch permissions';\n setError({ code: 'NETWORK_ERROR', message } as AuthError);\n // Fall back to defaults on error\n setPermissions(DEFAULT_DASHBOARD_PERMISSIONS);\n }\n } finally {\n if (requestId === requestIdRef.current) {\n setIsLoading(false);\n }\n }\n }, [authState, activeOrg]);\n\n const updatePermissions = useCallback(\n async (newPermissions: DashboardPermissions): Promise<void> => {\n if (authState !== 'authenticated' || !activeOrg) {\n throw new Error('Not authenticated');\n }\n\n if (role !== 'owner') {\n throw new Error('Only owners can modify dashboard permissions');\n }\n\n setIsUpdating(true);\n setError(null);\n\n try {\n await apiClientRef.current.request<{ permissions: DashboardPermissions }>({\n method: 'PUT',\n path: '/admin/dashboard-permissions',\n body: newPermissions,\n });\n setPermissions(newPermissions);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to update permissions';\n const authError = { code: 'NETWORK_ERROR', message } as AuthError;\n setError(authError);\n throw new Error(message);\n } finally {\n setIsUpdating(false);\n }\n },\n [authState, activeOrg, role]\n );\n\n /**\n * Check if the current user can access a dashboard section\n * - No org context (system admin): full access (permissions are org-scoped)\n * - Owner: always has full access\n * - Admin: check permissions.admin[section]\n * - Member: check permissions.member[section]\n */\n const canAccess = useCallback(\n (section: DashboardSection): boolean => {\n // No org context = system admin level, allow all\n // (dashboard permissions are org-scoped, not system-scoped)\n if (!activeOrg || !role) {\n return true;\n }\n\n // Owner always has full access\n if (role === 'owner') {\n return true;\n }\n\n // Admin and member: check configured permissions\n const rolePermissions = permissions[role as 'admin' | 'member'];\n return rolePermissions?.[section] ?? false;\n },\n [activeOrg, role, permissions]\n );\n\n // Fetch permissions when org changes\n useEffect(() => {\n if (activeOrg?.id) {\n fetchPermissions();\n }\n }, [activeOrg?.id, fetchPermissions]);\n\n return {\n permissions,\n canAccess,\n updatePermissions,\n isLoading,\n isUpdating,\n error,\n fetchPermissions,\n };\n}\n","import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { useSystemSettings } from './useSystemSettings';\n\n/**\n * Server-side feature flags stored in system settings.\n *\n * These control which features are available in the application.\n * Unlike client-side FeatureFlags (passed to CedrosLoginProvider),\n * these can be toggled at runtime via the admin dashboard.\n *\n * **Cosmetic vs enforced:**\n * Some flags only affect UI visibility (cosmetic) while others are\n * enforced server-side. See per-field docs below.\n *\n * Settings that are enforced per-request by the server (hard 403 if disabled):\n * `auth_email_enabled`, `auth_google_enabled`, `auth_apple_enabled`,\n * `auth_instantlink_enabled`, `feature_user_withdrawals`, `privacy_period_secs`,\n * withdrawal worker settings, and deposit fee settings.\n *\n * Settings applied at server startup (take effect after restart):\n * `security_cors_origins`, `rate_limit_*`, `auth_webauthn_*`, `webhook_*`.\n */\nexport interface ServerFeatures {\n /**\n * Enable multi-tenant organizations. Controls: Team, Invites sections.\n *\n * **Cosmetic** — org endpoints are always reachable server-side.\n * This flag only controls admin dashboard section visibility.\n */\n organizations: boolean;\n /** Enable Enterprise SSO for organizations. Startup-config enforced. */\n sso: boolean;\n /**\n * Enable two-factor authentication (TOTP).\n *\n * **Cosmetic** — MFA is actually gated by whether the user has TOTP\n * enrolled (`has_mfa_enabled()`), not by this flag. This controls\n * admin dashboard visibility only.\n */\n mfa: boolean;\n /**\n * Require email/password users to set up TOTP two-factor authentication.\n *\n * **Enforced** — the server returns a `setup_mfa` post-login action for\n * password users who haven't enrolled TOTP. Works independently of `mfa`\n * (which only controls UI visibility).\n */\n mfaRequired: boolean;\n /** Enable embedded wallet for transaction signing. Startup-config enforced. */\n walletSigning: boolean;\n /**\n * Enable deposits and credits system.\n * Controls: Deposits, Withdrawals, Credit System admin sections.\n * Deposit/withdrawal endpoints are enforced server-side.\n */\n credits: boolean;\n /**\n * Enable user withdrawals from embedded wallet to external addresses.\n * **Enforced** — server returns 403 on withdrawal endpoints when disabled.\n */\n userWithdrawals: boolean;\n /**\n * Enable Cedros Pay integration.\n * Controls: Products, Transactions, Refunds admin sections.\n *\n * **Cosmetic** — only controls admin dashboard tab visibility.\n */\n cedrosPay: boolean;\n}\n\n/**\n * Default feature values when settings haven't loaded yet.\n * All features disabled by default for safety.\n */\nconst DEFAULT_FEATURES: ServerFeatures = {\n organizations: false,\n sso: false,\n mfa: false,\n mfaRequired: false,\n walletSigning: false,\n credits: false,\n userWithdrawals: false,\n cedrosPay: false,\n};\n\nexport interface UseServerFeaturesReturn {\n /** Current feature flag states */\n features: ServerFeatures;\n /** Whether settings are still loading */\n isLoading: boolean;\n /** Error if settings failed to load */\n error: Error | null;\n /** Refresh feature flags from server */\n refetch: () => Promise<void>;\n /** Check if a specific feature is enabled */\n isEnabled: (feature: keyof ServerFeatures) => boolean;\n}\n\n/**\n * Hook for reading server-side feature flags from system settings.\n *\n * Use this to conditionally show/hide features based on admin settings.\n *\n * @example\n * ```tsx\n * function AdminDashboard() {\n * const { features, isLoading, isEnabled } = useServerFeatures();\n *\n * if (isLoading) return <LoadingSpinner />;\n *\n * return (\n * <nav>\n * {isEnabled('organizations') && <NavItem>Team</NavItem>}\n * {isEnabled('credits') && <NavItem>Deposits</NavItem>}\n * </nav>\n * );\n * }\n * ```\n */\nexport function useServerFeatures(): UseServerFeaturesReturn {\n const { settings, isLoading, error, fetchSettings, getValue } = useSystemSettings();\n const [hasFetched, setHasFetched] = useState(false);\n\n // Fetch settings on mount\n useEffect(() => {\n if (!hasFetched) {\n fetchSettings();\n setHasFetched(true);\n }\n }, [fetchSettings, hasFetched]);\n\n // Parse boolean value from string setting\n const parseBoolean = useCallback((value: string | undefined): boolean => {\n if (value === undefined) return false;\n return value === 'true' || value === '1';\n }, []);\n\n // Derive features from settings\n const features = useMemo<ServerFeatures>(() => {\n // If no settings loaded yet, return defaults\n if (Object.keys(settings).length === 0) {\n return DEFAULT_FEATURES;\n }\n\n return {\n organizations: parseBoolean(getValue('feature_organizations')),\n sso: parseBoolean(getValue('feature_sso')),\n mfa: parseBoolean(getValue('feature_mfa')),\n mfaRequired: parseBoolean(getValue('security_require_mfa')),\n walletSigning: parseBoolean(getValue('feature_wallet_signing')),\n credits: parseBoolean(getValue('feature_credits')),\n userWithdrawals: parseBoolean(getValue('feature_user_withdrawals')),\n cedrosPay: parseBoolean(getValue('feature_cedros_pay')),\n };\n }, [settings, getValue, parseBoolean]);\n\n const refetch = useCallback(async () => {\n await fetchSettings();\n }, [fetchSettings]);\n\n const isEnabled = useCallback(\n (feature: keyof ServerFeatures): boolean => {\n return features[feature];\n },\n [features]\n );\n\n return {\n features,\n isLoading,\n error,\n refetch,\n isEnabled,\n };\n}\n","/**\n * PermissionsSection - Dashboard permissions matrix for role configuration\n *\n * Allows org owners to configure which dashboard sections each role can access.\n */\n\nimport React, { useCallback, useRef, useEffect } from 'react';\nimport { useDashboardPermissions } from '../../hooks/useDashboardPermissions';\nimport { useServerFeatures } from '../../hooks/useServerFeatures';\nimport {\n LOGIN_DASHBOARD_SECTIONS,\n PAY_DASHBOARD_SECTIONS,\n DASHBOARD_SECTION_LABELS,\n type DashboardSection,\n type DashboardPermissions,\n type OrgRole,\n} from '../../types/org';\n\ninterface PermissionToggleProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n label: string;\n}\n\nfunction PermissionToggle({ checked, onChange, disabled, label }: PermissionToggleProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n disabled={disabled}\n className={`cedros-toggle cedros-toggle-sm ${checked ? 'cedros-toggle-on' : 'cedros-toggle-off'} ${disabled ? 'cedros-toggle-disabled' : ''}`}\n onClick={() => !disabled && onChange(!checked)}\n >\n <span className=\"cedros-toggle-track\">\n <span className=\"cedros-toggle-thumb\" />\n </span>\n </button>\n );\n}\n\nexport interface PermissionsSectionProps {\n /** Current user's role in the org */\n userRole?: OrgRole | null;\n}\n\nexport function PermissionsSection({ userRole }: PermissionsSectionProps): React.JSX.Element {\n const { permissions, updatePermissions, isLoading, isUpdating, error } =\n useDashboardPermissions();\n const { features, isLoading: featuresLoading } = useServerFeatures();\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingPermissions = useRef<DashboardPermissions | null>(null);\n\n const isOwner = userRole === 'owner';\n const cedrosPayEnabled = features.cedrosPay;\n\n // Debounced save - batch rapid changes\n const debouncedSave = useCallback(\n (newPermissions: DashboardPermissions) => {\n pendingPermissions.current = newPermissions;\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n debounceRef.current = setTimeout(() => {\n if (pendingPermissions.current) {\n updatePermissions(pendingPermissions.current).catch(() => {\n // Error is already set in state by the hook\n });\n pendingPermissions.current = null;\n }\n }, 500);\n },\n [updatePermissions]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, []);\n\n const handleToggle = useCallback(\n (role: 'admin' | 'member', section: DashboardSection, enabled: boolean) => {\n const newPermissions: DashboardPermissions = {\n ...permissions,\n [role]: {\n ...permissions[role],\n [section]: enabled,\n },\n };\n debouncedSave(newPermissions);\n },\n [permissions, debouncedSave]\n );\n\n if (isLoading || featuresLoading) {\n return (\n <div className=\"cedros-dashboard__section\">\n <div className=\"cedros-dashboard__loading\">Loading permissions...</div>\n </div>\n );\n }\n\n if (!isOwner) {\n return (\n <div className=\"cedros-dashboard__section\">\n <div className=\"cedros-dashboard__empty\">\n Only organization owners can configure dashboard permissions.\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"cedros-dashboard__section cedros-permissions-section\">\n <div className=\"cedros-permissions-header\">\n <p className=\"cedros-permissions-description\">\n Configure which dashboard sections each role can access. Owners always have full access.\n </p>\n {error && <div className=\"cedros-permissions-error\">{error.message}</div>}\n {isUpdating && <span className=\"cedros-permissions-saving\">Saving...</span>}\n </div>\n\n <div className=\"cedros-permissions-matrix\">\n <table className=\"cedros-permissions-table\">\n <tbody>\n {/* Cedros Login Sections */}\n <tr className=\"cedros-permissions-group-header\">\n <th className=\"cedros-permissions-section-header\">Cedros Login</th>\n <th className=\"cedros-permissions-role-header\">Admin</th>\n <th className=\"cedros-permissions-role-header\">Member</th>\n </tr>\n {LOGIN_DASHBOARD_SECTIONS.map((section) => (\n <tr key={section} className=\"cedros-permissions-row\">\n <td className=\"cedros-permissions-section-label\">\n {DASHBOARD_SECTION_LABELS[section]}\n </td>\n <td className=\"cedros-permissions-toggle-cell\">\n <PermissionToggle\n checked={permissions.admin[section] ?? false}\n onChange={(enabled) => handleToggle('admin', section, enabled)}\n disabled={isUpdating}\n label={`Admin access to ${DASHBOARD_SECTION_LABELS[section]}`}\n />\n </td>\n <td className=\"cedros-permissions-toggle-cell\">\n <PermissionToggle\n checked={permissions.member[section] ?? false}\n onChange={(enabled) => handleToggle('member', section, enabled)}\n disabled={isUpdating}\n label={`Member access to ${DASHBOARD_SECTION_LABELS[section]}`}\n />\n </td>\n </tr>\n ))}\n\n {/* Cedros Pay Sections (only when cedrosPay feature is enabled) */}\n {cedrosPayEnabled && (\n <>\n <tr className=\"cedros-permissions-group-header\">\n <th className=\"cedros-permissions-section-header\">Cedros Pay</th>\n <th className=\"cedros-permissions-role-header\">Admin</th>\n <th className=\"cedros-permissions-role-header\">Member</th>\n </tr>\n {PAY_DASHBOARD_SECTIONS.map((section) => (\n <tr key={section} className=\"cedros-permissions-row\">\n <td className=\"cedros-permissions-section-label\">\n {DASHBOARD_SECTION_LABELS[section]}\n </td>\n <td className=\"cedros-permissions-toggle-cell\">\n <PermissionToggle\n checked={permissions.admin[section] ?? false}\n onChange={(enabled) => handleToggle('admin', section, enabled)}\n disabled={isUpdating}\n label={`Admin access to ${DASHBOARD_SECTION_LABELS[section]}`}\n />\n </td>\n <td className=\"cedros-permissions-toggle-cell\">\n <PermissionToggle\n checked={permissions.member[section] ?? false}\n onChange={(enabled) => handleToggle('member', section, enabled)}\n disabled={isUpdating}\n label={`Member access to ${DASHBOARD_SECTION_LABELS[section]}`}\n />\n </td>\n </tr>\n ))}\n </>\n )}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n"],"names":["ROLE_OPTIONS","MemberList","members","currentUserId","isLoading","error","canManage","canChangeRoles","onUpdateRole","onRemove","className","sortField","setSortField","useState","sortOrder","setSortOrder","toggleSort","field","sortedMembers","useMemo","roleOrder","a","aVal","bVal","jsxs","jsx","LoadingSpinner","ErrorMessage","member","MemberRow","isCurrentUser","isUpdating","setIsUpdating","selectedRole","setSelectedRole","handleRoleChange","useCallback","newRole","handleRemove","isOwner","canModify","MemberAvatar","e","role","formatDate","user","sanitizedPicture","sanitizeImageUrl","initial","dateString","DEFAULT_ROLES","InviteForm","onSubmit","availableRoles","defaultRole","email","setEmail","setRole","formError","setFormError","success","setSuccess","successTimerRef","useRef","isMountedRef","useEffect","handleSubmit","trimmedEmail","validateEmail","CheckIcon","r","InviteList","invites","onCancel","onResend","invite","InviteItem","resendSuccess","setResendSuccess","resendTimerRef","isExpired","handleCancel","handleResend","formatRelativeTime","date","now","diffMs","diffDays","MemberApiClient","baseUrl","timeoutMs","retryAttempts","getAccessToken","ApiClient","orgId","limit","offset","response","handleApiError","userId","data","useMembers","config","authState","_internal","useCedrosLogin","setMembers","total","setTotal","setIsLoading","setError","fetchedOrgIdRef","requestIdRef","apiClient","apiClientRef","fetchMembers","options","requestId","err","updateMemberRole","removeMember","InviteApiClient","inviteId","useInvites","setInvites","fetchInvites","createInvite","cancelInvite","resendInvite","acceptInvite","token","LOGIN_DASHBOARD_SECTIONS","PAY_DASHBOARD_SECTIONS","DASHBOARD_SECTION_LABELS","DEFAULT_DASHBOARD_PERMISSIONS","useDashboardPermissions","activeOrg","useOrgs","permissions","setPermissions","fetchPermissions","message","updatePermissions","newPermissions","canAccess","section","DEFAULT_FEATURES","useServerFeatures","settings","fetchSettings","getValue","useSystemSettings","hasFetched","setHasFetched","parseBoolean","value","features","refetch","isEnabled","feature","PermissionToggle","checked","onChange","disabled","label","PermissionsSection","userRole","featuresLoading","debounceRef","pendingPermissions","cedrosPayEnabled","debouncedSave","handleToggle","enabled","Fragment"],"mappings":"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"}
@@ -4,10 +4,10 @@ import { L as O } from "./LoadingSpinner-6vml-zwr.js";
4
4
  import { E as P } from "./ErrorMessage-CcEK0pYO.js";
5
5
  import { a as B } from "./sanitization-CQ-H1MSg.js";
6
6
  import { b as W } from "./validation-B8kMV3BL.js";
7
- import { A as F, h as R, u as U } from "./useCedrosLogin-CFfID-0i.js";
7
+ import { A as F, h as _, u as U } from "./useCedrosLogin-CFfID-0i.js";
8
8
  import { u as H } from "./useOrgs-C90KT9KP.js";
9
9
  import { u as V } from "./useSystemSettings-rgskaDqP.js";
10
- const K = ["owner", "admin", "member"];
10
+ const G = ["owner", "admin", "member"];
11
11
  function ye({
12
12
  members: e,
13
13
  currentUserId: r,
@@ -88,7 +88,7 @@ function ye({
88
88
  (t || c) && /* @__PURE__ */ s("th", { children: "Actions" })
89
89
  ] }) }),
90
90
  /* @__PURE__ */ s("tbody", { children: i.map((d) => /* @__PURE__ */ s(
91
- G,
91
+ K,
92
92
  {
93
93
  member: d,
94
94
  isCurrentUser: d.userId === r,
@@ -101,7 +101,7 @@ function ye({
101
101
  )) })
102
102
  ] }) });
103
103
  }
104
- function G({
104
+ function K({
105
105
  member: e,
106
106
  isCurrentUser: r,
107
107
  canManage: n,
@@ -153,10 +153,10 @@ function G({
153
153
  onChange: (i) => E(i.target.value),
154
154
  disabled: f,
155
155
  className: "cedros-role-select",
156
- children: K.map((i) => /* @__PURE__ */ s("option", { value: i, children: i.charAt(0).toUpperCase() + i.slice(1) }, i))
156
+ children: G.map((i) => /* @__PURE__ */ s("option", { value: i, children: i.charAt(0).toUpperCase() + i.slice(1) }, i))
157
157
  }
158
158
  ) : /* @__PURE__ */ s("span", { className: `cedros-role-badge cedros-role-badge-${e.role}`, children: e.role.charAt(0).toUpperCase() + e.role.slice(1) }) }),
159
- /* @__PURE__ */ s("td", { className: "cedros-member-joined", children: Y(e.joinedAt) }),
159
+ /* @__PURE__ */ s("td", { className: "cedros-member-joined", children: Q(e.joinedAt) }),
160
160
  (n || a) && /* @__PURE__ */ s("td", { className: "cedros-member-actions", children: n && p && c && /* @__PURE__ */ s(
161
161
  "button",
162
162
  {
@@ -185,19 +185,19 @@ function J({ user: e }) {
185
185
  const n = (e.name?.[0] || e.email?.[0] || "?").toUpperCase();
186
186
  return /* @__PURE__ */ s("div", { className: "cedros-member-avatar-placeholder", children: n });
187
187
  }
188
- function Y(e) {
188
+ function Q(e) {
189
189
  return new Date(e).toLocaleDateString(void 0, {
190
190
  year: "numeric",
191
191
  month: "short",
192
192
  day: "numeric"
193
193
  });
194
194
  }
195
- const Q = ["admin", "member"];
195
+ const Y = ["admin", "member"];
196
196
  function we({
197
197
  onSubmit: e,
198
198
  isLoading: r = !1,
199
199
  error: n,
200
- availableRoles: a = Q,
200
+ availableRoles: a = Y,
201
201
  defaultRole: t = "member",
202
202
  className: c = ""
203
203
  }) {
@@ -358,7 +358,7 @@ function Z({ invite: e, canManage: r, onCancel: n, onResend: a }) {
358
358
  /* @__PURE__ */ h("div", { className: "cedros-invite-item-meta", children: [
359
359
  /* @__PURE__ */ h("span", { className: "cedros-invite-item-date", children: [
360
360
  "Invited ",
361
- q(e.createdAt)
361
+ x(e.createdAt)
362
362
  ] }),
363
363
  !o && /* @__PURE__ */ h("span", { className: "cedros-invite-item-expires", children: [
364
364
  "Expires ",
@@ -393,7 +393,7 @@ function Z({ invite: e, canManage: r, onCancel: n, onResend: a }) {
393
393
  ] })
394
394
  ] });
395
395
  }
396
- function q(e) {
396
+ function x(e) {
397
397
  return new Date(e).toLocaleDateString(void 0, {
398
398
  year: "numeric",
399
399
  month: "short",
@@ -402,7 +402,7 @@ function q(e) {
402
402
  }
403
403
  function ee(e) {
404
404
  const r = new Date(e), n = /* @__PURE__ */ new Date(), a = r.getTime() - n.getTime(), t = Math.ceil(a / (1e3 * 60 * 60 * 24));
405
- return t < 0 ? "expired" : t === 0 ? "today" : t === 1 ? "tomorrow" : t < 7 ? `in ${t} days` : q(e);
405
+ return t < 0 ? "expired" : t === 0 ? "today" : t === 1 ? "tomorrow" : t < 7 ? `in ${t} days` : x(e);
406
406
  }
407
407
  class se {
408
408
  client;
@@ -433,7 +433,7 @@ class se {
433
433
  total: t.total
434
434
  };
435
435
  } catch (t) {
436
- throw R(t, "Failed to list members");
436
+ throw _(t, "Failed to list members");
437
437
  }
438
438
  }
439
439
  /**
@@ -443,7 +443,7 @@ class se {
443
443
  try {
444
444
  return await this.client.patch(`/orgs/${r}/members/${n}`, a);
445
445
  } catch (t) {
446
- throw R(t, "Failed to update member role");
446
+ throw _(t, "Failed to update member role");
447
447
  }
448
448
  }
449
449
  /**
@@ -453,7 +453,7 @@ class se {
453
453
  try {
454
454
  await this.client.delete(`/orgs/${r}/members/${n}`);
455
455
  } catch (a) {
456
- throw R(a, "Failed to remove member");
456
+ throw _(a, "Failed to remove member");
457
457
  }
458
458
  }
459
459
  }
@@ -477,9 +477,9 @@ function be(e) {
477
477
  o(!0), l(null);
478
478
  const N = ++p.current;
479
479
  try {
480
- const { limit: A = 50, offset: T = 0 } = b ?? {}, _ = await d.current.listMembers(e, A, T);
480
+ const { limit: A = 50, offset: T = 0 } = b ?? {}, R = await d.current.listMembers(e, A, T);
481
481
  if (N !== p.current) return;
482
- c(_.members), u(_.total);
482
+ c(R.members), u(R.total);
483
483
  } catch (A) {
484
484
  if (N !== p.current) return;
485
485
  l(A);
@@ -561,7 +561,7 @@ class re {
561
561
  total: t.total
562
562
  };
563
563
  } catch (t) {
564
- throw R(t, "Failed to list invites");
564
+ throw _(t, "Failed to list invites");
565
565
  }
566
566
  }
567
567
  /**
@@ -571,7 +571,7 @@ class re {
571
571
  try {
572
572
  return await this.client.post(`/orgs/${r}/invites`, n);
573
573
  } catch (a) {
574
- throw R(a, "Failed to create invite");
574
+ throw _(a, "Failed to create invite");
575
575
  }
576
576
  }
577
577
  /**
@@ -581,7 +581,7 @@ class re {
581
581
  try {
582
582
  await this.client.delete(`/orgs/${r}/invites/${n}`);
583
583
  } catch (a) {
584
- throw R(a, "Failed to cancel invite");
584
+ throw _(a, "Failed to cancel invite");
585
585
  }
586
586
  }
587
587
  /**
@@ -591,7 +591,7 @@ class re {
591
591
  try {
592
592
  await this.client.post(`/orgs/${r}/invites/${n}/resend`, {});
593
593
  } catch (a) {
594
- throw R(a, "Failed to resend invite");
594
+ throw _(a, "Failed to resend invite");
595
595
  }
596
596
  }
597
597
  /**
@@ -601,7 +601,7 @@ class re {
601
601
  try {
602
602
  return await this.client.post("/invites/accept", r);
603
603
  } catch (n) {
604
- throw R(n, "Failed to accept invite");
604
+ throw _(n, "Failed to accept invite");
605
605
  }
606
606
  }
607
607
  }
@@ -625,12 +625,12 @@ function Ne(e) {
625
625
  o(!0), l(null);
626
626
  const T = ++p.current;
627
627
  try {
628
- const { limit: _ = 50, offset: z = 0 } = A ?? {}, x = await d.current.listInvites(e, _, z);
628
+ const { limit: R = 50, offset: z = 0 } = A ?? {}, q = await d.current.listInvites(e, R, z);
629
629
  if (T !== p.current) return;
630
- c(x.invites), u(x.total);
631
- } catch (_) {
630
+ c(q.invites), u(q.total);
631
+ } catch (R) {
632
632
  if (T !== p.current) return;
633
- l(_);
633
+ l(R);
634
634
  } finally {
635
635
  T === p.current && o(!1);
636
636
  }
@@ -651,8 +651,8 @@ function Ne(e) {
651
651
  o(!0), l(null);
652
652
  try {
653
653
  await d.current.createInvite(e, { email: A, role: T }), await g();
654
- } catch (_) {
655
- throw l(_), _;
654
+ } catch (R) {
655
+ throw l(R), R;
656
656
  } finally {
657
657
  o(!1);
658
658
  }
@@ -708,57 +708,24 @@ function Ne(e) {
708
708
  acceptInvite: N
709
709
  };
710
710
  }
711
- const te = {
712
- organizations: !1,
713
- sso: !1,
714
- mfa: !1,
715
- mfaRequired: !1,
716
- walletSigning: !1,
717
- credits: !1,
718
- userWithdrawals: !1,
719
- cedrosPay: !1
720
- };
721
- function ne() {
722
- const { settings: e, isLoading: r, error: n, fetchSettings: a, getValue: t } = V(), [c, f] = v(!1);
723
- I(() => {
724
- c || (a(), f(!0));
725
- }, [a, c]);
726
- const u = S((l) => l === void 0 ? !1 : l === "true" || l === "1", []), m = M(() => Object.keys(e).length === 0 ? te : {
727
- organizations: u(t("feature_organizations")),
728
- sso: u(t("feature_sso")),
729
- mfa: u(t("feature_mfa")),
730
- mfaRequired: u(t("security_require_mfa")),
731
- walletSigning: u(t("feature_wallet_signing")),
732
- credits: u(t("feature_credits")),
733
- userWithdrawals: u(t("feature_user_withdrawals")),
734
- cedrosPay: u(t("feature_cedros_pay"))
735
- }, [e, t, u]), o = S(async () => {
736
- await a();
737
- }, [a]), E = S(
738
- (l) => m[l],
739
- [m]
740
- );
741
- return {
742
- features: m,
743
- isLoading: r,
744
- error: n,
745
- refetch: o,
746
- isEnabled: E
747
- };
748
- }
749
- const ae = [
711
+ const te = [
750
712
  "users",
751
713
  "team",
752
714
  "referrals",
753
715
  "deposits",
754
716
  "withdrawals",
717
+ "compliance",
718
+ "accreditation-queue",
719
+ "sanctions",
755
720
  "settings-wallet",
756
721
  "settings-auth",
757
722
  "settings-messaging",
758
723
  "settings-credits",
724
+ "settings-compliance",
725
+ "settings-referrals",
759
726
  "settings-server",
760
727
  "settings-images"
761
- ], ie = [
728
+ ], ne = [
762
729
  "pay-products",
763
730
  "pay-subscriptions",
764
731
  "pay-transactions",
@@ -776,10 +743,15 @@ const ae = [
776
743
  referrals: "Referrals",
777
744
  deposits: "Deposits",
778
745
  withdrawals: "Withdrawals",
746
+ compliance: "Compliance",
747
+ "accreditation-queue": "Accreditation Queue",
748
+ sanctions: "Sanctions",
779
749
  "settings-wallet": "Wallet Settings",
780
750
  "settings-auth": "Auth Settings",
781
751
  "settings-messaging": "Messages Settings",
782
752
  "settings-credits": "Credits Settings",
753
+ "settings-compliance": "Compliance & Gating",
754
+ "settings-referrals": "Referrals & Rewards",
783
755
  "settings-server": "Server Settings",
784
756
  "settings-images": "Image Storage",
785
757
  // Cedros Pay
@@ -801,10 +773,15 @@ const ae = [
801
773
  referrals: !0,
802
774
  deposits: !0,
803
775
  withdrawals: !0,
776
+ compliance: !0,
777
+ "accreditation-queue": !0,
778
+ sanctions: !0,
804
779
  "settings-wallet": !0,
805
780
  "settings-auth": !0,
806
781
  "settings-messaging": !0,
807
782
  "settings-credits": !0,
783
+ "settings-compliance": !0,
784
+ "settings-referrals": !0,
808
785
  "settings-server": !0,
809
786
  "settings-images": !0,
810
787
  // Cedros Pay
@@ -826,10 +803,15 @@ const ae = [
826
803
  referrals: !1,
827
804
  deposits: !1,
828
805
  withdrawals: !1,
806
+ compliance: !1,
807
+ "accreditation-queue": !1,
808
+ sanctions: !1,
829
809
  "settings-wallet": !1,
830
810
  "settings-auth": !1,
831
811
  "settings-messaging": !1,
832
812
  "settings-credits": !1,
813
+ "settings-compliance": !1,
814
+ "settings-referrals": !1,
833
815
  "settings-server": !1,
834
816
  "settings-images": !1,
835
817
  // Cedros Pay
@@ -845,7 +827,7 @@ const ae = [
845
827
  "pay-settings": !1
846
828
  }
847
829
  };
848
- function ce() {
830
+ function ae() {
849
831
  const { config: e, authState: r, _internal: n } = U(), { activeOrg: a, role: t } = H(), [c, f] = v(
850
832
  k
851
833
  ), [u, m] = v(!1), [o, E] = v(!1), [l, y] = v(null), p = C(0), i = M(
@@ -919,6 +901,44 @@ function ce() {
919
901
  fetchPermissions: g
920
902
  };
921
903
  }
904
+ const ie = {
905
+ organizations: !1,
906
+ sso: !1,
907
+ mfa: !1,
908
+ mfaRequired: !1,
909
+ walletSigning: !1,
910
+ credits: !1,
911
+ userWithdrawals: !1,
912
+ cedrosPay: !1
913
+ };
914
+ function ce() {
915
+ const { settings: e, isLoading: r, error: n, fetchSettings: a, getValue: t } = V(), [c, f] = v(!1);
916
+ I(() => {
917
+ c || (a(), f(!0));
918
+ }, [a, c]);
919
+ const u = S((l) => l === void 0 ? !1 : l === "true" || l === "1", []), m = M(() => Object.keys(e).length === 0 ? ie : {
920
+ organizations: u(t("feature_organizations")),
921
+ sso: u(t("feature_sso")),
922
+ mfa: u(t("feature_mfa")),
923
+ mfaRequired: u(t("security_require_mfa")),
924
+ walletSigning: u(t("feature_wallet_signing")),
925
+ credits: u(t("feature_credits")),
926
+ userWithdrawals: u(t("feature_user_withdrawals")),
927
+ cedrosPay: u(t("feature_cedros_pay"))
928
+ }, [e, t, u]), o = S(async () => {
929
+ await a();
930
+ }, [a]), E = S(
931
+ (l) => m[l],
932
+ [m]
933
+ );
934
+ return {
935
+ features: m,
936
+ isLoading: r,
937
+ error: n,
938
+ refetch: o,
939
+ isEnabled: E
940
+ };
941
+ }
922
942
  function D({ checked: e, onChange: r, disabled: n, label: a }) {
923
943
  return /* @__PURE__ */ s(
924
944
  "button",
@@ -935,7 +955,7 @@ function D({ checked: e, onChange: r, disabled: n, label: a }) {
935
955
  );
936
956
  }
937
957
  function Ae({ userRole: e }) {
938
- const { permissions: r, updatePermissions: n, isLoading: a, isUpdating: t, error: c } = ce(), { features: f, isLoading: u } = ne(), m = C(null), o = C(null), E = e === "owner", l = f.cedrosPay, y = S(
958
+ const { permissions: r, updatePermissions: n, isLoading: a, isUpdating: t, error: c } = ae(), { features: f, isLoading: u } = ce(), m = C(null), o = C(null), E = e === "owner", l = f.cedrosPay, y = S(
939
959
  (i) => {
940
960
  o.current = i, m.current && clearTimeout(m.current), m.current = setTimeout(() => {
941
961
  o.current && (n(o.current).catch(() => {
@@ -972,7 +992,7 @@ function Ae({ userRole: e }) {
972
992
  /* @__PURE__ */ s("th", { className: "cedros-permissions-role-header", children: "Admin" }),
973
993
  /* @__PURE__ */ s("th", { className: "cedros-permissions-role-header", children: "Member" })
974
994
  ] }),
975
- ae.map((i) => /* @__PURE__ */ h("tr", { className: "cedros-permissions-row", children: [
995
+ te.map((i) => /* @__PURE__ */ h("tr", { className: "cedros-permissions-row", children: [
976
996
  /* @__PURE__ */ s("td", { className: "cedros-permissions-section-label", children: L[i] }),
977
997
  /* @__PURE__ */ s("td", { className: "cedros-permissions-toggle-cell", children: /* @__PURE__ */ s(
978
998
  D,
@@ -999,7 +1019,7 @@ function Ae({ userRole: e }) {
999
1019
  /* @__PURE__ */ s("th", { className: "cedros-permissions-role-header", children: "Admin" }),
1000
1020
  /* @__PURE__ */ s("th", { className: "cedros-permissions-role-header", children: "Member" })
1001
1021
  ] }),
1002
- ie.map((i) => /* @__PURE__ */ h("tr", { className: "cedros-permissions-row", children: [
1022
+ ne.map((i) => /* @__PURE__ */ h("tr", { className: "cedros-permissions-row", children: [
1003
1023
  /* @__PURE__ */ s("td", { className: "cedros-permissions-section-label", children: L[i] }),
1004
1024
  /* @__PURE__ */ s("td", { className: "cedros-permissions-toggle-cell", children: /* @__PURE__ */ s(
1005
1025
  D,
@@ -1030,7 +1050,7 @@ export {
1030
1050
  Ae as P,
1031
1051
  Ne as a,
1032
1052
  ve as b,
1033
- ne as c,
1034
- ce as d,
1053
+ ce as c,
1054
+ ae as d,
1035
1055
  be as u
1036
1056
  };