spine-framework 0.3.145 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/.env.example +76 -0
  2. package/.framework/.spine-manifest.json +19 -0
  3. package/.framework/cli/commands/agents.ts +61 -33
  4. package/.framework/cli/commands/auth.ts +60 -28
  5. package/.framework/cli/commands/create-app.ts +212 -80
  6. package/.framework/cli/commands/dev.ts +184 -68
  7. package/.framework/cli/commands/doctor.ts +324 -152
  8. package/.framework/cli/commands/generate.ts +119 -68
  9. package/.framework/cli/commands/init.ts +141 -242
  10. package/.framework/cli/commands/install-app.ts +1336 -314
  11. package/.framework/cli/commands/items.ts +31 -29
  12. package/.framework/cli/commands/migrate.ts +299 -156
  13. package/.framework/cli/commands/migrations.ts +62 -30
  14. package/.framework/cli/commands/pipelines.ts +31 -29
  15. package/.framework/cli/commands/status.ts +105 -45
  16. package/.framework/cli/commands/system.ts +47 -42
  17. package/.framework/cli/commands/test.ts +161 -102
  18. package/.framework/cli/commands/upgrade.ts +260 -0
  19. package/.framework/cli/commands/validate-app.ts +517 -161
  20. package/.framework/cli/context.ts +117 -85
  21. package/.framework/cli/env-loader.ts +74 -43
  22. package/.framework/cli/index.ts +70 -46
  23. package/.framework/cli/lib/project-files.ts +404 -0
  24. package/.framework/docs/guides/testing-guide.md +1 -1
  25. package/.framework/docs/runtime-types.md +72 -72
  26. package/.framework/functions/_shared/access.ts +84 -0
  27. package/.framework/functions/_shared/agent-runner.ts +5051 -1026
  28. package/.framework/functions/_shared/app-manifest.ts +214 -94
  29. package/.framework/functions/_shared/ast.ts +214 -0
  30. package/.framework/functions/_shared/audit.ts +91 -55
  31. package/.framework/functions/_shared/cil.ts +368 -127
  32. package/.framework/functions/_shared/db.ts +337 -68
  33. package/.framework/functions/_shared/funnel.ts +228 -0
  34. package/.framework/functions/_shared/geo.ts +105 -0
  35. package/.framework/functions/_shared/hash-api-key.ts +94 -17
  36. package/.framework/functions/_shared/index.ts +22 -224
  37. package/.framework/functions/_shared/kb.ts +832 -58
  38. package/.framework/functions/_shared/llm.ts +118 -18
  39. package/.framework/functions/_shared/logging.ts +317 -19
  40. package/.framework/functions/_shared/middleware.ts +701 -131
  41. package/.framework/functions/_shared/notify.ts +70 -0
  42. package/.framework/functions/_shared/outcomes.ts +34 -19
  43. package/.framework/functions/_shared/permissions.ts +501 -315
  44. package/.framework/functions/_shared/pipeline-runner.ts +704 -155
  45. package/.framework/functions/_shared/principal.ts +436 -263
  46. package/.framework/functions/_shared/rate-limit.ts +233 -0
  47. package/.framework/functions/_shared/resolve-credentials.ts +86 -19
  48. package/.framework/functions/_shared/resolve-ids.ts +203 -139
  49. package/.framework/functions/_shared/retry-deliveries.ts +51 -16
  50. package/.framework/functions/_shared/schema-utils.ts +602 -521
  51. package/.framework/functions/_shared/security.ts +345 -0
  52. package/.framework/functions/_shared/testing.ts +197 -172
  53. package/.framework/functions/_shared/tracing.ts +351 -21
  54. package/.framework/functions/_shared/trigger-engine.ts +425 -136
  55. package/.framework/functions/_shared/webhook-registration.ts +71 -70
  56. package/.framework/functions/_shared/webhook-registry.ts +126 -83
  57. package/.framework/functions/account-nodes.ts +30 -30
  58. package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
  59. package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
  60. package/.framework/functions/adapters/openai-outbound.ts +15 -16
  61. package/.framework/functions/admin-data.ts +596 -173
  62. package/.framework/functions/admin-funnel.ts +64 -60
  63. package/.framework/functions/admin-install-funnel.ts +84 -66
  64. package/.framework/functions/admin-signals.ts +69 -51
  65. package/.framework/functions/ai-agents.ts +431 -106
  66. package/.framework/functions/ai-interactions.ts +186 -112
  67. package/.framework/functions/api-keys.ts +107 -107
  68. package/.framework/functions/apps.ts +154 -136
  69. package/.framework/functions/auth.ts +83 -65
  70. package/.framework/functions/cil-agent-ingest.ts +189 -232
  71. package/.framework/functions/cil-agent.ts +433 -177
  72. package/.framework/functions/cil-callmap.ts +642 -430
  73. package/.framework/functions/cil-config.ts +139 -135
  74. package/.framework/functions/cil-context.ts +214 -127
  75. package/.framework/functions/cil-doc.ts +587 -458
  76. package/.framework/functions/cil-embeddings.ts +453 -364
  77. package/.framework/functions/cil-graph.ts +427 -142
  78. package/.framework/functions/cil-ingest.ts +1418 -1154
  79. package/.framework/functions/cil-pipeline.ts +276 -21
  80. package/.framework/functions/cil-project.ts +659 -132
  81. package/.framework/functions/cil-validate.ts +198 -164
  82. package/.framework/functions/debug-auth.ts +57 -55
  83. package/.framework/functions/deliveries.ts +80 -21
  84. package/.framework/functions/embeddings.ts +1023 -318
  85. package/.framework/functions/eval-harness.ts +146 -108
  86. package/.framework/functions/integration-outbound.ts +205 -75
  87. package/.framework/functions/integration-routes.ts +128 -23
  88. package/.framework/functions/integrations.ts +125 -100
  89. package/.framework/functions/invites.ts +1095 -460
  90. package/.framework/functions/item-progress.ts +158 -102
  91. package/.framework/functions/kb.ts +34 -10
  92. package/.framework/functions/logs.ts +133 -133
  93. package/.framework/functions/observability.ts +152 -122
  94. package/.framework/functions/pipeline-executions.ts +147 -132
  95. package/.framework/functions/pipelines.ts +134 -119
  96. package/.framework/functions/prompt-configs.ts +96 -80
  97. package/.framework/functions/roles.ts +112 -82
  98. package/.framework/functions/security.ts +450 -0
  99. package/.framework/functions/system-cron.ts +117 -80
  100. package/.framework/functions/system.ts +158 -98
  101. package/.framework/functions/tests.ts +29 -29
  102. package/.framework/functions/timers.ts +94 -95
  103. package/.framework/functions/trigger-scheduler.ts +10 -0
  104. package/.framework/functions/triggers.ts +179 -149
  105. package/.framework/functions/types.ts +137 -125
  106. package/.framework/mcp/index.ts +133 -0
  107. package/.framework/mcp/load-env.ts +60 -0
  108. package/.framework/mcp/shared/app-manifest.ts +275 -0
  109. package/.framework/mcp/shared/db.ts +477 -0
  110. package/.framework/mcp/shared/kb.ts +118 -0
  111. package/.framework/mcp/tools/architect.ts +431 -0
  112. package/.framework/mcp/tools/cil/context.ts +345 -0
  113. package/.framework/mcp/tools/cil/graph.ts +242 -0
  114. package/.framework/mcp/tools/cil/ingest.ts +1217 -0
  115. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
  116. package/.framework/mcp/tools/cil/pipeline.ts +767 -0
  117. package/.framework/mcp/tools/cil/project.ts +791 -0
  118. package/.framework/mcp/tools/cil/retrieval.ts +336 -0
  119. package/.framework/mcp/tools/cil/search-core.ts +454 -0
  120. package/.framework/mcp/tools/cil/search.ts +97 -0
  121. package/.framework/mcp/tools/cil/suggest.ts +186 -0
  122. package/.framework/mcp/tools/cil/validate.ts +1369 -0
  123. package/.framework/mcp/tools/kb/delete.ts +139 -0
  124. package/.framework/mcp/tools/kb/index.ts +52 -0
  125. package/.framework/mcp/tools/kb/ingest.ts +84 -0
  126. package/.framework/mcp/tools/kb/list-types.ts +102 -0
  127. package/.framework/mcp/tools/kb/publish.ts +100 -0
  128. package/.framework/mcp/tools/kb/reindex.ts +86 -0
  129. package/.framework/mcp/tools/kb/revoke.ts +85 -0
  130. package/.framework/mcp/tools/kb/search.ts +101 -0
  131. package/.framework/mcp/tools/kb/upsert.ts +125 -0
  132. package/.framework/mcp/tools/observability.ts +510 -0
  133. package/.framework/migrations/001_core_schema.sql +15 -0
  134. package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
  135. package/.framework/migrations/003_core_system_data.sql +16 -1
  136. package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
  137. package/.framework/migrations/005_core_observability.sql +17 -1
  138. package/.framework/migrations/006_security_hardening_rls.sql +15 -0
  139. package/.framework/migrations/007_kb_article_list.sql +17 -1
  140. package/.framework/migrations/008_items_target.sql +15 -0
  141. package/.framework/migrations/009_roles_slug_unique.sql +15 -0
  142. package/.framework/migrations/010_auth_user_trigger.sql +15 -0
  143. package/.framework/migrations/011_spine_system_account.sql +16 -0
  144. package/.framework/migrations/012_service_role_grants.sql +16 -0
  145. package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
  146. package/.framework/migrations/014_apps_required_roles.sql +16 -0
  147. package/.framework/migrations/015_types_kind_slug_unique.sql +15 -0
  148. package/.framework/migrations/016_cil_types.sql +281 -0
  149. package/.framework/migrations/017_cil_stable_ids.sql +37 -0
  150. package/.framework/migrations/018_runtime_tables.sql +129 -0
  151. package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
  152. package/.framework/migrations/020_schema_reconciliation.sql +67 -0
  153. package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
  154. package/.framework/migrations/032_cil_status_migration.sql +73 -0
  155. package/.framework/migrations/033_cil_versioning.sql +73 -0
  156. package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
  157. package/.framework/migrations/035_rate_limits.sql +55 -0
  158. package/.framework/migrations/036_demo_record_flags.sql +72 -0
  159. package/.framework/migrations/037_kb_types_canonical.sql +244 -0
  160. package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
  161. package/.framework/migrations/042_registration_hierarchy.sql +309 -0
  162. package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
  163. package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
  164. package/.framework/migrations/045_security_critical_rls.sql +139 -0
  165. package/.framework/migrations/046_security_missing_rls.sql +79 -0
  166. package/.framework/migrations/047_people_updated_by.sql +27 -0
  167. package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
  168. package/.framework/migrations/049_security_blocklist.sql +148 -0
  169. package/.framework/migrations/050_notifications.sql +49 -0
  170. package/.framework/migrations/051_message_agent_fields.sql +74 -0
  171. package/.framework/migrations/052_registration_security.sql +421 -0
  172. package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
  173. package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
  174. package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
  175. package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
  176. package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
  177. package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
  178. package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
  179. package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
  180. package/.framework/migrations/061_fk_dedup.sql +32 -0
  181. package/.framework/public/spine-logo.svg +10 -3
  182. package/.framework/scripts/app-install-cli.ts +190 -93
  183. package/.framework/scripts/assemble-frontend.sh +127 -44
  184. package/.framework/scripts/assemble-functions.sh +128 -30
  185. package/.framework/scripts/boundary-check.sh +6 -2
  186. package/.framework/scripts/build-manifest.sh +24 -68
  187. package/.framework/scripts/check-core-integrity.sh +15 -76
  188. package/.framework/scripts/checksum-manifest.mts +343 -0
  189. package/.framework/scripts/cil-migrate-markers.ts +403 -0
  190. package/.framework/scripts/fix-cil-markers.mjs +176 -0
  191. package/.framework/scripts/verify-integrity.sh +21 -57
  192. package/.framework/scripts/verify-manifest.mts +305 -0
  193. package/.framework/seeds/types/funnel_signal_use.json +74 -21
  194. package/.framework/seeds/types/spine_instance.json +73 -21
  195. package/.framework/src/App.tsx +118 -72
  196. package/.framework/src/apps/admin/index.tsx +855 -58
  197. package/.framework/src/components/AppWrapper.tsx +43 -45
  198. package/.framework/src/components/CustomAppLoader.tsx +160 -116
  199. package/.framework/src/components/admin/AdminListPage.tsx +46 -44
  200. package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
  201. package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
  202. package/.framework/src/components/admin/PageInstructions.tsx +98 -2
  203. package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
  204. package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
  205. package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
  206. package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
  207. package/.framework/src/components/app-sidebar.tsx +42 -45
  208. package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
  209. package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
  210. package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
  211. package/.framework/src/components/kb/KBArticleList.tsx +251 -10
  212. package/.framework/src/components/layout/AppShell.tsx +51 -45
  213. package/.framework/src/components/layout/Header.tsx +42 -43
  214. package/.framework/src/components/layout/Layout.tsx +46 -46
  215. package/.framework/src/components/layout/Sidebar.tsx +196 -96
  216. package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
  217. package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
  218. package/.framework/src/components/runtime/DataFilters.tsx +49 -74
  219. package/.framework/src/components/runtime/DataHeader.tsx +53 -32
  220. package/.framework/src/components/runtime/DataListPage.tsx +51 -155
  221. package/.framework/src/components/runtime/DataStats.tsx +66 -44
  222. package/.framework/src/components/runtime/DataTable.tsx +49 -149
  223. package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
  224. package/.framework/src/components/runtime/index.ts +119 -16
  225. package/.framework/src/components/search-form.tsx +46 -29
  226. package/.framework/src/components/shared/AgentView.tsx +65 -48
  227. package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
  228. package/.framework/src/components/shared/InviteManager.tsx +207 -97
  229. package/.framework/src/components/shared/MemberList.tsx +97 -0
  230. package/.framework/src/components/shared/SchemaFields.tsx +107 -86
  231. package/.framework/src/components/ui/DataTable.tsx +80 -68
  232. package/.framework/src/components/ui/Form.tsx +157 -146
  233. package/.framework/src/components/ui/ItemCard.tsx +74 -67
  234. package/.framework/src/components/ui/ItemListView.tsx +73 -68
  235. package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
  236. package/.framework/src/components/ui/Modal.tsx +78 -68
  237. package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
  238. package/.framework/src/components/ui/accordion.tsx +85 -86
  239. package/.framework/src/components/ui/alert-dialog.tsx +197 -184
  240. package/.framework/src/components/ui/alert.tsx +105 -94
  241. package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
  242. package/.framework/src/components/ui/avatar.tsx +122 -107
  243. package/.framework/src/components/ui/badge.tsx +60 -55
  244. package/.framework/src/components/ui/breadcrumb.tsx +127 -128
  245. package/.framework/src/components/ui/button-group.tsx +86 -72
  246. package/.framework/src/components/ui/button.tsx +71 -50
  247. package/.framework/src/components/ui/calendar.tsx +72 -57
  248. package/.framework/src/components/ui/card.tsx +136 -129
  249. package/.framework/src/components/ui/carousel.tsx +226 -107
  250. package/.framework/src/components/ui/chart.tsx +252 -147
  251. package/.framework/src/components/ui/checkbox.tsx +43 -44
  252. package/.framework/src/components/ui/collapsible.tsx +86 -71
  253. package/.framework/src/components/ui/combobox.tsx +282 -249
  254. package/.framework/src/components/ui/command.tsx +158 -146
  255. package/.framework/src/components/ui/context-menu.tsx +239 -240
  256. package/.framework/src/components/ui/dialog.tsx +174 -157
  257. package/.framework/src/components/ui/direction.tsx +72 -56
  258. package/.framework/src/components/ui/drawer.tsx +168 -169
  259. package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
  260. package/.framework/src/components/ui/empty.tsx +131 -120
  261. package/.framework/src/components/ui/field.tsx +205 -173
  262. package/.framework/src/components/ui/hover-card.tsx +71 -72
  263. package/.framework/src/components/ui/input-group.tsx +148 -133
  264. package/.framework/src/components/ui/input-otp.tsx +99 -86
  265. package/.framework/src/components/ui/input.tsx +43 -41
  266. package/.framework/src/components/ui/item.tsx +207 -185
  267. package/.framework/src/components/ui/kbd.tsx +57 -56
  268. package/.framework/src/components/ui/label.tsx +45 -41
  269. package/.framework/src/components/ui/menubar.tsx +268 -236
  270. package/.framework/src/components/ui/native-select.tsx +85 -86
  271. package/.framework/src/components/ui/navigation-menu.tsx +166 -156
  272. package/.framework/src/components/ui/pagination.tsx +131 -141
  273. package/.framework/src/components/ui/popover.tsx +125 -128
  274. package/.framework/src/components/ui/progress.tsx +47 -44
  275. package/.framework/src/components/ui/radio-group.tsx +60 -55
  276. package/.framework/src/components/ui/resizable.tsx +85 -72
  277. package/.framework/src/components/ui/scroll-area.tsx +57 -58
  278. package/.framework/src/components/ui/select.tsx +182 -169
  279. package/.framework/src/components/ui/separator.tsx +42 -43
  280. package/.framework/src/components/ui/sheet.tsx +170 -159
  281. package/.framework/src/components/ui/sidebar.tsx +395 -398
  282. package/.framework/src/components/ui/skeleton.tsx +42 -43
  283. package/.framework/src/components/ui/slider.tsx +61 -44
  284. package/.framework/src/components/ui/sonner.tsx +44 -44
  285. package/.framework/src/components/ui/spinner.tsx +47 -42
  286. package/.framework/src/components/ui/switch.tsx +56 -42
  287. package/.framework/src/components/ui/table-primitives.tsx +272 -132
  288. package/.framework/src/components/ui/table.tsx +140 -142
  289. package/.framework/src/components/ui/tabs.tsx +110 -93
  290. package/.framework/src/components/ui/textarea.tsx +43 -44
  291. package/.framework/src/components/ui/toggle-group.tsx +87 -71
  292. package/.framework/src/components/ui/toggle.tsx +56 -56
  293. package/.framework/src/components/ui/tooltip.tsx +99 -85
  294. package/.framework/src/contexts/AppContext.tsx +166 -114
  295. package/.framework/src/contexts/AuthContext.tsx +232 -137
  296. package/.framework/src/hooks/use-mobile.ts +43 -44
  297. package/.framework/src/hooks/useApi.ts +185 -172
  298. package/.framework/src/hooks/useAppPath.ts +31 -29
  299. package/.framework/src/hooks/useApps.ts +77 -42
  300. package/.framework/src/hooks/useEntityList.ts +66 -29
  301. package/.framework/src/hooks/useEntityRecord.ts +76 -32
  302. package/.framework/src/hooks/useForm.ts +62 -30
  303. package/.framework/src/hooks/useListSchema.ts +60 -43
  304. package/.framework/src/hooks/useSchemaRecord.ts +115 -95
  305. package/.framework/src/lib/api.ts +258 -134
  306. package/.framework/src/lib/registration.ts +181 -0
  307. package/.framework/src/lib/supabase.ts +118 -81
  308. package/.framework/src/lib/utils.ts +266 -266
  309. package/.framework/src/main.tsx +43 -44
  310. package/.framework/src/pages/DashboardPage.tsx +44 -43
  311. package/.framework/src/pages/NoAppPage.tsx +50 -0
  312. package/.framework/src/pages/NotFoundPage.tsx +32 -29
  313. package/.framework/src/pages/SetupPage.tsx +34 -33
  314. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
  315. package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
  316. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
  317. package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
  318. package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
  319. package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
  320. package/.framework/src/pages/admin/AppsPage.tsx +45 -42
  321. package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
  322. package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
  323. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
  324. package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
  325. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
  326. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
  327. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
  328. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
  329. package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
  330. package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
  331. package/.framework/src/pages/admin/LogsPage.tsx +87 -137
  332. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
  333. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
  334. package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
  335. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
  336. package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
  337. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
  338. package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
  339. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
  340. package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
  341. package/.framework/src/pages/admin/RolesPage.tsx +47 -164
  342. package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
  343. package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
  344. package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
  345. package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
  346. package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
  347. package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
  348. package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
  349. package/.framework/src/pages/admin/TimersPage.tsx +44 -42
  350. package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
  351. package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
  352. package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
  353. package/.framework/src/pages/admin/TypesPage.tsx +45 -42
  354. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
  355. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
  356. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
  357. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
  358. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
  359. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
  360. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
  361. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
  362. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
  363. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
  364. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
  365. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
  366. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  367. package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
  368. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
  369. package/.framework/src/pages/auth/LoginPage.tsx +38 -32
  370. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
  371. package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
  372. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
  373. package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
  374. package/.framework/src/types/auth.ts +101 -93
  375. package/.framework/src/types/types.ts +283 -262
  376. package/.framework/templates/project.json +87 -0
  377. package/.framework/templates/spine.config.neutral.json +7 -0
  378. package/.framework/tests/api/api-surface.test.ts +381 -0
  379. package/.framework/tests/fixtures/seed.ts +427 -0
  380. package/.framework/tests/fixtures/teardown.ts +228 -0
  381. package/.framework/tests/reporter.ts +351 -0
  382. package/.framework/tests/setup.ts +135 -0
  383. package/.framework/tests/ui/ui-sweep.ts +278 -0
  384. package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
  385. package/.framework/tests/unit/agent-runner.test.ts +2389 -0
  386. package/.framework/tests/unit/ai-interactions.test.ts +81 -0
  387. package/.framework/tests/unit/app-manifest.test.ts +359 -0
  388. package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
  389. package/.framework/tests/unit/cil-determinism.test.ts +85 -0
  390. package/.framework/tests/unit/core-isolation.test.ts +153 -0
  391. package/.framework/tests/unit/funnel-signals.test.ts +135 -0
  392. package/.framework/tests/unit/install-app.test.ts +1759 -0
  393. package/.framework/tests/unit/invites-security.test.ts +572 -0
  394. package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
  395. package/.framework/tests/unit/kb-search.test.ts +119 -0
  396. package/.framework/tests/unit/migrate.test.ts +509 -0
  397. package/.framework/tests/unit/notify.test.ts +136 -0
  398. package/.framework/tests/unit/permissions.test.ts +269 -0
  399. package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
  400. package/.framework/tests/unit/principal-cache.test.ts +138 -0
  401. package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
  402. package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
  403. package/.framework/tests/unit/schema-utils.test.ts +225 -0
  404. package/.framework/tests/unit/trigger-engine.test.ts +513 -0
  405. package/.framework/tests/unit/validate-app.test.ts +527 -0
  406. package/README.md +34 -3
  407. package/bin/spine-framework.cjs +1 -0
  408. package/config/tailwind.config.cjs +7 -0
  409. package/config/tsconfig.functions.json +42 -0
  410. package/config/tsconfig.json +37 -9
  411. package/config/vite.config.ts +31 -2
  412. package/netlify.toml +31 -3
  413. package/package.json +46 -29
  414. package/scripts/assemble-frontend.sh +127 -44
  415. package/scripts/assemble-functions.sh +127 -29
  416. package/scripts/boundary-check.sh +6 -2
  417. package/scripts/build-manifest.sh +24 -68
  418. package/scripts/checksum-manifest.mts +345 -0
  419. package/scripts/dev-clean.sh +86 -0
  420. package/scripts/dev-netlify.sh +49 -0
  421. package/scripts/netlify-dev-wrapper.sh +2 -0
  422. package/scripts/verify-install.ts +358 -0
  423. package/scripts/verify-integrity.sh +21 -57
  424. package/scripts/verify-manifest.mts +305 -0
  425. package/templates/project/gitignore +45 -0
  426. package/{config → templates/project}/package-lock.json +22335 -9366
  427. package/vitest.config.ts +46 -0
  428. package/.framework/public/spine.config.json +0 -91
  429. package/config/deno.lock +0 -108
  430. package/config/tsconfig.node.tsbuildinfo +0 -1
  431. package/config/tsconfig.tsbuildinfo +0 -1
  432. package/config/vite.config.d.ts +0 -2
  433. package/custom/.devin/AGENT.md +0 -357
  434. package/custom/.devin/skills/install-app/SKILL.md +0 -39
  435. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
  436. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
  437. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
  438. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
  439. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
  440. package/custom/.devin/workflows/app-install.yaml +0 -83
  441. package/custom/README.md +0 -79
  442. package/docs/README.md +0 -15
  443. package/scripts/app-install-cli.ts +0 -286
  444. package/scripts/check-core-integrity.sh +0 -82
  445. package/scripts/ingest-chunks.cjs +0 -202
  446. package/scripts/kb-chunk-parser.cjs +0 -312
  447. package/scripts/kb-chunk-parser.ts +0 -330
  448. package/scripts/kb-ingest-docs.ts +0 -203
  449. package/scripts/load-test-app-install.ts +0 -484
  450. package/scripts/test-login.js +0 -33
  451. package/spine.config.json +0 -91
@@ -1,18 +1,12 @@
1
- // CIL[BEGIN chunk_id="integration_outbound_module_header_1784200004" type="module_header" identity="imports" parent="none"]
2
- // CIL[DOC-MACRO purpose="Outbound integration broker action"]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Execute outbound HTTP calls through configured integrations and log deliveries"]
4
- // CIL[DOC-CONTEXT module="integration-outbound" layer="backend_functions" related_files="[".framework/functions/_shared/resolve-credentials.ts",".framework/functions/admin-data.ts",".framework/functions/_shared/audit.ts",".framework/functions/_shared/pipeline-runner.ts",".framework/migrations/051_integration_broker.sql"]"]
5
- // CIL[DOC-CONTRACT inputs="ctx, body with integration_slug and record_id" outputs="{ success, delivery_id, response_status }" errors="integration_not_found, credential_missing, adapter_error, http_error" side_effects="HTTP request, webhook_deliveries insert/update, optional admin-data update"]
6
- // CIL[DOC-MICRO logic_summary="Loads integration, resolves credential, loads adapter, builds request, performs HTTP call, and records the result in webhook_deliveries. Supports retry by delivery_id for internal callers." notable_decisions="["Outbound uses integrations.credentials, not api_keys (which are for inbound).","Failures are written to webhook_deliveries for retry by system-cron.","Record updates go through admin-data.","When delivery_id is passed by an internal principal, the existing delivery row is reused."]"]
7
- // CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
8
- // CIL[DOC-STABILITY stability="experimental"]
9
- // CIL[DOC-AUDIENCE audience="developer"]
10
- // CIL[DOC-VECTOR type="context" content="Layer: backend_functions. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/resolve-credentials.ts, .framework/functions/admin-data.ts, .framework/functions/_shared/audit.ts, .framework/functions/_shared/pipeline-runner.ts, .framework/migrations/051_integration_broker.sql."]
11
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
12
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
13
- // CIL[DOC-VECTOR type="constraint" content="Requires integration.slug and a credential field."]
14
- // CIL[DOC-VECTOR type="implementation_pattern" content="Called as a pipeline action or directly via /.netlify/functions/integration-outbound."]
15
- // CIL[DOC-VECTOR type="user_journey" content="Spine calls an external service through the broker."]
1
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/functions/integration-outbound.ts"]
2
+ // CIL[DOC-MACRO purpose="Module header: imports and adapter registration for outbound integration delivery"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Declares dependencies for the outbound integration handler and built-in adapter map"]
4
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts"]
5
+ // CIL[DOC-CONTRACT inputs="N/A" outputs="N/A" errors="N/A" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="Imports shared middleware, database, audit, credential resolution, admin-data and built-in outbound adapters." notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ // CIL[DOC-AUDIENCE audience="internal engineers"]
16
10
 
17
11
  import { createHandler, CoreContext } from './_shared/middleware'
18
12
  import { adminDb } from './_shared/db'
@@ -21,7 +15,22 @@ import { resolveCredential } from './_shared/resolve-credentials'
21
15
  import { get as adminDataGet, update as adminDataUpdate } from './admin-data'
22
16
  import * as openaiOutbound from './adapters/openai-outbound'
23
17
  import * as genericWebhookOutbound from './adapters/generic-webhook-outbound'
24
-
18
+ // CIL[DOC-VECTOR type="context" content="purpose='Module header: imports and adapter registration for outbound integration delivery'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
19
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
20
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
21
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
22
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
23
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
24
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:module_header:module_header"]
25
+
26
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:OutboundRequest:interface" type="interface" identity="OutboundRequest" parent="~/.framework/functions/integration-outbound.ts"]
27
+ // CIL[DOC-MACRO purpose="Shape of an outbound HTTP request produced by an adapter"]
28
+ // CIL[DOC-RESPONSIBILITY responsibility="Defines the contract between adapters and the outbound executor"]
29
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
30
+ // CIL[DOC-CONTRACT inputs="N/A" outputs="an OutboundRequest with url, method, optional headers, body and external_id" errors="N/A" side_effects="none"]
31
+ // CIL[DOC-MICRO logic_summary="Describes the fields required for a single outbound HTTP call." notable_decisions="[]"]
32
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
33
+ // CIL[DOC-STABILITY stability="stable"]
25
34
  interface OutboundRequest {
26
35
  url: string
27
36
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
@@ -29,7 +38,22 @@ interface OutboundRequest {
29
38
  body?: any
30
39
  external_id?: string
31
40
  }
32
-
41
+ // CIL[DOC-VECTOR type="context" content="purpose='Shape of an outbound HTTP request produced by an adapter'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
42
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
43
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
44
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
45
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
46
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
47
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:OutboundRequest:interface"]
48
+
49
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:OutboundAdapterContext:interface" type="interface" identity="OutboundAdapterContext" parent="~/.framework/functions/integration-outbound.ts"]
50
+ // CIL[DOC-MACRO purpose="Context object passed to outbound adapters when building a request"]
51
+ // CIL[DOC-RESPONSIBILITY responsibility="Encapsulates record, integration, resolved credential and runtime identifiers for adapter use"]
52
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
53
+ // CIL[DOC-CONTRACT inputs="N/A" outputs="an OutboundAdapterContext with record, integration, apiKey, accountId, appId and actionConfig" errors="N/A" side_effects="none"]
54
+ // CIL[DOC-MICRO logic_summary="Provides adapters with all runtime data needed to construct a request." notable_decisions="[]"]
55
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
56
+ // CIL[DOC-STABILITY stability="stable"]
33
57
  interface OutboundAdapterContext {
34
58
  record: any
35
59
  integration: any
@@ -38,17 +62,48 @@ interface OutboundAdapterContext {
38
62
  appId: string | null
39
63
  actionConfig: any
40
64
  }
41
-
65
+ // CIL[DOC-VECTOR type="context" content="purpose='Context object passed to outbound adapters when building a request'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
66
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
67
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
68
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
69
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
70
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
71
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:OutboundAdapterContext:interface"]
72
+
73
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:computeNextAttempt:function" type="function" identity="computeNextAttempt" parent="~/.framework/functions/integration-outbound.ts"]
74
+ // CIL[DOC-MACRO purpose="Compute the next retry timestamp for a failed outbound delivery"]
75
+ // CIL[DOC-RESPONSIBILITY responsibility="Calculate exponential backoff with jitter for delivery retries"]
76
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
77
+ // CIL[DOC-CONTRACT inputs="attemptCount: number, baseMs: number = 30000, maxDelayMs: number = 3600000" outputs="Date representing the next retry time" errors="none" side_effects="none"]
78
+ // CIL[DOC-MICRO logic_summary="Uses exponential backoff capped by maxDelayMs and adds up to 20% jitter." notable_decisions="[]"]
79
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
80
+ // CIL[DOC-STABILITY stability="stable"]
42
81
  function computeNextAttempt(attemptCount: number, baseMs = 30000, maxDelayMs = 3600000): Date {
43
82
  const delay = Math.min(baseMs * Math.pow(2, attemptCount), maxDelayMs)
44
83
  const jitter = Math.floor(Math.random() * delay * 0.2)
45
84
  return new Date(Date.now() + delay + jitter)
46
85
  }
47
-
86
+ // CIL[DOC-VECTOR type="context" content="purpose='Compute the next retry timestamp for a failed outbound delivery'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
87
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
88
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
89
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
90
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
91
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
92
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:computeNextAttempt:function"]
93
+
94
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:execute:function" type="function" identity="execute" parent="~/.framework/functions/integration-outbound.ts"]
95
+ // CIL[DOC-MACRO purpose="Execute an outbound integration webhook request with retries and audit logging"]
96
+ // CIL[DOC-RESPONSIBILITY responsibility="Resolve the integration, build an outbound request, call the target, and persist delivery status"]
97
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
98
+ // CIL[DOC-CONTRACT inputs="ctx: CoreContext, body: any = {}" outputs="object { success, delivery_id, response_status, response_body, is_retry }" errors="Throws if delivery not found, integration_slug missing or integration not found, adapter missing, request invalid, HTTP non-success, or delivery record update fails" side_effects="Inserts or updates webhook_deliveries, emits audit logs, calls an external HTTP endpoint, and optionally updates the source record"]
99
+ // CIL[DOC-MICRO logic_summary="Resolves tenant or system integration, creates or reuses a delivery record, loads the configured adapter, builds and executes the HTTP request, updates delivery status, and optionally writes the record." notable_decisions="[]"]
100
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
101
+ // CIL[DOC-STABILITY stability="stable"]
48
102
  export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
49
103
  let deliveryId = body?.delivery_id
50
104
  let requestBody = body
51
105
  let isRetry = false
106
+ let retryDelivery: any = null
52
107
 
53
108
  if (deliveryId && ctx.principal?.isInternal) {
54
109
  const { data: delivery, error: deliveryError } = await adminDb
@@ -61,6 +116,7 @@ export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
61
116
  throw new Error(`Delivery not found: ${deliveryId}`)
62
117
  }
63
118
 
119
+ retryDelivery = delivery
64
120
  requestBody = delivery.payload || {}
65
121
  isRetry = true
66
122
 
@@ -110,7 +166,20 @@ export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
110
166
  record = await adminDataGet(getCtx)
111
167
  }
112
168
 
169
+ const logStarted = (id: string) =>
170
+ emitLog(ctx, 'integration.outbound.started', { type: 'integration', id: integration.id }, undefined, {
171
+ delivery_id: id,
172
+ integration_id: integration.id,
173
+ record_id,
174
+ account_id: ctx.accountId,
175
+ is_retry: isRetry
176
+ }).catch(err => console.error('emitLog integration.outbound.started failed:', err))
177
+
113
178
  let deliveryPayload: any
179
+ // The delivery INSERT runs concurrently with the outbound request — the
180
+ // wire call dominates latency, so tracking no longer serializes ahead of
181
+ // it. insertPromise is awaited before any delivery update.
182
+ let insertPromise: Promise<string> | null = null
114
183
  if (!deliveryId) {
115
184
  deliveryPayload = {
116
185
  direction: 'outbound',
@@ -127,32 +196,27 @@ export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
127
196
  updated_at: new Date().toISOString()
128
197
  }
129
198
 
130
- const { data: deliveryRow, error: deliveryInsertError } = await adminDb
199
+ insertPromise = adminDb
131
200
  .from('webhook_deliveries')
132
201
  .insert(deliveryPayload)
133
202
  .select('id')
134
203
  .single()
135
-
136
- if (deliveryInsertError || !deliveryRow) {
137
- throw new Error('Failed to create outbound delivery record')
138
- }
139
-
140
- deliveryId = deliveryRow.id
204
+ .then(({ data: deliveryRow, error: deliveryInsertError }) => {
205
+ if (deliveryInsertError || !deliveryRow) {
206
+ throw new Error('Failed to create outbound delivery record')
207
+ }
208
+ void logStarted(deliveryRow.id)
209
+ return deliveryRow.id as string
210
+ })
211
+ insertPromise.catch(() => {}) // rejection is surfaced where it is awaited
141
212
  } else {
142
213
  await adminDb
143
214
  .from('webhook_deliveries')
144
215
  .update({ status: 'processing', updated_at: new Date().toISOString() })
145
216
  .eq('id', deliveryId)
217
+ void logStarted(deliveryId)
146
218
  }
147
219
 
148
- await emitLog(ctx, 'integration.outbound.started', { type: 'integration', id: integration.id }, undefined, {
149
- delivery_id: deliveryId,
150
- integration_id: integration.id,
151
- record_id,
152
- account_id: ctx.accountId,
153
- is_retry: isRetry
154
- })
155
-
156
220
  try {
157
221
  const credentialField = action_config.credential_field || 'api_token'
158
222
  const resolved = await resolveCredential(ctx, integration, credentialField)
@@ -201,18 +265,18 @@ export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
201
265
 
202
266
  const success = response.ok
203
267
 
204
- const { data: currentDelivery } = await adminDb
205
- .from('webhook_deliveries')
206
- .select('attempt_count')
207
- .eq('id', deliveryId)
208
- .single()
209
-
210
- const attemptCount = (currentDelivery?.attempt_count || 0) + 1
268
+ // The tracking insert overlapped the wire call — resolve it now for the
269
+ // status update. attempt_count is derived locally (fresh inserts start
270
+ // at 0, retries carry their count from the row loaded above), so no
271
+ // extra SELECT is needed.
272
+ if (!deliveryId && insertPromise) deliveryId = await insertPromise
273
+ const maxAttempts = deliveryPayload?.max_attempts ?? retryDelivery?.max_attempts ?? 3
274
+ const attemptCount = (isRetry ? retryDelivery?.attempt_count : 0) + 1
211
275
 
212
276
  await adminDb
213
277
  .from('webhook_deliveries')
214
278
  .update({
215
- status: success ? 'delivered' : (attemptCount >= (deliveryPayload?.max_attempts || 3) ? 'failed' : 'pending'),
279
+ status: success ? 'delivered' : (attemptCount >= maxAttempts ? 'failed' : 'pending'),
216
280
  attempt_count: attemptCount,
217
281
  next_attempt_at: success ? null : computeNextAttempt(attemptCount).toISOString(),
218
282
  response_status: response.status,
@@ -222,14 +286,14 @@ export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
222
286
  })
223
287
  .eq('id', deliveryId)
224
288
 
225
- await emitLog(ctx, success ? 'integration.outbound.succeeded' : 'integration.outbound.failed_http', { type: 'integration', id: integration.id }, undefined, {
289
+ void emitLog(ctx, success ? 'integration.outbound.succeeded' : 'integration.outbound.failed_http', { type: 'integration', id: integration.id }, undefined, {
226
290
  delivery_id: deliveryId,
227
291
  integration_id: integration.id,
228
292
  response_status: response.status,
229
293
  duration_ms: durationMs,
230
294
  account_id: ctx.accountId,
231
295
  is_retry: isRetry
232
- })
296
+ }).catch(err => console.error('emitLog integration.outbound result failed:', err))
233
297
 
234
298
  if (success && action_config.update_record && record_id) {
235
299
  await adminDataUpdate({ ...ctx, query: { entity: 'items', id: record_id } } as any, {
@@ -255,43 +319,73 @@ export async function execute(ctx: CoreContext, body: any = {}): Promise<any> {
255
319
  is_retry: isRetry
256
320
  }
257
321
  } catch (err: any) {
258
- const { data: currentDelivery } = await adminDb
259
- .from('webhook_deliveries')
260
- .select('attempt_count, max_attempts')
261
- .eq('id', deliveryId)
262
- .single()
263
-
264
- const attemptCount = (currentDelivery?.attempt_count || 0) + 1
265
- const shouldRetry = attemptCount < (currentDelivery?.max_attempts || 3)
266
-
267
- await adminDb
268
- .from('webhook_deliveries')
269
- .update({
270
- status: shouldRetry ? 'pending' : 'failed',
271
- attempt_count: attemptCount,
272
- next_attempt_at: shouldRetry ? computeNextAttempt(attemptCount).toISOString() : null,
273
- last_error: err.message || String(err),
274
- updated_at: new Date().toISOString()
275
- })
276
- .eq('id', deliveryId)
277
-
278
- await emitLog(ctx, 'integration.outbound.error', { type: 'integration', id: integration.id }, undefined, {
279
- delivery_id: deliveryId,
280
- integration_id: integration.id,
281
- error: err.message || String(err),
282
- account_id: ctx.accountId,
283
- is_retry: isRetry
284
- })
322
+ // Resolve the overlapped tracking insert — if it failed there is no
323
+ // delivery row to update, so skip the bookkeeping and rethrow.
324
+ if (!deliveryId && insertPromise) deliveryId = await insertPromise.catch(() => null)
325
+ if (deliveryId) {
326
+ const maxAttempts = deliveryPayload?.max_attempts ?? retryDelivery?.max_attempts ?? 3
327
+ const attemptCount = (isRetry ? retryDelivery?.attempt_count : 0) + 1
328
+ const shouldRetry = attemptCount < maxAttempts
329
+
330
+ await adminDb
331
+ .from('webhook_deliveries')
332
+ .update({
333
+ status: shouldRetry ? 'pending' : 'failed',
334
+ attempt_count: attemptCount,
335
+ next_attempt_at: shouldRetry ? computeNextAttempt(attemptCount).toISOString() : null,
336
+ last_error: err.message || String(err),
337
+ updated_at: new Date().toISOString()
338
+ })
339
+ .eq('id', deliveryId)
340
+
341
+ void emitLog(ctx, 'integration.outbound.error', { type: 'integration', id: integration.id }, undefined, {
342
+ delivery_id: deliveryId,
343
+ integration_id: integration.id,
344
+ error: err.message || String(err),
345
+ account_id: ctx.accountId,
346
+ is_retry: isRetry
347
+ }).catch(logErr => console.error('emitLog integration.outbound.error failed:', logErr))
348
+ }
285
349
 
286
350
  throw err
287
351
  }
288
352
  }
289
-
353
+ // CIL[DOC-VECTOR type="context" content="purpose='Execute an outbound integration webhook request with retries and audit logging'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
354
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
355
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
356
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
357
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
358
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
359
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:execute:function"]
360
+
361
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:builtInOutboundAdapters:constant" type="constant" identity="builtInOutboundAdapters" parent="~/.framework/functions/integration-outbound.ts"]
362
+ // CIL[DOC-MACRO purpose="Registry of built-in outbound adapter modules"]
363
+ // CIL[DOC-RESPONSIBILITY responsibility="Map adapter paths to their module exports"]
364
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
365
+ // CIL[DOC-CONTRACT inputs="N/A" outputs="Record<string, any> of built-in adapters" errors="N/A" side_effects="none"]
366
+ // CIL[DOC-MICRO logic_summary="Lists the openai and generic webhook outbound adapter modules." notable_decisions="[]"]
367
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
368
+ // CIL[DOC-STABILITY stability="stable"]
290
369
  const builtInOutboundAdapters: Record<string, any> = {
291
370
  'adapters/openai-outbound': openaiOutbound,
292
371
  'adapters/generic-webhook-outbound': genericWebhookOutbound
293
372
  }
294
-
373
+ // CIL[DOC-VECTOR type="context" content="purpose='Registry of built-in outbound adapter modules'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
374
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
375
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
376
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
377
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
378
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
379
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:builtInOutboundAdapters:constant"]
380
+
381
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:loadOutboundAdapter:function" type="function" identity="loadOutboundAdapter" parent="~/.framework/functions/integration-outbound.ts"]
382
+ // CIL[DOC-MACRO purpose="Load an outbound adapter by name from built-ins or dynamic imports"]
383
+ // CIL[DOC-RESPONSIBILITY responsibility="Resolve and return an adapter module that exposes buildRequest"]
384
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
385
+ // CIL[DOC-CONTRACT inputs="functionName: string" outputs="adapter module or null" errors="Returns null on import or validation failure" side_effects="Logs a console error on import failure"]
386
+ // CIL[DOC-MICRO logic_summary="Checks built-in registry first, then dynamically imports the requested adapter and verifies buildRequest exists." notable_decisions="[]"]
387
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
388
+ // CIL[DOC-STABILITY stability="stable"]
295
389
  async function loadOutboundAdapter(functionName: string): Promise<any | null> {
296
390
  if (builtInOutboundAdapters[functionName]) {
297
391
  return builtInOutboundAdapters[functionName]
@@ -304,8 +398,44 @@ async function loadOutboundAdapter(functionName: string): Promise<any | null> {
304
398
  return null
305
399
  }
306
400
  }
307
-
401
+ // CIL[DOC-VECTOR type="context" content="purpose='Load an outbound adapter by name from built-ins or dynamic imports'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
402
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
403
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
404
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
405
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
406
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
407
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:loadOutboundAdapter:function"]
408
+
409
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:integrationOutbound:constant" type="constant" identity="integrationOutbound" parent="~/.framework/functions/integration-outbound.ts"]
410
+ // CIL[DOC-MACRO purpose="Handler binding for the outbound integration execute function"]
411
+ // CIL[DOC-RESPONSIBILITY responsibility="Wrap execute in the shared middleware handler"]
412
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
413
+ // CIL[DOC-CONTRACT inputs="N/A" outputs="createHandler(execute) result" errors="N/A" side_effects="none"]
414
+ // CIL[DOC-MICRO logic_summary="Creates the middleware-backed handler from the execute function." notable_decisions="[]"]
415
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
416
+ // CIL[DOC-STABILITY stability="stable"]
308
417
  const integrationOutbound = createHandler(execute)
418
+ // CIL[DOC-VECTOR type="context" content="purpose='Handler binding for the outbound integration execute function'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
419
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
420
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
421
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
422
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
423
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
424
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:integrationOutbound:constant"]
425
+ // CIL[BEGIN stable_id="~/.framework/functions/integration-outbound.ts:default:function" type="function" identity="default" parent="~/.framework/functions/integration-outbound.ts"]
426
+ // CIL[DOC-MACRO purpose="Default export of the integration outbound handler"]
427
+ // CIL[DOC-RESPONSIBILITY responsibility="Export integrationOutbound as the module default"]
428
+ // CIL[DOC-CONTEXT module="integration-outbound" layer="functions" related_files=".framework/functions/_shared/audit.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-credentials.ts,.framework/functions/adapters/generic-webhook-outbound.ts,.framework/functions/adapters/openai-outbound.ts,.framework/functions/admin-data.ts,.framework/functions/integration-outbound.ts"]
429
+ // CIL[DOC-CONTRACT inputs="N/A" outputs="integrationOutbound handler" errors="N/A" side_effects="none"]
430
+ // CIL[DOC-MICRO logic_summary="Exports the prebuilt handler as the module default for serverless entry points." notable_decisions="[]"]
431
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
432
+ // CIL[DOC-STABILITY stability="stable"]
309
433
  export default integrationOutbound
434
+ // CIL[DOC-VECTOR type="context" content="purpose='Default export of the integration outbound handler'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
435
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
436
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
437
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
438
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
439
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
440
+ // CIL[END stable_id="~/.framework/functions/integration-outbound.ts:default:function"]
310
441
 
311
- // CIL[END chunk_id="integration_outbound_module_header_1784200004"]