@elevasis/core 0.20.0 → 0.22.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 +524 -6
- package/dist/index.js +417 -42
- package/dist/knowledge/index.d.ts +151 -1
- package/dist/organization-model/index.d.ts +524 -6
- package/dist/organization-model/index.js +417 -42
- package/dist/test-utils/index.d.ts +270 -1
- package/dist/test-utils/index.js +407 -41
- package/package.json +5 -5
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +501 -303
- package/src/auth/multi-tenancy/permissions.ts +20 -8
- package/src/business/README.md +2 -2
- package/src/business/acquisition/api-schemas.test.ts +198 -0
- package/src/business/acquisition/api-schemas.ts +250 -9
- package/src/business/acquisition/build-templates.test.ts +28 -0
- package/src/business/acquisition/build-templates.ts +20 -8
- package/src/business/acquisition/index.ts +12 -0
- package/src/business/acquisition/types.ts +6 -1
- package/src/business/clients/api-schemas.test.ts +115 -0
- package/src/business/clients/api-schemas.ts +158 -0
- package/src/business/clients/index.ts +1 -0
- package/src/business/deals/api-schemas.ts +8 -0
- package/src/business/index.ts +5 -2
- package/src/business/projects/types.ts +19 -0
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
- package/src/execution/engine/agent/core/types.ts +25 -15
- package/src/execution/engine/agent/index.ts +6 -4
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
- package/src/execution/engine/index.ts +3 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -41
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -0
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -0
- package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -0
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -0
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -0
- package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -0
- package/src/execution/engine/workflow/types.ts +7 -0
- package/src/integrations/credentials/api-schemas.ts +21 -2
- package/src/integrations/credentials/schemas.ts +200 -164
- package/src/organization-model/README.md +10 -3
- package/src/organization-model/__tests__/defaults.test.ts +6 -0
- package/src/organization-model/__tests__/domains/resources.test.ts +188 -0
- package/src/organization-model/__tests__/domains/roles.test.ts +402 -347
- package/src/organization-model/__tests__/domains/systems.test.ts +193 -0
- package/src/organization-model/__tests__/knowledge.test.ts +39 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +7 -4
- package/src/organization-model/__tests__/resolve.test.ts +1 -1
- package/src/organization-model/defaults.ts +24 -3
- package/src/organization-model/domains/knowledge.ts +3 -2
- package/src/organization-model/domains/prospecting.ts +182 -25
- package/src/organization-model/domains/resources.ts +88 -0
- package/src/organization-model/domains/roles.ts +93 -55
- package/src/organization-model/domains/sales.ts +24 -3
- package/src/organization-model/domains/systems.ts +46 -0
- package/src/organization-model/icons.ts +1 -0
- package/src/organization-model/index.ts +2 -0
- package/src/organization-model/organization-model.mdx +33 -14
- package/src/organization-model/published.ts +52 -1
- package/src/organization-model/schema.ts +121 -0
- package/src/organization-model/types.ts +46 -1
- package/src/platform/api/types.ts +38 -35
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/resource-registry.test.ts +2051 -2005
- package/src/platform/registry/__tests__/validation.test.ts +1343 -1086
- package/src/platform/registry/index.ts +14 -0
- package/src/platform/registry/resource-registry.ts +40 -2
- package/src/platform/registry/serialization.ts +241 -202
- package/src/platform/registry/serialized-types.ts +1 -0
- package/src/platform/registry/types.ts +411 -361
- package/src/platform/registry/validation.ts +743 -513
- package/src/projects/api-schemas.ts +290 -267
- package/src/reference/_generated/contracts.md +501 -303
- package/src/reference/glossary.md +8 -3
- package/src/server.ts +2 -0
- package/src/supabase/database.types.ts +121 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
|
|
4
|
+
SystemEntrySchema,
|
|
5
|
+
SystemKindSchema,
|
|
6
|
+
SystemsDomainSchema,
|
|
7
|
+
SystemStatusSchema
|
|
8
|
+
} from '../../domains/systems'
|
|
9
|
+
import { resolveOrganizationModel } from '../../resolve'
|
|
10
|
+
|
|
11
|
+
const VALID_SYSTEM = {
|
|
12
|
+
id: 'sys.lead-gen',
|
|
13
|
+
title: 'Lead Generation Pipeline',
|
|
14
|
+
description: 'Coordinates prospecting, enrichment, qualification, and outreach preparation.',
|
|
15
|
+
kind: 'operational' as const,
|
|
16
|
+
status: 'active' as const
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('SystemEntrySchema - positive parse', () => {
|
|
20
|
+
it('accepts a minimal tenant-defined system', () => {
|
|
21
|
+
const result = SystemEntrySchema.safeParse(VALID_SYSTEM)
|
|
22
|
+
|
|
23
|
+
expect(result.success).toBe(true)
|
|
24
|
+
if (result.success) {
|
|
25
|
+
expect(result.data.governedByKnowledge).toEqual([])
|
|
26
|
+
expect(result.data.drivesGoals).toEqual([])
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('accepts all optional governance references when present', () => {
|
|
31
|
+
const result = SystemEntrySchema.safeParse({
|
|
32
|
+
...VALID_SYSTEM,
|
|
33
|
+
responsibleRoleId: 'role.sales-ops',
|
|
34
|
+
governedByKnowledge: ['knowledge.lead-gen-playbook'],
|
|
35
|
+
drivesGoals: ['goal.pipeline-coverage']
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
expect(result.success).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('trims id, title, and description', () => {
|
|
42
|
+
const result = SystemEntrySchema.safeParse({
|
|
43
|
+
...VALID_SYSTEM,
|
|
44
|
+
id: ' sys.crm ',
|
|
45
|
+
title: ' CRM ',
|
|
46
|
+
description: ' Owns relationship and deal pipeline operations. '
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
expect(result.success).toBe(true)
|
|
50
|
+
if (result.success) {
|
|
51
|
+
expect(result.data.id).toBe('sys.crm')
|
|
52
|
+
expect(result.data.title).toBe('CRM')
|
|
53
|
+
expect(result.data.description).toBe('Owns relationship and deal pipeline operations.')
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('SystemEntrySchema - negative parse', () => {
|
|
59
|
+
it('rejects missing required fields', () => {
|
|
60
|
+
expect(SystemEntrySchema.safeParse({ id: 'sys.missing' }).success).toBe(false)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('rejects an unknown system kind', () => {
|
|
64
|
+
expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, kind: 'sales' }).success).toBe(false)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('rejects an unknown system status', () => {
|
|
68
|
+
expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, status: 'paused' }).success).toBe(false)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('rejects IDs that do not match the OM model-id format', () => {
|
|
72
|
+
expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, id: 'Sys Lead Gen' }).success).toBe(false)
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
describe('SystemsDomainSchema', () => {
|
|
77
|
+
it('accepts an empty systems array', () => {
|
|
78
|
+
expect(SystemsDomainSchema.safeParse({ systems: [] }).success).toBe(true)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('defaults systems to an empty array when omitted', () => {
|
|
82
|
+
const result = SystemsDomainSchema.safeParse({})
|
|
83
|
+
|
|
84
|
+
expect(result.success).toBe(true)
|
|
85
|
+
if (result.success) {
|
|
86
|
+
expect(result.data).toEqual(DEFAULT_ORGANIZATION_MODEL_SYSTEMS)
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('SystemKindSchema and SystemStatusSchema', () => {
|
|
92
|
+
it.each(['product', 'operational', 'platform', 'diagnostic'] as const)('accepts kind "%s"', (kind) => {
|
|
93
|
+
expect(SystemKindSchema.safeParse(kind).success).toBe(true)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it.each(['active', 'deprecated', 'archived'] as const)('accepts status "%s"', (status) => {
|
|
97
|
+
expect(SystemStatusSchema.safeParse(status).success).toBe(true)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
describe('resolveOrganizationModel - systems domain integration', () => {
|
|
102
|
+
it('omitting systems resolves to the empty default catalog', () => {
|
|
103
|
+
const model = resolveOrganizationModel({})
|
|
104
|
+
|
|
105
|
+
expect(model.systems).toEqual(DEFAULT_ORGANIZATION_MODEL_SYSTEMS)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('accepts valid responsible role, knowledge, and goal references', () => {
|
|
109
|
+
expect(() =>
|
|
110
|
+
resolveOrganizationModel({
|
|
111
|
+
roles: { roles: [{ id: 'role.sales-ops', title: 'Sales Ops' }] },
|
|
112
|
+
goals: {
|
|
113
|
+
objectives: [
|
|
114
|
+
{
|
|
115
|
+
id: 'goal.pipeline-coverage',
|
|
116
|
+
description: 'Improve sales pipeline coverage',
|
|
117
|
+
periodStart: '2026-01-01',
|
|
118
|
+
periodEnd: '2026-12-31'
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
knowledge: {
|
|
123
|
+
nodes: [
|
|
124
|
+
{
|
|
125
|
+
id: 'knowledge.lead-gen-playbook',
|
|
126
|
+
kind: 'playbook',
|
|
127
|
+
title: 'Lead Gen Playbook',
|
|
128
|
+
summary: 'How lead generation is governed.',
|
|
129
|
+
body: '## Lead Gen',
|
|
130
|
+
updatedAt: '2026-05-08'
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
systems: {
|
|
135
|
+
systems: [
|
|
136
|
+
{
|
|
137
|
+
...VALID_SYSTEM,
|
|
138
|
+
responsibleRoleId: 'role.sales-ops',
|
|
139
|
+
governedByKnowledge: ['knowledge.lead-gen-playbook'],
|
|
140
|
+
drivesGoals: ['goal.pipeline-coverage']
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
).not.toThrow()
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('throws when system IDs are duplicated', () => {
|
|
149
|
+
expect(() =>
|
|
150
|
+
resolveOrganizationModel({
|
|
151
|
+
systems: {
|
|
152
|
+
systems: [
|
|
153
|
+
VALID_SYSTEM,
|
|
154
|
+
{
|
|
155
|
+
...VALID_SYSTEM,
|
|
156
|
+
title: 'Duplicate System'
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
).toThrow(/System id \\"sys\.lead-gen\\" must be unique/)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('throws when responsibleRoleId references an unknown role', () => {
|
|
165
|
+
expect(() =>
|
|
166
|
+
resolveOrganizationModel({
|
|
167
|
+
systems: {
|
|
168
|
+
systems: [{ ...VALID_SYSTEM, responsibleRoleId: 'role.missing' }]
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
).toThrow(/unknown responsibleRoleId \\"role\.missing\\"/)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('throws when governedByKnowledge references an unknown knowledge node', () => {
|
|
175
|
+
expect(() =>
|
|
176
|
+
resolveOrganizationModel({
|
|
177
|
+
systems: {
|
|
178
|
+
systems: [{ ...VALID_SYSTEM, governedByKnowledge: ['knowledge.missing'] }]
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
).toThrow(/unknown knowledge node \\"knowledge\.missing\\"/)
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
it('throws when drivesGoals references an unknown goal', () => {
|
|
185
|
+
expect(() =>
|
|
186
|
+
resolveOrganizationModel({
|
|
187
|
+
systems: {
|
|
188
|
+
systems: [{ ...VALID_SYSTEM, drivesGoals: ['goal.missing'] }]
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
).toThrow(/unknown goal \\"goal\.missing\\"/)
|
|
192
|
+
})
|
|
193
|
+
})
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { OrganizationGraphEdgeKindSchema } from '../graph/schema'
|
|
9
9
|
import { buildOrganizationGraph } from '../graph/build'
|
|
10
10
|
import { DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE } from '../defaults'
|
|
11
|
+
import { resolveOrganizationModel } from '../resolve'
|
|
11
12
|
import type { OrganizationModel } from '../types'
|
|
12
13
|
|
|
13
14
|
// ---------------------------------------------------------------------------
|
|
@@ -74,6 +75,15 @@ describe('OrgKnowledgeNodeSchema', () => {
|
|
|
74
75
|
expect(node.ownerIds).toEqual([])
|
|
75
76
|
})
|
|
76
77
|
|
|
78
|
+
it('accepts role ids as knowledge owners', () => {
|
|
79
|
+
const node = OrgKnowledgeNodeSchema.parse({
|
|
80
|
+
...makeNode('strategy'),
|
|
81
|
+
ownerIds: ['role.ops-lead', 'role.ceo']
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
expect(node.ownerIds).toEqual(['role.ops-lead', 'role.ceo'])
|
|
85
|
+
})
|
|
86
|
+
|
|
77
87
|
it('accepts an optional semantic icon token', () => {
|
|
78
88
|
const node = OrgKnowledgeNodeSchema.parse({
|
|
79
89
|
...makeNode('playbook'),
|
|
@@ -93,6 +103,35 @@ describe('OrgKnowledgeNodeSchema', () => {
|
|
|
93
103
|
})
|
|
94
104
|
})
|
|
95
105
|
|
|
106
|
+
describe('resolveOrganizationModel with knowledge owner roles', () => {
|
|
107
|
+
const node = {
|
|
108
|
+
id: 'knowledge.test-owner',
|
|
109
|
+
kind: 'playbook' as const,
|
|
110
|
+
title: 'Owned Knowledge',
|
|
111
|
+
summary: 'A knowledge node with role ownership.',
|
|
112
|
+
body: '## Body\n\nContent.',
|
|
113
|
+
ownerIds: ['role.ops-lead'],
|
|
114
|
+
updatedAt: '2026-05-08'
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
it('passes when ownerIds reference declared role ids', () => {
|
|
118
|
+
expect(() =>
|
|
119
|
+
resolveOrganizationModel({
|
|
120
|
+
roles: { roles: [{ id: 'role.ops-lead', title: 'Ops Lead' }] },
|
|
121
|
+
knowledge: { nodes: [node] }
|
|
122
|
+
})
|
|
123
|
+
).not.toThrow()
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('throws when ownerIds reference unknown role ids', () => {
|
|
127
|
+
expect(() =>
|
|
128
|
+
resolveOrganizationModel({
|
|
129
|
+
knowledge: { nodes: [node] }
|
|
130
|
+
})
|
|
131
|
+
).toThrow(/unknown owner role/)
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
96
135
|
// ---------------------------------------------------------------------------
|
|
97
136
|
// OrgKnowledgeKindSchema — enum shape
|
|
98
137
|
// ---------------------------------------------------------------------------
|
|
@@ -5,6 +5,7 @@ import { CAPABILITY_REGISTRY, DEFAULT_ORGANIZATION_MODEL_PROSPECTING, PROSPECTIN
|
|
|
5
5
|
const EXPECTED_CAPABILITY_RESOURCE_BY_ID: Record<string, string> = {
|
|
6
6
|
'lead-gen.company.source': 'lgn-import-workflow',
|
|
7
7
|
'lead-gen.company.apollo-import': 'lgn-01c-apollo-import-workflow',
|
|
8
|
+
'lead-gen.company.apify-crawl': 'lgn-02a-apify-website-crawl-workflow',
|
|
8
9
|
'lead-gen.contact.discover': 'lgn-04-email-discovery-workflow',
|
|
9
10
|
'lead-gen.contact.verify-email': 'lgn-05-email-verification-workflow',
|
|
10
11
|
'lead-gen.company.website-extract': 'lgn-02-website-extract-workflow',
|
|
@@ -24,7 +25,9 @@ describe('prospecting organization-model SSOT', () => {
|
|
|
24
25
|
label: 'Decision-makers found',
|
|
25
26
|
description: 'Decision-maker contacts discovered and attached to a qualified company.',
|
|
26
27
|
order: 6,
|
|
27
|
-
entity: 'company'
|
|
28
|
+
entity: 'company',
|
|
29
|
+
recordEntity: 'contact',
|
|
30
|
+
recordStageKey: 'discovered'
|
|
28
31
|
})
|
|
29
32
|
})
|
|
30
33
|
|
|
@@ -63,12 +66,12 @@ describe('prospecting organization-model SSOT', () => {
|
|
|
63
66
|
|
|
64
67
|
it('derives prospecting lifecycle stages from the stage catalog by entity', () => {
|
|
65
68
|
const expectedCompanyStages = Object.values(LEAD_GEN_STAGE_CATALOG)
|
|
66
|
-
.filter((stage) => stage.entity === 'company')
|
|
69
|
+
.filter((stage) => stage.entity === 'company' || stage.additionalEntities?.includes('company'))
|
|
67
70
|
.sort((a, b) => a.order - b.order)
|
|
68
71
|
.map(({ key, label, order }) => ({ id: key, label, order }))
|
|
69
72
|
|
|
70
73
|
const expectedContactStages = Object.values(LEAD_GEN_STAGE_CATALOG)
|
|
71
|
-
.filter((stage) => stage.entity === 'contact')
|
|
74
|
+
.filter((stage) => stage.entity === 'contact' || stage.additionalEntities?.includes('contact'))
|
|
72
75
|
.sort((a, b) => a.order - b.order)
|
|
73
76
|
.map(({ key, label, order }) => ({ id: key, label, order }))
|
|
74
77
|
|
|
@@ -84,7 +87,7 @@ describe('prospecting organization-model SSOT', () => {
|
|
|
84
87
|
})
|
|
85
88
|
|
|
86
89
|
it('covers all known lead-gen capability registry entries', () => {
|
|
87
|
-
expect(CAPABILITY_REGISTRY).toHaveLength(
|
|
90
|
+
expect(CAPABILITY_REGISTRY).toHaveLength(13)
|
|
88
91
|
const actualResourceById = Object.fromEntries(CAPABILITY_REGISTRY.map((c) => [c.id, c.resourceId]))
|
|
89
92
|
expect(actualResourceById).toEqual(EXPECTED_CAPABILITY_RESOURCE_BY_ID)
|
|
90
93
|
})
|
|
@@ -7,7 +7,7 @@ describe('organization-model resolve', () => {
|
|
|
7
7
|
|
|
8
8
|
expect(model.version).toBe(1)
|
|
9
9
|
expect(model.features.find((feature) => feature.id === 'dashboard')?.path).toBe('/')
|
|
10
|
-
expect(model.features.find((feature) => feature.id === 'sales')?.path).
|
|
10
|
+
expect(model.features.find((feature) => feature.id === 'sales')?.path).toBe('/sales')
|
|
11
11
|
expect(model.features.find((feature) => feature.id === 'sales.crm')?.path).toBe('/crm')
|
|
12
12
|
expect(model.features.find((feature) => feature.id === 'admin')?.requiresAdmin).toBe(true)
|
|
13
13
|
expect(model.features.find((feature) => feature.id === 'archive')?.devOnly).toBe(true)
|
|
@@ -20,6 +20,8 @@ import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from './domains/prospecting'
|
|
|
20
20
|
import { DEFAULT_ORGANIZATION_MODEL_OPERATIONS } from './domains/operations'
|
|
21
21
|
import { DEFAULT_ORGANIZATION_MODEL_ROLES } from './domains/roles'
|
|
22
22
|
import { DEFAULT_ORGANIZATION_MODEL_GOALS } from './domains/goals'
|
|
23
|
+
import { DEFAULT_ORGANIZATION_MODEL_SYSTEMS } from './domains/systems'
|
|
24
|
+
import { DEFAULT_ORGANIZATION_MODEL_RESOURCES } from './domains/resources'
|
|
23
25
|
import { DEFAULT_ORGANIZATION_MODEL_STATUSES } from './domains/statuses'
|
|
24
26
|
import type { KnowledgeDomain } from './domains/knowledge'
|
|
25
27
|
|
|
@@ -61,6 +63,15 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
|
61
63
|
color: 'green',
|
|
62
64
|
icon: 'feature.finance'
|
|
63
65
|
},
|
|
66
|
+
{
|
|
67
|
+
id: 'business',
|
|
68
|
+
label: 'Business',
|
|
69
|
+
description: 'Revenue, client relationships, and project delivery',
|
|
70
|
+
enabled: true,
|
|
71
|
+
color: 'blue',
|
|
72
|
+
icon: 'feature.business',
|
|
73
|
+
uiPosition: 'sidebar-primary'
|
|
74
|
+
},
|
|
64
75
|
{
|
|
65
76
|
id: 'sales',
|
|
66
77
|
label: 'Sales',
|
|
@@ -68,7 +79,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
|
68
79
|
enabled: true,
|
|
69
80
|
color: 'blue',
|
|
70
81
|
icon: 'feature.sales',
|
|
71
|
-
|
|
82
|
+
path: '/sales'
|
|
72
83
|
},
|
|
73
84
|
{
|
|
74
85
|
id: 'sales.crm',
|
|
@@ -95,8 +106,16 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
|
95
106
|
enabled: true,
|
|
96
107
|
color: 'orange',
|
|
97
108
|
icon: 'feature.projects',
|
|
98
|
-
path: '/projects'
|
|
99
|
-
|
|
109
|
+
path: '/projects'
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'clients',
|
|
113
|
+
label: 'Clients',
|
|
114
|
+
description: 'Client relationships, accounts, and business context',
|
|
115
|
+
enabled: true,
|
|
116
|
+
color: 'orange',
|
|
117
|
+
icon: 'feature.projects',
|
|
118
|
+
path: '/business/clients'
|
|
100
119
|
},
|
|
101
120
|
{
|
|
102
121
|
id: 'operations',
|
|
@@ -341,6 +360,8 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
|
|
|
341
360
|
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
342
361
|
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
343
362
|
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
363
|
+
systems: DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
|
|
364
|
+
resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
|
|
344
365
|
statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
|
|
345
366
|
operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
|
|
346
367
|
knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { IconNameSchema, ModelIdSchema } from './shared'
|
|
3
3
|
import { NodeIdStringSchema } from './features'
|
|
4
|
+
import { RoleIdSchema } from './roles'
|
|
4
5
|
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
6
7
|
// KnowledgeLink — a typed graph link pointing to another OM node.
|
|
@@ -40,8 +41,8 @@ export const OrgKnowledgeNodeSchema = z.object({
|
|
|
40
41
|
skills: z.array(KnowledgeSkillBindingSchema).optional(),
|
|
41
42
|
/** Domain key used to derive fast graph->skill registries. */
|
|
42
43
|
domain: KnowledgeDomainBindingSchema.optional(),
|
|
43
|
-
/**
|
|
44
|
-
ownerIds: z.array(
|
|
44
|
+
/** Role identifiers that own this knowledge node. */
|
|
45
|
+
ownerIds: z.array(RoleIdSchema).default([]),
|
|
45
46
|
/** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
|
|
46
47
|
updatedAt: z.string().trim().min(1).max(50)
|
|
47
48
|
})
|