@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
@@ -14,18 +14,11 @@ var DisplayMetadataSchema = z.object({
14
14
  color: ColorTokenSchema.optional(),
15
15
  icon: IconNameSchema.optional()
16
16
  });
17
- var SemanticDomainSchema = DisplayMetadataSchema.extend({
18
- id: ModelIdSchema,
19
- entityIds: ReferenceIdsSchema,
20
- surfaceIds: ReferenceIdsSchema,
21
- resourceIds: ReferenceIdsSchema,
22
- capabilityIds: ReferenceIdsSchema
23
- });
24
17
  var ResourceMappingSchema = DisplayMetadataSchema.extend({
25
18
  id: ModelIdSchema,
26
19
  resourceId: z.string().trim().min(1).max(255),
27
20
  resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
28
- domainIds: ReferenceIdsSchema,
21
+ featureIds: ReferenceIdsSchema,
29
22
  entityIds: ReferenceIdsSchema,
30
23
  surfaceIds: ReferenceIdsSchema,
31
24
  capabilityIds: ReferenceIdsSchema
@@ -130,55 +123,18 @@ var DEFAULT_ORGANIZATION_MODEL_DELIVERY = {
130
123
  { id: "completed", label: "Completed", order: 9 }
131
124
  ]
132
125
  };
133
- var FeatureKeySchema = z.enum([
134
- "acquisition",
135
- "delivery",
136
- "operations",
137
- "monitoring",
138
- "settings",
139
- "seo",
140
- "calibration"
141
- ]);
142
- var OrganizationModelFeaturesSchema = z.object({
143
- enabled: z.object({
144
- acquisition: z.boolean().default(true),
145
- delivery: z.boolean().default(true),
146
- operations: z.boolean().default(true),
147
- monitoring: z.boolean().default(true),
148
- settings: z.boolean().default(true),
149
- seo: z.boolean().default(false),
150
- calibration: z.boolean().default(false)
151
- }).default({
152
- acquisition: true,
153
- delivery: true,
154
- operations: true,
155
- monitoring: true,
156
- settings: true,
157
- seo: false,
158
- calibration: false
159
- }),
160
- labels: z.object({
161
- acquisition: z.string().trim().min(1).max(80).optional(),
162
- delivery: z.string().trim().min(1).max(80).optional(),
163
- operations: z.string().trim().min(1).max(80).optional(),
164
- monitoring: z.string().trim().min(1).max(80).optional(),
165
- settings: z.string().trim().min(1).max(80).optional(),
166
- seo: z.string().trim().min(1).max(80).optional(),
167
- calibration: z.string().trim().min(1).max(80).optional()
168
- }).default({})
126
+ var FeatureSchema = z.object({
127
+ id: ModelIdSchema,
128
+ label: LabelSchema,
129
+ description: DescriptionSchema.optional(),
130
+ enabled: z.boolean().default(true),
131
+ color: ColorTokenSchema.optional(),
132
+ icon: IconNameSchema.optional(),
133
+ entityIds: ReferenceIdsSchema,
134
+ surfaceIds: ReferenceIdsSchema,
135
+ resourceIds: ReferenceIdsSchema,
136
+ capabilityIds: ReferenceIdsSchema
169
137
  });
170
- var DEFAULT_ORGANIZATION_MODEL_FEATURES = {
171
- enabled: {
172
- acquisition: true,
173
- delivery: true,
174
- operations: true,
175
- monitoring: true,
176
- settings: true,
177
- seo: false,
178
- calibration: false
179
- },
180
- labels: {}
181
- };
182
138
  var LeadGenLifecycleStageSchema = DisplayMetadataSchema.extend({
183
139
  id: ModelIdSchema,
184
140
  order: z.number().int().min(0)
@@ -207,6 +163,13 @@ var DEFAULT_ORGANIZATION_MODEL_LEAD_GEN = {
207
163
  { id: "uploaded", label: "Uploaded", order: 4 }
208
164
  ]
209
165
  };
166
+
167
+ // src/organization-model/contracts.ts
168
+ var PROJECTS_FEATURE_ID = "projects";
169
+ var PROJECTS_INDEX_SURFACE_ID = "projects.index";
170
+ var DELIVERY_PROJECTS_VIEW_CAPABILITY_ID = "delivery.projects.view";
171
+
172
+ // src/organization-model/domains/navigation.ts
210
173
  var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]);
211
174
  var SurfaceDefinitionSchema = z.object({
212
175
  id: ModelIdSchema,
@@ -215,8 +178,8 @@ var SurfaceDefinitionSchema = z.object({
215
178
  surfaceType: SurfaceTypeSchema,
216
179
  description: DescriptionSchema.optional(),
217
180
  icon: IconNameSchema.optional(),
218
- featureKey: FeatureKeySchema.optional(),
219
- domainIds: ReferenceIdsSchema,
181
+ featureId: ModelIdSchema.optional(),
182
+ featureIds: ReferenceIdsSchema,
220
183
  entityIds: ReferenceIdsSchema,
221
184
  resourceIds: ReferenceIdsSchema,
222
185
  capabilityIds: ReferenceIdsSchema,
@@ -241,8 +204,8 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
241
204
  label: "Pipeline",
242
205
  path: "/crm/pipeline",
243
206
  surfaceType: "graph",
244
- featureKey: "acquisition",
245
- domainIds: ["crm"],
207
+ featureId: "crm",
208
+ featureIds: ["crm"],
246
209
  entityIds: ["crm.deal"],
247
210
  resourceIds: [],
248
211
  capabilityIds: ["crm.pipeline.manage"]
@@ -252,30 +215,30 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
252
215
  label: "Lists",
253
216
  path: "/lead-gen/lists",
254
217
  surfaceType: "list",
255
- featureKey: "acquisition",
256
- domainIds: ["lead-gen"],
218
+ featureId: "lead-gen",
219
+ featureIds: ["lead-gen"],
257
220
  entityIds: ["leadgen.list"],
258
221
  resourceIds: [],
259
222
  capabilityIds: ["leadgen.lists.manage"]
260
223
  },
261
224
  {
262
- id: "projects.index",
225
+ id: PROJECTS_INDEX_SURFACE_ID,
263
226
  label: "Projects",
264
227
  path: "/projects",
265
228
  surfaceType: "list",
266
- featureKey: "delivery",
267
- domainIds: ["delivery"],
229
+ featureId: PROJECTS_FEATURE_ID,
230
+ featureIds: [PROJECTS_FEATURE_ID],
268
231
  entityIds: ["delivery.project"],
269
232
  resourceIds: [],
270
- capabilityIds: ["delivery.projects.view"]
233
+ capabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
271
234
  },
272
235
  {
273
236
  id: "operations.organization-graph",
274
237
  label: "Organization Graph",
275
238
  path: "/operations/organization-graph",
276
239
  surfaceType: "graph",
277
- featureKey: "operations",
278
- domainIds: ["operations"],
240
+ featureId: "operations",
241
+ featureIds: ["operations"],
279
242
  entityIds: [],
280
243
  resourceIds: [],
281
244
  capabilityIds: ["operations.organization-graph"]
@@ -285,15 +248,20 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
285
248
  label: "Command View",
286
249
  path: "/operations/command-view",
287
250
  surfaceType: "graph",
288
- featureKey: "operations",
289
- domainIds: ["operations"],
251
+ featureId: "operations",
252
+ featureIds: ["operations"],
290
253
  entityIds: [],
291
254
  resourceIds: [],
292
255
  capabilityIds: ["operations.command-view"]
293
256
  }
294
257
  ],
295
258
  groups: [
296
- { id: "primary-workspace", label: "Workspace", placement: "primary", surfaceIds: ["crm.pipeline", "lead-gen.lists", "projects.index"] },
259
+ {
260
+ id: "primary-workspace",
261
+ label: "Workspace",
262
+ placement: "primary",
263
+ surfaceIds: ["crm.pipeline", "lead-gen.lists", PROJECTS_INDEX_SURFACE_ID]
264
+ },
297
265
  {
298
266
  id: "primary-operations",
299
267
  label: "Operations",
@@ -306,9 +274,8 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
306
274
  // src/organization-model/schema.ts
307
275
  var OrganizationModelSchemaBase = z.object({
308
276
  version: z.literal(1).default(1),
309
- domains: z.array(SemanticDomainSchema).default([]),
277
+ features: z.array(FeatureSchema).default([]),
310
278
  branding: OrganizationModelBrandingSchema,
311
- features: OrganizationModelFeaturesSchema,
312
279
  navigation: OrganizationModelNavigationSchema,
313
280
  crm: OrganizationModelCrmSchema,
314
281
  leadGen: OrganizationModelLeadGenSchema,
@@ -334,7 +301,7 @@ function collectIds(items, ctx, collectionPath, label) {
334
301
  return itemsById;
335
302
  }
336
303
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
337
- const domainsById = collectIds(model.domains, ctx, ["domains"], "Domain");
304
+ const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
338
305
  const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Surface");
339
306
  collectIds(model.navigation.groups, ctx, ["navigation", "groups"], "Navigation group");
340
307
  collectIds(model.resourceMappings, ctx, ["resourceMappings"], "Resource mapping");
@@ -368,40 +335,40 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
368
335
  }
369
336
  });
370
337
  });
371
- model.domains.forEach((domain, domainIndex) => {
372
- domain.surfaceIds.forEach((surfaceId, surfaceIndex) => {
338
+ model.features.forEach((feature, featureIndex) => {
339
+ feature.surfaceIds.forEach((surfaceId, surfaceIndex) => {
373
340
  const surface = surfacesById.get(surfaceId);
374
341
  if (!surface) {
375
342
  addIssue(
376
343
  ctx,
377
- ["domains", domainIndex, "surfaceIds", surfaceIndex],
378
- `Domain "${domain.id}" references unknown surface "${surfaceId}"`
344
+ ["features", featureIndex, "surfaceIds", surfaceIndex],
345
+ `Feature "${feature.id}" references unknown surface "${surfaceId}"`
379
346
  );
380
347
  return;
381
348
  }
382
- if (!surface.domainIds.includes(domain.id)) {
349
+ if (!surface.featureIds.includes(feature.id)) {
383
350
  addIssue(
384
351
  ctx,
385
- ["domains", domainIndex, "surfaceIds", surfaceIndex],
386
- `Domain "${domain.id}" references surface "${surfaceId}" but that surface does not include domain "${domain.id}"`
352
+ ["features", featureIndex, "surfaceIds", surfaceIndex],
353
+ `Feature "${feature.id}" references surface "${surfaceId}" but that surface does not include feature "${feature.id}"`
387
354
  );
388
355
  }
389
356
  });
390
- domain.resourceIds.forEach((resourceId, resourceIndex) => {
357
+ feature.resourceIds.forEach((resourceId, resourceIndex) => {
391
358
  const resourceMapping = resourceMappingsByResourceId.get(resourceId);
392
359
  if (!resourceMapping) {
393
360
  addIssue(
394
361
  ctx,
395
- ["domains", domainIndex, "resourceIds", resourceIndex],
396
- `Domain "${domain.id}" references unknown resource "${resourceId}"`
362
+ ["features", featureIndex, "resourceIds", resourceIndex],
363
+ `Feature "${feature.id}" references unknown resource "${resourceId}"`
397
364
  );
398
365
  return;
399
366
  }
400
- if (!resourceMapping.domainIds.includes(domain.id)) {
367
+ if (!resourceMapping.featureIds.includes(feature.id)) {
401
368
  addIssue(
402
369
  ctx,
403
- ["domains", domainIndex, "resourceIds", resourceIndex],
404
- `Domain "${domain.id}" references resource "${resourceId}" but that resource mapping does not include domain "${domain.id}"`
370
+ ["features", featureIndex, "resourceIds", resourceIndex],
371
+ `Feature "${feature.id}" references resource "${resourceId}" but that resource mapping does not include feature "${feature.id}"`
405
372
  );
406
373
  }
407
374
  });
@@ -414,21 +381,21 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
414
381
  `Surface "${surface.id}" references unknown parent surface "${surface.parentId}"`
415
382
  );
416
383
  }
417
- surface.domainIds.forEach((domainId, domainIndex) => {
418
- const domain = domainsById.get(domainId);
419
- if (!domain) {
384
+ surface.featureIds.forEach((featureId, featureIndex) => {
385
+ const feature = featuresById.get(featureId);
386
+ if (!feature) {
420
387
  addIssue(
421
388
  ctx,
422
- ["navigation", "surfaces", surfaceIndex, "domainIds", domainIndex],
423
- `Surface "${surface.id}" references unknown domain "${domainId}"`
389
+ ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
390
+ `Surface "${surface.id}" references unknown feature "${featureId}"`
424
391
  );
425
392
  return;
426
393
  }
427
- if (!domain.surfaceIds.includes(surface.id)) {
394
+ if (!feature.surfaceIds.includes(surface.id)) {
428
395
  addIssue(
429
396
  ctx,
430
- ["navigation", "surfaces", surfaceIndex, "domainIds", domainIndex],
431
- `Surface "${surface.id}" references domain "${domainId}" but that domain does not include surface "${surface.id}"`
397
+ ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
398
+ `Surface "${surface.id}" references feature "${featureId}" but that feature does not include surface "${surface.id}"`
432
399
  );
433
400
  }
434
401
  });
@@ -452,21 +419,21 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
452
419
  });
453
420
  });
454
421
  model.resourceMappings.forEach((resourceMapping, resourceIndex) => {
455
- resourceMapping.domainIds.forEach((domainId, domainIndex) => {
456
- const domain = domainsById.get(domainId);
457
- if (!domain) {
422
+ resourceMapping.featureIds.forEach((featureId, featureIndex) => {
423
+ const feature = featuresById.get(featureId);
424
+ if (!feature) {
458
425
  addIssue(
459
426
  ctx,
460
- ["resourceMappings", resourceIndex, "domainIds", domainIndex],
461
- `Resource mapping "${resourceMapping.id}" references unknown domain "${domainId}"`
427
+ ["resourceMappings", resourceIndex, "featureIds", featureIndex],
428
+ `Resource mapping "${resourceMapping.id}" references unknown feature "${featureId}"`
462
429
  );
463
430
  return;
464
431
  }
465
- if (!domain.resourceIds.includes(resourceMapping.resourceId)) {
432
+ if (!feature.resourceIds.includes(resourceMapping.resourceId)) {
466
433
  addIssue(
467
434
  ctx,
468
- ["resourceMappings", resourceIndex, "domainIds", domainIndex],
469
- `Resource mapping "${resourceMapping.id}" references domain "${domainId}" but that domain does not include resource "${resourceMapping.resourceId}"`
435
+ ["resourceMappings", resourceIndex, "featureIds", featureIndex],
436
+ `Resource mapping "${resourceMapping.id}" references feature "${featureId}" but that feature does not include resource "${resourceMapping.resourceId}"`
470
437
  );
471
438
  }
472
439
  });
@@ -494,11 +461,12 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
494
461
  // src/organization-model/defaults.ts
495
462
  var DEFAULT_ORGANIZATION_MODEL = {
496
463
  version: 1,
497
- domains: [
464
+ features: [
498
465
  {
499
466
  id: "crm",
500
467
  label: "CRM",
501
468
  description: "Relationship pipeline and deal management",
469
+ enabled: true,
502
470
  color: "blue",
503
471
  entityIds: ["crm.deal"],
504
472
  surfaceIds: ["crm.pipeline"],
@@ -509,6 +477,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
509
477
  id: "lead-gen",
510
478
  label: "Lead Gen",
511
479
  description: "Prospecting, qualification, and outreach preparation",
480
+ enabled: true,
512
481
  color: "cyan",
513
482
  entityIds: ["leadgen.list", "leadgen.company", "leadgen.contact"],
514
483
  surfaceIds: ["lead-gen.lists"],
@@ -516,28 +485,56 @@ var DEFAULT_ORGANIZATION_MODEL = {
516
485
  capabilityIds: ["leadgen.lists.manage"]
517
486
  },
518
487
  {
519
- id: "delivery",
488
+ id: PROJECTS_FEATURE_ID,
520
489
  label: "Projects",
521
490
  description: "Projects, milestones, and client work execution",
491
+ enabled: true,
522
492
  color: "orange",
523
493
  entityIds: ["delivery.project", "delivery.milestone", "delivery.task"],
524
- surfaceIds: ["projects.index"],
494
+ surfaceIds: [PROJECTS_INDEX_SURFACE_ID],
525
495
  resourceIds: [],
526
- capabilityIds: ["delivery.projects.view"]
496
+ capabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
527
497
  },
528
498
  {
529
499
  id: "operations",
530
500
  label: "Operations",
531
501
  description: "Operational resources, topology, and orchestration visibility",
502
+ enabled: true,
532
503
  color: "violet",
533
504
  entityIds: [],
534
505
  surfaceIds: ["operations.organization-graph", "operations.command-view"],
535
506
  resourceIds: [],
536
507
  capabilityIds: ["operations.organization-graph", "operations.command-view"]
508
+ },
509
+ {
510
+ id: "monitoring",
511
+ label: "Monitoring",
512
+ enabled: true,
513
+ entityIds: [],
514
+ surfaceIds: [],
515
+ resourceIds: [],
516
+ capabilityIds: []
517
+ },
518
+ {
519
+ id: "settings",
520
+ label: "Settings",
521
+ enabled: true,
522
+ entityIds: [],
523
+ surfaceIds: [],
524
+ resourceIds: [],
525
+ capabilityIds: []
526
+ },
527
+ {
528
+ id: "seo",
529
+ label: "SEO",
530
+ enabled: false,
531
+ entityIds: [],
532
+ surfaceIds: [],
533
+ resourceIds: [],
534
+ capabilityIds: []
537
535
  }
538
536
  ],
539
537
  branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
540
- features: DEFAULT_ORGANIZATION_MODEL_FEATURES,
541
538
  navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
542
539
  crm: DEFAULT_ORGANIZATION_MODEL_CRM,
543
540
  leadGen: DEFAULT_ORGANIZATION_MODEL_LEAD_GEN,
@@ -592,4 +589,60 @@ function resolveOrganizationModel(override) {
592
589
  return OrganizationModelSchema.parse(merged);
593
590
  }
594
591
 
595
- export { DEFAULT_ORGANIZATION_MODEL, OrganizationModelSchema, defineOrganizationModel, resolveOrganizationModel };
592
+ // src/organization-model/foundation.ts
593
+ function createFoundationOrganizationModel(branding) {
594
+ const canonical = resolveOrganizationModel({ branding });
595
+ function requireCoreSurface(surfaceId) {
596
+ const surface = canonical.navigation.surfaces.find((candidate) => candidate.id === surfaceId);
597
+ if (!surface) {
598
+ throw new Error(`Missing organization surface: ${surfaceId}`);
599
+ }
600
+ return surface;
601
+ }
602
+ const operationsGraphSurface = requireCoreSurface("operations.organization-graph");
603
+ const projectsSurface = requireCoreSurface(PROJECTS_INDEX_SURFACE_ID);
604
+ const leadGenSurface = requireCoreSurface("lead-gen.lists");
605
+ const crmSurface = requireCoreSurface("crm.pipeline");
606
+ const navigationSurfaces = [
607
+ { ...operationsGraphSurface, id: "operations", path: "/operations", icon: "operations" },
608
+ { ...operationsGraphSurface, path: "/operations", icon: "operations" },
609
+ { ...projectsSurface, id: PROJECTS_FEATURE_ID, icon: "projects" },
610
+ { ...leadGenSurface, id: "lead-gen", icon: "lead-gen" },
611
+ { ...crmSurface, id: "crm", icon: "crm" },
612
+ {
613
+ id: "settings",
614
+ label: "Settings",
615
+ path: "/settings/account",
616
+ surfaceType: "settings",
617
+ icon: "settings",
618
+ featureId: "settings",
619
+ featureIds: ["settings"],
620
+ entityIds: [],
621
+ resourceIds: [],
622
+ capabilityIds: []
623
+ }
624
+ ];
625
+ const homeLabel = "Dashboard";
626
+ const quickAccessSurfaceIds = ["operations", PROJECTS_FEATURE_ID, "lead-gen", "crm"];
627
+ const model = {
628
+ ...canonical,
629
+ navigation: {
630
+ defaultSurfaceId: "operations",
631
+ homeLabel,
632
+ quickAccessSurfaceIds: [...quickAccessSurfaceIds],
633
+ surfaces: navigationSurfaces
634
+ }
635
+ };
636
+ function getOrganizationSurface(surfaceId) {
637
+ return model.navigation.surfaces.find((candidate) => candidate.id === surfaceId);
638
+ }
639
+ return {
640
+ canonical,
641
+ model,
642
+ homeLabel,
643
+ quickAccessSurfaceIds,
644
+ getOrganizationSurface
645
+ };
646
+ }
647
+
648
+ export { DEFAULT_ORGANIZATION_MODEL, DELIVERY_PROJECTS_VIEW_CAPABILITY_ID, FeatureSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, createFoundationOrganizationModel, defineOrganizationModel, resolveOrganizationModel };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "description": "Minimal shared constants across Elevasis monorepo",
6
6
  "sideEffects": false,
package/src/README.md CHANGED
@@ -6,26 +6,33 @@ This package is the source of truth for shared types, schemas, and contract help
6
6
 
7
7
  ## Import Rules
8
8
 
9
- - Use `@elevasis/core` for browser-safe shared types and schemas.
10
- - Use `@elevasis/core/server` only for Node.js-only helpers and services.
11
- - Use `@elevasis/core/test-utils` for test fixtures and mocks.
12
- - Prefer the narrowest published subpath that matches the work you are doing.
9
+ - Use `@elevasis/core` (root export) for browser-safe shared types and schemas.
10
+ - Use `@elevasis/core/organization-model` for the semantic contract layer.
11
+ - These are the only two subpaths available to external consumers of the published npm package.
12
+ - Paths like `@elevasis/core/server`, `@elevasis/core/test-utils`, `@elevasis/core/platform`, etc. are internal monorepo paths (`@repo/core/...`) and are NOT available to external consumers.
13
13
 
14
14
  ## Published Surface Groups
15
15
 
16
- - `platform` - shared constants, utilities, registry, SSE, and API types.
17
- - `auth` - multi-tenancy types for organizations, users, memberships, invitations, and credentials.
18
- - `execution` - workflow, agent, scheduler, calibration, and execution-interface contracts.
19
- - `commands` - command queue types and schemas.
20
- - `deployments` - deployment response types.
21
- - `operations` - sessions, notifications, observability, activities, triggers, and debug logs.
22
- - `business` - acquisition and SEO contracts, plus the PDF surface under its own subpaths.
23
- - `organization-model` - the semantic contract layer for CRM, lead gen, delivery, features, branding, and navigation.
24
- - `supabase` - generated database types and helpers.
25
- - `forms` - shared form schemas and form-facing types.
26
- - `integrations` - OAuth and credential contracts.
27
- - `projects` - project management request and response schemas.
28
- - `content` - published content metadata types.
16
+ The published `@elevasis/core` npm package exposes exactly two subpaths:
17
+
18
+ - `.` (`@elevasis/core`) - browser-safe shared types, schemas, and constants.
19
+ - `./organization-model` (`@elevasis/core/organization-model`) - the semantic contract layer for CRM, lead gen, delivery, features, branding, and navigation.
20
+
21
+ Within the monorepo, the internal `@repo/core` package exposes additional subpaths for use by `apps/` and other packages:
22
+
23
+ - `@repo/core/server` - Node.js-only helpers and services.
24
+ - `@repo/core/platform` - shared constants, utilities, registry, SSE, and API types.
25
+ - `@repo/core/auth` - multi-tenancy types for organizations, users, memberships, invitations, and credentials.
26
+ - `@repo/core/execution` - workflow, agent, scheduler, and execution-interface contracts.
27
+ - `@repo/core/commands` - command queue types and schemas.
28
+ - `@repo/core/operations` - sessions, notifications, observability, activities, triggers, and debug logs.
29
+ - `@repo/core/supabase` - generated database types and helpers.
30
+ - `@repo/core/integrations/...` - OAuth and credential contracts.
31
+ - `@repo/core/projects/api-schemas` - project management request and response schemas.
32
+ - `@repo/core/content` - published content metadata types.
33
+ - `@repo/core/test-utils` - test fixtures and mocks (internal use only).
34
+
35
+ These `@repo/core/*` subpaths are NOT available in the published `@elevasis/core` package.
29
36
 
30
37
  ## When To Read Deeper
31
38
 
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest'
2
+ import { DELIVERY_PROJECTS_VIEW_CAPABILITY_ID, PROJECTS_FEATURE_ID } from '../organization-model/published'
2
3
  import {
3
4
  getOrganizationSurface,
4
5
  homeLabel,
@@ -14,18 +15,18 @@ describe('template foundations compatibility', () => {
14
15
  expect(foundationOrganizationModel.navigation.defaultSurfaceId).toBe('operations')
15
16
  expect(getOrganizationSurface('operations')).toMatchObject({
16
17
  id: 'operations',
17
- label: 'Operations',
18
+ label: 'Organization Graph',
18
19
  path: '/operations',
19
20
  surfaceType: 'graph',
20
- featureKey: 'operations'
21
+ featureId: 'operations'
21
22
  })
22
23
 
23
24
  expect(getOrganizationSurface('operations.organization-graph')).toMatchObject({
24
25
  id: 'operations.organization-graph',
25
- label: 'Operations',
26
+ label: 'Organization Graph',
26
27
  path: '/operations',
27
28
  surfaceType: 'graph',
28
- featureKey: 'operations'
29
+ featureId: 'operations'
29
30
  })
30
31
  })
31
32
 
@@ -33,45 +34,41 @@ describe('template foundations compatibility', () => {
33
34
  const legacySurfaces = [
34
35
  {
35
36
  id: 'operations',
36
- label: 'Operations',
37
+ label: 'Organization Graph',
37
38
  surfaceType: 'graph',
38
- expectedFeatureKey: 'operations',
39
+ expectedFeatureId: 'operations',
39
40
  expectedIcon: 'operations',
40
41
  expectedPath: '/operations',
41
- expectedDomainIds: ['operations'],
42
42
  expectedEntityIds: [],
43
- expectedCapabilityIds: ['operations.organization-graph', 'operations.command-view']
43
+ expectedCapabilityIds: ['operations.organization-graph']
44
44
  },
45
45
  {
46
- id: 'projects',
46
+ id: PROJECTS_FEATURE_ID,
47
47
  label: 'Projects',
48
48
  surfaceType: 'list',
49
- expectedFeatureKey: 'projects',
49
+ expectedFeatureId: PROJECTS_FEATURE_ID,
50
50
  expectedIcon: 'projects',
51
51
  expectedPath: '/projects',
52
- expectedDomainIds: ['delivery'],
53
52
  expectedEntityIds: ['delivery.project'],
54
- expectedCapabilityIds: ['delivery.projects.view']
53
+ expectedCapabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
55
54
  },
56
55
  {
57
56
  id: 'lead-gen',
58
- label: 'Lead Gen',
57
+ label: 'Lists',
59
58
  surfaceType: 'list',
60
- expectedFeatureKey: 'lead-gen',
59
+ expectedFeatureId: 'lead-gen',
61
60
  expectedIcon: 'lead-gen',
62
- expectedPath: '/lead-gen',
63
- expectedDomainIds: ['lead-gen'],
61
+ expectedPath: '/lead-gen/lists',
64
62
  expectedEntityIds: ['leadgen.list'],
65
63
  expectedCapabilityIds: ['leadgen.lists.manage']
66
64
  },
67
65
  {
68
66
  id: 'crm',
69
- label: 'CRM',
67
+ label: 'Pipeline',
70
68
  surfaceType: 'graph',
71
- expectedFeatureKey: 'crm',
69
+ expectedFeatureId: 'crm',
72
70
  expectedIcon: 'crm',
73
- expectedPath: '/crm',
74
- expectedDomainIds: ['crm'],
71
+ expectedPath: '/crm/pipeline',
75
72
  expectedEntityIds: ['crm.deal'],
76
73
  expectedCapabilityIds: ['crm.pipeline.manage']
77
74
  }
@@ -86,8 +83,7 @@ describe('template foundations compatibility', () => {
86
83
  path: surface.expectedPath,
87
84
  surfaceType: surface.surfaceType,
88
85
  icon: surface.expectedIcon,
89
- featureKey: surface.expectedFeatureKey,
90
- domainIds: surface.expectedDomainIds,
86
+ featureId: surface.expectedFeatureId,
91
87
  entityIds: surface.expectedEntityIds,
92
88
  resourceIds: [],
93
89
  capabilityIds: surface.expectedCapabilityIds
@@ -96,20 +92,16 @@ describe('template foundations compatibility', () => {
96
92
  })
97
93
 
98
94
  it('maps grouped core features onto the legacy template feature vocabulary', () => {
99
- expect(foundationOrganizationModel.features.enabled.acquisition).toBe(true)
100
- expect(foundationOrganizationModel.features.enabled.delivery).toBe(true)
101
- expect(foundationOrganizationModel.features.enabled.crm).toBe(
102
- foundationOrganizationModel.features.enabled.acquisition
103
- )
104
- expect(foundationOrganizationModel.features.enabled['lead-gen']).toBe(
105
- foundationOrganizationModel.features.enabled.acquisition
106
- )
107
- expect(foundationOrganizationModel.features.enabled.projects).toBe(
108
- foundationOrganizationModel.features.enabled.delivery
109
- )
95
+ const features = foundationOrganizationModel.features as Array<{ id: string; label: string; enabled: boolean }>
96
+ const featureById = (id: string) => features.find((f) => f.id === id)
110
97
 
111
- expect(foundationOrganizationModel.features.labels.crm).toBe('CRM')
112
- expect(foundationOrganizationModel.features.labels['lead-gen']).toBe('Lead Gen')
113
- expect(foundationOrganizationModel.features.labels.projects).toBe('Projects')
98
+ expect(featureById('crm')?.enabled).toBe(true)
99
+ expect(featureById('lead-gen')?.enabled).toBe(true)
100
+ expect(featureById('projects')?.enabled).toBe(true)
101
+ expect(featureById('operations')?.enabled).toBe(true)
102
+
103
+ expect(featureById('crm')?.label).toBe('CRM')
104
+ expect(featureById('lead-gen')?.label).toBe('Lead Gen')
105
+ expect(featureById('projects')?.label).toBe('Projects')
114
106
  })
115
107
  })