@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.
Files changed (44) hide show
  1. package/dist/index.d.ts +60 -103
  2. package/dist/index.js +162 -109
  3. package/dist/organization-model/index.d.ts +60 -103
  4. package/dist/organization-model/index.js +162 -109
  5. package/package.json +1 -1
  6. package/src/README.md +24 -17
  7. package/src/__tests__/template-foundations-compatibility.test.ts +28 -36
  8. package/src/auth/multi-tenancy/types.ts +4 -11
  9. package/src/auth/multi-tenancy/users/api-schemas.ts +1 -1
  10. package/src/business/base-entities.test.ts +481 -0
  11. package/src/business/base-entities.ts +241 -0
  12. package/src/business/delivery/types.ts +1 -1
  13. package/src/business/index.ts +3 -0
  14. package/src/execution/index.ts +3 -6
  15. package/src/index.ts +1 -1
  16. package/src/organization-model/README.md +25 -26
  17. package/src/organization-model/__tests__/graph.test.ts +103 -71
  18. package/src/organization-model/__tests__/resolve.test.ts +20 -29
  19. package/src/organization-model/contracts.ts +3 -0
  20. package/src/organization-model/defaults.ts +40 -6
  21. package/src/organization-model/domains/features.ts +19 -54
  22. package/src/organization-model/domains/navigation.ts +25 -16
  23. package/src/organization-model/domains/shared.ts +1 -10
  24. package/src/organization-model/foundation.ts +96 -0
  25. package/src/organization-model/graph/build.ts +34 -67
  26. package/src/organization-model/graph/schema.ts +2 -4
  27. package/src/organization-model/graph/types.ts +3 -15
  28. package/src/organization-model/index.ts +2 -0
  29. package/src/organization-model/organization-model.mdx +34 -36
  30. package/src/organization-model/published.ts +12 -3
  31. package/src/organization-model/schema.ts +38 -34
  32. package/src/organization-model/types.ts +5 -10
  33. package/src/platform/constants/versions.ts +1 -1
  34. package/src/platform/sse/events.ts +1 -34
  35. package/src/projects/api-schemas.ts +2 -1
  36. package/src/reference/_generated/contracts.md +10 -31
  37. package/src/reference/glossary.md +14 -18
  38. package/src/supabase/database.types.ts +0 -107
  39. package/src/test-utils/rls/RLSTestContext.ts +1 -31
  40. package/src/execution/calibration/__tests__/schemas.test.ts +0 -320
  41. package/src/execution/calibration/index.ts +0 -3
  42. package/src/execution/calibration/schemas.ts +0 -121
  43. package/src/execution/calibration/sse-events.ts +0 -125
  44. package/src/execution/calibration/types.ts +0 -190
@@ -21,7 +21,7 @@ The model does **not** replace the shared feature-provider system. It enriches a
21
21
  - `packages/core/src/organization-model/types.ts` -- exported TypeScript types
22
22
  - `packages/core/src/organization-model/defaults.ts` -- `DEFAULT_ORGANIZATION_MODEL`
23
23
  - `packages/core/src/organization-model/resolve.ts` -- `defineOrganizationModel`, `resolveOrganizationModel`
24
- - `packages/core/src/organization-model/domains/*.ts` -- feature keys, navigation surfaces, CRM/lead-gen/delivery semantics
24
+ - `packages/core/src/organization-model/domains/*.ts` -- feature schema, navigation surfaces, CRM/lead-gen/delivery semantics
25
25
  - `packages/core/src/published.ts` -- curated root barrel for the published package
26
26
  - `packages/core/src/organization-model/published.ts` -- curated organization-model barrel
27
27
  - `packages/core/src/__tests__/template-foundations-compatibility.test.ts` -- adapter-baseline guard
@@ -31,9 +31,8 @@ The model does **not** replace the shared feature-provider system. It enriches a
31
31
  Top-level fields on `OrganizationModel`:
32
32
 
33
33
  - `version`
34
- - `domains` -- semantic domains (`crm`, `lead-gen`, `delivery`, `operations`)
34
+ - `features` -- unified feature array (`OrganizationModelFeature[]`); each entry combines access gating, semantic grouping, and display metadata
35
35
  - `branding`
36
- - `features` -- `enabled` map and `labels` overrides
37
36
  - `navigation` -- surfaces, groups, `defaultSurfaceId`
38
37
  - `crm` -- pipeline stages and stage semantics
39
38
  - `leadGen` -- company/contact lifecycle stages
@@ -61,24 +60,21 @@ All `id` fields, `parentId`, `defaultSurfaceId`, and reference ID arrays use `Mo
61
60
 
62
61
  This applies to domain IDs, surface IDs, navigation group IDs, and resource mapping IDs.
63
62
 
64
- ### Default Feature Keys
63
+ ### Default Features
65
64
 
66
- ```ts
67
- type OrganizationModelFeatureKey =
68
- | 'acquisition'
69
- | 'delivery'
70
- | 'operations'
71
- | 'monitoring'
72
- | 'settings'
73
- | 'seo'
74
- | 'calibration'
75
- ```
65
+ Seven features ship by default in `DEFAULT_ORGANIZATION_MODEL.features`:
76
66
 
77
- These are the **grouped** published access/visibility keys. They differ from shell feature-module keys (`crm`, `lead-gen`, `delivery`). See [Feature Shell](../ui/feature-shell.mdx) for how the provider bridges the two.
67
+ - `crm` -- enabled; CRM pipeline and deal management
68
+ - `lead-gen` -- enabled; prospecting, qualification, and outreach
69
+ - `projects` -- enabled; projects, milestones, and client work execution (formerly `delivery`)
70
+ - `operations` -- enabled; organizational topology and orchestration visibility
71
+ - `monitoring` -- enabled; execution monitoring
72
+ - `settings` -- enabled; organization settings
73
+ - `seo` -- disabled by default; SEO surface
78
74
 
79
- ### Default Semantic Domains
75
+ Each feature entry (`OrganizationModelFeature`) combines what were previously three separate concepts: an access/gating key (the former `OrganizationModelFeatureKey`), a semantic domain (the former `SemanticDomainSchema` entry), and display metadata. The `features` field is now `z.array(FeatureSchema)` -- there is no separate `domains` array and no separate `enabled`/`labels` map.
80
76
 
81
- Four domains ship by default -- `crm`, `lead-gen`, `delivery`, `operations`. Each binds together entity IDs, surface IDs, resource IDs, and capability IDs. Domains are semantic, not purely navigational -- they describe what area of the business or resource model a thing belongs to, not which access key gates it.
77
+ `FeatureModule.featureId` on the UI side maps directly to one of these IDs. No alias layer is needed. See [Feature Shell](../ui/feature-shell.mdx) for how the provider resolves feature access from this array.
82
78
 
83
79
  ### ResourceMapping Shape
84
80
 
@@ -88,7 +84,7 @@ Four domains ship by default -- `crm`, `lead-gen`, `delivery`, `operations`. Eac
88
84
  - `resourceId` -- the actual resource identifier (string, max 255 chars)
89
85
  - `resourceType` -- one of `'workflow' | 'agent' | 'trigger' | 'integration' | 'external' | 'human_checkpoint'`
90
86
  - `label`, `description`, `color`, `icon` -- display metadata (from `DisplayMetadataSchema`)
91
- - `domainIds` -- domains this resource belongs to
87
+ - `featureIds` -- features this resource belongs to (replaces the former `domainIds`)
92
88
  - `entityIds` -- entities this resource operates on
93
89
  - `surfaceIds` -- surfaces this resource is exposed in
94
90
  - `capabilityIds` -- capabilities this resource fulfills
@@ -109,9 +105,9 @@ Surfaces such as `crm.pipeline`, `lead-gen.lists`, `projects.index`, `operations
109
105
  - `surfaceType` -- `'page' | 'dashboard' | 'graph' | 'detail' | 'list' | 'settings'`
110
106
  - `description` -- optional
111
107
  - `icon` -- optional icon name token (max 80 chars)
112
- - `featureKey` -- optional `OrganizationModelFeatureKey` that gates this surface
108
+ - `featureId` -- optional feature ID that gates this surface (replaces the former `featureKey` field); must match a feature `id` in the features array
113
109
  - `parentId` -- optional ModelId referencing a parent surface; validated to exist
114
- - `domainIds` -- domains this surface belongs to (bidirectionally validated)
110
+ - `featureIds` -- features this surface belongs to (bidirectionally validated; replaces the former `domainIds`)
115
111
  - `entityIds` -- entity IDs relevant to this surface
116
112
  - `resourceIds` -- resources exposed on this surface (bidirectionally validated against resource mappings)
117
113
  - `capabilityIds` -- capabilities this surface fulfills
@@ -126,11 +122,13 @@ Surfaces such as `crm.pipeline`, `lead-gen.lists`, `projects.index`, `operations
126
122
 
127
123
  The default groups (`primary-workspace`, `primary-operations`) both use `placement: 'primary'`.
128
124
 
129
- ### Domain-Specific Semantics
125
+ ### Feature-Specific Semantics
130
126
 
131
- - **CRM** -- pipeline stages and stage semantics
132
- - **Lead-gen** -- company and contact lifecycle stages
133
- - **Delivery** -- project, milestone, and task statuses
127
+ The top-level `crm`, `leadGen`, and `delivery` fields on `OrganizationModel` remain as named fields (not moved into per-feature config) and carry domain-specific semantic shapes:
128
+
129
+ - `crm` -- pipeline stages and stage semantics
130
+ - `leadGen` -- company and contact lifecycle stages
131
+ - `delivery` -- project, milestone, and task statuses (used by the `projects` feature)
134
132
 
135
133
  This is why the organization model is semantic, not just nav config -- it owns product meaning for the business objects the shell surfaces expose.
136
134
 
@@ -152,7 +150,7 @@ Merge semantics:
152
150
 
153
151
  **Uniqueness checks** -- IDs must be unique within their respective collections:
154
152
 
155
- - `domains[].id`
153
+ - `features[].id`
156
154
  - `navigation.surfaces[].id`
157
155
  - `navigation.groups[].id`
158
156
  - `resourceMappings[].id`
@@ -162,20 +160,20 @@ Merge semantics:
162
160
 
163
161
  - `navigation.defaultSurfaceId` must point at a declared surface
164
162
  - every `surfaceId` in a navigation group must resolve to a declared surface
165
- - every `surfaceId` in a domain must resolve to a declared surface
166
- - every `resourceId` in a domain must resolve to a declared resource mapping (by `resourceId`)
163
+ - every `surfaceId` in a feature must resolve to a declared surface
164
+ - every `resourceId` in a feature must resolve to a declared resource mapping (by `resourceId`)
167
165
  - surface `parentId` must reference an existing surface
168
- - every `domainId` on a surface must resolve to a declared domain
166
+ - every `featureId` on a surface must resolve to a declared feature
169
167
  - every `resourceId` on a surface must resolve to a declared resource mapping
170
- - every `domainId` on a resource mapping must resolve to a declared domain
168
+ - every `featureId` on a resource mapping must resolve to a declared feature
171
169
  - every `surfaceId` on a resource mapping must resolve to a declared surface
172
170
 
173
171
  **Bidirectional reference enforcement** -- cross-references must be mutual, not one-sided:
174
172
 
175
- - a domain listing `surfaceId` S requires surface S to list that domain's ID in its `domainIds`
176
- - a surface listing `domainId` D requires domain D to list that surface's ID in its `surfaceIds`
177
- - a domain listing `resourceId` R requires resource mapping R to list that domain's ID in its `domainIds`
178
- - a resource mapping listing `domainId` D requires domain D to list that resource's `resourceId` in its `resourceIds`
173
+ - a feature listing `surfaceId` S requires surface S to list that feature's ID in its `featureIds`
174
+ - a surface listing `featureId` F requires feature F to list that surface's ID in its `surfaceIds`
175
+ - a feature listing `resourceId` R requires resource mapping R to list that feature's ID in its `featureIds`
176
+ - a resource mapping listing `featureId` F requires feature F to list that resource's `resourceId` in its `resourceIds`
179
177
  - a surface listing `resourceId` R requires resource mapping R to list that surface's ID in its `surfaceIds`
180
178
  - a resource mapping listing `surfaceId` S requires surface S to list that resource's `resourceId` in its `resourceIds`
181
179
 
@@ -185,8 +183,8 @@ This bidirectional enforcement is what keeps the organization model semantically
185
183
 
186
184
  `ElevasisFeaturesProvider` uses the organization model in three ways:
187
185
 
188
- 1. **Feature resolution** -- provider first checks `useFeatureAccess()`, then refines through organization-model feature state when the model knows the key.
189
- 2. **Nav label and path resolution** -- when `organizationModel` is present, feature labels resolve from `organizationModel.features.labels`, and surface labels and paths resolve from `organizationModel.navigation.surfaces`. Semantic customization without changing manifest code.
186
+ 1. **Feature resolution** -- the provider looks up each manifest's `featureId` in `organizationModel.features` to determine `access.enabled`. If no matching feature entry is found, `access.enabled` defaults to `false`.
187
+ 2. **Nav label and path resolution** -- when `organizationModel` is present, feature labels resolve from the matching feature entry's `label` field, and surface labels and paths resolve from `organizationModel.navigation.surfaces`. Semantic customization without changing manifest code.
190
188
  3. **Organization-graph bridge** -- the `operationsManifest` declares `organizationGraph.surfaceId = 'operations.organization-graph'`. The provider resolves that against organization-model surfaces and exposes the result as `organizationGraph` in context. See [Organization Graph](./organization-graph.mdx).
191
189
 
192
190
  ## Published Package: `@elevasis/core`
@@ -238,7 +236,7 @@ Exports the foundations module provides to consumers:
238
236
  - `FoundationFeatureKey`, `FoundationSurfaceIcon`, `FoundationNavigationSurface`, `FoundationOrganizationModel`
239
237
  - `homeLabel`, `quickAccessSurfaceIds`, `getOrganizationSurface(surfaceId)`
240
238
 
241
- Downstream template shells pass `canonicalOrganizationModel` into `ElevasisFeaturesProvider`, preserving host-local dashboard/nav customizations alongside the shared runtime. Grouped core features map onto template vocabulary -- `crm` and `lead-gen` project from `acquisition`, `projects` from `delivery`.
239
+ Downstream template shells pass `canonicalOrganizationModel` into `ElevasisFeaturesProvider`, preserving host-local dashboard/nav customizations alongside the shared runtime. Feature IDs are now direct matches -- `crm`, `lead-gen`, `projects` in the org model correspond directly to the same IDs on `FeatureModule.featureId`. No alias layer is needed.
242
240
 
243
241
  Derivative projects (`external/nirvana-marketing`, `external/ZentaraHQ`) follow the same adapter + provider-wiring baseline with their own project-local customizations.
244
242
 
@@ -1,6 +1,9 @@
1
1
  export { OrganizationModelSchema } from './schema'
2
+ export { FeatureSchema } from './domains/features'
3
+ export { PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, DELIVERY_PROJECTS_VIEW_CAPABILITY_ID } from './contracts'
2
4
  export { DEFAULT_ORGANIZATION_MODEL } from './defaults'
3
5
  export { defineOrganizationModel, resolveOrganizationModel } from './resolve'
6
+ export { createFoundationOrganizationModel } from './foundation'
4
7
 
5
8
  export type {
6
9
  DeepPartial,
@@ -8,11 +11,17 @@ export type {
8
11
  OrganizationModelBranding,
9
12
  OrganizationModelCrm,
10
13
  OrganizationModelDelivery,
11
- OrganizationModelFeatureKey,
12
- OrganizationModelFeatures,
14
+ OrganizationModelFeature,
13
15
  OrganizationModelLeadGen,
14
16
  OrganizationModelNavigation,
15
17
  OrganizationModelResourceMapping,
16
- OrganizationModelSemanticDomain,
17
18
  OrganizationModelSurface
18
19
  } from './types'
20
+
21
+ export type {
22
+ FoundationBranding,
23
+ FoundationNavigationSurface,
24
+ FoundationOrganizationModel,
25
+ FoundationSurfaceIcon,
26
+ FoundationSurfaceType
27
+ } from './foundation'
@@ -2,16 +2,15 @@ import { z } from 'zod'
2
2
  import { OrganizationModelBrandingSchema } from './domains/branding'
3
3
  import { OrganizationModelCrmSchema } from './domains/crm'
4
4
  import { OrganizationModelDeliverySchema } from './domains/delivery'
5
- import { OrganizationModelFeaturesSchema } from './domains/features'
5
+ import { FeatureSchema } from './domains/features'
6
6
  import { OrganizationModelLeadGenSchema } from './domains/lead-gen'
7
7
  import { OrganizationModelNavigationSchema } from './domains/navigation'
8
- import { ResourceMappingSchema, SemanticDomainSchema } from './domains/shared'
8
+ import { ResourceMappingSchema } from './domains/shared'
9
9
 
10
10
  const OrganizationModelSchemaBase = z.object({
11
11
  version: z.literal(1).default(1),
12
- domains: z.array(SemanticDomainSchema).default([]),
12
+ features: z.array(FeatureSchema).default([]),
13
13
  branding: OrganizationModelBrandingSchema,
14
- features: OrganizationModelFeaturesSchema,
15
14
  navigation: OrganizationModelNavigationSchema,
16
15
  crm: OrganizationModelCrmSchema,
17
16
  leadGen: OrganizationModelLeadGenSchema,
@@ -48,7 +47,7 @@ function collectIds<T extends { id: string }>(
48
47
  }
49
48
 
50
49
  export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
51
- const domainsById = collectIds(model.domains, ctx, ['domains'], 'Domain')
50
+ const featuresById = collectIds(model.features, ctx, ['features'], 'Feature')
52
51
  const surfacesById = collectIds(model.navigation.surfaces, ctx, ['navigation', 'surfaces'], 'Surface')
53
52
  collectIds(model.navigation.groups, ctx, ['navigation', 'groups'], 'Navigation group')
54
53
  collectIds(model.resourceMappings, ctx, ['resourceMappings'], 'Resource mapping')
@@ -87,48 +86,51 @@ export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((
87
86
  })
88
87
  })
89
88
 
90
- model.domains.forEach((domain, domainIndex) => {
91
- domain.surfaceIds.forEach((surfaceId, surfaceIndex) => {
89
+ // Feature -> Surface bidirectional validation
90
+ model.features.forEach((feature, featureIndex) => {
91
+ feature.surfaceIds.forEach((surfaceId, surfaceIndex) => {
92
92
  const surface = surfacesById.get(surfaceId)
93
93
  if (!surface) {
94
94
  addIssue(
95
95
  ctx,
96
- ['domains', domainIndex, 'surfaceIds', surfaceIndex],
97
- `Domain "${domain.id}" references unknown surface "${surfaceId}"`
96
+ ['features', featureIndex, 'surfaceIds', surfaceIndex],
97
+ `Feature "${feature.id}" references unknown surface "${surfaceId}"`
98
98
  )
99
99
  return
100
100
  }
101
101
 
102
- if (!surface.domainIds.includes(domain.id)) {
102
+ if (!surface.featureIds.includes(feature.id)) {
103
103
  addIssue(
104
104
  ctx,
105
- ['domains', domainIndex, 'surfaceIds', surfaceIndex],
106
- `Domain "${domain.id}" references surface "${surfaceId}" but that surface does not include domain "${domain.id}"`
105
+ ['features', featureIndex, 'surfaceIds', surfaceIndex],
106
+ `Feature "${feature.id}" references surface "${surfaceId}" but that surface does not include feature "${feature.id}"`
107
107
  )
108
108
  }
109
109
  })
110
110
 
111
- domain.resourceIds.forEach((resourceId, resourceIndex) => {
111
+ // Feature -> Resource bidirectional validation
112
+ feature.resourceIds.forEach((resourceId, resourceIndex) => {
112
113
  const resourceMapping = resourceMappingsByResourceId.get(resourceId)
113
114
  if (!resourceMapping) {
114
115
  addIssue(
115
116
  ctx,
116
- ['domains', domainIndex, 'resourceIds', resourceIndex],
117
- `Domain "${domain.id}" references unknown resource "${resourceId}"`
117
+ ['features', featureIndex, 'resourceIds', resourceIndex],
118
+ `Feature "${feature.id}" references unknown resource "${resourceId}"`
118
119
  )
119
120
  return
120
121
  }
121
122
 
122
- if (!resourceMapping.domainIds.includes(domain.id)) {
123
+ if (!resourceMapping.featureIds.includes(feature.id)) {
123
124
  addIssue(
124
125
  ctx,
125
- ['domains', domainIndex, 'resourceIds', resourceIndex],
126
- `Domain "${domain.id}" references resource "${resourceId}" but that resource mapping does not include domain "${domain.id}"`
126
+ ['features', featureIndex, 'resourceIds', resourceIndex],
127
+ `Feature "${feature.id}" references resource "${resourceId}" but that resource mapping does not include feature "${feature.id}"`
127
128
  )
128
129
  }
129
130
  })
130
131
  })
131
132
 
133
+ // Surface -> Feature bidirectional validation and other surface refs
132
134
  model.navigation.surfaces.forEach((surface, surfaceIndex) => {
133
135
  if (surface.parentId && !surfacesById.has(surface.parentId)) {
134
136
  addIssue(
@@ -138,26 +140,27 @@ export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((
138
140
  )
139
141
  }
140
142
 
141
- surface.domainIds.forEach((domainId, domainIndex) => {
142
- const domain = domainsById.get(domainId)
143
- if (!domain) {
143
+ surface.featureIds.forEach((featureId, featureIndex) => {
144
+ const feature = featuresById.get(featureId)
145
+ if (!feature) {
144
146
  addIssue(
145
147
  ctx,
146
- ['navigation', 'surfaces', surfaceIndex, 'domainIds', domainIndex],
147
- `Surface "${surface.id}" references unknown domain "${domainId}"`
148
+ ['navigation', 'surfaces', surfaceIndex, 'featureIds', featureIndex],
149
+ `Surface "${surface.id}" references unknown feature "${featureId}"`
148
150
  )
149
151
  return
150
152
  }
151
153
 
152
- if (!domain.surfaceIds.includes(surface.id)) {
154
+ if (!feature.surfaceIds.includes(surface.id)) {
153
155
  addIssue(
154
156
  ctx,
155
- ['navigation', 'surfaces', surfaceIndex, 'domainIds', domainIndex],
156
- `Surface "${surface.id}" references domain "${domainId}" but that domain does not include surface "${surface.id}"`
157
+ ['navigation', 'surfaces', surfaceIndex, 'featureIds', featureIndex],
158
+ `Surface "${surface.id}" references feature "${featureId}" but that feature does not include surface "${surface.id}"`
157
159
  )
158
160
  }
159
161
  })
160
162
 
163
+ // Surface -> Resource bidirectional validation
161
164
  surface.resourceIds.forEach((resourceId, resourceIndex) => {
162
165
  const resourceMapping = resourceMappingsByResourceId.get(resourceId)
163
166
  if (!resourceMapping) {
@@ -179,23 +182,24 @@ export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((
179
182
  })
180
183
  })
181
184
 
185
+ // ResourceMapping -> Feature and Surface bidirectional validation
182
186
  model.resourceMappings.forEach((resourceMapping, resourceIndex) => {
183
- resourceMapping.domainIds.forEach((domainId, domainIndex) => {
184
- const domain = domainsById.get(domainId)
185
- if (!domain) {
187
+ resourceMapping.featureIds.forEach((featureId, featureIndex) => {
188
+ const feature = featuresById.get(featureId)
189
+ if (!feature) {
186
190
  addIssue(
187
191
  ctx,
188
- ['resourceMappings', resourceIndex, 'domainIds', domainIndex],
189
- `Resource mapping "${resourceMapping.id}" references unknown domain "${domainId}"`
192
+ ['resourceMappings', resourceIndex, 'featureIds', featureIndex],
193
+ `Resource mapping "${resourceMapping.id}" references unknown feature "${featureId}"`
190
194
  )
191
195
  return
192
196
  }
193
197
 
194
- if (!domain.resourceIds.includes(resourceMapping.resourceId)) {
198
+ if (!feature.resourceIds.includes(resourceMapping.resourceId)) {
195
199
  addIssue(
196
200
  ctx,
197
- ['resourceMappings', resourceIndex, 'domainIds', domainIndex],
198
- `Resource mapping "${resourceMapping.id}" references domain "${domainId}" but that domain does not include resource "${resourceMapping.resourceId}"`
201
+ ['resourceMappings', resourceIndex, 'featureIds', featureIndex],
202
+ `Resource mapping "${resourceMapping.id}" references feature "${featureId}" but that feature does not include resource "${resourceMapping.resourceId}"`
199
203
  )
200
204
  }
201
205
  })
@@ -2,10 +2,10 @@ import type { z } from 'zod'
2
2
  import { OrganizationModelBrandingSchema } from './domains/branding'
3
3
  import { OrganizationModelCrmSchema } from './domains/crm'
4
4
  import { OrganizationModelDeliverySchema } from './domains/delivery'
5
- import { OrganizationModelFeaturesSchema, FeatureKeySchema } from './domains/features'
5
+ import { FeatureSchema } from './domains/features'
6
6
  import { OrganizationModelLeadGenSchema } from './domains/lead-gen'
7
7
  import { OrganizationModelNavigationSchema, SurfaceDefinitionSchema } from './domains/navigation'
8
- import { ResourceMappingSchema, SemanticDomainSchema } from './domains/shared'
8
+ import { ResourceMappingSchema } from './domains/shared'
9
9
  import { OrganizationModelSchema } from './schema'
10
10
 
11
11
  export type OrganizationModel = z.infer<typeof OrganizationModelSchema>
@@ -13,15 +13,10 @@ export type OrganizationModelBranding = z.infer<typeof OrganizationModelBranding
13
13
  export type OrganizationModelCrm = z.infer<typeof OrganizationModelCrmSchema>
14
14
  export type OrganizationModelLeadGen = z.infer<typeof OrganizationModelLeadGenSchema>
15
15
  export type OrganizationModelDelivery = z.infer<typeof OrganizationModelDeliverySchema>
16
- export type OrganizationModelFeatures = z.infer<typeof OrganizationModelFeaturesSchema>
17
- export type OrganizationModelFeatureKey = z.infer<typeof FeatureKeySchema>
16
+ export type OrganizationModelFeature = z.infer<typeof FeatureSchema>
18
17
  export type OrganizationModelNavigation = z.infer<typeof OrganizationModelNavigationSchema>
19
18
  export type OrganizationModelSurface = z.infer<typeof SurfaceDefinitionSchema>
20
- export type OrganizationModelSemanticDomain = z.infer<typeof SemanticDomainSchema>
21
19
  export type OrganizationModelResourceMapping = z.infer<typeof ResourceMappingSchema>
22
20
 
23
- export type DeepPartial<T> = T extends Array<infer U>
24
- ? Array<DeepPartial<U>>
25
- : T extends object
26
- ? { [K in keyof T]?: DeepPartial<T[K]> }
27
- : T
21
+ export type DeepPartial<T> =
22
+ T extends Array<infer U> ? Array<DeepPartial<U>> : T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T
@@ -1,3 +1,3 @@
1
1
  export const VERSION = {
2
- CURRENT: '1.5.6'
2
+ CURRENT: '1.5.7'
3
3
  }
@@ -14,54 +14,21 @@ import type {
14
14
  ExecutionCompleteEvent,
15
15
  ExecutionConnectedEvent
16
16
  } from '../../execution/core/sse-executions'
17
- import type {
18
- CalibrationSSEEvent,
19
- CalibrationExecutionStartedEvent,
20
- CalibrationExecutionCompletedEvent,
21
- CalibrationExecutionFailedEvent,
22
- CalibrationSessionStartedEvent,
23
- CalibrationTurnStartedEvent,
24
- CalibrationTurnCompletedEvent,
25
- CalibrationSessionCompletedEvent,
26
- CalibrationGradingStartedEvent,
27
- CalibrationGradingCompletedEvent,
28
- CalibrationGradingFailedEvent,
29
- CalibrationCompletedEvent,
30
- CalibrationFailedEvent,
31
- CalibrationConnectedEvent
32
- } from '../../execution/calibration/sse-events'
33
17
 
34
18
  // Re-export domain-specific event types
35
19
  export type { NotificationSSEEvent, NotificationCountUpdatedEvent }
36
20
  export type { ActivitySSEEvent, ActivityCreatedEvent, ActivityConnectedEvent }
37
21
  export type { CommandQueueSSEEvent, CommandQueueTaskUpdatedEvent, CommandQueueConnectedEvent }
38
22
  export type { ExecutionSSEEvent, ExecutionStartedEvent, ExecutionLogEvent, ExecutionCompleteEvent, ExecutionConnectedEvent }
39
- export type {
40
- CalibrationSSEEvent,
41
- CalibrationExecutionStartedEvent,
42
- CalibrationExecutionCompletedEvent,
43
- CalibrationExecutionFailedEvent,
44
- CalibrationSessionStartedEvent,
45
- CalibrationTurnStartedEvent,
46
- CalibrationTurnCompletedEvent,
47
- CalibrationSessionCompletedEvent,
48
- CalibrationGradingStartedEvent,
49
- CalibrationGradingCompletedEvent,
50
- CalibrationGradingFailedEvent,
51
- CalibrationCompletedEvent,
52
- CalibrationFailedEvent,
53
- CalibrationConnectedEvent
54
- }
55
23
 
56
24
  /**
57
25
  * Union of all application-level SSE events across all domains
58
26
  *
59
27
  * Use this for generic SSE handling that needs to support all event types.
60
- * For domain-specific handling, use NotificationSSEEvent, ActivitySSEEvent, ExecutionSSEEvent, CalibrationSSEEvent, etc.
28
+ * For domain-specific handling, use NotificationSSEEvent, ActivitySSEEvent, ExecutionSSEEvent, etc.
61
29
  */
62
30
  export type AppSSEEvent =
63
31
  | NotificationSSEEvent
64
32
  | ActivitySSEEvent
65
33
  | CommandQueueSSEEvent
66
34
  | ExecutionSSEEvent
67
- | CalibrationSSEEvent
@@ -102,7 +102,8 @@ export const UpdateProjectRequestSchema = z
102
102
  export const GetProjectsQuerySchema = z
103
103
  .object({
104
104
  kind: ProjectKindSchema.optional(),
105
- status: ProjectStatusSchema.optional()
105
+ status: ProjectStatusSchema.optional(),
106
+ search: z.string().trim().min(1).max(255).optional()
106
107
  })
107
108
  .strict()
108
109
 
@@ -1,3 +1,4 @@
1
+ <!-- Auto-generated on 2026-04-18T06:38:52.184Z by scripts/monorepo/generate-scaffold-contracts.js -->
1
2
  ---
2
3
  title: Reference Contracts
3
4
  description: Auto-generated TypeScript contracts for SDK consumers. Do not edit manually.
@@ -37,16 +38,10 @@ export type OrganizationModelLeadGen = z.infer<typeof OrganizationModelLeadGenSc
37
38
  export type OrganizationModelDelivery = z.infer<typeof OrganizationModelDeliverySchema>
38
39
  ```
39
40
 
40
- ### `OrganizationModelFeatures`
41
+ ### `OrganizationModelFeature`
41
42
 
42
43
  ```typescript
43
- export type OrganizationModelFeatures = z.infer<typeof OrganizationModelFeaturesSchema>
44
- ```
45
-
46
- ### `OrganizationModelFeatureKey`
47
-
48
- ```typescript
49
- export type OrganizationModelFeatureKey = z.infer<typeof FeatureKeySchema>
44
+ export type OrganizationModelFeature = z.infer<typeof FeatureSchema>
50
45
  ```
51
46
 
52
47
  ### `OrganizationModelNavigation`
@@ -61,12 +56,6 @@ export type OrganizationModelNavigation = z.infer<typeof OrganizationModelNaviga
61
56
  export type OrganizationModelSurface = z.infer<typeof SurfaceDefinitionSchema>
62
57
  ```
63
58
 
64
- ### `OrganizationModelSemanticDomain`
65
-
66
- ```typescript
67
- export type OrganizationModelSemanticDomain = z.infer<typeof SemanticDomainSchema>
68
- ```
69
-
70
59
  ### `OrganizationModelResourceMapping`
71
60
 
72
61
  ```typescript
@@ -76,11 +65,7 @@ export type OrganizationModelResourceMapping = z.infer<typeof ResourceMappingSch
76
65
  ### `DeepPartial`
77
66
 
78
67
  ```typescript
79
- export type DeepPartial<T> = T extends Array<infer U>
80
- ? Array<DeepPartial<U>>
81
- : T extends object
82
- ? { [K in keyof T]?: DeepPartial<T[K]> }
83
- : T
68
+ export type DeepPartial<T> = T extends Array<infer U> ? Array<DeepPartial<U>> : T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T
84
69
  ```
85
70
 
86
71
  ## Feature System
@@ -121,15 +106,10 @@ export type FeatureSidebarComponent = ComponentType
121
106
 
122
107
  ```typescript
123
108
  export interface FeatureModule {
124
- /** Unique stable identifier for this feature (e.g. `'crm'`, `'delivery'`). */
109
+ /** Unique stable identifier for this feature (e.g. `'crm'`, `'projects'`). */
125
110
  key: string
126
- /** Feature key used for access-flag gating in the organization model. */
127
- accessFeatureKey: OrganizationModelFeatureKey
128
- /**
129
- * Semantic domain identifiers contributed by this feature.
130
- * Merged with surface-derived domain IDs during resolution.
131
- */
132
- domainIds?: OrganizationModelSemanticDomain['id'][]
111
+ /** Feature ID used for access-flag gating — must match the `id` of a feature in the organization model. */
112
+ featureId: string
133
113
  /**
134
114
  * Capability identifiers contributed by this feature.
135
115
  * Merged into `ResolvedFeatureSemantics.capabilityIds` at resolution time.
@@ -156,7 +136,7 @@ export interface FeatureModule {
156
136
 
157
137
  ```typescript
158
138
  export interface ResolvedFeatureAccess {
159
- featureKey: string
139
+ featureId: string
160
140
  enabled: boolean
161
141
  }
162
142
  ```
@@ -165,7 +145,6 @@ export interface ResolvedFeatureAccess {
165
145
 
166
146
  ```typescript
167
147
  export interface ResolvedFeatureSemantics {
168
- domainIds: OrganizationModelSemanticDomain['id'][]
169
148
  capabilityIds: string[]
170
149
  surfaceIds: string[]
171
150
  surfaces: OrganizationModelSurface[]
@@ -199,7 +178,7 @@ export type ShellNavSource = 'app' | 'feature'
199
178
  export interface ResolvedShellNavItem extends FeatureNavEntry {
200
179
  placement: ShellNavPlacement
201
180
  source: ShellNavSource
202
- accessFeatureKey?: string
181
+ featureId?: string
203
182
  }
204
183
  ```
205
184
 
@@ -262,7 +241,7 @@ export interface OrganizationGraphContextValue {
262
241
  surfaceId?: string
263
242
  surfacePath?: string
264
243
  surfaceType?: OrganizationModelSurface['surfaceType']
265
- featureKey?: OrganizationModelFeatureKey
244
+ featureId?: string
266
245
  }
267
246
  ```
268
247