@elevasis/core 0.32.0 → 0.33.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.
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.js +7 -0
- package/package.json +1 -1
- package/src/auth/__tests__/access-keys.test.ts +16 -0
- package/src/auth/__tests__/access-model.test.ts +31 -0
- package/src/auth/access-keys.ts +1 -0
- package/src/auth/multi-tenancy/permissions.ts +19 -13
- package/src/organization-model/__tests__/define-domain-record.test.ts +31 -34
package/dist/auth/index.d.ts
CHANGED
|
@@ -123,6 +123,7 @@ declare const PERMISSIONS: {
|
|
|
123
123
|
readonly SECRETS_MANAGE: "secrets.manage";
|
|
124
124
|
readonly OPERATIONS_READ: "operations.read";
|
|
125
125
|
readonly OPERATIONS_MANAGE: "operations.manage";
|
|
126
|
+
readonly SALES_LEAD_GEN_MANAGE: "sales.lead-gen.manage";
|
|
126
127
|
readonly ACQUISITION_MANAGE: "acquisition.manage";
|
|
127
128
|
readonly PROJECTS_MANAGE: "projects.manage";
|
|
128
129
|
readonly CLIENTS_MANAGE: "clients.manage";
|
|
@@ -5262,6 +5263,10 @@ declare const AccessKeys: {
|
|
|
5262
5263
|
readonly systemPath: "permission.operations";
|
|
5263
5264
|
readonly action: "manage";
|
|
5264
5265
|
};
|
|
5266
|
+
readonly leadGenManage: {
|
|
5267
|
+
readonly systemPath: "sales.lead-gen";
|
|
5268
|
+
readonly action: "manage";
|
|
5269
|
+
};
|
|
5265
5270
|
readonly acquisitionManage: {
|
|
5266
5271
|
readonly systemPath: "permission.acquisition";
|
|
5267
5272
|
readonly action: "manage";
|
package/dist/auth/index.js
CHANGED
|
@@ -35,6 +35,7 @@ var PERMISSIONS = {
|
|
|
35
35
|
SECRETS_MANAGE: "secrets.manage",
|
|
36
36
|
OPERATIONS_READ: "operations.read",
|
|
37
37
|
OPERATIONS_MANAGE: "operations.manage",
|
|
38
|
+
SALES_LEAD_GEN_MANAGE: "sales.lead-gen.manage",
|
|
38
39
|
ACQUISITION_MANAGE: "acquisition.manage",
|
|
39
40
|
PROJECTS_MANAGE: "projects.manage",
|
|
40
41
|
CLIENTS_MANAGE: "clients.manage"
|
|
@@ -80,6 +81,11 @@ var PERMISSION_CATALOG = [
|
|
|
80
81
|
description: "Run and modify executions, sessions, schedules, queue",
|
|
81
82
|
isOrgGrantable: true
|
|
82
83
|
},
|
|
84
|
+
{
|
|
85
|
+
key: "sales.lead-gen.manage",
|
|
86
|
+
description: "Operate Lead Gen lists and list-builder workflows",
|
|
87
|
+
isOrgGrantable: true
|
|
88
|
+
},
|
|
83
89
|
{
|
|
84
90
|
key: "acquisition.manage",
|
|
85
91
|
description: "Create, update, and delete acquisition records (acq_companies, acq_contacts, acq_deals, acq_lists*, acq_content*, acquisition storage files)",
|
|
@@ -421,6 +427,7 @@ var AccessKeys = {
|
|
|
421
427
|
secretsManage: { systemPath: "permission.secrets", action: "manage" },
|
|
422
428
|
operationsRead: { systemPath: "permission.operations", action: DEFAULT_ACCESS_ACTION },
|
|
423
429
|
operationsManage: { systemPath: "permission.operations", action: "manage" },
|
|
430
|
+
leadGenManage: { systemPath: "sales.lead-gen", action: "manage" },
|
|
424
431
|
acquisitionManage: { systemPath: "permission.acquisition", action: "manage" },
|
|
425
432
|
projectsManage: { systemPath: "permission.projects", action: "manage" },
|
|
426
433
|
clientsManage: { systemPath: "permission.clients", action: "manage" },
|
package/package.json
CHANGED
|
@@ -23,6 +23,12 @@ const model = {
|
|
|
23
23
|
label: 'CRM',
|
|
24
24
|
lifecycle: 'active',
|
|
25
25
|
order: 10
|
|
26
|
+
},
|
|
27
|
+
'lead-gen': {
|
|
28
|
+
id: 'lead-gen',
|
|
29
|
+
label: 'Lead Gen',
|
|
30
|
+
lifecycle: 'active',
|
|
31
|
+
order: 20
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
},
|
|
@@ -53,6 +59,7 @@ describe('access keys', () => {
|
|
|
53
59
|
expect(keys).toContainEqual({ systemPath: 'sales', action: 'view' })
|
|
54
60
|
expect(keys).toContainEqual({ systemPath: 'sales.crm', action: 'view' })
|
|
55
61
|
expect(keys).toContainEqual({ systemPath: 'sales.crm', action: 'manage' })
|
|
62
|
+
expect(keys).toContainEqual(AccessKeys.leadGenManage)
|
|
56
63
|
expect(keys).toContainEqual({ systemPath: 'operations', action: 'manage' })
|
|
57
64
|
})
|
|
58
65
|
|
|
@@ -78,4 +85,13 @@ describe('access keys', () => {
|
|
|
78
85
|
rolePermission: 'members.manage'
|
|
79
86
|
})
|
|
80
87
|
})
|
|
88
|
+
|
|
89
|
+
it('maps the Lead Gen manage AccessKey to the OM System permission', () => {
|
|
90
|
+
const catalog = deriveAccessKeyCatalog(model)
|
|
91
|
+
|
|
92
|
+
expect(findAccessCatalogEntry(catalog, AccessKeys.leadGenManage)).toMatchObject({
|
|
93
|
+
source: 'om-system',
|
|
94
|
+
rolePermission: 'sales.lead-gen.manage'
|
|
95
|
+
})
|
|
96
|
+
})
|
|
81
97
|
})
|
|
@@ -17,6 +17,12 @@ const organizationModel = {
|
|
|
17
17
|
label: 'CRM',
|
|
18
18
|
lifecycle: 'active',
|
|
19
19
|
order: 10
|
|
20
|
+
},
|
|
21
|
+
'lead-gen': {
|
|
22
|
+
id: 'lead-gen',
|
|
23
|
+
label: 'Lead Gen',
|
|
24
|
+
lifecycle: 'active',
|
|
25
|
+
order: 20
|
|
20
26
|
}
|
|
21
27
|
}
|
|
22
28
|
},
|
|
@@ -179,6 +185,31 @@ describe('checkAccess', () => {
|
|
|
179
185
|
})
|
|
180
186
|
})
|
|
181
187
|
|
|
188
|
+
it('allows Lead Gen manage only with the explicit OM System permission', () => {
|
|
189
|
+
expect(
|
|
190
|
+
checkAccess(
|
|
191
|
+
AccessKeys.leadGenManage,
|
|
192
|
+
context({
|
|
193
|
+
membership: {
|
|
194
|
+
id: 'membership-1',
|
|
195
|
+
organizationId: 'org-1',
|
|
196
|
+
effectivePermissions: ['sales.lead-gen.manage']
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
)
|
|
200
|
+
).toEqual({
|
|
201
|
+
allowed: true,
|
|
202
|
+
restrictedBy: null,
|
|
203
|
+
reason: 'allowed'
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
expect(checkAccess(AccessKeys.leadGenManage, context())).toEqual({
|
|
207
|
+
allowed: false,
|
|
208
|
+
restrictedBy: 'role-permission',
|
|
209
|
+
reason: 'role-permission-denied'
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
|
|
182
213
|
it('requires explicit role permissions for permission-only access keys', () => {
|
|
183
214
|
expect(
|
|
184
215
|
checkAccess(
|
package/src/auth/access-keys.ts
CHANGED
|
@@ -54,6 +54,7 @@ export const AccessKeys = {
|
|
|
54
54
|
secretsManage: { systemPath: 'permission.secrets', action: 'manage' },
|
|
55
55
|
operationsRead: { systemPath: 'permission.operations', action: DEFAULT_ACCESS_ACTION },
|
|
56
56
|
operationsManage: { systemPath: 'permission.operations', action: 'manage' },
|
|
57
|
+
leadGenManage: { systemPath: 'sales.lead-gen', action: 'manage' },
|
|
57
58
|
acquisitionManage: { systemPath: 'permission.acquisition', action: 'manage' },
|
|
58
59
|
projectsManage: { systemPath: 'permission.projects', action: 'manage' },
|
|
59
60
|
clientsManage: { systemPath: 'permission.clients', action: 'manage' },
|
|
@@ -32,12 +32,13 @@ export const PERMISSIONS = {
|
|
|
32
32
|
MEMBERS_MANAGE: 'members.manage',
|
|
33
33
|
ROLES_MANAGE: 'roles.manage',
|
|
34
34
|
SECRETS_MANAGE: 'secrets.manage',
|
|
35
|
-
OPERATIONS_READ: 'operations.read',
|
|
36
|
-
OPERATIONS_MANAGE: 'operations.manage',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
OPERATIONS_READ: 'operations.read',
|
|
36
|
+
OPERATIONS_MANAGE: 'operations.manage',
|
|
37
|
+
SALES_LEAD_GEN_MANAGE: 'sales.lead-gen.manage',
|
|
38
|
+
ACQUISITION_MANAGE: 'acquisition.manage',
|
|
39
|
+
PROJECTS_MANAGE: 'projects.manage',
|
|
40
|
+
CLIENTS_MANAGE: 'clients.manage'
|
|
41
|
+
} as const
|
|
41
42
|
|
|
42
43
|
export type PermissionKey = (typeof PERMISSIONS)[keyof typeof PERMISSIONS]
|
|
43
44
|
|
|
@@ -89,13 +90,18 @@ export const PERMISSION_CATALOG: readonly PermissionDescriptor[] = [
|
|
|
89
90
|
description: 'View executions, sessions, schedules, and command queue',
|
|
90
91
|
isOrgGrantable: true
|
|
91
92
|
},
|
|
92
|
-
{
|
|
93
|
-
key: 'operations.manage',
|
|
94
|
-
description: 'Run and modify executions, sessions, schedules, queue',
|
|
95
|
-
isOrgGrantable: true
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
key: '
|
|
93
|
+
{
|
|
94
|
+
key: 'operations.manage',
|
|
95
|
+
description: 'Run and modify executions, sessions, schedules, queue',
|
|
96
|
+
isOrgGrantable: true
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
key: 'sales.lead-gen.manage',
|
|
100
|
+
description: 'Operate Lead Gen lists and list-builder workflows',
|
|
101
|
+
isOrgGrantable: true
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
key: 'acquisition.manage',
|
|
99
105
|
description:
|
|
100
106
|
'Create, update, and delete acquisition records (acq_companies, acq_contacts, acq_deals, acq_lists*, acq_content*, acquisition storage files)',
|
|
101
107
|
isOrgGrantable: false
|
|
@@ -216,45 +216,42 @@ describe.each([
|
|
|
216
216
|
idField: 'id' as const,
|
|
217
217
|
invalidOverride: { kind: 'invalid-kind' }
|
|
218
218
|
}
|
|
219
|
-
])(
|
|
220
|
-
'
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
expect((result as Record<string, unknown>)[idField]).toBe((valid as Record<string, unknown>)[idField])
|
|
226
|
-
})
|
|
219
|
+
])('define$domain — $domain', ({ domain: _domain, defineSingle, defineMultiple, valid, idField, invalidOverride }) => {
|
|
220
|
+
it('defineX — validates and returns a parsed entry', () => {
|
|
221
|
+
const result = defineSingle(valid as never)
|
|
222
|
+
expect(result).toHaveProperty(idField)
|
|
223
|
+
expect((result as Record<string, unknown>)[idField]).toBe((valid as Record<string, unknown>)[idField])
|
|
224
|
+
})
|
|
227
225
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
it('defineX — throws ZodError on invalid input', () => {
|
|
227
|
+
const bad = { ...valid, ...invalidOverride } as never
|
|
228
|
+
expect(() => defineSingle(bad)).toThrow(z.ZodError)
|
|
229
|
+
})
|
|
232
230
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
231
|
+
it('defineXs — produces an id-keyed map', () => {
|
|
232
|
+
const result = defineMultiple([valid] as never[])
|
|
233
|
+
const id = (valid as Record<string, unknown>)[idField] as string
|
|
234
|
+
expect(result).toHaveProperty(id)
|
|
235
|
+
expect((result[id] as Record<string, unknown>)[idField]).toBe(id)
|
|
236
|
+
})
|
|
239
237
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
238
|
+
it('defineXs — throws ZodError on invalid input', () => {
|
|
239
|
+
const bad = { ...valid, ...invalidOverride } as never
|
|
240
|
+
expect(() => defineMultiple([bad] as never[])).toThrow(z.ZodError)
|
|
241
|
+
})
|
|
244
242
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
243
|
+
it('defineXs — returns empty map for empty array', () => {
|
|
244
|
+
const result = defineMultiple([] as never[])
|
|
245
|
+
expect(result).toEqual({})
|
|
246
|
+
})
|
|
249
247
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
)
|
|
248
|
+
it('defineXs — validates through schema (no bypass)', () => {
|
|
249
|
+
// Confirm that defineMultiple uses schema.parse, not a pass-through.
|
|
250
|
+
// Missing required fields should throw even if the object looks similar.
|
|
251
|
+
const missingRequired = { [idField]: (valid as Record<string, unknown>)[idField] } as never
|
|
252
|
+
expect(() => defineMultiple([missingRequired] as never[])).toThrow(z.ZodError)
|
|
253
|
+
})
|
|
254
|
+
})
|
|
258
255
|
|
|
259
256
|
// ---------------------------------------------------------------------------
|
|
260
257
|
// Topology — existing helpers (defineTopology, defineTopologyRelationship)
|