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.
- package/.framework/cli/commands/agents.ts +35 -37
- package/.framework/cli/commands/auth.ts +35 -34
- package/.framework/cli/commands/create-app.ts +104 -40
- package/.framework/cli/commands/dev.ts +104 -69
- package/.framework/cli/commands/doctor.ts +179 -69
- package/.framework/cli/commands/generate.ts +83 -143
- package/.framework/cli/commands/init.ts +72 -34
- package/.framework/cli/commands/install-app.ts +260 -125
- package/.framework/cli/commands/items.ts +33 -44
- package/.framework/cli/commands/migrate.ts +122 -40
- package/.framework/cli/commands/migrations.ts +33 -40
- package/.framework/cli/commands/pipelines.ts +31 -39
- package/.framework/cli/commands/status.ts +47 -23
- package/.framework/cli/commands/system.ts +47 -37
- package/.framework/cli/commands/test.ts +112 -68
- package/.framework/cli/commands/validate-app.ts +215 -121
- package/.framework/cli/context.ts +112 -130
- package/.framework/cli/env-loader.ts +47 -18
- package/.framework/cli/index.ts +81 -42
- package/.framework/docs/runtime-types.md +1024 -0
- package/.framework/functions/_shared/agent-runner.ts +1296 -961
- package/.framework/functions/_shared/app-manifest.ts +82 -68
- package/.framework/functions/_shared/audit.ts +135 -83
- package/.framework/functions/_shared/{cil-state.ts → cil.ts} +158 -56
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +224 -335
- package/.framework/functions/_shared/kb.ts +319 -0
- package/.framework/functions/_shared/llm.ts +92 -0
- package/.framework/functions/_shared/logging.ts +288 -0
- package/.framework/functions/_shared/middleware.ts +329 -365
- package/.framework/functions/_shared/outcomes.ts +36 -0
- package/.framework/functions/_shared/permissions.ts +359 -643
- package/.framework/functions/_shared/pipeline-runner.ts +243 -316
- package/.framework/functions/_shared/principal.ts +376 -468
- package/.framework/functions/_shared/resolve-credentials.ts +102 -0
- package/.framework/functions/_shared/resolve-ids.ts +188 -16
- package/.framework/functions/_shared/retry-deliveries.ts +104 -0
- package/.framework/functions/_shared/schema-utils.ts +611 -373
- package/.framework/functions/_shared/testing.ts +207 -137
- package/.framework/functions/_shared/tracing.ts +276 -0
- package/.framework/functions/_shared/trigger-engine.ts +159 -211
- package/.framework/functions/_shared/webhook-registration.ts +95 -81
- package/.framework/functions/_shared/webhook-registry.ts +153 -75
- package/.framework/functions/account-nodes.ts +31 -53
- package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
- package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
- package/.framework/functions/adapters/openai-outbound.ts +40 -0
- package/.framework/functions/admin-data.ts +685 -537
- package/.framework/functions/admin-funnel.ts +31 -20
- package/.framework/functions/admin-install-funnel.ts +47 -28
- package/.framework/functions/admin-signals.ts +47 -29
- package/.framework/functions/ai-agents.ts +122 -147
- package/.framework/functions/ai-interactions.ts +180 -90
- package/.framework/functions/api-keys.ts +250 -192
- package/.framework/functions/apps.ts +203 -197
- package/.framework/functions/auth.ts +98 -91
- package/.framework/functions/cil-agent-ingest.ts +773 -0
- package/.framework/functions/cil-agent.ts +592 -0
- package/.framework/functions/cil-callmap.ts +1227 -0
- package/.framework/functions/cil-config.ts +583 -0
- package/.framework/functions/cil-context.ts +445 -0
- package/.framework/functions/cil-doc.ts +1752 -0
- package/.framework/functions/cil-embeddings.ts +1202 -0
- package/.framework/functions/cil-graph.ts +585 -0
- package/.framework/functions/cil-ingest.ts +2416 -0
- package/.framework/functions/cil-pipeline.ts +318 -0
- package/.framework/functions/cil-project.ts +499 -0
- package/.framework/functions/cil-validate.ts +469 -0
- package/.framework/functions/debug-auth.ts +73 -53
- package/.framework/functions/deliveries.ts +117 -0
- package/.framework/functions/embeddings.ts +528 -516
- package/.framework/functions/eval-harness.ts +158 -106
- package/.framework/functions/integration-outbound.ts +311 -0
- package/.framework/functions/integration-routes.ts +240 -466
- package/.framework/functions/integrations.ts +132 -140
- package/.framework/functions/invites.ts +401 -201
- package/.framework/functions/item-progress.ts +113 -53
- package/.framework/functions/kb.ts +28 -0
- package/.framework/functions/logs.ts +239 -222
- package/.framework/functions/observability.ts +308 -259
- package/.framework/functions/pipeline-executions.ts +179 -235
- package/.framework/functions/pipelines.ts +163 -205
- package/.framework/functions/prompt-configs.ts +109 -156
- package/.framework/functions/roles.ts +97 -147
- package/.framework/functions/system-cron.ts +132 -218
- package/.framework/functions/system.ts +112 -52
- package/.framework/functions/tests.ts +32 -28
- package/.framework/functions/timers.ts +162 -210
- package/.framework/functions/triggers.ts +282 -346
- package/.framework/functions/types.ts +283 -400
- package/.framework/migrations/001_core_schema.sql +630 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
- package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
- package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
- package/.framework/migrations/005_core_observability.sql +598 -0
- package/.framework/migrations/006_security_hardening_rls.sql +97 -0
- package/.framework/migrations/007_kb_article_list.sql +237 -0
- package/.framework/migrations/008_items_target.sql +8 -0
- package/.framework/migrations/009_roles_slug_unique.sql +11 -0
- package/.framework/public/spine.config.json +91 -0
- package/.framework/scripts/app-install-cli.ts +112 -98
- package/.framework/src/App.tsx +67 -20
- package/.framework/src/apps/admin/index.tsx +97 -27
- package/.framework/src/components/AppWrapper.tsx +50 -11
- package/.framework/src/components/CustomAppLoader.tsx +131 -22
- package/.framework/src/components/admin/AdminListPage.tsx +75 -8
- package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
- package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
- package/.framework/src/components/admin/PageInstructions.tsx +49 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
- package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
- package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
- package/.framework/src/components/app-sidebar.tsx +50 -3
- package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
- package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
- package/.framework/src/components/kb/KBArticleList.tsx +557 -0
- package/.framework/src/components/layout/AppShell.tsx +54 -16
- package/.framework/src/components/layout/Header.tsx +50 -38
- package/.framework/src/components/layout/Layout.tsx +48 -32
- package/.framework/src/components/layout/Sidebar.tsx +167 -16
- package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
- package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
- package/.framework/src/components/runtime/DataFilters.tsx +78 -1
- package/.framework/src/components/runtime/DataHeader.tsx +32 -29
- package/.framework/src/components/runtime/DataListPage.tsx +161 -2
- package/.framework/src/components/runtime/DataStats.tsx +48 -1
- package/.framework/src/components/runtime/DataTable.tsx +153 -1
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
- package/.framework/src/components/runtime/index.ts +16 -9
- package/.framework/src/components/search-form.tsx +33 -1
- package/.framework/src/components/shared/AgentView.tsx +48 -51
- package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
- package/.framework/src/components/shared/InviteManager.tsx +113 -52
- package/.framework/src/components/shared/MemberList.tsx +182 -0
- package/.framework/src/components/shared/SchemaFields.tsx +96 -78
- package/.framework/src/components/ui/DataTable.tsx +86 -56
- package/.framework/src/components/ui/Form.tsx +188 -109
- package/.framework/src/components/ui/ItemCard.tsx +86 -58
- package/.framework/src/components/ui/ItemListView.tsx +88 -61
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
- package/.framework/src/components/ui/Modal.tsx +81 -4
- package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
- package/.framework/src/components/ui/accordion.tsx +97 -5
- package/.framework/src/components/ui/alert-dialog.tsx +225 -13
- package/.framework/src/components/ui/alert.tsx +113 -6
- package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
- package/.framework/src/components/ui/avatar.tsx +129 -7
- package/.framework/src/components/ui/badge.tsx +65 -3
- package/.framework/src/components/ui/breadcrumb.tsx +145 -8
- package/.framework/src/components/ui/button-group.tsx +81 -4
- package/.framework/src/components/ui/button.tsx +49 -2
- package/.framework/src/components/ui/calendar.tsx +65 -3
- package/.framework/src/components/ui/card.tsx +145 -8
- package/.framework/src/components/ui/carousel.tsx +129 -7
- package/.framework/src/components/ui/chart.tsx +161 -10
- package/.framework/src/components/ui/checkbox.tsx +49 -2
- package/.framework/src/components/ui/collapsible.tsx +81 -5
- package/.framework/src/components/ui/combobox.tsx +305 -20
- package/.framework/src/components/ui/command.tsx +177 -11
- package/.framework/src/components/ui/context-menu.tsx +273 -17
- package/.framework/src/components/ui/dialog.tsx +209 -27
- package/.framework/src/components/ui/direction.tsx +64 -4
- package/.framework/src/components/ui/drawer.tsx +193 -12
- package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
- package/.framework/src/components/ui/empty.tsx +145 -9
- package/.framework/src/components/ui/field.tsx +209 -14
- package/.framework/src/components/ui/hover-card.tsx +81 -4
- package/.framework/src/components/ui/input-group.tsx +162 -10
- package/.framework/src/components/ui/input-otp.tsx +98 -5
- package/.framework/src/components/ui/input.tsx +49 -2
- package/.framework/src/components/ui/item.tsx +225 -13
- package/.framework/src/components/ui/kbd.tsx +65 -3
- package/.framework/src/components/ui/label.tsx +49 -2
- package/.framework/src/components/ui/menubar.tsx +289 -17
- package/.framework/src/components/ui/native-select.tsx +97 -5
- package/.framework/src/components/ui/navigation-menu.tsx +177 -10
- package/.framework/src/components/ui/pagination.tsx +161 -9
- package/.framework/src/components/ui/popover.tsx +145 -8
- package/.framework/src/components/ui/progress.tsx +49 -2
- package/.framework/src/components/ui/radio-group.tsx +65 -3
- package/.framework/src/components/ui/resizable.tsx +82 -4
- package/.framework/src/components/ui/scroll-area.tsx +65 -3
- package/.framework/src/components/ui/select.tsx +193 -11
- package/.framework/src/components/ui/separator.tsx +49 -2
- package/.framework/src/components/ui/sheet.tsx +193 -11
- package/.framework/src/components/ui/sidebar.tsx +481 -38
- package/.framework/src/components/ui/skeleton.tsx +49 -2
- package/.framework/src/components/ui/slider.tsx +49 -2
- package/.framework/src/components/ui/sonner.tsx +49 -2
- package/.framework/src/components/ui/spinner.tsx +49 -2
- package/.framework/src/components/ui/switch.tsx +49 -2
- package/.framework/src/components/ui/table-primitives.tsx +160 -33
- package/.framework/src/components/ui/table.tsx +161 -9
- package/.framework/src/components/ui/tabs.tsx +113 -6
- package/.framework/src/components/ui/textarea.tsx +49 -2
- package/.framework/src/components/ui/toggle-group.tsx +81 -4
- package/.framework/src/components/ui/toggle.tsx +65 -3
- package/.framework/src/components/ui/tooltip.tsx +97 -5
- package/.framework/src/contexts/AppContext.tsx +129 -45
- package/.framework/src/contexts/AuthContext.tsx +187 -144
- package/.framework/src/hooks/use-mobile.ts +48 -2
- package/.framework/src/hooks/useApi.ts +208 -159
- package/.framework/src/hooks/useAppPath.ts +32 -23
- package/.framework/src/hooks/useApps.ts +51 -20
- package/.framework/src/hooks/useEntityList.ts +32 -78
- package/.framework/src/hooks/useEntityRecord.ts +35 -96
- package/.framework/src/hooks/useForm.ts +32 -92
- package/.framework/src/hooks/useListSchema.ts +49 -78
- package/.framework/src/hooks/useSchemaRecord.ts +114 -105
- package/.framework/src/lib/api.ts +195 -116
- package/.framework/src/lib/supabase.ts +98 -64
- package/.framework/src/lib/utils.ts +287 -151
- package/.framework/src/main.tsx +49 -3
- package/.framework/src/pages/DashboardPage.tsx +52 -29
- package/.framework/src/pages/NotFoundPage.tsx +32 -10
- package/.framework/src/pages/SetupPage.tsx +32 -12
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
- package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
- package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
- package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
- package/.framework/src/pages/admin/AppsPage.tsx +49 -2
- package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
- package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
- package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
- package/.framework/src/pages/admin/LogsPage.tsx +422 -75
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
- package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
- package/.framework/src/pages/admin/RolesPage.tsx +171 -18
- package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
- package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
- package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
- package/.framework/src/pages/admin/TimersPage.tsx +48 -20
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
- package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
- package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
- package/.framework/src/pages/admin/TypesPage.tsx +48 -20
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
- package/.framework/src/pages/auth/LoginPage.tsx +50 -23
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
- package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
- package/.framework/src/types/auth.ts +128 -71
- package/.framework/src/types/types.ts +373 -157
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
- package/docs/README.md +9 -130
- package/netlify.toml +5 -2
- package/package.json +13 -25
- package/scripts/kb-ingest-docs.ts +203 -0
- package/spine.config.json +65 -4
- package/.framework/migrations/001_schema.sql +0 -425
- package/.framework/migrations/002_rls_and_functions.sql +0 -763
- package/.framework/migrations/004_enhancements.sql +0 -43
- package/.framework/migrations/005_auth_user_trigger.sql +0 -105
- package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
- package/.framework/migrations/016_invites.sql +0 -27
- package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
- package/.framework/migrations/018_apps_required_roles.sql +0 -17
- package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
- package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
- package/.framework/migrations/021_app_domains.sql +0 -112
- package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
- package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
- package/.framework/migrations/024_messages_account_id.sql +0 -9
- package/.framework/migrations/025_retype_threads_messages.sql +0 -240
- package/.framework/migrations/026_fix_rls_policies.sql +0 -47
- package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
- package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
- package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
- package/.framework/migrations/030_messages_updated_by.sql +0 -6
- package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
- package/docs/APPS.md +0 -232
- package/docs/ARCHITECTURE.md +0 -246
- package/docs/INSTALL.md +0 -155
- package/docs/design-schema-spec.md +0 -1837
- package/docs/dev-guides/01-create-an-app.md +0 -183
- package/docs/dev-guides/02-create-a-function.md +0 -178
- package/docs/dev-guides/03-create-a-component.md +0 -178
- package/docs/dev-guides/04-webhook-handlers.md +0 -129
- package/docs/dev-guides/05-testing.md +0 -168
- package/docs/dev-guides/README.md +0 -40
- package/docs/npm-packages-plan.md +0 -288
- package/docs/spine-core--api-reference.md +0 -822
|
@@ -1,86 +1,35 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module system-cron
|
|
3
|
-
* @audience core-contributor
|
|
4
|
-
* @layer api-handler
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Scheduled job runner invoked by an external cron service (e.g., AWS
|
|
8
|
-
* EventBridge, Google Cloud Scheduler). On each tick it:
|
|
9
|
-
*
|
|
10
|
-
* 1. Authenticates the request via `SCHEDULER_API_KEY` or machine principal
|
|
11
|
-
* 2. Fetches all schedules due via `get_due_schedules` RPC
|
|
12
|
-
* 3. For each schedule: validates creator, loads action + machine principal,
|
|
13
|
-
* checks scope, executes action, records outcome
|
|
14
|
-
* 4. Fetches all timers due via `get_due_timers` RPC and runs each pipeline
|
|
15
|
-
* 5. Evaluates threshold alerts via `evaluateThresholds`
|
|
16
|
-
* 6. Runs daily log cleanup at 00:00 UTC via `cleanupOldLogs`
|
|
17
|
-
*
|
|
18
|
-
* **Routed by:** `POST /.netlify/functions/system-cron`
|
|
19
|
-
*
|
|
20
|
-
* **Authentication:** Request must supply `SCHEDULER_API_KEY` via `?api_key`
|
|
21
|
-
* or `?scheduler_key`, OR originate from an internal machine principal
|
|
22
|
-
* (type='machine', machineType='internal'). Unauthorized requests receive 403.
|
|
23
|
-
*
|
|
24
|
-
* **Response shape:**
|
|
25
|
-
* ```ts
|
|
26
|
-
* {
|
|
27
|
-
* executed: number
|
|
28
|
-
* success: number
|
|
29
|
-
* failed: number
|
|
30
|
-
* skipped: number
|
|
31
|
-
* thresholds_evaluated: number
|
|
32
|
-
* thresholds_breached: number
|
|
33
|
-
* logs_cleaned: number
|
|
34
|
-
* results: Array<{ scheduleId, actionId, status, error?, durationMs }>
|
|
35
|
-
* }
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* INVARIANT: Uses `adminDb` (service-role client, bypasses RLS) because
|
|
39
|
-
* machine principals must access cross-account data.
|
|
40
|
-
* INVARIANT: Log cleanup only runs when the current UTC time is 00:00.
|
|
41
|
-
*
|
|
42
|
-
* @seeAlso timers.ts (timer configuration CRUD)
|
|
43
|
-
* @seeAlso pipelines.ts (pipeline configuration CRUD)
|
|
44
|
-
* @seeAlso pipeline-runner.ts (runPipeline — timer/schedule execution)
|
|
45
|
-
* @seeAlso observability.ts (analytics RPCs used by evaluateThresholds)
|
|
46
|
-
* @seeAlso audit.ts (emitAudit for cron lifecycle events)
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
1
|
import { createHandler, RequestContext } from './_shared/middleware'
|
|
50
2
|
import { adminDb } from './_shared/db'
|
|
51
3
|
import { emitAudit } from './_shared/audit'
|
|
52
4
|
import { runPipeline } from './_shared/pipeline-runner'
|
|
5
|
+
import { retryPendingDeliveries } from './_shared/retry-deliveries'
|
|
53
6
|
|
|
54
7
|
const SCHEDULER_API_KEY: string | undefined = (globalThis as any).process?.env?.SCHEDULER_API_KEY || (globalThis as any).Deno?.env?.get?.('SCHEDULER_API_KEY')
|
|
55
8
|
|
|
56
|
-
// ─── MAIN HANDLER ────────────────────────────────────────────────────────────
|
|
57
9
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// CIL[BEGIN chunk_id="system-cron_module_header_1783932909" type="module_header" identity="module_header" parent="none"]
|
|
15
|
+
// CIL[DOC-MACRO purpose="Executes scheduled actions, timers, and threshold monitoring"]
|
|
16
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Handle system cron execution with security"]
|
|
17
|
+
// CIL[DOC-CONTEXT module="system-cron" layer="api-handler" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
|
|
18
|
+
// CIL[DOC-CONTRACT inputs="ctx: RequestContext" outputs="Execution summary" errors="Throws on execution failures" side_effects="Database operations, audit logging"]
|
|
19
|
+
// CIL[DOC-MICRO logic_summary="Processes schedules, timers, thresholds, and cleanup" notable_decisions="[]"]
|
|
20
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="complex_dependencies"]
|
|
21
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
22
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
23
|
+
// CIL[DOC-VECTOR type="context" content="Layer: api-handler. 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/pages/admin/RolesPage.tsx, .framework/functions/_shared/principal.ts, \."]
|
|
24
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
25
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
26
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
27
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
28
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
74
29
|
export const handler = createHandler(async (ctx: RequestContext) => {
|
|
75
|
-
// ============================================
|
|
76
|
-
// SECURITY: Validate this is an internal request
|
|
77
|
-
// ============================================
|
|
78
|
-
|
|
79
|
-
// Check if request has scheduler authentication
|
|
80
30
|
const requestApiKey = ctx.query?.api_key || ctx.query?.scheduler_key
|
|
81
31
|
|
|
82
32
|
if (requestApiKey !== SCHEDULER_API_KEY) {
|
|
83
|
-
// Also allow if the principal is a system machine (for internal invocations)
|
|
84
33
|
if (ctx.principal?.type !== 'machine' || ctx.principal?.machineType !== 'internal') {
|
|
85
34
|
await emitAudit(ctx, 'system_cron.unauthorized_access', {
|
|
86
35
|
type: 'system',
|
|
@@ -94,10 +43,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
94
43
|
}
|
|
95
44
|
}
|
|
96
45
|
|
|
97
|
-
// ============================================
|
|
98
|
-
// Find and execute due schedules
|
|
99
|
-
// ============================================
|
|
100
|
-
|
|
101
46
|
const results: Array<{
|
|
102
47
|
scheduleId: string
|
|
103
48
|
actionId: string
|
|
@@ -107,7 +52,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
107
52
|
}> = []
|
|
108
53
|
|
|
109
54
|
try {
|
|
110
|
-
// Get all schedules due for execution
|
|
111
55
|
const { data: dueSchedules, error: schedulesError } = await adminDb.rpc('get_due_schedules', {
|
|
112
56
|
p_now: new Date().toISOString()
|
|
113
57
|
})
|
|
@@ -127,18 +71,15 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
127
71
|
}
|
|
128
72
|
}
|
|
129
73
|
|
|
130
|
-
// Execute each due schedule
|
|
131
74
|
for (const schedule of dueSchedules) {
|
|
132
75
|
const startTime = Date.now()
|
|
133
76
|
|
|
134
77
|
try {
|
|
135
|
-
// Validate schedule can run (creator still active)
|
|
136
78
|
const { data: validation, error: validationError } = await adminDb.rpc('validate_schedule_creator', {
|
|
137
79
|
p_schedule_id: schedule.schedule_id
|
|
138
80
|
})
|
|
139
81
|
|
|
140
82
|
if (validationError || !validation?.is_valid) {
|
|
141
|
-
// Schedule was auto-paused by validation function
|
|
142
83
|
results.push({
|
|
143
84
|
scheduleId: schedule.schedule_id,
|
|
144
85
|
actionId: schedule.action_id,
|
|
@@ -149,7 +90,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
149
90
|
continue
|
|
150
91
|
}
|
|
151
92
|
|
|
152
|
-
// Load the action
|
|
153
93
|
const { data: action, error: actionError } = await adminDb
|
|
154
94
|
.from('actions')
|
|
155
95
|
.select('*')
|
|
@@ -160,7 +100,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
160
100
|
throw new Error(`Action not found: ${schedule.action_id}`)
|
|
161
101
|
}
|
|
162
102
|
|
|
163
|
-
// Load the machine principal
|
|
164
103
|
const { data: machine, error: machineError } = await adminDb
|
|
165
104
|
.from('api_keys')
|
|
166
105
|
.select('*')
|
|
@@ -171,7 +110,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
171
110
|
throw new Error(`Machine principal not found: ${schedule.machine_principal_id}`)
|
|
172
111
|
}
|
|
173
112
|
|
|
174
|
-
// Create execution context with machine principal
|
|
175
113
|
const executionCtx: RequestContext = {
|
|
176
114
|
requestId: ctx.requestId,
|
|
177
115
|
principal: {
|
|
@@ -188,14 +126,13 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
188
126
|
cronId: schedule.schedule_id
|
|
189
127
|
}
|
|
190
128
|
},
|
|
191
|
-
db: adminDb,
|
|
129
|
+
db: adminDb,
|
|
192
130
|
accountId: machine.account_id,
|
|
193
131
|
appId: null,
|
|
194
132
|
requestPath: '/.netlify/functions/system-cron',
|
|
195
133
|
query: {}
|
|
196
134
|
}
|
|
197
135
|
|
|
198
|
-
// Check machine has required scope for this action
|
|
199
136
|
const requiredScope = action.required_scopes?.[0] || `${action.handler}:execute`
|
|
200
137
|
const hasScope = executionCtx.principal.scopes?.includes(requiredScope) ||
|
|
201
138
|
executionCtx.principal.scopes?.includes('*:*')
|
|
@@ -204,10 +141,8 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
204
141
|
throw new Error(`Machine lacks required scope: ${requiredScope}`)
|
|
205
142
|
}
|
|
206
143
|
|
|
207
|
-
// Execute the action
|
|
208
144
|
const executionResult = await executeAction(executionCtx, action, schedule.config)
|
|
209
145
|
|
|
210
|
-
// Record execution success
|
|
211
146
|
await adminDb.from('schedule_executions').insert({
|
|
212
147
|
schedule_id: schedule.schedule_id,
|
|
213
148
|
account_id: schedule.account_id,
|
|
@@ -218,14 +153,12 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
218
153
|
duration_ms: Date.now() - startTime
|
|
219
154
|
})
|
|
220
155
|
|
|
221
|
-
// Update schedule state
|
|
222
156
|
await adminDb.rpc('update_schedule_after_run', {
|
|
223
157
|
p_schedule_id: schedule.schedule_id,
|
|
224
158
|
p_success: true,
|
|
225
159
|
p_error_message: null
|
|
226
160
|
})
|
|
227
161
|
|
|
228
|
-
// Emit audit log
|
|
229
162
|
await emitAudit(executionCtx, 'schedule.execute', {
|
|
230
163
|
type: 'schedule',
|
|
231
164
|
id: schedule.schedule_id,
|
|
@@ -246,7 +179,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
246
179
|
} catch (execError: any) {
|
|
247
180
|
const errorMessage = execError.message || 'Execution failed'
|
|
248
181
|
|
|
249
|
-
// Record execution failure
|
|
250
182
|
await adminDb.from('schedule_executions').insert({
|
|
251
183
|
schedule_id: schedule.schedule_id,
|
|
252
184
|
account_id: schedule.account_id,
|
|
@@ -257,7 +189,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
257
189
|
duration_ms: Date.now() - startTime
|
|
258
190
|
})
|
|
259
191
|
|
|
260
|
-
// Update schedule state
|
|
261
192
|
await adminDb.rpc('update_schedule_after_run', {
|
|
262
193
|
p_schedule_id: schedule.schedule_id,
|
|
263
194
|
p_success: false,
|
|
@@ -274,10 +205,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
274
205
|
}
|
|
275
206
|
}
|
|
276
207
|
|
|
277
|
-
// ============================================
|
|
278
|
-
// Execute due timers (pipeline-based timers)
|
|
279
|
-
// ============================================
|
|
280
|
-
|
|
281
208
|
try {
|
|
282
209
|
const { data: dueTimers, error: timersError } = await adminDb.rpc('get_due_timers', {
|
|
283
210
|
p_now: new Date().toISOString()
|
|
@@ -288,12 +215,10 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
288
215
|
const timerStartTime = Date.now()
|
|
289
216
|
|
|
290
217
|
try {
|
|
291
|
-
// Validate timer can run
|
|
292
218
|
if (!timer.pipeline_id) {
|
|
293
219
|
throw new Error(`Timer ${timer.timer_id} has no pipeline_id`)
|
|
294
220
|
}
|
|
295
221
|
|
|
296
|
-
// Create execution context for timer
|
|
297
222
|
const timerCtx: RequestContext = {
|
|
298
223
|
requestId: ctx.requestId,
|
|
299
224
|
principal: {
|
|
@@ -317,14 +242,12 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
317
242
|
query: {}
|
|
318
243
|
}
|
|
319
244
|
|
|
320
|
-
// Run the pipeline
|
|
321
245
|
const result = await runPipeline(timer.pipeline_id, {
|
|
322
246
|
timer_id: timer.timer_id,
|
|
323
247
|
timer_name: timer.name,
|
|
324
248
|
execution_count: timer.execution_count || 0
|
|
325
249
|
}, timerCtx)
|
|
326
250
|
|
|
327
|
-
// Update timer state
|
|
328
251
|
await adminDb.rpc('update_timer_after_run', {
|
|
329
252
|
p_timer_id: timer.timer_id,
|
|
330
253
|
p_success: result.status === 'completed',
|
|
@@ -340,7 +263,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
340
263
|
})
|
|
341
264
|
|
|
342
265
|
} catch (timerError: any) {
|
|
343
|
-
// Update timer with failure
|
|
344
266
|
await adminDb.rpc('update_timer_after_run', {
|
|
345
267
|
p_timer_id: timer.timer_id,
|
|
346
268
|
p_success: false,
|
|
@@ -361,9 +283,6 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
361
283
|
console.error('Timer execution error:', timerLoopError)
|
|
362
284
|
}
|
|
363
285
|
|
|
364
|
-
// ============================================
|
|
365
|
-
// Evaluate threshold alerts (every minute)
|
|
366
|
-
// ============================================
|
|
367
286
|
let thresholdResults: any[] = []
|
|
368
287
|
try {
|
|
369
288
|
thresholdResults = await evaluateThresholds(ctx)
|
|
@@ -377,15 +296,11 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
377
296
|
console.error('Threshold evaluation error:', thresholdError)
|
|
378
297
|
}
|
|
379
298
|
|
|
380
|
-
// ============================================
|
|
381
|
-
// Daily log cleanup (check if it's time)
|
|
382
|
-
// ============================================
|
|
383
299
|
let logsCleaned = 0
|
|
384
300
|
const now = new Date()
|
|
385
301
|
const currentHour = now.getUTCHours()
|
|
386
302
|
const currentMinute = now.getUTCMinutes()
|
|
387
303
|
|
|
388
|
-
// Run cleanup once per day at 00:00 UTC
|
|
389
304
|
if (currentHour === 0 && currentMinute === 0) {
|
|
390
305
|
try {
|
|
391
306
|
logsCleaned = await cleanupOldLogs()
|
|
@@ -394,10 +309,11 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
394
309
|
}
|
|
395
310
|
}
|
|
396
311
|
|
|
397
|
-
// Return summary
|
|
398
312
|
const successCount = results.filter(r => r.status === 'success').length
|
|
399
313
|
const failedCount = results.filter(r => r.status === 'failed').length
|
|
400
314
|
const skippedCount = results.filter(r => r.status === 'skipped').length
|
|
315
|
+
|
|
316
|
+
const retrySummary = await retryPendingDeliveries(ctx)
|
|
401
317
|
|
|
402
318
|
return {
|
|
403
319
|
statusCode: 200,
|
|
@@ -410,6 +326,7 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
410
326
|
thresholds_evaluated: thresholdResults.length,
|
|
411
327
|
thresholds_breached: thresholdResults.filter(r => r.breached).length,
|
|
412
328
|
logs_cleaned: logsCleaned,
|
|
329
|
+
deliveries_retried: retrySummary,
|
|
413
330
|
results
|
|
414
331
|
})
|
|
415
332
|
}
|
|
@@ -434,17 +351,21 @@ export const handler = createHandler(async (ctx: RequestContext) => {
|
|
|
434
351
|
}
|
|
435
352
|
}
|
|
436
353
|
})
|
|
437
|
-
|
|
438
|
-
//
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
354
|
+
// CIL[END chunk_id="system-cron_module_header_1783932909"]
|
|
355
|
+
// CIL[BEGIN chunk_id="system-cron_executeaction_1783932909" type="function" identity="executeAction" parent="none"]
|
|
356
|
+
// CIL[DOC-MACRO purpose="Dispatches actions to appropriate handler modules"]
|
|
357
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Route action execution by handler module"]
|
|
358
|
+
// CIL[DOC-CONTEXT module="system-cron" layer="api-handler" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
|
|
359
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Action execution result" errors="Throws on unknown modules" side_effects="Delegates to handlers"]
|
|
360
|
+
// CIL[DOC-MICRO logic_summary="Routes to function/integration/custom handlers" notable_decisions="[]"]
|
|
361
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
362
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
363
|
+
// CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 1. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/src/components/ui/table-primitives.tsx, \."]
|
|
364
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
|
|
365
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
366
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
367
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
368
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
448
369
|
async function executeAction(
|
|
449
370
|
ctx: RequestContext,
|
|
450
371
|
action: any,
|
|
@@ -453,7 +374,6 @@ async function executeAction(
|
|
|
453
374
|
const handlerModule = action.handler_module || 'functions'
|
|
454
375
|
const handlerName = action.handler
|
|
455
376
|
|
|
456
|
-
// Merge action config with schedule-specific config
|
|
457
377
|
const mergedConfig = {
|
|
458
378
|
...action.config,
|
|
459
379
|
...config
|
|
@@ -467,49 +387,49 @@ async function executeAction(
|
|
|
467
387
|
return await executeIntegrationHandler(ctx, handlerName, mergedConfig)
|
|
468
388
|
|
|
469
389
|
case 'custom':
|
|
470
|
-
// Custom handlers would be loaded from v2-custom
|
|
471
390
|
throw new Error(`Custom handlers not yet implemented: ${handlerName}`)
|
|
472
391
|
|
|
473
392
|
default:
|
|
474
393
|
throw new Error(`Unknown handler module: ${handlerModule}`)
|
|
475
394
|
}
|
|
476
395
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
396
|
+
// CIL[END chunk_id="system-cron_executeaction_1783932909"]
|
|
397
|
+
// CIL[BEGIN chunk_id="system-cron_executefunctionhandler_1783932909" type="function" identity="executeFunctionHandler" parent="none"]
|
|
398
|
+
// CIL[DOC-MACRO purpose="Routes to built-in function handlers"]
|
|
399
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute built-in named functions"]
|
|
400
|
+
// CIL[DOC-CONTEXT module="system-cron" layer="api-handler" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/db.ts\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
401
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Handler execution result" errors="Throws on unknown handlers" side_effects="Function execution"]
|
|
402
|
+
// CIL[DOC-MICRO logic_summary="Maps handler names to implementations" notable_decisions="[]"]
|
|
403
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
404
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
405
|
+
// CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 1. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, .framework/functions/_shared/principal.ts, .framework/functions/_shared/db.ts, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
406
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 2."]
|
|
407
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
408
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
409
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
410
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
486
411
|
async function executeFunctionHandler(
|
|
487
412
|
ctx: RequestContext,
|
|
488
413
|
handlerName: string,
|
|
489
414
|
config: any
|
|
490
415
|
): Promise<any> {
|
|
491
|
-
// Built-in handlers
|
|
492
416
|
const handlers: Record<string, Function> = {
|
|
493
417
|
'send_email': async (ctx: RequestContext, config: any) => {
|
|
494
|
-
// Implementation would integrate with email service
|
|
495
418
|
console.log(`[${ctx.requestId}] Sending email:`, config)
|
|
496
419
|
return { sent: true, recipients: config.recipients }
|
|
497
420
|
},
|
|
498
421
|
|
|
499
422
|
'generate_report': async (ctx: RequestContext, config: any) => {
|
|
500
|
-
// Implementation would generate and deliver report
|
|
501
423
|
console.log(`[${ctx.requestId}] Generating report:`, config)
|
|
502
424
|
return { generated: true, format: config.output_format }
|
|
503
425
|
},
|
|
504
426
|
|
|
505
427
|
'notify_watchers': async (ctx: RequestContext, config: any) => {
|
|
506
|
-
// Implementation would notify item watchers
|
|
507
428
|
console.log(`[${ctx.requestId}] Notifying watchers:`, config)
|
|
508
429
|
return { notified: true }
|
|
509
430
|
},
|
|
510
431
|
|
|
511
432
|
'run_pipeline': async (ctx: RequestContext, config: any) => {
|
|
512
|
-
// Execute a pipeline as part of scheduled action
|
|
513
433
|
const { pipeline_id, trigger_data = {} } = config
|
|
514
434
|
|
|
515
435
|
if (!pipeline_id) {
|
|
@@ -533,49 +453,55 @@ async function executeFunctionHandler(
|
|
|
533
453
|
|
|
534
454
|
return await handler(ctx, config)
|
|
535
455
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
456
|
+
// CIL[END chunk_id="system-cron_executefunctionhandler_1783932909"]
|
|
457
|
+
// CIL[BEGIN chunk_id="system-cron_executeintegrationhandler_1783932909" type="function" identity="executeIntegrationHandler" parent="none"]
|
|
458
|
+
// CIL[DOC-MACRO purpose="Placeholder for integration-based action handlers"]
|
|
459
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Handle external service integration calls"]
|
|
460
|
+
// CIL[DOC-CONTEXT module="system-cron" layer="api-handler" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
|
|
461
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="{executed: true}" errors="None" side_effects="Logging"]
|
|
462
|
+
// CIL[DOC-MICRO logic_summary="Placeholder for future integration implementations" notable_decisions="[]"]
|
|
463
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
464
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
465
|
+
// CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 1. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx, \."]
|
|
466
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 2."]
|
|
467
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
468
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
469
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
470
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
541
471
|
async function executeIntegrationHandler(
|
|
542
472
|
ctx: RequestContext,
|
|
543
473
|
handlerName: string,
|
|
544
474
|
config: any
|
|
545
475
|
): Promise<any> {
|
|
546
|
-
// Integration handlers would call external services
|
|
547
|
-
// This is a placeholder for future implementation
|
|
548
476
|
console.log(`[${ctx.requestId}] Integration handler: ${handlerName}`, config)
|
|
549
477
|
return { executed: true, handler: handlerName }
|
|
550
478
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
async function evaluateThresholds(ctx: RequestContext): Promise<Array<{
|
|
567
|
-
const results: Array<{
|
|
479
|
+
// CIL[END chunk_id="system-cron_executeintegrationhandler_1783932909"]
|
|
480
|
+
// CIL[BEGIN chunk_id="system-cron_evaluatethresholds_1783932909" type="function" identity="evaluateThresholds" parent="none"]
|
|
481
|
+
// CIL[DOC-MACRO purpose="Evaluates threshold alerts and fires pipelines"]
|
|
482
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Monitor metrics and trigger automated responses"]
|
|
483
|
+
// CIL[DOC-CONTEXT module="system-cron" layer="api-handler" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
|
|
484
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Array of threshold evaluation results" errors="Returns empty array on errors" side_effects="Pipeline execution, audit logging"]
|
|
485
|
+
// CIL[DOC-MICRO logic_summary="Queries metrics, checks thresholds, triggers pipelines" notable_decisions="[]"]
|
|
486
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="complex_dependencies"]
|
|
487
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
488
|
+
// CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 1. 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/pages/admin/RolesPage.tsx, .framework/functions/_shared/principal.ts, \."]
|
|
489
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
|
|
490
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
491
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
492
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
493
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
494
|
+
async function evaluateThresholds(ctx: RequestContext): Promise<Array<{thresholdId: string, breached: boolean, fired: boolean}>> {
|
|
495
|
+
const results: Array<{thresholdId: string, breached: boolean, fired: boolean}> = []
|
|
568
496
|
|
|
569
497
|
try {
|
|
570
|
-
// Load all active threshold alerts from items table
|
|
571
498
|
const { data: thresholds, error } = await adminDb
|
|
572
|
-
.from('
|
|
499
|
+
.from('threshold_alerts')
|
|
573
500
|
.select('*')
|
|
574
|
-
.eq('
|
|
575
|
-
.eq('data->>is_active', 'true')
|
|
501
|
+
.eq('is_active', true)
|
|
576
502
|
|
|
577
503
|
if (error) {
|
|
578
|
-
console.error('Failed to
|
|
504
|
+
console.error('Failed to fetch thresholds:', error)
|
|
579
505
|
return results
|
|
580
506
|
}
|
|
581
507
|
|
|
@@ -583,75 +509,56 @@ async function evaluateThresholds(ctx: RequestContext): Promise<Array<{ threshol
|
|
|
583
509
|
return results
|
|
584
510
|
}
|
|
585
511
|
|
|
586
|
-
|
|
512
|
+
const now = new Date()
|
|
513
|
+
|
|
587
514
|
for (const threshold of thresholds) {
|
|
588
515
|
try {
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (!metric || !operator || value === undefined || !window_minutes) {
|
|
593
|
-
console.warn(`Threshold ${threshold.id} missing required fields`)
|
|
594
|
-
continue
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// Calculate time window
|
|
598
|
-
const now = new Date()
|
|
599
|
-
const from = new Date(now.getTime() - window_minutes * 60 * 1000)
|
|
600
|
-
|
|
516
|
+
const { metric, operator, value, window_minutes, pipeline_id } = threshold
|
|
517
|
+
let actualValue: number
|
|
601
518
|
let breached = false
|
|
602
|
-
let actualValue: number = 0
|
|
603
519
|
|
|
604
|
-
// Query appropriate RPC based on metric
|
|
605
520
|
switch (metric) {
|
|
606
|
-
case 'error_rate':
|
|
607
|
-
const { data } = await adminDb.rpc('get_error_rate', {
|
|
608
|
-
|
|
609
|
-
p_from: from.toISOString(),
|
|
610
|
-
p_to: now.toISOString()
|
|
521
|
+
case 'error_rate':
|
|
522
|
+
const { data: errorRateData } = await adminDb.rpc('get_error_rate', {
|
|
523
|
+
p_window_minutes: window_minutes
|
|
611
524
|
})
|
|
612
|
-
|
|
613
|
-
|
|
525
|
+
|
|
526
|
+
if (errorRateData && errorRateData.length > 0) {
|
|
527
|
+
actualValue = errorRateData[0].error_rate || 0
|
|
614
528
|
breached = operator === 'gt' ? actualValue > value : actualValue < value
|
|
615
529
|
}
|
|
616
530
|
break
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
p_account_id: threshold.account_id,
|
|
622
|
-
p_from: from.toISOString(),
|
|
623
|
-
p_to: now.toISOString()
|
|
531
|
+
|
|
532
|
+
case 'latency_p95':
|
|
533
|
+
const { data: latencyData } = await adminDb.rpc('get_latency_percentiles', {
|
|
534
|
+
p_window_minutes: window_minutes
|
|
624
535
|
})
|
|
625
|
-
|
|
626
|
-
|
|
536
|
+
|
|
537
|
+
if (latencyData && latencyData.length > 0) {
|
|
538
|
+
actualValue = latencyData[0].p95 || 0
|
|
627
539
|
breached = operator === 'gt' ? actualValue > value : actualValue < value
|
|
628
540
|
}
|
|
629
541
|
break
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
p_account_id: threshold.account_id,
|
|
635
|
-
p_from: from.toISOString(),
|
|
636
|
-
p_to: now.toISOString()
|
|
542
|
+
|
|
543
|
+
case 'pipeline_failure_rate':
|
|
544
|
+
const { data: pipelineStats } = await adminDb.rpc('get_pipeline_stats', {
|
|
545
|
+
p_window_minutes: window_minutes
|
|
637
546
|
})
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
const totalSuccess =
|
|
641
|
-
const totalFailure =
|
|
547
|
+
|
|
548
|
+
if (pipelineStats && pipelineStats.length > 0) {
|
|
549
|
+
const totalSuccess = pipelineStats[0].total_success || 0
|
|
550
|
+
const totalFailure = pipelineStats[0].total_failure || 0
|
|
642
551
|
const total = totalSuccess + totalFailure
|
|
643
552
|
actualValue = total > 0 ? (totalFailure / total) * 100 : 0
|
|
644
553
|
breached = operator === 'gt' ? actualValue > value : actualValue < value
|
|
645
554
|
}
|
|
646
555
|
break
|
|
647
|
-
|
|
648
|
-
|
|
556
|
+
|
|
649
557
|
default:
|
|
650
558
|
console.warn(`Unknown metric: ${metric}`)
|
|
651
559
|
continue
|
|
652
560
|
}
|
|
653
561
|
|
|
654
|
-
// Fire pipeline if breached and pipeline_id configured
|
|
655
562
|
let fired = false
|
|
656
563
|
if (breached && pipeline_id) {
|
|
657
564
|
try {
|
|
@@ -663,13 +570,13 @@ async function evaluateThresholds(ctx: RequestContext): Promise<Array<{ threshol
|
|
|
663
570
|
window_minutes,
|
|
664
571
|
triggered_at: now.toISOString()
|
|
665
572
|
}, ctx)
|
|
573
|
+
|
|
666
574
|
fired = true
|
|
667
575
|
} catch (pipelineError: any) {
|
|
668
576
|
console.error(`Failed to fire threshold pipeline ${pipeline_id}:`, pipelineError)
|
|
669
577
|
}
|
|
670
578
|
}
|
|
671
579
|
|
|
672
|
-
// Log threshold event if breached
|
|
673
580
|
if (breached) {
|
|
674
581
|
await emitAudit(ctx, 'threshold.breached', {
|
|
675
582
|
type: 'threshold_alert',
|
|
@@ -709,15 +616,21 @@ async function evaluateThresholds(ctx: RequestContext): Promise<Array<{ threshol
|
|
|
709
616
|
return results
|
|
710
617
|
}
|
|
711
618
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
619
|
+
// CIL[END chunk_id="system-cron_evaluatethresholds_1783932909"]
|
|
620
|
+
// CIL[BEGIN chunk_id="system-cron_cleanupoldlogs_1783932909" type="function" identity="cleanupOldLogs" parent="none"]
|
|
621
|
+
// CIL[DOC-MACRO purpose="Cleans up old log records beyond retention period"]
|
|
622
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Maintain log storage within retention limits"]
|
|
623
|
+
// CIL[DOC-CONTEXT module="system-cron" layer="api-handler" related_files="[]"]
|
|
624
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Number of deleted records" errors="Returns 0 on errors" side_effects="Database cleanup"]
|
|
625
|
+
// CIL[DOC-MICRO logic_summary="Calls cleanup RPC with 90-day retention" notable_decisions="[]"]
|
|
626
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
627
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
628
|
+
// CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
629
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
630
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
631
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
632
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
633
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
721
634
|
async function cleanupOldLogs(): Promise<number> {
|
|
722
635
|
try {
|
|
723
636
|
const { data, error } = await adminDb.rpc('cleanup_old_logs', {
|
|
@@ -740,3 +653,4 @@ async function cleanupOldLogs(): Promise<number> {
|
|
|
740
653
|
return 0
|
|
741
654
|
}
|
|
742
655
|
}
|
|
656
|
+
// CIL[END chunk_id="system-cron_cleanupoldlogs_1783932909"]
|