create-safest-tools 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +71 -0
  3. package/bin/create-safest-tools.mjs +12 -0
  4. package/package.json +34 -0
  5. package/src/cli.mjs +128 -0
  6. package/src/config.mjs +151 -0
  7. package/src/scaffold.mjs +30 -0
  8. package/template/LICENSE +201 -0
  9. package/template/README.md +35 -0
  10. package/template/console/README.md +28 -0
  11. package/template/console/analytics/AnalyticsWorkspace.tsx +55 -0
  12. package/template/console/analytics/controller.ts +133 -0
  13. package/template/console/analytics/events.ts +33 -0
  14. package/template/console/analytics/store.ts +33 -0
  15. package/template/console/analytics/types.ts +38 -0
  16. package/template/console/appeals/AppealWorkspace.tsx +73 -0
  17. package/template/console/appeals/controller.ts +125 -0
  18. package/template/console/appeals/events.ts +33 -0
  19. package/template/console/appeals/store.ts +35 -0
  20. package/template/console/appeals/types.ts +37 -0
  21. package/template/console/assistant/AssistantWorkspace.tsx +133 -0
  22. package/template/console/assistant/types.ts +34 -0
  23. package/template/console/auth/AccountJourney.tsx +69 -0
  24. package/template/console/auth/InvitationAcceptance.tsx +145 -0
  25. package/template/console/auth/OAuthButtons.tsx +78 -0
  26. package/template/console/auth/OperatorLogin.tsx +110 -0
  27. package/template/console/auth/PasswordRecovery.tsx +132 -0
  28. package/template/console/auth/account-route.ts +15 -0
  29. package/template/console/auth/browser-navigation.ts +7 -0
  30. package/template/console/auth/events.ts +15 -0
  31. package/template/console/command/CommandCentre.tsx +119 -0
  32. package/template/console/command/controller.ts +267 -0
  33. package/template/console/command/events.ts +19 -0
  34. package/template/console/command/store.ts +36 -0
  35. package/template/console/command/types.ts +61 -0
  36. package/template/console/components/AnalystIdentity.tsx +25 -0
  37. package/template/console/components/PageHeader.tsx +27 -0
  38. package/template/console/configuration/ConfigurationDialog.tsx +200 -0
  39. package/template/console/configuration/ConfigurationWorkspace.tsx +66 -0
  40. package/template/console/configuration/FormBuilder.tsx +143 -0
  41. package/template/console/configuration/api.ts +40 -0
  42. package/template/console/configuration/events.ts +14 -0
  43. package/template/console/configuration/types.ts +79 -0
  44. package/template/console/lib/format.ts +49 -0
  45. package/template/console/lib/http.ts +96 -0
  46. package/template/console/main.tsx +225 -0
  47. package/template/console/operations/OperationsWorkspace.tsx +126 -0
  48. package/template/console/operations/controller.ts +237 -0
  49. package/template/console/operations/events.ts +37 -0
  50. package/template/console/operations/store.ts +32 -0
  51. package/template/console/operations/types.ts +107 -0
  52. package/template/console/people/PeopleWorkspace.tsx +81 -0
  53. package/template/console/people/types.ts +25 -0
  54. package/template/console/profile/ProfileWorkspace.tsx +136 -0
  55. package/template/console/profile/events.ts +9 -0
  56. package/template/console/profile/types.ts +6 -0
  57. package/template/console/quality/QualityWorkspace.tsx +87 -0
  58. package/template/console/quality/controller.ts +154 -0
  59. package/template/console/quality/events.ts +34 -0
  60. package/template/console/quality/store.ts +36 -0
  61. package/template/console/quality/types.ts +70 -0
  62. package/template/console/queues/QueueEditor.tsx +173 -0
  63. package/template/console/queues/QueueWorkspace.tsx +109 -0
  64. package/template/console/queues/controller.ts +194 -0
  65. package/template/console/queues/events.ts +34 -0
  66. package/template/console/queues/store.ts +37 -0
  67. package/template/console/queues/types.ts +102 -0
  68. package/template/console/registry/RegistryDialog.tsx +198 -0
  69. package/template/console/registry/RegistryWorkspace.tsx +108 -0
  70. package/template/console/registry/events.ts +14 -0
  71. package/template/console/registry/types.ts +52 -0
  72. package/template/console/reports/ReportDrawer.tsx +159 -0
  73. package/template/console/reports/ReportWorkspace.tsx +90 -0
  74. package/template/console/reports/controller.ts +517 -0
  75. package/template/console/reports/events.ts +42 -0
  76. package/template/console/reports/store.ts +39 -0
  77. package/template/console/reports/types.ts +230 -0
  78. package/template/console/settings/BrandEditor.tsx +126 -0
  79. package/template/console/settings/ChannelDialog.tsx +241 -0
  80. package/template/console/settings/SettingsWorkspace.tsx +155 -0
  81. package/template/console/settings/events.ts +19 -0
  82. package/template/console/settings/handoff.ts +22 -0
  83. package/template/console/settings/types.ts +93 -0
  84. package/template/console/shell/WorkspaceShell.tsx +160 -0
  85. package/template/console/shell/controller.ts +182 -0
  86. package/template/console/shell/events.ts +25 -0
  87. package/template/console/shell/navigation.ts +61 -0
  88. package/template/console/shell/store.ts +56 -0
  89. package/template/console/shell/types.ts +86 -0
  90. package/template/console/workflows/CreateWorkflowDialog.tsx +87 -0
  91. package/template/console/workflows/WorkflowCanvas.tsx +42 -0
  92. package/template/console/workflows/WorkflowDialogs.tsx +6 -0
  93. package/template/console/workflows/WorkflowStudio.tsx +331 -0
  94. package/template/console/workflows/WorkflowWorkspace.tsx +82 -0
  95. package/template/console/workflows/events.ts +17 -0
  96. package/template/console/workflows/graph.ts +156 -0
  97. package/template/console/workflows/templates.ts +70 -0
  98. package/template/console/workflows/types.ts +201 -0
  99. package/template/gitignore.template +18 -0
  100. package/template/migrations/0001_reports_foundation.sql +444 -0
  101. package/template/migrations/0002_human_report_loop.sql +65 -0
  102. package/template/migrations/0003_delivery_reliability.sql +18 -0
  103. package/template/migrations/0004_public_intake.sql +14 -0
  104. package/template/migrations/0005_operations_visibility.sql +24 -0
  105. package/template/migrations/0006_ai_governance.sql +198 -0
  106. package/template/migrations/0007_ai_release_gates.sql +6 -0
  107. package/template/migrations/0008_retention_analytics_exports.sql +52 -0
  108. package/template/migrations/0009_retention_derived_copies.sql +14 -0
  109. package/template/migrations/0010_ai_quality_controls.sql +26 -0
  110. package/template/migrations/0011_analyst_presence.sql +28 -0
  111. package/template/migrations/0012_queue_policies.sql +87 -0
  112. package/template/migrations/0013_routing_agents.sql +63 -0
  113. package/template/migrations/0014_webhook_enrichments.sql +122 -0
  114. package/template/migrations/0015_queue_owned_ai.sql +55 -0
  115. package/template/migrations/0016_operator_accounts.sql +67 -0
  116. package/template/migrations/0017_operator_profiles_and_recovery.sql +33 -0
  117. package/template/migrations/0018_platform_configuration.sql +382 -0
  118. package/template/migrations/0019_workflow_authoring_runtime.sql +372 -0
  119. package/template/migrations/0020_tasks_findings_assistant_budgets.sql +427 -0
  120. package/template/migrations/0021_abuse_evidence_operations.sql +324 -0
  121. package/template/migrations/0022_workflow_dispatch_operations.sql +42 -0
  122. package/template/migrations/0023_component_connection_execution.sql +75 -0
  123. package/template/migrations/0024_access_runtime_integrity.sql +72 -0
  124. package/template/migrations/0025_installation_timezone.sql +11 -0
  125. package/template/migrations/0026_ai_and_egress_execution_controls.sql +49 -0
  126. package/template/migrations/0027_prompt_and_ai_registry.sql +37 -0
  127. package/template/migrations/0028_step_attempt_ai_provenance.sql +13 -0
  128. package/template/migrations/0029_evidence_fetch_transport.sql +5 -0
  129. package/template/migrations/0030_evidence_dlq_incidents.sql +45 -0
  130. package/template/migrations/0031_shadow_quality_integrity.sql +7 -0
  131. package/template/migrations/0032_action_delivery_outbox.sql +55 -0
  132. package/template/migrations/0033_configuration_and_assistant_drafts.sql +43 -0
  133. package/template/migrations/0034_installation_integrations.sql +31 -0
  134. package/template/migrations/0035_workspace_governance.sql +21 -0
  135. package/template/migrations/0036_published_routing_baseline.sql +15 -0
  136. package/template/migrations/0037_builtin_phishing_specialist.sql +71 -0
  137. package/template/migrations/0038_remove_deprecated_enrichment_runtime.sql +228 -0
  138. package/template/migrations/0039_secure_reporting_channels.sql +45 -0
  139. package/template/migrations/0040_notification_only_reporting.sql +24 -0
  140. package/template/migrations/0041_better_auth_credentials.sql +17 -0
  141. package/template/package.json +47 -0
  142. package/template/public/_headers +27 -0
  143. package/template/public/app-icon-192.png +0 -0
  144. package/template/public/app-icon-512.png +0 -0
  145. package/template/public/brand-icon.svg +7 -0
  146. package/template/public/brand-tokens.css +80 -0
  147. package/template/public/console/auth-shell.js +19340 -0
  148. package/template/public/customer-brand.js +58 -0
  149. package/template/public/embed/embed.css +139 -0
  150. package/template/public/embed/embed.js +408 -0
  151. package/template/public/embed/index.html +91 -0
  152. package/template/public/favicon.svg +7 -0
  153. package/template/public/fonts/Manrope-Variable.ttf +0 -0
  154. package/template/public/fonts/Newsreader-Italic-Variable.ttf +0 -0
  155. package/template/public/fonts/Newsreader-Variable.ttf +0 -0
  156. package/template/public/index.html +123 -0
  157. package/template/public/logo-primary.svg +7 -0
  158. package/template/public/logo-reversed.svg +7 -0
  159. package/template/public/manifest.webmanifest +21 -0
  160. package/template/public/public-report.js +184 -0
  161. package/template/public/report/index.html +39 -0
  162. package/template/public/report/public-report.css +20 -0
  163. package/template/public/social-card.png +0 -0
  164. package/template/public/styles.css +1521 -0
  165. package/template/public/widget.css +80 -0
  166. package/template/public/widget.js +220 -0
  167. package/template/reports.config.example.json +38 -0
  168. package/template/reports.schema.json +89 -0
  169. package/template/scripts/reports-auth-onboarding.mjs +180 -0
  170. package/template/scripts/reports-backup.mjs +276 -0
  171. package/template/scripts/reports-cloudflare-preflight.mjs +152 -0
  172. package/template/scripts/reports-deploy.mjs +173 -0
  173. package/template/scripts/reports-plan.mjs +226 -0
  174. package/template/scripts/reports-restore.mjs +180 -0
  175. package/template/scripts/reports-secrets.mjs +73 -0
  176. package/template/scripts/reports-uninstall-plan.mjs +32 -0
  177. package/template/src/agent-executor.ts +330 -0
  178. package/template/src/ai-observability.ts +163 -0
  179. package/template/src/ai-registry-validation.ts +244 -0
  180. package/template/src/ai-registry.ts +292 -0
  181. package/template/src/api-cursor.ts +84 -0
  182. package/template/src/assistant.ts +554 -0
  183. package/template/src/audit.ts +39 -0
  184. package/template/src/backup-service.ts +269 -0
  185. package/template/src/budget-control.ts +127 -0
  186. package/template/src/component-executor.ts +845 -0
  187. package/template/src/configuration-registry.ts +550 -0
  188. package/template/src/connection-egress.ts +430 -0
  189. package/template/src/connection-oauth.ts +368 -0
  190. package/template/src/evidence-service.ts +335 -0
  191. package/template/src/human-tasks.ts +316 -0
  192. package/template/src/index.ts +4114 -0
  193. package/template/src/installation-admin.ts +301 -0
  194. package/template/src/intake-abuse.ts +156 -0
  195. package/template/src/platform-registry-validation.ts +367 -0
  196. package/template/src/platform-registry.ts +753 -0
  197. package/template/src/report-admin.ts +342 -0
  198. package/template/src/report-ai-quality.ts +390 -0
  199. package/template/src/report-ai-validation.ts +80 -0
  200. package/template/src/report-ai.ts +857 -0
  201. package/template/src/report-auth.ts +292 -0
  202. package/template/src/report-better-auth.ts +583 -0
  203. package/template/src/report-context-schema.ts +132 -0
  204. package/template/src/report-context.ts +126 -0
  205. package/template/src/report-crypto.ts +142 -0
  206. package/template/src/report-delivery.ts +579 -0
  207. package/template/src/report-form-validation.ts +51 -0
  208. package/template/src/report-governance.ts +510 -0
  209. package/template/src/report-http.ts +90 -0
  210. package/template/src/report-operations.ts +685 -0
  211. package/template/src/report-operator-accounts.ts +810 -0
  212. package/template/src/report-presence.ts +398 -0
  213. package/template/src/report-queue-validation.ts +309 -0
  214. package/template/src/report-queues.ts +478 -0
  215. package/template/src/report-repository.ts +972 -0
  216. package/template/src/report-router-agent.ts +328 -0
  217. package/template/src/report-router-validation.ts +81 -0
  218. package/template/src/report-routing.ts +178 -0
  219. package/template/src/report-turnstile.ts +142 -0
  220. package/template/src/report-types.ts +224 -0
  221. package/template/src/report-validation.ts +279 -0
  222. package/template/src/report-workflow-validation.ts +119 -0
  223. package/template/src/report-workflow.ts +886 -0
  224. package/template/src/shadow-quality.ts +278 -0
  225. package/template/src/workflow-actions.ts +782 -0
  226. package/template/src/workflow-compiler.ts +230 -0
  227. package/template/src/workflow-dynamic-runtime.ts +613 -0
  228. package/template/src/workflow-effects.ts +316 -0
  229. package/template/src/workflow-expressions.ts +191 -0
  230. package/template/src/workflow-platform-types.ts +121 -0
  231. package/template/src/workflow-platform-validation.ts +540 -0
  232. package/template/src/workflow-repository.ts +916 -0
  233. package/template/src/workflow-runs.ts +686 -0
  234. package/template/src/workflow-simulator.ts +211 -0
  235. package/template/src/workspace-branding.ts +128 -0
  236. package/template/src/workspace-governance.ts +279 -0
  237. package/template/tsconfig.console.json +23 -0
  238. package/template/tsconfig.json +22 -0
  239. package/template/vite.console.config.ts +20 -0
  240. package/template/worker-configuration.d.ts +65 -0
@@ -0,0 +1,427 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ CREATE TABLE findings (
4
+ id TEXT PRIMARY KEY,
5
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
6
+ report_id TEXT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
7
+ run_id TEXT REFERENCES workflow_runs(id) ON DELETE SET NULL,
8
+ step_run_id TEXT REFERENCES workflow_step_runs(id) ON DELETE SET NULL,
9
+ component_version_id TEXT REFERENCES component_versions(id),
10
+ ai_run_id TEXT REFERENCES ai_runs(id),
11
+ finding_type TEXT NOT NULL,
12
+ subject_type TEXT NOT NULL,
13
+ subject_reference TEXT NOT NULL,
14
+ status TEXT NOT NULL CHECK (status IN ('available', 'unavailable', 'invalid', 'stale', 'superseded')),
15
+ confidence REAL CHECK (confidence IS NULL OR (confidence >= 0 AND confidence <= 1)),
16
+ summary TEXT NOT NULL,
17
+ data_json TEXT NOT NULL,
18
+ provenance_json TEXT NOT NULL,
19
+ uncertainty_json TEXT NOT NULL DEFAULT '[]',
20
+ input_digest TEXT,
21
+ output_digest TEXT NOT NULL,
22
+ expires_at TEXT,
23
+ created_at TEXT NOT NULL,
24
+ superseded_at TEXT
25
+ );
26
+
27
+ CREATE INDEX findings_report_idx
28
+ ON findings(report_id, created_at DESC, id DESC);
29
+ CREATE INDEX findings_run_idx
30
+ ON findings(run_id, step_run_id, created_at, id);
31
+
32
+ CREATE TABLE human_tasks (
33
+ id TEXT PRIMARY KEY,
34
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
35
+ report_id TEXT REFERENCES reports(id) ON DELETE SET NULL,
36
+ appeal_id TEXT REFERENCES appeals(id) ON DELETE SET NULL,
37
+ run_id TEXT NOT NULL REFERENCES workflow_runs(id) ON DELETE CASCADE,
38
+ step_run_id TEXT NOT NULL REFERENCES workflow_step_runs(id) ON DELETE CASCADE,
39
+ task_type TEXT NOT NULL CHECK (task_type IN (
40
+ 'review', 'approval', 'appeal_review', 'quality_review', 'operations', 'information_request'
41
+ )),
42
+ state TEXT NOT NULL CHECK (state IN ('open', 'claimed', 'completed', 'expired', 'cancelled')),
43
+ queue_id TEXT REFERENCES queue_definitions(id),
44
+ assigned_operator_id TEXT,
45
+ context_json TEXT NOT NULL,
46
+ context_digest TEXT NOT NULL,
47
+ response_schema_json TEXT NOT NULL,
48
+ action_proposal_id TEXT,
49
+ due_at TEXT,
50
+ escalation_at TEXT,
51
+ created_at TEXT NOT NULL,
52
+ updated_at TEXT NOT NULL,
53
+ completed_at TEXT,
54
+ UNIQUE (step_run_id)
55
+ );
56
+
57
+ CREATE INDEX human_tasks_work_idx
58
+ ON human_tasks(state, queue_id, due_at, created_at, id);
59
+ CREATE INDEX human_tasks_report_idx
60
+ ON human_tasks(report_id, created_at DESC, id DESC);
61
+
62
+ CREATE TABLE human_task_claims (
63
+ id TEXT PRIMARY KEY,
64
+ task_id TEXT NOT NULL REFERENCES human_tasks(id) ON DELETE CASCADE,
65
+ operator_id TEXT NOT NULL,
66
+ claimed_at TEXT NOT NULL,
67
+ expires_at TEXT NOT NULL,
68
+ released_at TEXT,
69
+ release_reason TEXT
70
+ );
71
+
72
+ CREATE UNIQUE INDEX human_task_claims_one_active_idx
73
+ ON human_task_claims(task_id) WHERE released_at IS NULL;
74
+ CREATE INDEX human_task_claims_operator_idx
75
+ ON human_task_claims(operator_id, released_at, expires_at, task_id);
76
+
77
+ CREATE TABLE human_task_responses (
78
+ id TEXT PRIMARY KEY,
79
+ task_id TEXT NOT NULL REFERENCES human_tasks(id) ON DELETE CASCADE,
80
+ claim_id TEXT REFERENCES human_task_claims(id),
81
+ operator_id TEXT NOT NULL,
82
+ response_json TEXT NOT NULL,
83
+ response_digest TEXT NOT NULL,
84
+ idempotency_key TEXT NOT NULL,
85
+ submitted_at TEXT NOT NULL,
86
+ UNIQUE (task_id),
87
+ UNIQUE (operator_id, idempotency_key)
88
+ );
89
+
90
+ CREATE TABLE action_proposals (
91
+ id TEXT PRIMARY KEY,
92
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
93
+ report_id TEXT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
94
+ appeal_id TEXT REFERENCES appeals(id) ON DELETE SET NULL,
95
+ run_id TEXT REFERENCES workflow_runs(id) ON DELETE SET NULL,
96
+ step_run_id TEXT REFERENCES workflow_step_runs(id) ON DELETE SET NULL,
97
+ decision_id TEXT REFERENCES decisions(id),
98
+ action_code TEXT NOT NULL,
99
+ target_json TEXT NOT NULL,
100
+ payload_json TEXT NOT NULL,
101
+ preconditions_json TEXT NOT NULL DEFAULT '{}',
102
+ payload_digest TEXT NOT NULL,
103
+ component_version_id TEXT REFERENCES component_versions(id),
104
+ authority_mode TEXT NOT NULL CHECK (authority_mode IN ('assist', 'bounded_auto')),
105
+ approval_policy_json TEXT NOT NULL,
106
+ state TEXT NOT NULL CHECK (state IN (
107
+ 'proposed', 'approval_required', 'approved', 'rejected', 'queued',
108
+ 'applying', 'applied', 'failed', 'cancelled', 'compensation_required', 'compensated'
109
+ )),
110
+ operation_id TEXT NOT NULL UNIQUE,
111
+ compensates_proposal_id TEXT REFERENCES action_proposals(id),
112
+ created_by_type TEXT NOT NULL,
113
+ created_by_id TEXT NOT NULL,
114
+ created_at TEXT NOT NULL,
115
+ updated_at TEXT NOT NULL
116
+ );
117
+
118
+ CREATE INDEX action_proposals_report_idx
119
+ ON action_proposals(report_id, created_at DESC, id DESC);
120
+ CREATE INDEX action_proposals_state_idx
121
+ ON action_proposals(state, updated_at, id);
122
+
123
+ CREATE TABLE action_approvals (
124
+ id TEXT PRIMARY KEY,
125
+ proposal_id TEXT NOT NULL REFERENCES action_proposals(id) ON DELETE CASCADE,
126
+ task_id TEXT REFERENCES human_tasks(id),
127
+ approver_id TEXT NOT NULL,
128
+ payload_digest TEXT NOT NULL,
129
+ decision TEXT NOT NULL CHECK (decision IN ('approved', 'rejected')),
130
+ reason TEXT,
131
+ idempotency_key TEXT NOT NULL,
132
+ created_at TEXT NOT NULL,
133
+ UNIQUE (proposal_id),
134
+ UNIQUE (approver_id, idempotency_key)
135
+ );
136
+
137
+ CREATE TABLE appeal_workflow_links (
138
+ appeal_id TEXT PRIMARY KEY REFERENCES appeals(id) ON DELETE CASCADE,
139
+ run_id TEXT NOT NULL UNIQUE REFERENCES workflow_runs(id) ON DELETE CASCADE,
140
+ original_run_id TEXT REFERENCES workflow_runs(id),
141
+ original_decision_id TEXT REFERENCES decisions(id),
142
+ created_at TEXT NOT NULL
143
+ );
144
+
145
+ CREATE TABLE conversations (
146
+ id TEXT PRIMARY KEY,
147
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
148
+ report_id TEXT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
149
+ audience TEXT NOT NULL CHECK (audience IN ('internal', 'reporter', 'affected_user')),
150
+ participant_id TEXT REFERENCES report_participants(id),
151
+ status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'closed', 'suppressed')),
152
+ locale TEXT NOT NULL,
153
+ created_at TEXT NOT NULL,
154
+ updated_at TEXT NOT NULL,
155
+ UNIQUE (report_id, audience)
156
+ );
157
+
158
+ CREATE INDEX conversations_report_idx
159
+ ON conversations(report_id, audience, id);
160
+
161
+ ALTER TABLE case_messages ADD COLUMN conversation_id TEXT REFERENCES conversations(id);
162
+ ALTER TABLE case_messages ADD COLUMN workflow_run_id TEXT REFERENCES workflow_runs(id);
163
+ ALTER TABLE case_messages ADD COLUMN audience_checked_at TEXT;
164
+
165
+ INSERT INTO conversations (
166
+ id, installation_id, report_id, audience, participant_id, status, locale, created_at, updated_at
167
+ )
168
+ SELECT
169
+ 'conversation:reporter:' || r.id,
170
+ r.installation_id,
171
+ r.id,
172
+ 'reporter',
173
+ (SELECT p.id FROM report_participants p WHERE p.report_id = r.id AND p.audience = 'reporter' ORDER BY p.id LIMIT 1),
174
+ 'open',
175
+ r.locale,
176
+ r.received_at,
177
+ r.updated_at
178
+ FROM reports r;
179
+
180
+ INSERT INTO conversations (
181
+ id, installation_id, report_id, audience, participant_id, status, locale, created_at, updated_at
182
+ )
183
+ SELECT
184
+ 'conversation:affected_user:' || r.id,
185
+ r.installation_id,
186
+ r.id,
187
+ 'affected_user',
188
+ (SELECT p.id FROM report_participants p WHERE p.report_id = r.id AND p.audience = 'affected_user' ORDER BY p.id LIMIT 1),
189
+ 'open',
190
+ r.locale,
191
+ r.received_at,
192
+ r.updated_at
193
+ FROM reports r
194
+ WHERE EXISTS (
195
+ SELECT 1 FROM report_participants p WHERE p.report_id = r.id AND p.audience = 'affected_user'
196
+ );
197
+
198
+ INSERT INTO conversations (
199
+ id, installation_id, report_id, audience, status, locale, created_at, updated_at
200
+ )
201
+ SELECT
202
+ 'conversation:internal:' || r.id,
203
+ r.installation_id,
204
+ r.id,
205
+ 'internal',
206
+ 'open',
207
+ r.locale,
208
+ r.received_at,
209
+ r.updated_at
210
+ FROM reports r;
211
+
212
+ UPDATE case_messages
213
+ SET conversation_id = CASE audience
214
+ WHEN 'affected_user' THEN 'conversation:affected_user:' || report_id
215
+ WHEN 'internal' THEN 'conversation:internal:' || report_id
216
+ ELSE 'conversation:reporter:' || report_id
217
+ END,
218
+ audience_checked_at = created_at;
219
+
220
+ CREATE INDEX case_messages_conversation_idx
221
+ ON case_messages(conversation_id, created_at, id);
222
+
223
+ CREATE TABLE email_deliveries (
224
+ id TEXT PRIMARY KEY,
225
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
226
+ message_id TEXT NOT NULL REFERENCES case_messages(id) ON DELETE CASCADE,
227
+ notification_outbox_id TEXT REFERENCES notification_outbox(id),
228
+ audience TEXT NOT NULL CHECK (audience IN ('operator', 'reporter', 'affected_user')),
229
+ recipient_hash TEXT NOT NULL,
230
+ provider TEXT NOT NULL,
231
+ provider_message_id TEXT,
232
+ state TEXT NOT NULL CHECK (state IN ('pending', 'sending', 'delivered', 'failed', 'suppressed', 'bounced')),
233
+ attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
234
+ last_error_code TEXT,
235
+ next_attempt_at TEXT,
236
+ delivered_at TEXT,
237
+ created_at TEXT NOT NULL,
238
+ updated_at TEXT NOT NULL
239
+ );
240
+
241
+ CREATE INDEX email_deliveries_due_idx
242
+ ON email_deliveries(state, next_attempt_at, id);
243
+ CREATE INDEX email_deliveries_message_idx
244
+ ON email_deliveries(message_id, created_at, id);
245
+
246
+ CREATE TABLE model_aliases (
247
+ id TEXT PRIMARY KEY,
248
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
249
+ alias_key TEXT NOT NULL,
250
+ name TEXT NOT NULL,
251
+ status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'paused', 'archived')),
252
+ active_version_id TEXT,
253
+ created_by TEXT NOT NULL,
254
+ created_at TEXT NOT NULL,
255
+ updated_at TEXT NOT NULL,
256
+ UNIQUE (installation_id, alias_key)
257
+ );
258
+
259
+ CREATE TABLE model_alias_versions (
260
+ id TEXT PRIMARY KEY,
261
+ alias_id TEXT NOT NULL REFERENCES model_aliases(id) ON DELETE CASCADE,
262
+ version INTEGER NOT NULL CHECK (version >= 1),
263
+ provider TEXT NOT NULL,
264
+ model TEXT NOT NULL,
265
+ connection_version_id TEXT REFERENCES connection_versions(id),
266
+ fallback_alias_version_id TEXT REFERENCES model_alias_versions(id),
267
+ input_cost_microusd_per_million INTEGER NOT NULL DEFAULT 0 CHECK (input_cost_microusd_per_million >= 0),
268
+ output_cost_microusd_per_million INTEGER NOT NULL DEFAULT 0 CHECK (output_cost_microusd_per_million >= 0),
269
+ capability_json TEXT NOT NULL DEFAULT '{}',
270
+ data_policy_json TEXT NOT NULL DEFAULT '{}',
271
+ published_at TEXT NOT NULL,
272
+ retired_at TEXT,
273
+ created_by TEXT NOT NULL,
274
+ created_at TEXT NOT NULL,
275
+ UNIQUE (alias_id, version)
276
+ );
277
+
278
+ CREATE TABLE agent_definitions (
279
+ id TEXT PRIMARY KEY,
280
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
281
+ agent_key TEXT NOT NULL,
282
+ name TEXT NOT NULL,
283
+ description TEXT NOT NULL DEFAULT '',
284
+ agent_kind TEXT NOT NULL CHECK (agent_kind IN ('routing', 'specialist', 'assistant', 'shadow')),
285
+ status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'paused', 'archived')),
286
+ active_version_id TEXT,
287
+ created_by TEXT NOT NULL,
288
+ created_at TEXT NOT NULL,
289
+ updated_at TEXT NOT NULL,
290
+ UNIQUE (installation_id, agent_key)
291
+ );
292
+
293
+ CREATE TABLE agent_versions (
294
+ id TEXT PRIMARY KEY,
295
+ agent_id TEXT NOT NULL REFERENCES agent_definitions(id) ON DELETE CASCADE,
296
+ version INTEGER NOT NULL CHECK (version >= 1),
297
+ prompt_version_id TEXT NOT NULL,
298
+ model_alias_version_id TEXT REFERENCES model_alias_versions(id),
299
+ tool_manifest_json TEXT NOT NULL,
300
+ memory_policy_json TEXT NOT NULL DEFAULT '{}',
301
+ maximum_turns INTEGER NOT NULL DEFAULT 8 CHECK (maximum_turns BETWEEN 1 AND 100),
302
+ approval_policy_json TEXT NOT NULL DEFAULT '{}',
303
+ input_schema_json TEXT NOT NULL,
304
+ output_schema_json TEXT NOT NULL,
305
+ published_at TEXT NOT NULL,
306
+ retired_at TEXT,
307
+ created_by TEXT NOT NULL,
308
+ created_at TEXT NOT NULL,
309
+ UNIQUE (agent_id, version)
310
+ );
311
+
312
+ CREATE TABLE assistant_sessions (
313
+ id TEXT PRIMARY KEY,
314
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
315
+ principal_id TEXT NOT NULL,
316
+ status TEXT NOT NULL CHECK (status IN ('active', 'closed', 'expired')),
317
+ timezone TEXT NOT NULL,
318
+ created_at TEXT NOT NULL,
319
+ updated_at TEXT NOT NULL,
320
+ expires_at TEXT NOT NULL
321
+ );
322
+
323
+ CREATE INDEX assistant_sessions_principal_idx
324
+ ON assistant_sessions(installation_id, principal_id, status, updated_at DESC, id DESC);
325
+
326
+ CREATE TABLE assistant_messages (
327
+ id TEXT PRIMARY KEY,
328
+ session_id TEXT NOT NULL REFERENCES assistant_sessions(id) ON DELETE CASCADE,
329
+ role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system', 'tool')),
330
+ body TEXT NOT NULL,
331
+ citations_json TEXT NOT NULL DEFAULT '[]',
332
+ model_alias_version_id TEXT REFERENCES model_alias_versions(id),
333
+ created_at TEXT NOT NULL
334
+ );
335
+
336
+ CREATE INDEX assistant_messages_session_idx
337
+ ON assistant_messages(session_id, created_at, id);
338
+
339
+ CREATE TABLE assistant_tool_calls (
340
+ id TEXT PRIMARY KEY,
341
+ session_id TEXT NOT NULL REFERENCES assistant_sessions(id) ON DELETE CASCADE,
342
+ message_id TEXT REFERENCES assistant_messages(id) ON DELETE SET NULL,
343
+ tool_name TEXT NOT NULL,
344
+ permission_snapshot_json TEXT NOT NULL,
345
+ input_json TEXT,
346
+ input_digest TEXT NOT NULL,
347
+ output_summary_json TEXT,
348
+ output_digest TEXT,
349
+ status TEXT NOT NULL CHECK (status IN ('running', 'succeeded', 'failed', 'denied')),
350
+ error_code TEXT,
351
+ started_at TEXT NOT NULL,
352
+ finished_at TEXT,
353
+ audit_event_id TEXT REFERENCES audit_events(id)
354
+ );
355
+
356
+ CREATE INDEX assistant_tool_calls_session_idx
357
+ ON assistant_tool_calls(session_id, started_at DESC, id DESC);
358
+
359
+ CREATE TABLE shadow_comparisons (
360
+ id TEXT PRIMARY KEY,
361
+ report_id TEXT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
362
+ primary_run_id TEXT REFERENCES workflow_runs(id) ON DELETE SET NULL,
363
+ shadow_run_id TEXT NOT NULL REFERENCES workflow_runs(id) ON DELETE CASCADE,
364
+ primary_decision_id TEXT REFERENCES decisions(id),
365
+ shadow_finding_id TEXT REFERENCES findings(id),
366
+ comparison_codes_json TEXT NOT NULL,
367
+ severity TEXT NOT NULL CHECK (severity IN ('info', 'low', 'medium', 'high', 'critical')),
368
+ status TEXT NOT NULL CHECK (status IN ('pending', 'quality_task_created', 'reviewed', 'dismissed')),
369
+ created_at TEXT NOT NULL,
370
+ reviewed_at TEXT
371
+ );
372
+
373
+ CREATE INDEX shadow_comparisons_status_idx
374
+ ON shadow_comparisons(status, severity, created_at, id);
375
+
376
+ CREATE TABLE budget_policies (
377
+ id TEXT PRIMARY KEY,
378
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
379
+ scope_type TEXT NOT NULL CHECK (scope_type IN (
380
+ 'installation', 'queue', 'workflow', 'component', 'connection', 'agent', 'assistant', 'shadow'
381
+ )),
382
+ scope_id TEXT NOT NULL,
383
+ metric TEXT NOT NULL CHECK (metric IN (
384
+ 'reports', 'calls', 'concurrent_calls', 'input_units', 'output_units', 'cost_microusd',
385
+ 'emails', 'actions', 'evidence_fetches', 'storage_bytes'
386
+ )),
387
+ limit_value INTEGER NOT NULL CHECK (limit_value >= 0),
388
+ window_seconds INTEGER NOT NULL CHECK (window_seconds BETWEEN 1 AND 2678400),
389
+ behavior TEXT NOT NULL CHECK (behavior IN ('block', 'fallback', 'defer', 'sample', 'pause')),
390
+ fallback_reference TEXT,
391
+ published_at TEXT NOT NULL,
392
+ retired_at TEXT,
393
+ created_by TEXT NOT NULL,
394
+ created_at TEXT NOT NULL
395
+ );
396
+
397
+ CREATE INDEX budget_policies_scope_idx
398
+ ON budget_policies(installation_id, scope_type, scope_id, metric, retired_at, published_at DESC, id);
399
+
400
+ CREATE TABLE budget_usage (
401
+ policy_id TEXT NOT NULL REFERENCES budget_policies(id) ON DELETE CASCADE,
402
+ window_start TEXT NOT NULL,
403
+ reserved_value INTEGER NOT NULL DEFAULT 0 CHECK (reserved_value >= 0),
404
+ consumed_value INTEGER NOT NULL DEFAULT 0 CHECK (consumed_value >= 0),
405
+ revision INTEGER NOT NULL DEFAULT 1 CHECK (revision >= 1),
406
+ updated_at TEXT NOT NULL,
407
+ PRIMARY KEY (policy_id, window_start)
408
+ );
409
+
410
+ CREATE TABLE budget_reservations (
411
+ id TEXT PRIMARY KEY,
412
+ policy_id TEXT NOT NULL REFERENCES budget_policies(id) ON DELETE CASCADE,
413
+ window_start TEXT NOT NULL,
414
+ operation_type TEXT NOT NULL,
415
+ operation_id TEXT NOT NULL,
416
+ attempt_id TEXT NOT NULL,
417
+ reserved_value INTEGER NOT NULL CHECK (reserved_value >= 0),
418
+ committed_value INTEGER CHECK (committed_value IS NULL OR committed_value >= 0),
419
+ status TEXT NOT NULL CHECK (status IN ('reserved', 'committed', 'released', 'expired')),
420
+ expires_at TEXT NOT NULL,
421
+ created_at TEXT NOT NULL,
422
+ updated_at TEXT NOT NULL,
423
+ UNIQUE (policy_id, operation_id, attempt_id)
424
+ );
425
+
426
+ CREATE INDEX budget_reservations_expiry_idx
427
+ ON budget_reservations(status, expires_at, id);