@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,158 +1,117 @@
1
- ---
2
- title: Gate by Feature or Admin
3
- description: Decision table and step-by-step recipes for gating routes, nav items, and UI elements by feature flag or admin role.
4
- ---
5
-
6
- # Gate by Feature or Admin
7
-
8
- End-to-end: gate a route, nav item, or UI element. Steps are sequential.
9
-
10
- See [glossary.md](../reference/glossary.md) under **FeatureGuard**, **AdminGuard**, **featureId**, **featureKey**, **Settings asymmetry**, and **MembershipFeatureConfig**. See [contracts.md](../reference/contracts.md) for `MembershipFeatureConfig` shape and the settings-asymmetry callout.
11
-
12
- For the three-concept model in full detail, see [feature-flags-and-gating.md](../ui/feature-flags-and-gating.md).
13
-
14
- ---
15
-
16
- ## 1. Decide: feature-level or admin-level?
17
-
18
- | Scenario | Gate to use |
19
- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
20
- | Surface should be off by default for all members, toggled org-wide or per member | `FeatureGuard` + `featureKey` on nav entry |
21
- | Surface is always visible to authenticated members but restricted to admins only | `AdminGuard` + `requiresAdmin` on nav entry |
22
- | Surface is both feature-gated and admin-only | Both: `FeatureGuard` wrapping `AdminGuard`, plus both nav-entry fields |
23
-
24
- Do not substitute one for the other. `FeatureGuard` reads feature flags; `AdminGuard` reads admin role. They are independent.
25
-
26
- ---
27
-
28
- ## 2. Feature gate -- org level
29
-
30
- Ensure a feature object with the matching `id` exists in the org model. File: `core/config/organization-model.ts`.
31
-
32
- ```ts
33
- import { defineOrganizationModel, OPERATIONS_FEATURE_ID, SALES_FEATURE_ID } from '@elevasis/core/organization-model'
34
-
35
- // In the features[] array inside defineOrganizationModel:
36
- features: [
37
- // ... existing features
38
- { id: 'analytics', label: 'Analytics', enabled: false, entityIds: [], surfaceIds: [], resourceIds: [], capabilityIds: [] }
39
- ]
40
- ```
41
-
42
- Use typed constants for the 7 platform features (`SALES_FEATURE_ID`, `OPERATIONS_FEATURE_ID`, etc.); use string literals for project-specific features you invent. In this example, `'analytics'` is a project-local feature and stays as a string literal.
43
-
44
- See [add-a-feature.md](add-a-feature.md) step 2 for the full feature object shape.
45
-
46
- Set `enabled: true` to enable for all members by default.
47
-
48
- ---
49
-
50
- ## 3. Feature gate -- route level
51
-
52
- Wrap the route layout with `FeatureGuard` inside `ProtectedRoute`. The template-local `FeatureGuard` resolves key aliases automatically.
53
-
54
- ```tsx
55
- import { ProtectedRoute } from '@/features/auth'
56
- import { FeatureGuard } from '@/features/auth/guards/FeatureGuard'
57
- import { createFileRoute, Outlet } from '@tanstack/react-router'
58
-
59
- export const Route = createFileRoute('/analytics')({ component: AnalyticsLayout })
60
-
61
- function AnalyticsLayout() {
62
- return (
63
- <ProtectedRoute>
64
- <FeatureGuard featureKey="analytics">
65
- <Outlet />
66
- </FeatureGuard>
67
- </ProtectedRoute>
68
- )
69
- }
70
- ```
71
-
72
- `FeatureGuard` redirects to `/` with a Mantine notification when the feature is off. All child routes under this layout are automatically protected -- no need to repeat the guard in children.
73
-
74
- Import path: `@/features/auth/guards/FeatureGuard` (template-local). Do not import `FeatureGuard` from `@elevasis/ui/features` -- that version does not close over the local org model. See [feature-flags-and-gating.md](../ui/feature-flags-and-gating.md) for the import-paths table.
75
-
76
- ---
77
-
78
- ## 4. Admin gate -- route level
79
-
80
- Wrap with `AdminGuard` inside `ProtectedRoute`. `AdminGuard` redirects non-admins to `redirectTo` (default `/`).
81
-
82
- ```tsx
83
- import { ProtectedRoute } from '@/features/auth'
84
- import { AdminGuard } from '@elevasis/ui/auth'
85
- import { createFileRoute, Outlet } from '@tanstack/react-router'
86
-
87
- export const Route = createFileRoute('/admin')({ component: AdminLayout })
88
-
89
- function AdminLayout() {
90
- return (
91
- <ProtectedRoute>
92
- <AdminGuard>
93
- <Outlet />
94
- </AdminGuard>
95
- </ProtectedRoute>
96
- )
97
- }
98
- ```
99
-
100
- Import path: `@elevasis/ui/auth` (published). Always nest inside `ProtectedRoute` -- the guard depends on the user profile being loaded.
101
-
102
- ---
103
-
104
- ## 5. Nav-item visibility
105
-
106
- Declare `featureKey` on the nav entry to have the shell auto-hide it when the feature is off. Declare `requiresAdmin: true` to hide it for non-admin members.
107
-
108
- ```ts
109
- // In FeatureModule.navEntry (manifest-backed features):
110
- navEntry: {
111
- label: 'Analytics',
112
- icon: IconChartBar,
113
- link: '/analytics',
114
- featureKey: 'analytics' // optional -- featureId already gates the whole module
115
- }
116
-
117
- // In nav-items.ts (app-local nav):
118
- { label: 'Analytics', icon: IconChartBar, link: '/analytics', featureKey: 'analytics' }
119
- { label: 'Admin', icon: IconShield, link: '/admin', requiresAdmin: true }
120
- ```
121
-
122
- `featureKey` on a nav entry is a display hint only -- it does not protect the route. Always pair with a route-level `FeatureGuard`. See [glossary.md](../reference/glossary.md) under **featureId vs featureKey** for the distinction. When the `featureKey` is one of the 7 platform features, prefer the typed constant (e.g., `featureKey: SALES_FEATURE_ID`) over a string literal to catch renames at compile time.
123
-
124
- ---
125
-
126
- ## 6. Per-member override
127
-
128
- `MembershipFeatureConfig.features` (stored in `org_memberships.config`) overrides org-level defaults per member. Full shape is in [contracts.md](../reference/contracts.md#membershipfeatureconfig).
129
-
130
- ```ts
131
- // Disable analytics for a specific member (stored in their membership record):
132
- {
133
- features: { analytics: false }
134
- }
135
- ```
136
-
137
- `MembershipFeatureConfig.features` is `Record<string, boolean>` -- a dynamic map keyed by feature ID. Any feature ID from the org model can be overridden per member without schema changes.
138
-
139
- **Settings asymmetry -- read this before writing membership config.** The `settings` feature is intentionally excluded from per-member overrides: settings access is controlled by `requiresAdmin` and `AdminGuard`, not per-member feature flags. Writing a `settings` key to `org_memberships.config` has no effect. See [contracts.md](../reference/contracts.md#membershipfeatureconfig) for the full callout, and [glossary.md](../reference/glossary.md) under **Settings asymmetry**.
140
-
141
- Membership config is read/written directly via the Supabase client (`org_memberships.config` column). There is no dedicated API route for bulk updates.
142
-
143
- ---
144
-
145
- ## 7. Verify
146
-
147
- State matrix -- confirm each combination:
148
-
149
- | Org feature enabled | Member override | Admin | Expected result |
150
- | ------------------- | --------------- | --------- | --------------------------------------------- |
151
- | true | (absent) | any | Route accessible, nav visible |
152
- | true | false | any | Route redirects, nav hidden |
153
- | false | (absent) | any | Route redirects, nav hidden |
154
- | false | true | any | Route redirects (org gate wins) |
155
- | true | (absent) | non-admin | Admin-gated route redirects, admin nav hidden |
156
- | true | (absent) | admin | Admin-gated route accessible, nav visible |
157
-
158
- Check each gate independently: feature toggle in `core/config/organization-model.ts`, membership config in `org_memberships.config`, and admin status in the user profile.
1
+ ---
2
+ title: Gate by Feature or Admin
3
+ description: Decision table and recipes for gating routes, sidebar entries, and UI elements by Organization Model feature ID or admin role.
4
+ ---
5
+ <!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
6
+ <!-- Regenerate: pnpm scaffold:sync -->
7
+
8
+
9
+ # Gate by Feature or Admin
10
+
11
+ Feature visibility starts in `core/config/organization-model.ts`. Routes still enforce access with guards.
12
+
13
+ ## Decide the gate
14
+
15
+ | Scenario | Gate to use |
16
+ | --- | --- |
17
+ | Surface can be enabled or disabled per organization/member | `FeatureGuard` with the feature ID |
18
+ | Surface is always available to members but restricted to admins | `AdminGuard` plus `requiresAdmin: true` on the feature node |
19
+ | Surface is both feature-gated and admin-only | Both guards, plus `requiresAdmin: true` on the feature node |
20
+
21
+ ## Feature gate in the org model
22
+
23
+ Add or update the feature in `features`.
24
+
25
+ ```ts
26
+ features: [
27
+ {
28
+ id: 'analytics',
29
+ label: 'Analytics',
30
+ enabled: false,
31
+ path: '/analytics',
32
+ icon: 'chart',
33
+ uiPosition: 'sidebar-primary'
34
+ }
35
+ ]
36
+ ```
37
+
38
+ Set `enabled: true` to enable it for all members by default. Dotted IDs such as `analytics.reports` inherit feature state and shell placement from their ancestors unless they declare their own value.
39
+
40
+ ## Route-level feature gate
41
+
42
+ ```tsx
43
+ import { ProtectedRoute } from '@/features/auth'
44
+ import { FeatureGuard } from '@/features/auth/guards/FeatureGuard'
45
+ import { createFileRoute, Outlet } from '@tanstack/react-router'
46
+
47
+ export const Route = createFileRoute('/analytics')({ component: AnalyticsLayout })
48
+
49
+ function AnalyticsLayout() {
50
+ return (
51
+ <ProtectedRoute>
52
+ <FeatureGuard featureKey="analytics">
53
+ <Outlet />
54
+ </FeatureGuard>
55
+ </ProtectedRoute>
56
+ )
57
+ }
58
+ ```
59
+
60
+ The sidebar is derived from `OrganizationModel.features`; hiding a node there is display behavior only. Keep route guards in place for direct URL access.
61
+
62
+ ## Admin-only route
63
+
64
+ ```tsx
65
+ import { ProtectedRoute } from '@/features/auth'
66
+ import { AdminGuard } from '@elevasis/ui/auth'
67
+ import { createFileRoute, Outlet } from '@tanstack/react-router'
68
+
69
+ export const Route = createFileRoute('/admin')({ component: AdminLayout })
70
+
71
+ function AdminLayout() {
72
+ return (
73
+ <ProtectedRoute>
74
+ <AdminGuard>
75
+ <Outlet />
76
+ </AdminGuard>
77
+ </ProtectedRoute>
78
+ )
79
+ }
80
+ ```
81
+
82
+ Pair the route guard with the feature node:
83
+
84
+ ```ts
85
+ {
86
+ id: 'admin',
87
+ label: 'Admin',
88
+ enabled: true,
89
+ path: '/admin',
90
+ uiPosition: 'sidebar-bottom',
91
+ requiresAdmin: true
92
+ }
93
+ ```
94
+
95
+ ## Per-member override
96
+
97
+ `MembershipFeatureConfig.features` in `org_memberships.config` overrides enabled state per member.
98
+
99
+ ```ts
100
+ {
101
+ features: { analytics: false }
102
+ }
103
+ ```
104
+
105
+ Settings and admin-only pages should use admin checks, not per-member feature flags.
106
+
107
+ ## Verify
108
+
109
+ Check the state matrix:
110
+
111
+ | Org feature enabled | Member override | Admin | Expected result |
112
+ | --- | --- | --- | --- |
113
+ | true | absent | any | Route accessible, sidebar visible |
114
+ | true | false | any | Route redirects, sidebar hidden |
115
+ | false | absent | any | Route redirects, sidebar hidden |
116
+ | true | absent | non-admin | Admin route redirects, admin sidebar hidden |
117
+ | true | absent | admin | Admin route accessible, admin sidebar visible |
@@ -2,6 +2,9 @@
2
2
  title: Pathway Recipes
3
3
  description: Terse end-to-end walkthroughs for the three most common authoring tasks -- adding a feature, adding a resource, and gating access.
4
4
  ---
5
+ <!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
6
+ <!-- Regenerate: pnpm scaffold:sync -->
7
+
5
8
 
6
9
  # Pathway Recipes
7
10