@elevasis/sdk 1.23.0 → 1.25.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.
- package/dist/cli.cjs +5927 -6985
- package/dist/index.d.ts +4893 -4759
- package/dist/index.js +1444 -3870
- package/dist/node/index.d.ts +3059 -2
- package/dist/node/index.js +163 -1
- package/dist/test-utils/index.d.ts +4413 -4439
- package/dist/test-utils/index.js +1766 -4753
- package/dist/types/worker/index.d.ts +5 -2
- package/dist/types/worker/platform.d.ts +2 -2
- package/dist/types/worker/utils.d.ts +9 -0
- package/dist/worker/index.js +427 -3708
- package/package.json +5 -4
- package/reference/_navigation.md +1 -0
- package/reference/claude-config/rules/active-change-index.md +11 -80
- package/reference/claude-config/rules/agent-start-here.md +11 -277
- package/reference/claude-config/rules/deployment.md +11 -57
- package/reference/claude-config/rules/error-handling.md +11 -56
- package/reference/claude-config/rules/execution.md +11 -40
- package/reference/claude-config/rules/frontend.md +11 -43
- package/reference/claude-config/rules/observability.md +11 -31
- package/reference/claude-config/rules/operations.md +11 -80
- package/reference/claude-config/rules/organization-model.md +5 -110
- package/reference/claude-config/rules/organization-os.md +7 -111
- package/reference/claude-config/rules/package-taxonomy.md +11 -33
- package/reference/claude-config/rules/platform.md +11 -42
- package/reference/claude-config/rules/shared-types.md +10 -48
- package/reference/claude-config/rules/task-tracking.md +11 -47
- package/reference/claude-config/rules/ui.md +11 -200
- package/reference/claude-config/rules/vibe.md +5 -229
- package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +83 -83
- package/reference/claude-config/sync-notes/2026-05-15-om-skill-rename-and-write-family.md +2 -2
- package/reference/claude-config/sync-notes/2026-05-17-sdk-boundary-consolidation.md +33 -0
- package/reference/cli.mdx +1107 -808
- package/reference/rules/active-change-index.md +83 -0
- package/reference/rules/agent-start-here.md +280 -0
- package/reference/rules/deployment.md +60 -0
- package/reference/rules/error-handling.md +59 -0
- package/reference/rules/execution.md +43 -0
- package/reference/rules/frontend.md +46 -0
- package/reference/rules/observability.md +34 -0
- package/reference/rules/operations.md +85 -0
- package/reference/rules/organization-model.md +119 -0
- package/reference/rules/organization-os.md +118 -0
- package/reference/rules/package-taxonomy.md +36 -0
- package/reference/rules/platform.md +45 -0
- package/reference/rules/shared-types.md +52 -0
- package/reference/rules/task-tracking.md +50 -0
- package/reference/rules/ui.md +203 -0
- package/reference/rules/vibe.md +238 -0
- package/reference/scaffold/core/organization-graph.mdx +4 -5
- package/reference/scaffold/core/organization-model.mdx +1 -1
- package/reference/scaffold/recipes/customize-crm-actions.md +45 -46
- package/reference/scaffold/recipes/extend-crm.md +253 -255
- package/reference/scaffold/recipes/index.md +43 -44
- package/reference/scaffold/reference/contracts.md +990 -1065
|
@@ -1,258 +1,256 @@
|
|
|
1
1
|
<!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
|
|
2
2
|
<!-- Regenerate: pnpm scaffold:sync -->
|
|
3
3
|
|
|
4
|
-
---
|
|
5
|
-
title: Build and Extend CRM
|
|
6
|
-
description: Map the CRM platform primitives available to SDK projects: shared UI pages, sidebar composition, data hooks, action definitions, workflow adapters, contracts, and org-model extension boundaries.
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Build and Extend CRM
|
|
10
|
-
|
|
11
|
-
Use this recipe when a downstream project wants to build on the shared CRM instead of forking it.
|
|
12
|
-
|
|
13
|
-
Good trigger phrases:
|
|
14
|
-
|
|
15
|
-
- "Add a CRM reports page."
|
|
16
|
-
- "Build a custom deal workspace."
|
|
17
|
-
- "Read and update deals from a workflow."
|
|
18
|
-
- "Add a Send Quote button."
|
|
19
|
-
- "Change the CRM pipeline stages for this business."
|
|
20
|
-
|
|
21
|
-
CRM is a layered platform surface, not one component:
|
|
22
|
-
|
|
23
|
-
- **Organization OS:** System access, sales pipeline semantics, quick access, and labels live in the organization model.
|
|
24
|
-
- **Shared UI:** CRM pages, sidebars, workbench panels, overview widgets, and Kanban/detail components live in `@elevasis/ui`.
|
|
25
|
-
- **Headless hooks:** deal, company, contact, note, task, list, transition, and action hooks live under `@elevasis/ui/hooks`.
|
|
26
|
-
- **Action system:** `ActionDef`, `
|
|
27
|
-
- **Workflow adapters:** `crm` and `acqDb` from `@elevasis/sdk/worker` let workflows read and mutate CRM/acquisition data through platform tools.
|
|
28
|
-
- **Contracts:** generated contract docs expose the current CRM shapes in `node_modules/@elevasis/sdk/reference/scaffold/reference/contracts.md`.
|
|
29
|
-
|
|
30
|
-
## Decision Table
|
|
31
|
-
|
|
32
|
-
| User wants
|
|
33
|
-
|
|
|
34
|
-
| Change CRM System availability, labels, pipeline stages, or resource descriptors | `core/config/organization-model.ts`
|
|
35
|
-
| Add CRM sidebar nav or a CRM route
|
|
36
|
-
| Wrap a shared CRM page with project chrome
|
|
37
|
-
| Build a custom deal page
|
|
38
|
-
| Add, hide, or replace deal action buttons
|
|
39
|
-
| Read or mutate CRM data inside a workflow
|
|
40
|
-
| Add a new persisted CRM column or table
|
|
41
|
-
|
|
42
|
-
## Published CRM Surfaces
|
|
43
|
-
|
|
44
|
-
| Surface
|
|
45
|
-
|
|
|
46
|
-
| `crmManifest`, `CRM_ITEMS`, `CrmSidebar`, `CrmSidebarTop`, `CrmSidebarMiddle`
|
|
47
|
-
| `CrmOverview`, `DealsListPage`, `DealDetailPage`, `CompanyDetailPage`
|
|
48
|
-
| `MyTasksPanel`, `SavedViewsPanel`, `QuickCreateActions`
|
|
49
|
-
| `PipelineFunnelWidget`, `ActivityFeedWidget`, `MetricsStrip`
|
|
50
|
-
| `KanbanBoard`, `DealKanbanCard`, `DealDrawer`
|
|
51
|
-
| `useDeals`, `useDealDetail`, `useTransitionItem`, `useExecuteAction`, `useDealNotes`, `useDealTasks` | `@elevasis/ui/hooks`
|
|
52
|
-
| `useCompanies`, `useContacts`, `useLists`, `useBatchTelemetry`
|
|
53
|
-
| `ElevasisUIProvider`, `ElevasisCoreProvider`, `useElevasisServices`
|
|
54
|
-
| `ActionDef`, `
|
|
55
|
-
| `crm`, `acqDb`
|
|
56
|
-
|
|
57
|
-
Read the generated contracts before changing typed boundaries:
|
|
58
|
-
|
|
59
|
-
`node_modules/@elevasis/sdk/reference/scaffold/reference/contracts.md`
|
|
60
|
-
|
|
61
|
-
Look for the **CRM Platform Primitives** section. It includes deal stages, deal rows, task shapes, API schemas, action definitions, and the focused CRM workflow adapter map. The broader acquisition/list adapter maps live under **Lead Gen Platform Primitives**.
|
|
62
|
-
|
|
63
|
-
Deal list and detail responses include a server-derived `priority` object. Use `deal.priority.bucketKey`, `rank`, `label`, `reason`, `latestActivityAt`, and `nextActionAt` when composing custom deal workspaces or workflow-side follow-up logic instead of re-deriving priority from `updated_at`.
|
|
64
|
-
|
|
65
|
-
## 1. Extend CRM Navigation or Sidebar
|
|
66
|
-
|
|
67
|
-
For a simple nav addition, extend `CRM_ITEMS` and override the CRM system manifest:
|
|
68
|
-
|
|
69
|
-
```tsx
|
|
70
|
-
// ui/src/routes/__root.tsx
|
|
71
|
-
import { crmManifest, CRM_ITEMS, CrmSidebar, CrmSidebarMiddle } from '@elevasis/ui/features/crm'
|
|
72
|
-
import type { SystemModule } from '@elevasis/ui/provider'
|
|
73
|
-
import type { NavItem } from '@elevasis/ui/layout'
|
|
74
|
-
import { IconFileText } from '@tabler/icons-react'
|
|
75
|
-
|
|
76
|
-
const customCrmItems: NavItem[] = [
|
|
77
|
-
...CRM_ITEMS,
|
|
78
|
-
{ label: 'Reports', to: '/crm/reports', icon: IconFileText, exact: false }
|
|
79
|
-
]
|
|
80
|
-
|
|
81
|
-
const CustomCrmSidebar = () => (
|
|
82
|
-
<CrmSidebar>
|
|
83
|
-
<CrmSidebarMiddle items={customCrmItems} />
|
|
84
|
-
</CrmSidebar>
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
export const customCrmManifest: SystemModule = {
|
|
88
|
-
...crmManifest,
|
|
89
|
-
sidebar: CustomCrmSidebar
|
|
90
|
-
}
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Then replace `crmManifest` with `customCrmManifest` in the local `SYSTEM_MANIFESTS` array and add the matching route under `ui/src/routes/crm/`.
|
|
94
|
-
|
|
95
|
-
For structural changes, compose `CrmSidebarTop`, `SubshellNavList`, `SubshellSidebarSection`, `MyTasksPanel`, and `QuickCreateActions`. The full sidebar decision tree lives in `node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md`.
|
|
96
|
-
|
|
97
|
-
## 2. Wrap Shared CRM Pages
|
|
98
|
-
|
|
99
|
-
If the shared page is close, keep it and wrap it:
|
|
100
|
-
|
|
101
|
-
```tsx
|
|
102
|
-
// ui/src/routes/crm/deals.index.tsx
|
|
103
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
104
|
-
import { DealsListPage } from '@elevasis/ui/features/crm'
|
|
105
|
-
import { Stack } from '@mantine/core'
|
|
106
|
-
import { ProjectAnnouncementBanner } from '@/lib/components/ProjectAnnouncementBanner'
|
|
107
|
-
|
|
108
|
-
export const Route = createFileRoute('/crm/deals/')({
|
|
109
|
-
component: DealsRoute
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
function DealsRoute() {
|
|
113
|
-
return (
|
|
114
|
-
<Stack gap={0}>
|
|
115
|
-
<ProjectAnnouncementBanner context="crm-deals" />
|
|
116
|
-
<DealsListPage />
|
|
117
|
-
</Stack>
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Use the same pattern for `CrmOverview`, `DealDetailPage`, and `CompanyDetailPage`.
|
|
123
|
-
|
|
124
|
-
## 3. Build a Custom Deal Page
|
|
125
|
-
|
|
126
|
-
When the project needs custom layout or additional workflows, use the hooks directly:
|
|
127
|
-
|
|
128
|
-
```tsx
|
|
129
|
-
import { Button, Group, Stack, Textarea } from '@mantine/core'
|
|
130
|
-
import { useState } from 'react'
|
|
131
|
-
import { useDealDetail, useDealNotes, useCreateDealNote, useExecuteAction } from '@elevasis/ui/hooks'
|
|
132
|
-
|
|
133
|
-
export function CustomDealWorkspace({ dealId }: { dealId: string }) {
|
|
134
|
-
const { data: deal, isLoading } = useDealDetail(dealId)
|
|
135
|
-
const { data: notes = [] } = useDealNotes(dealId)
|
|
136
|
-
const createNote = useCreateDealNote()
|
|
137
|
-
const executeAction = useExecuteAction({ dealId })
|
|
138
|
-
const [body, setBody] = useState('')
|
|
139
|
-
|
|
140
|
-
if (isLoading) return null
|
|
141
|
-
if (!deal) return <div>Deal not found</div>
|
|
142
|
-
|
|
143
|
-
return (
|
|
144
|
-
<Stack>
|
|
145
|
-
<h1>{deal.contact_email}</h1>
|
|
146
|
-
<Group>
|
|
147
|
-
<Button onClick={() => executeAction.mutate({ key: 'move_to_proposal' })}>
|
|
148
|
-
Move to Proposal
|
|
149
|
-
</Button>
|
|
150
|
-
</Group>
|
|
151
|
-
<Textarea value={body} onChange={(event) => setBody(event.currentTarget.value)} />
|
|
152
|
-
<Button onClick={() => createNote.mutate({ dealId, body })}>Add Note</Button>
|
|
153
|
-
<pre>{JSON.stringify(notes, null, 2)}</pre>
|
|
154
|
-
</Stack>
|
|
155
|
-
)
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
`useExecuteAction` is for platform-known/default action keys. Start custom action UI with the shared `crmActions` provider path; when a project-owned workflow is outside that server-dispatched action set, call `/execute` or `/execute-async` through `useElevasisServices`, or follow [customize-crm-actions.md](customize-crm-actions.md).
|
|
160
|
-
|
|
161
|
-
## 4. Read and Mutate CRM Data in Workflows
|
|
162
|
-
|
|
163
|
-
Inside deployed workflows, use worker adapters instead of browser hooks or direct database access:
|
|
164
|
-
|
|
165
|
-
```ts
|
|
166
|
-
// operations/src/sales/follow-up-stale-deals.ts
|
|
167
|
-
import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
168
|
-
import { crm } from '@elevasis/sdk/worker'
|
|
169
|
-
import { resourceDescriptors } from '@core/config/organization-model'
|
|
170
|
-
import { z } from 'zod'
|
|
171
|
-
|
|
172
|
-
const inputSchema = z.object({
|
|
173
|
-
stage: z.string().default('proposal')
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
const outputSchema = z.object({
|
|
177
|
-
touched: z.number()
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
export const followUpStaleDealsWorkflow: WorkflowDefinition = {
|
|
181
|
-
config: {
|
|
182
|
-
resource: resourceDescriptors.followUpStaleDeals,
|
|
183
|
-
resourceId: resourceDescriptors.followUpStaleDeals.id,
|
|
184
|
-
name: 'Follow Up Stale Deals',
|
|
185
|
-
type: resourceDescriptors.followUpStaleDeals.kind,
|
|
186
|
-
version: '1.0.0',
|
|
187
|
-
status: 'dev',
|
|
188
|
-
},
|
|
189
|
-
contract: { inputSchema, outputSchema },
|
|
190
|
-
steps: {
|
|
191
|
-
followUp: {
|
|
192
|
-
id: 'followUp',
|
|
193
|
-
name: 'Follow Up',
|
|
194
|
-
inputSchema,
|
|
195
|
-
outputSchema,
|
|
196
|
-
next: null,
|
|
197
|
-
handler: async (input) => {
|
|
198
|
-
const deals = await crm.listDeals({ stage: input.stage })
|
|
199
|
-
|
|
200
|
-
for (const deal of deals) {
|
|
201
|
-
if (!['follow_up_due', 'stale'].includes(deal.priority.bucketKey)) continue
|
|
202
|
-
|
|
203
|
-
await crm.createDealTask({
|
|
204
|
-
dealId: deal.id,
|
|
205
|
-
title: 'Follow up',
|
|
206
|
-
kind: 'email'
|
|
207
|
-
})
|
|
208
|
-
await crm.recordActivity({
|
|
209
|
-
dealId: deal.id,
|
|
210
|
-
type: 'workflow.follow_up_task_created',
|
|
211
|
-
title: 'Follow-up task created',
|
|
212
|
-
payload: { workflow: 'follow-up-stale-deals' }
|
|
213
|
-
})
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return { touched: deals.length }
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
entryPoint: 'followUp'
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
Use `crm` for focused CRM deal reads, notes, tasks, activity, and cleanup. Use `acqDb` when the workflow needs the broader acquisition substrate: companies, contacts, lists, list-stage transitions, enrichment data, social posts, or lower-level deal sync methods.
|
|
225
|
-
|
|
226
|
-
## 5. Customize Pipeline Semantics
|
|
227
|
-
|
|
228
|
-
CRM System identity is `sales.crm`, but the organization-model domain is `sales`.
|
|
229
|
-
|
|
230
|
-
For stage labels or stage sets, update the project model:
|
|
231
|
-
|
|
232
|
-
`core/config/organization-model.ts`
|
|
233
|
-
|
|
234
|
-
Keep these boundaries straight:
|
|
235
|
-
|
|
236
|
-
- Org-model sales pipelines describe business semantics.
|
|
237
|
-
- `DealStage` and platform action defaults describe the current shared platform deal state vocabulary.
|
|
238
|
-
- UI wrappers can relabel and route around shared surfaces, but changing persisted platform stages requires coordinated core/API/UI updates.
|
|
239
|
-
- Do not add `sales.actions` to the org model in v1. Deal action customization is covered by [customize-crm-actions.md](customize-crm-actions.md).
|
|
240
|
-
|
|
241
|
-
## Verify
|
|
242
|
-
|
|
243
|
-
Run the checks for the surfaces you touched:
|
|
244
|
-
|
|
245
|
-
```bash
|
|
246
|
-
pnpm -C ui run check
|
|
247
|
-
pnpm -C operations run check
|
|
248
|
-
pnpm -C operations exec elevasis-sdk check
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
If you changed platform-level CRM contracts in the monorepo, the platform maintainer must also regenerate and verify scaffold output:
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
pnpm scaffold:sync
|
|
255
|
-
pnpm scaffold:verify
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
|
|
4
|
+
---
|
|
5
|
+
title: Build and Extend CRM
|
|
6
|
+
description: Map the CRM platform primitives available to SDK projects: shared UI pages, sidebar composition, data hooks, action definitions, workflow adapters, contracts, and org-model extension boundaries.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Build and Extend CRM
|
|
10
|
+
|
|
11
|
+
Use this recipe when a downstream project wants to build on the shared CRM instead of forking it.
|
|
12
|
+
|
|
13
|
+
Good trigger phrases:
|
|
14
|
+
|
|
15
|
+
- "Add a CRM reports page."
|
|
16
|
+
- "Build a custom deal workspace."
|
|
17
|
+
- "Read and update deals from a workflow."
|
|
18
|
+
- "Add a Send Quote button."
|
|
19
|
+
- "Change the CRM pipeline stages for this business."
|
|
20
|
+
|
|
21
|
+
CRM is a layered platform surface, not one component:
|
|
22
|
+
|
|
23
|
+
- **Organization OS:** System access, sales pipeline semantics, quick access, and labels live in the organization model.
|
|
24
|
+
- **Shared UI:** CRM pages, sidebars, workbench panels, overview widgets, and Kanban/detail components live in `@elevasis/ui`.
|
|
25
|
+
- **Headless hooks:** deal, company, contact, note, task, list, transition, and action hooks live under `@elevasis/ui/hooks`.
|
|
26
|
+
- **Action system:** `ActionDef`, `deriveActions`, and the caller-supplied provider-level `crmActions` catalog configure deal actions. The published `@elevasis/sdk` surface ships no default Elevasis action catalog -- projects supply their own `ActionDef[]`.
|
|
27
|
+
- **Workflow adapters:** `crm` and `acqDb` from `@elevasis/sdk/worker` let workflows read and mutate CRM/acquisition data through platform tools.
|
|
28
|
+
- **Contracts:** generated contract docs expose the current CRM shapes in `node_modules/@elevasis/sdk/reference/scaffold/reference/contracts.md`.
|
|
29
|
+
|
|
30
|
+
## Decision Table
|
|
31
|
+
|
|
32
|
+
| User wants | Start here | Notes |
|
|
33
|
+
| -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| Change CRM System availability, labels, pipeline stages, or resource descriptors | `core/config/organization-model.ts` | Treat this as Organization OS work. Use the project's configure ceremony if available. |
|
|
35
|
+
| Add CRM sidebar nav or a CRM route | `@elevasis/ui/features/crm` and `node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md` | Prefer manifest/sidebar composition. Do not fork shared source first. |
|
|
36
|
+
| Wrap a shared CRM page with project chrome | `DealsListPage`, `DealDetailPage`, `CrmOverview` from `@elevasis/ui/features/crm` | Keep route files thin and put project-specific logic in local feature modules. |
|
|
37
|
+
| Build a custom deal page | `useDealDetail`, `useDealNotes`, `useDealTasks`, `useExecuteAction` from `@elevasis/ui/hooks` | Use hooks for platform data and compose your own UI. |
|
|
38
|
+
| Add, hide, or replace deal action buttons | [customize-crm-actions.md](customize-crm-actions.md) | Start with the shared `crmActions` provider path; use project-owned UI when a custom workflow path is outside platform-known/default action dispatch constraints. |
|
|
39
|
+
| Read or mutate CRM data inside a workflow | `crm` or `acqDb` from `@elevasis/sdk/worker` | `organizationId` is injected server-side by the platform dispatcher. Do not pass it from workflow code. |
|
|
40
|
+
| Add a new persisted CRM column or table | Platform/API migration work, not just scaffold work | Update DB, core schemas/types, API service/handlers, hooks, docs, and scaffold contracts together. |
|
|
41
|
+
|
|
42
|
+
## Published CRM Surfaces
|
|
43
|
+
|
|
44
|
+
| Surface | Import from | Use for |
|
|
45
|
+
| ---------------------------------------------------------------------------------------------------- | --------------------------- | ---------------------------------------------------- |
|
|
46
|
+
| `crmManifest`, `CRM_ITEMS`, `CrmSidebar`, `CrmSidebarTop`, `CrmSidebarMiddle` | `@elevasis/ui/features/crm` | Feature registration and sidebar composition |
|
|
47
|
+
| `CrmOverview`, `DealsListPage`, `DealDetailPage`, `CompanyDetailPage` | `@elevasis/ui/features/crm` | Shared CRM pages you can route to or wrap |
|
|
48
|
+
| `MyTasksPanel`, `SavedViewsPanel`, `QuickCreateActions` | `@elevasis/ui/features/crm` | Workbench/sidebar panels for custom CRM sidebars |
|
|
49
|
+
| `PipelineFunnelWidget`, `ActivityFeedWidget`, `MetricsStrip` | `@elevasis/ui/features/crm` | Overview widgets for custom dashboards |
|
|
50
|
+
| `KanbanBoard`, `DealKanbanCard`, `DealDrawer` | `@elevasis/ui/components` | Lower-level CRM deal UI primitives |
|
|
51
|
+
| `useDeals`, `useDealDetail`, `useTransitionItem`, `useExecuteAction`, `useDealNotes`, `useDealTasks` | `@elevasis/ui/hooks` | Headless deal and task data access |
|
|
52
|
+
| `useCompanies`, `useContacts`, `useLists`, `useBatchTelemetry` | `@elevasis/ui/hooks` | Acquisition substrate data access |
|
|
53
|
+
| `ElevasisUIProvider`, `ElevasisCoreProvider`, `useElevasisServices` | `@elevasis/ui/provider` | Provider setup, API access, and organization context |
|
|
54
|
+
| `ActionDef`, `deriveActions` | `@elevasis/sdk` | Deal action configuration and render-time derivation |
|
|
55
|
+
| `crm`, `acqDb` | `@elevasis/sdk/worker` | Workflow-side CRM/acquisition platform adapters |
|
|
56
|
+
|
|
57
|
+
Read the generated contracts before changing typed boundaries:
|
|
58
|
+
|
|
59
|
+
`node_modules/@elevasis/sdk/reference/scaffold/reference/contracts.md`
|
|
60
|
+
|
|
61
|
+
Look for the **CRM Platform Primitives** section. It includes deal stages, deal rows, task shapes, API schemas, action definitions, and the focused CRM workflow adapter map. The broader acquisition/list adapter maps live under **Lead Gen Platform Primitives**.
|
|
62
|
+
|
|
63
|
+
Deal list and detail responses include a server-derived `priority` object. Use `deal.priority.bucketKey`, `rank`, `label`, `reason`, `latestActivityAt`, and `nextActionAt` when composing custom deal workspaces or workflow-side follow-up logic instead of re-deriving priority from `updated_at`.
|
|
64
|
+
|
|
65
|
+
## 1. Extend CRM Navigation or Sidebar
|
|
66
|
+
|
|
67
|
+
For a simple nav addition, extend `CRM_ITEMS` and override the CRM system manifest:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
// ui/src/routes/__root.tsx
|
|
71
|
+
import { crmManifest, CRM_ITEMS, CrmSidebar, CrmSidebarMiddle } from '@elevasis/ui/features/crm'
|
|
72
|
+
import type { SystemModule } from '@elevasis/ui/provider'
|
|
73
|
+
import type { NavItem } from '@elevasis/ui/layout'
|
|
74
|
+
import { IconFileText } from '@tabler/icons-react'
|
|
75
|
+
|
|
76
|
+
const customCrmItems: NavItem[] = [
|
|
77
|
+
...CRM_ITEMS,
|
|
78
|
+
{ label: 'Reports', to: '/crm/reports', icon: IconFileText, exact: false }
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
const CustomCrmSidebar = () => (
|
|
82
|
+
<CrmSidebar>
|
|
83
|
+
<CrmSidebarMiddle items={customCrmItems} />
|
|
84
|
+
</CrmSidebar>
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
export const customCrmManifest: SystemModule = {
|
|
88
|
+
...crmManifest,
|
|
89
|
+
sidebar: CustomCrmSidebar
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then replace `crmManifest` with `customCrmManifest` in the local `SYSTEM_MANIFESTS` array and add the matching route under `ui/src/routes/crm/`.
|
|
94
|
+
|
|
95
|
+
For structural changes, compose `CrmSidebarTop`, `SubshellNavList`, `SubshellSidebarSection`, `MyTasksPanel`, and `QuickCreateActions`. The full sidebar decision tree lives in `node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md`.
|
|
96
|
+
|
|
97
|
+
## 2. Wrap Shared CRM Pages
|
|
98
|
+
|
|
99
|
+
If the shared page is close, keep it and wrap it:
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
// ui/src/routes/crm/deals.index.tsx
|
|
103
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
104
|
+
import { DealsListPage } from '@elevasis/ui/features/crm'
|
|
105
|
+
import { Stack } from '@mantine/core'
|
|
106
|
+
import { ProjectAnnouncementBanner } from '@/lib/components/ProjectAnnouncementBanner'
|
|
107
|
+
|
|
108
|
+
export const Route = createFileRoute('/crm/deals/')({
|
|
109
|
+
component: DealsRoute
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
function DealsRoute() {
|
|
113
|
+
return (
|
|
114
|
+
<Stack gap={0}>
|
|
115
|
+
<ProjectAnnouncementBanner context="crm-deals" />
|
|
116
|
+
<DealsListPage />
|
|
117
|
+
</Stack>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use the same pattern for `CrmOverview`, `DealDetailPage`, and `CompanyDetailPage`.
|
|
123
|
+
|
|
124
|
+
## 3. Build a Custom Deal Page
|
|
125
|
+
|
|
126
|
+
When the project needs custom layout or additional workflows, use the hooks directly:
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { Button, Group, Stack, Textarea } from '@mantine/core'
|
|
130
|
+
import { useState } from 'react'
|
|
131
|
+
import { useDealDetail, useDealNotes, useCreateDealNote, useExecuteAction } from '@elevasis/ui/hooks'
|
|
132
|
+
|
|
133
|
+
export function CustomDealWorkspace({ dealId }: { dealId: string }) {
|
|
134
|
+
const { data: deal, isLoading } = useDealDetail(dealId)
|
|
135
|
+
const { data: notes = [] } = useDealNotes(dealId)
|
|
136
|
+
const createNote = useCreateDealNote()
|
|
137
|
+
const executeAction = useExecuteAction({ dealId })
|
|
138
|
+
const [body, setBody] = useState('')
|
|
139
|
+
|
|
140
|
+
if (isLoading) return null
|
|
141
|
+
if (!deal) return <div>Deal not found</div>
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<Stack>
|
|
145
|
+
<h1>{deal.contact_email}</h1>
|
|
146
|
+
<Group>
|
|
147
|
+
<Button onClick={() => executeAction.mutate({ key: 'move_to_proposal' })}>
|
|
148
|
+
Move to Proposal
|
|
149
|
+
</Button>
|
|
150
|
+
</Group>
|
|
151
|
+
<Textarea value={body} onChange={(event) => setBody(event.currentTarget.value)} />
|
|
152
|
+
<Button onClick={() => createNote.mutate({ dealId, body })}>Add Note</Button>
|
|
153
|
+
<pre>{JSON.stringify(notes, null, 2)}</pre>
|
|
154
|
+
</Stack>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`useExecuteAction` is for platform-known/default action keys. Start custom action UI with the shared `crmActions` provider path; when a project-owned workflow is outside that server-dispatched action set, call `/execute` or `/execute-async` through `useElevasisServices`, or follow [customize-crm-actions.md](customize-crm-actions.md).
|
|
160
|
+
|
|
161
|
+
## 4. Read and Mutate CRM Data in Workflows
|
|
162
|
+
|
|
163
|
+
Inside deployed workflows, use worker adapters instead of browser hooks or direct database access:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
// operations/src/sales/follow-up-stale-deals.ts
|
|
167
|
+
import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
168
|
+
import { crm } from '@elevasis/sdk/worker'
|
|
169
|
+
import { resourceDescriptors } from '@core/config/organization-model'
|
|
170
|
+
import { z } from 'zod'
|
|
171
|
+
|
|
172
|
+
const inputSchema = z.object({
|
|
173
|
+
stage: z.string().default('proposal')
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
const outputSchema = z.object({
|
|
177
|
+
touched: z.number()
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
export const followUpStaleDealsWorkflow: WorkflowDefinition = {
|
|
181
|
+
config: {
|
|
182
|
+
resource: resourceDescriptors.followUpStaleDeals,
|
|
183
|
+
resourceId: resourceDescriptors.followUpStaleDeals.id,
|
|
184
|
+
name: 'Follow Up Stale Deals',
|
|
185
|
+
type: resourceDescriptors.followUpStaleDeals.kind,
|
|
186
|
+
version: '1.0.0',
|
|
187
|
+
status: 'dev',
|
|
188
|
+
},
|
|
189
|
+
contract: { inputSchema, outputSchema },
|
|
190
|
+
steps: {
|
|
191
|
+
followUp: {
|
|
192
|
+
id: 'followUp',
|
|
193
|
+
name: 'Follow Up',
|
|
194
|
+
inputSchema,
|
|
195
|
+
outputSchema,
|
|
196
|
+
next: null,
|
|
197
|
+
handler: async (input) => {
|
|
198
|
+
const deals = await crm.listDeals({ stage: input.stage })
|
|
199
|
+
|
|
200
|
+
for (const deal of deals) {
|
|
201
|
+
if (!['follow_up_due', 'stale'].includes(deal.priority.bucketKey)) continue
|
|
202
|
+
|
|
203
|
+
await crm.createDealTask({
|
|
204
|
+
dealId: deal.id,
|
|
205
|
+
title: 'Follow up',
|
|
206
|
+
kind: 'email'
|
|
207
|
+
})
|
|
208
|
+
await crm.recordActivity({
|
|
209
|
+
dealId: deal.id,
|
|
210
|
+
type: 'workflow.follow_up_task_created',
|
|
211
|
+
title: 'Follow-up task created',
|
|
212
|
+
payload: { workflow: 'follow-up-stale-deals' }
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return { touched: deals.length }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
entryPoint: 'followUp'
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Use `crm` for focused CRM deal reads, notes, tasks, activity, and cleanup. Use `acqDb` when the workflow needs the broader acquisition substrate: companies, contacts, lists, list-stage transitions, enrichment data, social posts, or lower-level deal sync methods.
|
|
225
|
+
|
|
226
|
+
## 5. Customize Pipeline Semantics
|
|
227
|
+
|
|
228
|
+
CRM System identity is `sales.crm`, but the organization-model domain is `sales`.
|
|
229
|
+
|
|
230
|
+
For stage labels or stage sets, update the project model:
|
|
231
|
+
|
|
232
|
+
`core/config/organization-model.ts`
|
|
233
|
+
|
|
234
|
+
Keep these boundaries straight:
|
|
235
|
+
|
|
236
|
+
- Org-model sales pipelines describe business semantics.
|
|
237
|
+
- `DealStage` and platform action defaults describe the current shared platform deal state vocabulary.
|
|
238
|
+
- UI wrappers can relabel and route around shared surfaces, but changing persisted platform stages requires coordinated core/API/UI updates.
|
|
239
|
+
- Do not add `sales.actions` to the org model in v1. Deal action customization is covered by [customize-crm-actions.md](customize-crm-actions.md).
|
|
240
|
+
|
|
241
|
+
## Verify
|
|
242
|
+
|
|
243
|
+
Run the checks for the surfaces you touched:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
pnpm -C ui run check
|
|
247
|
+
pnpm -C operations run check
|
|
248
|
+
pnpm -C operations exec elevasis-sdk check
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
If you changed platform-level CRM contracts in the monorepo, the platform maintainer must also regenerate and verify scaffold output:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pnpm scaffold:sync
|
|
255
|
+
pnpm scaffold:verify
|
|
256
|
+
```
|
|
@@ -1,51 +1,50 @@
|
|
|
1
1
|
<!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
|
|
2
2
|
<!-- Regenerate: pnpm scaffold:sync -->
|
|
3
3
|
|
|
4
|
-
---
|
|
5
|
-
title: Pathway Recipes
|
|
6
|
-
description: Terse end-to-end walkthroughs for the three most common authoring tasks -- adding a system, adding a resource, and gating access.
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Pathway Recipes
|
|
10
|
-
|
|
11
|
-
Three sequential walkthroughs for common authoring tasks. Each recipe links into the reference docs rather than duplicating them.
|
|
12
|
-
|
|
13
|
-
Before starting, read [glossary.md](../reference/glossary.md) to disambiguate overloaded terms (System, Resource, systemId, Settings asymmetry, Topology).
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Recipes
|
|
18
|
-
|
|
4
|
+
---
|
|
5
|
+
title: Pathway Recipes
|
|
6
|
+
description: Terse end-to-end walkthroughs for the three most common authoring tasks -- adding a system, adding a resource, and gating access.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pathway Recipes
|
|
10
|
+
|
|
11
|
+
Three sequential walkthroughs for common authoring tasks. Each recipe links into the reference docs rather than duplicating them.
|
|
12
|
+
|
|
13
|
+
Before starting, read [glossary.md](../reference/glossary.md) to disambiguate overloaded terms (System, Resource, systemId, Settings asymmetry, Topology).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Recipes
|
|
18
|
+
|
|
19
19
|
**[Add an OM-Backed System](add-a-feature.md)**
|
|
20
20
|
You want a new system with cohesive Organization Model semantics, executable resources, and optional UI. Covers Systems, System-owned ontology and config, Resource descriptors with `title`, `description`, `resource.ontology.actions`, `primaryAction`, `codeRefs`, OM topology, runtime assembly, manifests, routes, guards, tests, and compatibility notes for old `System.content` consumers.
|
|
21
|
-
|
|
22
|
-
**[Add a Resource](add-a-resource.md)**
|
|
23
|
-
You want a new workflow or agent deployed to the platform. Covers OM Resource descriptor authoring, descriptor-backed `WorkflowDefinition` binding, `DeploymentSpec` assembly, relationship declarations, and CLI verification.
|
|
24
|
-
|
|
25
|
-
**[Gate by System or Admin](gate-by-feature-or-admin.md)**
|
|
26
|
-
You want to restrict a route, nav item, or UI element by system flag or admin role. Covers the decision table, `SystemGuard`, `AdminGuard`, nav-entry visibility fields, per-member system overrides, and the settings-asymmetry gotcha.
|
|
27
|
-
|
|
28
|
-
**[Build and Extend CRM](extend-crm.md)**
|
|
29
|
-
You want to build on the shared CRM without forking it: add CRM routes, compose sidebars/pages, use deal/company/contact hooks, mutate CRM data from workflows, or understand which contracts and adapters form the extension surface.
|
|
30
|
-
|
|
31
|
-
**[Build and Extend Lead Gen](extend-lead-gen.md)**
|
|
32
|
-
You want to build on the shared lead-gen system without forking it: add lead-gen routes, compose sidebars/pages, use list/company/contact/artifact hooks, mutate list data from workflows, or understand which contracts and adapters form the extension surface.
|
|
33
|
-
|
|
34
|
-
**[Customize CRM Actions](customize-crm-actions.md)**
|
|
35
|
-
You want to add, hide, or replace CRM deal action buttons, configure the shared `crmActions` provider path, or call a project-owned workflow from custom UI when server-side action dispatch constraints require it. Covers `ActionDef`, `
|
|
36
|
-
|
|
37
|
-
**[Customize Knowledge Browser](customize-knowledge-browser.md)**
|
|
38
|
-
You want to mount, extend, or replace the default Knowledge Browser. Covers the three customization tiers (default manifest mount, sidebar composition via `KnowledgeSidebarMiddle` + `KNOWLEDGE_ITEMS`, and direct query access via `@elevasis/core/knowledge`), the one-line `vite.config.ts` plugin add (`knowledgePlugin()` from `@elevasis/ui/vite-plugin-knowledge`), and the CSS import requirement.
|
|
39
|
-
|
|
21
|
+
|
|
22
|
+
**[Add a Resource](add-a-resource.md)**
|
|
23
|
+
You want a new workflow or agent deployed to the platform. Covers OM Resource descriptor authoring, descriptor-backed `WorkflowDefinition` binding, `DeploymentSpec` assembly, relationship declarations, and CLI verification.
|
|
24
|
+
|
|
25
|
+
**[Gate by System or Admin](gate-by-feature-or-admin.md)**
|
|
26
|
+
You want to restrict a route, nav item, or UI element by system flag or admin role. Covers the decision table, `SystemGuard`, `AdminGuard`, nav-entry visibility fields, per-member system overrides, and the settings-asymmetry gotcha.
|
|
27
|
+
|
|
28
|
+
**[Build and Extend CRM](extend-crm.md)**
|
|
29
|
+
You want to build on the shared CRM without forking it: add CRM routes, compose sidebars/pages, use deal/company/contact hooks, mutate CRM data from workflows, or understand which contracts and adapters form the extension surface.
|
|
30
|
+
|
|
31
|
+
**[Build and Extend Lead Gen](extend-lead-gen.md)**
|
|
32
|
+
You want to build on the shared lead-gen system without forking it: add lead-gen routes, compose sidebars/pages, use list/company/contact/artifact hooks, mutate list data from workflows, or understand which contracts and adapters form the extension surface.
|
|
33
|
+
|
|
34
|
+
**[Customize CRM Actions](customize-crm-actions.md)**
|
|
35
|
+
You want to add, hide, or replace CRM deal action buttons, configure the shared `crmActions` provider path, or call a project-owned workflow from custom UI when server-side action dispatch constraints require it. Covers `ActionDef`, the caller-supplied `crmActions` catalog, provider wiring, and the current v1 boundary for custom action dispatch.
|
|
36
|
+
|
|
37
|
+
**[Customize Knowledge Browser](customize-knowledge-browser.md)**
|
|
38
|
+
You want to mount, extend, or replace the default Knowledge Browser. Covers the three customization tiers (default manifest mount, sidebar composition via `KnowledgeSidebarMiddle` + `KNOWLEDGE_ITEMS`, and direct query access via `@elevasis/core/knowledge`), the one-line `vite.config.ts` plugin add (`knowledgePlugin()` from `@elevasis/ui/vite-plugin-knowledge`), and the CSS import requirement.
|
|
39
|
+
|
|
40
40
|
**[Query the Knowledge Graph](query-the-knowledge-graph.md)**
|
|
41
41
|
You want to browse, inspect, or traverse the OrganizationModel knowledge graph from the command line. Covers the three verbs (`knowledge:ls`, `knowledge:cat`, `knowledge:graph`), all six mount axes (`/by-system/`, `/by-ontology/`, `/by-kind/`, `/by-owner/`, `/graph/.../governs/`, `/graph/.../governed-by/`), dual-CLI invocation patterns (`elevasis-sdk` for external projects, `elevasis` for the monorepo), JSON output shapes, and the Windows/MSYS PowerShell gotcha.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Reference docs these recipes link into
|
|
46
|
-
|
|
47
|
-
- [glossary.md](../reference/glossary.md) -- term disambiguation for System, Resource, systemId, Topology, Settings asymmetry
|
|
48
|
-
- [contracts.md](../reference/contracts.md) -- TypeScript shapes: `SystemModule`, `OrganizationModel`, CRM deal types, lead-gen list/member/artifact types, `CrmToolMap`, `LeadToolMap`, `ListToolMap`, `ActionDef`
|
|
49
|
-
- [feature-flags-and-gating.md](../ui/feature-flags-and-gating.md) -- full three-concept gating model
|
|
50
|
-
- [workflow-recipes.md](../operations/workflow-recipes.md) -- workflow anatomy, adapters, trigger patterns
|
|
51
|
-
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Reference docs these recipes link into
|
|
46
|
+
|
|
47
|
+
- [glossary.md](../reference/glossary.md) -- term disambiguation for System, Resource, systemId, Topology, Settings asymmetry
|
|
48
|
+
- [contracts.md](../reference/contracts.md) -- TypeScript shapes: `SystemModule`, `OrganizationModel`, CRM deal types, lead-gen list/member/artifact types, `CrmToolMap`, `LeadToolMap`, `ListToolMap`, `ActionDef`
|
|
49
|
+
- [feature-flags-and-gating.md](../ui/feature-flags-and-gating.md) -- full three-concept gating model
|
|
50
|
+
- [workflow-recipes.md](../operations/workflow-recipes.md) -- workflow anatomy, adapters, trigger patterns
|