@elevasis/sdk 1.8.2 → 1.8.3
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.
- package/dist/cli.cjs +1 -1
- package/dist/index.d.ts +88 -39
- package/dist/types/worker/adapters/lead.d.ts +1 -1
- package/dist/worker/index.js +2 -0
- package/package.json +2 -2
- package/reference/_navigation.md +7 -1
- package/reference/_reference-manifest.json +14 -0
- package/reference/claude-config/logs/scaffold-registry-reminder.log +3 -0
- package/reference/claude-config/rules/agent-start-here.md +254 -254
- package/reference/claude-config/rules/frontend.md +43 -43
- package/reference/claude-config/rules/operations.md +64 -64
- package/reference/claude-config/rules/organization-model.md +42 -43
- package/reference/claude-config/rules/organization-os.md +107 -107
- package/reference/claude-config/rules/shared-types.md +2 -2
- package/reference/claude-config/rules/task-tracking.md +1 -1
- package/reference/claude-config/rules/ui.md +202 -202
- package/reference/claude-config/rules/vibe.md +202 -202
- package/reference/claude-config/skills/configure/SKILL.md +98 -98
- package/reference/claude-config/skills/configure/operations/codify-level-a.md +100 -100
- package/reference/claude-config/skills/configure/operations/codify-level-b.md +158 -158
- package/reference/claude-config/skills/configure/operations/customers.md +150 -150
- package/reference/claude-config/skills/configure/operations/features.md +162 -162
- package/reference/claude-config/skills/configure/operations/goals.md +147 -147
- package/reference/claude-config/skills/configure/operations/identity.md +133 -133
- package/reference/claude-config/skills/configure/operations/labels.md +128 -128
- package/reference/claude-config/skills/configure/operations/offerings.md +159 -159
- package/reference/claude-config/skills/configure/operations/roles.md +153 -153
- package/reference/claude-config/skills/configure/operations/techStack.md +139 -139
- package/reference/claude-config/skills/explore/SKILL.md +78 -78
- package/reference/claude-config/skills/git-sync/SKILL.md +126 -0
- package/reference/claude-config/skills/save/SKILL.md +183 -183
- package/reference/claude-config/skills/setup/SKILL.md +275 -275
- package/reference/claude-config/skills/sync/SKILL.md +10 -44
- package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +27 -0
- package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +30 -0
- package/reference/claude-config/sync-notes/README.md +43 -0
- package/reference/packages/core/src/README.md +39 -36
- package/reference/packages/core/src/business/README.md +52 -52
- package/reference/packages/core/src/organization-model/README.md +97 -97
- package/reference/packages/core/src/test-utils/README.md +42 -0
- package/reference/scaffold/core/organization-graph.mdx +272 -272
- package/reference/scaffold/core/organization-model.mdx +320 -320
- package/reference/scaffold/index.mdx +64 -64
- package/reference/scaffold/operations/propagation-pipeline.md +125 -104
- package/reference/scaffold/operations/scaffold-maintenance.md +122 -122
- package/reference/scaffold/operations/workflow-recipes.md +436 -436
- package/reference/scaffold/recipes/add-a-feature.md +158 -158
- package/reference/scaffold/recipes/add-a-resource.md +158 -158
- package/reference/scaffold/recipes/customize-organization-model.md +400 -400
- package/reference/scaffold/recipes/extend-a-base-entity.md +140 -140
- package/reference/scaffold/recipes/gate-by-feature-or-admin.md +158 -158
- package/reference/scaffold/recipes/index.md +32 -32
- package/reference/scaffold/reference/contracts.md +608 -607
- package/reference/scaffold/reference/feature-registry.md +2 -0
- package/reference/scaffold/reference/glossary.md +105 -105
- package/reference/scaffold/ui/composition-extensibility.mdx +1 -1
- package/reference/scaffold/ui/feature-flags-and-gating.md +1 -1
|
@@ -1,158 +1,158 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Add a Feature
|
|
3
|
-
description: End-to-end walkthrough for adding a new shell feature (e.g., analytics) from org-model key through manifest, routes, and gating.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Add a Feature
|
|
7
|
-
|
|
8
|
-
End-to-end: add a new shell feature such as `analytics`. Steps are sequential.
|
|
9
|
-
|
|
10
|
-
See [glossary.md](../reference/glossary.md) for term disambiguation throughout this recipe (Feature has three distinct contexts). See [contracts.md](../reference/contracts.md) for authoritative TypeScript shapes.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 1. Decide the feature shape
|
|
15
|
-
|
|
16
|
-
A shell feature requires a `feature.id` in the org model's `features[]` array to gate it. You have two options:
|
|
17
|
-
|
|
18
|
-
- **Reuse an existing feature** (e.g., `operations`, `monitoring`). The new shell module shares the on/off toggle with the existing feature entry. Fine for sub-modules within the same product area.
|
|
19
|
-
- **Add a new feature object** -- add an entry to the `features[]` array in `foundations/config/organization-model.ts`. This is always a template-local change; no core package change is required.
|
|
20
|
-
|
|
21
|
-
For a genuinely new capability (e.g., `analytics`), you add a feature object to the defaults array and author a matching manifest.
|
|
22
|
-
|
|
23
|
-
See [glossary.md](../reference/glossary.md) under **Feature** (three contexts).
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## 2. Update the organization model
|
|
28
|
-
|
|
29
|
-
File: `foundations/config/organization-model.ts`
|
|
30
|
-
|
|
31
|
-
Add a new feature object to the `features[]` array passed to `defineOrganizationModel`.
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
import { defineOrganizationModel } from '@elevasis/core/organization-model'
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Use typed constants for the 7 platform features (`SALES_FEATURE_ID`, `PROSPECTING_FEATURE_ID`, `PROJECTS_FEATURE_ID`, `OPERATIONS_FEATURE_ID`, `MONITORING_FEATURE_ID`, `SETTINGS_FEATURE_ID`, `SEO_FEATURE_ID`); use string literals for project-specific features you invent.
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
const foundationOrganizationModelOverride = defineOrganizationModel({
|
|
41
|
-
features: [
|
|
42
|
-
// ... existing features
|
|
43
|
-
{
|
|
44
|
-
id: 'analytics',
|
|
45
|
-
label: 'Analytics',
|
|
46
|
-
enabled: false, // start disabled
|
|
47
|
-
entityIds: [],
|
|
48
|
-
surfaceIds: [],
|
|
49
|
-
resourceIds: [],
|
|
50
|
-
capabilityIds: []
|
|
51
|
-
}
|
|
52
|
-
],
|
|
53
|
-
// ... rest of model
|
|
54
|
-
})
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Each field of the feature object:
|
|
58
|
-
|
|
59
|
-
- `id` -- unique stable identifier; this is the value `FeatureModule.featureId` must match
|
|
60
|
-
- `label` -- display name; used by nav label resolution when no manifest override is provided
|
|
61
|
-
- `enabled` -- org-wide default; `MembershipFeatureConfig.features` can override per member
|
|
62
|
-
- `entityIds`, `surfaceIds`, `resourceIds`, `capabilityIds` -- semantic references (leave empty to start)
|
|
63
|
-
|
|
64
|
-
No domain entry or separate key resolver is needed. The `features[]` array is the sole source of truth.
|
|
65
|
-
|
|
66
|
-
**Two-step pattern:** in a template-derived project, the `defineOrganizationModel` output is passed to `createFoundationOrganizationModel(override)` in `foundations/config/organization-model.ts`. The result exposes `.model`, `.canonical`, and `.homeLabel`. See `external/_template/foundations/config/organization-model.ts` for the canonical two-step example.
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## 3. Author the FeatureModule
|
|
71
|
-
|
|
72
|
-
Create `ui/src/features/analytics/manifest.ts`. Full `FeatureModule` shape is in [contracts.md](../reference/contracts.md#featuremodule) (`@elevasis/ui/provider`).
|
|
73
|
-
|
|
74
|
-
```ts
|
|
75
|
-
import type { FeatureModule } from '@elevasis/ui/provider'
|
|
76
|
-
import { IconChartBar } from '@tabler/icons-react'
|
|
77
|
-
import { AnalyticsSidebar } from './sidebar'
|
|
78
|
-
|
|
79
|
-
export const analyticsManifest: FeatureModule = {
|
|
80
|
-
key: 'analytics',
|
|
81
|
-
featureId: 'analytics', // must match a feature.id in the org model's features[] array
|
|
82
|
-
navEntry: {
|
|
83
|
-
label: 'Analytics',
|
|
84
|
-
icon: IconChartBar,
|
|
85
|
-
link: '/analytics'
|
|
86
|
-
},
|
|
87
|
-
sidebar: AnalyticsSidebar,
|
|
88
|
-
subshellRoutes: ['/analytics', '/analytics/reports']
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Key fields:
|
|
93
|
-
|
|
94
|
-
- `featureId` -- the org-model feature ID that gates the entire feature. The provider throws at startup if this ID is not found in the org model's `features[]` array. See [glossary.md](../reference/glossary.md) under **featureId**.
|
|
95
|
-
- `sidebar` -- a component that renders the subshell sidebar. Compose from published primitives. See [customization.md](../ui/customization.md).
|
|
96
|
-
- `subshellRoutes` -- every path that should activate this feature's sidebar.
|
|
97
|
-
|
|
98
|
-
Register the manifest in `ui/src/routes/__root.tsx` by adding it to the `FEATURE_MANIFESTS` array passed to `ElevasisFeaturesProvider`.
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## 4. Add routes under the subshell
|
|
103
|
-
|
|
104
|
-
Create the TanStack Router layout and child routes.
|
|
105
|
-
|
|
106
|
-
Layout file (`ui/src/routes/analytics.tsx`) owns the subshell guard and renders `<Outlet />`:
|
|
107
|
-
|
|
108
|
-
```tsx
|
|
109
|
-
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
|
110
|
-
import { ProtectedRoute } from '@/features/auth'
|
|
111
|
-
import { FeatureGuard } from '@/features/auth/guards/FeatureGuard'
|
|
112
|
-
|
|
113
|
-
export const Route = createFileRoute('/analytics')({
|
|
114
|
-
component: AnalyticsLayout
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
function AnalyticsLayout() {
|
|
118
|
-
return (
|
|
119
|
-
<ProtectedRoute>
|
|
120
|
-
<FeatureGuard featureKey="analytics">
|
|
121
|
-
<Outlet />
|
|
122
|
-
</FeatureGuard>
|
|
123
|
-
</ProtectedRoute>
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Child pages go under `ui/src/routes/analytics/`. See [UI Recipes](../ui/recipes.md) recipe 2 for the nested page pattern.
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## 5. Gate the route
|
|
133
|
-
|
|
134
|
-
Two independent mechanisms -- use both:
|
|
135
|
-
|
|
136
|
-
- `FeatureGuard` (feature-level): blocks access when the org model has the feature key disabled or when the member's `MembershipFeatureConfig` disables it. Always nest inside `ProtectedRoute`.
|
|
137
|
-
- `AdminGuard` (admin-level): blocks access for non-admin members. Add this if the feature should only be accessible to admins.
|
|
138
|
-
|
|
139
|
-
Full decision table and import paths are in [gate-by-feature-or-admin.md](gate-by-feature-or-admin.md).
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## 6. (Optional) Add operations resources that back the feature
|
|
144
|
-
|
|
145
|
-
If the feature drives automation (e.g., an analytics pipeline workflow), create the resources in `operations/src/` and optionally map them into the org model via `resourceMappings`. See [add-a-resource.md](add-a-resource.md).
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## 7. Verify
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
pnpm -C ui dev
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
- Feature appears in the nav sidebar.
|
|
156
|
-
- Route is accessible and the subshell sidebar renders.
|
|
157
|
-
- Toggle `features.enabled.analytics` to `false` in `foundations/config/organization-model.ts` and confirm the nav item disappears and the route redirects.
|
|
158
|
-
- Check `FeatureGuard` by navigating directly to `/analytics` with the feature disabled.
|
|
1
|
+
---
|
|
2
|
+
title: Add a Feature
|
|
3
|
+
description: End-to-end walkthrough for adding a new shell feature (e.g., analytics) from org-model key through manifest, routes, and gating.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add a Feature
|
|
7
|
+
|
|
8
|
+
End-to-end: add a new shell feature such as `analytics`. Steps are sequential.
|
|
9
|
+
|
|
10
|
+
See [glossary.md](../reference/glossary.md) for term disambiguation throughout this recipe (Feature has three distinct contexts). See [contracts.md](../reference/contracts.md) for authoritative TypeScript shapes.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. Decide the feature shape
|
|
15
|
+
|
|
16
|
+
A shell feature requires a `feature.id` in the org model's `features[]` array to gate it. You have two options:
|
|
17
|
+
|
|
18
|
+
- **Reuse an existing feature** (e.g., `operations`, `monitoring`). The new shell module shares the on/off toggle with the existing feature entry. Fine for sub-modules within the same product area.
|
|
19
|
+
- **Add a new feature object** -- add an entry to the `features[]` array in `foundations/config/organization-model.ts`. This is always a template-local change; no core package change is required.
|
|
20
|
+
|
|
21
|
+
For a genuinely new capability (e.g., `analytics`), you add a feature object to the defaults array and author a matching manifest.
|
|
22
|
+
|
|
23
|
+
See [glossary.md](../reference/glossary.md) under **Feature** (three contexts).
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Update the organization model
|
|
28
|
+
|
|
29
|
+
File: `foundations/config/organization-model.ts`
|
|
30
|
+
|
|
31
|
+
Add a new feature object to the `features[]` array passed to `defineOrganizationModel`.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { defineOrganizationModel } from '@elevasis/core/organization-model'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use typed constants for the 7 platform features (`SALES_FEATURE_ID`, `PROSPECTING_FEATURE_ID`, `PROJECTS_FEATURE_ID`, `OPERATIONS_FEATURE_ID`, `MONITORING_FEATURE_ID`, `SETTINGS_FEATURE_ID`, `SEO_FEATURE_ID`); use string literals for project-specific features you invent.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const foundationOrganizationModelOverride = defineOrganizationModel({
|
|
41
|
+
features: [
|
|
42
|
+
// ... existing features
|
|
43
|
+
{
|
|
44
|
+
id: 'analytics',
|
|
45
|
+
label: 'Analytics',
|
|
46
|
+
enabled: false, // start disabled
|
|
47
|
+
entityIds: [],
|
|
48
|
+
surfaceIds: [],
|
|
49
|
+
resourceIds: [],
|
|
50
|
+
capabilityIds: []
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
// ... rest of model
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Each field of the feature object:
|
|
58
|
+
|
|
59
|
+
- `id` -- unique stable identifier; this is the value `FeatureModule.featureId` must match
|
|
60
|
+
- `label` -- display name; used by nav label resolution when no manifest override is provided
|
|
61
|
+
- `enabled` -- org-wide default; `MembershipFeatureConfig.features` can override per member
|
|
62
|
+
- `entityIds`, `surfaceIds`, `resourceIds`, `capabilityIds` -- semantic references (leave empty to start)
|
|
63
|
+
|
|
64
|
+
No domain entry or separate key resolver is needed. The `features[]` array is the sole source of truth.
|
|
65
|
+
|
|
66
|
+
**Two-step pattern:** in a template-derived project, the `defineOrganizationModel` output is passed to `createFoundationOrganizationModel(override)` in `foundations/config/organization-model.ts`. The result exposes `.model`, `.canonical`, and `.homeLabel`. See `external/_template/foundations/config/organization-model.ts` for the canonical two-step example.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 3. Author the FeatureModule
|
|
71
|
+
|
|
72
|
+
Create `ui/src/features/analytics/manifest.ts`. Full `FeatureModule` shape is in [contracts.md](../reference/contracts.md#featuremodule) (`@elevasis/ui/provider`).
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import type { FeatureModule } from '@elevasis/ui/provider'
|
|
76
|
+
import { IconChartBar } from '@tabler/icons-react'
|
|
77
|
+
import { AnalyticsSidebar } from './sidebar'
|
|
78
|
+
|
|
79
|
+
export const analyticsManifest: FeatureModule = {
|
|
80
|
+
key: 'analytics',
|
|
81
|
+
featureId: 'analytics', // must match a feature.id in the org model's features[] array
|
|
82
|
+
navEntry: {
|
|
83
|
+
label: 'Analytics',
|
|
84
|
+
icon: IconChartBar,
|
|
85
|
+
link: '/analytics'
|
|
86
|
+
},
|
|
87
|
+
sidebar: AnalyticsSidebar,
|
|
88
|
+
subshellRoutes: ['/analytics', '/analytics/reports']
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Key fields:
|
|
93
|
+
|
|
94
|
+
- `featureId` -- the org-model feature ID that gates the entire feature. The provider throws at startup if this ID is not found in the org model's `features[]` array. See [glossary.md](../reference/glossary.md) under **featureId**.
|
|
95
|
+
- `sidebar` -- a component that renders the subshell sidebar. Compose from published primitives. See [customization.md](../ui/customization.md).
|
|
96
|
+
- `subshellRoutes` -- every path that should activate this feature's sidebar.
|
|
97
|
+
|
|
98
|
+
Register the manifest in `ui/src/routes/__root.tsx` by adding it to the `FEATURE_MANIFESTS` array passed to `ElevasisFeaturesProvider`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 4. Add routes under the subshell
|
|
103
|
+
|
|
104
|
+
Create the TanStack Router layout and child routes.
|
|
105
|
+
|
|
106
|
+
Layout file (`ui/src/routes/analytics.tsx`) owns the subshell guard and renders `<Outlet />`:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
|
110
|
+
import { ProtectedRoute } from '@/features/auth'
|
|
111
|
+
import { FeatureGuard } from '@/features/auth/guards/FeatureGuard'
|
|
112
|
+
|
|
113
|
+
export const Route = createFileRoute('/analytics')({
|
|
114
|
+
component: AnalyticsLayout
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
function AnalyticsLayout() {
|
|
118
|
+
return (
|
|
119
|
+
<ProtectedRoute>
|
|
120
|
+
<FeatureGuard featureKey="analytics">
|
|
121
|
+
<Outlet />
|
|
122
|
+
</FeatureGuard>
|
|
123
|
+
</ProtectedRoute>
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Child pages go under `ui/src/routes/analytics/`. See [UI Recipes](../ui/recipes.md) recipe 2 for the nested page pattern.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 5. Gate the route
|
|
133
|
+
|
|
134
|
+
Two independent mechanisms -- use both:
|
|
135
|
+
|
|
136
|
+
- `FeatureGuard` (feature-level): blocks access when the org model has the feature key disabled or when the member's `MembershipFeatureConfig` disables it. Always nest inside `ProtectedRoute`.
|
|
137
|
+
- `AdminGuard` (admin-level): blocks access for non-admin members. Add this if the feature should only be accessible to admins.
|
|
138
|
+
|
|
139
|
+
Full decision table and import paths are in [gate-by-feature-or-admin.md](gate-by-feature-or-admin.md).
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 6. (Optional) Add operations resources that back the feature
|
|
144
|
+
|
|
145
|
+
If the feature drives automation (e.g., an analytics pipeline workflow), create the resources in `operations/src/` and optionally map them into the org model via `resourceMappings`. See [add-a-resource.md](add-a-resource.md).
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 7. Verify
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
pnpm -C ui dev
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- Feature appears in the nav sidebar.
|
|
156
|
+
- Route is accessible and the subshell sidebar renders.
|
|
157
|
+
- Toggle `features.enabled.analytics` to `false` in `foundations/config/organization-model.ts` and confirm the nav item disappears and the route redirects.
|
|
158
|
+
- Check `FeatureGuard` by navigating directly to `/analytics` with the feature disabled.
|
|
@@ -1,158 +1,158 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Add a Resource
|
|
3
|
-
description: End-to-end walkthrough for adding a new workflow or agent to the deployment spec, declaring relationships, and verifying in the resource inventory.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Add a Resource
|
|
7
|
-
|
|
8
|
-
End-to-end: add a new workflow or agent to `operations/` and verify it in the platform inventory. Steps are sequential.
|
|
9
|
-
|
|
10
|
-
See [glossary.md](../reference/glossary.md) under **Resource**, **DeploymentSpec**, and **Topology**. See [contracts.md](../reference/contracts.md) for `OrganizationModel` and `OrganizationModelResourceMapping` shapes.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 1. Author the resource
|
|
15
|
-
|
|
16
|
-
Create `operations/src/<name>/index.ts`. Follow the anatomy from [workflow-recipes.md](../operations/workflow-recipes.md) recipe 1 for the full `WorkflowDefinition` shape.
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
20
|
-
import { StepType } from '@elevasis/sdk'
|
|
21
|
-
import { myInputSchema, myOutputSchema } from '@foundation/types'
|
|
22
|
-
|
|
23
|
-
export const myWorkflow: WorkflowDefinition = {
|
|
24
|
-
config: {
|
|
25
|
-
resourceId: 'my-workflow',
|
|
26
|
-
name: 'My Workflow',
|
|
27
|
-
type: 'workflow',
|
|
28
|
-
version: '1.0.0',
|
|
29
|
-
status: 'dev'
|
|
30
|
-
},
|
|
31
|
-
contract: {
|
|
32
|
-
inputSchema: myInputSchema,
|
|
33
|
-
outputSchema: myOutputSchema
|
|
34
|
-
},
|
|
35
|
-
steps: {
|
|
36
|
-
run: {
|
|
37
|
-
id: 'run',
|
|
38
|
-
name: 'Run',
|
|
39
|
-
handler: async (rawInput, context) => {
|
|
40
|
-
context.logger.info('[run] starting')
|
|
41
|
-
// ...
|
|
42
|
-
return { result: 'done' }
|
|
43
|
-
},
|
|
44
|
-
inputSchema: myInputSchema,
|
|
45
|
-
outputSchema: myOutputSchema,
|
|
46
|
-
next: null
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
entryPoint: 'run'
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Define input/output schemas in `foundations/types/index.ts`, not inline. Both runtimes import from `@foundation/types`. See [workflow-recipes.md](../operations/workflow-recipes.md) for Zod schema conventions and adapter usage (`llm`, `storage`, `scheduler`, `notifications` from `@elevasis/sdk/worker`).
|
|
54
|
-
|
|
55
|
-
**Entity-backed workflows:** if your workflow operates on a domain entity (Project, Deal, Company, etc.), define or reference the entity shape in `foundations/types/entities.ts` rather than declaring an ad-hoc shape here. The entity types extend base contracts from `@elevasis/core/entities` (`BaseProject`, `BaseDeal`, etc.) with project-specific metadata. See [./extend-a-base-entity.md](./extend-a-base-entity.md) for the pattern.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## 2. Register in the DeploymentSpec
|
|
60
|
-
|
|
61
|
-
Create an exports barrel at `operations/src/<name>/exports.ts`:
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
import { myWorkflow } from './index.js'
|
|
65
|
-
import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
66
|
-
|
|
67
|
-
export const workflows: WorkflowDefinition[] = [myWorkflow]
|
|
68
|
-
export const agents: never[] = []
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Then spread into the top-level spec at `operations/src/index.ts`:
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
import * as myFeature from './my-feature/exports.js'
|
|
75
|
-
|
|
76
|
-
const org: DeploymentSpec = {
|
|
77
|
-
version: '0.1.0',
|
|
78
|
-
workflows: [...existing.workflows, ...myFeature.workflows],
|
|
79
|
-
agents: [...existing.agents, ...myFeature.agents]
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Use `.js` extensions in imports even though source is TypeScript -- required for ESM interoperability.
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## 3. (Optional) Declare relationships
|
|
88
|
-
|
|
89
|
-
If the resource triggers another resource, uses a human checkpoint, or depends on an integration, declare those relationships on the `DeploymentSpec`. See [glossary.md](../reference/glossary.md) under **Topology** for the three edge types (`triggers`, `uses`, `approval`).
|
|
90
|
-
|
|
91
|
-
```ts
|
|
92
|
-
const org: DeploymentSpec = {
|
|
93
|
-
// ...
|
|
94
|
-
relationships: {
|
|
95
|
-
'my-workflow': {
|
|
96
|
-
triggers: { workflows: ['email-notification'] }
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
humanCheckpoints: [
|
|
100
|
-
{
|
|
101
|
-
resourceId: 'approval-gate',
|
|
102
|
-
name: 'Approve before sending',
|
|
103
|
-
type: 'human',
|
|
104
|
-
version: '1.0.0',
|
|
105
|
-
status: 'prod',
|
|
106
|
-
routesTo: { workflows: ['my-workflow'] }
|
|
107
|
-
}
|
|
108
|
-
]
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Full relationship and checkpoint types are defined in `@elevasis/sdk` (`DeploymentSpec`). Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly.
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
## 4. (Optional) Map to a domain
|
|
117
|
-
|
|
118
|
-
To make the resource referenceable from the org model (so the Operations graph and Command View can link to it), add an entry to `resourceMappings` in `foundations/config/organization-model.ts`:
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
resourceMappings: [
|
|
122
|
-
{
|
|
123
|
-
id: 'my-workflow',
|
|
124
|
-
resourceId: 'my-workflow',
|
|
125
|
-
resourceType: 'workflow',
|
|
126
|
-
|
|
127
|
-
label: 'My Workflow'
|
|
128
|
-
}
|
|
129
|
-
]
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
See `OrganizationModelResourceMapping` in [contracts.md](../reference/contracts.md) for the full shape.
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## 5. Verify resource inventory
|
|
137
|
-
|
|
138
|
-
Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly. Confirm the new resource appears with the correct `resourceId`, `version`, and `status`.
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## 6. Verify
|
|
143
|
-
|
|
144
|
-
Validate and deploy:
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
pnpm -C operations run check # validate resource definitions
|
|
148
|
-
pnpm -C operations run deploy # deploy to dev
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Execute via the platform CLI from the project root:
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
pnpm exec elevasis describe Elevasis/my-workflow
|
|
155
|
-
pnpm exec elevasis exec Elevasis/my-workflow --input '{"field": "value"}'
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Use `--async` for long-running resources. Use `pnpm exec elevasis --prod exec ...` (flag before `exec`) for production. See [workflow-recipes.md](../operations/workflow-recipes.md) recipe 3 for the low-level frontend trigger pattern (`useApiClient` + `useMutation`). For the higher-level UI pattern using `RunResourceButton`, `useExecuteResource`, and `ZodFormRenderer`, see [../ui/recipes.md](../ui/recipes.md) recipe 6.
|
|
1
|
+
---
|
|
2
|
+
title: Add a Resource
|
|
3
|
+
description: End-to-end walkthrough for adding a new workflow or agent to the deployment spec, declaring relationships, and verifying in the resource inventory.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add a Resource
|
|
7
|
+
|
|
8
|
+
End-to-end: add a new workflow or agent to `operations/` and verify it in the platform inventory. Steps are sequential.
|
|
9
|
+
|
|
10
|
+
See [glossary.md](../reference/glossary.md) under **Resource**, **DeploymentSpec**, and **Topology**. See [contracts.md](../reference/contracts.md) for `OrganizationModel` and `OrganizationModelResourceMapping` shapes.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. Author the resource
|
|
15
|
+
|
|
16
|
+
Create `operations/src/<name>/index.ts`. Follow the anatomy from [workflow-recipes.md](../operations/workflow-recipes.md) recipe 1 for the full `WorkflowDefinition` shape.
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
20
|
+
import { StepType } from '@elevasis/sdk'
|
|
21
|
+
import { myInputSchema, myOutputSchema } from '@foundation/types'
|
|
22
|
+
|
|
23
|
+
export const myWorkflow: WorkflowDefinition = {
|
|
24
|
+
config: {
|
|
25
|
+
resourceId: 'my-workflow',
|
|
26
|
+
name: 'My Workflow',
|
|
27
|
+
type: 'workflow',
|
|
28
|
+
version: '1.0.0',
|
|
29
|
+
status: 'dev'
|
|
30
|
+
},
|
|
31
|
+
contract: {
|
|
32
|
+
inputSchema: myInputSchema,
|
|
33
|
+
outputSchema: myOutputSchema
|
|
34
|
+
},
|
|
35
|
+
steps: {
|
|
36
|
+
run: {
|
|
37
|
+
id: 'run',
|
|
38
|
+
name: 'Run',
|
|
39
|
+
handler: async (rawInput, context) => {
|
|
40
|
+
context.logger.info('[run] starting')
|
|
41
|
+
// ...
|
|
42
|
+
return { result: 'done' }
|
|
43
|
+
},
|
|
44
|
+
inputSchema: myInputSchema,
|
|
45
|
+
outputSchema: myOutputSchema,
|
|
46
|
+
next: null
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
entryPoint: 'run'
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Define input/output schemas in `foundations/types/index.ts`, not inline. Both runtimes import from `@foundation/types`. See [workflow-recipes.md](../operations/workflow-recipes.md) for Zod schema conventions and adapter usage (`llm`, `storage`, `scheduler`, `notifications` from `@elevasis/sdk/worker`).
|
|
54
|
+
|
|
55
|
+
**Entity-backed workflows:** if your workflow operates on a domain entity (Project, Deal, Company, etc.), define or reference the entity shape in `foundations/types/entities.ts` rather than declaring an ad-hoc shape here. The entity types extend base contracts from `@elevasis/core/entities` (`BaseProject`, `BaseDeal`, etc.) with project-specific metadata. See [./extend-a-base-entity.md](./extend-a-base-entity.md) for the pattern.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 2. Register in the DeploymentSpec
|
|
60
|
+
|
|
61
|
+
Create an exports barrel at `operations/src/<name>/exports.ts`:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { myWorkflow } from './index.js'
|
|
65
|
+
import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
66
|
+
|
|
67
|
+
export const workflows: WorkflowDefinition[] = [myWorkflow]
|
|
68
|
+
export const agents: never[] = []
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Then spread into the top-level spec at `operations/src/index.ts`:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import * as myFeature from './my-feature/exports.js'
|
|
75
|
+
|
|
76
|
+
const org: DeploymentSpec = {
|
|
77
|
+
version: '0.1.0',
|
|
78
|
+
workflows: [...existing.workflows, ...myFeature.workflows],
|
|
79
|
+
agents: [...existing.agents, ...myFeature.agents]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Use `.js` extensions in imports even though source is TypeScript -- required for ESM interoperability.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 3. (Optional) Declare relationships
|
|
88
|
+
|
|
89
|
+
If the resource triggers another resource, uses a human checkpoint, or depends on an integration, declare those relationships on the `DeploymentSpec`. See [glossary.md](../reference/glossary.md) under **Topology** for the three edge types (`triggers`, `uses`, `approval`).
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const org: DeploymentSpec = {
|
|
93
|
+
// ...
|
|
94
|
+
relationships: {
|
|
95
|
+
'my-workflow': {
|
|
96
|
+
triggers: { workflows: ['email-notification'] }
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
humanCheckpoints: [
|
|
100
|
+
{
|
|
101
|
+
resourceId: 'approval-gate',
|
|
102
|
+
name: 'Approve before sending',
|
|
103
|
+
type: 'human',
|
|
104
|
+
version: '1.0.0',
|
|
105
|
+
status: 'prod',
|
|
106
|
+
routesTo: { workflows: ['my-workflow'] }
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Full relationship and checkpoint types are defined in `@elevasis/sdk` (`DeploymentSpec`). Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 4. (Optional) Map to a domain
|
|
117
|
+
|
|
118
|
+
To make the resource referenceable from the org model (so the Operations graph and Command View can link to it), add an entry to `resourceMappings` in `foundations/config/organization-model.ts`:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
resourceMappings: [
|
|
122
|
+
{
|
|
123
|
+
id: 'my-workflow',
|
|
124
|
+
resourceId: 'my-workflow',
|
|
125
|
+
resourceType: 'workflow',
|
|
126
|
+
featureIds: ['operations'],
|
|
127
|
+
label: 'My Workflow'
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
See `OrganizationModelResourceMapping` in [contracts.md](../reference/contracts.md) for the full shape.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 5. Verify resource inventory
|
|
137
|
+
|
|
138
|
+
Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly. Confirm the new resource appears with the correct `resourceId`, `version`, and `status`.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 6. Verify
|
|
143
|
+
|
|
144
|
+
Validate and deploy:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pnpm -C operations run check # validate resource definitions
|
|
148
|
+
pnpm -C operations run deploy # deploy to dev
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Execute via the platform CLI from the project root:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pnpm exec elevasis describe Elevasis/my-workflow
|
|
155
|
+
pnpm exec elevasis exec Elevasis/my-workflow --input '{"field": "value"}'
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Use `--async` for long-running resources. Use `pnpm exec elevasis --prod exec ...` (flag before `exec`) for production. See [workflow-recipes.md](../operations/workflow-recipes.md) recipe 3 for the low-level frontend trigger pattern (`useApiClient` + `useMutation`). For the higher-level UI pattern using `RunResourceButton`, `useExecuteResource`, and `ZodFormRenderer`, see [../ui/recipes.md](../ui/recipes.md) recipe 6.
|