@elevasis/ui 2.36.0 → 2.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/api/index.js +4 -3
  2. package/dist/app/index.css +0 -384
  3. package/dist/app/index.d.ts +75 -2
  4. package/dist/app/index.js +22 -21
  5. package/dist/auth/index.d.ts +91 -28
  6. package/dist/auth/index.js +5 -1
  7. package/dist/charts/index.js +9 -3
  8. package/dist/chunk-4O3VAALW.js +349 -0
  9. package/dist/{chunk-O2Q4VMRN.js → chunk-566XWGPP.js} +76 -109
  10. package/dist/chunk-5EYJ2GIN.js +122 -0
  11. package/dist/chunk-6D4LCJ52.js +10 -0
  12. package/dist/chunk-6ROXVZ3L.js +9 -0
  13. package/dist/{chunk-YYX7OPZQ.js → chunk-73EWE2EW.js} +1 -1
  14. package/dist/{chunk-SIQ3P4OR.js → chunk-7GQFIWP4.js} +8 -756
  15. package/dist/{chunk-VKIZUUPM.js → chunk-7YXZFS56.js} +31 -14
  16. package/dist/{chunk-AKW7KISS.js → chunk-7ZWXTH5J.js} +2 -44
  17. package/dist/chunk-A7IG36LB.js +215 -0
  18. package/dist/chunk-B2DZLPDL.js +39 -0
  19. package/dist/chunk-C6BDBZRO.js +422 -0
  20. package/dist/chunk-CLDCYJQT.js +1 -0
  21. package/dist/{chunk-LUYVRATI.js → chunk-DA6I5VEY.js} +5 -213
  22. package/dist/chunk-H2MEFUQD.js +337 -0
  23. package/dist/chunk-I53EX4VU.js +734 -0
  24. package/dist/chunk-IIMU5YAJ.js +53 -0
  25. package/dist/chunk-JXVNHVK7.js +79 -0
  26. package/dist/chunk-M7Q4UBRY.js +85 -0
  27. package/dist/{chunk-K4UZU3TU.js → chunk-P34FFSOX.js} +1 -1
  28. package/dist/chunk-PGWANFNE.js +112 -0
  29. package/dist/{chunk-F6EFC2MJ.js → chunk-Q64E2TZY.js} +440 -2075
  30. package/dist/chunk-S3XR4II4.js +30 -0
  31. package/dist/chunk-SHZT7ULK.js +425 -0
  32. package/dist/{chunk-GX6XBRRF.js → chunk-TYRUKGGD.js} +2 -1
  33. package/dist/{chunk-R3VCBZDC.js → chunk-X4WBGKJQ.js} +3 -50
  34. package/dist/{chunk-GEFWMU26.js → chunk-X66MVMZT.js} +1 -9
  35. package/dist/{chunk-57OZ3AEG.js → chunk-Y3JQBSKQ.js} +1 -1
  36. package/dist/components/index.d.ts +74 -42
  37. package/dist/components/index.js +34 -19
  38. package/dist/components/navigation/index.js +3 -31
  39. package/dist/features/auth/index.d.ts +97 -99
  40. package/dist/features/auth/index.js +37 -99
  41. package/dist/features/clients/index.js +34 -19
  42. package/dist/features/crm/index.d.ts +65 -0
  43. package/dist/features/crm/index.js +34 -19
  44. package/dist/features/dashboard/index.js +34 -19
  45. package/dist/features/delivery/index.d.ts +65 -0
  46. package/dist/features/delivery/index.js +34 -19
  47. package/dist/features/knowledge/index.js +6 -30
  48. package/dist/features/lead-gen/index.d.ts +1096 -1
  49. package/dist/features/lead-gen/index.js +34 -19
  50. package/dist/features/monitoring/index.js +34 -19
  51. package/dist/features/monitoring/requests/index.js +34 -19
  52. package/dist/features/notes/index.d.ts +72 -0
  53. package/dist/features/notes/index.js +621 -0
  54. package/dist/features/operations/index.d.ts +10 -2
  55. package/dist/features/operations/index.js +34 -19
  56. package/dist/features/right-panel-host/index.d.ts +214 -0
  57. package/dist/features/right-panel-host/index.js +639 -0
  58. package/dist/features/seo/index.js +3 -2
  59. package/dist/features/settings/index.d.ts +68 -35
  60. package/dist/features/settings/index.js +34 -19
  61. package/dist/hooks/access/index.d.ts +90 -0
  62. package/dist/hooks/access/index.js +10 -0
  63. package/dist/hooks/delivery/index.d.ts +65 -0
  64. package/dist/hooks/delivery/index.js +34 -19
  65. package/dist/hooks/index.d.ts +1644 -1651
  66. package/dist/hooks/index.js +34 -19
  67. package/dist/hooks/published.d.ts +1644 -1651
  68. package/dist/hooks/published.js +34 -19
  69. package/dist/hooks/user-notes/index.d.ts +57 -0
  70. package/dist/hooks/user-notes/index.js +3 -0
  71. package/dist/index.d.ts +294 -277
  72. package/dist/index.js +35 -20
  73. package/dist/initialization/index.d.ts +65 -19
  74. package/dist/knowledge/index.d.ts +10 -2
  75. package/dist/knowledge/index.js +173 -28
  76. package/dist/layout/index.js +5 -3
  77. package/dist/organization/index.d.ts +0 -19
  78. package/dist/organization/index.js +34 -19
  79. package/dist/profile/index.d.ts +65 -0
  80. package/dist/provider/index.css +0 -384
  81. package/dist/provider/index.d.ts +75 -2
  82. package/dist/provider/index.js +16 -21
  83. package/dist/provider/published.css +0 -523
  84. package/dist/provider/published.d.ts +75 -2
  85. package/dist/provider/published.js +11 -21
  86. package/dist/supabase/index.d.ts +127 -0
  87. package/dist/test-utils/index.d.ts +2 -21
  88. package/dist/test-utils/index.js +5 -18
  89. package/dist/theme/index.js +3 -1
  90. package/dist/types/index.d.ts +115 -59
  91. package/dist/utils/index.js +2 -1
  92. package/package.json +21 -5
  93. package/src/auth/README.md +6 -6
  94. package/dist/components/navigation/index.css +0 -649
  95. package/dist/features/knowledge/index.css +0 -649
@@ -1,7 +1,11 @@
1
- export { AdminGuard, ProtectedRoute, useSessionCheck as useRefocusSessionCheck, useSessionCheck, useStableAccessToken } from '../chunk-VKIZUUPM.js';
1
+ export { AccessGuard, ProtectedRoute, useSessionCheck as useRefocusSessionCheck, useSessionCheck, useStableAccessToken } from '../chunk-7YXZFS56.js';
2
+ export { AccessKeys } from '../chunk-4O3VAALW.js';
3
+ import '../chunk-C6BDBZRO.js';
2
4
  import '../chunk-533DUEQY.js';
5
+ import '../chunk-566XWGPP.js';
3
6
  import '../chunk-DD3CCMCZ.js';
4
7
  import '../chunk-2Q2JQSQO.js';
8
+ import '../chunk-6ROXVZ3L.js';
5
9
  import '../chunk-KJ3QUBNU.js';
6
10
  export { AuthProvider, useAuthContext } from '../chunk-BRJ3QZ4E.js';
7
11
  import '../chunk-I2KLQ2HA.js';
@@ -1,15 +1,21 @@
1
- export { ActivityTrendChart, ChartFrame, CombinedTrendChart, CostTrendChart, CyberAreaChart, CyberDonut, CyberDonutTooltip, CyberLegendItem, HeroStatsRow, getSeriesColor, useCyberColors } from '../chunk-SIQ3P4OR.js';
1
+ export { ActivityTrendChart, ChartFrame, CombinedTrendChart, CostTrendChart, CyberAreaChart, CyberDonut, CyberDonutTooltip, CyberLegendItem, HeroStatsRow, getSeriesColor, useCyberColors } from '../chunk-7GQFIWP4.js';
2
+ import '../chunk-I53EX4VU.js';
2
3
  import '../chunk-3KMDHCAR.js';
4
+ import '../chunk-S3XR4II4.js';
3
5
  import '../chunk-NYBEU5TE.js';
4
6
  import '../chunk-DT3QYZVU.js';
5
7
  import '../chunk-2IFYDILW.js';
6
8
  import '../chunk-Q7DJKLEN.js';
7
- import '../chunk-GEFWMU26.js';
9
+ import '../chunk-X66MVMZT.js';
8
10
  import '../chunk-KRWALB24.js';
9
- import '../chunk-VKIZUUPM.js';
11
+ import '../chunk-7YXZFS56.js';
12
+ import '../chunk-4O3VAALW.js';
13
+ import '../chunk-C6BDBZRO.js';
10
14
  import '../chunk-533DUEQY.js';
15
+ import '../chunk-566XWGPP.js';
11
16
  import '../chunk-DD3CCMCZ.js';
12
17
  import '../chunk-2Q2JQSQO.js';
18
+ import '../chunk-6ROXVZ3L.js';
13
19
  import '../chunk-KJ3QUBNU.js';
14
20
  import '../chunk-BRJ3QZ4E.js';
15
21
  import '../chunk-I2KLQ2HA.js';
@@ -0,0 +1,349 @@
1
+ import { useOptionalElevasisSystems } from './chunk-C6BDBZRO.js';
2
+ import { InitializationContext } from './chunk-533DUEQY.js';
3
+ import { DEFAULT_ORGANIZATION_MODEL, listAllSystems, getSystem } from './chunk-566XWGPP.js';
4
+ import { OrganizationContext } from './chunk-DD3CCMCZ.js';
5
+ import { STALE_TIME_DEFAULT } from './chunk-6ROXVZ3L.js';
6
+ import { ElevasisServiceContext } from './chunk-KJ3QUBNU.js';
7
+ import { useContext, useMemo } from 'react';
8
+ import { useQuery } from '@tanstack/react-query';
9
+ import { z } from 'zod';
10
+
11
+ // ../core/src/auth/multi-tenancy/permissions.ts
12
+ var PERMISSIONS = {
13
+ ORG_READ: "org.read",
14
+ ORG_MANAGE: "org.manage",
15
+ ORG_DELETE: "org.delete",
16
+ MEMBERS_MANAGE: "members.manage",
17
+ ROLES_MANAGE: "roles.manage",
18
+ SECRETS_MANAGE: "secrets.manage",
19
+ OPERATIONS_READ: "operations.read",
20
+ OPERATIONS_MANAGE: "operations.manage",
21
+ ACQUISITION_MANAGE: "acquisition.manage",
22
+ PROJECTS_MANAGE: "projects.manage",
23
+ CLIENTS_MANAGE: "clients.manage"
24
+ };
25
+ var PERMISSION_CATALOG = [
26
+ {
27
+ key: "org.read",
28
+ description: "Read organization profile and listings",
29
+ isOrgGrantable: true
30
+ },
31
+ {
32
+ key: "org.manage",
33
+ description: "Update organization settings",
34
+ isOrgGrantable: false
35
+ },
36
+ {
37
+ key: "org.delete",
38
+ description: "Delete the organization (owner-only)",
39
+ isOrgGrantable: false
40
+ },
41
+ {
42
+ key: "members.manage",
43
+ description: "Invite, remove, and reassign roles for members",
44
+ isOrgGrantable: false
45
+ },
46
+ {
47
+ key: "roles.manage",
48
+ description: "Grant or revoke privileged system roles (owner, admin) within the organization",
49
+ isOrgGrantable: false
50
+ },
51
+ {
52
+ key: "secrets.manage",
53
+ description: "Create, update, and delete API keys and credentials",
54
+ isOrgGrantable: false
55
+ },
56
+ {
57
+ key: "operations.read",
58
+ description: "View executions, sessions, schedules, and command queue",
59
+ isOrgGrantable: true
60
+ },
61
+ {
62
+ key: "operations.manage",
63
+ description: "Run and modify executions, sessions, schedules, queue",
64
+ isOrgGrantable: true
65
+ },
66
+ {
67
+ key: "acquisition.manage",
68
+ description: "Create, update, and delete acquisition records (acq_companies, acq_contacts, acq_deals, acq_lists*, acq_content*, acquisition storage files)",
69
+ isOrgGrantable: false
70
+ },
71
+ {
72
+ key: "projects.manage",
73
+ description: "Create, update, and delete project records (prj_projects, prj_milestones, prj_tasks, prj_notes)",
74
+ isOrgGrantable: false
75
+ },
76
+ {
77
+ key: "clients.manage",
78
+ description: "Create, update, and delete client hub records (clients, clt_* satellites)",
79
+ isOrgGrantable: false
80
+ }
81
+ ];
82
+ new Set(PERMISSION_CATALOG.map((p) => p.key));
83
+ var DEFAULT_ACCESS_ACTION = "view";
84
+ var PLATFORM_ADMIN_ACCESS_KEY = "platform.admin";
85
+ var PLATFORM_ADMIN_ACCESS_KEY_SHORTHAND = "platformAdmin";
86
+ var AccessActionSchema = z.enum(["view", "manage"]);
87
+ var AccessKeyObjectSchema = z.object({
88
+ systemPath: z.string().trim().min(1),
89
+ action: AccessActionSchema.default(DEFAULT_ACCESS_ACTION)
90
+ }).strict();
91
+ var AccessKeyInputSchema = z.union([z.string().trim().min(1), AccessKeyObjectSchema]);
92
+ var NormalizedAccessKeySchema = AccessKeyObjectSchema;
93
+ var DIAGNOSTIC_VIEW_ACCESS_KEYS = [
94
+ "diagnostic.operations.overview",
95
+ "diagnostic.operations.recent-executions",
96
+ "diagnostic.monitoring.execution-logs",
97
+ "diagnostic.monitoring.notifications"
98
+ ];
99
+ var AccessKeys = {
100
+ platformAdmin: { systemPath: PLATFORM_ADMIN_ACCESS_KEY, action: DEFAULT_ACCESS_ACTION },
101
+ organizationManage: { systemPath: "permission.org", action: "manage" },
102
+ membersManage: { systemPath: "permission.members", action: "manage" },
103
+ rolesManage: { systemPath: "permission.roles", action: "manage" },
104
+ secretsManage: { systemPath: "permission.secrets", action: "manage" },
105
+ operationsRead: { systemPath: "permission.operations", action: DEFAULT_ACCESS_ACTION },
106
+ operationsManage: { systemPath: "permission.operations", action: "manage" },
107
+ acquisitionManage: { systemPath: "permission.acquisition", action: "manage" },
108
+ projectsManage: { systemPath: "permission.projects", action: "manage" },
109
+ clientsManage: { systemPath: "permission.clients", action: "manage" },
110
+ operationsOverview: { systemPath: "diagnostic.operations.overview", action: DEFAULT_ACCESS_ACTION },
111
+ operationsRecentExecutions: { systemPath: "diagnostic.operations.recent-executions", action: DEFAULT_ACCESS_ACTION },
112
+ monitoringExecutionLogs: { systemPath: "diagnostic.monitoring.execution-logs", action: DEFAULT_ACCESS_ACTION },
113
+ monitoringNotifications: { systemPath: "diagnostic.monitoring.notifications", action: DEFAULT_ACCESS_ACTION }
114
+ };
115
+ var PERMISSION_ACCESS_KEY_DEFINITIONS = [
116
+ { key: AccessKeys.organizationManage, rolePermission: PERMISSIONS.ORG_MANAGE },
117
+ { key: AccessKeys.membersManage, rolePermission: PERMISSIONS.MEMBERS_MANAGE },
118
+ { key: AccessKeys.rolesManage, rolePermission: PERMISSIONS.ROLES_MANAGE },
119
+ { key: AccessKeys.secretsManage, rolePermission: PERMISSIONS.SECRETS_MANAGE },
120
+ { key: AccessKeys.operationsRead, rolePermission: PERMISSIONS.OPERATIONS_READ },
121
+ { key: AccessKeys.operationsManage, rolePermission: PERMISSIONS.OPERATIONS_MANAGE },
122
+ { key: AccessKeys.acquisitionManage, rolePermission: PERMISSIONS.ACQUISITION_MANAGE },
123
+ { key: AccessKeys.projectsManage, rolePermission: PERMISSIONS.PROJECTS_MANAGE },
124
+ { key: AccessKeys.clientsManage, rolePermission: PERMISSIONS.CLIENTS_MANAGE }
125
+ ];
126
+ function normalizeAccessKey(input) {
127
+ const parsed = AccessKeyInputSchema.parse(input);
128
+ const normalized = typeof parsed === "string" ? {
129
+ systemPath: parsed === PLATFORM_ADMIN_ACCESS_KEY_SHORTHAND ? PLATFORM_ADMIN_ACCESS_KEY : parsed,
130
+ action: DEFAULT_ACCESS_ACTION
131
+ } : parsed;
132
+ return NormalizedAccessKeySchema.parse(normalized);
133
+ }
134
+ function rolePermissionForAccessKey(key) {
135
+ if (key.action === DEFAULT_ACCESS_ACTION) return void 0;
136
+ return `${key.systemPath}.${key.action}`;
137
+ }
138
+ function groupCatalogEntries(entries) {
139
+ const grouped = /* @__PURE__ */ new Map();
140
+ for (const entry of entries) {
141
+ const existing = grouped.get(entry.key.systemPath) ?? [];
142
+ existing.push(entry);
143
+ grouped.set(entry.key.systemPath, existing);
144
+ }
145
+ return grouped;
146
+ }
147
+ function buildCatalogEntry(systemPath, action, source) {
148
+ const key = normalizeAccessKey({ systemPath, action });
149
+ return {
150
+ key,
151
+ source,
152
+ rolePermission: rolePermissionForAccessKey(key)
153
+ };
154
+ }
155
+ function deriveAccessKeyCatalog(organizationModel, options = {}) {
156
+ const { diagnosticKeys = DIAGNOSTIC_VIEW_ACCESS_KEYS, includeManageActions = true } = options;
157
+ const entries = [
158
+ buildCatalogEntry(PLATFORM_ADMIN_ACCESS_KEY, DEFAULT_ACCESS_ACTION, "platform")
159
+ ];
160
+ for (const { path } of listAllSystems(organizationModel)) {
161
+ entries.push(buildCatalogEntry(path, DEFAULT_ACCESS_ACTION, "om-system"));
162
+ if (includeManageActions) {
163
+ entries.push(buildCatalogEntry(path, "manage", "om-system"));
164
+ }
165
+ }
166
+ for (const { key, rolePermission } of PERMISSION_ACCESS_KEY_DEFINITIONS) {
167
+ entries.push({
168
+ key,
169
+ source: "permission",
170
+ rolePermission
171
+ });
172
+ }
173
+ for (const systemPath of diagnosticKeys) {
174
+ entries.push(buildCatalogEntry(systemPath, DEFAULT_ACCESS_ACTION, "diagnostic"));
175
+ }
176
+ return {
177
+ bySystemPath: groupCatalogEntries(entries),
178
+ entries
179
+ };
180
+ }
181
+ function findAccessCatalogEntry(catalog, key) {
182
+ return catalog.bySystemPath.get(key.systemPath)?.find((entry) => entry.key.action === key.action);
183
+ }
184
+
185
+ // ../core/src/auth/access-model.ts
186
+ var ALLOWED = { allowed: true, restrictedBy: null, reason: "allowed" };
187
+ var PLATFORM_ADMIN_BYPASS = {
188
+ allowed: true,
189
+ restrictedBy: null,
190
+ reason: "platform-admin-bypass"
191
+ };
192
+ function deny(restrictedBy, reason) {
193
+ return { allowed: false, restrictedBy, reason };
194
+ }
195
+ function isPlatformAdmin(profile) {
196
+ return profile?.isPlatformAdmin === true || profile?.is_platform_admin === true;
197
+ }
198
+ function diagnosticAllowlistHas(allowlist, systemPath) {
199
+ if (allowlist === void 0) return false;
200
+ return "has" in allowlist ? allowlist.has(systemPath) : allowlist.includes(systemPath);
201
+ }
202
+ function lifecycleAllowsAccess(lifecycle, ctx) {
203
+ if (lifecycle === "active") return true;
204
+ if (lifecycle === "beta") return ctx.betaAccessEnabled === true || ctx.isDevelopment === true;
205
+ return false;
206
+ }
207
+ function getPermissionSource(ctx) {
208
+ return ctx.permissions ?? ctx.membership?.effectivePermissions;
209
+ }
210
+ function hasRequiredPermission(key, rolePermission, ctx) {
211
+ const permissionSource = getPermissionSource(ctx);
212
+ if (permissionSource === void 0 || permissionSource === null) return true;
213
+ const requiredPermission = rolePermission ?? `${key.systemPath}.${key.action}`;
214
+ return permissionSource.includes(requiredPermission);
215
+ }
216
+ function hasExplicitRequiredPermission(rolePermission, ctx) {
217
+ const permissionSource = getPermissionSource(ctx);
218
+ return rolePermission !== void 0 && permissionSource !== void 0 && permissionSource !== null ? permissionSource.includes(rolePermission) : false;
219
+ }
220
+ function checkAccess(input, ctx) {
221
+ if (isPlatformAdmin(ctx.profile)) return PLATFORM_ADMIN_BYPASS;
222
+ const parsed = (() => {
223
+ try {
224
+ return normalizeAccessKey(input);
225
+ } catch {
226
+ return null;
227
+ }
228
+ })();
229
+ if (parsed === null) return deny("catalog", "invalid-access-key");
230
+ const catalog = ctx.accessCatalog ?? deriveAccessKeyCatalog(ctx.organizationModel);
231
+ const catalogEntry = findAccessCatalogEntry(catalog, parsed);
232
+ if (catalogEntry === void 0) return deny("catalog", "unknown-access-key");
233
+ const membership = ctx.membership;
234
+ if (membership === void 0 || membership === null) return deny("membership", "missing-membership");
235
+ if (membership.organizationId !== ctx.organizationId) return deny("membership", "organization-mismatch");
236
+ if (parsed.systemPath === PLATFORM_ADMIN_ACCESS_KEY) {
237
+ return deny("role-permission", "role-permission-denied");
238
+ }
239
+ if (catalogEntry.source === "diagnostic") {
240
+ if (!diagnosticAllowlistHas(ctx.diagnosticAllowlist, parsed.systemPath)) {
241
+ return deny("diagnostic-allowlist", "diagnostic-key-not-allowed");
242
+ }
243
+ if (parsed.action !== DEFAULT_ACCESS_ACTION && !hasRequiredPermission(parsed, catalogEntry.rolePermission, ctx)) {
244
+ return deny("role-permission", "role-permission-denied");
245
+ }
246
+ return ALLOWED;
247
+ }
248
+ if (catalogEntry.source === "permission") {
249
+ if (!hasExplicitRequiredPermission(catalogEntry.rolePermission, ctx)) {
250
+ return deny("role-permission", "role-permission-denied");
251
+ }
252
+ return ALLOWED;
253
+ }
254
+ const system = getSystem(ctx.organizationModel, parsed.systemPath);
255
+ if (system === void 0 || !lifecycleAllowsAccess(system.lifecycle, ctx)) {
256
+ return deny("system-lifecycle", "system-not-active");
257
+ }
258
+ if (parsed.action !== DEFAULT_ACCESS_ACTION && !hasRequiredPermission(parsed, catalogEntry.rolePermission, ctx)) {
259
+ return deny("role-permission", "role-permission-denied");
260
+ }
261
+ return ALLOWED;
262
+ }
263
+ function createAccessModel(organizationModel) {
264
+ const catalog = deriveAccessKeyCatalog(organizationModel);
265
+ return {
266
+ catalog,
267
+ checkAccess: (key, ctx) => checkAccess(key, { ...ctx, organizationModel, accessCatalog: catalog })
268
+ };
269
+ }
270
+
271
+ // src/hooks/access/useAccess.ts
272
+ var MISSING_CONTEXT_ANSWER = {
273
+ allowed: false,
274
+ restrictedBy: "membership",
275
+ reason: "missing-membership"
276
+ };
277
+ function readStringArray(value) {
278
+ return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
279
+ }
280
+ function membershipPermissions(membership) {
281
+ if (!membership || typeof membership !== "object") return void 0;
282
+ const record = membership;
283
+ return readStringArray(record.effectivePermissions) ?? readStringArray(record.effective_permissions);
284
+ }
285
+ function resolveOrganizationId(organization) {
286
+ const membership = organization?.currentMembership;
287
+ return organization?.currentSupabaseOrganizationId ?? membership?.organizationId ?? membership?.organization?.id ?? null;
288
+ }
289
+ function toAccessMembership(membership, organizationId, permissions) {
290
+ if (!membership || !organizationId) return null;
291
+ return {
292
+ id: membership.id,
293
+ organizationId: membership.organizationId ?? organizationId,
294
+ role: membership.role?.slug ?? null,
295
+ effectivePermissions: permissions
296
+ };
297
+ }
298
+ function useAccess(key) {
299
+ const initialization = useContext(InitializationContext);
300
+ const organization = useContext(OrganizationContext);
301
+ const services = useContext(ElevasisServiceContext);
302
+ const systems = useOptionalElevasisSystems();
303
+ const profile = initialization?.profile ?? null;
304
+ const isPlatformAdmin2 = profile?.is_platform_admin === true;
305
+ const organizationId = resolveOrganizationId(organization);
306
+ const membership = organization?.currentMembership ?? null;
307
+ const organizationModel = systems?.organizationModel ?? DEFAULT_ORGANIZATION_MODEL;
308
+ const permissionsFromMembership = useMemo(() => membershipPermissions(membership), [membership]);
309
+ const shouldFetchPermissions = Boolean(services?.isReady && organizationId && !isPlatformAdmin2);
310
+ const permissionsQuery = useQuery({
311
+ // eslint-disable-next-line @tanstack/query/exhaustive-deps -- services.apiRequest is a stable context fn, not cache-relevant; query is keyed by organizationId
312
+ queryKey: ["access-permissions", organizationId],
313
+ queryFn: () => services.apiRequest(`/memberships/my-permissions/${organizationId}`),
314
+ enabled: shouldFetchPermissions,
315
+ staleTime: STALE_TIME_DEFAULT
316
+ });
317
+ const permissions = useMemo(
318
+ () => isPlatformAdmin2 ? Object.values(PERMISSIONS) : permissionsQuery.data?.permissions ?? permissionsFromMembership ?? [],
319
+ [isPlatformAdmin2, permissionsFromMembership, permissionsQuery.data?.permissions]
320
+ );
321
+ const accessMembership = useMemo(
322
+ () => toAccessMembership(membership, organizationId, permissions),
323
+ [membership, organizationId, permissions]
324
+ );
325
+ const accessModel = useMemo(() => createAccessModel(organizationModel), [organizationModel]);
326
+ const answer = useMemo(() => {
327
+ if (!organizationId && !isPlatformAdmin2) return MISSING_CONTEXT_ANSWER;
328
+ return accessModel.checkAccess(key, {
329
+ organizationId: organizationId ?? "",
330
+ organizationModel,
331
+ membership: accessMembership,
332
+ profile,
333
+ permissions,
334
+ diagnosticAllowlist: DIAGNOSTIC_VIEW_ACCESS_KEYS,
335
+ isDevelopment: import.meta.env?.DEV ?? false
336
+ });
337
+ }, [accessMembership, accessModel, isPlatformAdmin2, key, organizationId, organizationModel, permissions, profile]);
338
+ const providerReady = initialization?.organizationReady ?? Boolean(organizationId && accessMembership && systems?.organizationModel);
339
+ const permissionsReady = !shouldFetchPermissions || !permissionsQuery.isPending;
340
+ const isReady = isPlatformAdmin2 ? initialization?.userReady ?? true : providerReady && permissionsReady;
341
+ return {
342
+ ...answer,
343
+ isReady,
344
+ isPlatformAdmin: isPlatformAdmin2,
345
+ permissions
346
+ };
347
+ }
348
+
349
+ export { AccessKeys, useAccess };
@@ -761,107 +761,9 @@ var EntitySchema = z.object({
761
761
  var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
762
762
  message: "Each entity entry id must match its map key"
763
763
  }).default({});
764
- var ENTITY_ENTRY_INPUTS = [
765
- {
766
- id: "crm.deal",
767
- order: 10,
768
- label: "Deal",
769
- description: "A CRM opportunity or sales pipeline record.",
770
- ownedBySystemId: "sales.crm",
771
- table: "crm_deals",
772
- stateCatalogId: "crm.pipeline",
773
- links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
774
- },
775
- {
776
- id: "crm.contact",
777
- order: 20,
778
- label: "CRM Contact",
779
- description: "A person associated with a CRM relationship or deal.",
780
- ownedBySystemId: "sales.crm",
781
- table: "crm_contacts"
782
- },
783
- {
784
- id: "leadgen.list",
785
- order: 30,
786
- label: "Lead List",
787
- description: "A prospecting list that groups companies and contacts for acquisition workflows.",
788
- ownedBySystemId: "sales.lead-gen",
789
- table: "acq_lists",
790
- links: [
791
- { toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
792
- { toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
793
- ]
794
- },
795
- {
796
- id: "leadgen.company",
797
- order: 40,
798
- label: "Lead Company",
799
- description: "A company record sourced, enriched, and qualified during prospecting.",
800
- ownedBySystemId: "sales.lead-gen",
801
- table: "acq_list_companies",
802
- stateCatalogId: "lead-gen.company",
803
- links: [
804
- { toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
805
- { toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
806
- ]
807
- },
808
- {
809
- id: "leadgen.contact",
810
- order: 50,
811
- label: "Lead Contact",
812
- description: "A prospect contact discovered or enriched during lead generation.",
813
- ownedBySystemId: "sales.lead-gen",
814
- table: "acq_list_members",
815
- stateCatalogId: "lead-gen.contact",
816
- links: [
817
- { toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
818
- { toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
819
- ]
820
- },
821
- {
822
- id: "delivery.project",
823
- order: 60,
824
- label: "Project",
825
- description: "A client delivery project.",
826
- ownedBySystemId: "projects",
827
- table: "projects",
828
- links: [
829
- { toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
830
- { toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
831
- ]
832
- },
833
- {
834
- id: "delivery.milestone",
835
- order: 70,
836
- label: "Milestone",
837
- description: "A delivery checkpoint within a project.",
838
- ownedBySystemId: "projects",
839
- table: "project_milestones",
840
- links: [
841
- { toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
842
- { toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
843
- ]
844
- },
845
- {
846
- id: "delivery.task",
847
- order: 80,
848
- label: "Task",
849
- description: "A delivery task that can move through the task status catalog.",
850
- ownedBySystemId: "projects",
851
- table: "project_tasks",
852
- stateCatalogId: "delivery.task",
853
- links: [
854
- { toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
855
- { toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
856
- ]
857
- }
858
- ];
859
- var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
860
- ENTITY_ENTRY_INPUTS.map((entity) => {
861
- const parsed = EntitySchema.parse(entity);
862
- return [parsed.id, parsed];
863
- })
864
- );
764
+ function defineEntities(entries) {
765
+ return defineDomainRecord(EntitySchema, entries);
766
+ }
865
767
 
866
768
  // ../core/src/organization-model/domains/actions.ts
867
769
  var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
@@ -1086,8 +988,33 @@ var IdentityDomainSchema = z.object({
1086
988
  * background. Populated by /setup; surfaced to agents as organizational context.
1087
989
  * Optional — many projects have no external client.
1088
990
  */
1089
- clientBrief: z.string().trim().default("")
1090
- });
991
+ clientBrief: z.string().trim().default(""),
992
+ /**
993
+ * Display name of the organization as shown to end users.
994
+ * Recommended placement for display naming — prefer this over the deprecated
995
+ * `branding.organizationName`. Falls back to `branding.organizationName` for
996
+ * legacy tenants that have not yet migrated.
997
+ */
998
+ organizationName: LabelSchema.optional(),
999
+ /**
1000
+ * Display name of the primary product or platform.
1001
+ * Recommended placement for display naming — prefer this over the deprecated
1002
+ * `branding.productName`. Falls back to `branding.productName` for legacy tenants.
1003
+ */
1004
+ productName: LabelSchema.optional(),
1005
+ /**
1006
+ * Short abbreviated name used in space-constrained UI surfaces (max 40 chars).
1007
+ * Recommended placement for display naming — prefer this over the deprecated
1008
+ * `branding.shortName`. Falls back to `branding.shortName` for legacy tenants.
1009
+ */
1010
+ shortName: z.string().trim().min(1).max(40).optional(),
1011
+ /**
1012
+ * Plain-language description of the organization for display and discovery.
1013
+ * Recommended placement for display naming — prefer this over the deprecated
1014
+ * `branding.description`. Falls back to `branding.description` for legacy tenants.
1015
+ */
1016
+ description: DescriptionSchema.optional()
1017
+ }).passthrough();
1091
1018
  var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
1092
1019
  mission: "",
1093
1020
  vision: "",
@@ -1374,15 +1301,55 @@ function getAllProjectStatuses(model, appliesTo) {
1374
1301
  // ../core/src/organization-model/contracts.ts
1375
1302
  var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
1376
1303
  var OrganizationModelBrandingSchema = z.object({
1304
+ /**
1305
+ * @deprecated Prefer `identity.organizationName`; branding retains it for back-compat.
1306
+ * Legacy tenants that have not set `identity.organizationName` fall back to this field.
1307
+ */
1377
1308
  organizationName: LabelSchema,
1309
+ /**
1310
+ * @deprecated Prefer `identity.productName`; branding retains it for back-compat.
1311
+ * Legacy tenants that have not set `identity.productName` fall back to this field.
1312
+ */
1378
1313
  productName: LabelSchema,
1314
+ /**
1315
+ * @deprecated Prefer `identity.shortName`; branding retains it for back-compat.
1316
+ * Legacy tenants that have not set `identity.shortName` fall back to this field.
1317
+ */
1379
1318
  shortName: z.string().trim().min(1).max(40),
1319
+ /**
1320
+ * @deprecated Prefer `identity.description`; branding retains it for back-compat.
1321
+ * Legacy tenants that have not set `identity.description` fall back to this field.
1322
+ */
1380
1323
  description: DescriptionSchema.optional(),
1381
1324
  logos: z.object({
1382
1325
  light: z.string().trim().min(1).max(2048).optional(),
1383
1326
  dark: z.string().trim().min(1).max(2048).optional()
1384
- }).default({})
1385
- });
1327
+ }).default({}),
1328
+ /**
1329
+ * Brand voice — how the organization communicates. Plain-language description
1330
+ * of tone, register, and personality (e.g. "Direct and human — no jargon").
1331
+ * Max 280 characters.
1332
+ */
1333
+ voice: z.string().trim().max(280).optional(),
1334
+ /**
1335
+ * Brand tagline or positioning statement — the memorable one-liner that
1336
+ * captures the brand's promise or differentiator. Max 200 characters.
1337
+ */
1338
+ tagline: z.string().trim().max(200).optional(),
1339
+ /**
1340
+ * Core brand values — an ordered list of principles the organization stands
1341
+ * for (e.g. ["Transparency", "Craftsmanship", "Velocity"]). Each entry must
1342
+ * be a non-empty trimmed string.
1343
+ */
1344
+ values: z.array(z.string().trim().min(1)).optional(),
1345
+ /**
1346
+ * ID of the active UI theme preset from the UI theme-presets registry.
1347
+ * The UI layer resolves this to colors and typography via `usePresetsContext()`.
1348
+ * Free-form string — validation and fallback state are handled at the UI layer.
1349
+ * Min 1, max 64 characters.
1350
+ */
1351
+ themePresetId: z.string().trim().min(1).max(64).optional()
1352
+ }).passthrough();
1386
1353
  var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
1387
1354
  organizationName: "Default Organization",
1388
1355
  productName: "Organization OS",
@@ -2638,7 +2605,7 @@ var OrganizationModelSchemaBase = z.object({
2638
2605
  resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
2639
2606
  topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
2640
2607
  actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
2641
- entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
2608
+ entities: EntitiesDomainSchema.default({}),
2642
2609
  policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
2643
2610
  // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
2644
2611
  knowledge: KnowledgeDomainSchema.default({})
@@ -2647,7 +2614,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine(refineOrga
2647
2614
 
2648
2615
  // ../core/src/organization-model/defaults.ts
2649
2616
  var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
2650
- var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = {};
2617
+ var DEFAULT_ORGANIZATION_MODEL_ENTITIES = {};
2651
2618
  var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
2652
2619
  sidebar: {
2653
2620
  primary: {},
@@ -2675,7 +2642,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
2675
2642
  // Generic empty actions map. Elevasis-specific action entries have been relocated to
2676
2643
  // `@repo/elevasis-core/src/organization-model/actions.ts`.
2677
2644
  actions: {},
2678
- entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
2645
+ entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES,
2679
2646
  policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
2680
2647
  knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
2681
2648
  };
@@ -3745,4 +3712,4 @@ function projectOrganizationSurfaces(model) {
3745
3712
  });
3746
3713
  }
3747
3714
 
3748
- export { ActionSchema, AgentResourceEntrySchema, DEFAULT_SEMANTIC_ICON_REGISTRY, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, OntologyIdSchema, OrgKnowledgeNodeSchema, PROJECTS_VIEW_ACTION_ID, PolicySchema, RoleSchema, ScriptResourceEntrySchema, SemanticIcon, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, ancestorsOf, buildOrganizationGraph, childrenOf, compileOrganizationOntology, defaultPathFor, defineActions, defineResources, defineTopology, devOnlyFor, extendSemanticIconRegistry, findById, findByPath, getAllBuildTemplates, getLeadGenStageCatalog, getResourcesForSystem, getSemanticIconComponent, getSortedSidebarEntries, getSystem, getSystemAncestors, listAllSystems, ontologyGraphNodeId, parentOf, parseOntologyId, projectOrganizationSurfaces, requiresAdminFor, resolveOrganizationModel, resolveSemanticIconComponent, resolveSystemConfig, topLevel, topologyRef, topologyRelationship };
3715
+ export { ActionSchema, AgentResourceEntrySchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_SEMANTIC_ICON_REGISTRY, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, OntologyIdSchema, OrgKnowledgeNodeSchema, PROJECTS_VIEW_ACTION_ID, PolicySchema, RoleSchema, ScriptResourceEntrySchema, SemanticIcon, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, ancestorsOf, buildOrganizationGraph, childrenOf, compileOrganizationOntology, defaultPathFor, defineActions, defineEntities, defineResources, defineTopology, devOnlyFor, extendSemanticIconRegistry, findById, findByPath, getAllBuildTemplates, getLeadGenStageCatalog, getResourcesForSystem, getSemanticIconComponent, getSortedSidebarEntries, getSystem, getSystemAncestors, listAllSystems, ontologyGraphNodeId, parentOf, parseOntologyId, projectOrganizationSurfaces, requiresAdminFor, resolveOrganizationModel, resolveSemanticIconComponent, resolveSystemConfig, topLevel, topologyRef, topologyRelationship };