@elevasis/core 0.21.0 → 0.23.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 (132) hide show
  1. package/dist/index.d.ts +2518 -2169
  2. package/dist/index.js +2495 -1095
  3. package/dist/knowledge/index.d.ts +706 -1044
  4. package/dist/knowledge/index.js +9 -9
  5. package/dist/organization-model/index.d.ts +2518 -2169
  6. package/dist/organization-model/index.js +2495 -1095
  7. package/dist/test-utils/index.d.ts +826 -1014
  8. package/dist/test-utils/index.js +1894 -1032
  9. package/package.json +3 -3
  10. package/src/__tests__/template-core-compatibility.test.ts +11 -79
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
  12. package/src/auth/multi-tenancy/permissions.ts +20 -8
  13. package/src/business/README.md +2 -2
  14. package/src/business/acquisition/api-schemas.test.ts +175 -2
  15. package/src/business/acquisition/api-schemas.ts +132 -16
  16. package/src/business/acquisition/build-templates.test.ts +4 -4
  17. package/src/business/acquisition/build-templates.ts +72 -30
  18. package/src/business/acquisition/crm-state-actions.test.ts +13 -11
  19. package/src/business/acquisition/index.ts +12 -0
  20. package/src/business/acquisition/types.ts +7 -3
  21. package/src/business/clients/api-schemas.test.ts +115 -0
  22. package/src/business/clients/api-schemas.ts +158 -0
  23. package/src/business/clients/index.ts +1 -0
  24. package/src/business/deals/api-schemas.ts +8 -0
  25. package/src/business/index.ts +5 -2
  26. package/src/business/projects/types.ts +19 -0
  27. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
  28. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
  29. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
  30. package/src/execution/engine/agent/core/types.ts +25 -15
  31. package/src/execution/engine/agent/index.ts +6 -4
  32. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
  33. package/src/execution/engine/index.ts +3 -0
  34. package/src/execution/engine/workflow/types.ts +9 -2
  35. package/src/knowledge/README.md +8 -7
  36. package/src/knowledge/__tests__/queries.test.ts +74 -73
  37. package/src/knowledge/format.ts +10 -9
  38. package/src/knowledge/index.ts +1 -1
  39. package/src/knowledge/published.ts +1 -1
  40. package/src/knowledge/queries.ts +26 -25
  41. package/src/organization-model/README.md +73 -26
  42. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  43. package/src/organization-model/__tests__/defaults.test.ts +76 -96
  44. package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
  45. package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
  46. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  47. package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
  48. package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
  49. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
  50. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
  51. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  52. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
  53. package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
  54. package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
  55. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
  56. package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
  57. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
  58. package/src/organization-model/__tests__/foundation.test.ts +74 -102
  59. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  60. package/src/organization-model/__tests__/graph.test.ts +899 -71
  61. package/src/organization-model/__tests__/knowledge.test.ts +209 -49
  62. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  63. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  64. package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
  65. package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
  66. package/src/organization-model/__tests__/resolve.test.ts +174 -23
  67. package/src/organization-model/__tests__/schema.test.ts +291 -114
  68. package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
  69. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  70. package/src/organization-model/content-kinds/config.ts +36 -0
  71. package/src/organization-model/content-kinds/index.ts +74 -0
  72. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  73. package/src/organization-model/content-kinds/registry.ts +44 -0
  74. package/src/organization-model/content-kinds/status.ts +71 -0
  75. package/src/organization-model/content-kinds/template.ts +83 -0
  76. package/src/organization-model/content-kinds/types.ts +117 -0
  77. package/src/organization-model/contracts.ts +13 -3
  78. package/src/organization-model/defaults.ts +499 -86
  79. package/src/organization-model/domains/actions.ts +239 -0
  80. package/src/organization-model/domains/customers.ts +78 -75
  81. package/src/organization-model/domains/entities.ts +144 -0
  82. package/src/organization-model/domains/goals.ts +83 -80
  83. package/src/organization-model/domains/knowledge.ts +76 -17
  84. package/src/organization-model/domains/navigation.ts +107 -384
  85. package/src/organization-model/domains/offerings.ts +71 -66
  86. package/src/organization-model/domains/policies.ts +102 -0
  87. package/src/organization-model/domains/projects.ts +14 -48
  88. package/src/organization-model/domains/prospecting.ts +62 -181
  89. package/src/organization-model/domains/resources.ts +145 -0
  90. package/src/organization-model/domains/roles.ts +96 -55
  91. package/src/organization-model/domains/sales.ts +10 -219
  92. package/src/organization-model/domains/shared.ts +57 -57
  93. package/src/organization-model/domains/statuses.ts +339 -130
  94. package/src/organization-model/domains/systems.ts +203 -0
  95. package/src/organization-model/foundation.ts +54 -67
  96. package/src/organization-model/graph/build.ts +682 -54
  97. package/src/organization-model/graph/link.ts +1 -1
  98. package/src/organization-model/graph/schema.ts +24 -9
  99. package/src/organization-model/graph/types.ts +20 -7
  100. package/src/organization-model/helpers.ts +231 -26
  101. package/src/organization-model/icons.ts +1 -0
  102. package/src/organization-model/index.ts +118 -5
  103. package/src/organization-model/migration-helpers.ts +249 -0
  104. package/src/organization-model/organization-graph.mdx +16 -15
  105. package/src/organization-model/organization-model.mdx +111 -44
  106. package/src/organization-model/published.ts +172 -19
  107. package/src/organization-model/resolve.ts +117 -54
  108. package/src/organization-model/schema.ts +654 -112
  109. package/src/organization-model/surface-projection.ts +116 -122
  110. package/src/organization-model/types.ts +146 -20
  111. package/src/platform/api/types.ts +38 -35
  112. package/src/platform/constants/versions.ts +1 -1
  113. package/src/platform/registry/__tests__/command-view.test.ts +6 -8
  114. package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
  115. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
  116. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  117. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
  118. package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
  119. package/src/platform/registry/index.ts +14 -0
  120. package/src/platform/registry/resource-registry.ts +52 -2
  121. package/src/platform/registry/serialization.ts +241 -202
  122. package/src/platform/registry/serialized-types.ts +1 -0
  123. package/src/platform/registry/types.ts +411 -361
  124. package/src/platform/registry/validation.ts +745 -513
  125. package/src/projects/api-schemas.ts +290 -267
  126. package/src/reference/_generated/contracts.md +853 -397
  127. package/src/reference/glossary.md +23 -18
  128. package/src/supabase/database.types.ts +181 -0
  129. package/src/test-utils/test-utils.test.ts +1 -6
  130. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  131. package/src/organization-model/domains/features.ts +0 -31
  132. package/src/organization-model/domains/operations.ts +0 -85
@@ -11,41 +11,45 @@ description: Terminology disambiguation for Organization OS concepts used in the
11
11
 
12
12
  **Contract** -- the publishable boundary a consumer depends on: Zod schemas, TypeScript types, provider props, resource definitions, or workflow I/O schemas.
13
13
 
14
- **DeploymentSpec** -- resource collection for one organization: workflows, agents, triggers, integrations, relationships, external resources, and human checkpoints.
14
+ **DeploymentSpec** -- runtime/deploy assembly for one organization: workflows, agents, triggers, integrations, relationships, external resources, and human checkpoints. It assembles executable behavior around Organization Model resource descriptors; it is not the source of resource identity.
15
15
 
16
- **Feature** -- either a platform capability, a shell `FeatureModule`, or an Organization Model feature node. In the current shell contract, Organization Model feature nodes drive sidebar hierarchy and access state.
16
+ **Feature** -- legacy or UI-package wording for a platform capability area. In the current Organization Model, use **System** for semantic ownership and **navigation surface** for shell placement. Keep "feature" only when referring to existing UI package folders, exported manifest names, or legacy compatibility recipes.
17
17
 
18
- **FeatureGuard** -- route-level feature gate from `@elevasis/ui/features/auth`.
18
+ **SystemGuard** -- route-level System gate from `@elevasis/ui/features/auth`.
19
19
 
20
- **FeatureModule** -- manifest contract a shell feature provides to `ElevasisFeaturesProvider`. Key fields are `key`, `featureId`, optional `capabilityIds`, optional `icon`, optional `sidebar`, and optional graph bridge metadata.
20
+ **SystemModule** -- manifest contract a shell module provides to `ElevasisSystemsProvider`. Key fields are `key`, optional `systemId`, optional `routePrefixes`, optional `capabilityIds`, optional `icon`, optional `sidebar`, optional `sidebarWidth`, and optional graph bridge metadata.
21
21
 
22
- **featureId** -- the `FeatureModule` field that must match an `OrganizationModel.features[].id`.
22
+ **systemId** -- the `SystemModule` field that points to an `OrganizationModel.systems` entry. Navigation-only app modules may omit it and use route prefixes/surface metadata instead.
23
23
 
24
24
  **Foundations** -- local adapter layer in external projects that exports `canonicalOrganizationModel`, `organizationModel`, and workflow I/O schemas.
25
25
 
26
- **Graph node ID** -- kind-prefixed cross-collection identifier such as `feature:sales.crm`, `integration:instantly`, or `resource:lead-import`.
26
+ **Graph node ID** -- kind-prefixed cross-collection identifier such as `system:sales.crm`, `integration:instantly`, or `resource:lead-import`.
27
27
 
28
28
  **Manifest** -- a runtime declaration for a feature or resource collection.
29
29
 
30
- **MembershipFeatureConfig** -- per-member feature override config: `{ features?: Record<string, boolean> }`.
30
+ **MembershipFeatureConfig** -- legacy per-member feature override config. Current System visibility is resolved through Organization Model lifecycle/access metadata and provider compatibility layers.
31
31
 
32
- **OrganizationModel** -- top-level semantic contract for an organization. Current primary fields include `features`, `branding`, `navigation`, `sales`, `prospecting`, `projects`, `identity`, `customers`, `offerings`, `roles`, `goals`, `statuses`, and `operations`.
32
+ **OrganizationModel** -- top-level semantic contract for an organization. Current primary fields include `version`, `domainMetadata`, `branding`, `navigation`, `sales`, `prospecting`, `projects`, `identity`, `customers`, `offerings`, `roles`, `goals`, `systems`, `resources`, `actions`, `entities`, `policies`, `statuses`, and `knowledge`.
33
33
 
34
- **OrganizationModelFeature** -- feature node in `OrganizationModel.features`. Fields include `id`, `label`, `description`, `enabled`, `path`, `icon`, `color`, `uiPosition`, `requiresAdmin`, and `devOnly`.
34
+ **OrganizationModelSystemEntry** -- System node in `OrganizationModel.systems`. Fields include `id`, `label`, `description`, `parentSystemId`, `subsystems`, `lifecycle`, `ui`, `requiresAdmin`, `devOnly`, `responsibleRoleId`, `governedByKnowledge`, `drivesGoals`, `actions`, `content`, and `order`.
35
35
 
36
- **Provider / ElevasisFeaturesProvider** -- runtime that registers manifests, resolves feature access against the org model, and exposes shell helpers through `useElevasisFeatures()`.
36
+ **Provider / ElevasisSystemsProvider** -- runtime that registers System modules, resolves System access against the org model, projects sidebar navigation, and exposes shell helpers through `useElevasisSystems()`.
37
37
 
38
- **Resource** -- deployable workflow, agent, trigger, integration, external resource, or human checkpoint in a `DeploymentSpec`. Resources bind to the Organization Model graph through metadata `links` and are grouped for operations with `category`.
38
+ **Resource** -- governance-only descriptor in `OrganizationModel.resources` for a workflow, agent, integration, or script. Runtime code derives `resourceId` and kind from the descriptor, then attaches executable behavior in operations.
39
+
40
+ **Resource descriptor** -- OM entry with canonical `id`, required `systemPath`, governance `status`, and optional role ownership. Workflow descriptors may mirror `actionKey`; agent descriptors carry `agentKind`, `sessionCapable`, and optional `actsAsRoleId`; integration descriptors name a provider.
41
+
42
+ **System** -- tenant-defined bounded context in `OrganizationModel.systems.systems` that groups operational resources and carries governance metadata such as responsible role, governing knowledge, driven goals, kind, and status.
39
43
 
40
44
  **ResourceCategory** -- resource metadata category: `production`, `diagnostic`, `internal`, or `testing`.
41
45
 
42
46
  **ResourceLink** -- graph binding on resource metadata: `{ nodeId, kind }`.
43
47
 
44
- **Settings asymmetry** -- settings is a feature node, but individual access is normally governed by admin checks rather than user-facing feature toggles.
48
+ **Settings asymmetry** -- Settings is a navigation/app surface whose individual pages are normally governed by admin checks rather than user-facing System toggles.
45
49
 
46
- **Shell model** -- provider output used by sidebars and breadcrumbs. Includes `features`, `childrenOf`, `ancestorsOf`, `parentOf`, `topLevel`, `findByPath`, `uiPositionFor`, `requiresAdminFor`, and `devOnlyFor`.
50
+ **Shell model** -- provider output used by sidebars and breadcrumbs. Includes `systems`, `childrenOf`, `ancestorsOf`, `parentOf`, `topLevel`, `findByPath`, `requiresAdminFor`, and `devOnlyFor`.
47
51
 
48
- **Subshell / Sidebar** -- feature-scoped UI region rendered when the current route matches a feature whose manifest supplies a sidebar.
52
+ **Subshell / Sidebar** -- System- or route-prefix-scoped UI region rendered when the current route matches a module whose manifest supplies a sidebar.
49
53
 
50
54
  **Topology** -- runtime resource relationships declared in `DeploymentSpec.relationships`.
51
55
 
@@ -53,16 +57,17 @@ description: Terminology disambiguation for Organization OS concepts used in the
53
57
 
54
58
  **`@elevasis/core`**
55
59
 
56
- - `OrganizationModel`, `OrganizationModelFeature`
60
+ - `OrganizationModel`, `OrganizationModelSystemEntry`
61
+ - `SystemEntry`, `ResourceEntry`
57
62
  - `resolveOrganizationModel`, `defineOrganizationModel`, `DEFAULT_ORGANIZATION_MODEL`
58
63
  - `MembershipFeatureConfig`
59
64
  - `DeploymentSpec`, `ResourceLink`, `ResourceCategory`
60
65
 
61
66
  **`@elevasis/ui`**
62
67
 
63
- - `FeatureModule`
64
- - `FeatureGuard`, `AdminGuard`, `ProtectedRoute`
65
- - `ElevasisFeaturesProvider`, `ElevasisCoreProvider`, `useElevasisFeatures`
68
+ - `SystemModule`
69
+ - `SystemGuard`, `AdminGuard`, `ProtectedRoute`
70
+ - `ElevasisSystemsProvider`, `ElevasisCoreProvider`, `useElevasisSystems`
66
71
 
67
72
  **External project source**
68
73
 
@@ -66,6 +66,7 @@ export type Database = {
66
66
  batch_id: string | null
67
67
  category: string | null
68
68
  category_pain: string | null
69
+ client_id: string | null
69
70
  created_at: string
70
71
  domain: string | null
71
72
  enrichment_data: Json | null
@@ -92,6 +93,7 @@ export type Database = {
92
93
  batch_id?: string | null
93
94
  category?: string | null
94
95
  category_pain?: string | null
96
+ client_id?: string | null
95
97
  created_at?: string
96
98
  domain?: string | null
97
99
  enrichment_data?: Json | null
@@ -118,6 +120,7 @@ export type Database = {
118
120
  batch_id?: string | null
119
121
  category?: string | null
120
122
  category_pain?: string | null
123
+ client_id?: string | null
121
124
  created_at?: string
122
125
  domain?: string | null
123
126
  enrichment_data?: Json | null
@@ -141,6 +144,13 @@ export type Database = {
141
144
  website?: string | null
142
145
  }
143
146
  Relationships: [
147
+ {
148
+ foreignKeyName: "acq_companies_client_id_fkey"
149
+ columns: ["client_id"]
150
+ isOneToOne: false
151
+ referencedRelation: "clients"
152
+ referencedColumns: ["id"]
153
+ },
144
154
  {
145
155
  foreignKeyName: "acq_companies_organization_id_fkey"
146
156
  columns: ["organization_id"]
@@ -155,6 +165,7 @@ export type Database = {
155
165
  batch_id: string | null
156
166
  brochure_first_viewed_at: string | null
157
167
  brochure_view_count: number
168
+ client_id: string | null
158
169
  company_id: string | null
159
170
  created_at: string
160
171
  email: string
@@ -183,6 +194,7 @@ export type Database = {
183
194
  batch_id?: string | null
184
195
  brochure_first_viewed_at?: string | null
185
196
  brochure_view_count?: number
197
+ client_id?: string | null
186
198
  company_id?: string | null
187
199
  created_at?: string
188
200
  email: string
@@ -211,6 +223,7 @@ export type Database = {
211
223
  batch_id?: string | null
212
224
  brochure_first_viewed_at?: string | null
213
225
  brochure_view_count?: number
226
+ client_id?: string | null
214
227
  company_id?: string | null
215
228
  created_at?: string
216
229
  email?: string
@@ -236,6 +249,13 @@ export type Database = {
236
249
  updated_at?: string
237
250
  }
238
251
  Relationships: [
252
+ {
253
+ foreignKeyName: "acq_contacts_client_id_fkey"
254
+ columns: ["client_id"]
255
+ isOneToOne: false
256
+ referencedRelation: "clients"
257
+ referencedColumns: ["id"]
258
+ },
239
259
  {
240
260
  foreignKeyName: "acq_contacts_company_id_fkey"
241
261
  columns: ["company_id"]
@@ -479,8 +499,10 @@ export type Database = {
479
499
  acq_deals: {
480
500
  Row: {
481
501
  activity_log: Json
502
+ client_id: string | null
482
503
  closed_lost_at: string | null
483
504
  closed_lost_reason: string | null
505
+ company_id: string | null
484
506
  contact_email: string
485
507
  contact_id: string | null
486
508
  created_at: string
@@ -516,8 +538,10 @@ export type Database = {
516
538
  }
517
539
  Insert: {
518
540
  activity_log?: Json
541
+ client_id?: string | null
519
542
  closed_lost_at?: string | null
520
543
  closed_lost_reason?: string | null
544
+ company_id?: string | null
521
545
  contact_email: string
522
546
  contact_id?: string | null
523
547
  created_at?: string
@@ -553,8 +577,10 @@ export type Database = {
553
577
  }
554
578
  Update: {
555
579
  activity_log?: Json
580
+ client_id?: string | null
556
581
  closed_lost_at?: string | null
557
582
  closed_lost_reason?: string | null
583
+ company_id?: string | null
558
584
  contact_email?: string
559
585
  contact_id?: string | null
560
586
  created_at?: string
@@ -589,6 +615,20 @@ export type Database = {
589
615
  updated_at?: string
590
616
  }
591
617
  Relationships: [
618
+ {
619
+ foreignKeyName: "acq_deals_client_id_fkey"
620
+ columns: ["client_id"]
621
+ isOneToOne: false
622
+ referencedRelation: "clients"
623
+ referencedColumns: ["id"]
624
+ },
625
+ {
626
+ foreignKeyName: "acq_deals_company_id_fkey"
627
+ columns: ["company_id"]
628
+ isOneToOne: false
629
+ referencedRelation: "acq_companies"
630
+ referencedColumns: ["id"]
631
+ },
592
632
  {
593
633
  foreignKeyName: "acq_deals_contact_id_fkey"
594
634
  columns: ["contact_id"]
@@ -1206,6 +1246,77 @@ export type Database = {
1206
1246
  },
1207
1247
  ]
1208
1248
  }
1249
+ clients: {
1250
+ Row: {
1251
+ converted_at: string | null
1252
+ created_at: string
1253
+ id: string
1254
+ metadata: Json
1255
+ name: string
1256
+ organization_id: string
1257
+ primary_company_id: string | null
1258
+ primary_contact_id: string | null
1259
+ source_deal_id: string | null
1260
+ status: string
1261
+ updated_at: string
1262
+ }
1263
+ Insert: {
1264
+ converted_at?: string | null
1265
+ created_at?: string
1266
+ id?: string
1267
+ metadata?: Json
1268
+ name: string
1269
+ organization_id: string
1270
+ primary_company_id?: string | null
1271
+ primary_contact_id?: string | null
1272
+ source_deal_id?: string | null
1273
+ status?: string
1274
+ updated_at?: string
1275
+ }
1276
+ Update: {
1277
+ converted_at?: string | null
1278
+ created_at?: string
1279
+ id?: string
1280
+ metadata?: Json
1281
+ name?: string
1282
+ organization_id?: string
1283
+ primary_company_id?: string | null
1284
+ primary_contact_id?: string | null
1285
+ source_deal_id?: string | null
1286
+ status?: string
1287
+ updated_at?: string
1288
+ }
1289
+ Relationships: [
1290
+ {
1291
+ foreignKeyName: "clients_organization_id_fkey"
1292
+ columns: ["organization_id"]
1293
+ isOneToOne: false
1294
+ referencedRelation: "organizations"
1295
+ referencedColumns: ["id"]
1296
+ },
1297
+ {
1298
+ foreignKeyName: "clients_primary_company_id_fkey"
1299
+ columns: ["primary_company_id"]
1300
+ isOneToOne: false
1301
+ referencedRelation: "acq_companies"
1302
+ referencedColumns: ["id"]
1303
+ },
1304
+ {
1305
+ foreignKeyName: "clients_primary_contact_id_fkey"
1306
+ columns: ["primary_contact_id"]
1307
+ isOneToOne: false
1308
+ referencedRelation: "acq_contacts"
1309
+ referencedColumns: ["id"]
1310
+ },
1311
+ {
1312
+ foreignKeyName: "clients_source_deal_id_fkey"
1313
+ columns: ["source_deal_id"]
1314
+ isOneToOne: false
1315
+ referencedRelation: "acq_deals"
1316
+ referencedColumns: ["id"]
1317
+ },
1318
+ ]
1319
+ }
1209
1320
  command_queue: {
1210
1321
  Row: {
1211
1322
  action_payload: Json | null
@@ -2175,6 +2286,7 @@ export type Database = {
2175
2286
  Row: {
2176
2287
  actual_end_date: string | null
2177
2288
  client_company_id: string | null
2289
+ client_id: string | null
2178
2290
  contract_value: number | null
2179
2291
  created_at: string
2180
2292
  deal_id: string | null
@@ -2192,6 +2304,7 @@ export type Database = {
2192
2304
  Insert: {
2193
2305
  actual_end_date?: string | null
2194
2306
  client_company_id?: string | null
2307
+ client_id?: string | null
2195
2308
  contract_value?: number | null
2196
2309
  created_at?: string
2197
2310
  deal_id?: string | null
@@ -2209,6 +2322,7 @@ export type Database = {
2209
2322
  Update: {
2210
2323
  actual_end_date?: string | null
2211
2324
  client_company_id?: string | null
2325
+ client_id?: string | null
2212
2326
  contract_value?: number | null
2213
2327
  created_at?: string
2214
2328
  deal_id?: string | null
@@ -2245,6 +2359,13 @@ export type Database = {
2245
2359
  referencedRelation: "acq_companies"
2246
2360
  referencedColumns: ["id"]
2247
2361
  },
2362
+ {
2363
+ foreignKeyName: "prj_projects_client_id_fkey"
2364
+ columns: ["client_id"]
2365
+ isOneToOne: false
2366
+ referencedRelation: "clients"
2367
+ referencedColumns: ["id"]
2368
+ },
2248
2369
  {
2249
2370
  foreignKeyName: "prj_projects_deal_id_fkey"
2250
2371
  columns: ["deal_id"]
@@ -2649,6 +2770,66 @@ export type Database = {
2649
2770
  },
2650
2771
  ]
2651
2772
  }
2773
+ user_notes: {
2774
+ Row: {
2775
+ content: string
2776
+ created_at: string
2777
+ created_by: string
2778
+ id: string
2779
+ metadata: Json
2780
+ organization_id: string | null
2781
+ pinned: boolean
2782
+ priority: string
2783
+ source: string | null
2784
+ title: string | null
2785
+ updated_at: string
2786
+ user_id: string
2787
+ }
2788
+ Insert: {
2789
+ content: string
2790
+ created_at?: string
2791
+ created_by?: string
2792
+ id?: string
2793
+ metadata?: Json
2794
+ organization_id?: string | null
2795
+ pinned?: boolean
2796
+ priority?: string
2797
+ source?: string | null
2798
+ title?: string | null
2799
+ updated_at?: string
2800
+ user_id: string
2801
+ }
2802
+ Update: {
2803
+ content?: string
2804
+ created_at?: string
2805
+ created_by?: string
2806
+ id?: string
2807
+ metadata?: Json
2808
+ organization_id?: string | null
2809
+ pinned?: boolean
2810
+ priority?: string
2811
+ source?: string | null
2812
+ title?: string | null
2813
+ updated_at?: string
2814
+ user_id?: string
2815
+ }
2816
+ Relationships: [
2817
+ {
2818
+ foreignKeyName: "user_notes_organization_id_fkey"
2819
+ columns: ["organization_id"]
2820
+ isOneToOne: false
2821
+ referencedRelation: "organizations"
2822
+ referencedColumns: ["id"]
2823
+ },
2824
+ {
2825
+ foreignKeyName: "user_notes_user_id_fkey"
2826
+ columns: ["user_id"]
2827
+ isOneToOne: false
2828
+ referencedRelation: "users"
2829
+ referencedColumns: ["id"]
2830
+ },
2831
+ ]
2832
+ }
2652
2833
  users: {
2653
2834
  Row: {
2654
2835
  config: Json
@@ -1,6 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest'
2
2
  import { BaseProjectSchema, BaseTaskSchema } from '../business/base-entities'
3
- import { DEFAULT_ORGANIZATION_MODEL } from '../organization-model'
4
3
  import {
5
4
  makeInitializationState,
6
5
  makeOrganizationModel,
@@ -28,16 +27,12 @@ describe('published test-utils factories', () => {
28
27
 
29
28
  it('creates organization model and initialization fixtures', () => {
30
29
  const model = makeOrganizationModel({
31
- branding: { organizationName: 'Test Brand' },
32
- features: DEFAULT_ORGANIZATION_MODEL.features.map((feature) =>
33
- feature.id === 'seo' ? { ...feature, enabled: true } : feature
34
- )
30
+ branding: { organizationName: 'Test Brand' }
35
31
  })
36
32
  const profile = makeUserProfile({ id: TEST_USERS.admin.id, email: TEST_USERS.admin.email })
37
33
  const state = makeInitializationState({ profile, organizationReady: false, allReady: false })
38
34
 
39
35
  expect(model.branding.organizationName).toBe('Test Brand')
40
- expect(model.features.find((feature) => feature.id === 'seo')?.enabled).toBe(true)
41
36
  expect(state.profile?.email).toBe(TEST_USERS.admin.email)
42
37
  expect(state.organizationReady).toBe(false)
43
38
  })
@@ -1,203 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import {
3
- DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
4
- OperationEntrySchema,
5
- OperationsDomainSchema,
6
- OperationSemanticClassSchema
7
- } from '../../domains/operations'
8
-
9
- // ---------------------------------------------------------------------------
10
- // Group 1: OperationEntrySchema — positive parse
11
- // ---------------------------------------------------------------------------
12
-
13
- describe('OperationEntrySchema — positive parse', () => {
14
- it('accepts a fully-specified entry (id, label, semanticClass, featureId, supportedStatusSemanticClass)', () => {
15
- const result = OperationEntrySchema.safeParse({
16
- id: 'operations.queue',
17
- label: 'HITL Queue',
18
- semanticClass: 'queue',
19
- featureId: 'operations',
20
- supportedStatusSemanticClass: ['queue']
21
- })
22
- expect(result.success).toBe(true)
23
- })
24
-
25
- it('accepts a minimal entry without optional fields', () => {
26
- const result = OperationEntrySchema.safeParse({
27
- id: 'operations.sessions',
28
- label: 'Sessions',
29
- semanticClass: 'sessions'
30
- })
31
- expect(result.success).toBe(true)
32
- if (result.success) {
33
- expect(result.data.featureId).toBeUndefined()
34
- expect(result.data.supportedStatusSemanticClass).toBeUndefined()
35
- }
36
- })
37
-
38
- it('trims whitespace from id and label', () => {
39
- const result = OperationEntrySchema.safeParse({
40
- id: ' trimmed-id ',
41
- label: ' Trimmed Label ',
42
- semanticClass: 'executions'
43
- })
44
- expect(result.success).toBe(true)
45
- if (result.success) {
46
- expect(result.data.id).toBe('trimmed-id')
47
- expect(result.data.label).toBe('Trimmed Label')
48
- }
49
- })
50
- })
51
-
52
- // ---------------------------------------------------------------------------
53
- // Group 2: OperationEntrySchema — negative parse
54
- // ---------------------------------------------------------------------------
55
-
56
- describe('OperationEntrySchema — negative parse', () => {
57
- it('rejects a missing id field', () => {
58
- const result = OperationEntrySchema.safeParse({
59
- label: 'No ID',
60
- semanticClass: 'queue'
61
- })
62
- expect(result.success).toBe(false)
63
- })
64
-
65
- it('rejects a missing label field', () => {
66
- const result = OperationEntrySchema.safeParse({
67
- id: 'operations.queue',
68
- semanticClass: 'queue'
69
- })
70
- expect(result.success).toBe(false)
71
- })
72
-
73
- it('rejects a missing semanticClass field', () => {
74
- const result = OperationEntrySchema.safeParse({
75
- id: 'operations.queue',
76
- label: 'HITL Queue'
77
- })
78
- expect(result.success).toBe(false)
79
- })
80
-
81
- it('rejects an unknown semanticClass value', () => {
82
- const result = OperationEntrySchema.safeParse({
83
- id: 'some.entry',
84
- label: 'Some Entry',
85
- semanticClass: 'not-a-real-class'
86
- })
87
- expect(result.success).toBe(false)
88
- })
89
-
90
- it('rejects a non-string id (number)', () => {
91
- const result = OperationEntrySchema.safeParse({
92
- id: 42,
93
- label: 'Label',
94
- semanticClass: 'queue'
95
- })
96
- expect(result.success).toBe(false)
97
- })
98
-
99
- it('rejects an empty string label (min length 1 after trim)', () => {
100
- const result = OperationEntrySchema.safeParse({
101
- id: 'some.entry',
102
- label: ' ',
103
- semanticClass: 'queue'
104
- })
105
- expect(result.success).toBe(false)
106
- })
107
- })
108
-
109
- // ---------------------------------------------------------------------------
110
- // Group 3: OperationsDomainSchema — structural tests
111
- // ---------------------------------------------------------------------------
112
-
113
- describe('OperationsDomainSchema — structural tests', () => {
114
- it('accepts an entries-empty domain object', () => {
115
- const result = OperationsDomainSchema.safeParse({ entries: [] })
116
- expect(result.success).toBe(true)
117
- })
118
-
119
- it('applies an empty-array default when entries is omitted', () => {
120
- const result = OperationsDomainSchema.safeParse({})
121
- expect(result.success).toBe(true)
122
- if (result.success) {
123
- expect(result.data.entries).toEqual([])
124
- }
125
- })
126
- })
127
-
128
- // ---------------------------------------------------------------------------
129
- // Group 4: Semantic class enum — all 5 values declared
130
- // ---------------------------------------------------------------------------
131
-
132
- describe('OperationSemanticClassSchema — enum coverage', () => {
133
- const expectedClasses = ['queue', 'executions', 'sessions', 'notifications', 'schedules'] as const
134
-
135
- it('enum exposes exactly 5 semantic classes', () => {
136
- expect(OperationSemanticClassSchema.options).toHaveLength(5)
137
- })
138
-
139
- it.each(expectedClasses)('"%s" is a valid semanticClass value', (cls) => {
140
- const result = OperationSemanticClassSchema.safeParse(cls)
141
- expect(result.success).toBe(true)
142
- })
143
-
144
- it('every entry in the seed uses one of the 5 known semanticClass values', () => {
145
- const valid = new Set<string>(OperationSemanticClassSchema.options)
146
- for (const entry of DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries) {
147
- expect(
148
- valid.has(entry.semanticClass),
149
- `Unexpected semanticClass "${entry.semanticClass}" on entry "${entry.id}"`
150
- ).toBe(true)
151
- }
152
- })
153
-
154
- it('all 5 semanticClass values have exactly one seed entry', () => {
155
- const presentClasses = new Set(DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries.map((e) => e.semanticClass))
156
- for (const cls of OperationSemanticClassSchema.options) {
157
- expect(presentClasses.has(cls), `No seed entry found for semanticClass "${cls}"`).toBe(true)
158
- }
159
- })
160
- })
161
-
162
- // ---------------------------------------------------------------------------
163
- // Group 5: Seed completeness
164
- // ---------------------------------------------------------------------------
165
-
166
- describe('DEFAULT_ORGANIZATION_MODEL_OPERATIONS seed — completeness', () => {
167
- it('has exactly 5 entries (one per entity category)', () => {
168
- expect(DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries).toHaveLength(5)
169
- })
170
-
171
- it('all entry ids are unique', () => {
172
- const ids = DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries.map((e) => e.id)
173
- const uniqueIds = new Set(ids)
174
- expect(uniqueIds.size).toBe(ids.length)
175
- })
176
-
177
- it('every entry has a non-empty id, label, and semanticClass', () => {
178
- for (const entry of DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries) {
179
- expect(entry.id.length).toBeGreaterThan(0)
180
- expect(entry.label.length).toBeGreaterThan(0)
181
- expect(entry.semanticClass.length).toBeGreaterThan(0)
182
- }
183
- })
184
-
185
- it('queue entry references queue status semantic class', () => {
186
- const queueEntry = DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries.find((e) => e.semanticClass === 'queue')
187
- expect(queueEntry).toBeDefined()
188
- expect(queueEntry?.supportedStatusSemanticClass).toContain('queue')
189
- })
190
-
191
- it('executions entry references execution status semantic class', () => {
192
- const execEntry = DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries.find((e) => e.semanticClass === 'executions')
193
- expect(execEntry).toBeDefined()
194
- expect(execEntry?.supportedStatusSemanticClass).toContain('execution')
195
- })
196
-
197
- it('schedules entry references schedule and schedule.run status semantic classes', () => {
198
- const schedEntry = DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries.find((e) => e.semanticClass === 'schedules')
199
- expect(schedEntry).toBeDefined()
200
- expect(schedEntry?.supportedStatusSemanticClass).toContain('schedule')
201
- expect(schedEntry?.supportedStatusSemanticClass).toContain('schedule.run')
202
- })
203
- })
@@ -1,31 +0,0 @@
1
- import { z } from 'zod'
2
- import { ColorTokenSchema, DescriptionSchema, IconNameSchema, LabelSchema, PathSchema } from './shared'
3
-
4
- export const NodeIdPathSchema = z
5
- .string()
6
- .trim()
7
- .min(1)
8
- .max(100)
9
- .regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, 'Node IDs must be lowercase dotted paths')
10
-
11
- export const NodeIdStringSchema = z
12
- .string()
13
- .trim()
14
- .min(1)
15
- .max(200)
16
- .regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, 'Node references must use kind:dotted-path')
17
-
18
- export const UiPositionSchema = z.enum(['sidebar-primary', 'sidebar-bottom'])
19
-
20
- export const FeatureSchema = z.object({
21
- id: NodeIdPathSchema,
22
- label: LabelSchema,
23
- description: DescriptionSchema.optional(),
24
- enabled: z.boolean().default(true),
25
- path: PathSchema.optional(),
26
- icon: IconNameSchema.optional(),
27
- color: ColorTokenSchema.optional(),
28
- uiPosition: UiPositionSchema.optional(),
29
- requiresAdmin: z.boolean().optional(),
30
- devOnly: z.boolean().optional()
31
- })