@obsunified/collector 2.0.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.
Files changed (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/auth.d.ts +2 -0
  4. package/dist/auth.js +9 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/chunk-UGWDOGGH.js +319 -0
  7. package/dist/chunk-UGWDOGGH.js.map +1 -0
  8. package/dist/chunk-XKQTVIRE.js +671 -0
  9. package/dist/chunk-XKQTVIRE.js.map +1 -0
  10. package/dist/index.d.ts +1197 -0
  11. package/dist/index.js +17707 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/ingest-auth-HFVO1zIp.d.ts +165 -0
  14. package/dist/openai-FJYOQ7WO.js +384 -0
  15. package/dist/openai-FJYOQ7WO.js.map +1 -0
  16. package/package.json +73 -0
  17. package/src/ai-parity/ai-parity.acceptance.test.ts +449 -0
  18. package/src/analyses/derive.ts +642 -0
  19. package/src/analyses/index.ts +50 -0
  20. package/src/analyses/investigations.ts +277 -0
  21. package/src/analyses/tier0.ts +568 -0
  22. package/src/auth/dashboard-auth.ts +269 -0
  23. package/src/auth/ingest-auth.ts +147 -0
  24. package/src/durable-objects/tail-hub.test.ts +32 -0
  25. package/src/durable-objects/tail-hub.ts +158 -0
  26. package/src/framework/collector.ts +467 -0
  27. package/src/framework/env.ts +90 -0
  28. package/src/framework/logger.ts +81 -0
  29. package/src/index.ts +211 -0
  30. package/src/lib/action-aggregates.ts +1031 -0
  31. package/src/lib/action-identity.ts +106 -0
  32. package/src/lib/actions-store.ts +397 -0
  33. package/src/lib/ai-pricing.ts +80 -0
  34. package/src/lib/ai-store/calls.ts +148 -0
  35. package/src/lib/ai-store/evaluations.test.ts +47 -0
  36. package/src/lib/ai-store/evaluations.ts +125 -0
  37. package/src/lib/ai-store/helpers.ts +37 -0
  38. package/src/lib/ai-store/retention.ts +17 -0
  39. package/src/lib/ai-store/sessions.ts +277 -0
  40. package/src/lib/ai-store/spans.ts +109 -0
  41. package/src/lib/ai-store/types.ts +112 -0
  42. package/src/lib/ai-store.ts +76 -0
  43. package/src/lib/alerts-store.ts +458 -0
  44. package/src/lib/analyses-runner.ts +439 -0
  45. package/src/lib/analyses-store.test.ts +243 -0
  46. package/src/lib/analyses-store.ts +454 -0
  47. package/src/lib/ask.test.ts +302 -0
  48. package/src/lib/ask.ts +390 -0
  49. package/src/lib/blob-store-s3.ts +213 -0
  50. package/src/lib/blob-store.ts +366 -0
  51. package/src/lib/eval-cases-store.test.ts +171 -0
  52. package/src/lib/eval-cases-store.ts +1033 -0
  53. package/src/lib/evidence-references.test.ts +10 -0
  54. package/src/lib/evidence-references.ts +684 -0
  55. package/src/lib/hash.ts +26 -0
  56. package/src/lib/identity-index/action-lookups.ts +805 -0
  57. package/src/lib/identity-index/constants.ts +1 -0
  58. package/src/lib/identity-index/key-lookups.ts +199 -0
  59. package/src/lib/identity-index/mappers.ts +349 -0
  60. package/src/lib/identity-index/types.ts +196 -0
  61. package/src/lib/identity-index/user-lookup.ts +137 -0
  62. package/src/lib/identity-index.test.ts +624 -0
  63. package/src/lib/identity-index.ts +85 -0
  64. package/src/lib/json.ts +39 -0
  65. package/src/lib/llm.ts +263 -0
  66. package/src/lib/logs-store.ts +188 -0
  67. package/src/lib/metrics-store.test.ts +189 -0
  68. package/src/lib/metrics-store.ts +312 -0
  69. package/src/lib/narrate-gate.test.ts +260 -0
  70. package/src/lib/narrate-gate.ts +253 -0
  71. package/src/lib/openai.test.ts +300 -0
  72. package/src/lib/openai.ts +512 -0
  73. package/src/lib/otlp.ts +212 -0
  74. package/src/lib/parse-pprof.test.ts +64 -0
  75. package/src/lib/parse-pprof.ts +184 -0
  76. package/src/lib/payload-capture.ts +22 -0
  77. package/src/lib/projects-store.ts +207 -0
  78. package/src/lib/propagation-metric.test.ts +196 -0
  79. package/src/lib/propagation-metric.ts +175 -0
  80. package/src/lib/sql-db-dialect.test.ts +22 -0
  81. package/src/lib/sql-db-postgres.ts +229 -0
  82. package/src/lib/sql-db.ts +166 -0
  83. package/src/lib/stage6.test.ts +216 -0
  84. package/src/lib/store/export.ts +65 -0
  85. package/src/lib/store/helpers.ts +367 -0
  86. package/src/lib/store/ingest.ts +68 -0
  87. package/src/lib/store/issues.ts +158 -0
  88. package/src/lib/store/overview.ts +127 -0
  89. package/src/lib/store/retention.ts +10 -0
  90. package/src/lib/store/service-map.ts +384 -0
  91. package/src/lib/store/trace-detail.bench.ts +76 -0
  92. package/src/lib/store/trace-detail.test.ts +410 -0
  93. package/src/lib/store/trace-detail.ts +427 -0
  94. package/src/lib/store/trace-queries.test.ts +29 -0
  95. package/src/lib/store/trace-queries.ts +89 -0
  96. package/src/lib/store-overview.test.ts +77 -0
  97. package/src/lib/store.ts +96 -0
  98. package/src/lib/tail-publisher.ts +64 -0
  99. package/src/lib/test-utils/mem-sql-db.test.ts +93 -0
  100. package/src/lib/test-utils/mem-sql-db.ts +86 -0
  101. package/src/lib/ua-parser.ts +61 -0
  102. package/src/lib/usage-store.ts +567 -0
  103. package/src/migrations/001_telemetry_spans.sql +28 -0
  104. package/src/migrations/002_usage_events.sql +24 -0
  105. package/src/migrations/003_usage_analytics_columns.sql +13 -0
  106. package/src/migrations/004_logs.sql +19 -0
  107. package/src/migrations/005_ai_calls.sql +25 -0
  108. package/src/migrations/006_user_profiles.sql +11 -0
  109. package/src/migrations/007_session_replay_metadata.sql +10 -0
  110. package/src/migrations/008_session_replay_storage_bytes.sql +1 -0
  111. package/src/migrations/009_projects_and_keys.sql +22 -0
  112. package/src/migrations/010_signal_project_id.sql +15 -0
  113. package/src/migrations/011_default_project_seed.sql +3 -0
  114. package/src/migrations/012_alert_rules.sql +17 -0
  115. package/src/migrations/013_alert_evaluations.sql +13 -0
  116. package/src/migrations/014_alert_state.sql +9 -0
  117. package/src/migrations/015_metrics.sql +58 -0
  118. package/src/migrations/016_metrics_exp_histogram_summary.sql +5 -0
  119. package/src/migrations/017_span_dropped_counts.sql +11 -0
  120. package/src/migrations/018_log_flags.sql +8 -0
  121. package/src/migrations/019_ai_span_payloads.sql +30 -0
  122. package/src/migrations/020_ai_span_evaluations.sql +33 -0
  123. package/src/migrations/021_ai_span_session.sql +13 -0
  124. package/src/migrations/022_span_log_session_id.sql +13 -0
  125. package/src/migrations/023_service_map_indexes.sql +32 -0
  126. package/src/migrations/024_analysis_results.sql +49 -0
  127. package/src/migrations/025_stage6_autopinning_alerts.sql +38 -0
  128. package/src/migrations/026_obs_dashboard_project_seed.sql +18 -0
  129. package/src/migrations/027_identity_propagation.sql +50 -0
  130. package/src/migrations/028_profile_blobs.sql +57 -0
  131. package/src/migrations/029_telemetry_sdk_name.sql +20 -0
  132. package/src/migrations/030_analysis_claim.sql +18 -0
  133. package/src/migrations/031_agent_action_graph.sql +154 -0
  134. package/src/migrations/032_payload_capture_flags.sql +8 -0
  135. package/src/migrations/033_eval_cases.sql +52 -0
  136. package/src/migrations/034_eval_case_results.sql +23 -0
  137. package/src/migrations/035_metric_exemplars.sql +33 -0
  138. package/src/migrations/036_trace_instrumentation_gaps.sql +19 -0
  139. package/src/migrations/037_eval_runs.sql +37 -0
  140. package/src/migrations/038_tool_call_evidence.sql +11 -0
  141. package/src/migrations/039_drop_trace_instrumentation_gaps.sql +11 -0
  142. package/src/migrations/040_evidence_retrieval_refs.sql +50 -0
  143. package/src/migrations-postgres/001_telemetry_spans.sql +33 -0
  144. package/src/migrations-postgres/002_usage_events.sql +24 -0
  145. package/src/migrations-postgres/003_usage_analytics_columns.sql +13 -0
  146. package/src/migrations-postgres/004_logs.sql +19 -0
  147. package/src/migrations-postgres/005_ai_calls.sql +25 -0
  148. package/src/migrations-postgres/006_user_profiles.sql +11 -0
  149. package/src/migrations-postgres/007_session_replay_metadata.sql +10 -0
  150. package/src/migrations-postgres/008_session_replay_storage_bytes.sql +2 -0
  151. package/src/migrations-postgres/009_projects_and_keys.sql +25 -0
  152. package/src/migrations-postgres/010_signal_project_id.sql +18 -0
  153. package/src/migrations-postgres/011_default_project_seed.sql +5 -0
  154. package/src/migrations-postgres/012_alert_rules.sql +17 -0
  155. package/src/migrations-postgres/013_alert_evaluations.sql +13 -0
  156. package/src/migrations-postgres/014_alert_state.sql +9 -0
  157. package/src/migrations-postgres/015_metrics.sql +47 -0
  158. package/src/migrations-postgres/016_metrics_exp_histogram_summary.sql +1 -0
  159. package/src/migrations-postgres/017_span_dropped_counts.sql +4 -0
  160. package/src/migrations-postgres/018_log_flags.sql +2 -0
  161. package/src/migrations-postgres/019_ai_span_payloads.sql +18 -0
  162. package/src/migrations-postgres/020_ai_span_evaluations.sql +21 -0
  163. package/src/migrations-postgres/021_ai_span_session.sql +7 -0
  164. package/src/migrations-postgres/022_span_log_session_id.sql +7 -0
  165. package/src/migrations-postgres/023_service_map_indexes.sql +9 -0
  166. package/src/migrations-postgres/024_analysis_results.sql +41 -0
  167. package/src/migrations-postgres/025_stage6_autopinning_alerts.sql +17 -0
  168. package/src/migrations-postgres/026_obs_dashboard_project_seed.sql +14 -0
  169. package/src/migrations-postgres/027_identity_propagation.sql +27 -0
  170. package/src/migrations-postgres/028_profile_blobs.sql +48 -0
  171. package/src/migrations-postgres/029_telemetry_sdk_name.sql +5 -0
  172. package/src/migrations-postgres/030_analysis_claim.sql +5 -0
  173. package/src/migrations-postgres/031_agent_action_graph.sql +190 -0
  174. package/src/migrations-postgres/032_payload_capture_flags.sql +8 -0
  175. package/src/migrations-postgres/033_eval_cases.sql +55 -0
  176. package/src/migrations-postgres/034_eval_case_results.sql +26 -0
  177. package/src/migrations-postgres/035_metric_exemplars.sql +31 -0
  178. package/src/migrations-postgres/036_trace_instrumentation_gaps.sql +19 -0
  179. package/src/migrations-postgres/037_eval_runs.sql +40 -0
  180. package/src/migrations-postgres/038_tool_call_evidence.sql +11 -0
  181. package/src/migrations-postgres/039_drop_trace_instrumentation_gaps.sql +11 -0
  182. package/src/migrations-postgres/040_evidence_retrieval_refs.sql +47 -0
  183. package/src/migrations-postgres/README.md +40 -0
  184. package/src/otlp/acceptance.test.ts +373 -0
  185. package/src/otlp/decode/body.ts +127 -0
  186. package/src/otlp/decode/logs.ts +96 -0
  187. package/src/otlp/decode/metrics.ts +402 -0
  188. package/src/otlp/decode/traces.ts +92 -0
  189. package/src/otlp/decode/values.ts +150 -0
  190. package/src/otlp/decode.test.ts +800 -0
  191. package/src/otlp/decode.ts +11 -0
  192. package/src/otlp/gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.ts +132 -0
  193. package/src/otlp/gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.ts +158 -0
  194. package/src/otlp/gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.ts +158 -0
  195. package/src/otlp/gen/opentelemetry/proto/common/v1/common_pb.ts +289 -0
  196. package/src/otlp/gen/opentelemetry/proto/logs/v1/logs_pb.ts +397 -0
  197. package/src/otlp/gen/opentelemetry/proto/metrics/v1/metrics_pb.ts +1329 -0
  198. package/src/otlp/gen/opentelemetry/proto/resource/v1/resource_pb.ts +86 -0
  199. package/src/otlp/gen/opentelemetry/proto/trace/v1/trace_pb.ts +710 -0
  200. package/src/otlp/response.test.ts +158 -0
  201. package/src/otlp/response.ts +129 -0
  202. package/src/plugins/_context.ts +15 -0
  203. package/src/plugins/action-graph-processor/enrichers.ts +45 -0
  204. package/src/plugins/action-graph-processor/redaction.ts +84 -0
  205. package/src/plugins/action-graph-processor.test.ts +1023 -0
  206. package/src/plugins/action-graph-processor.ts +1172 -0
  207. package/src/plugins/action-routes.test.ts +716 -0
  208. package/src/plugins/action-routes.ts +343 -0
  209. package/src/plugins/ai-receiver.ts +254 -0
  210. package/src/plugins/ai-span-payloads-processor.test.ts +90 -0
  211. package/src/plugins/ai-span-payloads-processor.ts +180 -0
  212. package/src/plugins/alerts-evaluator.test.ts +91 -0
  213. package/src/plugins/alerts-evaluator.ts +328 -0
  214. package/src/plugins/alerts-routes.ts +101 -0
  215. package/src/plugins/analyses-routes.ts +138 -0
  216. package/src/plugins/ask-routes.ts +182 -0
  217. package/src/plugins/bot-filter.ts +19 -0
  218. package/src/plugins/connected-routes/manifest.ts +531 -0
  219. package/src/plugins/connected-routes.test.ts +1791 -0
  220. package/src/plugins/connected-routes.ts +1103 -0
  221. package/src/plugins/dashboard-routes.ts +41 -0
  222. package/src/plugins/default-span-enrichment.ts +92 -0
  223. package/src/plugins/eval-cases-routes.test.ts +391 -0
  224. package/src/plugins/eval-cases-routes.ts +529 -0
  225. package/src/plugins/evidence-retrieval-routes.benchmark.test.ts +245 -0
  226. package/src/plugins/evidence-retrieval-routes.test.ts +932 -0
  227. package/src/plugins/evidence-retrieval-routes.ts +2179 -0
  228. package/src/plugins/gen-ai-normalizer.test.ts +680 -0
  229. package/src/plugins/gen-ai-normalizer.ts +302 -0
  230. package/src/plugins/identity-receiver.ts +96 -0
  231. package/src/plugins/issue-enrichment.ts +132 -0
  232. package/src/plugins/issue-insights.ts +81 -0
  233. package/src/plugins/logs-receiver.ts +160 -0
  234. package/src/plugins/metrics-receiver.ts +91 -0
  235. package/src/plugins/onboarding-routes.ts +54 -0
  236. package/src/plugins/otlp-receiver.ts +124 -0
  237. package/src/plugins/platform-routes.ts +165 -0
  238. package/src/plugins/profile-routes.ts +468 -0
  239. package/src/plugins/projects-routes.ts +92 -0
  240. package/src/plugins/query-routes.ts +220 -0
  241. package/src/plugins/redaction-processor.ts +132 -0
  242. package/src/plugins/replay-query-routes.test.ts +38 -0
  243. package/src/plugins/replay-query-routes.ts +199 -0
  244. package/src/plugins/replay-receiver.ts +81 -0
  245. package/src/plugins/tail-routes.test.ts +47 -0
  246. package/src/plugins/tail-routes.ts +42 -0
  247. package/src/plugins/timeline-routes.ts +244 -0
  248. package/src/plugins/ua-enrichment.ts +27 -0
  249. package/src/plugins/usage-normalization.ts +46 -0
  250. package/src/plugins/usage-privacy.ts +55 -0
  251. package/src/plugins/usage-query-routes.ts +102 -0
  252. package/src/plugins/usage-receiver.ts +129 -0
  253. package/src/plugins/users-query-routes.ts +78 -0
  254. package/src/plugins/utm-enrichment.ts +36 -0
@@ -0,0 +1,154 @@
1
+ -- RFC 0010: Agent Action Graph Spine Schema (Phase 1)
2
+ --
3
+ -- Creates the action spine and detail leaf tables, and extends existing tables
4
+ -- to support higher-level causal action tracing for agentic systems.
5
+
6
+ -- 1. General Action Spine
7
+ CREATE TABLE IF NOT EXISTS actions (
8
+ id TEXT PRIMARY KEY, -- Unique ULID / ID for this action
9
+ project_id TEXT NOT NULL, -- Project scope
10
+ root_action_id TEXT NOT NULL, -- ULID of the root causal action
11
+ caused_by_action_id TEXT, -- ULID of the parent causal action
12
+ actor_type TEXT NOT NULL, -- human, agent, service, workflow, system
13
+ actor_id TEXT, -- ID of the actor initiating this action
14
+ action_kind TEXT NOT NULL, -- agent.run, agent.step, llm.call, tool.call, retrieval, eval, etc.
15
+ name TEXT, -- Human readable name
16
+ status TEXT NOT NULL DEFAULT 'ok', -- ok, error
17
+ started_at TEXT NOT NULL, -- ISO8601 timestamp
18
+ ended_at TEXT, -- ISO8601 timestamp
19
+ duration_ms INTEGER, -- Execution duration
20
+ trace_id TEXT, -- Optional linked OTel trace ID
21
+ span_id TEXT, -- Optional linked OTel span ID
22
+ session_id TEXT, -- Optional browser/user session
23
+ interaction_id TEXT, -- Optional click-scoped correlation key
24
+ user_id TEXT, -- Optional user ID
25
+ agent_run_id TEXT, -- Optional linked Agent Run ID
26
+ step_id TEXT, -- Optional linked Step ID
27
+ tool_call_id TEXT, -- Optional linked Tool Call ID
28
+ prompt_version TEXT, -- Denormalized prompt version
29
+ model_name TEXT, -- Denormalized LLM model name
30
+ provider TEXT, -- Denormalized LLM provider name
31
+ total_cost_usd REAL, -- Denormalized token/tool cost
32
+ attrs_json TEXT -- Arbitrary JSON key-value store for plugin/custom data
33
+ );
34
+
35
+ -- Indices for fast spine traversal
36
+ CREATE INDEX IF NOT EXISTS idx_actions_project_root
37
+ ON actions (project_id, root_action_id, started_at);
38
+
39
+ CREATE INDEX IF NOT EXISTS idx_actions_project_actor
40
+ ON actions (project_id, actor_type, actor_id, started_at DESC);
41
+
42
+ CREATE INDEX IF NOT EXISTS idx_actions_project_trace
43
+ ON actions (project_id, trace_id)
44
+ WHERE trace_id IS NOT NULL;
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_actions_project_interaction
47
+ ON actions (project_id, interaction_id)
48
+ WHERE interaction_id IS NOT NULL;
49
+
50
+ CREATE INDEX IF NOT EXISTS idx_actions_project_agent_run
51
+ ON actions (project_id, agent_run_id, started_at)
52
+ WHERE agent_run_id IS NOT NULL;
53
+
54
+
55
+ -- 2. Detail Leaf: Agent Runs
56
+ CREATE TABLE IF NOT EXISTS agent_runs (
57
+ id TEXT PRIMARY KEY, -- Matches actions.id for the run's root action
58
+ project_id TEXT NOT NULL,
59
+ agent_id TEXT NOT NULL, -- Stable identifier of the agent template/codebase
60
+ agent_name TEXT NOT NULL, -- Human-readable name of the agent
61
+ agent_version TEXT NOT NULL, -- Version of agent configuration/strategy
62
+ goal TEXT, -- High-level prompt or goal of the run
63
+ outcome TEXT, -- Final answer, result summary, or output
64
+ autonomy_level TEXT NOT NULL, -- read_only, suggested_action, human_approved_write, autonomous_write, blocked_by_policy
65
+ status TEXT NOT NULL DEFAULT 'running', -- running, success, failed
66
+ error_message TEXT, -- Optional error string
67
+ total_cost_usd REAL DEFAULT 0.0,
68
+ total_duration_ms INTEGER,
69
+ metadata_json TEXT -- Opt-in debug metadata
70
+ );
71
+
72
+ CREATE INDEX IF NOT EXISTS idx_agent_runs_project_agent
73
+ ON agent_runs (project_id, agent_id, status);
74
+
75
+
76
+ -- 3. Detail Leaf: Tool Calls
77
+ CREATE TABLE IF NOT EXISTS tool_calls (
78
+ id TEXT PRIMARY KEY, -- Unique identifier (often matches OTel span_id or actions.id)
79
+ action_id TEXT NOT NULL, -- Links back to actions.id
80
+ project_id TEXT NOT NULL,
81
+ tool_name TEXT NOT NULL, -- Named tool (e.g. sql_query, fetch_invoice)
82
+ args_hash TEXT NOT NULL, -- SHA256 of args for privacy-preserving cache key
83
+ result_hash TEXT NOT NULL, -- SHA256 of result for parity verification
84
+ error_type TEXT, -- Optional error classifier (e.g. timeout, auth)
85
+ side_effect INTEGER NOT NULL DEFAULT 0, -- Boolean (0/1): does this tool mutate state?
86
+ approval_state TEXT, -- suggested, human_approved, bypassed, blocked
87
+ args_redacted TEXT, -- Opt-in redacted parameters JSON
88
+ result_redacted TEXT -- Opt-in redacted result JSON
89
+ );
90
+
91
+ CREATE INDEX IF NOT EXISTS idx_tool_calls_action
92
+ ON tool_calls (action_id);
93
+
94
+ CREATE INDEX IF NOT EXISTS idx_tool_calls_name
95
+ ON tool_calls (project_id, tool_name);
96
+
97
+
98
+ -- 4. Detail Leaf: Retrieval Events
99
+ CREATE TABLE IF NOT EXISTS retrieval_events (
100
+ id TEXT PRIMARY KEY,
101
+ action_id TEXT NOT NULL, -- Links back to actions.id
102
+ project_id TEXT NOT NULL,
103
+ retriever_name TEXT NOT NULL, -- Name of vector DB or retriever system
104
+ query_hash TEXT NOT NULL, -- SHA-256 of the retrieval query string
105
+ documents_json TEXT, -- Array of { docId, score, sourceId, snippet_preview }
106
+ total_results INTEGER NOT NULL DEFAULT 0,
107
+ max_relevance_score REAL,
108
+ duration_ms INTEGER
109
+ );
110
+
111
+ CREATE INDEX IF NOT EXISTS idx_retrieval_events_action
112
+ ON retrieval_events (action_id);
113
+
114
+
115
+ -- 5. Detail Leaf: Evaluation & Guardrail Results
116
+ CREATE TABLE IF NOT EXISTS eval_results (
117
+ id TEXT PRIMARY KEY,
118
+ action_id TEXT NOT NULL, -- Links back to actions.id
119
+ project_id TEXT NOT NULL,
120
+ evaluator_name TEXT NOT NULL, -- Name of the evaluator or guardrail (e.g. groundedness)
121
+ evaluator_version TEXT NOT NULL, -- Grader version
122
+ score REAL, -- Numeric metric between 0.0 and 1.0
123
+ passed INTEGER NOT NULL DEFAULT 1, -- Boolean (0/1) for binary policy gates
124
+ reasoning TEXT, -- Explanation or chain-of-thought of the grader
125
+ rubric_json TEXT -- Optional grader schema or rubric details
126
+ );
127
+
128
+ CREATE INDEX IF NOT EXISTS idx_eval_results_action
129
+ ON eval_results (action_id);
130
+
131
+
132
+ -- 6. Detail Leaf: Generated Artifacts
133
+ CREATE TABLE IF NOT EXISTS artifacts (
134
+ id TEXT PRIMARY KEY,
135
+ action_id TEXT NOT NULL, -- Links back to actions.id
136
+ project_id TEXT NOT NULL,
137
+ artifact_name TEXT NOT NULL, -- e.g. "invoice-pdf"
138
+ artifact_type TEXT NOT NULL, -- file, patch, text, message, data
139
+ storage_ref TEXT, -- S3 / Blob reference
140
+ size_bytes INTEGER,
141
+ sha256_hash TEXT,
142
+ content_preview TEXT -- Redacted preview or summary
143
+ );
144
+
145
+ CREATE INDEX IF NOT EXISTS idx_artifacts_action
146
+ ON artifacts (action_id);
147
+
148
+
149
+ -- 7. Extend Existing AI Span Payloads Table
150
+ ALTER TABLE ai_span_payloads ADD COLUMN action_id TEXT;
151
+
152
+ CREATE INDEX IF NOT EXISTS idx_ai_payloads_action
153
+ ON ai_span_payloads (project_id, action_id)
154
+ WHERE action_id IS NOT NULL;
@@ -0,0 +1,8 @@
1
+ ALTER TABLE projects
2
+ ADD COLUMN payload_capture_enabled INTEGER NOT NULL DEFAULT 0;
3
+
4
+ ALTER TABLE ai_span_payloads
5
+ ADD COLUMN input_hash TEXT;
6
+
7
+ ALTER TABLE ai_span_payloads
8
+ ADD COLUMN output_hash TEXT;
@@ -0,0 +1,52 @@
1
+ -- RFC 0010 Phase 7: production-to-eval case persistence.
2
+ --
3
+ -- Eval cases are reusable fixtures captured from production telemetry. They
4
+ -- retain stable source links back to the production entity that created the
5
+ -- case while keeping prompts/payloads in explicitly redacted JSON fields.
6
+
7
+ CREATE TABLE IF NOT EXISTS eval_cases (
8
+ id TEXT PRIMARY KEY,
9
+ project_id TEXT NOT NULL,
10
+ source_entity_type TEXT NOT NULL,
11
+ source_entity_id TEXT NOT NULL,
12
+ source_agent_run_id TEXT,
13
+ source_action_id TEXT,
14
+ source_ai_call_id TEXT,
15
+ source_tool_call_id TEXT,
16
+ source_trace_id TEXT,
17
+ source_span_id TEXT,
18
+ name TEXT NOT NULL,
19
+ expected_outcome TEXT,
20
+ rubric_json TEXT,
21
+ redacted_prompt_json TEXT,
22
+ reference_payload_json TEXT,
23
+ metadata_json TEXT NOT NULL DEFAULT '{}',
24
+ created_at TEXT NOT NULL,
25
+ updated_at TEXT NOT NULL
26
+ );
27
+
28
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_project_created
29
+ ON eval_cases (project_id, created_at DESC);
30
+
31
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_project_source
32
+ ON eval_cases (project_id, source_entity_type, source_entity_id, created_at DESC);
33
+
34
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_agent_run
35
+ ON eval_cases (project_id, source_agent_run_id)
36
+ WHERE source_agent_run_id IS NOT NULL;
37
+
38
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_action
39
+ ON eval_cases (project_id, source_action_id)
40
+ WHERE source_action_id IS NOT NULL;
41
+
42
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_ai_call
43
+ ON eval_cases (project_id, source_ai_call_id)
44
+ WHERE source_ai_call_id IS NOT NULL;
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_tool_call
47
+ ON eval_cases (project_id, source_tool_call_id)
48
+ WHERE source_tool_call_id IS NOT NULL;
49
+
50
+ CREATE INDEX IF NOT EXISTS idx_eval_cases_trace
51
+ ON eval_cases (project_id, source_trace_id)
52
+ WHERE source_trace_id IS NOT NULL;
@@ -0,0 +1,23 @@
1
+ -- RFC 0010 Phase 7: reusable eval-case run results.
2
+ --
3
+ -- Results are produced by offline or CI evaluators against a saved production
4
+ -- eval case. They intentionally store compact comparison metadata rather than
5
+ -- raw prompts or completions.
6
+
7
+ CREATE TABLE IF NOT EXISTS eval_case_results (
8
+ id TEXT PRIMARY KEY,
9
+ project_id TEXT NOT NULL,
10
+ eval_case_id TEXT NOT NULL,
11
+ run_id TEXT NOT NULL,
12
+ passed INTEGER NOT NULL,
13
+ score REAL,
14
+ actual_outcome TEXT,
15
+ details_json TEXT,
16
+ created_at TEXT NOT NULL
17
+ );
18
+
19
+ CREATE INDEX IF NOT EXISTS idx_eval_case_results_case_created
20
+ ON eval_case_results (project_id, eval_case_id, created_at DESC);
21
+
22
+ CREATE INDEX IF NOT EXISTS idx_eval_case_results_run
23
+ ON eval_case_results (project_id, run_id);
@@ -0,0 +1,33 @@
1
+ -- Reverse index for OTLP metric exemplars.
2
+ --
3
+ -- metric_point.exemplars_json preserves the raw exemplar payload on the point,
4
+ -- but investigation flows need trace/span lookup without scanning JSON blobs.
5
+ -- This table turns exemplars into first-class correlation edges.
6
+
7
+ CREATE TABLE IF NOT EXISTS metric_exemplars (
8
+ id TEXT PRIMARY KEY,
9
+ point_id TEXT NOT NULL,
10
+ series_id TEXT NOT NULL,
11
+ project_id TEXT NOT NULL,
12
+ metric_name TEXT NOT NULL,
13
+ service_name TEXT,
14
+ trace_id TEXT,
15
+ span_id TEXT,
16
+ ts_ns TEXT NOT NULL,
17
+ value REAL NOT NULL,
18
+ received_at TEXT NOT NULL,
19
+ expires_at TEXT NOT NULL,
20
+ FOREIGN KEY (point_id) REFERENCES metric_point(id),
21
+ FOREIGN KEY (series_id) REFERENCES metric_series(id)
22
+ );
23
+
24
+ CREATE INDEX IF NOT EXISTS idx_metric_exemplars_project_trace
25
+ ON metric_exemplars (project_id, trace_id, ts_ns)
26
+ WHERE trace_id IS NOT NULL;
27
+
28
+ CREATE INDEX IF NOT EXISTS idx_metric_exemplars_project_span
29
+ ON metric_exemplars (project_id, trace_id, span_id, ts_ns)
30
+ WHERE trace_id IS NOT NULL AND span_id IS NOT NULL;
31
+
32
+ CREATE INDEX IF NOT EXISTS idx_metric_exemplars_expires
33
+ ON metric_exemplars (expires_at);
@@ -0,0 +1,19 @@
1
+ -- SQLite/D1 migration 036_trace_instrumentation_gaps.sql
2
+ -- Computes and persists uninstrumented trace gaps during span ingestion.
3
+
4
+ CREATE TABLE IF NOT EXISTS trace_instrumentation_gaps (
5
+ trace_id TEXT NOT NULL,
6
+ parent_span_id TEXT NOT NULL,
7
+ parent_service_name TEXT NOT NULL,
8
+ parent_span_name TEXT NOT NULL,
9
+ offset_ms INTEGER NOT NULL,
10
+ duration_ms INTEGER NOT NULL,
11
+ ratio_of_parent REAL NOT NULL,
12
+ child_span_count INTEGER NOT NULL,
13
+ async_parent INTEGER NOT NULL, -- 0/1 boolean (async parent gap)
14
+ recommendation TEXT NOT NULL,
15
+ PRIMARY KEY (trace_id, parent_span_id)
16
+ );
17
+
18
+ CREATE INDEX IF NOT EXISTS idx_trace_gaps_duration
19
+ ON trace_instrumentation_gaps (duration_ms DESC);
@@ -0,0 +1,37 @@
1
+ -- RFC 0010 Phase 7: durable eval runner records.
2
+ --
3
+ -- Eval runs group one or more eval case results under a candidate agent,
4
+ -- prompt, and model configuration so production behavior can be compared with
5
+ -- attempted fixes across repeatable runs.
6
+
7
+ CREATE TABLE IF NOT EXISTS eval_runs (
8
+ id TEXT PRIMARY KEY,
9
+ project_id TEXT NOT NULL,
10
+ eval_case_id TEXT,
11
+ candidate_agent_id TEXT,
12
+ candidate_agent_version TEXT,
13
+ candidate_prompt_id TEXT,
14
+ candidate_prompt_version TEXT,
15
+ candidate_model_provider TEXT,
16
+ candidate_model TEXT,
17
+ candidate_model_version TEXT,
18
+ status TEXT NOT NULL,
19
+ started_at TEXT,
20
+ ended_at TEXT,
21
+ total_count INTEGER NOT NULL DEFAULT 0,
22
+ pass_count INTEGER NOT NULL DEFAULT 0,
23
+ fail_count INTEGER NOT NULL DEFAULT 0,
24
+ average_score REAL,
25
+ metadata_json TEXT NOT NULL DEFAULT '{}',
26
+ created_at TEXT NOT NULL
27
+ );
28
+
29
+ CREATE INDEX IF NOT EXISTS idx_eval_runs_project_created
30
+ ON eval_runs (project_id, created_at DESC);
31
+
32
+ CREATE INDEX IF NOT EXISTS idx_eval_runs_case_created
33
+ ON eval_runs (project_id, eval_case_id, created_at DESC)
34
+ WHERE eval_case_id IS NOT NULL;
35
+
36
+ CREATE INDEX IF NOT EXISTS idx_eval_runs_project_status_created
37
+ ON eval_runs (project_id, status, created_at DESC);
@@ -0,0 +1,11 @@
1
+ -- AI debugging evidence for side-effecting tool calls.
2
+ --
3
+ -- These fields are opt-in evidence channels. They intentionally store only
4
+ -- explicit audit/diff envelopes emitted by instrumentation, not raw tool
5
+ -- arguments, results, or transport metadata.
6
+
7
+ ALTER TABLE tool_calls ADD COLUMN mcp_audit_json TEXT;
8
+ ALTER TABLE tool_calls ADD COLUMN mutation_before_json TEXT;
9
+ ALTER TABLE tool_calls ADD COLUMN mutation_after_json TEXT;
10
+ ALTER TABLE tool_calls ADD COLUMN mutation_diff_json TEXT;
11
+ ALTER TABLE tool_calls ADD COLUMN mutation_artifact_id TEXT;
@@ -0,0 +1,11 @@
1
+ -- Drop the materialized trace instrumentation gaps table.
2
+ --
3
+ -- Trace instrumentation gaps are now computed lazily at read time from the
4
+ -- trace's spans (see `getTelemetryTraceGaps` in lib/store/trace-detail.ts),
5
+ -- rather than being materialized on the ingest hot path. The table and its
6
+ -- index are therefore unused: nothing writes to them, and reads compute gaps
7
+ -- on demand. Dropping the index first is redundant on SQLite (DROP TABLE
8
+ -- removes it) but kept explicit for clarity and Postgres parity.
9
+
10
+ DROP INDEX IF EXISTS idx_trace_gaps_duration;
11
+ DROP TABLE IF EXISTS trace_instrumentation_gaps;
@@ -0,0 +1,50 @@
1
+ -- RFC 0011 — materialized evidence retrieval refs and expansion telemetry.
2
+ --
3
+ -- Encoded refs remain portable handles. This table gives the product a durable
4
+ -- view of which refs were issued and which ones agents actually expand.
5
+
6
+ CREATE TABLE IF NOT EXISTS evidence_retrieval_refs (
7
+ ref_id TEXT PRIMARY KEY,
8
+ project_id TEXT NOT NULL,
9
+ kind TEXT NOT NULL,
10
+ anchor_kind TEXT NOT NULL,
11
+ anchor_id TEXT NOT NULL,
12
+ source TEXT NOT NULL,
13
+ query_json TEXT,
14
+ compacted_from_json TEXT,
15
+ returned_json TEXT,
16
+ issued_at TEXT NOT NULL DEFAULT (datetime('now')),
17
+ last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
18
+ expires_at TEXT
19
+ );
20
+
21
+ CREATE INDEX IF NOT EXISTS idx_evidence_refs_project_seen
22
+ ON evidence_retrieval_refs (project_id, last_seen_at DESC);
23
+
24
+ CREATE INDEX IF NOT EXISTS idx_evidence_refs_project_kind
25
+ ON evidence_retrieval_refs (project_id, kind, last_seen_at DESC);
26
+
27
+ CREATE INDEX IF NOT EXISTS idx_evidence_refs_project_anchor
28
+ ON evidence_retrieval_refs (project_id, anchor_kind, anchor_id);
29
+
30
+ CREATE TABLE IF NOT EXISTS evidence_ref_expansions (
31
+ id TEXT PRIMARY KEY,
32
+ ref_id TEXT NOT NULL,
33
+ project_id TEXT NOT NULL,
34
+ kind TEXT NOT NULL,
35
+ source TEXT,
36
+ operation TEXT NOT NULL,
37
+ result_status TEXT NOT NULL,
38
+ limit_value INTEGER,
39
+ query_text TEXT,
40
+ expanded_at TEXT NOT NULL DEFAULT (datetime('now'))
41
+ );
42
+
43
+ CREATE INDEX IF NOT EXISTS idx_evidence_expansions_project_time
44
+ ON evidence_ref_expansions (project_id, expanded_at DESC);
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_evidence_expansions_project_ref
47
+ ON evidence_ref_expansions (project_id, ref_id, expanded_at DESC);
48
+
49
+ CREATE INDEX IF NOT EXISTS idx_evidence_expansions_project_kind
50
+ ON evidence_ref_expansions (project_id, kind, expanded_at DESC);
@@ -0,0 +1,33 @@
1
+ CREATE TABLE IF NOT EXISTS telemetry_spans (
2
+ trace_id TEXT NOT NULL,
3
+ span_id TEXT NOT NULL,
4
+ parent_span_id TEXT,
5
+ service_name TEXT,
6
+ scope_name TEXT,
7
+ scope_version TEXT,
8
+ span_name TEXT NOT NULL,
9
+ span_kind BIGINT,
10
+ status_code BIGINT,
11
+ status_message TEXT,
12
+ start_time TEXT NOT NULL,
13
+ end_time TEXT NOT NULL,
14
+ duration_ms DOUBLE PRECISION NOT NULL,
15
+ attributes_json JSONB,
16
+ resource_attributes_json JSONB,
17
+ events_json JSONB,
18
+ links_json JSONB,
19
+ received_at TEXT NOT NULL,
20
+ expires_at TEXT NOT NULL,
21
+ PRIMARY KEY (trace_id, span_id)
22
+ );
23
+
24
+ CREATE INDEX IF NOT EXISTS idx_spans_received_at ON telemetry_spans (received_at DESC);
25
+ CREATE INDEX IF NOT EXISTS idx_spans_trace_id ON telemetry_spans (trace_id);
26
+ CREATE INDEX IF NOT EXISTS idx_spans_service ON telemetry_spans (service_name);
27
+ CREATE INDEX IF NOT EXISTS idx_spans_status ON telemetry_spans (status_code);
28
+ CREATE INDEX IF NOT EXISTS idx_spans_root ON telemetry_spans (parent_span_id, received_at DESC);
29
+
30
+ -- Postgres-only: GIN index on attributes_json enables fast JSONB
31
+ -- containment queries used by the dashboard's attribute filter.
32
+ CREATE INDEX IF NOT EXISTS idx_spans_attributes_gin
33
+ ON telemetry_spans USING GIN (attributes_json);
@@ -0,0 +1,24 @@
1
+ CREATE TABLE IF NOT EXISTS usage_events (
2
+ event_id TEXT PRIMARY KEY,
3
+ session_id TEXT NOT NULL,
4
+ visitor_id TEXT NOT NULL,
5
+ event_type TEXT NOT NULL,
6
+ event_name TEXT NOT NULL,
7
+ page_path TEXT,
8
+ page_title TEXT,
9
+ referrer TEXT,
10
+ severity TEXT,
11
+ source TEXT,
12
+ context_json JSONB NOT NULL,
13
+ properties_json JSONB NOT NULL,
14
+ user_agent TEXT,
15
+ occurred_at TEXT NOT NULL,
16
+ received_at TEXT NOT NULL,
17
+ expires_at TEXT NOT NULL
18
+ );
19
+
20
+ CREATE INDEX IF NOT EXISTS idx_usage_received ON usage_events (received_at DESC);
21
+ CREATE INDEX IF NOT EXISTS idx_usage_session ON usage_events (session_id);
22
+ CREATE INDEX IF NOT EXISTS idx_usage_visitor ON usage_events (visitor_id);
23
+ CREATE INDEX IF NOT EXISTS idx_usage_path ON usage_events (page_path);
24
+ CREATE INDEX IF NOT EXISTS idx_usage_type ON usage_events (event_type);
@@ -0,0 +1,13 @@
1
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS country TEXT;
2
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS browser TEXT;
3
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS os TEXT;
4
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS device_type TEXT;
5
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS is_bot BOOLEAN DEFAULT FALSE;
6
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS utm_source TEXT;
7
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS utm_medium TEXT;
8
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS utm_campaign TEXT;
9
+
10
+ CREATE INDEX IF NOT EXISTS idx_usage_country ON usage_events (country);
11
+ CREATE INDEX IF NOT EXISTS idx_usage_bot ON usage_events (is_bot);
12
+ CREATE INDEX IF NOT EXISTS idx_usage_browser ON usage_events (browser);
13
+ CREATE INDEX IF NOT EXISTS idx_usage_utm ON usage_events (utm_source);
@@ -0,0 +1,19 @@
1
+ CREATE TABLE IF NOT EXISTS logs (
2
+ log_id TEXT PRIMARY KEY,
3
+ trace_id TEXT,
4
+ span_id TEXT,
5
+ service_name TEXT,
6
+ severity TEXT NOT NULL,
7
+ severity_number BIGINT NOT NULL,
8
+ logger_name TEXT,
9
+ message TEXT NOT NULL,
10
+ attributes_json JSONB,
11
+ occurred_at TEXT NOT NULL,
12
+ received_at TEXT NOT NULL,
13
+ expires_at TEXT NOT NULL
14
+ );
15
+
16
+ CREATE INDEX IF NOT EXISTS idx_logs_received ON logs (received_at DESC);
17
+ CREATE INDEX IF NOT EXISTS idx_logs_trace ON logs (trace_id);
18
+ CREATE INDEX IF NOT EXISTS idx_logs_service ON logs (service_name);
19
+ CREATE INDEX IF NOT EXISTS idx_logs_severity ON logs (severity_number);
@@ -0,0 +1,25 @@
1
+ CREATE TABLE IF NOT EXISTS ai_calls (
2
+ call_id TEXT PRIMARY KEY,
3
+ trace_id TEXT,
4
+ span_id TEXT,
5
+ service_name TEXT,
6
+ model_name TEXT NOT NULL,
7
+ provider TEXT NOT NULL,
8
+ call_type TEXT NOT NULL, -- 'text_completion', 'chat', 'prompt_to_image', 'embedding'
9
+ request_json JSONB, -- raw prompt/messages or image configuration
10
+ response_json JSONB, -- raw completion text or image URLs
11
+ prompt_tokens BIGINT,
12
+ completion_tokens BIGINT,
13
+ total_cost_usd DOUBLE PRECISION,
14
+ latency_ms DOUBLE PRECISION,
15
+ is_error BOOLEAN DEFAULT FALSE,
16
+ error_message TEXT,
17
+ occurred_at TEXT NOT NULL,
18
+ received_at TEXT NOT NULL,
19
+ expires_at TEXT NOT NULL
20
+ );
21
+
22
+ CREATE INDEX IF NOT EXISTS idx_aicalls_received ON ai_calls (received_at DESC);
23
+ CREATE INDEX IF NOT EXISTS idx_aicalls_trace ON ai_calls (trace_id);
24
+ CREATE INDEX IF NOT EXISTS idx_aicalls_service ON ai_calls (service_name);
25
+ CREATE INDEX IF NOT EXISTS idx_aicalls_model ON ai_calls (model_name);
@@ -0,0 +1,11 @@
1
+ CREATE TABLE IF NOT EXISTS user_profiles (
2
+ user_id TEXT PRIMARY KEY,
3
+ visitor_id TEXT NOT NULL,
4
+ email TEXT,
5
+ name TEXT,
6
+ properties_json JSONB, -- custom traits (plan_tier, role)
7
+ first_seen_at TEXT NOT NULL,
8
+ last_seen_at TEXT NOT NULL
9
+ );
10
+
11
+ CREATE INDEX IF NOT EXISTS idx_user_visitor ON user_profiles (visitor_id);
@@ -0,0 +1,10 @@
1
+ CREATE TABLE IF NOT EXISTS session_replay_metadata (
2
+ session_id TEXT PRIMARY KEY,
3
+ visitor_id TEXT NOT NULL,
4
+ first_chunk_at TEXT NOT NULL,
5
+ last_chunk_at TEXT NOT NULL,
6
+ chunk_count BIGINT DEFAULT 0,
7
+ events_count BIGINT DEFAULT 0
8
+ );
9
+
10
+ CREATE INDEX IF NOT EXISTS idx_replay_visitor ON session_replay_metadata (visitor_id);
@@ -0,0 +1,2 @@
1
+ ALTER TABLE session_replay_metadata
2
+ ADD COLUMN IF NOT EXISTS storage_bytes BIGINT NOT NULL DEFAULT 0;
@@ -0,0 +1,25 @@
1
+ CREATE TABLE IF NOT EXISTS projects (
2
+ id TEXT PRIMARY KEY,
3
+ name TEXT NOT NULL,
4
+ slug TEXT NOT NULL UNIQUE,
5
+ created_at TEXT NOT NULL
6
+ );
7
+
8
+ CREATE INDEX IF NOT EXISTS idx_projects_slug ON projects (slug);
9
+
10
+ CREATE TABLE IF NOT EXISTS ingest_keys (
11
+ id TEXT PRIMARY KEY,
12
+ project_id TEXT NOT NULL,
13
+ -- D1 used TEXT for the bcrypt hash. Postgres stores it as BYTEA so
14
+ -- the column-comparison code in ingest-auth.ts (constant-time
15
+ -- compare via bytes) doesn't pay a UTF-8 decode cost on every check.
16
+ key_hash BYTEA NOT NULL UNIQUE,
17
+ key_prefix TEXT NOT NULL,
18
+ name TEXT NOT NULL,
19
+ created_at TEXT NOT NULL,
20
+ revoked_at TEXT,
21
+ FOREIGN KEY (project_id) REFERENCES projects (id)
22
+ );
23
+
24
+ CREATE INDEX IF NOT EXISTS idx_ingest_keys_project ON ingest_keys (project_id, revoked_at);
25
+ CREATE INDEX IF NOT EXISTS idx_ingest_keys_hash ON ingest_keys (key_hash);
@@ -0,0 +1,18 @@
1
+ -- Add project_id to every signal table. DEFAULT 'default' backfills
2
+ -- existing rows so multi-tenant queries continue to work with a
3
+ -- sentinel project for un-tagged emissions.
4
+
5
+ ALTER TABLE telemetry_spans ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT 'default';
6
+ ALTER TABLE logs ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT 'default';
7
+ ALTER TABLE usage_events ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT 'default';
8
+ ALTER TABLE ai_calls ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT 'default';
9
+ ALTER TABLE session_replay_metadata ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT 'default';
10
+ ALTER TABLE user_profiles ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT 'default';
11
+
12
+ -- Composite indexes for project-scoped queries.
13
+ CREATE INDEX IF NOT EXISTS idx_spans_project_received ON telemetry_spans (project_id, received_at DESC);
14
+ CREATE INDEX IF NOT EXISTS idx_logs_project_received ON logs (project_id, received_at DESC);
15
+ CREATE INDEX IF NOT EXISTS idx_usage_project_received ON usage_events (project_id, received_at DESC);
16
+ CREATE INDEX IF NOT EXISTS idx_ai_project_received ON ai_calls (project_id, received_at DESC);
17
+ CREATE INDEX IF NOT EXISTS idx_replay_project_last ON session_replay_metadata (project_id, last_chunk_at DESC);
18
+ CREATE INDEX IF NOT EXISTS idx_users_project_last ON user_profiles (project_id, last_seen_at DESC);
@@ -0,0 +1,5 @@
1
+ -- Seed the default project. Existing rows already carry project_id='default'
2
+ -- via migration 010's column default.
3
+ INSERT INTO projects (id, name, slug, created_at)
4
+ VALUES ('default', 'Default', 'default', now()::text)
5
+ ON CONFLICT (id) DO NOTHING;
@@ -0,0 +1,17 @@
1
+ CREATE TABLE IF NOT EXISTS alert_rules (
2
+ id TEXT PRIMARY KEY,
3
+ project_id TEXT NOT NULL,
4
+ name TEXT NOT NULL,
5
+ signal TEXT NOT NULL,
6
+ query_json JSONB NOT NULL,
7
+ threshold DOUBLE PRECISION NOT NULL,
8
+ window_mins INTEGER NOT NULL,
9
+ comparison TEXT NOT NULL,
10
+ channels_json JSONB NOT NULL,
11
+ enabled INTEGER NOT NULL DEFAULT 1,
12
+ created_at TEXT NOT NULL,
13
+ updated_at TEXT NOT NULL,
14
+ FOREIGN KEY (project_id) REFERENCES projects(id)
15
+ );
16
+
17
+ CREATE INDEX IF NOT EXISTS idx_alert_rules_project ON alert_rules (project_id, enabled);
@@ -0,0 +1,13 @@
1
+ CREATE TABLE IF NOT EXISTS alert_evaluations (
2
+ id TEXT PRIMARY KEY,
3
+ rule_id TEXT NOT NULL,
4
+ project_id TEXT NOT NULL,
5
+ evaluated_at TEXT NOT NULL,
6
+ value DOUBLE PRECISION NOT NULL,
7
+ state TEXT NOT NULL,
8
+ notified INTEGER NOT NULL DEFAULT 0,
9
+ FOREIGN KEY (rule_id) REFERENCES alert_rules(id)
10
+ );
11
+
12
+ CREATE INDEX IF NOT EXISTS idx_alert_eval_rule_time ON alert_evaluations (rule_id, evaluated_at DESC);
13
+ CREATE INDEX IF NOT EXISTS idx_alert_eval_project ON alert_evaluations (project_id, evaluated_at DESC);
@@ -0,0 +1,9 @@
1
+ CREATE TABLE IF NOT EXISTS alert_state (
2
+ rule_id TEXT PRIMARY KEY,
3
+ project_id TEXT NOT NULL,
4
+ current_state TEXT NOT NULL,
5
+ last_state_change TEXT NOT NULL,
6
+ FOREIGN KEY (rule_id) REFERENCES alert_rules(id)
7
+ );
8
+
9
+ CREATE INDEX IF NOT EXISTS idx_alert_state_project ON alert_state (project_id);