@lead-routing/cli 0.5.0 → 0.6.1

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.
@@ -0,0 +1,36 @@
1
+ -- Fix: the existing @@unique constraint does not prevent duplicate rows
2
+ -- because PostgreSQL treats NULLs as distinct in unique indexes.
3
+
4
+ -- Step 1: Clean up any existing duplicate rows (keep the one with highest totalCount)
5
+ DELETE FROM "routing_daily_aggregates" a
6
+ USING "routing_daily_aggregates" b
7
+ WHERE a."orgId" = b."orgId"
8
+ AND a."date" = b."date"
9
+ AND a."objectType" IS NOT DISTINCT FROM b."objectType"
10
+ AND a."ruleId" IS NOT DISTINCT FROM b."ruleId"
11
+ AND a."pathLabel" IS NOT DISTINCT FROM b."pathLabel"
12
+ AND a."branchId" IS NOT DISTINCT FROM b."branchId"
13
+ AND a."teamId" IS NOT DISTINCT FROM b."teamId"
14
+ AND a."assigneeId" IS NOT DISTINCT FROM b."assigneeId"
15
+ AND a."id" < b."id";
16
+
17
+ -- Step 2: Create an immutable cast helper for the enum column.
18
+ -- PostgreSQL's built-in enum::text cast is only STABLE, not IMMUTABLE,
19
+ -- so it cannot be used directly in an index expression.
20
+ CREATE OR REPLACE FUNCTION immutable_object_type_text(val "SfdcObjectType")
21
+ RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$
22
+ SELECT val::text;
23
+ $$;
24
+
25
+ -- Step 3: Create a functional unique index using COALESCE to handle NULLs
26
+ CREATE UNIQUE INDEX "routing_daily_aggregates_dimension_key"
27
+ ON "routing_daily_aggregates" (
28
+ "orgId",
29
+ "date",
30
+ COALESCE("ruleId", ''),
31
+ COALESCE("pathLabel", ''),
32
+ COALESCE("branchId", ''),
33
+ COALESCE("teamId", ''),
34
+ COALESCE("assigneeId", ''),
35
+ COALESCE(immutable_object_type_text("objectType"), '')
36
+ );
@@ -0,0 +1,5 @@
1
+ -- AlterTable
2
+ ALTER TABLE "organizations" ADD COLUMN IF NOT EXISTS "licenseKey" TEXT;
3
+ ALTER TABLE "organizations" ADD COLUMN IF NOT EXISTS "licenseTier" TEXT;
4
+ ALTER TABLE "organizations" ADD COLUMN IF NOT EXISTS "licenseValidUntil" TIMESTAMP(3);
5
+ ALTER TABLE "organizations" ADD COLUMN IF NOT EXISTS "licenseActivatedAt" TIMESTAMP(3);
@@ -0,0 +1,36 @@
1
+ -- AlterTable
2
+ ALTER TABLE "routing_rules" ADD COLUMN "searchMaxRecords" INTEGER,
3
+ ADD COLUMN "searchBatchSize" INTEGER;
4
+
5
+ -- CreateTable
6
+ CREATE TABLE "bulk_search_runs" (
7
+ "id" TEXT NOT NULL,
8
+ "orgId" TEXT NOT NULL,
9
+ "ruleId" TEXT NOT NULL,
10
+ "status" TEXT NOT NULL DEFAULT 'RUNNING',
11
+ "recordsFound" INTEGER NOT NULL DEFAULT 0,
12
+ "recordsProcessed" INTEGER NOT NULL DEFAULT 0,
13
+ "recordsRouted" INTEGER NOT NULL DEFAULT 0,
14
+ "recordsFailed" INTEGER NOT NULL DEFAULT 0,
15
+ "recordsSkipped" INTEGER NOT NULL DEFAULT 0,
16
+ "error" TEXT,
17
+ "startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ "completedAt" TIMESTAMP(3),
19
+ "durationMs" INTEGER,
20
+ "maxRecords" INTEGER,
21
+ "batchSize" INTEGER,
22
+
23
+ CONSTRAINT "bulk_search_runs_pkey" PRIMARY KEY ("id")
24
+ );
25
+
26
+ -- CreateIndex
27
+ CREATE INDEX "bulk_search_runs_orgId_ruleId_idx" ON "bulk_search_runs"("orgId", "ruleId");
28
+
29
+ -- CreateIndex
30
+ CREATE INDEX "bulk_search_runs_ruleId_status_idx" ON "bulk_search_runs"("ruleId", "status");
31
+
32
+ -- AddForeignKey
33
+ ALTER TABLE "bulk_search_runs" ADD CONSTRAINT "bulk_search_runs_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
34
+
35
+ -- AddForeignKey
36
+ ALTER TABLE "bulk_search_runs" ADD CONSTRAINT "bulk_search_runs_ruleId_fkey" FOREIGN KEY ("ruleId") REFERENCES "routing_rules"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,97 @@
1
+ -- AlterTable
2
+ ALTER TABLE "route_match_configs" ALTER COLUMN "updatedAt" DROP DEFAULT;
3
+
4
+ -- AlterTable
5
+ ALTER TABLE "routing_branches" ALTER COLUMN "updatedAt" DROP DEFAULT;
6
+
7
+ -- CreateTable
8
+ CREATE TABLE "ai_custom_prompts" (
9
+ "id" TEXT NOT NULL,
10
+ "orgId" TEXT NOT NULL,
11
+ "type" TEXT NOT NULL,
12
+ "name" TEXT NOT NULL,
13
+ "content" TEXT NOT NULL,
14
+ "context" TEXT,
15
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
16
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
17
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ "updatedAt" TIMESTAMP(3) NOT NULL,
19
+
20
+ CONSTRAINT "ai_custom_prompts_pkey" PRIMARY KEY ("id")
21
+ );
22
+
23
+ -- CreateTable
24
+ CREATE TABLE "ai_agent_logs" (
25
+ "id" TEXT NOT NULL,
26
+ "orgId" TEXT NOT NULL,
27
+ "context" TEXT NOT NULL,
28
+ "toolName" TEXT NOT NULL,
29
+ "action" TEXT NOT NULL,
30
+ "entityType" TEXT NOT NULL,
31
+ "entityId" TEXT,
32
+ "entityName" TEXT,
33
+ "input" JSONB NOT NULL,
34
+ "output" JSONB,
35
+ "status" TEXT NOT NULL,
36
+ "error" TEXT,
37
+ "actorId" TEXT NOT NULL,
38
+ "actorName" TEXT NOT NULL,
39
+ "durationMs" INTEGER,
40
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
41
+
42
+ CONSTRAINT "ai_agent_logs_pkey" PRIMARY KEY ("id")
43
+ );
44
+
45
+ -- CreateTable
46
+ CREATE TABLE "ai_chat_feedback" (
47
+ "id" TEXT NOT NULL,
48
+ "orgId" TEXT NOT NULL,
49
+ "rating" TEXT NOT NULL,
50
+ "userMessage" TEXT NOT NULL,
51
+ "aiResponse" TEXT NOT NULL,
52
+ "toolsUsed" JSONB,
53
+ "context" TEXT,
54
+ "feedback" TEXT,
55
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
56
+
57
+ CONSTRAINT "ai_chat_feedback_pkey" PRIMARY KEY ("id")
58
+ );
59
+
60
+ -- CreateIndex
61
+ CREATE INDEX "ai_custom_prompts_orgId_type_isActive_idx" ON "ai_custom_prompts"("orgId", "type", "isActive");
62
+
63
+ -- CreateIndex
64
+ CREATE INDEX "ai_agent_logs_orgId_createdAt_idx" ON "ai_agent_logs"("orgId", "createdAt");
65
+
66
+ -- CreateIndex
67
+ CREATE INDEX "ai_agent_logs_orgId_context_idx" ON "ai_agent_logs"("orgId", "context");
68
+
69
+ -- CreateIndex
70
+ CREATE INDEX "ai_chat_feedback_orgId_rating_idx" ON "ai_chat_feedback"("orgId", "rating");
71
+
72
+ -- AddForeignKey
73
+ ALTER TABLE "routing_rules" ADD CONSTRAINT "routing_rules_defaultOwnerUserId_fkey" FOREIGN KEY ("defaultOwnerUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
74
+
75
+ -- AddForeignKey
76
+ ALTER TABLE "routing_rules" ADD CONSTRAINT "routing_rules_defaultOwnerTeamId_fkey" FOREIGN KEY ("defaultOwnerTeamId") REFERENCES "round_robin_teams"("id") ON DELETE SET NULL ON UPDATE CASCADE;
77
+
78
+ -- AddForeignKey
79
+ ALTER TABLE "routing_rules" ADD CONSTRAINT "routing_rules_defaultOwnerQueueId_fkey" FOREIGN KEY ("defaultOwnerQueueId") REFERENCES "sfdc_queues"("id") ON DELETE SET NULL ON UPDATE CASCADE;
80
+
81
+ -- AddForeignKey
82
+ ALTER TABLE "routing_branches" ADD CONSTRAINT "routing_branches_assigneeUserId_fkey" FOREIGN KEY ("assigneeUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
83
+
84
+ -- AddForeignKey
85
+ ALTER TABLE "routing_branches" ADD CONSTRAINT "routing_branches_assigneeTeamId_fkey" FOREIGN KEY ("assigneeTeamId") REFERENCES "round_robin_teams"("id") ON DELETE SET NULL ON UPDATE CASCADE;
86
+
87
+ -- AddForeignKey
88
+ ALTER TABLE "routing_branches" ADD CONSTRAINT "routing_branches_assigneeQueueId_fkey" FOREIGN KEY ("assigneeQueueId") REFERENCES "sfdc_queues"("id") ON DELETE SET NULL ON UPDATE CASCADE;
89
+
90
+ -- AddForeignKey
91
+ ALTER TABLE "ai_custom_prompts" ADD CONSTRAINT "ai_custom_prompts_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
92
+
93
+ -- AddForeignKey
94
+ ALTER TABLE "ai_agent_logs" ADD CONSTRAINT "ai_agent_logs_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
95
+
96
+ -- AddForeignKey
97
+ ALTER TABLE "ai_chat_feedback" ADD CONSTRAINT "ai_chat_feedback_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,76 @@
1
+ -- CreateEnum
2
+ CREATE TYPE "FlowStatus" AS ENUM ('DRAFT', 'ACTIVE', 'INACTIVE');
3
+
4
+ -- CreateEnum
5
+ CREATE TYPE "FlowNodeType" AS ENUM ('ENTRY', 'DECISION', 'BRANCH_DECISION', 'MATCH', 'ASSIGNMENT', 'UPDATE_FIELD', 'CREATE_TASK', 'FILTER', 'DEFAULT');
6
+
7
+ -- AlterTable
8
+ ALTER TABLE "organizations" ADD COLUMN "routingMode" JSONB;
9
+
10
+ -- AlterTable
11
+ ALTER TABLE "routing_logs" ADD COLUMN "flowId" TEXT,
12
+ ADD COLUMN "flowNodePath" JSONB;
13
+
14
+ -- CreateTable
15
+ CREATE TABLE "routing_flows" (
16
+ "id" TEXT NOT NULL,
17
+ "orgId" TEXT NOT NULL,
18
+ "objectType" "SfdcObjectType" NOT NULL,
19
+ "name" TEXT NOT NULL DEFAULT 'Untitled Flow',
20
+ "status" "FlowStatus" NOT NULL DEFAULT 'DRAFT',
21
+ "triggerEvent" "TriggerEvent" NOT NULL DEFAULT 'BOTH',
22
+ "isDryRun" BOOLEAN NOT NULL DEFAULT false,
23
+ "version" INTEGER NOT NULL DEFAULT 1,
24
+ "publishedAt" TIMESTAMP(3),
25
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
26
+ "updatedAt" TIMESTAMP(3) NOT NULL,
27
+
28
+ CONSTRAINT "routing_flows_pkey" PRIMARY KEY ("id")
29
+ );
30
+
31
+ -- CreateTable
32
+ CREATE TABLE "flow_nodes" (
33
+ "id" TEXT NOT NULL,
34
+ "flowId" TEXT NOT NULL,
35
+ "type" "FlowNodeType" NOT NULL,
36
+ "label" TEXT,
37
+ "positionX" DOUBLE PRECISION NOT NULL DEFAULT 0,
38
+ "positionY" DOUBLE PRECISION NOT NULL DEFAULT 0,
39
+ "config" JSONB,
40
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
41
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
42
+ "updatedAt" TIMESTAMP(3) NOT NULL,
43
+
44
+ CONSTRAINT "flow_nodes_pkey" PRIMARY KEY ("id")
45
+ );
46
+
47
+ -- CreateTable
48
+ CREATE TABLE "flow_edges" (
49
+ "id" TEXT NOT NULL,
50
+ "flowId" TEXT NOT NULL,
51
+ "fromId" TEXT NOT NULL,
52
+ "toId" TEXT NOT NULL,
53
+ "label" TEXT,
54
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
55
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
56
+
57
+ CONSTRAINT "flow_edges_pkey" PRIMARY KEY ("id")
58
+ );
59
+
60
+ -- CreateIndex
61
+ CREATE UNIQUE INDEX "routing_flows_orgId_objectType_key" ON "routing_flows"("orgId", "objectType");
62
+
63
+ -- AddForeignKey
64
+ ALTER TABLE "routing_flows" ADD CONSTRAINT "routing_flows_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
65
+
66
+ -- AddForeignKey
67
+ ALTER TABLE "flow_nodes" ADD CONSTRAINT "flow_nodes_flowId_fkey" FOREIGN KEY ("flowId") REFERENCES "routing_flows"("id") ON DELETE CASCADE ON UPDATE CASCADE;
68
+
69
+ -- AddForeignKey
70
+ ALTER TABLE "flow_edges" ADD CONSTRAINT "flow_edges_flowId_fkey" FOREIGN KEY ("flowId") REFERENCES "routing_flows"("id") ON DELETE CASCADE ON UPDATE CASCADE;
71
+
72
+ -- AddForeignKey
73
+ ALTER TABLE "flow_edges" ADD CONSTRAINT "flow_edges_fromId_fkey" FOREIGN KEY ("fromId") REFERENCES "flow_nodes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
74
+
75
+ -- AddForeignKey
76
+ ALTER TABLE "flow_edges" ADD CONSTRAINT "flow_edges_toId_fkey" FOREIGN KEY ("toId") REFERENCES "flow_nodes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,3 @@
1
+ -- AlterTable
2
+ ALTER TABLE "flow_edges" ADD COLUMN "sourceHandle" TEXT;
3
+ ALTER TABLE "flow_edges" ADD COLUMN "targetHandle" TEXT;
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "routing_branches" ADD COLUMN "steps" JSONB;
@@ -0,0 +1,24 @@
1
+ -- CreateTable
2
+ CREATE TABLE "api_tokens" (
3
+ "id" TEXT NOT NULL,
4
+ "orgId" TEXT NOT NULL,
5
+ "name" TEXT NOT NULL,
6
+ "tokenHash" TEXT NOT NULL,
7
+ "prefix" TEXT NOT NULL,
8
+ "scopes" TEXT[] DEFAULT ARRAY['read', 'route']::TEXT[],
9
+ "lastUsedAt" TIMESTAMP(3),
10
+ "expiresAt" TIMESTAMP(3),
11
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
+ "revokedAt" TIMESTAMP(3),
13
+
14
+ CONSTRAINT "api_tokens_pkey" PRIMARY KEY ("id")
15
+ );
16
+
17
+ -- CreateIndex
18
+ CREATE UNIQUE INDEX "api_tokens_tokenHash_key" ON "api_tokens"("tokenHash");
19
+
20
+ -- CreateIndex
21
+ CREATE INDEX "api_tokens_orgId_idx" ON "api_tokens"("orgId");
22
+
23
+ -- AddForeignKey
24
+ ALTER TABLE "api_tokens" ADD CONSTRAINT "api_tokens_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -1,3 +1,3 @@
1
1
  # Please do not edit this file manually
2
- # It should be added in your version-control system (i.e. Git)
3
- provider = "postgresql"
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "postgresql"
@@ -77,6 +77,24 @@ enum Plan {
77
77
  PAID
78
78
  }
79
79
 
80
+ enum FlowStatus {
81
+ DRAFT
82
+ ACTIVE
83
+ INACTIVE
84
+ }
85
+
86
+ enum FlowNodeType {
87
+ ENTRY
88
+ DECISION
89
+ BRANCH_DECISION
90
+ MATCH
91
+ ASSIGNMENT
92
+ UPDATE_FIELD
93
+ CREATE_TASK
94
+ FILTER
95
+ DEFAULT
96
+ }
97
+
80
98
  // ─── Models ───────────────────────────────────────────────────────────────────
81
99
 
82
100
  model Organization {
@@ -107,6 +125,11 @@ model Organization {
107
125
  aiBaseUrl String? // custom endpoint URL (null = default)
108
126
  aiCustomHeaders Json? // custom headers for self-hosted proxies
109
127
  aiChatCount Int @default(0)
128
+ // License activation (from web UI)
129
+ licenseKey String?
130
+ licenseTier String? // "free" | "pro"
131
+ licenseValidUntil DateTime?
132
+ licenseActivatedAt DateTime?
110
133
  createdAt DateTime @default(now())
111
134
  updatedAt DateTime @updatedAt
112
135
 
@@ -123,6 +146,13 @@ model Organization {
123
146
  routingDailyAggregates RoutingDailyAggregate[]
124
147
  conversionTracking ConversionTracking[]
125
148
  companyAliases CompanyAlias[]
149
+ bulkSearchRuns BulkSearchRun[]
150
+ aiCustomPrompts AiCustomPrompt[]
151
+ aiAgentLogs AiAgentLog[]
152
+ aiChatFeedback AiChatFeedback[]
153
+ routingMode Json?
154
+ routingFlows RoutingFlow[]
155
+ apiTokens ApiToken[]
126
156
 
127
157
  @@map("organizations")
128
158
  }
@@ -250,6 +280,9 @@ model RoutingRule {
250
280
  lastRunDurationMs Int?
251
281
  totalRuns Int @default(0)
252
282
  totalRecordsRouted Int @default(0)
283
+ // Bulk search configuration
284
+ searchMaxRecords Int? // user-configurable max records per run
285
+ searchBatchSize Int? // micro-batch size (default 500)
253
286
  // Default owner: absolute catch-all for new Route Builder routes
254
287
  defaultOwnerType AssignmentType?
255
288
  defaultOwnerUserId String?
@@ -268,6 +301,7 @@ model RoutingRule {
268
301
  branches RoutingBranch[] // new Route Builder paths
269
302
  matchConfig RouteMatchConfig?
270
303
  triggerConditions TriggerCondition[]
304
+ bulkSearchRuns BulkSearchRun[]
271
305
 
272
306
  @@map("routing_rules")
273
307
  }
@@ -285,6 +319,7 @@ model RoutingBranch {
285
319
  assigneeTeam RoundRobinTeam? @relation("BranchAssigneeTeam", fields: [assigneeTeamId], references: [id])
286
320
  assigneeQueueId String?
287
321
  assigneeQueue SfdcQueue? @relation("BranchAssigneeQueue", fields: [assigneeQueueId], references: [id])
322
+ steps Json?
288
323
  createdAt DateTime @default(now())
289
324
  updatedAt DateTime @updatedAt
290
325
 
@@ -405,6 +440,8 @@ model RoutingLog {
405
440
  branchId String? // FK → RoutingBranch for path-level analytics
406
441
  createdAt DateTime @default(now())
407
442
 
443
+ flowId String?
444
+ flowNodePath Json?
408
445
  org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
409
446
  branch RoutingBranch? @relation(fields: [branchId], references: [id])
410
447
  conversionTracking ConversionTracking?
@@ -435,6 +472,64 @@ model AuditLog {
435
472
  @@map("audit_logs")
436
473
  }
437
474
 
475
+ model RoutingFlow {
476
+ id String @id @default(cuid())
477
+ orgId String
478
+ objectType SfdcObjectType
479
+ name String @default("Untitled Flow")
480
+ status FlowStatus @default(DRAFT)
481
+ triggerEvent TriggerEvent @default(BOTH)
482
+ isDryRun Boolean @default(false)
483
+ version Int @default(1)
484
+ publishedAt DateTime?
485
+ createdAt DateTime @default(now())
486
+ updatedAt DateTime @updatedAt
487
+
488
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
489
+ nodes FlowNode[]
490
+ edges FlowEdge[]
491
+
492
+ @@unique([orgId, objectType])
493
+ @@map("routing_flows")
494
+ }
495
+
496
+ model FlowNode {
497
+ id String @id @default(cuid())
498
+ flowId String
499
+ type FlowNodeType
500
+ label String?
501
+ positionX Float @default(0)
502
+ positionY Float @default(0)
503
+ config Json?
504
+ sortOrder Int @default(0)
505
+ createdAt DateTime @default(now())
506
+ updatedAt DateTime @updatedAt
507
+
508
+ flow RoutingFlow @relation(fields: [flowId], references: [id], onDelete: Cascade)
509
+ outEdges FlowEdge[] @relation("FromNode")
510
+ inEdges FlowEdge[] @relation("ToNode")
511
+
512
+ @@map("flow_nodes")
513
+ }
514
+
515
+ model FlowEdge {
516
+ id String @id @default(cuid())
517
+ flowId String
518
+ fromId String
519
+ toId String
520
+ label String?
521
+ sourceHandle String?
522
+ targetHandle String?
523
+ sortOrder Int @default(0)
524
+ createdAt DateTime @default(now())
525
+
526
+ flow RoutingFlow @relation(fields: [flowId], references: [id], onDelete: Cascade)
527
+ from FlowNode @relation("FromNode", fields: [fromId], references: [id], onDelete: Cascade)
528
+ to FlowNode @relation("ToNode", fields: [toId], references: [id], onDelete: Cascade)
529
+
530
+ @@map("flow_edges")
531
+ }
532
+
438
533
  model SfdcQueue {
439
534
  id String @id @default(cuid())
440
535
  orgId String
@@ -576,3 +671,103 @@ model CompanyAlias {
576
671
  @@index([orgId, nameB])
577
672
  @@map("company_aliases")
578
673
  }
674
+
675
+ model BulkSearchRun {
676
+ id String @id @default(cuid())
677
+ orgId String
678
+ ruleId String
679
+ status String @default("RUNNING") // RUNNING | COMPLETE | FAILED | CANCELLED
680
+ recordsFound Int @default(0)
681
+ recordsProcessed Int @default(0)
682
+ recordsRouted Int @default(0)
683
+ recordsFailed Int @default(0)
684
+ recordsSkipped Int @default(0)
685
+ error String?
686
+ startedAt DateTime @default(now())
687
+ completedAt DateTime?
688
+ durationMs Int?
689
+ maxRecords Int?
690
+ batchSize Int?
691
+
692
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
693
+ rule RoutingRule @relation(fields: [ruleId], references: [id], onDelete: Cascade)
694
+
695
+ @@index([orgId, ruleId])
696
+ @@index([ruleId, status])
697
+ @@map("bulk_search_runs")
698
+ }
699
+
700
+ model ApiToken {
701
+ id String @id @default(cuid())
702
+ orgId String
703
+ name String
704
+ tokenHash String @unique
705
+ prefix String
706
+ scopes String[] @default(["read", "route"])
707
+ lastUsedAt DateTime?
708
+ expiresAt DateTime?
709
+ createdAt DateTime @default(now())
710
+ revokedAt DateTime?
711
+
712
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
713
+
714
+ @@index([orgId])
715
+ @@map("api_tokens")
716
+ }
717
+
718
+ model AiCustomPrompt {
719
+ id String @id @default(cuid())
720
+ orgId String
721
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
722
+ type String // "instruction" | "template" | "alias" | "memory"
723
+ name String
724
+ content String
725
+ context String? // null = global, "license-users" | "teams" | "routing-rules"
726
+ isActive Boolean @default(true)
727
+ sortOrder Int @default(0)
728
+ createdAt DateTime @default(now())
729
+ updatedAt DateTime @updatedAt
730
+
731
+ @@index([orgId, type, isActive])
732
+ @@map("ai_custom_prompts")
733
+ }
734
+
735
+ model AiAgentLog {
736
+ id String @id @default(cuid())
737
+ orgId String
738
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
739
+ context String
740
+ toolName String
741
+ action String
742
+ entityType String
743
+ entityId String?
744
+ entityName String?
745
+ input Json
746
+ output Json?
747
+ status String
748
+ error String?
749
+ actorId String
750
+ actorName String
751
+ durationMs Int?
752
+ createdAt DateTime @default(now())
753
+
754
+ @@index([orgId, createdAt])
755
+ @@index([orgId, context])
756
+ @@map("ai_agent_logs")
757
+ }
758
+
759
+ model AiChatFeedback {
760
+ id String @id @default(cuid())
761
+ orgId String
762
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
763
+ rating String
764
+ userMessage String
765
+ aiResponse String
766
+ toolsUsed Json?
767
+ context String?
768
+ feedback String?
769
+ createdAt DateTime @default(now())
770
+
771
+ @@index([orgId, rating])
772
+ @@map("ai_chat_feedback")
773
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lead-routing/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Self-hosted deployment CLI for Lead Routing",
5
5
  "homepage": "https://github.com/lead-routing/lead-routing",
6
6
  "keywords": [