@elevasis/core 0.29.0 → 0.30.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.
@@ -0,0 +1,173 @@
1
+ import { z } from 'zod'
2
+ import { listAllSystems } from '../organization-model/helpers'
3
+ import type { OrganizationModel } from '../organization-model/types'
4
+ import { PERMISSIONS, type PermissionKey } from './multi-tenancy/permissions'
5
+
6
+ export const DEFAULT_ACCESS_ACTION = 'view' as const
7
+ export const PLATFORM_ADMIN_ACCESS_KEY = 'platform.admin' as const
8
+ export const PLATFORM_ADMIN_ACCESS_KEY_SHORTHAND = 'platformAdmin' as const
9
+
10
+ export const AccessActionSchema = z.enum(['view', 'manage'])
11
+
12
+ export const AccessKeyObjectSchema = z
13
+ .object({
14
+ systemPath: z.string().trim().min(1),
15
+ action: AccessActionSchema.default(DEFAULT_ACCESS_ACTION)
16
+ })
17
+ .strict()
18
+
19
+ export const AccessKeyInputSchema = z.union([z.string().trim().min(1), AccessKeyObjectSchema])
20
+ export const NormalizedAccessKeySchema = AccessKeyObjectSchema
21
+ export const AccessKeySchema = AccessKeyInputSchema
22
+
23
+ export type AccessAction = z.infer<typeof AccessActionSchema>
24
+ export type AccessKeyObject = z.infer<typeof AccessKeyObjectSchema>
25
+ export type AccessKeyInput = z.input<typeof AccessKeyInputSchema>
26
+ export type NormalizedAccessKey = z.infer<typeof NormalizedAccessKeySchema>
27
+ export type AccessKey = NormalizedAccessKey
28
+
29
+ export type AccessCatalogEntrySource = 'om-system' | 'diagnostic' | 'platform' | 'permission'
30
+
31
+ export interface AccessCatalogEntry {
32
+ key: NormalizedAccessKey
33
+ source: AccessCatalogEntrySource
34
+ rolePermission?: string
35
+ }
36
+
37
+ export interface AccessKeyCatalog {
38
+ bySystemPath: ReadonlyMap<string, readonly AccessCatalogEntry[]>
39
+ entries: readonly AccessCatalogEntry[]
40
+ }
41
+
42
+ export const DIAGNOSTIC_VIEW_ACCESS_KEYS = [
43
+ 'diagnostic.operations.overview',
44
+ 'diagnostic.operations.recent-executions',
45
+ 'diagnostic.monitoring.execution-logs',
46
+ 'diagnostic.monitoring.notifications'
47
+ ] as const
48
+
49
+ export const AccessKeys = {
50
+ platformAdmin: { systemPath: PLATFORM_ADMIN_ACCESS_KEY, action: DEFAULT_ACCESS_ACTION },
51
+ organizationManage: { systemPath: 'permission.org', action: 'manage' },
52
+ membersManage: { systemPath: 'permission.members', action: 'manage' },
53
+ rolesManage: { systemPath: 'permission.roles', action: 'manage' },
54
+ secretsManage: { systemPath: 'permission.secrets', action: 'manage' },
55
+ operationsRead: { systemPath: 'permission.operations', action: DEFAULT_ACCESS_ACTION },
56
+ operationsManage: { systemPath: 'permission.operations', action: 'manage' },
57
+ acquisitionManage: { systemPath: 'permission.acquisition', action: 'manage' },
58
+ projectsManage: { systemPath: 'permission.projects', action: 'manage' },
59
+ clientsManage: { systemPath: 'permission.clients', action: 'manage' },
60
+ operationsOverview: { systemPath: 'diagnostic.operations.overview', action: DEFAULT_ACCESS_ACTION },
61
+ operationsRecentExecutions: { systemPath: 'diagnostic.operations.recent-executions', action: DEFAULT_ACCESS_ACTION },
62
+ monitoringExecutionLogs: { systemPath: 'diagnostic.monitoring.execution-logs', action: DEFAULT_ACCESS_ACTION },
63
+ monitoringNotifications: { systemPath: 'diagnostic.monitoring.notifications', action: DEFAULT_ACCESS_ACTION }
64
+ } as const satisfies Record<string, NormalizedAccessKey>
65
+
66
+ const PERMISSION_ACCESS_KEY_DEFINITIONS: readonly {
67
+ key: NormalizedAccessKey
68
+ rolePermission: PermissionKey
69
+ }[] = [
70
+ { key: AccessKeys.organizationManage, rolePermission: PERMISSIONS.ORG_MANAGE },
71
+ { key: AccessKeys.membersManage, rolePermission: PERMISSIONS.MEMBERS_MANAGE },
72
+ { key: AccessKeys.rolesManage, rolePermission: PERMISSIONS.ROLES_MANAGE },
73
+ { key: AccessKeys.secretsManage, rolePermission: PERMISSIONS.SECRETS_MANAGE },
74
+ { key: AccessKeys.operationsRead, rolePermission: PERMISSIONS.OPERATIONS_READ },
75
+ { key: AccessKeys.operationsManage, rolePermission: PERMISSIONS.OPERATIONS_MANAGE },
76
+ { key: AccessKeys.acquisitionManage, rolePermission: PERMISSIONS.ACQUISITION_MANAGE },
77
+ { key: AccessKeys.projectsManage, rolePermission: PERMISSIONS.PROJECTS_MANAGE },
78
+ { key: AccessKeys.clientsManage, rolePermission: PERMISSIONS.CLIENTS_MANAGE }
79
+ ]
80
+
81
+ export function normalizeAccessKey(input: AccessKeyInput): NormalizedAccessKey {
82
+ const parsed = AccessKeyInputSchema.parse(input)
83
+ const normalized =
84
+ typeof parsed === 'string'
85
+ ? {
86
+ systemPath: parsed === PLATFORM_ADMIN_ACCESS_KEY_SHORTHAND ? PLATFORM_ADMIN_ACCESS_KEY : parsed,
87
+ action: DEFAULT_ACCESS_ACTION
88
+ }
89
+ : parsed
90
+
91
+ return NormalizedAccessKeySchema.parse(normalized)
92
+ }
93
+
94
+ export function accessKeyToString(input: AccessKeyInput): string {
95
+ const key = normalizeAccessKey(input)
96
+ return `${key.systemPath}:${key.action}`
97
+ }
98
+
99
+ export function rolePermissionForAccessKey(key: NormalizedAccessKey): string | undefined {
100
+ if (key.action === DEFAULT_ACCESS_ACTION) return undefined
101
+ return `${key.systemPath}.${key.action}`
102
+ }
103
+
104
+ export interface DeriveAccessKeyCatalogOptions {
105
+ diagnosticKeys?: readonly string[]
106
+ includeManageActions?: boolean
107
+ }
108
+
109
+ function groupCatalogEntries(entries: readonly AccessCatalogEntry[]): ReadonlyMap<string, readonly AccessCatalogEntry[]> {
110
+ const grouped = new Map<string, AccessCatalogEntry[]>()
111
+
112
+ for (const entry of entries) {
113
+ const existing = grouped.get(entry.key.systemPath) ?? []
114
+ existing.push(entry)
115
+ grouped.set(entry.key.systemPath, existing)
116
+ }
117
+
118
+ return grouped
119
+ }
120
+
121
+ function buildCatalogEntry(systemPath: string, action: AccessAction, source: AccessCatalogEntrySource): AccessCatalogEntry {
122
+ const key = normalizeAccessKey({ systemPath, action })
123
+ return {
124
+ key,
125
+ source,
126
+ rolePermission: rolePermissionForAccessKey(key)
127
+ }
128
+ }
129
+
130
+ export function deriveAccessKeyCatalog(
131
+ organizationModel: OrganizationModel,
132
+ options: DeriveAccessKeyCatalogOptions = {}
133
+ ): AccessKeyCatalog {
134
+ const { diagnosticKeys = DIAGNOSTIC_VIEW_ACCESS_KEYS, includeManageActions = true } = options
135
+ const entries: AccessCatalogEntry[] = [
136
+ buildCatalogEntry(PLATFORM_ADMIN_ACCESS_KEY, DEFAULT_ACCESS_ACTION, 'platform')
137
+ ]
138
+
139
+ for (const { path } of listAllSystems(organizationModel)) {
140
+ entries.push(buildCatalogEntry(path, DEFAULT_ACCESS_ACTION, 'om-system'))
141
+ if (includeManageActions) {
142
+ entries.push(buildCatalogEntry(path, 'manage', 'om-system'))
143
+ }
144
+ }
145
+
146
+ for (const { key, rolePermission } of PERMISSION_ACCESS_KEY_DEFINITIONS) {
147
+ entries.push({
148
+ key,
149
+ source: 'permission',
150
+ rolePermission
151
+ })
152
+ }
153
+
154
+ for (const systemPath of diagnosticKeys) {
155
+ entries.push(buildCatalogEntry(systemPath, DEFAULT_ACCESS_ACTION, 'diagnostic'))
156
+ }
157
+
158
+ return {
159
+ bySystemPath: groupCatalogEntries(entries),
160
+ entries
161
+ }
162
+ }
163
+
164
+ export function findAccessCatalogEntry(
165
+ catalog: AccessKeyCatalog,
166
+ key: NormalizedAccessKey
167
+ ): AccessCatalogEntry | undefined {
168
+ return catalog.bySystemPath.get(key.systemPath)?.find((entry) => entry.key.action === key.action)
169
+ }
170
+
171
+ export function listAccessKeys(catalog: AccessKeyCatalog): NormalizedAccessKey[] {
172
+ return catalog.entries.map((entry) => entry.key)
173
+ }
@@ -0,0 +1,185 @@
1
+ import {
2
+ DEFAULT_ACCESS_ACTION,
3
+ PLATFORM_ADMIN_ACCESS_KEY,
4
+ deriveAccessKeyCatalog,
5
+ findAccessCatalogEntry,
6
+ normalizeAccessKey,
7
+ type AccessKeyCatalog,
8
+ type AccessKeyInput,
9
+ type NormalizedAccessKey
10
+ } from './access-keys'
11
+ import { getSystem } from '../organization-model/helpers'
12
+ import type { OrganizationModel, OrganizationModelSystemLifecycle } from '../organization-model/types'
13
+
14
+ export type AccessRestrictedBy =
15
+ | 'catalog'
16
+ | 'membership'
17
+ | 'system-lifecycle'
18
+ | 'role-permission'
19
+ | 'diagnostic-allowlist'
20
+ | null
21
+
22
+ export type AccessReason =
23
+ | 'allowed'
24
+ | 'platform-admin-bypass'
25
+ | 'invalid-access-key'
26
+ | 'unknown-access-key'
27
+ | 'organization-mismatch'
28
+ | 'missing-membership'
29
+ | 'system-not-active'
30
+ | 'role-permission-denied'
31
+ | 'diagnostic-key-not-allowed'
32
+
33
+ export interface AccessAnswer {
34
+ allowed: boolean
35
+ restrictedBy: AccessRestrictedBy
36
+ reason: AccessReason
37
+ }
38
+
39
+ export interface AccessContextMembership {
40
+ id?: string
41
+ organizationId: string
42
+ role?: string | null
43
+ effectivePermissions?: readonly string[] | null
44
+ }
45
+
46
+ export interface AccessContextProfile {
47
+ id?: string
48
+ isPlatformAdmin?: boolean | null
49
+ is_platform_admin?: boolean | null
50
+ }
51
+
52
+ export interface AccessContext {
53
+ organizationId: string
54
+ organizationModel: OrganizationModel
55
+ membership?: AccessContextMembership | null
56
+ profile?: AccessContextProfile | null
57
+ permissions?: readonly string[] | null
58
+ diagnosticAllowlist?: ReadonlySet<string> | readonly string[]
59
+ accessCatalog?: AccessKeyCatalog
60
+ betaAccessEnabled?: boolean
61
+ isDevelopment?: boolean
62
+ }
63
+
64
+ export interface AccessModel {
65
+ catalog: AccessKeyCatalog
66
+ checkAccess: (key: AccessKeyInput, ctx: Omit<AccessContext, 'accessCatalog'>) => AccessAnswer
67
+ }
68
+
69
+ const ALLOWED: AccessAnswer = { allowed: true, restrictedBy: null, reason: 'allowed' }
70
+ const PLATFORM_ADMIN_BYPASS: AccessAnswer = {
71
+ allowed: true,
72
+ restrictedBy: null,
73
+ reason: 'platform-admin-bypass'
74
+ }
75
+
76
+ function deny(restrictedBy: Exclude<AccessRestrictedBy, null>, reason: Exclude<AccessReason, 'allowed'>): AccessAnswer {
77
+ return { allowed: false, restrictedBy, reason }
78
+ }
79
+
80
+ function isPlatformAdmin(profile: AccessContextProfile | null | undefined): boolean {
81
+ return profile?.isPlatformAdmin === true || profile?.is_platform_admin === true
82
+ }
83
+
84
+ function diagnosticAllowlistHas(
85
+ allowlist: AccessContext['diagnosticAllowlist'],
86
+ systemPath: string
87
+ ): boolean {
88
+ if (allowlist === undefined) return false
89
+ return 'has' in allowlist ? allowlist.has(systemPath) : allowlist.includes(systemPath)
90
+ }
91
+
92
+ function lifecycleAllowsAccess(
93
+ lifecycle: OrganizationModelSystemLifecycle | undefined,
94
+ ctx: Pick<AccessContext, 'betaAccessEnabled' | 'isDevelopment'>
95
+ ): boolean {
96
+ if (lifecycle === 'active') return true
97
+ if (lifecycle === 'beta') return ctx.betaAccessEnabled === true || ctx.isDevelopment === true
98
+ return false
99
+ }
100
+
101
+ function getPermissionSource(ctx: AccessContext): readonly string[] | null | undefined {
102
+ return ctx.permissions ?? ctx.membership?.effectivePermissions
103
+ }
104
+
105
+ function hasRequiredPermission(key: NormalizedAccessKey, rolePermission: string | undefined, ctx: AccessContext): boolean {
106
+ const permissionSource = getPermissionSource(ctx)
107
+ if (permissionSource === undefined || permissionSource === null) return true
108
+
109
+ const requiredPermission = rolePermission ?? `${key.systemPath}.${key.action}`
110
+ return permissionSource.includes(requiredPermission)
111
+ }
112
+
113
+ function hasExplicitRequiredPermission(rolePermission: string | undefined, ctx: AccessContext): boolean {
114
+ const permissionSource = getPermissionSource(ctx)
115
+ return rolePermission !== undefined && permissionSource !== undefined && permissionSource !== null
116
+ ? permissionSource.includes(rolePermission)
117
+ : false
118
+ }
119
+
120
+ export function checkAccess(input: AccessKeyInput, ctx: AccessContext): AccessAnswer {
121
+ if (isPlatformAdmin(ctx.profile)) return PLATFORM_ADMIN_BYPASS
122
+
123
+ const parsed = (() => {
124
+ try {
125
+ return normalizeAccessKey(input)
126
+ } catch {
127
+ return null
128
+ }
129
+ })()
130
+
131
+ if (parsed === null) return deny('catalog', 'invalid-access-key')
132
+
133
+ const catalog = ctx.accessCatalog ?? deriveAccessKeyCatalog(ctx.organizationModel)
134
+ const catalogEntry = findAccessCatalogEntry(catalog, parsed)
135
+
136
+ if (catalogEntry === undefined) return deny('catalog', 'unknown-access-key')
137
+
138
+ const membership = ctx.membership
139
+ if (membership === undefined || membership === null) return deny('membership', 'missing-membership')
140
+ if (membership.organizationId !== ctx.organizationId) return deny('membership', 'organization-mismatch')
141
+
142
+ if (parsed.systemPath === PLATFORM_ADMIN_ACCESS_KEY) {
143
+ return deny('role-permission', 'role-permission-denied')
144
+ }
145
+
146
+ if (catalogEntry.source === 'diagnostic') {
147
+ if (!diagnosticAllowlistHas(ctx.diagnosticAllowlist, parsed.systemPath)) {
148
+ return deny('diagnostic-allowlist', 'diagnostic-key-not-allowed')
149
+ }
150
+
151
+ if (parsed.action !== DEFAULT_ACCESS_ACTION && !hasRequiredPermission(parsed, catalogEntry.rolePermission, ctx)) {
152
+ return deny('role-permission', 'role-permission-denied')
153
+ }
154
+
155
+ return ALLOWED
156
+ }
157
+
158
+ if (catalogEntry.source === 'permission') {
159
+ if (!hasExplicitRequiredPermission(catalogEntry.rolePermission, ctx)) {
160
+ return deny('role-permission', 'role-permission-denied')
161
+ }
162
+
163
+ return ALLOWED
164
+ }
165
+
166
+ const system = getSystem(ctx.organizationModel, parsed.systemPath)
167
+ if (system === undefined || !lifecycleAllowsAccess(system.lifecycle, ctx)) {
168
+ return deny('system-lifecycle', 'system-not-active')
169
+ }
170
+
171
+ if (parsed.action !== DEFAULT_ACCESS_ACTION && !hasRequiredPermission(parsed, catalogEntry.rolePermission, ctx)) {
172
+ return deny('role-permission', 'role-permission-denied')
173
+ }
174
+
175
+ return ALLOWED
176
+ }
177
+
178
+ export function createAccessModel(organizationModel: OrganizationModel): AccessModel {
179
+ const catalog = deriveAccessKeyCatalog(organizationModel)
180
+
181
+ return {
182
+ catalog,
183
+ checkAccess: (key, ctx) => checkAccess(key, { ...ctx, organizationModel, accessCatalog: catalog })
184
+ }
185
+ }
package/src/auth/index.ts CHANGED
@@ -4,5 +4,9 @@
4
4
  * Identity and multi-tenancy types
5
5
  */
6
6
 
7
- // Multi-tenancy types (browser-safe only)
8
- export * from './multi-tenancy/index'
7
+ // Multi-tenancy types (browser-safe only)
8
+ export * from './multi-tenancy/index'
9
+
10
+ // Unified access model primitives (browser-safe only)
11
+ export * from './access-keys'
12
+ export * from './access-model'
@@ -1,5 +1,4 @@
1
- import type { MembershipFeatureConfig } from '../types'
2
- import { type MembershipStatus } from './api-schemas.js'
1
+ import { type MembershipStatus } from './api-schemas.js'
3
2
 
4
3
  export type { MembershipStatus }
5
4
 
@@ -75,8 +74,7 @@ export interface MembershipWithDetails extends OrganizationMembership {
75
74
  metadata?: Record<string, unknown>
76
75
  config?: Record<string, unknown>
77
76
  }
78
- config?: MembershipFeatureConfig
79
- }
77
+ }
80
78
 
81
79
  /**
82
80
  * UI-specific membership table row data
@@ -4,7 +4,7 @@
4
4
  * Source of truth for the permission keys used by:
5
5
  * - RLS policies in Supabase (via has_org_permission(org_id, key))
6
6
  * - API middleware (via requireOrganizationPermission(key))
7
- * - UI hooks (via useOrganizationPermissions().hasPermission(key))
7
+ * - UI access checks (via useAccess() permission-backed AccessKeys)
8
8
  *
9
9
  * The DB table `org_rol_permissions` mirrors this constant. There is no
10
10
  * runtime reconciler; parity is enforced two ways:
@@ -3,23 +3,14 @@
3
3
  *
4
4
  * Config is stored in dedicated `config` columns (NOT nested in metadata):
5
5
  * - organizations.config: Org-level config (no feature toggles -- all features available by default)
6
- * - org_memberships.config: Per-user-per-org feature overrides
6
+ * - org_memberships.config: Reserved for non-access membership configuration
7
7
  * - users.config: User-global config
8
8
  */
9
9
 
10
10
  import type { ThemePresetName } from './theme-presets'
11
11
 
12
- /**
13
- * Per-user-per-org config (stored in org_memberships.config)
14
- * Controls which features a specific member can access within their org.
15
- * Keys are feature IDs from the organization model (e.g. crm, lead-gen, projects, seo).
16
- */
17
- export interface MembershipFeatureConfig {
18
- features?: Record<string, boolean>
19
- }
20
-
21
- /**
22
- * User-global config (stored in users.config)
12
+ /**
13
+ * User-global config (stored in users.config)
23
14
  * Theme and onboarding are user-specific, NOT org-specific
24
15
  */
25
16
  export interface UserConfig {
@@ -7,7 +7,9 @@ description: Terminology disambiguation for Organization OS concepts used in the
7
7
 
8
8
  ## Terms
9
9
 
10
- **AdminGuard** -- route-level admin wrapper from `@elevasis/ui/features/auth`. Must nest inside `ProtectedRoute`.
10
+ **AccessGuard** -- route-level and section-level access wrapper from `@elevasis/ui/auth`. It consumes the unified Access Model and gates on an `accessKey`.
11
+
12
+ **AccessKeys** -- exported access-key constants from `@elevasis/core/auth` / `@repo/core/auth` for platform-admin, diagnostic, and permission-backed gates.
11
13
 
12
14
  **Contract** -- the publishable boundary a consumer depends on: Zod schemas, TypeScript types, provider props, resource definitions, or workflow I/O schemas.
13
15
 
@@ -15,7 +17,7 @@ description: Terminology disambiguation for Organization OS concepts used in the
15
17
 
16
18
  **Feature** -- legacy or UI-package wording for a platform capability area. In the current Organization Model, use **System** for semantic ownership and **navigation surface** for shell placement. Keep "feature" only when referring to existing UI package folders, exported manifest names, or legacy compatibility recipes.
17
19
 
18
- **SystemGuard** -- route-level System gate from `@elevasis/ui/features/auth`.
20
+ **SystemGuard** -- retired route-level System gate. Use **AccessGuard** with a System path or `AccessKeys` constant.
19
21
 
20
22
  **SystemModule** -- manifest contract a shell module provides to `ElevasisSystemsProvider`. Key fields are `key`, optional `systemId`, optional `routePrefixes`, optional `capabilityIds`, optional `icon`, optional `sidebar`, and optional `sidebarWidth`. Graph bridge metadata is compatibility-only; new semantic bindings belong in the Organization Model System, ontology, navigation, and Resource descriptors.
21
23
 
@@ -29,13 +31,13 @@ description: Terminology disambiguation for Organization OS concepts used in the
29
31
 
30
32
  **Manifest** -- a runtime declaration for a feature or resource collection.
31
33
 
32
- **MembershipFeatureConfig** -- legacy per-member feature override config. Current System visibility should be authored through Organization Model System lifecycle/access metadata and resolved through provider compatibility layers for older consumers.
34
+ **MembershipFeatureConfig** -- retired per-member feature override config. The migration is complete: access is resolved through the unified Access Model using Organization Model System lifecycle, role permissions, diagnostic allowlists, membership scope, and platform-admin bypass.
33
35
 
34
36
  **OrganizationModel** -- top-level semantic contract for an organization. Current primary fields include `version`, `domainMetadata`, `branding`, `navigation`, `ontology`, `systems`, `resources`, `topology`, `identity`, `customers`, `offerings`, `roles`, `goals`, `policies`, `statuses`, and `knowledge`. Legacy domain keys such as `sales`, `prospecting`, `projects`, `actions`, and `entities` remain compatibility inputs while projects migrate to System-owned ontology/config/resource contracts.
35
37
 
36
38
  **OrganizationModelSystemEntry** -- System node in `OrganizationModel.systems`. Primary authoring fields include `id`, `label`, `description`, `parentSystemId`, `systems`, `lifecycle`, `ui`, `requiresAdmin`, `devOnly`, `responsibleRoleId`, `governedByKnowledge`, `drivesGoals`, `actions`, `policies`, `ontology`, `config`, and `order`. `subsystems` and `content` are retained compatibility inputs for older projects and should not be used for new recursive Systems, schemas, catalogs, or config.
37
39
 
38
- **Provider / ElevasisSystemsProvider** -- runtime that registers System modules, resolves System access against the org model, projects sidebar navigation, and exposes shell helpers through `useElevasisSystems()`.
40
+ **Provider / ElevasisSystemsProvider** -- runtime that registers System modules, resolves System lifecycle against the org model, projects sidebar navigation, and exposes shell helpers through `useElevasisSystems()`.
39
41
 
40
42
  **Resource** -- governance-only descriptor in `OrganizationModel.resources` for a workflow, agent, integration, or script. Runtime code derives `resourceId` and kind from the descriptor, then attaches executable behavior in operations.
41
43
 
@@ -62,13 +64,13 @@ description: Terminology disambiguation for Organization OS concepts used in the
62
64
  - `OrganizationModel`, `OrganizationModelSystemEntry`
63
65
  - `SystemEntry`, `ResourceEntry`
64
66
  - `resolveOrganizationModel`, `defineOrganizationModel`, `DEFAULT_ORGANIZATION_MODEL`
65
- - `MembershipFeatureConfig`
67
+ - `AccessKeys`, `checkAccess`, `createAccessModel`
66
68
  - `DeploymentSpec`, `ResourceLink`, `ResourceCategory`
67
69
 
68
70
  **`@elevasis/ui`**
69
71
 
70
72
  - `SystemModule`
71
- - `SystemGuard`, `AdminGuard`, `ProtectedRoute`
73
+ - `AccessGuard`, `ProtectedRoute`
72
74
  - `ElevasisSystemsProvider`, `ElevasisCoreProvider`, `useElevasisSystems`
73
75
 
74
76
  **External project source**
@@ -2965,6 +2965,10 @@ export type Database = {
2965
2965
  Returns: boolean
2966
2966
  }
2967
2967
  current_user_is_platform_admin: { Args: never; Returns: boolean }
2968
+ current_user_shares_org_with: {
2969
+ Args: { other_user_id: string }
2970
+ Returns: boolean
2971
+ }
2968
2972
  current_user_supabase_id: { Args: never; Returns: string }
2969
2973
  detect_stalled_executions: { Args: never; Returns: undefined }
2970
2974
  execute_session_turn: {
@@ -2985,6 +2989,12 @@ export type Database = {
2985
2989
  get_platform_credential_kek: { Args: never; Returns: string }
2986
2990
  get_storage_org_id: { Args: { file_path: string }; Returns: string }
2987
2991
  get_workos_user_id: { Args: never; Returns: string }
2992
+ has_org_access:
2993
+ | {
2994
+ Args: { action?: string; org_id: string; system_path: string }
2995
+ Returns: boolean
2996
+ }
2997
+ | { Args: { action?: string; system_path: string }; Returns: boolean }
2988
2998
  has_org_permission: {
2989
2999
  Args: { org_id: string; perm_key: string }
2990
3000
  Returns: boolean