@elevasis/sdk 1.10.0 → 1.12.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 (40) hide show
  1. package/dist/cli.cjs +52 -149
  2. package/dist/index.d.ts +468 -198
  3. package/dist/index.js +225 -147
  4. package/dist/test-utils/index.d.ts +272 -99
  5. package/dist/test-utils/index.js +4756 -125
  6. package/dist/types/worker/adapters/llm.d.ts +1 -1
  7. package/dist/worker/index.js +14 -6
  8. package/package.json +2 -2
  9. package/reference/claude-config/rules/agent-start-here.md +14 -14
  10. package/reference/claude-config/skills/configure/SKILL.md +3 -3
  11. package/reference/claude-config/skills/setup/SKILL.md +6 -6
  12. package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +55 -0
  13. package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +101 -0
  14. package/reference/cli.mdx +57 -0
  15. package/reference/deployment/provided-features.mdx +40 -267
  16. package/reference/examples/organization-model.ts +99 -564
  17. package/reference/packages/core/src/organization-model/README.md +102 -97
  18. package/reference/resources/types.mdx +72 -163
  19. package/reference/scaffold/core/organization-graph.mdx +92 -272
  20. package/reference/scaffold/core/organization-model.mdx +155 -320
  21. package/reference/scaffold/index.mdx +3 -0
  22. package/reference/scaffold/operations/propagation-pipeline.md +4 -1
  23. package/reference/scaffold/operations/scaffold-maintenance.md +3 -0
  24. package/reference/scaffold/operations/workflow-recipes.md +13 -10
  25. package/reference/scaffold/recipes/add-a-feature.md +105 -158
  26. package/reference/scaffold/recipes/add-a-resource.md +88 -158
  27. package/reference/scaffold/recipes/customize-organization-model.md +144 -400
  28. package/reference/scaffold/recipes/extend-a-base-entity.md +11 -8
  29. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +117 -158
  30. package/reference/scaffold/recipes/index.md +3 -0
  31. package/reference/scaffold/reference/contracts.md +107 -435
  32. package/reference/scaffold/reference/feature-registry.md +11 -8
  33. package/reference/scaffold/reference/glossary.md +74 -105
  34. package/reference/scaffold/ui/composition-extensibility.mdx +3 -0
  35. package/reference/scaffold/ui/customization.md +3 -0
  36. package/reference/scaffold/ui/feature-flags-and-gating.md +29 -231
  37. package/reference/scaffold/ui/feature-shell.mdx +53 -219
  38. package/reference/scaffold/ui/recipes.md +65 -397
  39. package/reference/claude-config/logs/pre-edit-vibe-gate.log +0 -40
  40. package/reference/claude-config/logs/scaffold-registry-reminder.log +0 -38
@@ -1,241 +1,75 @@
1
1
  ---
2
2
  title: Feature Shell & Provider Runtime
3
- description: Organization OS UI Shell Runtime and Features layer architecture covering FeatureModule manifests, ElevasisFeaturesProvider, route-to-sidebar dispatch, and organization-model-aware runtime resolution.
3
+ description: Current feature shell contract for flat Organization Model features, manifests, route matching, sidebars, and breadcrumbs.
4
4
  ---
5
+ <!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
6
+ <!-- Regenerate: pnpm scaffold:sync -->
5
7
 
6
- ## Overview
7
-
8
- Within Organization OS, the feature shell spans two layers: the **UI Shell Runtime** that resolves shared nav/sidebar behavior, and the **Features** layer that declares what each feature contributes. It lets command-center and external template consumers compose the same nav, sidebars, and subshell routes from a small set of manifests. It is intentionally a thin layer: manifests describe what a feature contributes, the provider resolves that into a runtime shell model, and consumers still own their own routes, branding, and app-local nav.
9
-
10
- Three layers participate, and the word "feature" means something different in each:
11
-
12
- - **Platform capabilities** -- product-facing areas documented under `technical/features/` (Execution Engine, Workflows, Agents, Operations, etc.). These are not one-to-one with shell features.
13
- - **Shell features** -- features in `packages/ui/src/features/*`. Seven are manifest-backed (`crm`, `lead-gen`, `projects`, `operations`, `monitoring`, `settings`, `seo`); two are utility features without manifests (`auth`, `dashboard`).
14
- - **Organization-model features** -- feature objects in `@repo/core/organization-model` with shape `{ id, label, enabled, entityIds, surfaceIds, resourceIds, capabilityIds }`. The 7 defaults are `crm`, `lead-gen`, `projects`, `operations`, `monitoring`, `settings`, `seo`. See [Organization Model](../core/organization-model.mdx).
15
-
16
- One shell feature can contain several platform capabilities; a manifest's `featureId` directly matches `feature.id` in the org model with no alias layer.
17
-
18
- ## Source of Truth
19
-
20
- - `packages/ui/src/features/registry/types.ts` -- `FeatureModule` contract
21
- - `packages/ui/src/features/registry/manifests.ts` -- published `FEATURE_MANIFESTS` convenience map
22
- - `packages/ui/src/provider/ElevasisFeaturesProvider.tsx` -- runtime composition
23
- - `packages/ui/src/provider/FeatureShell.tsx` -- route-to-sidebar dispatch
24
- - `packages/ui/src/provider/resolvers/{RouteResolver,NavResolver}.ts` -- pure path/nav helpers
25
- - `packages/ui/src/provider/validateManifests.ts` -- startup-time manifest validation
26
- - `packages/ui/src/provider/published.ts` -- headless published barrel
27
- - `apps/command-center/src/routes/__root.tsx` -- reference composition
28
-
29
- ## The FeatureModule Contract
30
-
31
- A `FeatureModule` describes one shell feature's contribution. Fields:
32
-
33
- - `key` -- unique stable identifier (e.g., `'crm'`, `'projects'`)
34
- - `featureId` -- **required**; the `feature.id` value from the org model that this module maps to; used by `useFeatureAccess()` for gating
35
- - `capabilityIds` -- semantic references into the organization model
36
- - `navEntry` -- top-level nav contribution (label, icon, optional `link`, optional nested `links`, optional `requiresAdmin`, optional onboarding-tour ID, optional `featureKey` override when nav identity must diverge from access identity)
37
- - `sidebar` -- optional `ComponentType` for the feature's subshell sidebar
38
- - `subshellRoutes` -- routes the feature owns under its subshell
39
- - `organizationGraph` -- **Operations-only**; bridges a manifest to an organization-model surface (ignored by other features)
40
-
41
- `FeatureModule.label` has been removed; nav labels resolve from `navEntry.label` or from the matching organization-model feature's `label` field.
42
-
43
- Manifests are validated at provider registration via `validateManifests()`. Unknown `featureId` or `capabilityIds` (measured against the resolved organization model) throw with all violations collected into one error.
44
-
45
- ### ResolvedFeatureModule
46
-
47
- `ResolvedFeatureModule` extends `FeatureModule` with two additional fields added during provider resolution:
48
-
49
- - `access: ResolvedFeatureAccess` -- `{ featureId: string, enabled: boolean }` -- the resolved access state for this feature
50
- - `semantics: ResolvedFeatureSemantics` -- `{ capabilityIds, surfaceIds, surfaces }` -- merged semantic identifiers derived from both manifest declarations and organization-model surface data
51
-
52
- `ResolvedFeatureSemantics.surfaces` carries the full `OrganizationModelSurface[]` objects (not just IDs), so consumers can inspect surface metadata without a separate lookup.
53
-
54
- ## Provider Architecture
55
-
56
- The provider layer is composed of several focused context providers. `ElevasisCoreProvider` and `ElevasisFeaturesProvider` are the two consumer-facing entry points; the others are internal building blocks also published for advanced use.
57
-
58
- ### ElevasisCoreProvider
59
-
60
- `ElevasisCoreProvider` is the headless root provider for Elevasis-powered applications. It is pure auth + API with no style side-effects -- no CSS variables, no `data-elevasis-scheme`, no font loading. When `apiUrl` is provided it composes the full provider stack:
61
-
62
- `QueryClientProvider` -> `AuthProvider` -> `ApiClientProvider` -> `ProfileProvider` -> `OrganizationProvider` -> `ElevasisServiceProvider` -> `NotificationProvider` -> `InitializationProvider`
63
-
64
- Consumers that need Mantine theming use `ElevasisUIProvider` (internal) or `ElevasisProvider` instead. `ElevasisCoreProvider` is exported from `packages/ui/src/provider/published.ts` for headless SDK consumers.
65
-
66
- ### ElevasisServiceProvider
67
-
68
- `ElevasisServiceProvider` (from `ElevasisServiceContext.tsx`) is the standalone service context. It accepts three props directly: `apiRequest`, `organizationId`, and `isReady`. `ElevasisCoreProvider` composes this internally after org resolution; advanced consumers can mount it standalone for testing or embedding.
69
-
70
- `useElevasisServices()` reads this context and throws if used outside a provider. Consumed throughout the shared component library wherever API requests are needed.
71
-
72
- ### AppearanceProvider
73
-
74
- `AppearanceProvider` (from `AppearanceContext.tsx`) supplies an `AppearanceConfig` to the tree: `{ background?: ReactNode, loader?: ReactNode }`. The `background` field controls layers rendered behind app content; `loader` controls loading-state elements. Defaults are set in the provider rather than at context creation to avoid importing heavy visual components at module scope.
75
-
76
- `useAppearance()` reads this context and throws if used outside a provider.
77
-
78
- ### NotificationProvider
79
-
80
- `NotificationProvider` (from `NotificationContext.tsx`) accepts a pluggable `NotificationAdapter` for routing notifications to any library. The adapter interface is `{ success, error, info, warning, apiError }`. `ElevasisUIProvider` wires the Mantine adapter automatically.
81
-
82
- When no provider is present in the tree, `useNotificationAdapter()` falls back to a console-based adapter (not a no-op), so template consumers work without Mantine. The hook never throws.
83
-
84
- ### Memoization Strategy
85
-
86
- All computed values inside `ElevasisFeaturesProvider` are wrapped in `useMemo()` with precise dependency tracking. Resolved features, nav items, shell model, organization graph, and the context value object are each memoized separately so downstream consumers only re-render when their specific inputs change.
87
-
88
- ## Provider Responsibilities
89
8
 
90
- `ElevasisFeaturesProvider` owns:
91
-
92
- - registration of shared feature manifests
93
- - feature-flag-aware nav contribution
94
- - route-to-sidebar subshell dispatch (via `shellRuntime.resolveRoute`)
95
- - provider-scoped shared runtime context
96
- - resolved shell-model composition and shell-native route matching
97
- - organization-model-aware nav label and path resolution
98
- - resolved feature output (no legacy `shellModule` wrapper)
99
-
100
- It does **not** own:
101
-
102
- - TanStack file-based route registration
103
- - app branding, topbar behavior, admin entries, assistant/context glue
104
-
105
- Consumers keep thin local route wrappers and app-local nav where needed.
106
-
107
- ## Runtime Flow
108
-
109
- 1. The app defines a manifest list (often by spreading `FEATURE_MANIFESTS` and overriding entries).
110
- 2. The app optionally resolves an organization model and passes it to the provider.
111
- 3. The provider combines `useFeatureAccess()` with the org model's `features[]` array to compute enabled features.
112
- 4. Nav labels and nav paths resolve from the matching `feature.label` in `organizationModel.features` and from `organizationModel.navigation.surfaces` when present.
113
- 5. The provider exposes `shellModel`, `shellRuntime`, resolved feature access, `organizationGraph`, and shared runtime inputs via `useElevasisFeatures()`.
114
- 6. `FeatureShell` calls `shellRuntime.resolveRoute(currentPath)`:
115
- - `matched` -- render the feature's sidebar subshell
116
- - `hidden` -- render `FeatureUnavailableState`
117
- - `unmatched` -- render plain children (consumer owns the route)
118
-
119
- A route resolves as `hidden` when the matched nav link meets either of these conditions: its `featureKey` fails the `isFeatureEnabled()` check, or its path matches an entry in `disabledSubsectionPaths`. Both checks are applied recursively through nested nav links.
120
-
121
- Consumer nav derivation runs locally from `shellModel.navItems`; the provider no longer exposes `visibleNavItems`.
122
-
123
- ## Provider-Scoped Runtime Context
124
-
125
- `useElevasisFeatures()` exposes:
126
-
127
- - `shellModel` -- `{ navItems: ResolvedShellNavItem[] }` -- the full resolved nav list
128
- - `shellRuntime` -- `{ resolveRoute: (path) => ResolvedShellRouteMatch }` -- route dispatch
129
- - `resolvedFeatures` -- all `ResolvedFeatureModule[]` regardless of enabled state
130
- - `enabledResolvedFeatures` -- filtered to `access.enabled === true`
131
- - `timeRange`
132
- - `operationsApiUrl`, `operationsSSEManager`
133
- - `deliveryApiUrl`, `deliverySSEManager`
134
- - `organizationModel`
135
- - `organizationGraph` (resolved from `operations.organization-graph` surface; see [Organization Graph](../core/organization-graph.mdx))
136
- - `disabledSubsectionPaths` -- used by consumers like `_template` to hide specific subsections (e.g., `/settings/appearance`)
137
- - `isFeatureEnabled(key: string): boolean` -- checks both membership flag and organization-model feature state
138
- - `getResolvedFeature(key: string): ResolvedFeatureModule | undefined` -- looks up a resolved feature by its `key` field (module key, not access key)
139
-
140
- ## Nav Resolution
141
-
142
- ### ResolvedShellNavItem
143
-
144
- `ResolvedShellNavItem` extends `FeatureNavEntry` with two additional fields:
145
-
146
- - `placement: 'primary' | 'bottom'` -- where the item appears in the shell nav; feature manifests always produce `'primary'`; `appShellOverrides.bottomNavItems` produce `'bottom'`
147
- - `source: 'app' | 'feature'` -- whether the item came from a manifest (`'feature'`) or from `appShellOverrides` (`'app'`)
148
- - `featureId?: string` -- the feature ID associated with this nav item for gating checks
149
-
150
- `shellModel.navItems` contains the merged and filtered list of all `ResolvedShellNavItem`s from both manifest features and `appShellOverrides`.
151
-
152
- ### filterNavLinks
153
-
154
- `filterNavLinks()` in `ElevasisFeaturesProvider.tsx` recursively removes gated and disabled-subsection links from a `FeatureNavLink[]` array. A link is removed if its `featureKey` fails `isFeatureEnabled()` or if its path matches any entry in `disabledSubsectionPaths`. The function recurses into nested `links` arrays before deciding whether a parent with now-empty children should be retained or dropped.
155
-
156
- ## Access Resolution
157
-
158
- Shell feature-module keys map directly to feature IDs in the organization model. There is no alias layer:
159
-
160
- - `createFeatureAccessHook` is the factory that produces `useFeatureAccess`. (Old name `createUseFeatureAccess` is re-exported as `@deprecated`.)
161
- - `FeatureModule.featureId` must match a `feature.id` value in the org model's `features[]` array. The provider throws at startup if the ID is not found.
162
- - `MembershipFeatureConfig.features` is `Record<string, boolean>` -- a dynamic map keyed by feature ID. Any feature can be overridden per member without schema changes.
163
- - The provider fallback for missing feature access identity is retired -- explicit `featureId` is required.
164
-
165
- ## Published Surface
166
-
167
- `packages/ui/src/provider/published.ts` is intentionally headless: it exports the provider, types, and hooks, but no Mantine-dependent visual provider pieces. External consumers can adopt the feature/provider contract without pulling the full internal visual surface.
168
-
169
- All nine features are published as individual subpath exports from `@elevasis/ui`:
170
-
171
- - `@elevasis/ui/features/auth` -- `ProtectedRoute`, `AdminGuard`, `FeatureGuard`, `useUserProfile` (utility feature; no manifest)
172
- - `@elevasis/ui/features/dashboard` -- `Dashboard`, `ResourceOverview`, `RecentExecutionsByResource`, `UnresolvedErrorsTeaser` (utility feature; no manifest)
173
- - `@elevasis/ui/features/crm`
174
- - `@elevasis/ui/features/lead-gen`
175
- - `@elevasis/ui/features/projects`
176
- - `@elevasis/ui/features/monitoring`
177
- - `@elevasis/ui/features/operations`
178
- - `@elevasis/ui/features/seo`
179
- - `@elevasis/ui/features/settings`
180
-
181
- The `auth` and `dashboard` features are not in `FEATURE_MANIFESTS` and are not registered with `ElevasisFeaturesProvider`. They are standalone published feature modules consumed directly by host apps.
182
-
183
- ## Composition Patterns
184
-
185
- ### Command-center composition
186
-
187
- `apps/command-center/src/routes/__root.tsx`:
188
-
189
- 1. imports the mounted manifest list
190
- 2. resolves `COMMAND_CENTER_ORGANIZATION_MODEL`
191
- 3. passes manifests, organization model, time range, operations API URL, and SSE manager to `ElevasisFeaturesProvider`
192
- 4. keeps app-local nav entries for dashboard, admin, archive (passed into `appShellOverrides`)
193
- 5. derives filtered nav locally from `shellModel.navItems`
194
- 6. lets `FeatureShell` dispatch subshell sidebars for matched routes
195
-
196
- ### appShellOverrides
197
-
198
- `appShellOverrides` is an `AppShellOverrides` prop on `ElevasisFeaturesProvider` that lets the host app inject nav items outside the manifest registry:
9
+ ## Overview
199
10
 
200
- - `primaryNavItems?: FeatureNavEntry[]` -- prepended before feature nav items in the primary nav position; organization-model label and path resolution is applied to these entries
201
- - `bottomNavItems?: FeatureNavEntry[]` -- rendered at the bottom of the shell nav; also subject to organization-model resolution and `filterNavLinks` filtering
11
+ The feature shell derives app navigation from `OrganizationModel.features`. Feature manifests provide implementation hooks such as icons and sidebars; they no longer own structural navigation.
202
12
 
203
- Both arrays go through the same `isFeatureEnabled()` and `disabledSubsectionPaths` filtering as manifest-derived items. Items whose `featureKey` is disabled, or that have only disabled nested links and no direct `link`, are dropped entirely.
13
+ ## Source Of Truth
204
14
 
205
- Nine feature modules are published (see **Published Surface** above). Six are currently mounted in command-center: `leadGenManifest`, `crmManifest`, `projectsManifest`, `operationsManifest`, `monitoringManifest`, `settingsManifest`. The remaining three (`seoManifest`, `auth`, `dashboard`) are published but not mounted through `ElevasisFeaturesProvider` in command-center -- `auth` and `dashboard` are utility features consumed directly, while `seoManifest` is available for composition but not wired into the current command-center shell.
15
+ - `packages/core/src/organization-model/defaults.ts` -- default flat feature list
16
+ - `packages/core/src/organization-model/helpers.ts` -- `childrenOf`, `ancestorsOf`, `parentOf`, `topLevel`, `findByPath`
17
+ - `packages/ui/src/features/registry/types.ts` -- `FeatureModule`
18
+ - `packages/ui/src/provider/ElevasisFeaturesProvider.tsx` -- runtime resolver
19
+ - `packages/ui/src/components/navigation/useBreadcrumbs.ts` -- breadcrumb derivation
206
20
 
207
- ### External-consumer composition
21
+ ## FeatureModule
208
22
 
209
- External shells consume the published `@elevasis/ui` provider surface. `_template/ui` imports individual manifests, composes a local `FEATURE_MANIFESTS: FeatureModule[]` array, and passes `canonicalOrganizationModel` (from `@foundation/config/organization-model`) into the provider. Host-local nav (home/dashboard) remains app-owned -- the provider covers shared shell features, not total shell ownership.
23
+ ```ts
24
+ export interface FeatureModule {
25
+ key: string
26
+ featureId: string
27
+ capabilityIds?: string[]
28
+ icon?: FeatureIconComponent
29
+ sidebar?: FeatureSidebarComponent
30
+ organizationGraph?: { featureId: string }
31
+ }
32
+ ```
210
33
 
211
- See [Composition & Extensibility](./composition-extensibility.mdx) for the sidebar/page override patterns consumers use to customize shared features without forking.
34
+ `featureId` must match an Organization Model feature ID. Structural fields such as route lists, nav labels, and nested links belong on `OrganizationModel.features`.
212
35
 
213
- ## Feature-Specific Sidebar Behavior
36
+ ## Shell Model
214
37
 
215
- ### CRM Sidebar
38
+ `useElevasisFeatures()` exposes `shellModel`:
216
39
 
217
- The CRM sidebar (`packages/ui/src/features/crm/sidebar/`) exports `CrmSidebar`, `CrmSidebarTop`, and `CrmSidebarMiddle`. `SavedViewsPanel` lives in `packages/ui/src/features/crm/workbench/SavedViewsPanel.tsx` and is exported from the CRM workbench barrel; it provides the saved contact views panel. It is currently commented out of the default `CrmSidebarMiddle` layout while the CRM sidebar section model is being reworked, but can be re-included explicitly when composing a custom sidebar.
40
+ ```ts
41
+ {
42
+ features,
43
+ findByPath,
44
+ findById,
45
+ childrenOf,
46
+ ancestorsOf,
47
+ parentOf,
48
+ topLevel,
49
+ uiPositionFor,
50
+ requiresAdminFor,
51
+ devOnlyFor
52
+ }
53
+ ```
218
54
 
219
- ### Operations Sidebar
55
+ Sidebar rendering walks `topLevel()` and `childrenOf(id)`. Breadcrumbs resolve `findByPath(location.pathname)` and then map `ancestorsOf(id)`.
220
56
 
221
- `OperationsSidebarTop` in `packages/ui/src/features/operations/sidebar/OperationsSidebarTop.tsx` is context-aware by route:
57
+ ## Access
222
58
 
223
- - Returns `null` for sessions (`/operations/sessions`) and command-view (`/operations/command-view`) routes -- these sections own their own top-area UI
224
- - Shows a "Resource Overview" navigation button for the resources section (`/operations/resources`)
225
- - Returns `null` for all other paths (e.g., the operations index)
59
+ Feature access is keyed by Organization Model feature ID. `requiresAdmin` and `devOnly` inherit from ancestor feature nodes and are applied when deriving visible sidebar entries.
226
60
 
227
- This pattern avoids hardcoding sidebar top content in the parent and lets each operations sub-section declare its own top panel entry point.
61
+ Routes still need guards:
228
62
 
229
- ## Testing
63
+ ```tsx
64
+ <ProtectedRoute>
65
+ <FeatureGuard featureKey="sales.crm">
66
+ <Outlet />
67
+ </FeatureGuard>
68
+ </ProtectedRoute>
69
+ ```
230
70
 
231
- - `createTestFeaturesProvider` fixture at `packages/ui/src/provider/createTestFeaturesProvider.tsx` (internal; exported from `provider/index.ts`) gives tests a pre-wired provider with configurable organization model and feature access.
232
- - Resolver modules have focused unit tests (`RouteResolver.test.ts`, `NavResolver.test.ts`).
233
- - `validateManifests.test.ts` covers manifest validation against the organization model.
234
- - `ElevasisFeaturesProvider.test.tsx`, `FeatureShell.test.tsx`, and `feature-contract.test.ts` cover runtime composition and the published surface.
71
+ Use `AdminGuard` for pages that require platform-admin privileges.
235
72
 
236
- ## Key Conceptual Distinctions
73
+ ## External Shells
237
74
 
238
- - **Platform capability vs. shell feature** -- capabilities are the product map; shell features are manifest-backed UI surfaces.
239
- - **Shell feature key vs. org-model feature id** -- both are the same value (e.g., `crm`). `FeatureModule.featureId` directly matches `feature.id` in the org model; there is no alias layer.
240
- - **Feature vs. capability** -- a feature object in the org model carries `entityIds`, `surfaceIds`, `resourceIds`, and `capabilityIds`; capabilities are one kind of semantic reference a feature can hold.
241
- - **Provider-owned vs. consumer-owned** -- provider owns shared manifests, nav contribution, sidebar dispatch, shared runtime context; consumers own route files, branding, topbar behavior, admin entries.
75
+ External templates pass `canonicalOrganizationModel` into `ElevasisFeaturesProvider` and derive sidebar links locally from `shellModel`. There is no separate nav config file to keep in sync.