spine-framework 0.3.124 → 0.3.126

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 +179 -69
  6. package/.framework/cli/commands/generate.ts +83 -143
  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} +158 -56
  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 +224 -335
  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 +188 -16
  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 +685 -537
  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 +187 -144
  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 +195 -116
  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 +5 -2
  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,59 +1,44 @@
1
- /**
2
- * @module timers
3
- * @audience core-contributor
4
- * @layer api-handler
5
- * @stability stable
6
- *
7
- * CRUD API for the `timers` table. Timers are scheduled pipeline triggers
8
- * (cron-style). They are evaluated and fired by `system-cron.ts` on each
9
- * scheduled invocation.
10
- *
11
- * **Routed by:** `GET/POST/PATCH/DELETE /.netlify/functions/timers`
12
- *
13
- * **Actions:**
14
- * | method | ?action | handler |
15
- * |--------|----------|----------|
16
- * | POST | toggle | toggle |
17
- * | GET | ?id | get |
18
- * | GET | (default)| list |
19
- * | POST | — | create |
20
- * | PATCH | — | update |
21
- * | DELETE | — | remove (hard) |
22
- *
23
- * **Authorization:** All operations use `ctx.db` (RLS-scoped). Authenticated
24
- * principal required for writes.
25
- *
26
- * INVARIANT: `remove` is a hard delete.
27
- * INVARIANT: `update` only patches allowed fields: name, description, config,
28
- * pipeline_id, metadata, is_active.
29
- *
30
- * @seeAlso system-cron.ts (fires timers on schedule)
31
- * @seeAlso pipelines.ts (pipeline_id FK on timers)
32
- * @seeAlso audit.ts (emitLog for timer.* events)
33
- */
34
1
 
2
+
3
+
4
+
5
+
6
+
7
+ // CIL[BEGIN chunk_id="timers_module_header_1783931956" type="module_header" identity="module_header" parent="none"]
8
+ // CIL[DOC-MACRO purpose="Import dependencies for timers CRUD API"]
9
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide middleware, database, audit and permissions utilities"]
10
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
11
+ // CIL[DOC-CONTRACT inputs="none" outputs="imported modules" errors="none" side_effects="none"]
12
+ // CIL[DOC-MICRO logic_summary="Imports all required modules for timer management operations" notable_decisions="[]"]
13
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
14
+ // CIL[DOC-STABILITY stability="stable"]
15
+ // CIL[DOC-AUDIENCE audience="developer"]
16
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx, \."]
17
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
18
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
19
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
20
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
21
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
35
22
  import { createHandler } from './_shared/middleware'
36
- import { joins } from './_shared/db'
23
+ import { joins, adminDb } from './_shared/db'
37
24
  import { emitLog } from './_shared/audit'
38
25
  import { sanitizeRecordData } from './_shared/permissions'
39
-
40
- // ─── HANDLERS ─────────────────────────────────────────────────────────────────
41
-
42
- // ─── CHUNK_START: TIMERS_LIST ──────────────────────────────────────────────
43
- /**
44
- * @chunk-id TIMERS_LIST_1_0_0
45
- * @version 1.0.0
46
- * @hash 151a2403c9d974004a34303443368921966ea3adeada07e5f63b9a20ad3f08a1
47
- * @macro Timers List Handler
48
- * @micro Lists timers with filtering and sanitization
49
- * @inputs ctx: CoreContext — Request context with principal and database
50
- * @inputs _body: any — Request body (unused for GET)
51
- * @outputs Array of sanitized timer records with app/createdBy joins
52
- * @depends-on [createHandler, joins, sanitizeRecordData]
53
- * @depended-by [Netlify function routing]
54
- * @side-effects [DB queries, permission sanitization]
55
- * @tags timers, list, crud, filtering
56
- */
26
+ import { isSystemAdmin } from './_shared/principal'
27
+ // CIL[END chunk_id="timers_module_header_1783931956"]
28
+ // CIL[BEGIN chunk_id="timers_list_1783931956" type="function" identity="list" parent="none"]
29
+ // CIL[DOC-MACRO purpose="List timers with filtering and sanitization"]
30
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle timer listing with authentication and permissions"]
31
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
32
+ // CIL[DOC-CONTRACT inputs="none" outputs="sanitized timer array" errors="throws" side_effects="database queries"]
33
+ // CIL[DOC-MICRO logic_summary="Filters timers by app/type/active status, sanitizes based on permissions" notable_decisions="[]"]
34
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
35
+ // CIL[DOC-STABILITY stability="stable"]
36
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, \."]
37
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
38
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
39
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
40
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
41
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
57
42
  export const list = createHandler(async (ctx, _body) => {
58
43
  const { app_id, timer_type, is_active } = ctx.query || {}
59
44
 
@@ -61,9 +46,11 @@ export const list = createHandler(async (ctx, _body) => {
61
46
  throw new Error('Account context required')
62
47
  }
63
48
 
64
- let query = ctx.db
49
+ const db = isSystemAdmin(ctx.principal) ? adminDb : ctx.db
50
+
51
+ let query = db
65
52
  .from('timers')
66
- .select(`*, ${joins.app}, ${joins.createdBy}`)
53
+ .select('*')
67
54
  .order('name')
68
55
 
69
56
  if (app_id) {
@@ -87,23 +74,21 @@ export const list = createHandler(async (ctx, _body) => {
87
74
 
88
75
  return sanitized
89
76
  })
90
- // ─── CHUNK_END: TIMERS_LIST ────────────────────────────────────────────────
91
-
92
- // ─── CHUNK_START: TIMERS_GET ──────────────────────────────────────────────
93
- /**
94
- * @chunk-id TIMERS_GET_1_0_0
95
- * @version 1.0.0
96
- * @hash 8bbf46bb1410299eb881680ba4b508093157000a7fe525f7380e96ff0a241f32
97
- * @macro Timer Get Handler
98
- * @micro Returns single timer record with joins and sanitization
99
- * @inputs ctx: CoreContext — Request context with principal and database
100
- * @inputs _body: any — Request body (unused for GET)
101
- * @outputs Sanitized timer record with app/createdBy joins
102
- * @depends-on [createHandler, joins, sanitizeRecordData]
103
- * @depended-by [Netlify function routing]
104
- * @side-effects [DB single row query, permission sanitization]
105
- * @tags timers, get, crud, single-record
106
- */
77
+ // CIL[END chunk_id="timers_list_1783931956"]
78
+ // CIL[BEGIN chunk_id="timers_get_1783931956" type="function" identity="get" parent="none"]
79
+ // CIL[DOC-MACRO purpose="Get single timer by ID with sanitization"]
80
+ // CIL[DOC-RESPONSIBILITY responsibility="Retrieve and sanitize individual timer records"]
81
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"\\\"]"]
82
+ // CIL[DOC-CONTRACT inputs="none" outputs="sanitized timer object" errors="throws" side_effects="database query"]
83
+ // CIL[DOC-MICRO logic_summary="Queries timer by ID with app/createdBy joins, sanitizes based on permissions" notable_decisions="[]"]
84
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
85
+ // CIL[DOC-STABILITY stability="stable"]
86
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, \."]
87
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
88
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
89
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
90
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
91
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
107
92
  export const get = createHandler(async (ctx, _body) => {
108
93
  const { id } = ctx.query || {}
109
94
 
@@ -111,9 +96,11 @@ export const get = createHandler(async (ctx, _body) => {
111
96
  throw new Error('Timer ID is required')
112
97
  }
113
98
 
114
- const { data, error: err } = await ctx.db
99
+ const db = isSystemAdmin(ctx.principal) ? adminDb : ctx.db
100
+
101
+ const { data, error: err } = await db
115
102
  .from('timers')
116
- .select(`*, ${joins.app}, ${joins.createdBy}`)
103
+ .select('*')
117
104
  .eq('id', id)
118
105
  .single()
119
106
 
@@ -121,23 +108,21 @@ export const get = createHandler(async (ctx, _body) => {
121
108
 
122
109
  return await sanitizeRecordData(ctx, data, 'timer')
123
110
  })
124
- // ─── CHUNK_END: TIMERS_GET ────────────────────────────────────────────────
125
-
126
- // ─── CHUNK_START: TIMERS_CREATE ──────────────────────────────────────────────
127
- /**
128
- * @chunk-id TIMERS_CREATE_1_0_0
129
- * @version 1.0.0
130
- * @hash b655ea396b23dac3548323612decef91b712c0a2b42bc5c7bc0f79aee4d11af4
131
- * @macro Timer Create Handler
132
- * @micro Creates timer with validation and audit logging
133
- * @inputs ctx: CoreContext — Request context with principal and database
134
- * @inputs body: object — Timer data including name, timer_type, and optional fields
135
- * @outputs Inserted timer record
136
- * @depends-on [createHandler, emitLog]
137
- * @depended-by [Netlify function routing]
138
- * @side-effects [DB insert, audit logging]
139
- * @tags timers, create, crud, audit
140
- */
111
+ // CIL[END chunk_id="timers_get_1783931956"]
112
+ // CIL[BEGIN chunk_id="timers_create_1783931956" type="function" identity="create" parent="none"]
113
+ // CIL[DOC-MACRO purpose="Create new timer with validation and audit"]
114
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle timer creation with authentication and logging"]
115
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\"\\\"]"]
116
+ // CIL[DOC-CONTRACT inputs="none" outputs="created timer record" errors="throws" side_effects="database insert, audit log"]
117
+ // CIL[DOC-MICRO logic_summary="Validates user context, creates timer with defaults, emits audit log" notable_decisions="[]"]
118
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
119
+ // CIL[DOC-STABILITY stability="stable"]
120
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 1. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/src/components/ui/dialog.tsx, \."]
121
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
122
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
123
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
124
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
125
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
141
126
  export const create = createHandler(async (ctx, body) => {
142
127
  const { app_id, name, description, timer_type, config, pipeline_id, metadata } = body
143
128
 
@@ -174,23 +159,21 @@ export const create = createHandler(async (ctx, body) => {
174
159
 
175
160
  return data
176
161
  })
177
- // ─── CHUNK_END: TIMERS_CREATE ────────────────────────────────────────────────
178
-
179
- // ─── CHUNK_START: TIMERS_UPDATE ──────────────────────────────────────────────
180
- /**
181
- * @chunk-id TIMERS_UPDATE_1_0_0
182
- * @version 1.0.0
183
- * @hash 3c53499205d63b8643e28671b397b97b344976e88ea561860e2e394ca246942d
184
- * @macro Timer Update Handler
185
- * @micro Updates timer with field allowlist and audit logging
186
- * @inputs ctx: CoreContext — Request context with principal and database
187
- * @inputs body: object — Timer updates including id and updatable fields
188
- * @outputs Updated timer record
189
- * @depends-on [createHandler, emitLog]
190
- * @depended-by [Netlify function routing]
191
- * @side-effects [DB update, audit logging]
192
- * @tags timers, update, crud, audit
193
- */
162
+ // CIL[END chunk_id="timers_create_1783931956"]
163
+ // CIL[BEGIN chunk_id="timers_update_1783931956" type="function" identity="update" parent="none"]
164
+ // CIL[DOC-MACRO purpose="Update existing timer with field allowlist"]
165
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle timer updates with validation and audit logging"]
166
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[]"]
167
+ // CIL[DOC-CONTRACT inputs="none" outputs="updated timer record" errors="throws" side_effects="database update, audit log"]
168
+ // CIL[DOC-MICRO logic_summary="Updates only allowed fields, adds timestamp, emits audit log" notable_decisions="[]"]
169
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
170
+ // CIL[DOC-STABILITY stability="stable"]
171
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: none."]
172
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
173
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
174
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
175
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
176
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
194
177
  export const update = createHandler(async (ctx, body) => {
195
178
  const id = body?.id || ctx.query?.id
196
179
  const { id: _bodyId, ...updates } = body || {}
@@ -199,7 +182,7 @@ export const update = createHandler(async (ctx, body) => {
199
182
  throw new Error('Timer ID is required')
200
183
  }
201
184
 
202
- const allowed = ['name', 'description', 'config', 'pipeline_id', 'metadata', 'is_active']
185
+ const allowed = ['name', 'description', 'config', 'pipeline_id', 'metadata', 'is_active', 'timer_type', 'app_id']
203
186
  const updateData: Record<string, any> = { updated_at: new Date().toISOString() }
204
187
  for (const key of allowed) {
205
188
  if (updates[key] !== undefined) updateData[key] = updates[key]
@@ -221,137 +204,106 @@ export const update = createHandler(async (ctx, body) => {
221
204
 
222
205
  return data
223
206
  })
224
- // ─── CHUNK_END: TIMERS_UPDATE ────────────────────────────────────────────────
225
-
226
- // ─── CHUNK_START: TIMERS_TOGGLE ──────────────────────────────────────────────
227
- /**
228
- * @chunk-id TIMERS_TOGGLE_1_0_0
229
- * @version 1.0.0
230
- * @hash 5db82e7a94fbdb9a0e3452c63a044789a993ed8881033d9372b86778c50a2d8c
231
- * @macro Timer Toggle Handler
232
- * @micro Activates or deactivates timer with audit logging
233
- * @inputs ctx: CoreContext — Request context with principal and database
234
- * @inputs body: object — Timer id and is_active boolean
235
- * @outputs Updated timer record
236
- * @depends-on [createHandler, emitLog]
237
- * @depended-by [Netlify function routing]
238
- * @side-effects [DB update, audit logging]
239
- * @tags timers, toggle, state-transition, audit
240
- */
241
- export const toggle = createHandler(async (ctx, body) => {
242
- const { id, is_active } = body
207
+ // CIL[END chunk_id="timers_update_1783931956"]
208
+ // CIL[BEGIN chunk_id="timers_remove_1783931956" type="function" identity="remove" parent="none"]
209
+ // CIL[DOC-MACRO purpose="Hard delete timer with validation and audit"]
210
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle timer deletion with safety checks and logging"]
211
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[]"]
212
+ // CIL[DOC-CONTRACT inputs="none" outputs="success indicator" errors="throws" side_effects="database delete, audit log"]
213
+ // CIL[DOC-MICRO logic_summary="Validates timer exists, hard deletes record, emits audit log" notable_decisions="[]"]
214
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
215
+ // CIL[DOC-STABILITY stability="stable"]
216
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: none."]
217
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
218
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
219
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
220
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
221
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
222
+ export const remove = createHandler(async (ctx, body) => {
223
+ const id = body?.id || ctx.query?.id
243
224
 
244
- if (!id || is_active === undefined) {
245
- throw new Error('Timer ID and is_active are required')
225
+ if (!id) {
226
+ throw new Error('Timer ID is required')
246
227
  }
247
228
 
248
- const { data, error: err } = await ctx.db
229
+ const { data: existing } = await ctx.db
249
230
  .from('timers')
250
- .update({ is_active, updated_at: new Date().toISOString() })
231
+ .select('name, timer_type')
251
232
  .eq('id', id)
252
- .select()
253
233
  .single()
254
234
 
235
+ if (!existing) {
236
+ throw new Error('Timer not found')
237
+ }
238
+
239
+ const { error: err } = await ctx.db
240
+ .from('timers')
241
+ .delete()
242
+ .eq('id', id)
243
+
255
244
  if (err) throw err
256
245
 
257
- await emitLog(ctx, 'timer.toggled',
246
+ await emitLog(ctx, 'timer.deleted',
258
247
  { type: 'timer', id },
259
- { after: { is_active } }
248
+ { before: { name: existing.name, timer_type: existing.timer_type } }
260
249
  )
261
250
 
262
- return data
251
+ return { success: true }
263
252
  })
264
- // ─── CHUNK_END: TIMERS_TOGGLE ────────────────────────────────────────────────
265
-
266
- // ─── CHUNK_START: TIMERS_REMOVE ──────────────────────────────────────────────
267
- /**
268
- * @chunk-id TIMERS_REMOVE_1_0_0
269
- * @version 1.0.0
270
- * @hash 2d999f6948d616925eaa36be8b39b2fd23de364bf242d4fb0ff3304e1ff9f275
271
- * @macro Timer Remove Handler
272
- * @micro Hard-deletes timer with audit logging
273
- * @inputs ctx: CoreContext — Request context with principal and database
274
- * @inputs _body: any — Request body (unused for DELETE)
275
- * @outputs {success: true} — Confirmation of successful deletion
276
- * @depends-on [createHandler, emitLog]
277
- * @depended-by [Netlify function routing]
278
- * @side-effects [DB delete, audit logging]
279
- * @tags timers, remove, delete, audit
280
- */
281
- export const remove = createHandler(async (ctx, _body) => {
282
- const id = ctx.query?.id
253
+ // CIL[END chunk_id="timers_remove_1783931956"]
254
+ // CIL[BEGIN chunk_id="timers_toggle_1783931956" type="function" identity="toggle" parent="none"]
255
+ // CIL[DOC-MACRO purpose="Toggle timer active status with audit logging"]
256
+ // CIL[DOC-RESPONSIBILITY responsibility="Handle timer activation/deactivation with validation"]
257
+ // CIL[DOC-CONTEXT module="timers" layer="api-handler" related_files="[]"]
258
+ // CIL[DOC-CONTRACT inputs="none" outputs="updated timer record" errors="throws" side_effects="database update, audit log"]
259
+ // CIL[DOC-MICRO logic_summary="Flips is_active boolean, updates timestamp, emits audit log" notable_decisions="[]"]
260
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
261
+ // CIL[DOC-STABILITY stability="stable"]
262
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: none."]
263
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
264
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
265
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
266
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
267
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
268
+ export const toggle = createHandler(async (ctx, body) => {
269
+ const id = body?.id || ctx.query?.id
283
270
 
284
271
  if (!id) {
285
272
  throw new Error('Timer ID is required')
286
273
  }
287
274
 
288
- const { data: current } = await ctx.db
275
+ const { data: existing } = await ctx.db
289
276
  .from('timers')
290
- .select('id, name')
277
+ .select('is_active, name')
291
278
  .eq('id', id)
292
279
  .single()
293
280
 
294
- if (!current) throw new Error('Timer not found')
281
+ if (!existing) {
282
+ throw new Error('Timer not found')
283
+ }
295
284
 
296
- const { error: err } = await ctx.db
285
+ const newStatus = !existing.is_active
286
+
287
+ const { data, error: err } = await ctx.db
297
288
  .from('timers')
298
- .delete()
289
+ .update({
290
+ is_active: newStatus,
291
+ updated_at: new Date().toISOString()
292
+ })
299
293
  .eq('id', id)
294
+ .select()
295
+ .single()
300
296
 
301
297
  if (err) throw err
302
298
 
303
- await emitLog(ctx, 'timer.deleted',
299
+ await emitLog(ctx, 'timer.toggled',
304
300
  { type: 'timer', id },
305
- { before: current }
301
+ {
302
+ before: { is_active: existing.is_active },
303
+ after: { is_active: newStatus }
304
+ }
306
305
  )
307
306
 
308
- return { success: true }
309
- })
310
- // ─── CHUNK_END: TIMERS_REMOVE ────────────────────────────────────────────────
311
-
312
- // ─── MAIN HANDLER ────────────────────────────────────────────────────────────
313
-
314
- // ─── CHUNK_START: TIMERS_HANDLER ──────────────────────────────────────────────
315
- /**
316
- * @chunk-id TIMERS_HANDLER_1_0_0
317
- * @version 1.0.0
318
- * @hash e890b54a4f767885a6e9d54b4ab19b968e09f6fc2f8db840d5b60df1e3cd2ba3
319
- * @macro Timers Router
320
- * @micro Routes HTTP methods and actions to appropriate timer handlers
321
- * @inputs ctx: CoreContext — Request context with principal and database
322
- * @inputs body: any — Request body for POST/PATCH/DELETE operations
323
- * @outputs Varies — Depends on routed handler (list/get/create/update/remove/toggle)
324
- * @depends-on [createHandler, list, get, create, update, remove, toggle]
325
- * @depended-by [Netlify function routing]
326
- * @side-effects [Delegates to appropriate handler]
327
- * @tags timers, router, crud, netlify-function
328
- */
329
- export const handler = createHandler(async (ctx, body) => {
330
- const { action } = ctx.query || {}
331
- const method = ctx.query?.method || 'GET'
332
-
333
- switch (action) {
334
- case 'toggle':
335
- if (method === 'POST') {
336
- return await toggle(ctx, body)
337
- }
338
- break
339
- default:
340
- if (method === 'GET') {
341
- if (ctx.query?.id) {
342
- return await get(ctx, body)
343
- } else {
344
- return await list(ctx, body)
345
- }
346
- } else if (method === 'POST') {
347
- return await create(ctx, body)
348
- } else if (method === 'PATCH') {
349
- return await update(ctx, body)
350
- } else if (method === 'DELETE') {
351
- return await remove(ctx, body)
352
- }
353
- }
354
-
355
- throw new Error('Invalid action or method')
307
+ return data
356
308
  })
357
- // ─── CHUNK_END: TIMERS_HANDLER ────────────────────────────────────────────────
309
+ // CIL[END chunk_id="timers_toggle_1783931956"]