@elevasis/core 0.2.0 → 0.3.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/index.d.ts +60 -103
- package/dist/index.js +162 -109
- package/dist/organization-model/index.d.ts +60 -103
- package/dist/organization-model/index.js +162 -109
- package/package.json +1 -1
- package/src/README.md +24 -17
- package/src/__tests__/template-foundations-compatibility.test.ts +28 -36
- package/src/auth/multi-tenancy/types.ts +4 -11
- package/src/auth/multi-tenancy/users/api-schemas.ts +1 -1
- package/src/business/base-entities.test.ts +481 -0
- package/src/business/base-entities.ts +241 -0
- package/src/business/delivery/types.ts +1 -1
- package/src/business/index.ts +3 -0
- package/src/execution/index.ts +3 -6
- package/src/index.ts +1 -1
- package/src/organization-model/README.md +25 -26
- package/src/organization-model/__tests__/graph.test.ts +103 -71
- package/src/organization-model/__tests__/resolve.test.ts +20 -29
- package/src/organization-model/contracts.ts +3 -0
- package/src/organization-model/defaults.ts +40 -6
- package/src/organization-model/domains/features.ts +19 -54
- package/src/organization-model/domains/navigation.ts +25 -16
- package/src/organization-model/domains/shared.ts +1 -10
- package/src/organization-model/foundation.ts +96 -0
- package/src/organization-model/graph/build.ts +34 -67
- package/src/organization-model/graph/schema.ts +2 -4
- package/src/organization-model/graph/types.ts +3 -15
- package/src/organization-model/index.ts +2 -0
- package/src/organization-model/organization-model.mdx +34 -36
- package/src/organization-model/published.ts +12 -3
- package/src/organization-model/schema.ts +38 -34
- package/src/organization-model/types.ts +5 -10
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/sse/events.ts +1 -34
- package/src/projects/api-schemas.ts +2 -1
- package/src/reference/_generated/contracts.md +10 -31
- package/src/reference/glossary.md +14 -18
- package/src/supabase/database.types.ts +0 -107
- package/src/test-utils/rls/RLSTestContext.ts +1 -31
- package/src/execution/calibration/__tests__/schemas.test.ts +0 -320
- package/src/execution/calibration/index.ts +0 -3
- package/src/execution/calibration/schemas.ts +0 -121
- package/src/execution/calibration/sse-events.ts +0 -125
- package/src/execution/calibration/types.ts +0 -190
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import type { OrganizationModel } from './types'
|
|
2
|
+
import {
|
|
3
|
+
DELIVERY_PROJECTS_VIEW_CAPABILITY_ID,
|
|
4
|
+
PROJECTS_FEATURE_ID,
|
|
5
|
+
PROJECTS_INDEX_SURFACE_ID
|
|
6
|
+
} from './contracts'
|
|
2
7
|
import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from './domains/branding'
|
|
3
8
|
import { DEFAULT_ORGANIZATION_MODEL_CRM } from './domains/crm'
|
|
4
9
|
import { DEFAULT_ORGANIZATION_MODEL_DELIVERY } from './domains/delivery'
|
|
5
|
-
import { DEFAULT_ORGANIZATION_MODEL_FEATURES } from './domains/features'
|
|
6
10
|
import { DEFAULT_ORGANIZATION_MODEL_LEAD_GEN } from './domains/lead-gen'
|
|
7
11
|
import { DEFAULT_ORGANIZATION_MODEL_NAVIGATION } from './domains/navigation'
|
|
8
12
|
|
|
9
13
|
export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
10
14
|
version: 1,
|
|
11
|
-
|
|
15
|
+
features: [
|
|
12
16
|
{
|
|
13
17
|
id: 'crm',
|
|
14
18
|
label: 'CRM',
|
|
15
19
|
description: 'Relationship pipeline and deal management',
|
|
20
|
+
enabled: true,
|
|
16
21
|
color: 'blue',
|
|
17
22
|
entityIds: ['crm.deal'],
|
|
18
23
|
surfaceIds: ['crm.pipeline'],
|
|
@@ -23,6 +28,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
|
23
28
|
id: 'lead-gen',
|
|
24
29
|
label: 'Lead Gen',
|
|
25
30
|
description: 'Prospecting, qualification, and outreach preparation',
|
|
31
|
+
enabled: true,
|
|
26
32
|
color: 'cyan',
|
|
27
33
|
entityIds: ['leadgen.list', 'leadgen.company', 'leadgen.contact'],
|
|
28
34
|
surfaceIds: ['lead-gen.lists'],
|
|
@@ -30,28 +36,56 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
|
30
36
|
capabilityIds: ['leadgen.lists.manage']
|
|
31
37
|
},
|
|
32
38
|
{
|
|
33
|
-
id:
|
|
39
|
+
id: PROJECTS_FEATURE_ID,
|
|
34
40
|
label: 'Projects',
|
|
35
41
|
description: 'Projects, milestones, and client work execution',
|
|
42
|
+
enabled: true,
|
|
36
43
|
color: 'orange',
|
|
37
44
|
entityIds: ['delivery.project', 'delivery.milestone', 'delivery.task'],
|
|
38
|
-
surfaceIds: [
|
|
45
|
+
surfaceIds: [PROJECTS_INDEX_SURFACE_ID],
|
|
39
46
|
resourceIds: [],
|
|
40
|
-
capabilityIds: [
|
|
47
|
+
capabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
|
|
41
48
|
},
|
|
42
49
|
{
|
|
43
50
|
id: 'operations',
|
|
44
51
|
label: 'Operations',
|
|
45
52
|
description: 'Operational resources, topology, and orchestration visibility',
|
|
53
|
+
enabled: true,
|
|
46
54
|
color: 'violet',
|
|
47
55
|
entityIds: [],
|
|
48
56
|
surfaceIds: ['operations.organization-graph', 'operations.command-view'],
|
|
49
57
|
resourceIds: [],
|
|
50
58
|
capabilityIds: ['operations.organization-graph', 'operations.command-view']
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'monitoring',
|
|
62
|
+
label: 'Monitoring',
|
|
63
|
+
enabled: true,
|
|
64
|
+
entityIds: [],
|
|
65
|
+
surfaceIds: [],
|
|
66
|
+
resourceIds: [],
|
|
67
|
+
capabilityIds: []
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'settings',
|
|
71
|
+
label: 'Settings',
|
|
72
|
+
enabled: true,
|
|
73
|
+
entityIds: [],
|
|
74
|
+
surfaceIds: [],
|
|
75
|
+
resourceIds: [],
|
|
76
|
+
capabilityIds: []
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'seo',
|
|
80
|
+
label: 'SEO',
|
|
81
|
+
enabled: false,
|
|
82
|
+
entityIds: [],
|
|
83
|
+
surfaceIds: [],
|
|
84
|
+
resourceIds: [],
|
|
85
|
+
capabilityIds: []
|
|
51
86
|
}
|
|
52
87
|
],
|
|
53
88
|
branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
|
|
54
|
-
features: DEFAULT_ORGANIZATION_MODEL_FEATURES,
|
|
55
89
|
navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
|
|
56
90
|
crm: DEFAULT_ORGANIZATION_MODEL_CRM,
|
|
57
91
|
leadGen: DEFAULT_ORGANIZATION_MODEL_LEAD_GEN,
|
|
@@ -1,57 +1,22 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
+
import {
|
|
3
|
+
ColorTokenSchema,
|
|
4
|
+
DescriptionSchema,
|
|
5
|
+
IconNameSchema,
|
|
6
|
+
LabelSchema,
|
|
7
|
+
ModelIdSchema,
|
|
8
|
+
ReferenceIdsSchema
|
|
9
|
+
} from './shared'
|
|
2
10
|
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
enabled: z
|
|
15
|
-
.object({
|
|
16
|
-
acquisition: z.boolean().default(true),
|
|
17
|
-
delivery: z.boolean().default(true),
|
|
18
|
-
operations: z.boolean().default(true),
|
|
19
|
-
monitoring: z.boolean().default(true),
|
|
20
|
-
settings: z.boolean().default(true),
|
|
21
|
-
seo: z.boolean().default(false),
|
|
22
|
-
calibration: z.boolean().default(false)
|
|
23
|
-
})
|
|
24
|
-
.default({
|
|
25
|
-
acquisition: true,
|
|
26
|
-
delivery: true,
|
|
27
|
-
operations: true,
|
|
28
|
-
monitoring: true,
|
|
29
|
-
settings: true,
|
|
30
|
-
seo: false,
|
|
31
|
-
calibration: false
|
|
32
|
-
}),
|
|
33
|
-
labels: z
|
|
34
|
-
.object({
|
|
35
|
-
acquisition: z.string().trim().min(1).max(80).optional(),
|
|
36
|
-
delivery: z.string().trim().min(1).max(80).optional(),
|
|
37
|
-
operations: z.string().trim().min(1).max(80).optional(),
|
|
38
|
-
monitoring: z.string().trim().min(1).max(80).optional(),
|
|
39
|
-
settings: z.string().trim().min(1).max(80).optional(),
|
|
40
|
-
seo: z.string().trim().min(1).max(80).optional(),
|
|
41
|
-
calibration: z.string().trim().min(1).max(80).optional()
|
|
42
|
-
})
|
|
43
|
-
.default({})
|
|
11
|
+
export const FeatureSchema = z.object({
|
|
12
|
+
id: ModelIdSchema,
|
|
13
|
+
label: LabelSchema,
|
|
14
|
+
description: DescriptionSchema.optional(),
|
|
15
|
+
enabled: z.boolean().default(true),
|
|
16
|
+
color: ColorTokenSchema.optional(),
|
|
17
|
+
icon: IconNameSchema.optional(),
|
|
18
|
+
entityIds: ReferenceIdsSchema,
|
|
19
|
+
surfaceIds: ReferenceIdsSchema,
|
|
20
|
+
resourceIds: ReferenceIdsSchema,
|
|
21
|
+
capabilityIds: ReferenceIdsSchema
|
|
44
22
|
})
|
|
45
|
-
|
|
46
|
-
export const DEFAULT_ORGANIZATION_MODEL_FEATURES: z.infer<typeof OrganizationModelFeaturesSchema> = {
|
|
47
|
-
enabled: {
|
|
48
|
-
acquisition: true,
|
|
49
|
-
delivery: true,
|
|
50
|
-
operations: true,
|
|
51
|
-
monitoring: true,
|
|
52
|
-
settings: true,
|
|
53
|
-
seo: false,
|
|
54
|
-
calibration: false
|
|
55
|
-
},
|
|
56
|
-
labels: {}
|
|
57
|
-
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DELIVERY_PROJECTS_VIEW_CAPABILITY_ID,
|
|
4
|
+
PROJECTS_FEATURE_ID,
|
|
5
|
+
PROJECTS_INDEX_SURFACE_ID
|
|
6
|
+
} from '../contracts'
|
|
3
7
|
import { DescriptionSchema, IconNameSchema, LabelSchema, ModelIdSchema, PathSchema, ReferenceIdsSchema } from './shared'
|
|
4
8
|
|
|
5
9
|
export const SurfaceTypeSchema = z.enum(['page', 'dashboard', 'graph', 'detail', 'list', 'settings'])
|
|
@@ -11,8 +15,8 @@ export const SurfaceDefinitionSchema = z.object({
|
|
|
11
15
|
surfaceType: SurfaceTypeSchema,
|
|
12
16
|
description: DescriptionSchema.optional(),
|
|
13
17
|
icon: IconNameSchema.optional(),
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
featureId: ModelIdSchema.optional(),
|
|
19
|
+
featureIds: ReferenceIdsSchema,
|
|
16
20
|
entityIds: ReferenceIdsSchema,
|
|
17
21
|
resourceIds: ReferenceIdsSchema,
|
|
18
22
|
capabilityIds: ReferenceIdsSchema,
|
|
@@ -40,8 +44,8 @@ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationM
|
|
|
40
44
|
label: 'Pipeline',
|
|
41
45
|
path: '/crm/pipeline',
|
|
42
46
|
surfaceType: 'graph',
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
featureId: 'crm',
|
|
48
|
+
featureIds: ['crm'],
|
|
45
49
|
entityIds: ['crm.deal'],
|
|
46
50
|
resourceIds: [],
|
|
47
51
|
capabilityIds: ['crm.pipeline.manage']
|
|
@@ -51,30 +55,30 @@ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationM
|
|
|
51
55
|
label: 'Lists',
|
|
52
56
|
path: '/lead-gen/lists',
|
|
53
57
|
surfaceType: 'list',
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
featureId: 'lead-gen',
|
|
59
|
+
featureIds: ['lead-gen'],
|
|
56
60
|
entityIds: ['leadgen.list'],
|
|
57
61
|
resourceIds: [],
|
|
58
62
|
capabilityIds: ['leadgen.lists.manage']
|
|
59
63
|
},
|
|
60
64
|
{
|
|
61
|
-
id:
|
|
65
|
+
id: PROJECTS_INDEX_SURFACE_ID,
|
|
62
66
|
label: 'Projects',
|
|
63
67
|
path: '/projects',
|
|
64
68
|
surfaceType: 'list',
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
featureId: PROJECTS_FEATURE_ID,
|
|
70
|
+
featureIds: [PROJECTS_FEATURE_ID],
|
|
67
71
|
entityIds: ['delivery.project'],
|
|
68
72
|
resourceIds: [],
|
|
69
|
-
capabilityIds: [
|
|
73
|
+
capabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
|
|
70
74
|
},
|
|
71
75
|
{
|
|
72
76
|
id: 'operations.organization-graph',
|
|
73
77
|
label: 'Organization Graph',
|
|
74
78
|
path: '/operations/organization-graph',
|
|
75
79
|
surfaceType: 'graph',
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
featureId: 'operations',
|
|
81
|
+
featureIds: ['operations'],
|
|
78
82
|
entityIds: [],
|
|
79
83
|
resourceIds: [],
|
|
80
84
|
capabilityIds: ['operations.organization-graph']
|
|
@@ -84,15 +88,20 @@ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationM
|
|
|
84
88
|
label: 'Command View',
|
|
85
89
|
path: '/operations/command-view',
|
|
86
90
|
surfaceType: 'graph',
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
featureId: 'operations',
|
|
92
|
+
featureIds: ['operations'],
|
|
89
93
|
entityIds: [],
|
|
90
94
|
resourceIds: [],
|
|
91
95
|
capabilityIds: ['operations.command-view']
|
|
92
96
|
}
|
|
93
97
|
],
|
|
94
98
|
groups: [
|
|
95
|
-
{
|
|
99
|
+
{
|
|
100
|
+
id: 'primary-workspace',
|
|
101
|
+
label: 'Workspace',
|
|
102
|
+
placement: 'primary',
|
|
103
|
+
surfaceIds: ['crm.pipeline', 'lead-gen.lists', PROJECTS_INDEX_SURFACE_ID]
|
|
104
|
+
},
|
|
96
105
|
{
|
|
97
106
|
id: 'primary-operations',
|
|
98
107
|
label: 'Operations',
|
|
@@ -22,21 +22,12 @@ export const DisplayMetadataSchema = z.object({
|
|
|
22
22
|
icon: IconNameSchema.optional()
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
export const SemanticDomainSchema = DisplayMetadataSchema.extend({
|
|
26
|
-
id: ModelIdSchema,
|
|
27
|
-
entityIds: ReferenceIdsSchema,
|
|
28
|
-
surfaceIds: ReferenceIdsSchema,
|
|
29
|
-
resourceIds: ReferenceIdsSchema,
|
|
30
|
-
capabilityIds: ReferenceIdsSchema
|
|
31
|
-
})
|
|
32
|
-
|
|
33
25
|
export const ResourceMappingSchema = DisplayMetadataSchema.extend({
|
|
34
26
|
id: ModelIdSchema,
|
|
35
27
|
resourceId: z.string().trim().min(1).max(255),
|
|
36
28
|
resourceType: z.enum(['workflow', 'agent', 'trigger', 'integration', 'external', 'human_checkpoint']),
|
|
37
|
-
|
|
29
|
+
featureIds: ReferenceIdsSchema,
|
|
38
30
|
entityIds: ReferenceIdsSchema,
|
|
39
31
|
surfaceIds: ReferenceIdsSchema,
|
|
40
32
|
capabilityIds: ReferenceIdsSchema
|
|
41
33
|
})
|
|
42
|
-
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID } from './contracts'
|
|
2
|
+
import { resolveOrganizationModel } from './resolve'
|
|
3
|
+
import type { OrganizationModel, OrganizationModelSurface } from './types'
|
|
4
|
+
|
|
5
|
+
export type FoundationSurfaceType = OrganizationModelSurface['surfaceType']
|
|
6
|
+
|
|
7
|
+
export type FoundationSurfaceIcon = 'dashboard' | 'crm' | 'lead-gen' | 'projects' | 'operations' | 'settings'
|
|
8
|
+
|
|
9
|
+
export interface FoundationNavigationSurface extends Omit<OrganizationModelSurface, 'icon'> {
|
|
10
|
+
icon?: FoundationSurfaceIcon
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface FoundationOrganizationModel extends Omit<OrganizationModel, 'navigation'> {
|
|
14
|
+
navigation: {
|
|
15
|
+
defaultSurfaceId: string
|
|
16
|
+
homeLabel: string
|
|
17
|
+
quickAccessSurfaceIds: readonly string[]
|
|
18
|
+
surfaces: FoundationNavigationSurface[]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FoundationBranding {
|
|
23
|
+
organizationName: string
|
|
24
|
+
productName: string
|
|
25
|
+
shortName: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function createFoundationOrganizationModel(branding: FoundationBranding): {
|
|
29
|
+
canonical: OrganizationModel
|
|
30
|
+
model: FoundationOrganizationModel
|
|
31
|
+
homeLabel: string
|
|
32
|
+
quickAccessSurfaceIds: readonly string[]
|
|
33
|
+
getOrganizationSurface: (surfaceId: string) => FoundationNavigationSurface | undefined
|
|
34
|
+
} {
|
|
35
|
+
const canonical = resolveOrganizationModel({ branding })
|
|
36
|
+
|
|
37
|
+
function requireCoreSurface(surfaceId: string): OrganizationModelSurface {
|
|
38
|
+
const surface = canonical.navigation.surfaces.find((candidate) => candidate.id === surfaceId)
|
|
39
|
+
|
|
40
|
+
if (!surface) {
|
|
41
|
+
throw new Error(`Missing organization surface: ${surfaceId}`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return surface
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const operationsGraphSurface = requireCoreSurface('operations.organization-graph')
|
|
48
|
+
const projectsSurface = requireCoreSurface(PROJECTS_INDEX_SURFACE_ID)
|
|
49
|
+
const leadGenSurface = requireCoreSurface('lead-gen.lists')
|
|
50
|
+
const crmSurface = requireCoreSurface('crm.pipeline')
|
|
51
|
+
|
|
52
|
+
const navigationSurfaces: FoundationNavigationSurface[] = [
|
|
53
|
+
{ ...operationsGraphSurface, id: 'operations', path: '/operations', icon: 'operations' },
|
|
54
|
+
{ ...operationsGraphSurface, path: '/operations', icon: 'operations' },
|
|
55
|
+
{ ...projectsSurface, id: PROJECTS_FEATURE_ID, icon: 'projects' },
|
|
56
|
+
{ ...leadGenSurface, id: 'lead-gen', icon: 'lead-gen' },
|
|
57
|
+
{ ...crmSurface, id: 'crm', icon: 'crm' },
|
|
58
|
+
{
|
|
59
|
+
id: 'settings',
|
|
60
|
+
label: 'Settings',
|
|
61
|
+
path: '/settings/account',
|
|
62
|
+
surfaceType: 'settings',
|
|
63
|
+
icon: 'settings',
|
|
64
|
+
featureId: 'settings',
|
|
65
|
+
featureIds: ['settings'],
|
|
66
|
+
entityIds: [],
|
|
67
|
+
resourceIds: [],
|
|
68
|
+
capabilityIds: []
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
const homeLabel = 'Dashboard'
|
|
73
|
+
const quickAccessSurfaceIds = ['operations', PROJECTS_FEATURE_ID, 'lead-gen', 'crm'] as const
|
|
74
|
+
|
|
75
|
+
const model: FoundationOrganizationModel = {
|
|
76
|
+
...canonical,
|
|
77
|
+
navigation: {
|
|
78
|
+
defaultSurfaceId: 'operations',
|
|
79
|
+
homeLabel,
|
|
80
|
+
quickAccessSurfaceIds: [...quickAccessSurfaceIds],
|
|
81
|
+
surfaces: navigationSurfaces
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getOrganizationSurface(surfaceId: string): FoundationNavigationSurface | undefined {
|
|
86
|
+
return model.navigation.surfaces.find((candidate) => candidate.id === surfaceId)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
canonical,
|
|
91
|
+
model,
|
|
92
|
+
homeLabel,
|
|
93
|
+
quickAccessSurfaceIds,
|
|
94
|
+
getOrganizationSurface
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -73,16 +73,6 @@ function ensureResourceNode(
|
|
|
73
73
|
})
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
function titleCase(value: string): string {
|
|
77
|
-
return value
|
|
78
|
-
.replace(/[-_.]+/g, ' ')
|
|
79
|
-
.replace(/\s+/g, ' ')
|
|
80
|
-
.trim()
|
|
81
|
-
.split(' ')
|
|
82
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
83
|
-
.join(' ')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
76
|
type CommandViewResource =
|
|
87
77
|
| CommandViewData['workflows'][number]
|
|
88
78
|
| CommandViewData['agents'][number]
|
|
@@ -126,38 +116,10 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
126
116
|
}
|
|
127
117
|
pushUniqueNode(nodes, nodeIds, organizationNode)
|
|
128
118
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
key: featureKey,
|
|
134
|
-
enabled,
|
|
135
|
-
label: organizationModel.features.labels[key] ?? titleCase(featureKey)
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
.sort((a, b) => a.key.localeCompare(b.key))
|
|
139
|
-
|
|
140
|
-
for (const feature of featureEntries) {
|
|
141
|
-
const id = nodeId('feature', feature.key)
|
|
142
|
-
pushUniqueNode(nodes, nodeIds, {
|
|
143
|
-
id,
|
|
144
|
-
kind: 'feature',
|
|
145
|
-
label: feature.label,
|
|
146
|
-
sourceId: feature.key,
|
|
147
|
-
enabled: feature.enabled,
|
|
148
|
-
featureKey: feature.key as OrganizationGraphNode['featureKey']
|
|
149
|
-
})
|
|
150
|
-
pushUniqueEdge(edges, edgeIds, {
|
|
151
|
-
id: edgeId('contains', organizationNode.id, id),
|
|
152
|
-
kind: 'contains',
|
|
153
|
-
sourceId: organizationNode.id,
|
|
154
|
-
targetId: id
|
|
155
|
-
})
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const domainMap = new Map<string, (typeof organizationModel.domains)[number]>()
|
|
159
|
-
for (const domain of organizationModel.domains) {
|
|
160
|
-
domainMap.set(domain.id, domain)
|
|
119
|
+
// Build feature map for lookups
|
|
120
|
+
const featureMap = new Map<string, (typeof organizationModel.features)[number]>()
|
|
121
|
+
for (const feature of organizationModel.features) {
|
|
122
|
+
featureMap.set(feature.id, feature)
|
|
161
123
|
}
|
|
162
124
|
|
|
163
125
|
const surfaceMap = new Map<string, (typeof organizationModel.navigation.surfaces)[number]>()
|
|
@@ -167,7 +129,9 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
167
129
|
|
|
168
130
|
const entityIds = new Set<string>()
|
|
169
131
|
const capabilityIds = new Set<string>()
|
|
170
|
-
const resourceMappings = [...organizationModel.resourceMappings].sort((a, b) =>
|
|
132
|
+
const resourceMappings = [...organizationModel.resourceMappings].sort((a, b) =>
|
|
133
|
+
a.resourceId.localeCompare(b.resourceId)
|
|
134
|
+
)
|
|
171
135
|
for (const resourceMapping of resourceMappings) {
|
|
172
136
|
for (const entityId of resourceMapping.entityIds) {
|
|
173
137
|
entityIds.add(entityId)
|
|
@@ -177,14 +141,17 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
177
141
|
}
|
|
178
142
|
}
|
|
179
143
|
|
|
180
|
-
|
|
181
|
-
|
|
144
|
+
// Unified feature loop: creates feature nodes with semantic data (replaces old feature + domain loops)
|
|
145
|
+
for (const feature of [...organizationModel.features].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
146
|
+
const id = nodeId('feature', feature.id)
|
|
182
147
|
pushUniqueNode(nodes, nodeIds, {
|
|
183
148
|
id,
|
|
184
|
-
kind: '
|
|
185
|
-
label:
|
|
186
|
-
sourceId:
|
|
187
|
-
description:
|
|
149
|
+
kind: 'feature',
|
|
150
|
+
label: feature.label,
|
|
151
|
+
sourceId: feature.id,
|
|
152
|
+
description: feature.description,
|
|
153
|
+
enabled: feature.enabled,
|
|
154
|
+
featureId: feature.id
|
|
188
155
|
})
|
|
189
156
|
pushUniqueEdge(edges, edgeIds, {
|
|
190
157
|
id: edgeId('contains', organizationNode.id, id),
|
|
@@ -193,13 +160,13 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
193
160
|
targetId: id
|
|
194
161
|
})
|
|
195
162
|
|
|
196
|
-
for (const entityId of
|
|
163
|
+
for (const entityId of feature.entityIds) {
|
|
197
164
|
entityIds.add(entityId)
|
|
198
165
|
}
|
|
199
|
-
for (const capabilityId of
|
|
166
|
+
for (const capabilityId of feature.capabilityIds) {
|
|
200
167
|
capabilityIds.add(capabilityId)
|
|
201
168
|
}
|
|
202
|
-
for (const surfaceId of
|
|
169
|
+
for (const surfaceId of feature.surfaceIds) {
|
|
203
170
|
const surface = surfaceMap.get(surfaceId)
|
|
204
171
|
if (surface) {
|
|
205
172
|
pushUniqueEdge(edges, edgeIds, {
|
|
@@ -229,22 +196,22 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
229
196
|
targetId: id
|
|
230
197
|
})
|
|
231
198
|
|
|
232
|
-
if (surface.
|
|
199
|
+
if (surface.featureId) {
|
|
233
200
|
pushUniqueEdge(edges, edgeIds, {
|
|
234
|
-
id: edgeId('exposes', nodeId('feature', surface.
|
|
201
|
+
id: edgeId('exposes', nodeId('feature', surface.featureId), id),
|
|
235
202
|
kind: 'exposes',
|
|
236
|
-
sourceId: nodeId('feature', surface.
|
|
203
|
+
sourceId: nodeId('feature', surface.featureId),
|
|
237
204
|
targetId: id
|
|
238
205
|
})
|
|
239
206
|
}
|
|
240
207
|
|
|
241
|
-
for (const
|
|
242
|
-
if (
|
|
208
|
+
for (const featureId of surface.featureIds) {
|
|
209
|
+
if (featureMap.has(featureId)) {
|
|
243
210
|
pushUniqueEdge(edges, edgeIds, {
|
|
244
|
-
id: edgeId('references', id, nodeId('
|
|
211
|
+
id: edgeId('references', id, nodeId('feature', featureId)),
|
|
245
212
|
kind: 'references',
|
|
246
213
|
sourceId: id,
|
|
247
|
-
targetId: nodeId('
|
|
214
|
+
targetId: nodeId('feature', featureId)
|
|
248
215
|
})
|
|
249
216
|
}
|
|
250
217
|
}
|
|
@@ -317,13 +284,13 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
317
284
|
targetId: id
|
|
318
285
|
})
|
|
319
286
|
|
|
320
|
-
for (const
|
|
321
|
-
if (
|
|
287
|
+
for (const featureId of resourceMapping.featureIds) {
|
|
288
|
+
if (featureMap.has(featureId)) {
|
|
322
289
|
pushUniqueEdge(edges, edgeIds, {
|
|
323
|
-
id: edgeId('maps_to', id, nodeId('
|
|
290
|
+
id: edgeId('maps_to', id, nodeId('feature', featureId)),
|
|
324
291
|
kind: 'maps_to',
|
|
325
292
|
sourceId: id,
|
|
326
|
-
targetId: nodeId('
|
|
293
|
+
targetId: nodeId('feature', featureId)
|
|
327
294
|
})
|
|
328
295
|
}
|
|
329
296
|
}
|
|
@@ -374,13 +341,13 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
|
|
|
374
341
|
resourceType: normalizeCommandViewResourceType(resource.type)
|
|
375
342
|
})
|
|
376
343
|
|
|
377
|
-
for (const
|
|
378
|
-
if (
|
|
344
|
+
for (const featureId of resource.domains ?? []) {
|
|
345
|
+
if (featureMap.has(featureId)) {
|
|
379
346
|
pushUniqueEdge(edges, edgeIds, {
|
|
380
|
-
id: edgeId('references', resourceNode.id, nodeId('
|
|
347
|
+
id: edgeId('references', resourceNode.id, nodeId('feature', featureId), 'feature'),
|
|
381
348
|
kind: 'references',
|
|
382
349
|
sourceId: resourceNode.id,
|
|
383
|
-
targetId: nodeId('
|
|
350
|
+
targetId: nodeId('feature', featureId)
|
|
384
351
|
})
|
|
385
352
|
}
|
|
386
353
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
-
import { DescriptionSchema, LabelSchema } from '../domains/shared'
|
|
3
|
-
import { FeatureKeySchema } from '../domains/features'
|
|
2
|
+
import { DescriptionSchema, LabelSchema, ModelIdSchema } from '../domains/shared'
|
|
4
3
|
import { SurfaceTypeSchema } from '../domains/navigation'
|
|
5
4
|
import { OrganizationModelSchema } from '../schema'
|
|
6
5
|
|
|
7
6
|
export const OrganizationGraphNodeKindSchema = z.enum([
|
|
8
7
|
'organization',
|
|
9
8
|
'feature',
|
|
10
|
-
'domain',
|
|
11
9
|
'surface',
|
|
12
10
|
'entity',
|
|
13
11
|
'capability',
|
|
@@ -23,7 +21,7 @@ export const OrganizationGraphNodeSchema = z.object({
|
|
|
23
21
|
sourceId: z.string().trim().min(1).max(255).optional(),
|
|
24
22
|
description: DescriptionSchema.optional(),
|
|
25
23
|
enabled: z.boolean().optional(),
|
|
26
|
-
|
|
24
|
+
featureId: ModelIdSchema.optional(),
|
|
27
25
|
surfaceType: SurfaceTypeSchema.optional(),
|
|
28
26
|
resourceType: z.enum(['workflow', 'agent', 'trigger', 'integration', 'external', 'human_checkpoint']).optional()
|
|
29
27
|
})
|
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
import type { CommandViewData } from '../../platform/registry/command-view'
|
|
2
|
-
import type {
|
|
3
|
-
OrganizationModel,
|
|
4
|
-
OrganizationModelFeatureKey,
|
|
5
|
-
OrganizationModelResourceMapping,
|
|
6
|
-
OrganizationModelSurface
|
|
7
|
-
} from '../types'
|
|
2
|
+
import type { OrganizationModel, OrganizationModelResourceMapping, OrganizationModelSurface } from '../types'
|
|
8
3
|
import type { RelationshipType } from '../../platform/registry/command-view'
|
|
9
4
|
|
|
10
|
-
export type OrganizationGraphNodeKind =
|
|
11
|
-
| 'organization'
|
|
12
|
-
| 'feature'
|
|
13
|
-
| 'domain'
|
|
14
|
-
| 'surface'
|
|
15
|
-
| 'entity'
|
|
16
|
-
| 'capability'
|
|
17
|
-
| 'resource'
|
|
5
|
+
export type OrganizationGraphNodeKind = 'organization' | 'feature' | 'surface' | 'entity' | 'capability' | 'resource'
|
|
18
6
|
|
|
19
7
|
export type OrganizationGraphEdgeKind = 'contains' | 'references' | 'exposes' | 'maps_to'
|
|
20
8
|
|
|
@@ -25,7 +13,7 @@ export interface OrganizationGraphNode {
|
|
|
25
13
|
sourceId?: string
|
|
26
14
|
description?: string
|
|
27
15
|
enabled?: boolean
|
|
28
|
-
|
|
16
|
+
featureId?: string
|
|
29
17
|
surfaceType?: OrganizationModelSurface['surfaceType']
|
|
30
18
|
resourceType?: OrganizationModelResourceMapping['resourceType']
|
|
31
19
|
}
|