spine-framework 0.3.125 → 0.3.127

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 (319) hide show
  1. package/.framework/cli/commands/agents.ts +35 -37
  2. package/.framework/cli/commands/auth.ts +35 -34
  3. package/.framework/cli/commands/create-app.ts +104 -40
  4. package/.framework/cli/commands/dev.ts +104 -69
  5. package/.framework/cli/commands/doctor.ts +169 -97
  6. package/.framework/cli/commands/generate.ts +82 -161
  7. package/.framework/cli/commands/init.ts +72 -34
  8. package/.framework/cli/commands/install-app.ts +260 -125
  9. package/.framework/cli/commands/items.ts +33 -44
  10. package/.framework/cli/commands/migrate.ts +122 -40
  11. package/.framework/cli/commands/migrations.ts +33 -40
  12. package/.framework/cli/commands/pipelines.ts +31 -39
  13. package/.framework/cli/commands/status.ts +47 -23
  14. package/.framework/cli/commands/system.ts +47 -37
  15. package/.framework/cli/commands/test.ts +112 -68
  16. package/.framework/cli/commands/validate-app.ts +215 -121
  17. package/.framework/cli/context.ts +112 -130
  18. package/.framework/cli/env-loader.ts +47 -18
  19. package/.framework/cli/index.ts +81 -42
  20. package/.framework/docs/runtime-types.md +1024 -0
  21. package/.framework/functions/_shared/agent-runner.ts +1296 -961
  22. package/.framework/functions/_shared/app-manifest.ts +82 -68
  23. package/.framework/functions/_shared/audit.ts +135 -83
  24. package/.framework/functions/_shared/{cil-state.ts → cil.ts} +147 -54
  25. package/.framework/functions/_shared/db.ts +80 -126
  26. package/.framework/functions/_shared/hash-api-key.ts +63 -0
  27. package/.framework/functions/_shared/index.ts +222 -347
  28. package/.framework/functions/_shared/kb.ts +319 -0
  29. package/.framework/functions/_shared/llm.ts +92 -0
  30. package/.framework/functions/_shared/logging.ts +288 -0
  31. package/.framework/functions/_shared/middleware.ts +329 -365
  32. package/.framework/functions/_shared/outcomes.ts +36 -0
  33. package/.framework/functions/_shared/permissions.ts +359 -643
  34. package/.framework/functions/_shared/pipeline-runner.ts +243 -316
  35. package/.framework/functions/_shared/principal.ts +376 -468
  36. package/.framework/functions/_shared/resolve-credentials.ts +102 -0
  37. package/.framework/functions/_shared/resolve-ids.ts +162 -14
  38. package/.framework/functions/_shared/retry-deliveries.ts +104 -0
  39. package/.framework/functions/_shared/schema-utils.ts +611 -373
  40. package/.framework/functions/_shared/testing.ts +207 -137
  41. package/.framework/functions/_shared/tracing.ts +276 -0
  42. package/.framework/functions/_shared/trigger-engine.ts +159 -211
  43. package/.framework/functions/_shared/webhook-registration.ts +95 -81
  44. package/.framework/functions/_shared/webhook-registry.ts +153 -75
  45. package/.framework/functions/account-nodes.ts +31 -53
  46. package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
  47. package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
  48. package/.framework/functions/adapters/openai-outbound.ts +40 -0
  49. package/.framework/functions/admin-data.ts +687 -533
  50. package/.framework/functions/admin-funnel.ts +31 -20
  51. package/.framework/functions/admin-install-funnel.ts +47 -28
  52. package/.framework/functions/admin-signals.ts +47 -29
  53. package/.framework/functions/ai-agents.ts +122 -147
  54. package/.framework/functions/ai-interactions.ts +180 -90
  55. package/.framework/functions/api-keys.ts +250 -192
  56. package/.framework/functions/apps.ts +203 -197
  57. package/.framework/functions/auth.ts +98 -91
  58. package/.framework/functions/cil-agent-ingest.ts +773 -0
  59. package/.framework/functions/cil-agent.ts +592 -0
  60. package/.framework/functions/cil-callmap.ts +1227 -0
  61. package/.framework/functions/cil-config.ts +583 -0
  62. package/.framework/functions/cil-context.ts +445 -0
  63. package/.framework/functions/cil-doc.ts +1752 -0
  64. package/.framework/functions/cil-embeddings.ts +1202 -0
  65. package/.framework/functions/cil-graph.ts +585 -0
  66. package/.framework/functions/cil-ingest.ts +2416 -0
  67. package/.framework/functions/cil-pipeline.ts +318 -0
  68. package/.framework/functions/cil-project.ts +499 -0
  69. package/.framework/functions/cil-validate.ts +469 -0
  70. package/.framework/functions/debug-auth.ts +73 -53
  71. package/.framework/functions/deliveries.ts +117 -0
  72. package/.framework/functions/embeddings.ts +528 -516
  73. package/.framework/functions/eval-harness.ts +158 -106
  74. package/.framework/functions/integration-outbound.ts +311 -0
  75. package/.framework/functions/integration-routes.ts +240 -466
  76. package/.framework/functions/integrations.ts +132 -140
  77. package/.framework/functions/invites.ts +401 -201
  78. package/.framework/functions/item-progress.ts +113 -53
  79. package/.framework/functions/kb.ts +28 -0
  80. package/.framework/functions/logs.ts +239 -222
  81. package/.framework/functions/observability.ts +308 -259
  82. package/.framework/functions/pipeline-executions.ts +179 -235
  83. package/.framework/functions/pipelines.ts +163 -205
  84. package/.framework/functions/prompt-configs.ts +109 -156
  85. package/.framework/functions/roles.ts +97 -147
  86. package/.framework/functions/system-cron.ts +132 -218
  87. package/.framework/functions/system.ts +112 -52
  88. package/.framework/functions/tests.ts +32 -28
  89. package/.framework/functions/timers.ts +162 -210
  90. package/.framework/functions/triggers.ts +282 -346
  91. package/.framework/functions/types.ts +283 -400
  92. package/.framework/migrations/001_core_schema.sql +630 -0
  93. package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
  94. package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
  95. package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
  96. package/.framework/migrations/005_core_observability.sql +598 -0
  97. package/.framework/migrations/006_security_hardening_rls.sql +97 -0
  98. package/.framework/migrations/007_kb_article_list.sql +237 -0
  99. package/.framework/migrations/008_items_target.sql +8 -0
  100. package/.framework/migrations/009_roles_slug_unique.sql +11 -0
  101. package/.framework/public/spine.config.json +91 -0
  102. package/.framework/scripts/app-install-cli.ts +112 -98
  103. package/.framework/src/App.tsx +67 -20
  104. package/.framework/src/apps/admin/index.tsx +97 -27
  105. package/.framework/src/components/AppWrapper.tsx +50 -11
  106. package/.framework/src/components/CustomAppLoader.tsx +131 -22
  107. package/.framework/src/components/admin/AdminListPage.tsx +75 -8
  108. package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
  109. package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
  110. package/.framework/src/components/admin/PageInstructions.tsx +49 -0
  111. package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
  112. package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
  113. package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
  114. package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
  115. package/.framework/src/components/app-sidebar.tsx +50 -3
  116. package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
  117. package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
  118. package/.framework/src/components/kb/KBArticleList.tsx +557 -0
  119. package/.framework/src/components/layout/AppShell.tsx +54 -16
  120. package/.framework/src/components/layout/Header.tsx +50 -38
  121. package/.framework/src/components/layout/Layout.tsx +48 -32
  122. package/.framework/src/components/layout/Sidebar.tsx +167 -16
  123. package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
  124. package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
  125. package/.framework/src/components/runtime/DataFilters.tsx +78 -1
  126. package/.framework/src/components/runtime/DataHeader.tsx +32 -29
  127. package/.framework/src/components/runtime/DataListPage.tsx +161 -2
  128. package/.framework/src/components/runtime/DataStats.tsx +48 -1
  129. package/.framework/src/components/runtime/DataTable.tsx +153 -1
  130. package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
  131. package/.framework/src/components/runtime/index.ts +16 -9
  132. package/.framework/src/components/search-form.tsx +33 -1
  133. package/.framework/src/components/shared/AgentView.tsx +48 -51
  134. package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
  135. package/.framework/src/components/shared/InviteManager.tsx +113 -52
  136. package/.framework/src/components/shared/MemberList.tsx +182 -0
  137. package/.framework/src/components/shared/SchemaFields.tsx +96 -78
  138. package/.framework/src/components/ui/DataTable.tsx +86 -56
  139. package/.framework/src/components/ui/Form.tsx +188 -109
  140. package/.framework/src/components/ui/ItemCard.tsx +86 -58
  141. package/.framework/src/components/ui/ItemListView.tsx +88 -61
  142. package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
  143. package/.framework/src/components/ui/Modal.tsx +81 -4
  144. package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
  145. package/.framework/src/components/ui/accordion.tsx +97 -5
  146. package/.framework/src/components/ui/alert-dialog.tsx +225 -13
  147. package/.framework/src/components/ui/alert.tsx +113 -6
  148. package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
  149. package/.framework/src/components/ui/avatar.tsx +129 -7
  150. package/.framework/src/components/ui/badge.tsx +65 -3
  151. package/.framework/src/components/ui/breadcrumb.tsx +145 -8
  152. package/.framework/src/components/ui/button-group.tsx +81 -4
  153. package/.framework/src/components/ui/button.tsx +49 -2
  154. package/.framework/src/components/ui/calendar.tsx +65 -3
  155. package/.framework/src/components/ui/card.tsx +145 -8
  156. package/.framework/src/components/ui/carousel.tsx +129 -7
  157. package/.framework/src/components/ui/chart.tsx +161 -10
  158. package/.framework/src/components/ui/checkbox.tsx +49 -2
  159. package/.framework/src/components/ui/collapsible.tsx +81 -5
  160. package/.framework/src/components/ui/combobox.tsx +305 -20
  161. package/.framework/src/components/ui/command.tsx +177 -11
  162. package/.framework/src/components/ui/context-menu.tsx +273 -17
  163. package/.framework/src/components/ui/dialog.tsx +209 -27
  164. package/.framework/src/components/ui/direction.tsx +64 -4
  165. package/.framework/src/components/ui/drawer.tsx +193 -12
  166. package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
  167. package/.framework/src/components/ui/empty.tsx +145 -9
  168. package/.framework/src/components/ui/field.tsx +209 -14
  169. package/.framework/src/components/ui/hover-card.tsx +81 -4
  170. package/.framework/src/components/ui/input-group.tsx +162 -10
  171. package/.framework/src/components/ui/input-otp.tsx +98 -5
  172. package/.framework/src/components/ui/input.tsx +49 -2
  173. package/.framework/src/components/ui/item.tsx +225 -13
  174. package/.framework/src/components/ui/kbd.tsx +65 -3
  175. package/.framework/src/components/ui/label.tsx +49 -2
  176. package/.framework/src/components/ui/menubar.tsx +289 -17
  177. package/.framework/src/components/ui/native-select.tsx +97 -5
  178. package/.framework/src/components/ui/navigation-menu.tsx +177 -10
  179. package/.framework/src/components/ui/pagination.tsx +161 -9
  180. package/.framework/src/components/ui/popover.tsx +145 -8
  181. package/.framework/src/components/ui/progress.tsx +49 -2
  182. package/.framework/src/components/ui/radio-group.tsx +65 -3
  183. package/.framework/src/components/ui/resizable.tsx +82 -4
  184. package/.framework/src/components/ui/scroll-area.tsx +65 -3
  185. package/.framework/src/components/ui/select.tsx +193 -11
  186. package/.framework/src/components/ui/separator.tsx +49 -2
  187. package/.framework/src/components/ui/sheet.tsx +193 -11
  188. package/.framework/src/components/ui/sidebar.tsx +481 -38
  189. package/.framework/src/components/ui/skeleton.tsx +49 -2
  190. package/.framework/src/components/ui/slider.tsx +49 -2
  191. package/.framework/src/components/ui/sonner.tsx +49 -2
  192. package/.framework/src/components/ui/spinner.tsx +49 -2
  193. package/.framework/src/components/ui/switch.tsx +49 -2
  194. package/.framework/src/components/ui/table-primitives.tsx +160 -33
  195. package/.framework/src/components/ui/table.tsx +161 -9
  196. package/.framework/src/components/ui/tabs.tsx +113 -6
  197. package/.framework/src/components/ui/textarea.tsx +49 -2
  198. package/.framework/src/components/ui/toggle-group.tsx +81 -4
  199. package/.framework/src/components/ui/toggle.tsx +65 -3
  200. package/.framework/src/components/ui/tooltip.tsx +97 -5
  201. package/.framework/src/contexts/AppContext.tsx +129 -45
  202. package/.framework/src/contexts/AuthContext.tsx +173 -145
  203. package/.framework/src/hooks/use-mobile.ts +48 -2
  204. package/.framework/src/hooks/useApi.ts +208 -159
  205. package/.framework/src/hooks/useAppPath.ts +32 -23
  206. package/.framework/src/hooks/useApps.ts +51 -20
  207. package/.framework/src/hooks/useEntityList.ts +32 -78
  208. package/.framework/src/hooks/useEntityRecord.ts +35 -96
  209. package/.framework/src/hooks/useForm.ts +32 -92
  210. package/.framework/src/hooks/useListSchema.ts +49 -78
  211. package/.framework/src/hooks/useSchemaRecord.ts +114 -105
  212. package/.framework/src/lib/api.ts +192 -115
  213. package/.framework/src/lib/supabase.ts +98 -64
  214. package/.framework/src/lib/utils.ts +287 -151
  215. package/.framework/src/main.tsx +49 -3
  216. package/.framework/src/pages/DashboardPage.tsx +52 -29
  217. package/.framework/src/pages/NotFoundPage.tsx +32 -10
  218. package/.framework/src/pages/SetupPage.tsx +32 -12
  219. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
  220. package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
  221. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
  222. package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
  223. package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
  224. package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
  225. package/.framework/src/pages/admin/AppsPage.tsx +49 -2
  226. package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
  227. package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
  228. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
  229. package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
  230. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
  231. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
  232. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
  233. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
  234. package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
  235. package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
  236. package/.framework/src/pages/admin/LogsPage.tsx +422 -75
  237. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
  238. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
  239. package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
  240. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
  241. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
  242. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
  243. package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
  244. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
  245. package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
  246. package/.framework/src/pages/admin/RolesPage.tsx +171 -18
  247. package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
  248. package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
  249. package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
  250. package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
  251. package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
  252. package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
  253. package/.framework/src/pages/admin/TimersPage.tsx +48 -20
  254. package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
  255. package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
  256. package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
  257. package/.framework/src/pages/admin/TypesPage.tsx +48 -20
  258. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
  259. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
  260. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
  261. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
  262. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
  263. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
  264. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
  265. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
  266. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
  267. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  268. package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
  269. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
  270. package/.framework/src/pages/auth/LoginPage.tsx +50 -23
  271. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
  272. package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
  273. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
  274. package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
  275. package/.framework/src/types/auth.ts +128 -71
  276. package/.framework/src/types/types.ts +373 -157
  277. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
  278. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
  279. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
  280. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
  281. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
  282. package/docs/README.md +9 -130
  283. package/netlify.toml +3 -3
  284. package/package.json +13 -25
  285. package/scripts/kb-ingest-docs.ts +203 -0
  286. package/spine.config.json +65 -4
  287. package/.framework/migrations/001_schema.sql +0 -425
  288. package/.framework/migrations/002_rls_and_functions.sql +0 -763
  289. package/.framework/migrations/004_enhancements.sql +0 -43
  290. package/.framework/migrations/005_auth_user_trigger.sql +0 -105
  291. package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
  292. package/.framework/migrations/016_invites.sql +0 -27
  293. package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
  294. package/.framework/migrations/018_apps_required_roles.sql +0 -17
  295. package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
  296. package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
  297. package/.framework/migrations/021_app_domains.sql +0 -112
  298. package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
  299. package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
  300. package/.framework/migrations/024_messages_account_id.sql +0 -9
  301. package/.framework/migrations/025_retype_threads_messages.sql +0 -240
  302. package/.framework/migrations/026_fix_rls_policies.sql +0 -47
  303. package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
  304. package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
  305. package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
  306. package/.framework/migrations/030_messages_updated_by.sql +0 -6
  307. package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
  308. package/docs/APPS.md +0 -232
  309. package/docs/ARCHITECTURE.md +0 -246
  310. package/docs/INSTALL.md +0 -155
  311. package/docs/design-schema-spec.md +0 -1837
  312. package/docs/dev-guides/01-create-an-app.md +0 -183
  313. package/docs/dev-guides/02-create-a-function.md +0 -178
  314. package/docs/dev-guides/03-create-a-component.md +0 -178
  315. package/docs/dev-guides/04-webhook-handlers.md +0 -129
  316. package/docs/dev-guides/05-testing.md +0 -168
  317. package/docs/dev-guides/README.md +0 -40
  318. package/docs/npm-packages-plan.md +0 -288
  319. package/docs/spine-core--api-reference.md +0 -822
@@ -1,28 +1,48 @@
1
- /**
2
- * @module src/pages/admin/LogsPage
3
- * @audience installer
4
- * @layer frontend-page
5
- * @stability stable
6
- *
7
- * Admin log viewer. Fetches system audit/activity logs via
8
- * `/api/admin-data?action=logs`, applies client-side search, severity
9
- * filter, date-range filter, and sort. Renders inside `AdminListPage`
10
- * with a sortable table. Useful for debugging pipeline executions,
11
- * auth events, and API errors.
12
- *
13
- * @seeAlso src/pages/admin/ObservabilityDashboard.tsx
14
- */
15
1
 
16
- import React, { useState } from 'react'
17
- import { FileText, Search, Calendar, AlertTriangle, CheckCircle, User } from 'lucide-react';
2
+
3
+
4
+
5
+
6
+ // CIL[BEGIN chunk_id="logspage_module_header_1783666257" type="module_header" identity="imports" parent="none"]
7
+ // CIL[DOC-MACRO purpose="Import React dependencies and UI components"]
8
+ // CIL[DOC-RESPONSIBILITY responsibility="Import all required modules for LogsPage component"]
9
+ // CIL[DOC-CONTEXT module="LogsPage" layer="ui" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/components/layout/Sidebar.tsx\",\"custom/apps/portal/pages/CoursesPage.tsx\",\"\\\"]"]
10
+ // CIL[DOC-CONTRACT inputs="none" outputs="React hooks, UI components, utilities" errors="Import errors" side_effects="Module loading"]
11
+ // CIL[DOC-MICRO logic_summary="Imports React, icons, UI components, and utility functions" notable_decisions="[]"]
12
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
13
+ // CIL[DOC-STABILITY stability="stable"]
14
+ // CIL[DOC-AUDIENCE audience="developer"]
15
+ // CIL[DOC-VECTOR type="context" content="Layer: ui. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/dialog.tsx, .framework/src/components/layout/Sidebar.tsx, custom/apps/portal/pages/CoursesPage.tsx, \."]
16
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
17
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
18
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
19
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
20
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
21
+ import React, { useState, useEffect } from 'react'
22
+ import { FileText, Search, Calendar, AlertTriangle, CheckCircle, User, X } from 'lucide-react';
18
23
  import { LoadingSpinner } from '../../components/ui/LoadingSpinner'
19
24
  import { Button } from '../../components/ui/button'
25
+ import { Input } from '../../components/ui/input'
20
26
  import { AdminListPage } from '../../components/admin/AdminListPage'
21
27
  import { SortableTableHeader } from '../../components/admin/SortableTableHeader'
22
28
  import { formatDateTime } from '../../lib/utils'
23
29
  import { useApi } from '../../hooks/useApi'
24
30
  import { apiFetch } from '../../lib/api'
25
-
31
+ // CIL[END chunk_id="logspage_module_header_1783666257"]
32
+ // CIL[BEGIN chunk_id="logspage_interface_logentry_1783666257" type="interface" identity="LogEntry" parent="none"]
33
+ // CIL[DOC-MACRO purpose="Define log entry data structure"]
34
+ // CIL[DOC-RESPONSIBILITY responsibility="Type definition for log entries"]
35
+ // CIL[DOC-CONTEXT module="LogsPage" layer="types" related_files="[\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
36
+ // CIL[DOC-CONTRACT inputs="none" outputs="LogEntry interface" errors="Type errors" side_effects="Type system"]
37
+ // CIL[DOC-MICRO logic_summary="Defines structure for system log entries with optional fields" notable_decisions="[]"]
38
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
39
+ // CIL[DOC-STABILITY stability="stable"]
40
+ // CIL[DOC-VECTOR type="context" content="Layer: types. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/schema-utils.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, \."]
41
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
42
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
43
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
44
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
45
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
26
46
  interface LogEntry {
27
47
  id: string
28
48
  event_type: string
@@ -30,8 +50,17 @@ interface LogEntry {
30
50
  target_type?: string
31
51
  target_id?: string
32
52
  action?: string
53
+ span_name?: string
54
+ trace_id?: string
55
+ span_id?: string
56
+ parent_span_id?: string
57
+ duration_ms?: number
58
+ outcome?: string
59
+ event_category?: string
60
+ kind?: string
33
61
  details?: Record<string, any>
34
62
  metadata?: Record<string, any>
63
+ message?: string
35
64
  created_at: string
36
65
  actor?: {
37
66
  id: string
@@ -40,50 +69,154 @@ interface LogEntry {
40
69
  }
41
70
  }
42
71
 
43
- export function LogsPage() {
72
+ interface LogsResponse {
73
+ data: LogEntry[]
74
+ total: number
75
+ }
76
+
77
+ interface StatsResponse {
78
+ total: number
79
+ error_count: number
80
+ user_action_count: number
81
+ event_type_count: number
82
+ levels: string[]
83
+ sources: string[]
84
+ source_types: string[]
85
+ }
86
+ // CIL[END chunk_id="logspage_interface_logentry_1783666257"]
87
+ // CIL[BEGIN chunk_id="logspage_function_logspage_1783666257" type="function" identity="LogsPage" parent="none"]
88
+ // CIL[DOC-MACRO purpose="Render the complete logs interface"]
89
+ // CIL[DOC-RESPONSIBILITY responsibility="Main render logic for logs page"]
90
+ // CIL[DOC-CONTEXT module="LogsPage" layer="ui" related_files="[\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/layout/Sidebar.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\"]"]
91
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSX structure" errors="Render errors" side_effects="DOM updates"]
92
+ // CIL[DOC-MICRO logic_summary="Renders AdminListPage with date filters, table, and empty states" notable_decisions="[]"]
93
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
94
+ // CIL[DOC-STABILITY stability="stable"]
95
+ // CIL[DOC-VECTOR type="context" content="Layer: ui. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/layout/Sidebar.tsx, .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx."]
96
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
97
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
98
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
99
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
100
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
101
+ export function LogsPage({ title = 'System Logs' }: { title?: string }) {
44
102
  const [searchTerm, setSearchTerm] = useState('')
45
103
  const [selectedEventType, setSelectedEventType] = useState('all')
104
+ const [selectedSource, setSelectedSource] = useState('all')
105
+ const [selectedSourceType, setSelectedSourceType] = useState('all')
106
+ const [sourceIdFilter, setSourceIdFilter] = useState('')
107
+ const [actorIdFilter, setActorIdFilter] = useState('')
46
108
  const [dateFrom, setDateFrom] = useState('')
47
109
  const [dateTo, setDateTo] = useState('')
48
110
  const [sortKey, setSortKey] = useState('created_at')
49
111
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc')
112
+ const [page, setPage] = useState(1)
113
+ const [expandedRowId, setExpandedRowId] = useState<string | null>(null)
114
+ const [traceIdFilter, setTraceIdFilter] = useState('')
115
+ const pageSize = 100
116
+
117
+ const buildLogUrl = (forStats = false) => {
118
+ const params = new URLSearchParams()
119
+ params.set('action', forStats ? 'stats' : 'account')
120
+ if (searchTerm.trim()) params.set('query', searchTerm.trim())
121
+ if (selectedEventType !== 'all') params.set('event_type', selectedEventType)
122
+ if (selectedSource !== 'all') params.set('source', selectedSource)
123
+ if (selectedSourceType !== 'all') params.set('target_type', selectedSourceType)
124
+ if (sourceIdFilter.trim()) params.set('source_id', sourceIdFilter.trim())
125
+ if (actorIdFilter.trim()) params.set('actor_id', actorIdFilter.trim())
126
+ if (traceIdFilter.trim()) params.set('trace_id', traceIdFilter.trim())
127
+ if (dateFrom) params.set('date_from', dateFrom)
128
+ if (dateTo) params.set('date_to', dateTo)
129
+ if (!forStats) {
130
+ params.set('limit', pageSize.toString())
131
+ params.set('offset', ((page - 1) * pageSize).toString())
132
+ }
133
+ return `/api/logs?${params.toString()}`
134
+ }
50
135
 
51
- const { data: logs, loading, error, refetch } = useApi<LogEntry[]>(
136
+ // CIL[BEGIN chunk_id="logspage_hooks_1783666257" type="hooks" identity="useApi" parent="logspage_function_logspage_1783666257"]
137
+ // CIL[DOC-MACRO purpose="Fetch logs and stats data from API"]
138
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle useApi"]
139
+ // CIL[DOC-CONTEXT module="LogsPage" layer="data" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
140
+ // CIL[DOC-CONTRACT inputs="none" outputs="logs data, stats data" errors="API errors" side_effects="HTTP requests"]
141
+ // CIL[DOC-MICRO logic_summary="Uses useApi hook to fetch logs and statistics with date filtering" notable_decisions="[]"]
142
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
143
+ // CIL[DOC-STABILITY stability="stable"]
144
+ // CIL[DOC-VECTOR type="context" content="Layer: data. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/functions/_shared/schema-utils.ts, \."]
145
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
146
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
147
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
148
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
149
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
150
+ const { data: logsData, loading, error, refetch } = useApi<LogsResponse>(
52
151
  async () => {
53
- let url = '/api/logs?action=account'
54
- if (dateFrom) url += `&date_from=${dateFrom}`
55
- if (dateTo) url += `&date_to=${dateTo}`
56
-
57
- const response = await apiFetch(url)
152
+ const response = await apiFetch(buildLogUrl())
58
153
  if (!response.ok) throw new Error('Failed to fetch logs')
59
154
  const result = await response.json()
60
- return (result.data || result) as LogEntry[]
155
+ return (result.data || result) as LogsResponse
61
156
  },
62
157
  { immediate: true }
63
158
  )
64
159
 
65
- const { data: stats } = useApi<{ total: number; by_type: Record<string, number> }>(
160
+ const logs = logsData?.data || []
161
+ const totalLogs = logsData?.total || 0
162
+
163
+ const { data: stats, refetch: refetchStats } = useApi<StatsResponse>(
66
164
  async () => {
67
- const response = await apiFetch('/api/logs?action=stats')
165
+ const response = await apiFetch(buildLogUrl(true))
68
166
  if (!response.ok) return null
69
167
  const result = await response.json()
70
- return result.data || result
168
+ return (result.data || result) as StatsResponse
71
169
  },
72
170
  { immediate: true }
73
171
  )
74
172
 
75
- const filteredLogs = (logs || []).filter(log => {
76
- const matchesSearch = !searchTerm ||
77
- log.event_type.toLowerCase().includes(searchTerm.toLowerCase()) ||
78
- log.target_type?.toLowerCase().includes(searchTerm.toLowerCase()) ||
79
- log.action?.toLowerCase().includes(searchTerm.toLowerCase()) ||
80
- JSON.stringify(log.details).toLowerCase().includes(searchTerm.toLowerCase())
81
- const matchesType = selectedEventType === 'all' || log.event_type === selectedEventType
82
- return matchesSearch && matchesType
83
- })
173
+ useEffect(() => {
174
+ const timer = setTimeout(() => {
175
+ refetch()
176
+ refetchStats()
177
+ }, 300)
178
+ return () => clearTimeout(timer)
179
+ }, [searchTerm, selectedEventType, selectedSource, selectedSourceType, sourceIdFilter, actorIdFilter, traceIdFilter, dateFrom, dateTo, page, refetch, refetchStats])
180
+
181
+ useEffect(() => {
182
+ setPage(1)
183
+ }, [searchTerm, selectedEventType, selectedSource, selectedSourceType, sourceIdFilter, actorIdFilter, traceIdFilter, dateFrom, dateTo])
184
+ // CIL[END chunk_id="logspage_hooks_1783666257"]
84
185
 
85
- const eventTypes = Array.from(new Set((logs || []).map(l => l.event_type)))
186
+ // CIL[BEGIN chunk_id="logspage_filters_1783666257" type="filter_logic" identity="filteredLogs" parent="logspage_function_logspage_1783666257"]
187
+ // CIL[DOC-MACRO purpose="Filter logs by search and event type"]
188
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle filteredLogs"]
189
+ // CIL[DOC-CONTEXT module="LogsPage" layer="logic" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/migrations/025_retype_threads_messages.sql\",\"\\\"]"]
190
+ // CIL[DOC-CONTRACT inputs="none" outputs="filtered logs" errors="none" side_effects="none"]
191
+ // CIL[DOC-MICRO logic_summary="Filters logs based on search term and event type selection" notable_decisions="[]"]
192
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
193
+ // CIL[DOC-STABILITY stability="stable"]
194
+ // CIL[DOC-VECTOR type="context" content="Layer: logic. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/migrations/025_retype_threads_messages.sql, \."]
195
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
196
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
197
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
198
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
199
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
200
+ const filteredLogs = logs || []
86
201
 
202
+ const eventTypes = stats?.levels || []
203
+ const sourceOptions = stats?.sources || []
204
+ // CIL[END chunk_id="logspage_filters_1783666257"]
205
+
206
+ // CIL[BEGIN chunk_id="logspage_sorting_1783666257" type="sorting_logic" identity="handleSort" parent="logspage_function_logspage_1783666257"]
207
+ // CIL[DOC-MACRO purpose="Handle column sorting for logs table"]
208
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle handleSort"]
209
+ // CIL[DOC-CONTEXT module="handleSort" layer="unknown" related_files="[]"]
210
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
211
+ // CIL[DOC-MICRO logic_summary="Implements handleSort" notable_decisions="[]"]
212
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
213
+ // CIL[DOC-STABILITY stability="stable"]
214
+ // CIL[DOC-VECTOR type="context" content="Layer: unknown. Direct callers: 0. Direct calls: 0. Related files: none."]
215
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
216
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
217
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
218
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
219
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
87
220
  const handleSort = (key: string) => {
88
221
  if (sortKey === key) {
89
222
  setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc')
@@ -105,7 +238,22 @@ export function LogsPage() {
105
238
 
106
239
  return 0
107
240
  })
241
+ // CIL[END chunk_id="logspage_sorting_1783666257"]
108
242
 
243
+ // CIL[BEGIN chunk_id="logspage_badge_1783666257" type="utility_function" identity="getEventTypeBadge" parent="logspage_function_logspage_1783666257"]
244
+ // CIL[DOC-MACRO purpose="Generate colored badges for event types"]
245
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle getEventTypeBadge"]
246
+ // CIL[DOC-CONTEXT module="getEventTypeBadge" layer="unknown" related_files="[]"]
247
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
248
+ // CIL[DOC-MICRO logic_summary="Implements getEventTypeBadge" notable_decisions="[]"]
249
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
250
+ // CIL[DOC-STABILITY stability="stable"]
251
+ // CIL[DOC-VECTOR type="context" content="Layer: unknown. Direct callers: 0. Direct calls: 0. Related files: none."]
252
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
253
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
254
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
255
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
256
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
109
257
  const getEventTypeBadge = (eventType: string) => {
110
258
  if (eventType.includes('error') || eventType.includes('failed')) {
111
259
  return <span className="inline-flex px-2 py-0.5 text-xs font-medium rounded-md bg-red-100 text-red-700">{eventType}</span>
@@ -118,51 +266,102 @@ export function LogsPage() {
118
266
  }
119
267
  return <span className="inline-flex px-2 py-0.5 text-xs font-medium rounded-md bg-slate-100 text-slate-600">{eventType}</span>
120
268
  }
269
+ // CIL[END chunk_id="logspage_badge_1783666257"]
121
270
 
271
+ // CIL[BEGIN chunk_id="logspage_stats_1783666257" type="stats_config" identity="statsCards" parent="logspage_function_logspage_1783666257"]
272
+ // CIL[DOC-MACRO purpose="Configure statistics cards and filters"]
273
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle statsCards"]
274
+ // CIL[DOC-CONTEXT module="LogsPage" layer="ui" related_files="[]"]
275
+ // CIL[DOC-CONTRACT inputs="none" outputs="stats cards, filter options" errors="none" side_effects="none"]
276
+ // CIL[DOC-MICRO logic_summary="Creates stats cards and filter options for logs display" notable_decisions="[]"]
277
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
278
+ // CIL[DOC-STABILITY stability="stable"]
279
+ // CIL[DOC-VECTOR type="context" content="Layer: ui. Direct callers: 0. Direct calls: 0. Related files: none."]
280
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
281
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
282
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
283
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
284
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
122
285
  const statsCards = [
123
286
  {
124
287
  title: 'Total Events',
125
- value: stats?.total || (logs || []).length,
288
+ value: stats?.total ?? totalLogs,
126
289
  icon: FileText,
127
290
  iconColor: 'text-blue-500'
128
291
  },
129
292
  {
130
293
  title: 'Event Types',
131
- value: eventTypes.length,
294
+ value: stats?.event_type_count ?? eventTypes.length,
132
295
  icon: Calendar,
133
296
  iconColor: 'text-purple-500'
134
297
  },
135
298
  {
136
299
  title: 'Errors',
137
- value: (logs || []).filter(l => l.event_type.includes('error')).length,
300
+ value: stats?.error_count ?? 0,
138
301
  icon: AlertTriangle,
139
302
  iconColor: 'text-red-500'
140
303
  },
141
304
  {
142
305
  title: 'User Actions',
143
- value: (logs || []).filter(l => l.actor_id).length,
306
+ value: stats?.user_action_count ?? 0,
144
307
  icon: User,
145
308
  iconColor: 'text-green-500'
146
309
  }
147
310
  ]
148
311
 
149
- const eventTypeOptions = [
150
- { value: 'all', label: 'All Events' },
151
- ...eventTypes.map(type => ({ value: type, label: type }))
312
+ const makeOptions = (values: string[], current: string) => {
313
+ const set = new Set(['all', current, ...values])
314
+ return Array.from(set)
315
+ .filter(v => v && v !== 'all')
316
+ .map(v => ({ value: v, label: v }))
317
+ }
318
+
319
+ const eventTypeOptions = [{ value: 'all', label: 'All Levels' }, ...makeOptions(eventTypes, selectedEventType)]
320
+ const sourceSelectOptions = [{ value: 'all', label: 'All Sources' }, ...makeOptions(sourceOptions, selectedSource)]
321
+ const sourceTypeOptions = [
322
+ { value: 'all', label: 'All Source Types' },
323
+ ...makeOptions(stats?.source_types || [], selectedSourceType)
152
324
  ]
153
325
 
154
326
  const filters = [
155
327
  {
156
- label: 'Event Type',
328
+ label: 'Level',
157
329
  value: selectedEventType,
158
330
  options: eventTypeOptions,
159
331
  onChange: setSelectedEventType
332
+ },
333
+ {
334
+ label: 'Source',
335
+ value: selectedSource,
336
+ options: sourceSelectOptions,
337
+ onChange: setSelectedSource
338
+ },
339
+ {
340
+ label: 'Source Type',
341
+ value: selectedSourceType,
342
+ options: sourceTypeOptions,
343
+ onChange: setSelectedSourceType
160
344
  }
161
345
  ]
346
+ // CIL[END chunk_id="logspage_stats_1783666257"]
162
347
 
348
+ // CIL[BEGIN chunk_id="logspage_render_1783666257" type="render_logic" identity="return" parent="logspage_function_logspage_1783666257"]
349
+ // CIL[DOC-MACRO purpose="Render the complete logs interface"]
350
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle return"]
351
+ // CIL[DOC-CONTEXT module="return" layer="unknown" related_files="[]"]
352
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
353
+ // CIL[DOC-MICRO logic_summary="Implements return" notable_decisions="[]"]
354
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
355
+ // CIL[DOC-STABILITY stability="stable"]
356
+ // CIL[DOC-VECTOR type="context" content="Layer: unknown. Direct callers: 0. Direct calls: 0. Related files: none."]
357
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
358
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
359
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
360
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
361
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
163
362
  return (
164
363
  <AdminListPage
165
- title="System Logs"
364
+ title={title}
166
365
  description="Audit trail and event history"
167
366
  statsCards={statsCards}
168
367
  searchPlaceholder="Search logs..."
@@ -175,7 +374,7 @@ export function LogsPage() {
175
374
  emptyIcon={FileText}
176
375
  >
177
376
  <div className="px-6 py-4 border-b border-slate-200 bg-slate-50">
178
- <div className="flex items-center gap-4">
377
+ <div className="flex flex-wrap items-center gap-4">
179
378
  <div>
180
379
  <label className="block text-xs font-medium text-slate-500 mb-1">From</label>
181
380
  <input
@@ -194,13 +393,77 @@ export function LogsPage() {
194
393
  className="px-3 py-1.5 text-sm border border-slate-300 rounded-md"
195
394
  />
196
395
  </div>
396
+ <div>
397
+ <label className="block text-xs font-medium text-slate-500 mb-1">Source ID</label>
398
+ <Input
399
+ type="text"
400
+ placeholder="uuid"
401
+ value={sourceIdFilter}
402
+ onChange={(e) => setSourceIdFilter(e.target.value)}
403
+ className="w-48 px-3 py-1.5 text-sm"
404
+ />
405
+ </div>
406
+ <div>
407
+ <label className="block text-xs font-medium text-slate-500 mb-1">Actor ID</label>
408
+ <Input
409
+ type="text"
410
+ placeholder="uuid"
411
+ value={actorIdFilter}
412
+ onChange={(e) => setActorIdFilter(e.target.value)}
413
+ className="w-48 px-3 py-1.5 text-sm"
414
+ />
415
+ </div>
416
+ <div>
417
+ <label className="block text-xs font-medium text-slate-500 mb-1">Trace ID</label>
418
+ <Input
419
+ type="text"
420
+ placeholder="trace id"
421
+ value={traceIdFilter}
422
+ onChange={(e) => setTraceIdFilter(e.target.value)}
423
+ className="w-48 px-3 py-1.5 text-sm"
424
+ />
425
+ </div>
197
426
  <div className="flex-1" />
427
+ <Button
428
+ variant="outline"
429
+ onClick={() => {
430
+ setSearchTerm('')
431
+ setSelectedEventType('all')
432
+ setSelectedSource('all')
433
+ setSelectedSourceType('all')
434
+ setSourceIdFilter('')
435
+ setActorIdFilter('')
436
+ setTraceIdFilter('')
437
+ setDateFrom('')
438
+ setDateTo('')
439
+ setPage(1)
440
+ }}
441
+ className="text-sm"
442
+ >
443
+ <X className="h-4 w-4 mr-1" />
444
+ Clear
445
+ </Button>
198
446
  <Button variant="secondary" onClick={refetch} className="text-sm">
199
447
  Refresh
200
448
  </Button>
201
449
  </div>
202
450
  </div>
203
451
 
452
+ {traceIdFilter && (
453
+ <div className="px-6 py-3 bg-blue-50 border-b border-blue-100 flex items-center justify-between">
454
+ <div className="text-sm text-blue-900">
455
+ Viewing trace <span className="font-mono font-medium">{traceIdFilter}</span>
456
+ </div>
457
+ <Button
458
+ variant="outline"
459
+ size="sm"
460
+ onClick={() => setTraceIdFilter('')}
461
+ >
462
+ Clear trace
463
+ </Button>
464
+ </div>
465
+ )}
466
+
204
467
  {sortedLogs.length === 0 ? (
205
468
  <div className="p-8 text-center">
206
469
  <FileText className="mx-auto h-12 w-12 text-slate-400" />
@@ -221,29 +484,50 @@ export function LogsPage() {
221
484
  onSort={handleSort}
222
485
  />
223
486
  <SortableTableHeader
224
- title="Event Type"
487
+ title="Trace"
488
+ sortKey="trace_id"
489
+ currentSortKey={sortKey}
490
+ currentSortDirection={sortDirection}
491
+ onSort={handleSort}
492
+ />
493
+ <SortableTableHeader
494
+ title="Level"
225
495
  sortKey="event_type"
226
496
  currentSortKey={sortKey}
227
497
  currentSortDirection={sortDirection}
228
498
  onSort={handleSort}
229
499
  />
230
500
  <SortableTableHeader
231
- title="Action"
501
+ title="Source"
232
502
  sortKey="action"
233
503
  currentSortKey={sortKey}
234
504
  currentSortDirection={sortDirection}
235
505
  onSort={handleSort}
236
506
  />
237
507
  <SortableTableHeader
238
- title="Target"
508
+ title="Source Type"
239
509
  sortKey="target_type"
240
510
  currentSortKey={sortKey}
241
511
  currentSortDirection={sortDirection}
242
512
  onSort={handleSort}
243
513
  />
244
514
  <SortableTableHeader
245
- title="Actor"
246
- sortKey="actor"
515
+ title="Source ID"
516
+ sortKey="target_id"
517
+ currentSortKey={sortKey}
518
+ currentSortDirection={sortDirection}
519
+ onSort={handleSort}
520
+ />
521
+ <SortableTableHeader
522
+ title="Person"
523
+ sortKey="actor_id"
524
+ currentSortKey={sortKey}
525
+ currentSortDirection={sortDirection}
526
+ onSort={handleSort}
527
+ />
528
+ <SortableTableHeader
529
+ title="Message"
530
+ sortKey="message"
247
531
  currentSortKey={sortKey}
248
532
  currentSortDirection={sortDirection}
249
533
  onSort={handleSort}
@@ -252,32 +536,95 @@ export function LogsPage() {
252
536
  </thead>
253
537
  <tbody className="bg-white divide-y divide-slate-200">
254
538
  {sortedLogs.map((log) => (
255
- <tr key={log.id} className="hover:bg-slate-50">
256
- <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-500">
257
- {formatDateTime(log.created_at)}
258
- </td>
259
- <td className="px-6 py-4 whitespace-nowrap">
260
- {getEventTypeBadge(log.event_type)}
261
- </td>
262
- <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-900">
263
- {log.action || '—'}
264
- </td>
265
- <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-600">
266
- {log.target_type ? (
267
- <span>
268
- {log.target_type}
269
- {log.target_id && <span className="text-slate-400 ml-1">({log.target_id.slice(0, 8)})</span>}
270
- </span>
271
- ) : '—'}
272
- </td>
273
- <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-600">
274
- {log.actor?.full_name || log.actor_id?.slice(0, 8) || 'System'}
275
- </td>
276
- </tr>
539
+ <React.Fragment key={log.id}>
540
+ <tr
541
+ className="hover:bg-slate-50 cursor-pointer"
542
+ onClick={() => setExpandedRowId(expandedRowId === log.id ? null : log.id)}
543
+ >
544
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-500">
545
+ {formatDateTime(log.created_at)}
546
+ </td>
547
+ <td className="px-6 py-4 whitespace-nowrap text-sm">
548
+ {log.trace_id ? (
549
+ <button
550
+ className="text-blue-600 hover:text-blue-800 font-mono"
551
+ title={`Trace: ${log.trace_id}${log.span_name ? ` / ${log.span_name}` : ''}`}
552
+ onClick={(e) => {
553
+ e.stopPropagation()
554
+ setTraceIdFilter(log.trace_id!)
555
+ setPage(1)
556
+ }}
557
+ >
558
+ {log.trace_id.slice(0, 8)}
559
+ </button>
560
+ ) : (
561
+ <span className="text-slate-300">—</span>
562
+ )}
563
+ </td>
564
+ <td className="px-6 py-4 whitespace-nowrap">
565
+ {getEventTypeBadge(log.event_type)}
566
+ </td>
567
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-900">
568
+ {log.action || '—'}
569
+ </td>
570
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-600">
571
+ {log.target_type || '—'}
572
+ </td>
573
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-600">
574
+ {log.target_id ? log.target_id.slice(0, 8) : '—'}
575
+ </td>
576
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-600">
577
+ {log.actor?.full_name || log.actor_id?.slice(0, 8) || 'System'}
578
+ </td>
579
+ <td className="px-6 py-4 text-sm text-slate-600 max-w-md truncate" title={log.message}>
580
+ {log.message || '—'}
581
+ </td>
582
+ </tr>
583
+ {expandedRowId === log.id && (
584
+ <tr>
585
+ <td colSpan={8} className="p-0 border-b border-slate-200">
586
+ <div className="p-6 bg-slate-50">
587
+ <h4 className="text-sm font-semibold text-slate-900 mb-3">Log Record</h4>
588
+ <pre className="text-xs bg-white border border-slate-200 rounded-md p-4 overflow-auto max-h-96">
589
+ {JSON.stringify(log, null, 2)}
590
+ </pre>
591
+ </div>
592
+ </td>
593
+ </tr>
594
+ )}
595
+ </React.Fragment>
277
596
  ))}
278
597
  </tbody>
279
598
  </table>
280
599
  )}
600
+
601
+ {totalLogs > 0 && (
602
+ <div className="px-6 py-4 border-t border-slate-200 bg-slate-50 flex items-center justify-between">
603
+ <div className="text-sm text-slate-600">
604
+ Page {page} of {Math.max(1, Math.ceil(totalLogs / pageSize))} ({totalLogs} total)
605
+ </div>
606
+ <div className="flex gap-2">
607
+ <Button
608
+ variant="outline"
609
+ size="sm"
610
+ onClick={() => setPage(p => Math.max(1, p - 1))}
611
+ disabled={page <= 1}
612
+ >
613
+ Previous
614
+ </Button>
615
+ <Button
616
+ variant="outline"
617
+ size="sm"
618
+ onClick={() => setPage(p => p + 1)}
619
+ disabled={page >= Math.ceil(totalLogs / pageSize)}
620
+ >
621
+ Next
622
+ </Button>
623
+ </div>
624
+ </div>
625
+ )}
281
626
  </AdminListPage>
282
627
  )
283
628
  }
629
+ // CIL[END chunk_id="logspage_render_1783666257"]
630
+ // CIL[END chunk_id="logspage_function_logspage_1783666257"]