@elevasis/core 0.34.1 → 0.35.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 (33) hide show
  1. package/dist/auth/index.d.ts +74 -2
  2. package/dist/auth/index.js +65 -30
  3. package/dist/index.d.ts +60 -2
  4. package/dist/index.js +52 -1
  5. package/dist/knowledge/index.d.ts +12 -0
  6. package/dist/organization-model/index.d.ts +60 -2
  7. package/dist/organization-model/index.js +52 -1
  8. package/dist/test-utils/index.d.ts +12 -0
  9. package/dist/test-utils/index.js +51 -0
  10. package/package.json +1 -1
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +69 -30
  12. package/src/auth/multi-tenancy/index.ts +29 -26
  13. package/src/auth/multi-tenancy/org-id.test.ts +139 -0
  14. package/src/auth/multi-tenancy/org-id.ts +112 -0
  15. package/src/business/acquisition/api-schemas.test.ts +456 -28
  16. package/src/business/acquisition/ontology-validation.ts +715 -23
  17. package/src/execution/engine/tools/platform/storage/__tests__/storage.test.ts +997 -998
  18. package/src/organization-model/__tests__/domains/systems.test.ts +61 -15
  19. package/src/organization-model/__tests__/domains/topology.test.ts +23 -0
  20. package/src/organization-model/__tests__/schema.test.ts +112 -0
  21. package/src/organization-model/domains/systems.ts +44 -0
  22. package/src/organization-model/domains/topology.ts +18 -1
  23. package/src/organization-model/published.ts +19 -1
  24. package/src/organization-model/schema-refinements.ts +23 -0
  25. package/src/organization-model/types.ts +17 -1
  26. package/src/platform/constants/versions.ts +1 -1
  27. package/src/platform/registry/__tests__/validation.test.ts +254 -15
  28. package/src/platform/registry/index.ts +28 -15
  29. package/src/platform/registry/validation.ts +180 -2
  30. package/src/reference/_generated/contracts.md +44 -0
  31. package/src/supabase/__tests__/helpers.test.ts +92 -51
  32. package/src/supabase/helpers.ts +40 -20
  33. package/src/supabase/index.ts +52 -52
@@ -992,6 +992,26 @@ var SystemUiSchema = z.object({
992
992
  icon: IconNameSchema.optional(),
993
993
  order: z.number().int().optional()
994
994
  });
995
+ var SystemInterfaceKeySchema = ModelIdSchema;
996
+ var SystemInterfaceLifecycleSchema = z.enum(["draft", "active", "disabled", "deprecated", "archived"]).meta({ label: "System interface lifecycle", color: "teal" });
997
+ var SystemInterfaceReadinessProfileSchema = z.string().trim().min(1).max(200).regex(
998
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*(?:\.[a-z0-9][a-z0-9-]*)?$/,
999
+ 'Readiness profiles must use dotted lowercase identifiers (e.g. "sales.lead-gen.api")'
1000
+ );
1001
+ var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
1002
+ var SystemApiInterfaceSchema = z.object({
1003
+ lifecycle: SystemInterfaceLifecycleSchema.default("active"),
1004
+ readinessProfile: SystemInterfaceReadinessProfileSchema.optional(),
1005
+ /**
1006
+ * Resource ids that participate in this API interface. This scopes readiness
1007
+ * derivation without duplicating authored required/provided contract refs.
1008
+ */
1009
+ resourceIds: SystemInterfaceResourceScopeSchema.optional()
1010
+ }).strict();
1011
+ var SystemInterfaceRefSchema = z.object({
1012
+ systemPath: SystemPathSchema,
1013
+ interfaceKey: SystemInterfaceKeySchema
1014
+ }).strict();
995
1015
  var JsonValueSchema = z.lazy(
996
1016
  () => z.union([
997
1017
  z.string(),
@@ -1030,6 +1050,8 @@ var SystemEntrySchema = z.object({
1030
1050
  policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
1031
1051
  /** Optional goals this system contributes to. */
1032
1052
  drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
1053
+ /** Thin API runtime-boundary marker. Readiness is derived from scoped resources and topology. */
1054
+ apiInterface: SystemApiInterfaceSchema.optional(),
1033
1055
  /** @deprecated Use lifecycle. Accepted for one publish cycle. */
1034
1056
  status: SystemStatusSchema.optional(),
1035
1057
  /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
@@ -1508,6 +1530,15 @@ var OmTopologyMetadataSchema = z.record(z.string().trim().min(1).max(120), JsonV
1508
1530
  }
1509
1531
  visit(metadata, []);
1510
1532
  });
1533
+ var OmTopologySystemInterfaceGrantSchema = z.object({
1534
+ consumer: SystemInterfaceRefSchema,
1535
+ provider: SystemInterfaceRefSchema,
1536
+ resourceIds: z.array(ResourceIdSchema).default([]),
1537
+ ontologyIds: z.array(OntologyIdSchema).default([])
1538
+ }).strict();
1539
+ var OmTopologySystemInterfaceGrantMetadataSchema = z.object({
1540
+ systemInterfaceGrant: OmTopologySystemInterfaceGrantSchema
1541
+ }).strict();
1511
1542
  var OmTopologyRelationshipSchema = z.object({
1512
1543
  from: OmTopologyNodeRefSchema,
1513
1544
  kind: OmTopologyRelationshipKindSchema,
@@ -2247,6 +2278,26 @@ function refineOrganizationModel(model, ctx) {
2247
2278
  );
2248
2279
  }
2249
2280
  });
2281
+ allSystems.forEach(({ path: systemPath, schemaPath, system }) => {
2282
+ system.apiInterface?.resourceIds?.forEach((resourceId, resourceIndex) => {
2283
+ const resource = resourcesById.get(resourceId);
2284
+ if (resource === void 0) {
2285
+ addIssue(
2286
+ ctx,
2287
+ [...schemaPath, "apiInterface", "resourceIds", resourceIndex],
2288
+ `System Interface "${systemPath}/api" scopes unknown resource "${resourceId}"`
2289
+ );
2290
+ return;
2291
+ }
2292
+ if (resource.systemPath !== systemPath) {
2293
+ addIssue(
2294
+ ctx,
2295
+ [...schemaPath, "apiInterface", "resourceIds", resourceIndex],
2296
+ `System Interface "${systemPath}/api" scopes resource "${resourceId}" from system "${resource.systemPath}"`
2297
+ );
2298
+ }
2299
+ });
2300
+ });
2250
2301
  function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
2251
2302
  const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
2252
2303
  ontologyIds2.forEach((ontologyId, ontologyIndex) => {
@@ -3406,4 +3457,4 @@ function scaffoldOrganizationModel(model, spec) {
3406
3457
  return scaffoldKnowledgeNode(model, spec);
3407
3458
  }
3408
3459
 
3409
- export { ActionIdSchema, ActionInvocationKindSchema, ActionInvocationSchema, ActionRefSchema, ActionSchema, ActionScopeSchema, ActionsDomainSchema, AgentKindSchema, AgentResourceEntrySchema, AgentRoleHolderSchema, ApiEndpointInvocationSchema, CodeReferenceRoleSchema, CodeReferenceSchema, ContractRefSchema, CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ONTOLOGY_SCOPE, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_ACTIONS, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_NAVIGATION, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_POLICIES, DEFAULT_ORGANIZATION_MODEL_RESOURCES, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, DEFAULT_ORGANIZATION_MODEL_TOPOLOGY, EntitiesDomainSchema, EntityIdSchema, EntityLinkKindSchema, EntityLinkSchema, EntitySchema, EventDescriptorSchema, EventEmissionDescriptorSchema, EventIdSchema, FirmographicsSchema, GoalsDomainSchema, HumanRoleHolderSchema, IconNameSchema, IntegrationResourceEntrySchema, KNOWLEDGE_FEATURE_ID, KNOWLEDGE_SYSTEM_ID, KeyResultSchema, KnowledgeDomainSchema, KnowledgeLinkSchema, KnowledgeTargetKindSchema, KnowledgeTargetRefSchema, LinkSchema, MONITORING_FEATURE_ID, MONITORING_SYSTEM_ID, McpToolInvocationSchema, NavigationGroupSchema, NodeIdPathSchema, NodeIdStringSchema, OPERATIONS_COMMAND_VIEW_SURFACE_ID, OPERATIONS_FEATURE_ID, OPERATIONS_SYSTEM_ID, ORGANIZATION_MODEL_ICON_TOKENS, ObjectiveSchema, OfferingsDomainSchema, OmTopologyDomainSchema, OmTopologyMetadataSchema, OmTopologyNodeKindSchema, OmTopologyNodeRefSchema, OmTopologyRelationshipKindSchema, OmTopologyRelationshipSchema, OntologyActionTypeSchema, OntologyCatalogTypeSchema, OntologyEventTypeSchema, OntologyGroupSchema, OntologyIdSchema, OntologyInterfaceTypeSchema, OntologyKindSchema, OntologyLinkTypeSchema, OntologyObjectTypeSchema, OntologyScopeSchema, OntologySharedPropertySchema, OntologySurfaceTypeSchema, OntologyValueTypeSchema, OrgKnowledgeKindSchema, OrgKnowledgeNodeSchema, OrganizationModelBuiltinIconTokenSchema, OrganizationModelDomainKeySchema, OrganizationModelDomainMetadataByDomainSchema, OrganizationModelDomainMetadataSchema, OrganizationModelIconTokenSchema, OrganizationModelNavigationSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_SYSTEM_ID, PROJECTS_VIEW_ACTION_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PROSPECTING_SYSTEM_ID, PoliciesDomainSchema, PolicyApplicabilitySchema, PolicyEffectSchema, PolicyIdSchema, PolicyPredicateSchema, PolicySchema, PolicyTriggerSchema, PricingModelSchema, ProductSchema, ResourceEntrySchema, ResourceGovernanceStatusSchema, ResourceIdSchema, ResourceKindSchema, ResourceOntologyBindingSchema, ResourcesDomainSchema, RoleHolderSchema, RoleHoldersSchema, RoleIdSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SALES_SYSTEM_ID, SEO_FEATURE_ID, SEO_SYSTEM_ID, SETTINGS_FEATURE_ID, SETTINGS_ROLES_SURFACE_ID, SETTINGS_SYSTEM_ID, ScriptExecutionInvocationSchema, ScriptResourceEntrySchema, ScriptResourceLanguageSchema, ScriptResourceSourceSchema, SidebarNavigationSchema, SidebarNodeSchema, SidebarSectionSchema, SidebarSurfaceTargetsSchema, SlashCommandInvocationSchema, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, SurfaceDefinitionSchema, SurfaceTypeSchema, SystemEntrySchema, SystemIdSchema, SystemKindSchema, SystemLifecycleSchema, SystemPathSchema, SystemStatusSchema, SystemUiSchema, SystemsDomainSchema, TeamRoleHolderSchema, TechStackEntrySchema, UiPositionSchema, WorkflowResourceEntrySchema, compileOrganizationOntology, compileTopologyNodeRef, createFoundationOrganizationModel, defineAction, defineActions, defineCustomer, defineCustomers, defineDomainRecord, defineEntities, defineEntity, defineGoal, defineGoals, defineKnowledgeNode, defineKnowledgeNodes, defineOffering, defineOfferings, defineOrganizationModel, definePolicies, definePolicy, defineResource, defineResourceOntology, defineResources, defineRole, defineRoles, defineStatus, defineStatuses, defineSystem, defineSystems, defineTopology, defineTopologyRelationship, findOrganizationActionById, formatOntologyId, getOntologyDiagnostics, getSortedSidebarEntries, isOntologyGraphNodeId, isOntologyTopologyRef, listAllSystems, listResolvedOntologyRecords, ontologyGraphNodeId, ontologyIdFromGraphNodeId, parseContractRef, parseOntologyId, parseTopologyNodeRef, projectOrganizationSurfaces, resolveOrganizationModel, resolveOrganizationModelWithResources, scaffoldOrganizationModel, topologyRef, topologyRelationship, validateOrganizationSurfaceProjection };
3460
+ export { ActionIdSchema, ActionInvocationKindSchema, ActionInvocationSchema, ActionRefSchema, ActionSchema, ActionScopeSchema, ActionsDomainSchema, AgentKindSchema, AgentResourceEntrySchema, AgentRoleHolderSchema, ApiEndpointInvocationSchema, CodeReferenceRoleSchema, CodeReferenceSchema, ContractRefSchema, CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ONTOLOGY_SCOPE, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_ACTIONS, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_NAVIGATION, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_POLICIES, DEFAULT_ORGANIZATION_MODEL_RESOURCES, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, DEFAULT_ORGANIZATION_MODEL_TOPOLOGY, EntitiesDomainSchema, EntityIdSchema, EntityLinkKindSchema, EntityLinkSchema, EntitySchema, EventDescriptorSchema, EventEmissionDescriptorSchema, EventIdSchema, FirmographicsSchema, GoalsDomainSchema, HumanRoleHolderSchema, IconNameSchema, IntegrationResourceEntrySchema, KNOWLEDGE_FEATURE_ID, KNOWLEDGE_SYSTEM_ID, KeyResultSchema, KnowledgeDomainSchema, KnowledgeLinkSchema, KnowledgeTargetKindSchema, KnowledgeTargetRefSchema, LinkSchema, MONITORING_FEATURE_ID, MONITORING_SYSTEM_ID, McpToolInvocationSchema, NavigationGroupSchema, NodeIdPathSchema, NodeIdStringSchema, OPERATIONS_COMMAND_VIEW_SURFACE_ID, OPERATIONS_FEATURE_ID, OPERATIONS_SYSTEM_ID, ORGANIZATION_MODEL_ICON_TOKENS, ObjectiveSchema, OfferingsDomainSchema, OmTopologyDomainSchema, OmTopologyMetadataSchema, OmTopologyNodeKindSchema, OmTopologyNodeRefSchema, OmTopologyRelationshipKindSchema, OmTopologyRelationshipSchema, OmTopologySystemInterfaceGrantMetadataSchema, OmTopologySystemInterfaceGrantSchema, OntologyActionTypeSchema, OntologyCatalogTypeSchema, OntologyEventTypeSchema, OntologyGroupSchema, OntologyIdSchema, OntologyInterfaceTypeSchema, OntologyKindSchema, OntologyLinkTypeSchema, OntologyObjectTypeSchema, OntologyScopeSchema, OntologySharedPropertySchema, OntologySurfaceTypeSchema, OntologyValueTypeSchema, OrgKnowledgeKindSchema, OrgKnowledgeNodeSchema, OrganizationModelBuiltinIconTokenSchema, OrganizationModelDomainKeySchema, OrganizationModelDomainMetadataByDomainSchema, OrganizationModelDomainMetadataSchema, OrganizationModelIconTokenSchema, OrganizationModelNavigationSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_SYSTEM_ID, PROJECTS_VIEW_ACTION_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PROSPECTING_SYSTEM_ID, PoliciesDomainSchema, PolicyApplicabilitySchema, PolicyEffectSchema, PolicyIdSchema, PolicyPredicateSchema, PolicySchema, PolicyTriggerSchema, PricingModelSchema, ProductSchema, ResourceEntrySchema, ResourceGovernanceStatusSchema, ResourceIdSchema, ResourceKindSchema, ResourceOntologyBindingSchema, ResourcesDomainSchema, RoleHolderSchema, RoleHoldersSchema, RoleIdSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SALES_SYSTEM_ID, SEO_FEATURE_ID, SEO_SYSTEM_ID, SETTINGS_FEATURE_ID, SETTINGS_ROLES_SURFACE_ID, SETTINGS_SYSTEM_ID, ScriptExecutionInvocationSchema, ScriptResourceEntrySchema, ScriptResourceLanguageSchema, ScriptResourceSourceSchema, SidebarNavigationSchema, SidebarNodeSchema, SidebarSectionSchema, SidebarSurfaceTargetsSchema, SlashCommandInvocationSchema, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, SurfaceDefinitionSchema, SurfaceTypeSchema, SystemApiInterfaceSchema, SystemEntrySchema, SystemIdSchema, SystemInterfaceKeySchema, SystemInterfaceLifecycleSchema, SystemInterfaceReadinessProfileSchema, SystemInterfaceRefSchema, SystemKindSchema, SystemLifecycleSchema, SystemPathSchema, SystemStatusSchema, SystemUiSchema, SystemsDomainSchema, TeamRoleHolderSchema, TechStackEntrySchema, UiPositionSchema, WorkflowResourceEntrySchema, compileOrganizationOntology, compileTopologyNodeRef, createFoundationOrganizationModel, defineAction, defineActions, defineCustomer, defineCustomers, defineDomainRecord, defineEntities, defineEntity, defineGoal, defineGoals, defineKnowledgeNode, defineKnowledgeNodes, defineOffering, defineOfferings, defineOrganizationModel, definePolicies, definePolicy, defineResource, defineResourceOntology, defineResources, defineRole, defineRoles, defineStatus, defineStatuses, defineSystem, defineSystems, defineTopology, defineTopologyRelationship, findOrganizationActionById, formatOntologyId, getOntologyDiagnostics, getSortedSidebarEntries, isOntologyGraphNodeId, isOntologyTopologyRef, listAllSystems, listResolvedOntologyRecords, ontologyGraphNodeId, ontologyIdFromGraphNodeId, parseContractRef, parseOntologyId, parseTopologyNodeRef, projectOrganizationSurfaces, resolveOrganizationModel, resolveOrganizationModelWithResources, scaffoldOrganizationModel, topologyRef, topologyRelationship, validateOrganizationSurfaceProjection };
@@ -3739,6 +3739,17 @@ declare const OntologyScopeSchema: z.ZodDefault<z.ZodObject<{
3739
3739
  }, z.core.$strip>>;
3740
3740
  type OntologyScope = z.infer<typeof OntologyScopeSchema>;
3741
3741
 
3742
+ declare const SystemApiInterfaceSchema: z.ZodObject<{
3743
+ lifecycle: z.ZodDefault<z.ZodEnum<{
3744
+ active: "active";
3745
+ deprecated: "deprecated";
3746
+ draft: "draft";
3747
+ archived: "archived";
3748
+ disabled: "disabled";
3749
+ }>>;
3750
+ readinessProfile: z.ZodOptional<z.ZodString>;
3751
+ resourceIds: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString>>>;
3752
+ }, z.core.$strict>;
3742
3753
  type JsonPrimitive = string | number | boolean | null;
3743
3754
  type JsonValue = JsonPrimitive | JsonValue[] | {
3744
3755
  [key: string]: JsonValue;
@@ -3767,6 +3778,7 @@ interface SystemEntry {
3767
3778
  }[];
3768
3779
  policies?: string[];
3769
3780
  drivesGoals?: string[];
3781
+ apiInterface?: z.infer<typeof SystemApiInterfaceSchema>;
3770
3782
  /** @deprecated Use lifecycle. Accepted for one publish cycle. */
3771
3783
  status?: 'active' | 'deprecated' | 'archived';
3772
3784
  path?: string;
@@ -20318,6 +20318,26 @@ var SystemUiSchema = z.object({
20318
20318
  icon: IconNameSchema.optional(),
20319
20319
  order: z.number().int().optional()
20320
20320
  });
20321
+ var SystemInterfaceKeySchema = ModelIdSchema;
20322
+ var SystemInterfaceLifecycleSchema = z.enum(["draft", "active", "disabled", "deprecated", "archived"]).meta({ label: "System interface lifecycle", color: "teal" });
20323
+ var SystemInterfaceReadinessProfileSchema = z.string().trim().min(1).max(200).regex(
20324
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*(?:\.[a-z0-9][a-z0-9-]*)?$/,
20325
+ 'Readiness profiles must use dotted lowercase identifiers (e.g. "sales.lead-gen.api")'
20326
+ );
20327
+ var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
20328
+ var SystemApiInterfaceSchema = z.object({
20329
+ lifecycle: SystemInterfaceLifecycleSchema.default("active"),
20330
+ readinessProfile: SystemInterfaceReadinessProfileSchema.optional(),
20331
+ /**
20332
+ * Resource ids that participate in this API interface. This scopes readiness
20333
+ * derivation without duplicating authored required/provided contract refs.
20334
+ */
20335
+ resourceIds: SystemInterfaceResourceScopeSchema.optional()
20336
+ }).strict();
20337
+ var SystemInterfaceRefSchema = z.object({
20338
+ systemPath: SystemPathSchema,
20339
+ interfaceKey: SystemInterfaceKeySchema
20340
+ }).strict();
20321
20341
  var JsonValueSchema = z.lazy(
20322
20342
  () => z.union([
20323
20343
  z.string(),
@@ -20356,6 +20376,8 @@ var SystemEntrySchema = z.object({
20356
20376
  policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
20357
20377
  /** Optional goals this system contributes to. */
20358
20378
  drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
20379
+ /** Thin API runtime-boundary marker. Readiness is derived from scoped resources and topology. */
20380
+ apiInterface: SystemApiInterfaceSchema.optional(),
20359
20381
  /** @deprecated Use lifecycle. Accepted for one publish cycle. */
20360
20382
  status: SystemStatusSchema.optional(),
20361
20383
  /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
@@ -20771,6 +20793,15 @@ var OmTopologyMetadataSchema = z.record(z.string().trim().min(1).max(120), JsonV
20771
20793
  }
20772
20794
  visit(metadata, []);
20773
20795
  });
20796
+ var OmTopologySystemInterfaceGrantSchema = z.object({
20797
+ consumer: SystemInterfaceRefSchema,
20798
+ provider: SystemInterfaceRefSchema,
20799
+ resourceIds: z.array(ResourceIdSchema).default([]),
20800
+ ontologyIds: z.array(OntologyIdSchema).default([])
20801
+ }).strict();
20802
+ z.object({
20803
+ systemInterfaceGrant: OmTopologySystemInterfaceGrantSchema
20804
+ }).strict();
20774
20805
  var OmTopologyRelationshipSchema = z.object({
20775
20806
  from: OmTopologyNodeRefSchema,
20776
20807
  kind: OmTopologyRelationshipKindSchema,
@@ -21398,6 +21429,26 @@ function refineOrganizationModel(model, ctx) {
21398
21429
  );
21399
21430
  }
21400
21431
  });
21432
+ allSystems.forEach(({ path: systemPath, schemaPath, system }) => {
21433
+ system.apiInterface?.resourceIds?.forEach((resourceId, resourceIndex) => {
21434
+ const resource = resourcesById.get(resourceId);
21435
+ if (resource === void 0) {
21436
+ addIssue(
21437
+ ctx,
21438
+ [...schemaPath, "apiInterface", "resourceIds", resourceIndex],
21439
+ `System Interface "${systemPath}/api" scopes unknown resource "${resourceId}"`
21440
+ );
21441
+ return;
21442
+ }
21443
+ if (resource.systemPath !== systemPath) {
21444
+ addIssue(
21445
+ ctx,
21446
+ [...schemaPath, "apiInterface", "resourceIds", resourceIndex],
21447
+ `System Interface "${systemPath}/api" scopes resource "${resourceId}" from system "${resource.systemPath}"`
21448
+ );
21449
+ }
21450
+ });
21451
+ });
21401
21452
  function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
21402
21453
  const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
21403
21454
  ontologyIds2.forEach((ontologyId, ontologyIndex) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/core",
3
- "version": "0.34.1",
3
+ "version": "0.35.0",
4
4
  "license": "MIT",
5
5
  "description": "Minimal shared constants across Elevasis monorepo",
6
6
  "sideEffects": false,
@@ -303,6 +303,36 @@ export type OrganizationModelSystemKind = z.infer<typeof SystemKindSchema>
303
303
  export type OrganizationModelSystemLifecycle = z.infer<typeof SystemLifecycleSchema>
304
304
  ```
305
305
 
306
+ ### `OrganizationModelSystemInterfaceKey`
307
+
308
+ ```typescript
309
+ export type OrganizationModelSystemInterfaceKey = z.infer<typeof SystemInterfaceKeySchema>
310
+ ```
311
+
312
+ ### `OrganizationModelSystemInterfaceLifecycle`
313
+
314
+ ```typescript
315
+ export type OrganizationModelSystemInterfaceLifecycle = z.infer<typeof SystemInterfaceLifecycleSchema>
316
+ ```
317
+
318
+ ### `OrganizationModelSystemInterfaceReadinessProfile`
319
+
320
+ ```typescript
321
+ export type OrganizationModelSystemInterfaceReadinessProfile = z.infer<typeof SystemInterfaceReadinessProfileSchema>
322
+ ```
323
+
324
+ ### `OrganizationModelSystemApiInterface`
325
+
326
+ ```typescript
327
+ export type OrganizationModelSystemApiInterface = z.infer<typeof SystemApiInterfaceSchema>
328
+ ```
329
+
330
+ ### `OrganizationModelSystemInterfaceRef`
331
+
332
+ ```typescript
333
+ export type OrganizationModelSystemInterfaceRef = z.infer<typeof SystemInterfaceRefSchema>
334
+ ```
335
+
306
336
  ### `OrganizationModelSystemStatus`
307
337
 
308
338
  ```typescript
@@ -466,6 +496,20 @@ export type OrganizationModelTopologyRelationship = z.infer<typeof OmTopologyRel
466
496
  export type OrganizationModelTopologyMetadata = z.infer<typeof OmTopologyMetadataSchema>
467
497
  ```
468
498
 
499
+ ### `OrganizationModelTopologySystemInterfaceGrant`
500
+
501
+ ```typescript
502
+ export type OrganizationModelTopologySystemInterfaceGrant = z.infer<typeof OmTopologySystemInterfaceGrantSchema>
503
+ ```
504
+
505
+ ### `OrganizationModelTopologySystemInterfaceGrantMetadata`
506
+
507
+ ```typescript
508
+ export type OrganizationModelTopologySystemInterfaceGrantMetadata = z.infer<
509
+ typeof OmTopologySystemInterfaceGrantMetadataSchema
510
+ >
511
+ ```
512
+
469
513
  ### `OrganizationModelActions`
470
514
 
471
515
  ```typescript
@@ -1328,38 +1372,33 @@ export interface HumanCheckpointDefinition extends ResourceDefinition {
1328
1372
  ### `DeploymentSpec`
1329
1373
 
1330
1374
  ```typescript
1331
- /**
1332
- * Organization-specific resource collection
1333
- *
1334
- * Complete manifest of all automation resources for an organization.
1335
- * Used by ResourceRegistry for discovery and Command View for visualization.
1336
- */
1337
- export interface DeploymentSpec {
1375
+ /**
1376
+ * Organization-specific resource collection
1377
+ *
1378
+ * Complete manifest of all automation resources for an organization.
1379
+ * Used by ResourceRegistry for discovery and Command View for visualization.
1380
+ */
1381
+ export interface DeploymentSpec {
1338
1382
  /** Deployment version (semver) */
1339
1383
  version: string
1340
- /** Optional Organization Model governance catalog used for OM-code validation */
1341
- organizationModel?: Partial<
1342
- Pick<
1343
- OrganizationModel,
1344
- 'systems' | 'resources' | 'ontology' | 'topology' | 'roles' | 'policies' | 'entities' | 'actions'
1345
- >
1346
- >
1347
- /** Workflow definitions */
1348
- workflows?: WorkflowDefinition[]
1349
- /** Agent definitions */
1350
- agents?: AgentDefinition[]
1351
-
1352
- // Resource Manifest fields (optional for backwards compatibility)
1353
- /** Trigger definitions - entry points that initiate executions */
1354
- triggers?: TriggerDefinition[]
1355
- /** Integration definitions - external service connections */
1356
- integrations?: IntegrationDefinition[]
1357
- /** Explicit relationship declarations between resources */
1358
- relationships?: ResourceRelationships
1359
- /** External automation resources (n8n, Make, Zapier, etc.) */
1360
- externalResources?: ExternalResourceDefinition[]
1361
- /** Human checkpoint definitions - human decision points in automation */
1362
- humanCheckpoints?: HumanCheckpointDefinition[]
1384
+ /** Optional full Organization Model snapshot used for OM-code validation and deployment persistence */
1385
+ organizationModel?: OrganizationModel
1386
+ /** Workflow definitions */
1387
+ workflows?: WorkflowDefinition[]
1388
+ /** Agent definitions */
1389
+ agents?: AgentDefinition[]
1390
+
1391
+ // Resource Manifest fields (optional for backwards compatibility)
1392
+ /** Trigger definitions - entry points that initiate executions */
1393
+ triggers?: TriggerDefinition[]
1394
+ /** Integration definitions - external service connections */
1395
+ integrations?: IntegrationDefinition[]
1396
+ /** Explicit relationship declarations between resources */
1397
+ relationships?: ResourceRelationships
1398
+ /** External automation resources (n8n, Make, Zapier, etc.) */
1399
+ externalResources?: ExternalResourceDefinition[]
1400
+ /** Human checkpoint definitions - human decision points in automation */
1401
+ humanCheckpoints?: HumanCheckpointDefinition[]
1363
1402
  }
1364
1403
  ```
1365
1404
 
@@ -1,26 +1,29 @@
1
- // Theme preset SSOT (const tuple + derived union + Zod enum)
2
- export * from './theme-presets'
3
-
4
- // Config types
5
- export * from './types'
6
-
7
- // Permission catalog (canonical PERMISSIONS constant + types)
8
- export * from './permissions'
9
-
10
- // Role management schemas
11
- export * from './role-management/index'
12
-
13
- // Organization types
14
- export * from './organizations/index'
15
-
16
- // User types
17
- export * from './users/index'
18
-
19
- // Membership types
20
- export * from './memberships/index'
21
-
22
- // Invitation types
23
- export * from './invitations/index'
24
-
25
- // Credentials types
26
- export * from './credentials/index'
1
+ // Theme preset SSOT (const tuple + derived union + Zod enum)
2
+ export * from './theme-presets'
3
+
4
+ // Config types
5
+ export * from './types'
6
+
7
+ // Branded organization identifiers (WorkOS id vs Supabase UUID)
8
+ export * from './org-id'
9
+
10
+ // Permission catalog (canonical PERMISSIONS constant + types)
11
+ export * from './permissions'
12
+
13
+ // Role management schemas
14
+ export * from './role-management/index'
15
+
16
+ // Organization types
17
+ export * from './organizations/index'
18
+
19
+ // User types
20
+ export * from './users/index'
21
+
22
+ // Membership types
23
+ export * from './memberships/index'
24
+
25
+ // Invitation types
26
+ export * from './invitations/index'
27
+
28
+ // Credentials types
29
+ export * from './credentials/index'
@@ -0,0 +1,139 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import {
3
+ asSupabaseOrgId,
4
+ asWorkOsOrgId,
5
+ asSupabaseOrgIdOrNull,
6
+ asWorkOsOrgIdOrNull,
7
+ brandSupabaseOrgId,
8
+ brandWorkOsOrgId,
9
+ isSupabaseOrgId,
10
+ isWorkOsOrgId,
11
+ type SupabaseOrgId,
12
+ type WorkOsOrgId
13
+ } from './org-id'
14
+
15
+ // Real fixtures pulled from the dev `organizations` table so the format checks
16
+ // exercise production-shaped values, not invented ones.
17
+ const ELEVASIS_UUID = 'f9aa5a56-8c13-4cd1-9161-8827ae7b452b'
18
+ const ELEVASIS_WORKOS = 'org_01K64D59CA5J3PJCWJFQV87PPN'
19
+ const TESTER_UUID = '1b7a6cb2-d73f-44cb-942b-1fa841085ec0'
20
+ const TESTER_WORKOS = 'org_01K4EW076HK9ND7JWPFZKGCNJF'
21
+ // A WorkOS test-org id -- still prefixed `org_`, must be treated as a WorkOS id.
22
+ const TEST_ORG_WORKOS = 'org_test_1776593934703_6gfvsb_l6nyy6'
23
+ const TEST_ORG_UUID = '2ac228f7-a0a1-49f9-920e-8a348f5253d3'
24
+
25
+ describe('org-id brands: runtime validation', () => {
26
+ it('asSupabaseOrgId accepts real Supabase UUIDs and returns the same value', () => {
27
+ expect(asSupabaseOrgId(ELEVASIS_UUID)).toBe(ELEVASIS_UUID)
28
+ expect(asSupabaseOrgId(TESTER_UUID)).toBe(TESTER_UUID)
29
+ expect(asSupabaseOrgId(TEST_ORG_UUID)).toBe(TEST_ORG_UUID)
30
+ })
31
+
32
+ it('asWorkOsOrgId accepts real WorkOS ids (including org_test_*) and returns the same value', () => {
33
+ expect(asWorkOsOrgId(ELEVASIS_WORKOS)).toBe(ELEVASIS_WORKOS)
34
+ expect(asWorkOsOrgId(TESTER_WORKOS)).toBe(TESTER_WORKOS)
35
+ expect(asWorkOsOrgId(TEST_ORG_WORKOS)).toBe(TEST_ORG_WORKOS)
36
+ })
37
+
38
+ it('asSupabaseOrgId throws loudly when handed a WorkOS id (the silent footgun, surfaced)', () => {
39
+ expect(() => asSupabaseOrgId(ELEVASIS_WORKOS)).toThrow(/Supabase organization UUID/)
40
+ expect(() => asSupabaseOrgId(TEST_ORG_WORKOS)).toThrow(/Supabase organization UUID/)
41
+ })
42
+
43
+ it('asWorkOsOrgId throws loudly when handed a Supabase UUID (the reverse footgun)', () => {
44
+ expect(() => asWorkOsOrgId(ELEVASIS_UUID)).toThrow(/WorkOS organization id/)
45
+ expect(() => asWorkOsOrgId(TESTER_UUID)).toThrow(/WorkOS organization id/)
46
+ })
47
+
48
+ it('rejects empty and obviously malformed values', () => {
49
+ expect(() => asSupabaseOrgId('')).toThrow()
50
+ expect(() => asSupabaseOrgId('not-a-uuid')).toThrow()
51
+ expect(() => asWorkOsOrgId('')).toThrow()
52
+ expect(() => asWorkOsOrgId('01K64D59CA5J3PJCWJFQV87PPN')).toThrow() // missing org_ prefix
53
+ })
54
+ })
55
+
56
+ describe('org-id brands: type guards', () => {
57
+ it('isSupabaseOrgId is true only for UUIDs', () => {
58
+ expect(isSupabaseOrgId(ELEVASIS_UUID)).toBe(true)
59
+ expect(isSupabaseOrgId(ELEVASIS_WORKOS)).toBe(false)
60
+ })
61
+
62
+ it('isWorkOsOrgId is true only for org_ prefixed values', () => {
63
+ expect(isWorkOsOrgId(ELEVASIS_WORKOS)).toBe(true)
64
+ expect(isWorkOsOrgId(TEST_ORG_WORKOS)).toBe(true)
65
+ expect(isWorkOsOrgId(ELEVASIS_UUID)).toBe(false)
66
+ })
67
+ })
68
+
69
+ describe('org-id brands: nullable mint helpers', () => {
70
+ it('pass null/undefined through unchanged', () => {
71
+ expect(asSupabaseOrgIdOrNull(null)).toBeNull()
72
+ expect(asSupabaseOrgIdOrNull(undefined)).toBeNull()
73
+ expect(asWorkOsOrgIdOrNull(null)).toBeNull()
74
+ expect(asWorkOsOrgIdOrNull(undefined)).toBeNull()
75
+ })
76
+
77
+ it('validate non-null values', () => {
78
+ expect(asSupabaseOrgIdOrNull(ELEVASIS_UUID)).toBe(ELEVASIS_UUID)
79
+ expect(asWorkOsOrgIdOrNull(ELEVASIS_WORKOS)).toBe(ELEVASIS_WORKOS)
80
+ expect(() => asSupabaseOrgIdOrNull(ELEVASIS_WORKOS)).toThrow()
81
+ })
82
+ })
83
+
84
+ describe('org-id brands: trusted-source casts', () => {
85
+ it('brand* never throws (trusted values are not re-validated) and preserves the value', () => {
86
+ expect(brandSupabaseOrgId(ELEVASIS_UUID)).toBe(ELEVASIS_UUID)
87
+ expect(brandWorkOsOrgId(ELEVASIS_WORKOS)).toBe(ELEVASIS_WORKOS)
88
+ // Unlike as*, brand* does not validate -- it is the trusted-data path.
89
+ expect(() => brandSupabaseOrgId('anything')).not.toThrow()
90
+ expect(() => brandWorkOsOrgId('anything')).not.toThrow()
91
+ })
92
+
93
+ it('brand* maps null/undefined to null', () => {
94
+ expect(brandSupabaseOrgId(null)).toBeNull()
95
+ expect(brandSupabaseOrgId(undefined)).toBeNull()
96
+ expect(brandWorkOsOrgId(null)).toBeNull()
97
+ expect(brandWorkOsOrgId(undefined)).toBeNull()
98
+ })
99
+ })
100
+
101
+ /**
102
+ * Compile-time enforcement. These sinks model the real consumers: a Supabase
103
+ * `.eq('organization_id', ...)` helper (needs SupabaseOrgId) and a query-key
104
+ * factory (needs WorkOsOrgId). The `@ts-expect-error` directives are the actual
105
+ * assertions -- if a brand ever fails to block a swap, the directive becomes
106
+ * "unused" and `tsc` (check-types) fails. The sinks are runtime no-ops, so this
107
+ * block executes harmlessly under vitest; the guarantee is verified by the type
108
+ * checker.
109
+ */
110
+ describe('org-id brands: compile-time swap prevention', () => {
111
+ function expectsSupabaseOrgId(_id: SupabaseOrgId): void {}
112
+ function expectsWorkOsOrgId(_id: WorkOsOrgId): void {}
113
+
114
+ it('accepts correctly-branded ids and keeps string compatibility', () => {
115
+ // Positive: the right brand flows into the right sink.
116
+ expectsSupabaseOrgId(asSupabaseOrgId(ELEVASIS_UUID))
117
+ expectsWorkOsOrgId(asWorkOsOrgId(ELEVASIS_WORKOS))
118
+
119
+ // A branded id is still a string everywhere a plain string is expected.
120
+ const asString: string = asSupabaseOrgId(ELEVASIS_UUID)
121
+ expect(asString).toBe(ELEVASIS_UUID)
122
+ })
123
+
124
+ it('rejects cross-brand and raw-string assignment at compile time', () => {
125
+ // @ts-expect-error WorkOsOrgId must not be usable where a SupabaseOrgId is required.
126
+ expectsSupabaseOrgId(asWorkOsOrgId(ELEVASIS_WORKOS))
127
+
128
+ // @ts-expect-error SupabaseOrgId must not be usable where a WorkOsOrgId is required.
129
+ expectsWorkOsOrgId(asSupabaseOrgId(ELEVASIS_UUID))
130
+
131
+ // @ts-expect-error a raw string cannot reach the sink without minting through the factory.
132
+ expectsSupabaseOrgId(ELEVASIS_UUID)
133
+
134
+ // @ts-expect-error a raw string cannot reach the sink without minting through the factory.
135
+ expectsWorkOsOrgId(ELEVASIS_WORKOS)
136
+
137
+ expect(true).toBe(true)
138
+ })
139
+ })
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Branded organization identifiers.
3
+ *
4
+ * Every organization carries TWO distinct ID values that are both plain
5
+ * strings at runtime but mean different things:
6
+ *
7
+ * - WorkOS organization id (`org_...`) -- the auth/JWT identity. Used for API
8
+ * requests, SSE headers, and org-scoped query keys.
9
+ * - Supabase organization id (UUID) -- the database key. Used for
10
+ * `.eq('organization_id', ...)` queries and RLS scoping.
11
+ *
12
+ * They are not interchangeable, yet both are `string` -- so a swap compiles
13
+ * cleanly and fails silently (zero rows on the Supabase side, cross-pollinated
14
+ * cache keys on the API side). These brands make the two non-assignable to one
15
+ * another, turning that silent footgun into a compile error at the sink.
16
+ *
17
+ * Mint a brand only through the `as*` factories below: they are the single
18
+ * validate-and-tag boundary (compile-time brand + runtime format check). The
19
+ * type predicates double as the cast, so no raw `as` cast is needed anywhere.
20
+ *
21
+ * Lives on the published `@repo/core` / `@repo/core/auth` surface so the UI,
22
+ * the API, and the dogfooding `@repo/elevasis-*` packages can all use it.
23
+ */
24
+
25
+ import { UuidSchema } from '../../platform/utils/validation'
26
+
27
+ declare const supabaseOrgIdBrand: unique symbol
28
+ declare const workOsOrgIdBrand: unique symbol
29
+
30
+ /** A Supabase organization id (UUID) -- the database key for RLS-scoped rows. */
31
+ export type SupabaseOrgId = string & { readonly [supabaseOrgIdBrand]: true }
32
+
33
+ /** A WorkOS organization id (`org_...`) -- the auth identity for API/SSE/query keys. */
34
+ export type WorkOsOrgId = string & { readonly [workOsOrgIdBrand]: true }
35
+
36
+ /** WorkOS organization ids are always prefixed with `org_` (incl. `org_test_...`). */
37
+ const WORKOS_ORG_ID_PREFIX = 'org_'
38
+
39
+ /** True when `value` is shaped like a Supabase organization UUID. */
40
+ export function isSupabaseOrgId(value: string): value is SupabaseOrgId {
41
+ return UuidSchema.safeParse(value).success
42
+ }
43
+
44
+ /** True when `value` is shaped like a WorkOS organization id (`org_...`). */
45
+ export function isWorkOsOrgId(value: string): value is WorkOsOrgId {
46
+ return value.startsWith(WORKOS_ORG_ID_PREFIX)
47
+ }
48
+
49
+ /**
50
+ * Validate-and-brand a string as a Supabase organization id.
51
+ *
52
+ * @throws {Error} if the value is not a UUID (e.g. a WorkOS `org_...` id leaked in).
53
+ */
54
+ export function asSupabaseOrgId(value: string): SupabaseOrgId {
55
+ if (!isSupabaseOrgId(value)) {
56
+ throw new Error(
57
+ `Expected a Supabase organization UUID, received "${value}". ` +
58
+ `A WorkOS org id (org_...) was likely used where the database key is required.`
59
+ )
60
+ }
61
+ return value
62
+ }
63
+
64
+ /**
65
+ * Validate-and-brand a string as a WorkOS organization id.
66
+ *
67
+ * @throws {Error} if the value is not `org_...` (e.g. a Supabase UUID leaked in).
68
+ */
69
+ export function asWorkOsOrgId(value: string): WorkOsOrgId {
70
+ if (!isWorkOsOrgId(value)) {
71
+ throw new Error(
72
+ `Expected a WorkOS organization id (org_...), received "${value}". ` +
73
+ `A Supabase UUID was likely used where the auth identity is required.`
74
+ )
75
+ }
76
+ return value
77
+ }
78
+
79
+ /** Nullable convenience for mint sites that read `... ?? null` from a membership. */
80
+ export function asSupabaseOrgIdOrNull(value: string | null | undefined): SupabaseOrgId | null {
81
+ return value == null ? null : asSupabaseOrgId(value)
82
+ }
83
+
84
+ /** Nullable convenience for mint sites that read `... ?? null` from a membership. */
85
+ export function asWorkOsOrgIdOrNull(value: string | null | undefined): WorkOsOrgId | null {
86
+ return value == null ? null : asWorkOsOrgId(value)
87
+ }
88
+
89
+ // ---------------------------------------------------------------------------
90
+ // Trusted-source casts (brand WITHOUT validating).
91
+ //
92
+ // Use these when the value is already known to be well-formed -- e.g. an
93
+ // organization id read from our own database/membership API, or a test
94
+ // fixture. They never throw, so they are safe at UI mint points (a provider
95
+ // must not white-screen on data shape) and avoid re-validating trusted DB
96
+ // UUIDs on every render. For UNTRUSTED input (route params, external ids)
97
+ // prefer the validating `as*` factories above, which throw on a bad shape.
98
+ // ---------------------------------------------------------------------------
99
+
100
+ /** Brand a trusted string as a Supabase organization id without validating. */
101
+ export function brandSupabaseOrgId(value: string): SupabaseOrgId
102
+ export function brandSupabaseOrgId(value: string | null | undefined): SupabaseOrgId | null
103
+ export function brandSupabaseOrgId(value: string | null | undefined): SupabaseOrgId | null {
104
+ return (value ?? null) as SupabaseOrgId | null
105
+ }
106
+
107
+ /** Brand a trusted string as a WorkOS organization id without validating. */
108
+ export function brandWorkOsOrgId(value: string): WorkOsOrgId
109
+ export function brandWorkOsOrgId(value: string | null | undefined): WorkOsOrgId | null
110
+ export function brandWorkOsOrgId(value: string | null | undefined): WorkOsOrgId | null {
111
+ return (value ?? null) as WorkOsOrgId | null
112
+ }