whale-code 6.5.11 → 6.6.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.
- package/dist/cli/chat/ChatApp.js +7 -11
- package/dist/cli/chat/ChatApp.js.map +1 -1
- package/dist/cli/chat/ChatInput.js +7 -3
- package/dist/cli/chat/ChatInput.js.map +1 -1
- package/dist/cli/chat/MessageList.js +5 -6
- package/dist/cli/chat/MessageList.js.map +1 -1
- package/dist/cli/chat/StatusBar.d.ts +2 -2
- package/dist/cli/chat/StatusBar.js +90 -160
- package/dist/cli/chat/StatusBar.js.map +1 -1
- package/dist/cli/chat/components/LiveArea.js +78 -115
- package/dist/cli/chat/components/LiveArea.js.map +1 -1
- package/dist/cli/chat/components/StaticMessages.js +60 -79
- package/dist/cli/chat/components/StaticMessages.js.map +1 -1
- package/dist/cli/chat/hooks/useAgentLoop.js +45 -37
- package/dist/cli/chat/hooks/useAgentLoop.js.map +1 -1
- package/dist/cli/chat/store.d.ts +12 -0
- package/dist/cli/chat/store.js +19 -0
- package/dist/cli/chat/store.js.map +1 -1
- package/dist/cli/services/agent-loop-tools.js +10 -1
- package/dist/cli/services/agent-loop-tools.js.map +1 -1
- package/dist/cli/services/cli-agent-loop.js +3 -2
- package/dist/cli/services/cli-agent-loop.js.map +1 -1
- package/dist/cli/services/config-store.js +4 -3
- package/dist/cli/services/config-store.js.map +1 -1
- package/dist/cli/services/memory-manager.js +2 -2
- package/dist/cli/services/memory-manager.js.map +1 -1
- package/dist/cli/services/permission-modes.js +14 -10
- package/dist/cli/services/permission-modes.js.map +1 -1
- package/dist/cli/services/session-client.js +2 -1
- package/dist/cli/services/session-client.js.map +1 -1
- package/dist/cli/services/session-persistence.js +14 -6
- package/dist/cli/services/session-persistence.js.map +1 -1
- package/dist/cli/shared/SpinnerSlot.js +4 -1
- package/dist/cli/shared/SpinnerSlot.js.map +1 -1
- package/dist/server/handlers/browser-lifecycle.js +10 -0
- package/dist/server/handlers/browser-lifecycle.js.map +1 -1
- package/dist/server/handlers/browser.js +16 -1
- package/dist/server/handlers/browser.js.map +1 -1
- package/dist/server/handlers/campaigns.js +11 -0
- package/dist/server/handlers/campaigns.js.map +1 -1
- package/dist/server/handlers/catalog-products.js +19 -5
- package/dist/server/handlers/catalog-products.js.map +1 -1
- package/dist/server/handlers/catalog.js +42 -8
- package/dist/server/handlers/catalog.js.map +1 -1
- package/dist/server/handlers/clickhouse.js +4 -4
- package/dist/server/handlers/clickhouse.js.map +1 -1
- package/dist/server/handlers/comms-email.js +70 -8
- package/dist/server/handlers/comms-email.js.map +1 -1
- package/dist/server/handlers/comms.js +63 -21
- package/dist/server/handlers/comms.js.map +1 -1
- package/dist/server/handlers/coupons.js +141 -77
- package/dist/server/handlers/coupons.js.map +1 -1
- package/dist/server/handlers/google-ads.js +280 -8
- package/dist/server/handlers/google-ads.js.map +1 -1
- package/dist/server/handlers/remove-bg.d.ts +33 -0
- package/dist/server/handlers/remove-bg.js +698 -44
- package/dist/server/handlers/remove-bg.js.map +1 -1
- package/dist/server/handlers/supply-chain.js +93 -1
- package/dist/server/handlers/supply-chain.js.map +1 -1
- package/dist/server/handlers/workflow-steps-types.d.ts +1 -1
- package/dist/server/handlers/workflow-steps-types.js +7 -1
- package/dist/server/handlers/workflow-steps-types.js.map +1 -1
- package/dist/server/handlers/workflow-steps.js +1 -1
- package/dist/server/handlers/workflow-steps.js.map +1 -1
- package/dist/server/index.js +122 -29
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent-loop-turn.js +33 -3
- package/dist/server/lib/agent-loop-turn.js.map +1 -1
- package/dist/server/lib/agent-loop-types.d.ts +6 -2
- package/dist/server/lib/agent-loop-types.js +14 -2
- package/dist/server/lib/agent-loop-types.js.map +1 -1
- package/dist/server/lib/clickhouse-client.js +4 -2
- package/dist/server/lib/clickhouse-client.js.map +1 -1
- package/dist/server/lib/code-worker.js +4 -1
- package/dist/server/lib/code-worker.js.map +1 -1
- package/dist/server/providers/anthropic.js +103 -33
- package/dist/server/providers/anthropic.js.map +1 -1
- package/dist/server/server-chat.js +2 -2
- package/dist/server/server-chat.js.map +1 -1
- package/dist/server/server-helpers.d.ts +8 -1
- package/dist/server/server-helpers.js +17 -3
- package/dist/server/server-helpers.js.map +1 -1
- package/dist/server/server-persist.js +34 -21
- package/dist/server/server-persist.js.map +1 -1
- package/dist/server/server-rate-limit.d.ts +0 -1
- package/dist/server/server-rate-limit.js +5 -5
- package/dist/server/server-rate-limit.js.map +1 -1
- package/dist/server/server-routes-approvals.js +2 -2
- package/dist/server/server-routes-approvals.js.map +1 -1
- package/dist/server/server-routes-auth.js +2 -2
- package/dist/server/server-routes-auth.js.map +1 -1
- package/dist/server/server-routes-events.js +2 -2
- package/dist/server/server-routes-events.js.map +1 -1
- package/dist/server/server-routes-public.js +4 -4
- package/dist/server/server-routes-public.js.map +1 -1
- package/dist/server/server-routes-webchat.js +3 -3
- package/dist/server/server-routes-webchat.js.map +1 -1
- package/dist/server/server-store-circuit-breaker.js +1 -1
- package/dist/server/server-store-circuit-breaker.js.map +1 -1
- package/dist/server/tool-router.js +7 -4
- package/dist/server/tool-router.js.map +1 -1
- package/dist/server/validation.js +11 -0
- package/dist/server/validation.js.map +1 -1
- package/dist/shared/api-client.js +38 -11
- package/dist/shared/api-client.js.map +1 -1
- package/package.json +12 -10
- package/vendor/ink/build/ink.js +68 -24
- package/vendor/ink/node_modules/react-devtools-core/README.md +152 -0
- package/vendor/ink/node_modules/react-devtools-core/backend.js +1 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/648.chunk.js +2 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/648.chunk.js.map +1 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/backend.js +15691 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/backend.js.map +1 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/importFile.worker.worker.js +2 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/importFile.worker.worker.js.map +1 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/parseSourceAndMetadata.worker.worker.js +14 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/parseSourceAndMetadata.worker.worker.js.map +1 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/standalone.js +2 -0
- package/vendor/ink/node_modules/react-devtools-core/dist/standalone.js.map +1 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/LICENSE +21 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/README.md +495 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/browser.js +8 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/index.js +10 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/buffer-util.js +129 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/constants.js +10 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/event-target.js +184 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/extension.js +223 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/limiter.js +55 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/permessage-deflate.js +518 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/receiver.js +607 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/sender.js +409 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/stream.js +180 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/validation.js +104 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/websocket-server.js +449 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/lib/websocket.js +1197 -0
- package/vendor/ink/node_modules/react-devtools-core/node_modules/ws/package.json +56 -0
- package/vendor/ink/node_modules/react-devtools-core/package.json +38 -0
- package/vendor/ink/node_modules/react-devtools-core/standalone.js +1 -0
- package/dist/cli/__tests__/print-mode-streaming.test.js +0 -270
- package/dist/cli/__tests__/print-mode.basic-output.test.js +0 -230
- package/dist/cli/__tests__/print-mode.session-errors.test.js +0 -252
- package/dist/cli/__tests__/print-mode.test.js +0 -273
- package/dist/cli/__tests__/serve-mode-messages.test.js +0 -338
- package/dist/cli/__tests__/serve-mode.messages.part2.test.js +0 -266
- package/dist/cli/__tests__/serve-mode.messages.test.js +0 -277
- package/dist/cli/__tests__/serve-mode.startup-http.test.js +0 -279
- package/dist/cli/__tests__/serve-mode.test.js +0 -345
- package/dist/cli/chat/NodeManager.d.ts +0 -30
- package/dist/cli/chat/NodeManager.js +0 -66
- package/dist/cli/chat/NodeManager.js.map +0 -1
- package/dist/cli/chat/chat-input-menu-handler.d.ts +0 -32
- package/dist/cli/chat/hooks/slash-imsg-handlers.js +0 -148
- package/dist/cli/chat/hooks/slash-imsg-handlers.js.map +0 -1
- package/dist/cli/chat/hooks/useStreamingReducer.d.ts +0 -66
- package/dist/cli/commands/__tests__/config-cmd.test.js +0 -270
- package/dist/cli/commands/__tests__/doctor.test.js +0 -257
- package/dist/cli/commands/__tests__/imsg-node-bridge.test.js +0 -99
- package/dist/cli/commands/__tests__/imsg-utils.test.js +0 -73
- package/dist/cli/commands/__tests__/init.test.js +0 -214
- package/dist/cli/commands/__tests__/mcp.test.js +0 -287
- package/dist/cli/commands/imsg-watcher-helpers.d.ts +0 -40
- package/dist/cli/commands/imsg-watcher-helpers.js +0 -184
- package/dist/cli/commands/imsg-watcher-helpers.js.map +0 -1
- package/dist/cli/commands/imsg-watcher.d.ts +0 -11
- package/dist/cli/commands/imsg-watcher.js +0 -230
- package/dist/cli/commands/imsg-watcher.js.map +0 -1
- package/dist/cli/services/__tests__/agent-definitions.test.js +0 -153
- package/dist/cli/services/__tests__/agent-events-global.test.js +0 -39
- package/dist/cli/services/__tests__/agent-events.part2.test.js +0 -113
- package/dist/cli/services/__tests__/agent-events.test.js +0 -157
- package/dist/cli/services/__tests__/agent-loop-auth.test.js +0 -392
- package/dist/cli/services/__tests__/agent-loop-budget.test.js +0 -389
- package/dist/cli/services/__tests__/agent-loop-tools-lifecycle.test.js +0 -430
- package/dist/cli/services/__tests__/agent-loop-tools-maxturns.test.js +0 -486
- package/dist/cli/services/__tests__/agent-loop-utils-execution.test.js +0 -528
- package/dist/cli/services/__tests__/agent-loop-utils-helpers.test.js +0 -466
- package/dist/cli/services/__tests__/agent-worker-base-execute.test.js +0 -257
- package/dist/cli/services/__tests__/agent-worker-base-helpers.test.js +0 -198
- package/dist/cli/services/__tests__/agent-worker-base.test.js +0 -278
- package/dist/cli/services/__tests__/auth-service-exports.test.js +0 -41
- package/dist/cli/services/__tests__/auth-service.part2.test.js +0 -169
- package/dist/cli/services/__tests__/auth-service.test.js +0 -242
- package/dist/cli/services/__tests__/background-processes.test.js +0 -282
- package/dist/cli/services/__tests__/claude-md-loader.test.js +0 -134
- package/dist/cli/services/__tests__/config-store.test.js +0 -247
- package/dist/cli/services/__tests__/debug-log.test.js +0 -199
- package/dist/cli/services/__tests__/edge-cases-caching.test.js +0 -174
- package/dist/cli/services/__tests__/edge-cases-compaction-core.test.js +0 -226
- package/dist/cli/services/__tests__/edge-cases-compaction-openai.test.js +0 -152
- package/dist/cli/services/__tests__/edge-cases-compaction-shapes.test.js +0 -53
- package/dist/cli/services/__tests__/edge-cases-compaction-thinking.test.js +0 -226
- package/dist/cli/services/__tests__/edge-cases-compaction.test.js +0 -131
- package/dist/cli/services/__tests__/edge-cases-paths.test.js +0 -86
- package/dist/cli/services/__tests__/error-logger-messages.test.js +0 -81
- package/dist/cli/services/__tests__/error-logger-transport.test.js +0 -119
- package/dist/cli/services/__tests__/error-logger.test.js +0 -264
- package/dist/cli/services/__tests__/file-history.test.js +0 -136
- package/dist/cli/services/__tests__/git-context-cache-reset.test.js +0 -223
- package/dist/cli/services/__tests__/git-context.test.js +0 -241
- package/dist/cli/services/__tests__/interactive-tools-execute.test.js +0 -166
- package/dist/cli/services/__tests__/interactive-tools-plan.test.js +0 -197
- package/dist/cli/services/__tests__/interactive-tools.part2.test.js +0 -168
- package/dist/cli/services/__tests__/interactive-tools.test.js +0 -179
- package/dist/cli/services/__tests__/keybinding-manager.test.js +0 -205
- package/dist/cli/services/__tests__/local-tools-dispatch.test.js +0 -404
- package/dist/cli/services/__tests__/local-tools.test.js +0 -238
- package/dist/cli/services/__tests__/lsp-manager.test.js +0 -364
- package/dist/cli/services/__tests__/mcp-client-connect-disconnect.test.js +0 -310
- package/dist/cli/services/__tests__/mcp-client.test.js +0 -93
- package/dist/cli/services/__tests__/memory-manager.test.js +0 -154
- package/dist/cli/services/__tests__/model-manager-utils.test.js +0 -154
- package/dist/cli/services/__tests__/model-manager.test.js +0 -175
- package/dist/cli/services/__tests__/permission-modes.test.js +0 -222
- package/dist/cli/services/__tests__/ripgrep.test.js +0 -328
- package/dist/cli/services/__tests__/server-tools-execute.test.js +0 -317
- package/dist/cli/services/__tests__/server-tools.test.js +0 -272
- package/dist/cli/services/__tests__/session-persistence.test.js +0 -245
- package/dist/cli/services/__tests__/subagent-basic.test.js +0 -489
- package/dist/cli/services/__tests__/subagent-edge.test.js +0 -545
- package/dist/cli/services/__tests__/subagent-prompts.test.js +0 -558
- package/dist/cli/services/__tests__/subagent-worker-errors.test.js +0 -255
- package/dist/cli/services/__tests__/subagent-worker.test.js +0 -242
- package/dist/cli/services/__tests__/system-prompt.test.js +0 -210
- package/dist/cli/services/__tests__/team-lead-comms-messaging.test.js +0 -250
- package/dist/cli/services/__tests__/team-lead-comms-result.test.js +0 -232
- package/dist/cli/services/__tests__/team-lead-comms-stop.test.js +0 -344
- package/dist/cli/services/__tests__/team-lead-comms.test.js +0 -285
- package/dist/cli/services/__tests__/team-lead-create.test.js +0 -327
- package/dist/cli/services/__tests__/team-lead-run.test.js +0 -318
- package/dist/cli/services/__tests__/team-lead-stop.test.js +0 -199
- package/dist/cli/services/__tests__/team-state-comms.test.js +0 -240
- package/dist/cli/services/__tests__/team-state-core.test.js +0 -230
- package/dist/cli/services/__tests__/team-state-tasks-complete-fail-available.test.js +0 -224
- package/dist/cli/services/__tests__/team-state-tasks.test.js +0 -184
- package/dist/cli/services/__tests__/telemetry-ai-metadata.test.js +0 -116
- package/dist/cli/services/__tests__/telemetry.part2.test.js +0 -195
- package/dist/cli/services/__tests__/telemetry.test.js +0 -176
- package/dist/cli/services/agent-loop-iteration.d.ts +0 -13
- package/dist/cli/services/agent-loop-setup.d.ts +0 -32
- package/dist/cli/services/agent-worker-base-api.d.ts +0 -19
- package/dist/cli/services/agent-worker-base-helpers.d.ts +0 -27
- package/dist/cli/services/agent-worker-base-tools.d.ts +0 -16
- package/dist/cli/services/agent-worker-base-types.d.ts +0 -81
- package/dist/cli/services/background-agents.d.ts +0 -26
- package/dist/cli/services/background-processes-ops.d.ts +0 -24
- package/dist/cli/services/background-tool-defs.d.ts +0 -50
- package/dist/cli/services/config-modules-model.test.js +0 -133
- package/dist/cli/services/config-modules-permission.test.js +0 -85
- package/dist/cli/services/config-modules-permissions.test.js +0 -85
- package/dist/cli/services/config-modules-session.test.js +0 -297
- package/dist/cli/services/format-server-response-columns.test.js +0 -265
- package/dist/cli/services/format-server-response-fallback.test.js +0 -65
- package/dist/cli/services/format-server-response-primitives-basic.test.js +0 -261
- package/dist/cli/services/format-server-response-primitives-nested.test.js +0 -188
- package/dist/cli/services/format-server-response-primitives.test.js +0 -300
- package/dist/cli/services/format-server-response-realworld.test.js +0 -248
- package/dist/cli/services/format-server-response-values.test.js +0 -247
- package/dist/cli/services/hooks-runners.test.js +0 -184
- package/dist/cli/services/hooks.glob-load.test.js +0 -233
- package/dist/cli/services/hooks.run-hooks.test.js +0 -184
- package/dist/cli/services/hooks.test.js +0 -233
- package/dist/cli/services/ink-incremental.d.ts +0 -19
- package/dist/cli/services/ink-incremental.js +0 -59
- package/dist/cli/services/ink-incremental.js.map +0 -1
- package/dist/cli/services/ink-resize-fix.d.ts +0 -18
- package/dist/cli/services/ink-resize-fix.js +0 -76
- package/dist/cli/services/ink-resize-fix.js.map +0 -1
- package/dist/cli/services/ink-sync-output.d.ts +0 -12
- package/dist/cli/services/ink-sync-output.js +0 -16
- package/dist/cli/services/ink-sync-output.js.map +0 -1
- package/dist/cli/services/interactive-tool-defs.d.ts +0 -80
- package/dist/cli/services/local-tools-definitions.d.ts +0 -6
- package/dist/cli/services/local-tools-files.test.js +0 -256
- package/dist/cli/services/local-tools-read-many.d.ts +0 -6
- package/dist/cli/services/model-router.test.js +0 -245
- package/dist/cli/services/rewind-rewindTo.test.js +0 -202
- package/dist/cli/services/rewind.test.js +0 -175
- package/dist/cli/services/sandbox.test.js +0 -198
- package/dist/cli/services/subagent-execution.d.ts +0 -12
- package/dist/cli/services/team-lead-auto.d.ts +0 -11
- package/dist/cli/services/team-lead-execution.d.ts +0 -28
- package/dist/cli/services/teammate-loop.js +0 -557
- package/dist/cli/services/teammate-loop.js.map +0 -1
- package/dist/cli/services/tools/__tests__/agent-tools-tasks-teams.test.js +0 -250
- package/dist/cli/services/tools/__tests__/agent-tools-teams.test.js +0 -200
- package/dist/cli/services/tools/__tests__/agent-tools.test.js +0 -340
- package/dist/cli/services/tools/__tests__/file-ops-cache.test.js +0 -152
- package/dist/cli/services/tools/__tests__/file-ops-notebook.test.js +0 -249
- package/dist/cli/services/tools/__tests__/file-ops-read.test.js +0 -261
- package/dist/cli/services/tools/__tests__/file-ops-write.test.js +0 -292
- package/dist/cli/services/tools/__tests__/search-tools-rg.test.js +0 -92
- package/dist/cli/services/tools/__tests__/search-tools.part2.test.js +0 -174
- package/dist/cli/services/tools/__tests__/search-tools.test.js +0 -227
- package/dist/cli/services/tools/__tests__/shell-exec-allowed-core.test.js +0 -163
- package/dist/cli/services/tools/__tests__/shell-exec-allowed-extended.test.js +0 -220
- package/dist/cli/services/tools/__tests__/shell-exec-allowed.part2.test.js +0 -215
- package/dist/cli/services/tools/__tests__/shell-exec-allowed.test.js +0 -154
- package/dist/cli/services/tools/__tests__/shell-exec-blocked.test.js +0 -132
- package/dist/cli/services/tools/__tests__/shell-exec-execution.test.js +0 -245
- package/dist/cli/services/tools/__tests__/task-manager-create.test.js +0 -110
- package/dist/cli/services/tools/__tests__/task-manager-crud.test.js +0 -339
- package/dist/cli/services/tools/__tests__/task-manager-list-get.test.js +0 -343
- package/dist/cli/services/tools/__tests__/task-manager-query.test.js +0 -346
- package/dist/cli/services/tools/__tests__/task-manager-routing.test.js +0 -58
- package/dist/cli/services/tools/__tests__/task-manager-update.test.js +0 -224
- package/dist/cli/services/tools/__tests__/task-manager.test.js +0 -159
- package/dist/cli/services/tools/__tests__/web-tools-html-search.test.js +0 -227
- package/dist/cli/services/tools/__tests__/web-tools.test.js +0 -285
- package/dist/cli/services/tools/shell-exec.test.js +0 -148
- package/dist/cli/shared/SharedTick.d.ts +0 -10
- package/dist/cli/shared/__tests__/markdown.test.js +0 -188
- package/dist/local-agent/__tests__/connection-disconnect.test.js +0 -201
- package/dist/local-agent/__tests__/connection-lifecycle.test.js +0 -289
- package/dist/local-agent/__tests__/connection-msghandling.test.js +0 -311
- package/dist/local-agent/__tests__/connection-reconnect.test.js +0 -230
- package/dist/local-agent/__tests__/connection-toolexec.test.js +0 -253
- package/dist/local-agent/__tests__/discovery.test.js +0 -328
- package/dist/local-agent/__tests__/executor-background.test.js +0 -219
- package/dist/local-agent/__tests__/executor-exec.test.js +0 -221
- package/dist/local-agent/__tests__/executor-jobs-sessions.test.js +0 -220
- package/dist/local-agent/__tests__/executor-system-info.test.js +0 -133
- package/dist/local-agent/__tests__/executor-systeminfo.test.js +0 -109
- package/dist/local-agent/__tests__/executor.test.js +0 -235
- package/dist/local-agent/__tests__/index.test.js +0 -139
- package/dist/node/__tests__/cli-channels.test.js +0 -293
- package/dist/node/__tests__/cli-config-edge.test.js +0 -154
- package/dist/node/__tests__/cli-config.test.js +0 -215
- package/dist/node/__tests__/config.test.js +0 -292
- package/dist/node/__tests__/runtime-heartbeat.test.js +0 -153
- package/dist/node/__tests__/runtime-lifecycle-init.test.js +0 -263
- package/dist/node/__tests__/runtime-lifecycle-stats.test.js +0 -180
- package/dist/node/__tests__/runtime-lifecycle.test.js +0 -305
- package/dist/node/__tests__/runtime-relay.test.js +0 -341
- package/dist/node/adapters/__tests__/base.test.js +0 -286
- package/dist/node/adapters/__tests__/discord.test.js +0 -284
- package/dist/node/adapters/__tests__/email-send.test.js +0 -295
- package/dist/node/adapters/__tests__/email.inbound-send.test.js +0 -217
- package/dist/node/adapters/__tests__/email.lifecycle.test.js +0 -211
- package/dist/node/adapters/__tests__/email.test.js +0 -290
- package/dist/node/adapters/__tests__/email.webhook-send.test.js +0 -251
- package/dist/node/adapters/__tests__/imessage-filter.test.js +0 -183
- package/dist/node/adapters/__tests__/imessage-lifecycle.test.js +0 -215
- package/dist/node/adapters/__tests__/imessage-send-restart.test.js +0 -227
- package/dist/node/adapters/__tests__/slack.part2.test.js +0 -135
- package/dist/node/adapters/__tests__/slack.test.js +0 -241
- package/dist/node/adapters/__tests__/sms-extras.test.js +0 -108
- package/dist/node/adapters/__tests__/sms-lifecycle.test.js +0 -203
- package/dist/node/adapters/__tests__/sms-messaging.test.js +0 -266
- package/dist/node/adapters/__tests__/sms.part2.test.js +0 -174
- package/dist/node/adapters/__tests__/sms.test.js +0 -253
- package/dist/node/adapters/__tests__/telegram-polling.test.js +0 -256
- package/dist/node/adapters/__tests__/telegram-send.test.js +0 -166
- package/dist/node/adapters/__tests__/webchat-inbound.test.js +0 -188
- package/dist/node/adapters/__tests__/webchat-outbound.test.js +0 -178
- package/dist/node/adapters/__tests__/whatsapp-inbound.test.js +0 -200
- package/dist/node/adapters/__tests__/whatsapp-send.test.js +0 -212
- package/dist/node/adapters/__tests__/whatsapp.test.js +0 -280
- package/dist/server/__tests__/gateway-fast-fail.test.js +0 -160
- package/dist/server/__tests__/local-agent-gateway.test.js +0 -186
- package/dist/server/__tests__/proxy-handlers-delegation.test.js +0 -240
- package/dist/server/__tests__/proxy-handlers-validation.test.js +0 -211
- package/dist/server/__tests__/proxy-handlers.part2.test.js +0 -240
- package/dist/server/__tests__/proxy-handlers.test.js +0 -213
- package/dist/server/__tests__/strip-base64-e2e.test.js +0 -303
- package/dist/server/__tests__/strip-base64.test.js +0 -256
- package/dist/server/__tests__/tool-router-agent-tools.test.js +0 -324
- package/dist/server/__tests__/tool-router-execute-core.test.js +0 -357
- package/dist/server/__tests__/tool-router-execute-permissions.test.js +0 -332
- package/dist/server/__tests__/tool-router-execute.test.js +0 -348
- package/dist/server/__tests__/tool-router-load.test.js +0 -432
- package/dist/server/__tests__/tool-router-permissions.test.js +0 -359
- package/dist/server/__tests__/tool-router-registry-cache.test.js +0 -383
- package/dist/server/__tests__/tool-router-registry-handlers.test.js +0 -272
- package/dist/server/__tests__/tool-router-registry.test.js +0 -331
- package/dist/server/__tests__/validation-inventory.test.js +0 -250
- package/dist/server/__tests__/validation-misc.test.js +0 -243
- package/dist/server/__tests__/validation-supply-chain.test.js +0 -188
- package/dist/server/__tests__/worker.test.js +0 -265
- package/dist/server/handlers/__tests__/conversation-lock.test.js +0 -117
- package/dist/server/handlers/__tests__/e2e/auth-cross-platform-login.e2e.test.js +0 -268
- package/dist/server/handlers/__tests__/e2e/auth-cross-platform-tokens.e2e.test.js +0 -264
- package/dist/server/handlers/__tests__/e2e/email-pipeline-send.e2e.test.js +0 -214
- package/dist/server/handlers/__tests__/e2e/email-pipeline-threads.e2e.test.js +0 -168
- package/dist/server/handlers/__tests__/e2e/error-logging-pipeline-dedup.e2e.test.js +0 -229
- package/dist/server/handlers/__tests__/e2e/error-logging-pipeline.e2e.test.js +0 -239
- package/dist/server/handlers/__tests__/e2e/error-logging-rate-limit.e2e.test.js +0 -150
- package/dist/server/handlers/__tests__/e2e/inventory-sync-guards.e2e.test.js +0 -177
- package/dist/server/handlers/__tests__/e2e/inventory-sync.e2e.test.js +0 -228
- package/dist/server/handlers/__tests__/e2e/inventory-sync.part2.e2e.test.js +0 -188
- package/dist/server/handlers/__tests__/e2e/order-lifecycle-fulfillment.e2e.test.js +0 -295
- package/dist/server/handlers/__tests__/e2e/order-lifecycle.e2e.test.js +0 -277
- package/dist/server/handlers/__tests__/e2e/order-lifecycle.fulfillment.e2e.test.js +0 -307
- package/dist/server/handlers/__tests__/e2e/order-lifecycle.setup.e2e.test.js +0 -177
- package/dist/server/handlers/__tests__/e2e/storefront-checkout-cart.e2e.test.js +0 -255
- package/dist/server/handlers/__tests__/e2e/storefront-checkout-webhook.e2e.test.js +0 -231
- package/dist/server/handlers/__tests__/e2e/workflow-execution-failures.e2e.test.js +0 -235
- package/dist/server/handlers/__tests__/e2e/workflow-execution.e2e.test.js +0 -294
- package/dist/server/handlers/__tests__/e2e/workflow-security.e2e.test.js +0 -311
- package/dist/server/handlers/__tests__/e2e/workflow-security.part2.e2e.test.js +0 -267
- package/dist/server/handlers/__tests__/workflow-cache.test.js +0 -237
- package/dist/server/handlers/analytics-errors-edge.test.js +0 -173
- package/dist/server/handlers/analytics.test.js +0 -280
- package/dist/server/handlers/api-docs-examples-ext.d.ts +0 -9
- package/dist/server/handlers/api-docs-examples-ext.js +0 -278
- package/dist/server/handlers/api-docs-examples-ext.js.map +0 -1
- package/dist/server/handlers/api-docs-examples.d.ts +0 -8
- package/dist/server/handlers/api-docs-examples.js +0 -221
- package/dist/server/handlers/api-docs-examples.js.map +0 -1
- package/dist/server/handlers/api-docs-sections-ext.d.ts +0 -2
- package/dist/server/handlers/api-docs-sections-ext.js +0 -497
- package/dist/server/handlers/api-docs-sections-ext.js.map +0 -1
- package/dist/server/handlers/api-docs-sections.d.ts +0 -21
- package/dist/server/handlers/api-docs-sections.js +0 -293
- package/dist/server/handlers/api-docs-sections.js.map +0 -1
- package/dist/server/handlers/api-keys.part2.test.js +0 -157
- package/dist/server/handlers/api-keys.test.js +0 -161
- package/dist/server/handlers/billing-routes.test.js +0 -123
- package/dist/server/handlers/billing.test.js +0 -215
- package/dist/server/handlers/browser-actions-errors.test.js +0 -94
- package/dist/server/handlers/browser-actions.part2.test.js +0 -190
- package/dist/server/handlers/browser-actions.test.js +0 -190
- package/dist/server/handlers/browser-validation.test.js +0 -257
- package/dist/server/handlers/catalog.test.js +0 -297
- package/dist/server/handlers/comms.test.js +0 -289
- package/dist/server/handlers/creations-advanced-collections.test.js +0 -214
- package/dist/server/handlers/creations-advanced-generate.test.js +0 -142
- package/dist/server/handlers/creations-advanced.test.js +0 -171
- package/dist/server/handlers/creations-collections-preview.test.js +0 -214
- package/dist/server/handlers/creations-crud.test.js +0 -260
- package/dist/server/handlers/creations-mutations.test.js +0 -197
- package/dist/server/handlers/crm.test.js +0 -179
- package/dist/server/handlers/discovery-advertise.test.js +0 -185
- package/dist/server/handlers/discovery-scan.test.js +0 -233
- package/dist/server/handlers/embeddings-embed-search.test.js +0 -196
- package/dist/server/handlers/embeddings-index-delete-stats.test.js +0 -140
- package/dist/server/handlers/embeddings-search.test.js +0 -221
- package/dist/server/handlers/embeddings.test.js +0 -137
- package/dist/server/handlers/enrichment-breach.d.ts +0 -8
- package/dist/server/handlers/enrichment-breach.js +0 -266
- package/dist/server/handlers/enrichment-breach.js.map +0 -1
- package/dist/server/handlers/enrichment-data.d.ts +0 -13
- package/dist/server/handlers/enrichment-data.js +0 -145
- package/dist/server/handlers/enrichment-data.js.map +0 -1
- package/dist/server/handlers/enrichment-mutations.test.js +0 -240
- package/dist/server/handlers/enrichment-queries.test.js +0 -181
- package/dist/server/handlers/enrichment-validation.test.js +0 -177
- package/dist/server/handlers/enrichment-writes.d.ts +0 -16
- package/dist/server/handlers/enrichment-writes.js +0 -226
- package/dist/server/handlers/enrichment-writes.js.map +0 -1
- package/dist/server/handlers/image-gen.test.js +0 -205
- package/dist/server/handlers/inventory.test.js +0 -380
- package/dist/server/handlers/kali-background.test.js +0 -222
- package/dist/server/handlers/kali-errors.test.js +0 -92
- package/dist/server/handlers/kali-validation.test.js +0 -234
- package/dist/server/handlers/llm-providers-actions.test.js +0 -220
- package/dist/server/handlers/llm-providers-anthropic.test.js +0 -239
- package/dist/server/handlers/llm-providers-failover.test.js +0 -232
- package/dist/server/handlers/llm-providers-providers.test.js +0 -300
- package/dist/server/handlers/llm-providers-validation.test.js +0 -239
- package/dist/server/handlers/local-agent-tools.test.js +0 -224
- package/dist/server/handlers/local-agent.test.js +0 -198
- package/dist/server/handlers/local-agent.tools-status.test.js +0 -204
- package/dist/server/handlers/local-agent.validation-exec.test.js +0 -182
- package/dist/server/handlers/meta-ads-audience-rules.test.js +0 -243
- package/dist/server/handlers/meta-ads-audience-targeting.test.js +0 -205
- package/dist/server/handlers/meta-ads-audiences-targeting.test.js +0 -383
- package/dist/server/handlers/meta-ads-crud-ads.test.js +0 -136
- package/dist/server/handlers/meta-ads-crud-campaigns.test.js +0 -189
- package/dist/server/handlers/meta-ads-crud-create.test.js +0 -303
- package/dist/server/handlers/meta-ads-crud-list-update.test.js +0 -259
- package/dist/server/handlers/meta-ads-delete-publish-sync.test.js +0 -282
- package/dist/server/handlers/meta-ads-insights.test.js +0 -80
- package/dist/server/handlers/meta-ads-list-get.test.js +0 -237
- package/dist/server/handlers/meta-ads-publish-delete.test.js +0 -254
- package/dist/server/handlers/meta-ads-publish-helpers.js +0 -117
- package/dist/server/handlers/meta-ads-publish-helpers.js.map +0 -1
- package/dist/server/handlers/meta-ads-publish-sync.test.js +0 -205
- package/dist/server/handlers/meta-ads-publish.test.js +0 -254
- package/dist/server/handlers/meta-ads-sync-insights.test.js +0 -184
- package/dist/server/handlers/meta-ads-update.test.js +0 -117
- package/dist/server/handlers/nodes-channels.test.js +0 -413
- package/dist/server/handlers/nodes-events.test.js +0 -131
- package/dist/server/handlers/nodes-list-delete.test.js +0 -171
- package/dist/server/handlers/nodes-messages-delivery.test.js +0 -208
- package/dist/server/handlers/nodes-messages.test.js +0 -211
- package/dist/server/handlers/nodes-register.test.js +0 -277
- package/dist/server/handlers/nodes.test.js +0 -353
- package/dist/server/handlers/operations.test.js +0 -136
- package/dist/server/handlers/platform-telemetry.test.js +0 -200
- package/dist/server/handlers/platform-websearch.test.js +0 -160
- package/dist/server/handlers/storefront.test.js +0 -329
- package/dist/server/handlers/supply-chain.test.js +0 -347
- package/dist/server/handlers/transcription.test.js +0 -118
- package/dist/server/handlers/video-gen-veo.js +0 -114
- package/dist/server/handlers/video-gen-veo.js.map +0 -1
- package/dist/server/handlers/video-gen.test.js +0 -146
- package/dist/server/handlers/voice.test.js +0 -153
- package/dist/server/handlers/workflow-steps.test.js +0 -330
- package/dist/server/handlers/workflows-extras.test.js +0 -65
- package/dist/server/handlers/workflows.part2.test.js +0 -170
- package/dist/server/handlers/workflows.test.js +0 -281
- package/dist/server/lib/__tests__/batch-client-conversion-jsonl.test.js +0 -171
- package/dist/server/lib/__tests__/batch-client-polling.test.js +0 -292
- package/dist/server/lib/__tests__/batch-client-queue.test.js +0 -270
- package/dist/server/lib/__tests__/clickhouse-buffer.test.js +0 -236
- package/dist/server/lib/__tests__/code-worker-edge-cases.test.js +0 -118
- package/dist/server/lib/__tests__/code-worker-pool-execute.test.js +0 -193
- package/dist/server/lib/__tests__/code-worker-pool-execution.test.js +0 -165
- package/dist/server/lib/__tests__/code-worker-pool-init.test.js +0 -131
- package/dist/server/lib/__tests__/code-worker-pool.test.js +0 -194
- package/dist/server/lib/__tests__/code-worker-sandbox-ops.test.js +0 -123
- package/dist/server/lib/__tests__/code-worker-sandbox.test.js +0 -217
- package/dist/server/lib/__tests__/code-worker.test.js +0 -179
- package/dist/server/lib/__tests__/compaction-service-generate.test.js +0 -229
- package/dist/server/lib/__tests__/compaction-service.test.js +0 -319
- package/dist/server/lib/__tests__/otel.test.js +0 -146
- package/dist/server/lib/__tests__/prompt-sanitizer-validation.test.js +0 -165
- package/dist/server/lib/__tests__/prompt-sanitizer.sanitize.test.js +0 -343
- package/dist/server/lib/__tests__/prompt-sanitizer.test.js +0 -328
- package/dist/server/lib/__tests__/prompt-sanitizer.validate-tool.test.js +0 -145
- package/dist/server/lib/__tests__/provider-capabilities.test.js +0 -263
- package/dist/server/lib/__tests__/provider-failover-routing.test.js +0 -145
- package/dist/server/lib/__tests__/provider-failover-state.test.js +0 -131
- package/dist/server/lib/__tests__/rate-limiter-budgets.test.js +0 -216
- package/dist/server/lib/__tests__/rate-limiter.budgets-tools.test.js +0 -113
- package/dist/server/lib/__tests__/rate-limiter.check-request.test.js +0 -141
- package/dist/server/lib/__tests__/rate-limiter.stats-lifecycle.test.js +0 -135
- package/dist/server/lib/__tests__/rate-limiter.test.js +0 -207
- package/dist/server/lib/__tests__/server-agent-loop-abort-conditions.test.js +0 -544
- package/dist/server/lib/__tests__/server-agent-loop-abort.part2.test.js +0 -504
- package/dist/server/lib/__tests__/server-agent-loop-abort.test.js +0 -396
- package/dist/server/lib/__tests__/server-agent-loop-compaction.test.js +0 -397
- package/dist/server/lib/__tests__/server-agent-loop-failover.test.js +0 -356
- package/dist/server/lib/__tests__/server-agent-loop-features-caching.test.js +0 -519
- package/dist/server/lib/__tests__/server-agent-loop-features-edges.test.js +0 -512
- package/dist/server/lib/__tests__/server-subagent-bailout.test.js +0 -194
- package/dist/server/lib/__tests__/server-subagent-basics.test.js +0 -348
- package/dist/server/lib/__tests__/server-subagent-errors-abort.test.js +0 -319
- package/dist/server/lib/__tests__/server-subagent-errors-progress.test.js +0 -253
- package/dist/server/lib/__tests__/server-subagent-errors.part2.test.js +0 -253
- package/dist/server/lib/__tests__/server-subagent-errors.test.js +0 -319
- package/dist/server/lib/__tests__/session-checkpoint-load.test.js +0 -275
- package/dist/server/lib/__tests__/session-checkpoint-save.test.js +0 -159
- package/dist/server/lib/__tests__/ssrf-guard.test.js +0 -93
- package/dist/server/lib/__tests__/supabase-client.test.js +0 -111
- package/dist/server/lib/__tests__/template-resolver.test.js +0 -317
- package/dist/server/lib/__tests__/utils-timeout.test.js +0 -49
- package/dist/server/lib/__tests__/utils.test.js +0 -322
- package/dist/server/providers/__tests__/anthropic-adapter.test.js +0 -228
- package/dist/server/providers/__tests__/anthropic-betas-toolchoice.test.js +0 -257
- package/dist/server/providers/__tests__/anthropic-errors.test.js +0 -262
- package/dist/server/providers/__tests__/anthropic-stream-core.test.js +0 -275
- package/dist/server/providers/__tests__/anthropic-streaming-betas.test.js +0 -247
- package/dist/server/providers/__tests__/anthropic-streaming-core.test.js +0 -275
- package/dist/server/providers/__tests__/bedrock-config.test.js +0 -177
- package/dist/server/providers/__tests__/bedrock-stream-behavior-streaming.test.js +0 -272
- package/dist/server/providers/__tests__/bedrock-stream-behavior-toolchoice.test.js +0 -214
- package/dist/server/providers/__tests__/bedrock-stream-behavior.part2.test.js +0 -165
- package/dist/server/providers/__tests__/bedrock-stream-behavior.test.js +0 -309
- package/dist/server/providers/__tests__/bedrock-stream-body-credentials.test.js +0 -170
- package/dist/server/providers/__tests__/bedrock-stream-body-extras.test.js +0 -183
- package/dist/server/providers/__tests__/bedrock-stream-body-request.test.js +0 -305
- package/dist/server/providers/__tests__/bedrock-stream-body.part2.test.js +0 -305
- package/dist/server/providers/__tests__/bedrock-stream-body.test.js +0 -175
- package/dist/server/providers/__tests__/bedrock-stream-errors.test.js +0 -165
- package/dist/server/providers/__tests__/gemini-config-methods.test.js +0 -182
- package/dist/server/providers/__tests__/gemini-config-streaming.test.js +0 -257
- package/dist/server/providers/__tests__/gemini-conversion-messages.test.js +0 -247
- package/dist/server/providers/__tests__/gemini-conversion-schema.test.js +0 -365
- package/dist/server/providers/__tests__/gemini-tools-choice.test.js +0 -221
- package/dist/server/providers/__tests__/gemini-tools-fn.test.js +0 -252
- package/dist/server/providers/__tests__/openai-config.test.js +0 -194
- package/dist/server/providers/__tests__/openai-conversion.test.js +0 -276
- package/dist/server/providers/__tests__/openai-messages.test.js +0 -261
- package/dist/server/providers/__tests__/openai-streaming.test.js +0 -394
- package/dist/server/providers/__tests__/openai-tools-cache.test.js +0 -227
- package/dist/server/providers/__tests__/registry.test.js +0 -183
- package/dist/server/providers/__tests__/shared.test.js +0 -297
- package/dist/shared/agent-core-config.test.js +0 -132
- package/dist/shared/agent-core-context-thinking.test.js +0 -293
- package/dist/shared/agent-core-loop-calls.test.js +0 -174
- package/dist/shared/agent-core-loop-detector-bail.test.js +0 -201
- package/dist/shared/agent-core-loop-detector.test.js +0 -195
- package/dist/shared/agent-core-loop-errors.test.js +0 -258
- package/dist/shared/agent-core-pricing.test.js +0 -191
- package/dist/shared/agent-core-sanitize-retry.test.js +0 -129
- package/dist/shared/api-client-build-request.test.js +0 -228
- package/dist/shared/api-client-build-system-caching.test.js +0 -107
- package/dist/shared/api-client-build.test.js +0 -223
- package/dist/shared/api-client-config.d.ts +0 -21
- package/dist/shared/api-client-helpers.d.ts +0 -57
- package/dist/shared/api-client-helpers.test.js +0 -261
- package/dist/shared/api-client-proxy-happy.test.js +0 -255
- package/dist/shared/api-client-proxy-retry.test.js +0 -307
- package/dist/shared/api-client-proxy.d.ts +0 -26
- package/dist/shared/api-client-proxy.test.js +0 -255
- package/dist/shared/api-client-retry.test.js +0 -307
- package/dist/shared/api-client-system-trimming.test.js +0 -261
- package/dist/shared/api-client-trimming.d.ts +0 -36
- package/dist/shared/api-client.test.js +0 -228
- package/dist/shared/compaction-thinking.test.js +0 -315
- package/dist/shared/compaction-trimming.test.js +0 -223
- package/dist/shared/sse-parser-callbacks.test.js +0 -422
- package/dist/shared/sse-parser-collect.test.js +0 -252
- package/dist/shared/sse-parser-e2e.test.js +0 -558
- package/dist/shared/sse-parser-parse.test.js +0 -253
- package/dist/shared/tool-dispatch-advanced-batch-build.test.js +0 -405
- package/dist/shared/tool-dispatch-advanced.test.js +0 -320
- package/dist/shared/tool-dispatch-basic.test.js +0 -278
- package/dist/shared/tool-dispatch-content.d.ts +0 -14
- package/dist/shared/tool-dispatch-parallel.test.js +0 -378
- package/dist/webchat/__tests__/widget-messaging.test.js +0 -323
- package/dist/webchat/__tests__/widget.test.js +0 -273
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { createLogger } from "./lib/logger.js";
|
|
6
6
|
import { getServiceClient } from "./lib/supabase-client.js";
|
|
7
7
|
import { verifyGuestApprovalSignature, executeInlineChain } from "./handlers/workflows.js";
|
|
8
|
-
import { jsonResponse, readBody, safeCompare } from "./server-helpers.js";
|
|
8
|
+
import { jsonResponse, readBody, safeCompare, getClientIp } from "./server-helpers.js";
|
|
9
9
|
import { sendIpRateLimit } from "./server-rate-limit.js";
|
|
10
10
|
const log = createLogger("server-routes-approvals");
|
|
11
11
|
const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
@@ -36,7 +36,7 @@ export async function handleGuestApproval(req, res, ctx) {
|
|
|
36
36
|
} = ctx;
|
|
37
37
|
const guestApprovalMatch = pathname.match(/^\/approvals\/guest\/([a-f0-9-]+)$/);
|
|
38
38
|
if (!(guestApprovalMatch && req.method === "GET")) return false;
|
|
39
|
-
const clientIp = req
|
|
39
|
+
const clientIp = getClientIp(req);
|
|
40
40
|
if (sendIpRateLimit(res, clientIp, corsHeaders)) return true;
|
|
41
41
|
const stepRunId = guestApprovalMatch[1];
|
|
42
42
|
const urlParams = new URL(req.url || "", `http://${req.headers.host}`).searchParams;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-routes-approvals.js","names":["createLogger","getServiceClient","verifyGuestApprovalSignature","executeInlineChain","jsonResponse","readBody","safeCompare","sendIpRateLimit","log","SUPABASE_SERVICE_ROLE_KEY","process","env","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","getToken","req","authHeader","headers","authorization","startsWith","substring","isInternalAuth","token","handleGuestApproval","res","ctx","pathname","corsHeaders","guestApprovalMatch","match","method","clientIp","toString","split","trim","socket","remoteAddress","stepRunId","urlParams","URL","url","host","searchParams","action","get","expires","sig","error","Date","guestSupabase","data","approval","from","select","eq","limit","length","status","isApprove","guestResult","guestErr","rpc","p_approval_id","id","p_store_id","store_id","p_response","p_response_data","guest","p_responded_by","success","message","run_id","err","runId","writeHead","end","handleApprovalRespond","approvalMatch","approvalId","isInternal","supabase","userId","user","authUser","authError","auth","getUser","rawBody","body","JSON","parse","single","approvalMembership","result","response_data","responded_by"],"sources":["../../src/server/server-routes-approvals.ts"],"sourcesContent":["// server/server-routes-approvals.ts — Approval route handlers\n// Guest approval GET and authenticated approval respond POST\n// Extracted from index.ts for domain-based modularity.\n\nimport http from \"node:http\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { verifyGuestApprovalSignature, executeInlineChain } from \"./handlers/workflows.js\";\nimport { jsonResponse, readBody, safeCompare, type ServerContext } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\n\nconst log = createLogger(\"server-routes-approvals\");\n\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction getToken(req: http.IncomingMessage): string {\n const authHeader = req.headers.authorization;\n return authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n}\n\nfunction isInternalAuth(token: string): boolean {\n return safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n}\n\n// ============================================================================\n// GET /approvals/guest/:id — Guest approval via signed URL (no auth required)\n// GET /approvals/guest/:id?action=approve&expires=...&sig=...\n// ============================================================================\n\nexport async function handleGuestApproval(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n const guestApprovalMatch = pathname.match(/^\\/approvals\\/guest\\/([a-f0-9-]+)$/);\n if (!(guestApprovalMatch && req.method === \"GET\")) return false;\n\n const clientIp = req.headers[\"x-forwarded-for\"]?.toString().split(\",\")[0]?.trim() || req.socket.remoteAddress || \"unknown\";\n if (sendIpRateLimit(res, clientIp, corsHeaders)) return true;\n\n const stepRunId = guestApprovalMatch[1];\n const urlParams = new URL(req.url || \"\", `http://${req.headers.host}`).searchParams;\n const action = urlParams.get(\"action\") || \"\";\n const expires = urlParams.get(\"expires\") || \"\";\n const sig = urlParams.get(\"sig\") || \"\";\n\n if (!action || !expires || !sig) {\n jsonResponse(res, 400, { error: \"Missing action, expires, or sig parameter\" }, corsHeaders);\n return true;\n }\n if (new Date(expires) < new Date()) {\n jsonResponse(res, 410, { error: \"This approval link has expired\" }, corsHeaders);\n return true;\n }\n if (!verifyGuestApprovalSignature(stepRunId, action, expires, sig)) {\n jsonResponse(res, 403, { error: \"Invalid signature\" }, corsHeaders);\n return true;\n }\n\n const guestSupabase = getServiceClient();\n\n const { data: approval } = await guestSupabase.from(\"workflow_approval_requests\")\n .select(\"id, store_id, run_id, status\").eq(\"step_run_id\", stepRunId).limit(1);\n if (!approval?.length) {\n jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders);\n return true;\n }\n if (approval[0].status !== \"pending\") {\n jsonResponse(res, 409, { error: `Approval already ${approval[0].status}` }, corsHeaders);\n return true;\n }\n\n const isApprove = action === \"approve\" || action === \"approved\";\n const { data: guestResult, error: guestErr } = await guestSupabase.rpc(\"respond_to_approval\", {\n p_approval_id: approval[0].id,\n p_store_id: approval[0].store_id,\n p_response: isApprove ? \"approved\" : \"rejected\",\n p_response_data: { guest: true, action },\n p_responded_by: null,\n });\n\n if (guestErr) {\n jsonResponse(res, 500, { success: false, error: guestErr.message }, corsHeaders);\n return true;\n }\n\n if (guestResult?.success && approval[0].run_id) {\n try {\n await executeInlineChain(guestSupabase, approval[0].run_id);\n } catch (err) {\n log.error({ err: (err as Error).message, runId: approval[0].run_id }, \"inline chain failed after guest approval\");\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\", ...corsHeaders });\n res.end(`<!DOCTYPE html><html><body style=\"font-family:system-ui;text-align:center;padding:40px\">\n <h2>${isApprove ? \"Approved\" : \"Rejected\"}</h2>\n <p>Your response has been recorded. You can close this window.</p>\n </body></html>`);\n return true;\n}\n\n// ============================================================================\n// POST /approvals/:id/respond — Authenticated approval response\n// ============================================================================\n\nexport async function handleApprovalRespond(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n const approvalMatch = pathname.match(/^\\/approvals\\/([a-f0-9-]+)\\/respond$/);\n if (!approvalMatch || req.method !== \"POST\") return false;\n\n const approvalId = approvalMatch[1];\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n\n if (!isInternal && !token) {\n jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders);\n return true;\n }\n\n const supabase = getServiceClient();\n let userId: string | null = null;\n\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) {\n jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders);\n return true;\n }\n userId = authUser.id;\n }\n\n let rawBody: string;\n try { rawBody = await readBody(req); } catch {\n jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders);\n return true;\n }\n\n let body: any;\n try { body = JSON.parse(rawBody); } catch {\n jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders);\n return true;\n }\n if (!body.status) {\n jsonResponse(res, 400, { error: \"status required (approved/rejected)\" }, corsHeaders);\n return true;\n }\n\n // Get store_id from approval\n const { data: approval } = await supabase.from(\"workflow_approval_requests\")\n .select(\"store_id, run_id\").eq(\"id\", approvalId).single();\n if (!approval) {\n jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders);\n return true;\n }\n\n // P1 FIX: Verify user has access to the approval's store\n if (!isInternal && userId) {\n const { data: approvalMembership } = await supabase.from(\"store_members\")\n .select(\"id\").eq(\"store_id\", approval.store_id).eq(\"user_id\", userId).single();\n if (!approvalMembership) {\n jsonResponse(res, 403, { error: \"Not authorized to respond to this approval\" }, corsHeaders);\n return true;\n }\n }\n\n const { data: result, error } = await supabase.rpc(\"respond_to_approval\", {\n p_approval_id: approvalId,\n p_store_id: approval.store_id,\n p_response: body.status,\n p_response_data: body.response_data || {},\n p_responded_by: userId || body.responded_by || null,\n });\n\n if (error) {\n jsonResponse(res, 500, { success: false, error: error.message }, corsHeaders);\n return true;\n }\n\n // Inline resume — execute next step immediately\n if (result?.success && approval.run_id) {\n try {\n await executeInlineChain(supabase, approval.run_id);\n } catch (err) {\n log.error({ err: (err as Error).message }, \"inline chain failed after approval\");\n }\n }\n\n jsonResponse(res, result?.success ? 200 : 422, result, corsHeaders);\n return true;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"server-routes-approvals.js","names":["createLogger","getServiceClient","verifyGuestApprovalSignature","executeInlineChain","jsonResponse","readBody","safeCompare","getClientIp","sendIpRateLimit","log","SUPABASE_SERVICE_ROLE_KEY","process","env","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","getToken","req","authHeader","headers","authorization","startsWith","substring","isInternalAuth","token","handleGuestApproval","res","ctx","pathname","corsHeaders","guestApprovalMatch","match","method","clientIp","stepRunId","urlParams","URL","url","host","searchParams","action","get","expires","sig","error","Date","guestSupabase","data","approval","from","select","eq","limit","length","status","isApprove","guestResult","guestErr","rpc","p_approval_id","id","p_store_id","store_id","p_response","p_response_data","guest","p_responded_by","success","message","run_id","err","runId","writeHead","end","handleApprovalRespond","approvalMatch","approvalId","isInternal","supabase","userId","user","authUser","authError","auth","getUser","rawBody","body","JSON","parse","single","approvalMembership","result","response_data","responded_by"],"sources":["../../src/server/server-routes-approvals.ts"],"sourcesContent":["// server/server-routes-approvals.ts — Approval route handlers\n// Guest approval GET and authenticated approval respond POST\n// Extracted from index.ts for domain-based modularity.\n\nimport http from \"node:http\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { verifyGuestApprovalSignature, executeInlineChain } from \"./handlers/workflows.js\";\nimport { jsonResponse, readBody, safeCompare, getClientIp, type ServerContext } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\n\nconst log = createLogger(\"server-routes-approvals\");\n\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction getToken(req: http.IncomingMessage): string {\n const authHeader = req.headers.authorization;\n return authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n}\n\nfunction isInternalAuth(token: string): boolean {\n return safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n}\n\n// ============================================================================\n// GET /approvals/guest/:id — Guest approval via signed URL (no auth required)\n// GET /approvals/guest/:id?action=approve&expires=...&sig=...\n// ============================================================================\n\nexport async function handleGuestApproval(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n const guestApprovalMatch = pathname.match(/^\\/approvals\\/guest\\/([a-f0-9-]+)$/);\n if (!(guestApprovalMatch && req.method === \"GET\")) return false;\n\n const clientIp = getClientIp(req);\n if (sendIpRateLimit(res, clientIp, corsHeaders)) return true;\n\n const stepRunId = guestApprovalMatch[1];\n const urlParams = new URL(req.url || \"\", `http://${req.headers.host}`).searchParams;\n const action = urlParams.get(\"action\") || \"\";\n const expires = urlParams.get(\"expires\") || \"\";\n const sig = urlParams.get(\"sig\") || \"\";\n\n if (!action || !expires || !sig) {\n jsonResponse(res, 400, { error: \"Missing action, expires, or sig parameter\" }, corsHeaders);\n return true;\n }\n if (new Date(expires) < new Date()) {\n jsonResponse(res, 410, { error: \"This approval link has expired\" }, corsHeaders);\n return true;\n }\n if (!verifyGuestApprovalSignature(stepRunId, action, expires, sig)) {\n jsonResponse(res, 403, { error: \"Invalid signature\" }, corsHeaders);\n return true;\n }\n\n const guestSupabase = getServiceClient();\n\n const { data: approval } = await guestSupabase.from(\"workflow_approval_requests\")\n .select(\"id, store_id, run_id, status\").eq(\"step_run_id\", stepRunId).limit(1);\n if (!approval?.length) {\n jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders);\n return true;\n }\n if (approval[0].status !== \"pending\") {\n jsonResponse(res, 409, { error: `Approval already ${approval[0].status}` }, corsHeaders);\n return true;\n }\n\n const isApprove = action === \"approve\" || action === \"approved\";\n const { data: guestResult, error: guestErr } = await guestSupabase.rpc(\"respond_to_approval\", {\n p_approval_id: approval[0].id,\n p_store_id: approval[0].store_id,\n p_response: isApprove ? \"approved\" : \"rejected\",\n p_response_data: { guest: true, action },\n p_responded_by: null,\n });\n\n if (guestErr) {\n jsonResponse(res, 500, { success: false, error: guestErr.message }, corsHeaders);\n return true;\n }\n\n if (guestResult?.success && approval[0].run_id) {\n try {\n await executeInlineChain(guestSupabase, approval[0].run_id);\n } catch (err) {\n log.error({ err: (err as Error).message, runId: approval[0].run_id }, \"inline chain failed after guest approval\");\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\", ...corsHeaders });\n res.end(`<!DOCTYPE html><html><body style=\"font-family:system-ui;text-align:center;padding:40px\">\n <h2>${isApprove ? \"Approved\" : \"Rejected\"}</h2>\n <p>Your response has been recorded. You can close this window.</p>\n </body></html>`);\n return true;\n}\n\n// ============================================================================\n// POST /approvals/:id/respond — Authenticated approval response\n// ============================================================================\n\nexport async function handleApprovalRespond(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n const approvalMatch = pathname.match(/^\\/approvals\\/([a-f0-9-]+)\\/respond$/);\n if (!approvalMatch || req.method !== \"POST\") return false;\n\n const approvalId = approvalMatch[1];\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n\n if (!isInternal && !token) {\n jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders);\n return true;\n }\n\n const supabase = getServiceClient();\n let userId: string | null = null;\n\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) {\n jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders);\n return true;\n }\n userId = authUser.id;\n }\n\n let rawBody: string;\n try { rawBody = await readBody(req); } catch {\n jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders);\n return true;\n }\n\n let body: any;\n try { body = JSON.parse(rawBody); } catch {\n jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders);\n return true;\n }\n if (!body.status) {\n jsonResponse(res, 400, { error: \"status required (approved/rejected)\" }, corsHeaders);\n return true;\n }\n\n // Get store_id from approval\n const { data: approval } = await supabase.from(\"workflow_approval_requests\")\n .select(\"store_id, run_id\").eq(\"id\", approvalId).single();\n if (!approval) {\n jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders);\n return true;\n }\n\n // P1 FIX: Verify user has access to the approval's store\n if (!isInternal && userId) {\n const { data: approvalMembership } = await supabase.from(\"store_members\")\n .select(\"id\").eq(\"store_id\", approval.store_id).eq(\"user_id\", userId).single();\n if (!approvalMembership) {\n jsonResponse(res, 403, { error: \"Not authorized to respond to this approval\" }, corsHeaders);\n return true;\n }\n }\n\n const { data: result, error } = await supabase.rpc(\"respond_to_approval\", {\n p_approval_id: approvalId,\n p_store_id: approval.store_id,\n p_response: body.status,\n p_response_data: body.response_data || {},\n p_responded_by: userId || body.responded_by || null,\n });\n\n if (error) {\n jsonResponse(res, 500, { success: false, error: error.message }, corsHeaders);\n return true;\n }\n\n // Inline resume — execute next step immediately\n if (result?.success && approval.run_id) {\n try {\n await executeInlineChain(supabase, approval.run_id);\n } catch (err) {\n log.error({ err: (err as Error).message }, \"inline chain failed after approval\");\n }\n }\n\n jsonResponse(res, result?.success ? 200 : 422, result, corsHeaders);\n return true;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -7,7 +7,7 @@ import { sanitizeError } from "../shared/agent-core.js";
|
|
|
7
7
|
import { getServiceClient } from "./lib/supabase-client.js";
|
|
8
8
|
import { loadCheckpoint } from "./lib/session-checkpoint.js";
|
|
9
9
|
import { processWorkflowSteps, handleWebhookIngestion, executeInlineChain } from "./handlers/workflows.js";
|
|
10
|
-
import { jsonResponse, readBody, safeCompare } from "./server-helpers.js";
|
|
10
|
+
import { jsonResponse, readBody, safeCompare, getClientIp } from "./server-helpers.js";
|
|
11
11
|
import { sendIpRateLimit } from "./server-rate-limit.js";
|
|
12
12
|
const log = createLogger("server-routes-auth");
|
|
13
13
|
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
|
|
@@ -272,7 +272,7 @@ export async function handleAuthenticatedRoutes(req, res, pathname, url, corsHea
|
|
|
272
272
|
// Webhook ingestion
|
|
273
273
|
const webhookMatch = pathname.match(/^\/webhooks\/([a-zA-Z0-9_-]+)$/);
|
|
274
274
|
if (webhookMatch) {
|
|
275
|
-
const whClientIp = req
|
|
275
|
+
const whClientIp = getClientIp(req);
|
|
276
276
|
if (sendIpRateLimit(res, whClientIp, corsHeaders)) return true;
|
|
277
277
|
const slug = webhookMatch[1];
|
|
278
278
|
let rawBody;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-routes-auth.js","names":["createLogger","sanitizeError","getServiceClient","loadCheckpoint","processWorkflowSteps","handleWebhookIngestion","executeInlineChain","jsonResponse","readBody","safeCompare","sendIpRateLimit","log","ANTHROPIC_API_KEY","process","env","SUPABASE_SERVICE_ROLE_KEY","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","handleAuthenticatedRoutes","req","res","pathname","url","corsHeaders","method","error","resumeMatch","match","convId","token","getToken","isInternal","isInternalAuth","supabase","data","user","authUser","authError","auth","getUser","checkpoint","parsedMessages","JSON","parse","messages","success","conversation_id","turn","tokens_used","cost_so_far","tools_used","checkpointed_at","created_at","approvalMatch","approvalId","userId","id","rawBody","body","status","approval","from","select","eq","single","approvalMembership","store_id","result","rpc","p_approval_id","p_store_id","p_response","p_response_data","response_data","p_responded_by","responded_by","message","run_id","err","waitpointMatch","wpToken","authToken","wp","Date","expires_at","update","completion_data","completed_at","toISOString","input","waitpoint_completed","waitpoint_data","step_run_id","runId","webhookMatch","whClientIp","headers","toString","split","trim","socket","remoteAddress","slug","k","v","Object","entries","event_type","idempotency_key","existing","limit","length","event_id","deduplicated","eventId","fireErr","p_event_type","p_event_payload","payload","p_source","source","batch_size","workflow_id","wfOwner","wfOwnerErr","p_workflow_id","p_trigger_type","trigger_type","p_trigger_payload","trigger_payload","p_idempotency_key","wf","published_version_id","version_id","headersSent","authHeader","authorization","startsWith","substring"],"sources":["../../src/server/server-routes-auth.ts"],"sourcesContent":["// server/server-routes-auth.ts — Authenticated POST route handlers\n// Resume, approvals, waitpoints, webhooks, events, workflows, tool exec, telemetry, etc.\n// Extracted from index.ts for modularity.\n\nimport http from \"node:http\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { sanitizeError } from \"../shared/agent-core.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { handleProxy } from \"./proxy-handlers.js\";\nimport { handleTranscribe } from \"./handlers/transcription.js\";\nimport { generateCompaction } from \"./lib/compaction-service.js\";\nimport { loadCheckpoint } from \"./lib/session-checkpoint.js\";\nimport { rateLimiter } from \"./lib/rate-limiter.js\";\nimport { sanitizeAndLog } from \"./lib/prompt-sanitizer.js\";\nimport {\n processWorkflowSteps, handleWebhookIngestion, executeInlineChain,\n} from \"./handlers/workflows.js\";\nimport {\n loadUserTools, executeTool, type UserToolRow,\n} from \"./tool-router.js\";\nimport { queueSpan, auditRowToSpan } from \"./lib/clickhouse-buffer.js\";\nimport { jsonResponse, readBody, safeCompare } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\nimport { resolveAndValidateStoreId } from \"./server-store.js\";\nimport { handleAgentChat } from \"./server-chat.js\";\n\nconst log = createLogger(\"server-routes-auth\");\n\nconst ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY!;\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n/**\n * Handle all authenticated POST/PUT/DELETE routes.\n * Called after public routes have been checked.\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleAuthenticatedRoutes(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, url: URL, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n if (req.method !== \"POST\" && req.method !== \"DELETE\" && req.method !== \"PUT\") {\n jsonResponse(res, 405, { error: \"Method not allowed\" }, corsHeaders);\n return true;\n }\n\n try {\n // Resume conversation from checkpoint\n const resumeMatch = pathname.match(/^\\/conversations\\/([a-f0-9-]+)\\/resume$/);\n if (resumeMatch && req.method === \"POST\") {\n const convId = resumeMatch[1];\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n }\n try { await readBody(req); } catch { /* body not needed */ }\n const checkpoint = await loadCheckpoint(supabase, convId);\n if (!checkpoint) { jsonResponse(res, 404, { error: \"No checkpoint found for this conversation\" }, corsHeaders); return true; }\n let parsedMessages: unknown[];\n try { parsedMessages = JSON.parse(checkpoint.messages); } catch { jsonResponse(res, 422, { error: \"Checkpoint messages corrupted\" }, corsHeaders); return true; }\n jsonResponse(res, 200, { success: true, conversation_id: checkpoint.conversation_id, turn: checkpoint.turn, messages: parsedMessages, tokens_used: checkpoint.tokens_used, cost_so_far: checkpoint.cost_so_far, tools_used: checkpoint.tools_used, checkpointed_at: checkpoint.created_at }, corsHeaders);\n return true;\n }\n\n // Approval response\n const approvalMatch = pathname.match(/^\\/approvals\\/([a-f0-9-]+)\\/respond$/);\n if (approvalMatch) {\n const approvalId = approvalMatch[1];\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n let userId: string | null = null;\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n userId = authUser.id;\n }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n if (!body.status) { jsonResponse(res, 400, { error: \"status required (approved/rejected)\" }, corsHeaders); return true; }\n const { data: approval } = await supabase.from(\"workflow_approval_requests\").select(\"store_id, run_id\").eq(\"id\", approvalId).single();\n if (!approval) { jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders); return true; }\n if (!isInternal && userId) {\n const { data: approvalMembership } = await supabase.from(\"store_members\").select(\"id\").eq(\"store_id\", approval.store_id).eq(\"user_id\", userId).single();\n if (!approvalMembership) { jsonResponse(res, 403, { error: \"Not authorized to respond to this approval\" }, corsHeaders); return true; }\n }\n const { data: result, error } = await supabase.rpc(\"respond_to_approval\", { p_approval_id: approvalId, p_store_id: approval.store_id, p_response: body.status, p_response_data: body.response_data || {}, p_responded_by: userId || body.responded_by || null });\n if (error) { jsonResponse(res, 500, { success: false, error: error.message }, corsHeaders); return true; }\n if (result?.success && approval.run_id) { try { await executeInlineChain(supabase, approval.run_id); } catch (err) { log.error({ err: (err as Error).message }, \"inline chain failed after approval\"); } }\n jsonResponse(res, result?.success ? 200 : 422, result, corsHeaders);\n return true;\n }\n\n // Waitpoint completion\n const waitpointMatch = pathname.match(/^\\/waitpoints\\/([a-f0-9-]+)\\/complete$/);\n if (waitpointMatch) {\n const wpToken = waitpointMatch[1];\n const authToken = getToken(req);\n const isInternal = isInternalAuth(authToken);\n if (!isInternal && !authToken) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n const { data: wp } = await supabase.from(\"waitpoint_tokens\").select(\"id, run_id, step_run_id, store_id, expires_at, status\").eq(\"token\", wpToken).single();\n if (!wp) { jsonResponse(res, 404, { error: \"Waitpoint token not found\" }, corsHeaders); return true; }\n if (wp.status === \"completed\") { jsonResponse(res, 409, { error: \"Waitpoint already completed\" }, corsHeaders); return true; }\n if (new Date(wp.expires_at) < new Date()) { jsonResponse(res, 410, { error: \"Waitpoint expired\" }, corsHeaders); return true; }\n await supabase.from(\"waitpoint_tokens\").update({ status: \"completed\", completion_data: body.data || {}, completed_at: new Date().toISOString() }).eq(\"id\", wp.id);\n await supabase.from(\"workflow_step_runs\").update({ status: \"pending\", input: { waitpoint_completed: true, waitpoint_data: body.data || {} } }).eq(\"id\", wp.step_run_id).eq(\"status\", \"waiting\");\n try { await executeInlineChain(supabase, wp.run_id); } catch (err) { log.error({ err: (err as Error).message, runId: wp.run_id }, \"inline chain failed after waitpoint\"); }\n jsonResponse(res, 200, { success: true, run_id: wp.run_id }, corsHeaders);\n return true;\n }\n\n // Webhook ingestion\n const webhookMatch = pathname.match(/^\\/webhooks\\/([a-zA-Z0-9_-]+)$/);\n if (webhookMatch) {\n const whClientIp = req.headers[\"x-forwarded-for\"]?.toString().split(\",\")[0]?.trim() || req.socket.remoteAddress || \"unknown\";\n if (sendIpRateLimit(res, whClientIp, corsHeaders)) return true;\n const slug = webhookMatch[1];\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(req.headers)) { if (typeof v === \"string\") headers[k] = v; }\n const result = await handleWebhookIngestion(supabase, slug, rawBody, headers);\n if (result.body.run_id && result.status === 200) {\n try { await executeInlineChain(supabase, result.body.run_id as string); } catch (err) { log.error({ err: (err as Error).message }, \"webhook inline chain error\"); }\n }\n jsonResponse(res, result.status, result.body, corsHeaders);\n return true;\n }\n\n // Fire event\n if (pathname === \"/events\") {\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n if (!body.store_id || !body.event_type) { jsonResponse(res, 400, { error: \"store_id and event_type required\" }, corsHeaders); return true; }\n if (body.idempotency_key) {\n const { data: existing } = await supabase.from(\"workflow_events\").select(\"id\").eq(\"idempotency_key\", body.idempotency_key).limit(1);\n if (existing && existing.length > 0) { jsonResponse(res, 200, { success: true, event_id: existing[0].id, deduplicated: true }, corsHeaders); return true; }\n }\n const { data: eventId, error: fireErr } = await supabase.rpc(\"fire_event\", { p_store_id: body.store_id, p_event_type: body.event_type, p_event_payload: body.payload || {}, p_source: body.source || \"api\" });\n if (fireErr) jsonResponse(res, 500, { success: false, error: fireErr.message }, corsHeaders);\n else jsonResponse(res, 200, { success: true, event_id: eventId }, corsHeaders);\n return true;\n }\n\n // Workflow process (internal)\n if (pathname === \"/workflows/process\") {\n const token = getToken(req);\n if (!FLY_INTERNAL_SECRET || (!safeCompare(token, FLY_INTERNAL_SECRET) && !safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) && !safeCompare(token, SERVICE_ROLE_JWT))) { jsonResponse(res, 401, { error: \"Unauthorized\" }, corsHeaders); return true; }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { rawBody = \"{}\"; }\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n const result = await processWorkflowSteps(supabase, body.batch_size || 10);\n jsonResponse(res, 200, { success: true, ...result }, corsHeaders);\n return true;\n }\n\n // Start workflow run\n if (pathname === \"/workflows/start\") {\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n if (body.workflow_id && body.store_id) {\n const { data: wfOwner, error: wfOwnerErr } = await supabase.from(\"workflows\").select(\"id\").eq(\"id\", body.workflow_id).eq(\"store_id\", body.store_id).single();\n if (wfOwnerErr || !wfOwner) { jsonResponse(res, 403, { error: \"Workflow does not belong to this store\" }, corsHeaders); return true; }\n }\n const { data, error } = await supabase.rpc(\"start_workflow_run\", { p_workflow_id: body.workflow_id, p_store_id: body.store_id, p_trigger_type: body.trigger_type || \"api\", p_trigger_payload: body.trigger_payload || {}, p_idempotency_key: body.idempotency_key || null });\n if (error) { jsonResponse(res, 500, { success: false, error: error.message }, corsHeaders); }\n else {\n if (data?.success && data.run_id && !data.deduplicated) {\n try {\n const { data: wf } = await supabase.from(\"workflows\").select(\"published_version_id\").eq(\"id\", body.workflow_id).single();\n if (wf?.published_version_id) await supabase.from(\"workflow_runs\").update({ version_id: wf.published_version_id }).eq(\"id\", data.run_id);\n await executeInlineChain(supabase, data.run_id);\n } catch (err) { log.error({ err: (err as Error).message }, \"start-inline chain error\"); }\n }\n jsonResponse(res, data?.success ? 200 : 422, data, corsHeaders);\n }\n return true;\n }\n\n // If none of the above matched, return false — caller handles auth gate + mode dispatch\n return false;\n } catch (err) {\n if (!res.headersSent) jsonResponse(res, 500, { error: sanitizeError(err) }, corsHeaders);\n return true;\n }\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction getToken(req: http.IncomingMessage): string {\n const authHeader = req.headers.authorization;\n return authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n}\n\nfunction isInternalAuth(token: string): boolean {\n return safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"server-routes-auth.js","names":["createLogger","sanitizeError","getServiceClient","loadCheckpoint","processWorkflowSteps","handleWebhookIngestion","executeInlineChain","jsonResponse","readBody","safeCompare","getClientIp","sendIpRateLimit","log","ANTHROPIC_API_KEY","process","env","SUPABASE_SERVICE_ROLE_KEY","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","handleAuthenticatedRoutes","req","res","pathname","url","corsHeaders","method","error","resumeMatch","match","convId","token","getToken","isInternal","isInternalAuth","supabase","data","user","authUser","authError","auth","getUser","checkpoint","parsedMessages","JSON","parse","messages","success","conversation_id","turn","tokens_used","cost_so_far","tools_used","checkpointed_at","created_at","approvalMatch","approvalId","userId","id","rawBody","body","status","approval","from","select","eq","single","approvalMembership","store_id","result","rpc","p_approval_id","p_store_id","p_response","p_response_data","response_data","p_responded_by","responded_by","message","run_id","err","waitpointMatch","wpToken","authToken","wp","Date","expires_at","update","completion_data","completed_at","toISOString","input","waitpoint_completed","waitpoint_data","step_run_id","runId","webhookMatch","whClientIp","slug","headers","k","v","Object","entries","event_type","idempotency_key","existing","limit","length","event_id","deduplicated","eventId","fireErr","p_event_type","p_event_payload","payload","p_source","source","batch_size","workflow_id","wfOwner","wfOwnerErr","p_workflow_id","p_trigger_type","trigger_type","p_trigger_payload","trigger_payload","p_idempotency_key","wf","published_version_id","version_id","headersSent","authHeader","authorization","startsWith","substring"],"sources":["../../src/server/server-routes-auth.ts"],"sourcesContent":["// server/server-routes-auth.ts — Authenticated POST route handlers\n// Resume, approvals, waitpoints, webhooks, events, workflows, tool exec, telemetry, etc.\n// Extracted from index.ts for modularity.\n\nimport http from \"node:http\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { sanitizeError } from \"../shared/agent-core.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { handleProxy } from \"./proxy-handlers.js\";\nimport { handleTranscribe } from \"./handlers/transcription.js\";\nimport { generateCompaction } from \"./lib/compaction-service.js\";\nimport { loadCheckpoint } from \"./lib/session-checkpoint.js\";\nimport { rateLimiter } from \"./lib/rate-limiter.js\";\nimport { sanitizeAndLog } from \"./lib/prompt-sanitizer.js\";\nimport {\n processWorkflowSteps, handleWebhookIngestion, executeInlineChain,\n} from \"./handlers/workflows.js\";\nimport {\n loadUserTools, executeTool, type UserToolRow,\n} from \"./tool-router.js\";\nimport { queueSpan, auditRowToSpan } from \"./lib/clickhouse-buffer.js\";\nimport { jsonResponse, readBody, safeCompare, getClientIp } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\nimport { resolveAndValidateStoreId } from \"./server-store.js\";\nimport { handleAgentChat } from \"./server-chat.js\";\n\nconst log = createLogger(\"server-routes-auth\");\n\nconst ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY!;\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n/**\n * Handle all authenticated POST/PUT/DELETE routes.\n * Called after public routes have been checked.\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleAuthenticatedRoutes(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, url: URL, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n if (req.method !== \"POST\" && req.method !== \"DELETE\" && req.method !== \"PUT\") {\n jsonResponse(res, 405, { error: \"Method not allowed\" }, corsHeaders);\n return true;\n }\n\n try {\n // Resume conversation from checkpoint\n const resumeMatch = pathname.match(/^\\/conversations\\/([a-f0-9-]+)\\/resume$/);\n if (resumeMatch && req.method === \"POST\") {\n const convId = resumeMatch[1];\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n }\n try { await readBody(req); } catch { /* body not needed */ }\n const checkpoint = await loadCheckpoint(supabase, convId);\n if (!checkpoint) { jsonResponse(res, 404, { error: \"No checkpoint found for this conversation\" }, corsHeaders); return true; }\n let parsedMessages: unknown[];\n try { parsedMessages = JSON.parse(checkpoint.messages); } catch { jsonResponse(res, 422, { error: \"Checkpoint messages corrupted\" }, corsHeaders); return true; }\n jsonResponse(res, 200, { success: true, conversation_id: checkpoint.conversation_id, turn: checkpoint.turn, messages: parsedMessages, tokens_used: checkpoint.tokens_used, cost_so_far: checkpoint.cost_so_far, tools_used: checkpoint.tools_used, checkpointed_at: checkpoint.created_at }, corsHeaders);\n return true;\n }\n\n // Approval response\n const approvalMatch = pathname.match(/^\\/approvals\\/([a-f0-9-]+)\\/respond$/);\n if (approvalMatch) {\n const approvalId = approvalMatch[1];\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n let userId: string | null = null;\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n userId = authUser.id;\n }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n if (!body.status) { jsonResponse(res, 400, { error: \"status required (approved/rejected)\" }, corsHeaders); return true; }\n const { data: approval } = await supabase.from(\"workflow_approval_requests\").select(\"store_id, run_id\").eq(\"id\", approvalId).single();\n if (!approval) { jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders); return true; }\n if (!isInternal && userId) {\n const { data: approvalMembership } = await supabase.from(\"store_members\").select(\"id\").eq(\"store_id\", approval.store_id).eq(\"user_id\", userId).single();\n if (!approvalMembership) { jsonResponse(res, 403, { error: \"Not authorized to respond to this approval\" }, corsHeaders); return true; }\n }\n const { data: result, error } = await supabase.rpc(\"respond_to_approval\", { p_approval_id: approvalId, p_store_id: approval.store_id, p_response: body.status, p_response_data: body.response_data || {}, p_responded_by: userId || body.responded_by || null });\n if (error) { jsonResponse(res, 500, { success: false, error: error.message }, corsHeaders); return true; }\n if (result?.success && approval.run_id) { try { await executeInlineChain(supabase, approval.run_id); } catch (err) { log.error({ err: (err as Error).message }, \"inline chain failed after approval\"); } }\n jsonResponse(res, result?.success ? 200 : 422, result, corsHeaders);\n return true;\n }\n\n // Waitpoint completion\n const waitpointMatch = pathname.match(/^\\/waitpoints\\/([a-f0-9-]+)\\/complete$/);\n if (waitpointMatch) {\n const wpToken = waitpointMatch[1];\n const authToken = getToken(req);\n const isInternal = isInternalAuth(authToken);\n if (!isInternal && !authToken) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n const { data: wp } = await supabase.from(\"waitpoint_tokens\").select(\"id, run_id, step_run_id, store_id, expires_at, status\").eq(\"token\", wpToken).single();\n if (!wp) { jsonResponse(res, 404, { error: \"Waitpoint token not found\" }, corsHeaders); return true; }\n if (wp.status === \"completed\") { jsonResponse(res, 409, { error: \"Waitpoint already completed\" }, corsHeaders); return true; }\n if (new Date(wp.expires_at) < new Date()) { jsonResponse(res, 410, { error: \"Waitpoint expired\" }, corsHeaders); return true; }\n await supabase.from(\"waitpoint_tokens\").update({ status: \"completed\", completion_data: body.data || {}, completed_at: new Date().toISOString() }).eq(\"id\", wp.id);\n await supabase.from(\"workflow_step_runs\").update({ status: \"pending\", input: { waitpoint_completed: true, waitpoint_data: body.data || {} } }).eq(\"id\", wp.step_run_id).eq(\"status\", \"waiting\");\n try { await executeInlineChain(supabase, wp.run_id); } catch (err) { log.error({ err: (err as Error).message, runId: wp.run_id }, \"inline chain failed after waitpoint\"); }\n jsonResponse(res, 200, { success: true, run_id: wp.run_id }, corsHeaders);\n return true;\n }\n\n // Webhook ingestion\n const webhookMatch = pathname.match(/^\\/webhooks\\/([a-zA-Z0-9_-]+)$/);\n if (webhookMatch) {\n const whClientIp = getClientIp(req);\n if (sendIpRateLimit(res, whClientIp, corsHeaders)) return true;\n const slug = webhookMatch[1];\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(req.headers)) { if (typeof v === \"string\") headers[k] = v; }\n const result = await handleWebhookIngestion(supabase, slug, rawBody, headers);\n if (result.body.run_id && result.status === 200) {\n try { await executeInlineChain(supabase, result.body.run_id as string); } catch (err) { log.error({ err: (err as Error).message }, \"webhook inline chain error\"); }\n }\n jsonResponse(res, result.status, result.body, corsHeaders);\n return true;\n }\n\n // Fire event\n if (pathname === \"/events\") {\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n if (!body.store_id || !body.event_type) { jsonResponse(res, 400, { error: \"store_id and event_type required\" }, corsHeaders); return true; }\n if (body.idempotency_key) {\n const { data: existing } = await supabase.from(\"workflow_events\").select(\"id\").eq(\"idempotency_key\", body.idempotency_key).limit(1);\n if (existing && existing.length > 0) { jsonResponse(res, 200, { success: true, event_id: existing[0].id, deduplicated: true }, corsHeaders); return true; }\n }\n const { data: eventId, error: fireErr } = await supabase.rpc(\"fire_event\", { p_store_id: body.store_id, p_event_type: body.event_type, p_event_payload: body.payload || {}, p_source: body.source || \"api\" });\n if (fireErr) jsonResponse(res, 500, { success: false, error: fireErr.message }, corsHeaders);\n else jsonResponse(res, 200, { success: true, event_id: eventId }, corsHeaders);\n return true;\n }\n\n // Workflow process (internal)\n if (pathname === \"/workflows/process\") {\n const token = getToken(req);\n if (!FLY_INTERNAL_SECRET || (!safeCompare(token, FLY_INTERNAL_SECRET) && !safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) && !safeCompare(token, SERVICE_ROLE_JWT))) { jsonResponse(res, 401, { error: \"Unauthorized\" }, corsHeaders); return true; }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { rawBody = \"{}\"; }\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n const result = await processWorkflowSteps(supabase, body.batch_size || 10);\n jsonResponse(res, 200, { success: true, ...result }, corsHeaders);\n return true;\n }\n\n // Start workflow run\n if (pathname === \"/workflows/start\") {\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n const supabase = getServiceClient();\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n }\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders); return true; }\n let body: any;\n try { body = JSON.parse(rawBody); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders); return true; }\n if (body.workflow_id && body.store_id) {\n const { data: wfOwner, error: wfOwnerErr } = await supabase.from(\"workflows\").select(\"id\").eq(\"id\", body.workflow_id).eq(\"store_id\", body.store_id).single();\n if (wfOwnerErr || !wfOwner) { jsonResponse(res, 403, { error: \"Workflow does not belong to this store\" }, corsHeaders); return true; }\n }\n const { data, error } = await supabase.rpc(\"start_workflow_run\", { p_workflow_id: body.workflow_id, p_store_id: body.store_id, p_trigger_type: body.trigger_type || \"api\", p_trigger_payload: body.trigger_payload || {}, p_idempotency_key: body.idempotency_key || null });\n if (error) { jsonResponse(res, 500, { success: false, error: error.message }, corsHeaders); }\n else {\n if (data?.success && data.run_id && !data.deduplicated) {\n try {\n const { data: wf } = await supabase.from(\"workflows\").select(\"published_version_id\").eq(\"id\", body.workflow_id).single();\n if (wf?.published_version_id) await supabase.from(\"workflow_runs\").update({ version_id: wf.published_version_id }).eq(\"id\", data.run_id);\n await executeInlineChain(supabase, data.run_id);\n } catch (err) { log.error({ err: (err as Error).message }, \"start-inline chain error\"); }\n }\n jsonResponse(res, data?.success ? 200 : 422, data, corsHeaders);\n }\n return true;\n }\n\n // If none of the above matched, return false — caller handles auth gate + mode dispatch\n return false;\n } catch (err) {\n if (!res.headersSent) jsonResponse(res, 500, { error: sanitizeError(err) }, corsHeaders);\n return true;\n }\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction getToken(req: http.IncomingMessage): string {\n const authHeader = req.headers.authorization;\n return authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n}\n\nfunction isInternalAuth(token: string): boolean {\n return safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n}\n"],"mappings":"AAAA;AACA;AACA;;AAKA,SAASA,YAAY,QAAQ,iBAAiB;AAC9C,SAASC,aAAa,QAAQ,yBAAyB;AACvD,SAASC,gBAAgB,QAAQ,0BAA0B;AAI3D,SAASC,cAAc,QAAQ,6BAA6B;AAG5D,SACEC,oBAAoB,EAAEC,sBAAsB,EAAEC,kBAAkB,QAC3D,yBAAyB;AAKhC,SAASC,YAAY,EAAEC,QAAQ,EAAEC,WAAW,EAAEC,WAAW,QAAQ,qBAAqB;AACtF,SAASC,eAAe,QAAQ,wBAAwB;AAIxD,MAAMC,GAAG,GAAGZ,YAAY,CAAC,oBAAoB,CAAC;AAE9C,MAAMa,iBAAiB,GAAGC,OAAO,CAACC,GAAG,CAACF,iBAAkB;AACxD,MAAMG,yBAAyB,GAAGF,OAAO,CAACC,GAAG,CAACC,yBAA0B;AACxE,MAAMC,gBAAgB,GAAGH,OAAO,CAACC,GAAG,CAACE,gBAAgB,IAAI,EAAE;AAC3D,MAAMC,mBAAmB,GAAGJ,OAAO,CAACC,GAAG,CAACG,mBAAmB,IAAI,EAAE;;AAEjE;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,yBAAyBA,CAC7CC,GAAyB,EAAEC,GAAwB,EACnDC,QAAgB,EAAEC,GAAQ,EAAEC,WAAmC,EAC7C;EAClB,IAAIJ,GAAG,CAACK,MAAM,KAAK,MAAM,IAAIL,GAAG,CAACK,MAAM,KAAK,QAAQ,IAAIL,GAAG,CAACK,MAAM,KAAK,KAAK,EAAE;IAC5ElB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;MAAEK,KAAK,EAAE;IAAqB,CAAC,EAAEF,WAAW,CAAC;IACpE,OAAO,IAAI;EACb;EAEA,IAAI;IACF;IACA,MAAMG,WAAW,GAAGL,QAAQ,CAACM,KAAK,CAAC,yCAAyC,CAAC;IAC7E,IAAID,WAAW,IAAIP,GAAG,CAACK,MAAM,KAAK,MAAM,EAAE;MACxC,MAAMI,MAAM,GAAGF,WAAW,CAAC,CAAC,CAAC;MAC7B,MAAMG,KAAK,GAAGC,QAAQ,CAACX,GAAG,CAAC;MAC3B,MAAMY,UAAU,GAAGC,cAAc,CAACH,KAAK,CAAC;MACxC,IAAI,CAACE,UAAU,IAAI,CAACF,KAAK,EAAE;QAAEvB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAwB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACnH,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,IAAI,CAAC8B,UAAU,EAAE;QACf,MAAM;UAAEG,IAAI,EAAE;YAAEC,IAAI,EAAEC;UAAS,CAAC;UAAEX,KAAK,EAAEY;QAAU,CAAC,GAAG,MAAMJ,QAAQ,CAACK,IAAI,CAACC,OAAO,CAACV,KAAK,CAAC;QACzF,IAAIQ,SAAS,IAAI,CAACD,QAAQ,EAAE;UAAE9B,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEK,KAAK,EAAE;UAA2B,CAAC,EAAEF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;MACzH;MACA,IAAI;QAAE,MAAMhB,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM,CAAE;MACrC,MAAMqB,UAAU,GAAG,MAAMtC,cAAc,CAAC+B,QAAQ,EAAEL,MAAM,CAAC;MACzD,IAAI,CAACY,UAAU,EAAE;QAAElC,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAA4C,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MAC7H,IAAIkB,cAAyB;MAC7B,IAAI;QAAEA,cAAc,GAAGC,IAAI,CAACC,KAAK,CAACH,UAAU,CAACI,QAAQ,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEtC,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAgC,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MAChKjB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;QAAEyB,OAAO,EAAE,IAAI;QAAEC,eAAe,EAAEN,UAAU,CAACM,eAAe;QAAEC,IAAI,EAAEP,UAAU,CAACO,IAAI;QAAEH,QAAQ,EAAEH,cAAc;QAAEO,WAAW,EAAER,UAAU,CAACQ,WAAW;QAAEC,WAAW,EAAET,UAAU,CAACS,WAAW;QAAEC,UAAU,EAAEV,UAAU,CAACU,UAAU;QAAEC,eAAe,EAAEX,UAAU,CAACY;MAAW,CAAC,EAAE7B,WAAW,CAAC;MACzS,OAAO,IAAI;IACb;;IAEA;IACA,MAAM8B,aAAa,GAAGhC,QAAQ,CAACM,KAAK,CAAC,sCAAsC,CAAC;IAC5E,IAAI0B,aAAa,EAAE;MACjB,MAAMC,UAAU,GAAGD,aAAa,CAAC,CAAC,CAAC;MACnC,MAAMxB,KAAK,GAAGC,QAAQ,CAACX,GAAG,CAAC;MAC3B,MAAMY,UAAU,GAAGC,cAAc,CAACH,KAAK,CAAC;MACxC,IAAI,CAACE,UAAU,IAAI,CAACF,KAAK,EAAE;QAAEvB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAwB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACnH,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,IAAIsD,MAAqB,GAAG,IAAI;MAChC,IAAI,CAACxB,UAAU,EAAE;QACf,MAAM;UAAEG,IAAI,EAAE;YAAEC,IAAI,EAAEC;UAAS,CAAC;UAAEX,KAAK,EAAEY;QAAU,CAAC,GAAG,MAAMJ,QAAQ,CAACK,IAAI,CAACC,OAAO,CAACV,KAAK,CAAC;QACzF,IAAIQ,SAAS,IAAI,CAACD,QAAQ,EAAE;UAAE9B,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEK,KAAK,EAAE;UAA2B,CAAC,EAAEF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;QACvHgC,MAAM,GAAGnB,QAAQ,CAACoB,EAAE;MACtB;MACA,IAAIC,OAAe;MACnB,IAAI;QAAEA,OAAO,GAAG,MAAMlD,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEb,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAyB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACtI,IAAImC,IAAS;MACb,IAAI;QAAEA,IAAI,GAAGhB,IAAI,CAACC,KAAK,CAACc,OAAO,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEnD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAe,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACzH,IAAI,CAACmC,IAAI,CAACC,MAAM,EAAE;QAAErD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAsC,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACxH,MAAM;QAAEW,IAAI,EAAE0B;MAAS,CAAC,GAAG,MAAM3B,QAAQ,CAAC4B,IAAI,CAAC,4BAA4B,CAAC,CAACC,MAAM,CAAC,kBAAkB,CAAC,CAACC,EAAE,CAAC,IAAI,EAAET,UAAU,CAAC,CAACU,MAAM,CAAC,CAAC;MACrI,IAAI,CAACJ,QAAQ,EAAE;QAAEtD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAqB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACpG,IAAI,CAACQ,UAAU,IAAIwB,MAAM,EAAE;QACzB,MAAM;UAAErB,IAAI,EAAE+B;QAAmB,CAAC,GAAG,MAAMhC,QAAQ,CAAC4B,IAAI,CAAC,eAAe,CAAC,CAACC,MAAM,CAAC,IAAI,CAAC,CAACC,EAAE,CAAC,UAAU,EAAEH,QAAQ,CAACM,QAAQ,CAAC,CAACH,EAAE,CAAC,SAAS,EAAER,MAAM,CAAC,CAACS,MAAM,CAAC,CAAC;QACvJ,IAAI,CAACC,kBAAkB,EAAE;UAAE3D,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEK,KAAK,EAAE;UAA6C,CAAC,EAAEF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;MACxI;MACA,MAAM;QAAEW,IAAI,EAAEiC,MAAM;QAAE1C;MAAM,CAAC,GAAG,MAAMQ,QAAQ,CAACmC,GAAG,CAAC,qBAAqB,EAAE;QAAEC,aAAa,EAAEf,UAAU;QAAEgB,UAAU,EAAEV,QAAQ,CAACM,QAAQ;QAAEK,UAAU,EAAEb,IAAI,CAACC,MAAM;QAAEa,eAAe,EAAEd,IAAI,CAACe,aAAa,IAAI,CAAC,CAAC;QAAEC,cAAc,EAAEnB,MAAM,IAAIG,IAAI,CAACiB,YAAY,IAAI;MAAK,CAAC,CAAC;MAChQ,IAAIlD,KAAK,EAAE;QAAEnB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEyB,OAAO,EAAE,KAAK;UAAEpB,KAAK,EAAEA,KAAK,CAACmD;QAAQ,CAAC,EAAErD,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACzG,IAAI4C,MAAM,EAAEtB,OAAO,IAAIe,QAAQ,CAACiB,MAAM,EAAE;QAAE,IAAI;UAAE,MAAMxE,kBAAkB,CAAC4B,QAAQ,EAAE2B,QAAQ,CAACiB,MAAM,CAAC;QAAE,CAAC,CAAC,OAAOC,GAAG,EAAE;UAAEnE,GAAG,CAACc,KAAK,CAAC;YAAEqD,GAAG,EAAGA,GAAG,CAAWF;UAAQ,CAAC,EAAE,oCAAoC,CAAC;QAAE;MAAE;MACzMtE,YAAY,CAACc,GAAG,EAAE+C,MAAM,EAAEtB,OAAO,GAAG,GAAG,GAAG,GAAG,EAAEsB,MAAM,EAAE5C,WAAW,CAAC;MACnE,OAAO,IAAI;IACb;;IAEA;IACA,MAAMwD,cAAc,GAAG1D,QAAQ,CAACM,KAAK,CAAC,wCAAwC,CAAC;IAC/E,IAAIoD,cAAc,EAAE;MAClB,MAAMC,OAAO,GAAGD,cAAc,CAAC,CAAC,CAAC;MACjC,MAAME,SAAS,GAAGnD,QAAQ,CAACX,GAAG,CAAC;MAC/B,MAAMY,UAAU,GAAGC,cAAc,CAACiD,SAAS,CAAC;MAC5C,IAAI,CAAClD,UAAU,IAAI,CAACkD,SAAS,EAAE;QAAE3E,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAwB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACvH,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,IAAIwD,OAAe;MACnB,IAAI;QAAEA,OAAO,GAAG,MAAMlD,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEb,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAyB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACtI,IAAImC,IAAS;MACb,IAAI;QAAEA,IAAI,GAAGhB,IAAI,CAACC,KAAK,CAACc,OAAO,IAAI,IAAI,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEnD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAe,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACjI,MAAM;QAAEW,IAAI,EAAEgD;MAAG,CAAC,GAAG,MAAMjD,QAAQ,CAAC4B,IAAI,CAAC,kBAAkB,CAAC,CAACC,MAAM,CAAC,uDAAuD,CAAC,CAACC,EAAE,CAAC,OAAO,EAAEiB,OAAO,CAAC,CAAChB,MAAM,CAAC,CAAC;MAC1J,IAAI,CAACkB,EAAE,EAAE;QAAE5E,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAA4B,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACrG,IAAI2D,EAAE,CAACvB,MAAM,KAAK,WAAW,EAAE;QAAErD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAA8B,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MAC7H,IAAI,IAAI4D,IAAI,CAACD,EAAE,CAACE,UAAU,CAAC,GAAG,IAAID,IAAI,CAAC,CAAC,EAAE;QAAE7E,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAoB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MAC9H,MAAMU,QAAQ,CAAC4B,IAAI,CAAC,kBAAkB,CAAC,CAACwB,MAAM,CAAC;QAAE1B,MAAM,EAAE,WAAW;QAAE2B,eAAe,EAAE5B,IAAI,CAACxB,IAAI,IAAI,CAAC,CAAC;QAAEqD,YAAY,EAAE,IAAIJ,IAAI,CAAC,CAAC,CAACK,WAAW,CAAC;MAAE,CAAC,CAAC,CAACzB,EAAE,CAAC,IAAI,EAAEmB,EAAE,CAAC1B,EAAE,CAAC;MACjK,MAAMvB,QAAQ,CAAC4B,IAAI,CAAC,oBAAoB,CAAC,CAACwB,MAAM,CAAC;QAAE1B,MAAM,EAAE,SAAS;QAAE8B,KAAK,EAAE;UAAEC,mBAAmB,EAAE,IAAI;UAAEC,cAAc,EAAEjC,IAAI,CAACxB,IAAI,IAAI,CAAC;QAAE;MAAE,CAAC,CAAC,CAAC6B,EAAE,CAAC,IAAI,EAAEmB,EAAE,CAACU,WAAW,CAAC,CAAC7B,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;MAC/L,IAAI;QAAE,MAAM1D,kBAAkB,CAAC4B,QAAQ,EAAEiD,EAAE,CAACL,MAAM,CAAC;MAAE,CAAC,CAAC,OAAOC,GAAG,EAAE;QAAEnE,GAAG,CAACc,KAAK,CAAC;UAAEqD,GAAG,EAAGA,GAAG,CAAWF,OAAO;UAAEiB,KAAK,EAAEX,EAAE,CAACL;QAAO,CAAC,EAAE,qCAAqC,CAAC;MAAE;MAC1KvE,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;QAAEyB,OAAO,EAAE,IAAI;QAAEgC,MAAM,EAAEK,EAAE,CAACL;MAAO,CAAC,EAAEtD,WAAW,CAAC;MACzE,OAAO,IAAI;IACb;;IAEA;IACA,MAAMuE,YAAY,GAAGzE,QAAQ,CAACM,KAAK,CAAC,gCAAgC,CAAC;IACrE,IAAImE,YAAY,EAAE;MAChB,MAAMC,UAAU,GAAGtF,WAAW,CAACU,GAAG,CAAC;MACnC,IAAIT,eAAe,CAACU,GAAG,EAAE2E,UAAU,EAAExE,WAAW,CAAC,EAAE,OAAO,IAAI;MAC9D,MAAMyE,IAAI,GAAGF,YAAY,CAAC,CAAC,CAAC;MAC5B,IAAIrC,OAAe;MACnB,IAAI;QAAEA,OAAO,GAAG,MAAMlD,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEb,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAyB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACtI,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,MAAMgG,OAA+B,GAAG,CAAC,CAAC;MAC1C,KAAK,MAAM,CAACC,CAAC,EAAEC,CAAC,CAAC,IAAIC,MAAM,CAACC,OAAO,CAAClF,GAAG,CAAC8E,OAAO,CAAC,EAAE;QAAE,IAAI,OAAOE,CAAC,KAAK,QAAQ,EAAEF,OAAO,CAACC,CAAC,CAAC,GAAGC,CAAC;MAAE;MAC/F,MAAMhC,MAAM,GAAG,MAAM/D,sBAAsB,CAAC6B,QAAQ,EAAE+D,IAAI,EAAEvC,OAAO,EAAEwC,OAAO,CAAC;MAC7E,IAAI9B,MAAM,CAACT,IAAI,CAACmB,MAAM,IAAIV,MAAM,CAACR,MAAM,KAAK,GAAG,EAAE;QAC/C,IAAI;UAAE,MAAMtD,kBAAkB,CAAC4B,QAAQ,EAAEkC,MAAM,CAACT,IAAI,CAACmB,MAAgB,CAAC;QAAE,CAAC,CAAC,OAAOC,GAAG,EAAE;UAAEnE,GAAG,CAACc,KAAK,CAAC;YAAEqD,GAAG,EAAGA,GAAG,CAAWF;UAAQ,CAAC,EAAE,4BAA4B,CAAC;QAAE;MACpK;MACAtE,YAAY,CAACc,GAAG,EAAE+C,MAAM,CAACR,MAAM,EAAEQ,MAAM,CAACT,IAAI,EAAEnC,WAAW,CAAC;MAC1D,OAAO,IAAI;IACb;;IAEA;IACA,IAAIF,QAAQ,KAAK,SAAS,EAAE;MAC1B,MAAMQ,KAAK,GAAGC,QAAQ,CAACX,GAAG,CAAC;MAC3B,MAAMY,UAAU,GAAGC,cAAc,CAACH,KAAK,CAAC;MACxC,IAAI,CAACE,UAAU,IAAI,CAACF,KAAK,EAAE;QAAEvB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAwB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACnH,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,IAAI,CAAC8B,UAAU,EAAE;QACf,MAAM;UAAEG,IAAI,EAAE;YAAEC,IAAI,EAAEC;UAAS,CAAC;UAAEX,KAAK,EAAEY;QAAU,CAAC,GAAG,MAAMJ,QAAQ,CAACK,IAAI,CAACC,OAAO,CAACV,KAAK,CAAC;QACzF,IAAIQ,SAAS,IAAI,CAACD,QAAQ,EAAE;UAAE9B,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEK,KAAK,EAAE;UAA2B,CAAC,EAAEF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;MACzH;MACA,IAAIkC,OAAe;MACnB,IAAI;QAAEA,OAAO,GAAG,MAAMlD,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEb,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAyB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACtI,IAAImC,IAAS;MACb,IAAI;QAAEA,IAAI,GAAGhB,IAAI,CAACC,KAAK,CAACc,OAAO,IAAI,IAAI,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEnD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAe,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACjI,IAAI,CAACmC,IAAI,CAACQ,QAAQ,IAAI,CAACR,IAAI,CAAC4C,UAAU,EAAE;QAAEhG,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAmC,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MAC3I,IAAImC,IAAI,CAAC6C,eAAe,EAAE;QACxB,MAAM;UAAErE,IAAI,EAAEsE;QAAS,CAAC,GAAG,MAAMvE,QAAQ,CAAC4B,IAAI,CAAC,iBAAiB,CAAC,CAACC,MAAM,CAAC,IAAI,CAAC,CAACC,EAAE,CAAC,iBAAiB,EAAEL,IAAI,CAAC6C,eAAe,CAAC,CAACE,KAAK,CAAC,CAAC,CAAC;QACnI,IAAID,QAAQ,IAAIA,QAAQ,CAACE,MAAM,GAAG,CAAC,EAAE;UAAEpG,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEyB,OAAO,EAAE,IAAI;YAAE8D,QAAQ,EAAEH,QAAQ,CAAC,CAAC,CAAC,CAAChD,EAAE;YAAEoD,YAAY,EAAE;UAAK,CAAC,EAAErF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;MAC5J;MACA,MAAM;QAAEW,IAAI,EAAE2E,OAAO;QAAEpF,KAAK,EAAEqF;MAAQ,CAAC,GAAG,MAAM7E,QAAQ,CAACmC,GAAG,CAAC,YAAY,EAAE;QAAEE,UAAU,EAAEZ,IAAI,CAACQ,QAAQ;QAAE6C,YAAY,EAAErD,IAAI,CAAC4C,UAAU;QAAEU,eAAe,EAAEtD,IAAI,CAACuD,OAAO,IAAI,CAAC,CAAC;QAAEC,QAAQ,EAAExD,IAAI,CAACyD,MAAM,IAAI;MAAM,CAAC,CAAC;MAC7M,IAAIL,OAAO,EAAExG,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;QAAEyB,OAAO,EAAE,KAAK;QAAEpB,KAAK,EAAEqF,OAAO,CAAClC;MAAQ,CAAC,EAAErD,WAAW,CAAC,CAAC,KACxFjB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;QAAEyB,OAAO,EAAE,IAAI;QAAE8D,QAAQ,EAAEE;MAAQ,CAAC,EAAEtF,WAAW,CAAC;MAC9E,OAAO,IAAI;IACb;;IAEA;IACA,IAAIF,QAAQ,KAAK,oBAAoB,EAAE;MACrC,MAAMQ,KAAK,GAAGC,QAAQ,CAACX,GAAG,CAAC;MAC3B,IAAI,CAACF,mBAAmB,IAAK,CAACT,WAAW,CAACqB,KAAK,EAAEZ,mBAAmB,CAAC,IAAI,CAACT,WAAW,CAACqB,KAAK,EAAEd,yBAAyB,CAAC,IAAI,CAACP,WAAW,CAACqB,KAAK,EAAEb,gBAAgB,CAAE,EAAE;QAAEV,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAe,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MAClP,IAAIkC,OAAe;MACnB,IAAI;QAAEA,OAAO,GAAG,MAAMlD,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEsC,OAAO,GAAG,IAAI;MAAE;MAC/D,IAAIC,IAAS;MACb,IAAI;QAAEA,IAAI,GAAGhB,IAAI,CAACC,KAAK,CAACc,OAAO,IAAI,IAAI,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEnD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAe,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACjI,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,MAAMkE,MAAM,GAAG,MAAMhE,oBAAoB,CAAC8B,QAAQ,EAAEyB,IAAI,CAAC0D,UAAU,IAAI,EAAE,CAAC;MAC1E9G,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;QAAEyB,OAAO,EAAE,IAAI;QAAE,GAAGsB;MAAO,CAAC,EAAE5C,WAAW,CAAC;MACjE,OAAO,IAAI;IACb;;IAEA;IACA,IAAIF,QAAQ,KAAK,kBAAkB,EAAE;MACnC,MAAMQ,KAAK,GAAGC,QAAQ,CAACX,GAAG,CAAC;MAC3B,MAAMY,UAAU,GAAGC,cAAc,CAACH,KAAK,CAAC;MACxC,IAAI,CAACE,UAAU,IAAI,CAACF,KAAK,EAAE;QAAEvB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAwB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACnH,MAAMU,QAAQ,GAAGhC,gBAAgB,CAAC,CAAC;MACnC,IAAI,CAAC8B,UAAU,EAAE;QACf,MAAM;UAAEG,IAAI,EAAE;YAAEC,IAAI,EAAEC;UAAS,CAAC;UAAEX,KAAK,EAAEY;QAAU,CAAC,GAAG,MAAMJ,QAAQ,CAACK,IAAI,CAACC,OAAO,CAACV,KAAK,CAAC;QACzF,IAAIQ,SAAS,IAAI,CAACD,QAAQ,EAAE;UAAE9B,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEK,KAAK,EAAE;UAA2B,CAAC,EAAEF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;MACzH;MACA,IAAIkC,OAAe;MACnB,IAAI;QAAEA,OAAO,GAAG,MAAMlD,QAAQ,CAACY,GAAG,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEb,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAyB,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACtI,IAAImC,IAAS;MACb,IAAI;QAAEA,IAAI,GAAGhB,IAAI,CAACC,KAAK,CAACc,OAAO,CAAC;MAAE,CAAC,CAAC,MAAM;QAAEnD,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEK,KAAK,EAAE;QAAe,CAAC,EAAEF,WAAW,CAAC;QAAE,OAAO,IAAI;MAAE;MACzH,IAAImC,IAAI,CAAC2D,WAAW,IAAI3D,IAAI,CAACQ,QAAQ,EAAE;QACrC,MAAM;UAAEhC,IAAI,EAAEoF,OAAO;UAAE7F,KAAK,EAAE8F;QAAW,CAAC,GAAG,MAAMtF,QAAQ,CAAC4B,IAAI,CAAC,WAAW,CAAC,CAACC,MAAM,CAAC,IAAI,CAAC,CAACC,EAAE,CAAC,IAAI,EAAEL,IAAI,CAAC2D,WAAW,CAAC,CAACtD,EAAE,CAAC,UAAU,EAAEL,IAAI,CAACQ,QAAQ,CAAC,CAACF,MAAM,CAAC,CAAC;QAC5J,IAAIuD,UAAU,IAAI,CAACD,OAAO,EAAE;UAAEhH,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;YAAEK,KAAK,EAAE;UAAyC,CAAC,EAAEF,WAAW,CAAC;UAAE,OAAO,IAAI;QAAE;MACvI;MACA,MAAM;QAAEW,IAAI;QAAET;MAAM,CAAC,GAAG,MAAMQ,QAAQ,CAACmC,GAAG,CAAC,oBAAoB,EAAE;QAAEoD,aAAa,EAAE9D,IAAI,CAAC2D,WAAW;QAAE/C,UAAU,EAAEZ,IAAI,CAACQ,QAAQ;QAAEuD,cAAc,EAAE/D,IAAI,CAACgE,YAAY,IAAI,KAAK;QAAEC,iBAAiB,EAAEjE,IAAI,CAACkE,eAAe,IAAI,CAAC,CAAC;QAAEC,iBAAiB,EAAEnE,IAAI,CAAC6C,eAAe,IAAI;MAAK,CAAC,CAAC;MAC5Q,IAAI9E,KAAK,EAAE;QAAEnB,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;UAAEyB,OAAO,EAAE,KAAK;UAAEpB,KAAK,EAAEA,KAAK,CAACmD;QAAQ,CAAC,EAAErD,WAAW,CAAC;MAAE,CAAC,MACxF;QACH,IAAIW,IAAI,EAAEW,OAAO,IAAIX,IAAI,CAAC2C,MAAM,IAAI,CAAC3C,IAAI,CAAC0E,YAAY,EAAE;UACtD,IAAI;YACF,MAAM;cAAE1E,IAAI,EAAE4F;YAAG,CAAC,GAAG,MAAM7F,QAAQ,CAAC4B,IAAI,CAAC,WAAW,CAAC,CAACC,MAAM,CAAC,sBAAsB,CAAC,CAACC,EAAE,CAAC,IAAI,EAAEL,IAAI,CAAC2D,WAAW,CAAC,CAACrD,MAAM,CAAC,CAAC;YACxH,IAAI8D,EAAE,EAAEC,oBAAoB,EAAE,MAAM9F,QAAQ,CAAC4B,IAAI,CAAC,eAAe,CAAC,CAACwB,MAAM,CAAC;cAAE2C,UAAU,EAAEF,EAAE,CAACC;YAAqB,CAAC,CAAC,CAAChE,EAAE,CAAC,IAAI,EAAE7B,IAAI,CAAC2C,MAAM,CAAC;YACxI,MAAMxE,kBAAkB,CAAC4B,QAAQ,EAAEC,IAAI,CAAC2C,MAAM,CAAC;UACjD,CAAC,CAAC,OAAOC,GAAG,EAAE;YAAEnE,GAAG,CAACc,KAAK,CAAC;cAAEqD,GAAG,EAAGA,GAAG,CAAWF;YAAQ,CAAC,EAAE,0BAA0B,CAAC;UAAE;QAC1F;QACAtE,YAAY,CAACc,GAAG,EAAEc,IAAI,EAAEW,OAAO,GAAG,GAAG,GAAG,GAAG,EAAEX,IAAI,EAAEX,WAAW,CAAC;MACjE;MACA,OAAO,IAAI;IACb;;IAEA;IACA,OAAO,KAAK;EACd,CAAC,CAAC,OAAOuD,GAAG,EAAE;IACZ,IAAI,CAAC1D,GAAG,CAAC6G,WAAW,EAAE3H,YAAY,CAACc,GAAG,EAAE,GAAG,EAAE;MAAEK,KAAK,EAAEzB,aAAa,CAAC8E,GAAG;IAAE,CAAC,EAAEvD,WAAW,CAAC;IACxF,OAAO,IAAI;EACb;AACF;;AAEA;AACA;AACA;;AAEA,SAASO,QAAQA,CAACX,GAAyB,EAAU;EACnD,MAAM+G,UAAU,GAAG/G,GAAG,CAAC8E,OAAO,CAACkC,aAAa;EAC5C,OAAOD,UAAU,EAAEE,UAAU,CAAC,SAAS,CAAC,GAAGF,UAAU,CAACG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE;AACzE;AAEA,SAASrG,cAAcA,CAACH,KAAa,EAAW;EAC9C,OAAOrB,WAAW,CAACqB,KAAK,EAAEZ,mBAAmB,CAAC,IAAIT,WAAW,CAACqB,KAAK,EAAEd,yBAAyB,CAAC,IAAIP,WAAW,CAACqB,KAAK,EAAEb,gBAAgB,CAAC;AACzI","ignoreList":[]}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { createLogger } from "./lib/logger.js";
|
|
6
6
|
import { getServiceClient } from "./lib/supabase-client.js";
|
|
7
7
|
import { handleWebhookIngestion as processWebhook, executeInlineChain } from "./handlers/workflows.js";
|
|
8
|
-
import { jsonResponse, readBody, safeCompare } from "./server-helpers.js";
|
|
8
|
+
import { jsonResponse, readBody, safeCompare, getClientIp } from "./server-helpers.js";
|
|
9
9
|
import { sendIpRateLimit } from "./server-rate-limit.js";
|
|
10
10
|
const log = createLogger("server-routes-events");
|
|
11
11
|
const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
@@ -132,7 +132,7 @@ export async function handleWebhookRoute(req, res, ctx) {
|
|
|
132
132
|
} = ctx;
|
|
133
133
|
const webhookMatch = pathname.match(/^\/webhooks\/([a-zA-Z0-9_-]+)$/);
|
|
134
134
|
if (!(webhookMatch && req.method === "POST")) return false;
|
|
135
|
-
const whClientIp = req
|
|
135
|
+
const whClientIp = getClientIp(req);
|
|
136
136
|
if (sendIpRateLimit(res, whClientIp, corsHeaders)) return true;
|
|
137
137
|
const slug = webhookMatch[1];
|
|
138
138
|
let rawBody;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-routes-events.js","names":["createLogger","getServiceClient","handleWebhookIngestion","processWebhook","executeInlineChain","jsonResponse","readBody","safeCompare","sendIpRateLimit","log","SUPABASE_SERVICE_ROLE_KEY","process","env","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","getToken","req","authHeader","headers","authorization","startsWith","substring","isInternalAuth","token","handleFireEvent","res","ctx","pathname","corsHeaders","method","isInternal","error","supabase","data","user","authUser","authError","auth","getUser","rawBody","body","JSON","parse","store_id","event_type","idempotency_key","existing","from","select","eq","limit","length","success","event_id","id","deduplicated","eventId","fireErr","rpc","p_store_id","p_event_type","p_event_payload","payload","p_source","source","message","handleWebhookRoute","webhookMatch","match","whClientIp","toString","split","trim","socket","remoteAddress","slug","k","v","Object","entries","result","run_id","status","err"],"sources":["../../src/server/server-routes-events.ts"],"sourcesContent":["// server/server-routes-events.ts — Event and webhook route handlers\n// Events POST and webhook POST\n// Extracted from index.ts for domain-based modularity.\n\nimport http from \"node:http\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { handleWebhookIngestion as processWebhook, executeInlineChain } from \"./handlers/workflows.js\";\nimport { jsonResponse, readBody, safeCompare, type ServerContext } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\n\nconst log = createLogger(\"server-routes-events\");\n\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction getToken(req: http.IncomingMessage): string {\n const authHeader = req.headers.authorization;\n return authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n}\n\nfunction isInternalAuth(token: string): boolean {\n return safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n}\n\n// ============================================================================\n// POST /events — Fire event (service-role or internal auth)\n// ============================================================================\n\nexport async function handleFireEvent(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n if (!(pathname === \"/events\" && req.method === \"POST\")) return false;\n\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n\n if (!isInternal && !token) {\n jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders);\n return true;\n }\n\n const supabase = getServiceClient();\n\n // Verify user auth if not internal\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) {\n jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders);\n return true;\n }\n }\n\n let rawBody: string;\n try {\n rawBody = await readBody(req);\n } catch {\n jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders);\n return true;\n }\n\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch {\n jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders);\n return true;\n }\n if (!body.store_id || !body.event_type) {\n jsonResponse(res, 400, { error: \"store_id and event_type required\" }, corsHeaders);\n return true;\n }\n\n // Idempotency: if client provides idempotency_key, check for duplicate\n if (body.idempotency_key) {\n const { data: existing } = await supabase.from(\"workflow_events\")\n .select(\"id\")\n .eq(\"idempotency_key\", body.idempotency_key)\n .limit(1);\n if (existing && existing.length > 0) {\n jsonResponse(res, 200, { success: true, event_id: existing[0].id, deduplicated: true }, corsHeaders);\n return true;\n }\n }\n\n const { data: eventId, error: fireErr } = await supabase.rpc(\"fire_event\", {\n p_store_id: body.store_id,\n p_event_type: body.event_type,\n p_event_payload: body.payload || {},\n p_source: body.source || \"api\",\n });\n\n if (fireErr) {\n jsonResponse(res, 500, { success: false, error: fireErr.message }, corsHeaders);\n } else {\n jsonResponse(res, 200, { success: true, event_id: eventId }, corsHeaders);\n }\n return true;\n}\n\n// ============================================================================\n// POST /webhooks/:slug — Webhook ingestion (no auth — uses HMAC verification)\n// ============================================================================\n\nexport async function handleWebhookRoute(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n const webhookMatch = pathname.match(/^\\/webhooks\\/([a-zA-Z0-9_-]+)$/);\n if (!(webhookMatch && req.method === \"POST\")) return false;\n\n const whClientIp = req.headers[\"x-forwarded-for\"]?.toString().split(\",\")[0]?.trim() || req.socket.remoteAddress || \"unknown\";\n if (sendIpRateLimit(res, whClientIp, corsHeaders)) return true;\n\n const slug = webhookMatch[1];\n let rawBody: string;\n try {\n rawBody = await readBody(req);\n } catch {\n jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders);\n return true;\n }\n\n const supabase = getServiceClient();\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(req.headers)) {\n if (typeof v === \"string\") headers[k] = v;\n }\n\n const result = await processWebhook(supabase, slug, rawBody, headers);\n\n // Phase 1: Inline execution for webhook-triggered workflows\n if (result.body.run_id && result.status === 200) {\n try {\n await executeInlineChain(supabase, result.body.run_id as string);\n } catch (err) {\n log.error({ err: (err as Error).message }, \"webhook inline chain error\");\n }\n }\n\n jsonResponse(res, result.status, result.body, corsHeaders);\n return true;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"server-routes-events.js","names":["createLogger","getServiceClient","handleWebhookIngestion","processWebhook","executeInlineChain","jsonResponse","readBody","safeCompare","getClientIp","sendIpRateLimit","log","SUPABASE_SERVICE_ROLE_KEY","process","env","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","getToken","req","authHeader","headers","authorization","startsWith","substring","isInternalAuth","token","handleFireEvent","res","ctx","pathname","corsHeaders","method","isInternal","error","supabase","data","user","authUser","authError","auth","getUser","rawBody","body","JSON","parse","store_id","event_type","idempotency_key","existing","from","select","eq","limit","length","success","event_id","id","deduplicated","eventId","fireErr","rpc","p_store_id","p_event_type","p_event_payload","payload","p_source","source","message","handleWebhookRoute","webhookMatch","match","whClientIp","slug","k","v","Object","entries","result","run_id","status","err"],"sources":["../../src/server/server-routes-events.ts"],"sourcesContent":["// server/server-routes-events.ts — Event and webhook route handlers\n// Events POST and webhook POST\n// Extracted from index.ts for domain-based modularity.\n\nimport http from \"node:http\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { handleWebhookIngestion as processWebhook, executeInlineChain } from \"./handlers/workflows.js\";\nimport { jsonResponse, readBody, safeCompare, getClientIp, type ServerContext } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\n\nconst log = createLogger(\"server-routes-events\");\n\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction getToken(req: http.IncomingMessage): string {\n const authHeader = req.headers.authorization;\n return authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n}\n\nfunction isInternalAuth(token: string): boolean {\n return safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n}\n\n// ============================================================================\n// POST /events — Fire event (service-role or internal auth)\n// ============================================================================\n\nexport async function handleFireEvent(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n if (!(pathname === \"/events\" && req.method === \"POST\")) return false;\n\n const token = getToken(req);\n const isInternal = isInternalAuth(token);\n\n if (!isInternal && !token) {\n jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders);\n return true;\n }\n\n const supabase = getServiceClient();\n\n // Verify user auth if not internal\n if (!isInternal) {\n const { data: { user: authUser }, error: authError } = await supabase.auth.getUser(token);\n if (authError || !authUser) {\n jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders);\n return true;\n }\n }\n\n let rawBody: string;\n try {\n rawBody = await readBody(req);\n } catch {\n jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders);\n return true;\n }\n\n let body: any;\n try { body = JSON.parse(rawBody || \"{}\"); } catch {\n jsonResponse(res, 400, { error: \"Invalid JSON\" }, corsHeaders);\n return true;\n }\n if (!body.store_id || !body.event_type) {\n jsonResponse(res, 400, { error: \"store_id and event_type required\" }, corsHeaders);\n return true;\n }\n\n // Idempotency: if client provides idempotency_key, check for duplicate\n if (body.idempotency_key) {\n const { data: existing } = await supabase.from(\"workflow_events\")\n .select(\"id\")\n .eq(\"idempotency_key\", body.idempotency_key)\n .limit(1);\n if (existing && existing.length > 0) {\n jsonResponse(res, 200, { success: true, event_id: existing[0].id, deduplicated: true }, corsHeaders);\n return true;\n }\n }\n\n const { data: eventId, error: fireErr } = await supabase.rpc(\"fire_event\", {\n p_store_id: body.store_id,\n p_event_type: body.event_type,\n p_event_payload: body.payload || {},\n p_source: body.source || \"api\",\n });\n\n if (fireErr) {\n jsonResponse(res, 500, { success: false, error: fireErr.message }, corsHeaders);\n } else {\n jsonResponse(res, 200, { success: true, event_id: eventId }, corsHeaders);\n }\n return true;\n}\n\n// ============================================================================\n// POST /webhooks/:slug — Webhook ingestion (no auth — uses HMAC verification)\n// ============================================================================\n\nexport async function handleWebhookRoute(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ctx: ServerContext,\n): Promise<boolean> {\n const { pathname, corsHeaders } = ctx;\n\n const webhookMatch = pathname.match(/^\\/webhooks\\/([a-zA-Z0-9_-]+)$/);\n if (!(webhookMatch && req.method === \"POST\")) return false;\n\n const whClientIp = getClientIp(req);\n if (sendIpRateLimit(res, whClientIp, corsHeaders)) return true;\n\n const slug = webhookMatch[1];\n let rawBody: string;\n try {\n rawBody = await readBody(req);\n } catch {\n jsonResponse(res, 413, { error: \"Request body too large\" }, corsHeaders);\n return true;\n }\n\n const supabase = getServiceClient();\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(req.headers)) {\n if (typeof v === \"string\") headers[k] = v;\n }\n\n const result = await processWebhook(supabase, slug, rawBody, headers);\n\n // Phase 1: Inline execution for webhook-triggered workflows\n if (result.body.run_id && result.status === 200) {\n try {\n await executeInlineChain(supabase, result.body.run_id as string);\n } catch (err) {\n log.error({ err: (err as Error).message }, \"webhook inline chain error\");\n }\n }\n\n jsonResponse(res, result.status, result.body, corsHeaders);\n return true;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -7,7 +7,7 @@ import { createLogger } from "./lib/logger.js";
|
|
|
7
7
|
import { getServiceClient } from "./lib/supabase-client.js";
|
|
8
8
|
import { checkPlanLimits, incrementUsage } from "./handlers/billing.js";
|
|
9
9
|
import { verifyGuestApprovalSignature, executeInlineChain } from "./handlers/workflows.js";
|
|
10
|
-
import { jsonResponse, readBody, safeCompare } from "./server-helpers.js";
|
|
10
|
+
import { jsonResponse, readBody, safeCompare, getClientIp } from "./server-helpers.js";
|
|
11
11
|
import { sendIpRateLimit } from "./server-rate-limit.js";
|
|
12
12
|
import { getSseClients, sendWorkflowSSE, safeSseWrite, MAX_SSE_CLIENTS_PER_RUN, MAX_SSE_TOTAL_CLIENTS, getTotalSseClients } from "./server-sse.js";
|
|
13
13
|
const log = createLogger("server-routes-public");
|
|
@@ -127,7 +127,7 @@ export async function handleSseStreamRoute(req, res, pathname, corsHeaders) {
|
|
|
127
127
|
export async function handleGuestApprovalRoute(req, res, pathname, corsHeaders) {
|
|
128
128
|
const guestApprovalMatch = pathname.match(/^\/approvals\/guest\/([a-f0-9-]+)$/);
|
|
129
129
|
if (!(guestApprovalMatch && req.method === "GET")) return false;
|
|
130
|
-
const clientIp = req
|
|
130
|
+
const clientIp = getClientIp(req);
|
|
131
131
|
if (sendIpRateLimit(res, clientIp, corsHeaders)) return true;
|
|
132
132
|
const stepRunId = guestApprovalMatch[1];
|
|
133
133
|
const urlParams = new URL(req.url || "", `http://${req.headers.host}`).searchParams;
|
|
@@ -223,7 +223,7 @@ export async function handleWebchatRoutes(req, res, pathname, url, corsHeaders)
|
|
|
223
223
|
// POST /webchat/channels/:id/messages
|
|
224
224
|
const webchatMsgMatch = pathname.match(/^\/webchat\/channels\/([a-f0-9-]+)\/messages$/);
|
|
225
225
|
if (webchatMsgMatch && req.method === "POST") {
|
|
226
|
-
const clientIp = req
|
|
226
|
+
const clientIp = getClientIp(req);
|
|
227
227
|
if (sendIpRateLimit(res, clientIp, webchatCors)) return true;
|
|
228
228
|
let rawBody;
|
|
229
229
|
try {
|
|
@@ -366,7 +366,7 @@ export async function handleWebchatRoutes(req, res, pathname, url, corsHeaders)
|
|
|
366
366
|
// GET /webchat/channels/:id/history
|
|
367
367
|
const webchatHistoryMatch = pathname.match(/^\/webchat\/channels\/([a-f0-9-]+)\/history$/);
|
|
368
368
|
if (webchatHistoryMatch && req.method === "GET") {
|
|
369
|
-
const clientIp = req
|
|
369
|
+
const clientIp = getClientIp(req);
|
|
370
370
|
if (sendIpRateLimit(res, clientIp, webchatCors)) return true;
|
|
371
371
|
const channelId = webchatHistoryMatch[1];
|
|
372
372
|
const senderId = url.searchParams.get("sender_id") || "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-routes-public.js","names":["randomUUID","createLogger","getServiceClient","checkPlanLimits","incrementUsage","verifyGuestApprovalSignature","executeInlineChain","jsonResponse","readBody","safeCompare","sendIpRateLimit","getSseClients","sendWorkflowSSE","safeSseWrite","MAX_SSE_CLIENTS_PER_RUN","MAX_SSE_TOTAL_CLIENTS","getTotalSseClients","log","webchatAgentInvoker","setWebchatAgentInvoker","invoker","SUPABASE_SERVICE_ROLE_KEY","process","env","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","handleSseStreamRoute","req","res","pathname","corsHeaders","method","match","runId","split","authHeader","headers","authorization","token","startsWith","substring","isInternal","error","sb","data","user","authUser","authError","auth","getUser","sseRun","from","select","eq","single","membership","store_id","id","sseClients","existingClients","get","size","writeHead","Connection","run","stepRuns","order","ascending","type","steps","has","set","Set","add","cleanup","clearInterval","heartbeat","clients","delete","setInterval","on","handleGuestApprovalRoute","guestApprovalMatch","clientIp","toString","trim","socket","remoteAddress","stepRunId","urlParams","URL","url","host","searchParams","action","expires","sig","Date","guestSupabase","approval","limit","length","status","isApprove","guestResult","guestErr","rpc","p_approval_id","p_store_id","p_response","p_response_data","guest","p_responded_by","success","message","run_id","err","end","handleWebchatRoutes","webchatCors","webchatMsgMatch","rawBody","channelId","wcBody","JSON","parse","content","supabase","channel","planCheck","allowed","reason","senderId","sender_id","conversationId","conversation_id","thirtyMinAgo","now","toISOString","recent","gt","not","msgErr","insert","channel_id","direction","sender_name","content_type","metadata","source","ip","widget_version","agent_id","messages_in","catch","p_channel_id","agentResponse","result","response","outMsg","auto_response","messages_out","agent_invocations","agent_response","webchatHistoryMatch","reqConvId","wcChannel","test","query","in","messages","histErr","fs","path","possiblePaths","join","import","meta","dirname","__dirname","cwd","widgetJs","p","readFileSync"],"sources":["../../src/server/server-routes-public.ts"],"sourcesContent":["// server/server-routes-public.ts — Public/unauthenticated route handlers\n// SSE streaming, guest approvals, webchat, billing, node routes\n// Extracted from index.ts for modularity.\n\nimport http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { checkPlanLimits, incrementUsage } from \"./handlers/billing.js\";\nimport { handleBillingRoutes } from \"./handlers/billing.js\";\nimport { handleNodeRoutes } from \"./handlers/nodes.js\";\nimport { verifyGuestApprovalSignature, executeInlineChain } from \"./handlers/workflows.js\";\nimport { jsonResponse, readBody, safeCompare } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\nimport { getSseClients, sendWorkflowSSE, safeSseWrite, MAX_SSE_CLIENTS_PER_RUN, MAX_SSE_TOTAL_CLIENTS, getTotalSseClients } from \"./server-sse.js\";\n\nconst log = createLogger(\"server-routes-public\");\n\n// Webchat agent invoker — set later to avoid circular deps\nlet webchatAgentInvoker: ((\n supabase: SupabaseClient, agentId: string, message: string, storeId: string, conversationId: string, senderContext?: any,\n) => Promise<{ success: boolean; response?: string; error?: string }>) | null = null;\n\nexport function setWebchatAgentInvoker(invoker: typeof webchatAgentInvoker): void {\n webchatAgentInvoker = invoker;\n}\n\n// Env secrets (needed for auth checks)\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n/**\n * Handle SSE workflow stream route.\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleSseStreamRoute(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n if (!(req.method === \"GET\" && pathname.match(/^\\/workflows\\/runs\\/[a-f0-9-]+\\/stream$/))) return false;\n\n const runId = pathname.split(\"/\")[3];\n const authHeader = req.headers.authorization;\n const token = authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n const isInternal = safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n\n if (!isInternal) {\n const sb = getServiceClient();\n const { data: { user: authUser }, error: authError } = await sb.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n const { data: sseRun } = await sb.from(\"workflow_runs\").select(\"store_id\").eq(\"id\", runId).single();\n if (sseRun) {\n const { data: membership } = await sb.from(\"store_members\").select(\"id\").eq(\"store_id\", sseRun.store_id).eq(\"user_id\", authUser.id).single();\n if (!membership) { jsonResponse(res, 403, { error: \"Not authorized to view this run\" }, corsHeaders); return true; }\n }\n }\n\n const sseClients = getSseClients();\n const existingClients = sseClients.get(runId)?.size || 0;\n if (existingClients >= MAX_SSE_CLIENTS_PER_RUN) { jsonResponse(res, 429, { error: \"Too many SSE clients for this run\" }, corsHeaders); return true; }\n if (getTotalSseClients() >= MAX_SSE_TOTAL_CLIENTS) { jsonResponse(res, 429, { error: \"Too many total SSE connections\" }, corsHeaders); return true; }\n\n res.writeHead(200, { \"Content-Type\": \"text/event-stream\", \"Cache-Control\": \"no-cache\", Connection: \"keep-alive\", ...corsHeaders });\n\n const sb = getServiceClient();\n const { data: run } = await sb.from(\"workflow_runs\")\n .select(\"id, workflow_id, status, trigger_type, current_step_key, error_message, error_step_key, started_at, completed_at, duration_ms\")\n .eq(\"id\", runId).single();\n const { data: stepRuns } = await sb.from(\"workflow_step_runs\")\n .select(\"id, step_key, step_type, status, error_message, duration_ms, started_at, completed_at\")\n .eq(\"run_id\", runId).order(\"created_at\", { ascending: true });\n\n sendWorkflowSSE(res, { type: \"snapshot\", run, steps: stepRuns || [] });\n\n if (!sseClients.has(runId)) sseClients.set(runId, new Set());\n sseClients.get(runId)!.add(res);\n\n const cleanup = () => {\n clearInterval(heartbeat);\n const clients = sseClients.get(runId);\n if (clients) { clients.delete(res); if (clients.size === 0) sseClients.delete(runId); }\n };\n\n const heartbeat = setInterval(() => {\n if (!safeSseWrite(res, `: heartbeat\\n\\n`, cleanup)) clearInterval(heartbeat);\n }, 15_000);\n\n req.on(\"close\", cleanup);\n req.on(\"error\", cleanup);\n return true;\n}\n\n/**\n * Handle guest approval route.\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleGuestApprovalRoute(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n const guestApprovalMatch = pathname.match(/^\\/approvals\\/guest\\/([a-f0-9-]+)$/);\n if (!(guestApprovalMatch && req.method === \"GET\")) return false;\n\n const clientIp = req.headers[\"x-forwarded-for\"]?.toString().split(\",\")[0]?.trim() || req.socket.remoteAddress || \"unknown\";\n if (sendIpRateLimit(res, clientIp, corsHeaders)) return true;\n\n const stepRunId = guestApprovalMatch[1];\n const urlParams = new URL(req.url || \"\", `http://${req.headers.host}`).searchParams;\n const action = urlParams.get(\"action\") || \"\";\n const expires = urlParams.get(\"expires\") || \"\";\n const sig = urlParams.get(\"sig\") || \"\";\n\n if (!action || !expires || !sig) { jsonResponse(res, 400, { error: \"Missing action, expires, or sig parameter\" }, corsHeaders); return true; }\n if (new Date(expires) < new Date()) { jsonResponse(res, 410, { error: \"This approval link has expired\" }, corsHeaders); return true; }\n if (!verifyGuestApprovalSignature(stepRunId, action, expires, sig)) { jsonResponse(res, 403, { error: \"Invalid signature\" }, corsHeaders); return true; }\n\n const guestSupabase = getServiceClient();\n const { data: approval } = await guestSupabase.from(\"workflow_approval_requests\").select(\"id, store_id, run_id, status\").eq(\"step_run_id\", stepRunId).limit(1);\n if (!approval?.length) { jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders); return true; }\n if (approval[0].status !== \"pending\") { jsonResponse(res, 409, { error: `Approval already ${approval[0].status}` }, corsHeaders); return true; }\n\n const isApprove = action === \"approve\" || action === \"approved\";\n const { data: guestResult, error: guestErr } = await guestSupabase.rpc(\"respond_to_approval\", {\n p_approval_id: approval[0].id, p_store_id: approval[0].store_id,\n p_response: isApprove ? \"approved\" : \"rejected\", p_response_data: { guest: true, action }, p_responded_by: null,\n });\n\n if (guestErr) { jsonResponse(res, 500, { success: false, error: guestErr.message }, corsHeaders); return true; }\n\n if (guestResult?.success && approval[0].run_id) {\n try { await executeInlineChain(guestSupabase, approval[0].run_id); } catch (err) { log.error({ err: (err as Error).message, runId: approval[0].run_id }, \"inline chain failed after guest approval\"); }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\", ...corsHeaders });\n res.end(`<!DOCTYPE html><html><body style=\"font-family:system-ui;text-align:center;padding:40px\">\n <h2>${isApprove ? \"Approved\" : \"Rejected\"}</h2>\n <p>Your response has been recorded. You can close this window.</p>\n </body></html>`);\n return true;\n}\n\n/**\n * Handle webchat routes (messages, history, widget.js).\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleWebchatRoutes(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, url: URL, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n const webchatCors = { ...corsHeaders, \"Access-Control-Allow-Origin\": \"*\" };\n\n // POST /webchat/channels/:id/messages\n const webchatMsgMatch = pathname.match(/^\\/webchat\\/channels\\/([a-f0-9-]+)\\/messages$/);\n if (webchatMsgMatch && req.method === \"POST\") {\n const clientIp = req.headers[\"x-forwarded-for\"]?.toString().split(\",\")[0]?.trim() || req.socket.remoteAddress || \"unknown\";\n if (sendIpRateLimit(res, clientIp, webchatCors)) return true;\n\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, webchatCors); return true; }\n\n const channelId = webchatMsgMatch[1];\n let wcBody: any;\n try { wcBody = JSON.parse(rawBody); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, webchatCors); return true; }\n if (!wcBody.content || typeof wcBody.content !== \"string\") { jsonResponse(res, 400, { error: \"content (string) is required\" }, webchatCors); return true; }\n if (wcBody.content.length > 5000) { jsonResponse(res, 400, { error: \"Message too long (max 5000 characters)\" }, webchatCors); return true; }\n\n const supabase = getServiceClient();\n const { data: channel } = await supabase.from(\"channels\").select(\"id, store_id, node_id, agent_id, type, config\").eq(\"id\", channelId).eq(\"type\", \"webchat\").single();\n if (!channel) { jsonResponse(res, 404, { error: \"Webchat channel not found\" }, webchatCors); return true; }\n\n try {\n const planCheck = await checkPlanLimits(supabase, channel.store_id, \"message\");\n if (!planCheck.allowed) { jsonResponse(res, 429, { error: planCheck.reason || \"Plan limit reached\" }, webchatCors); return true; }\n } catch { /* billing tables may not exist yet */ }\n\n const senderId = (wcBody.sender_id as string) || \"anonymous\";\n let conversationId: string = (wcBody.conversation_id as string) || \"\";\n if (!conversationId) {\n const thirtyMinAgo = new Date(Date.now() - 30 * 60 * 1000).toISOString();\n const { data: recent } = await supabase.from(\"channel_messages\").select(\"conversation_id\")\n .eq(\"channel_id\", channelId).eq(\"sender_id\", senderId).gt(\"created_at\", thirtyMinAgo)\n .not(\"conversation_id\", \"is\", null).order(\"created_at\", { ascending: false }).limit(1);\n conversationId = (recent?.length && recent[0].conversation_id) || randomUUID();\n }\n\n const { data: message, error: msgErr } = await supabase.from(\"channel_messages\").insert({\n store_id: channel.store_id, channel_id: channelId, direction: \"inbound\",\n sender_id: senderId, sender_name: wcBody.sender_name || \"Visitor\",\n content: wcBody.content, content_type: \"text\",\n metadata: { source: \"webchat\", ip: clientIp, widget_version: \"1.0.0\" },\n agent_id: channel.agent_id, conversation_id: conversationId,\n }).select(\"id, direction, content, conversation_id, created_at\").single();\n if (msgErr) { jsonResponse(res, 500, { error: msgErr.message }, webchatCors); return true; }\n\n incrementUsage(supabase, channel.store_id, { messages_in: 1 }).catch(() => {});\n try { await supabase.rpc(\"increment_channel_stats\", { p_channel_id: channelId }); } catch { /* ok */ }\n\n let agentResponse: any = null;\n if (channel.agent_id && webchatAgentInvoker) {\n try {\n const result = await webchatAgentInvoker(supabase, channel.agent_id, wcBody.content, channel.store_id, conversationId);\n if (result.success && result.response) {\n const { data: outMsg } = await supabase.from(\"channel_messages\").insert({\n store_id: channel.store_id, channel_id: channelId, direction: \"outbound\",\n sender_id: \"agent\", sender_name: \"AI Agent\",\n content: result.response, content_type: \"text\",\n metadata: { agent_id: channel.agent_id, auto_response: true, source: \"webchat\" },\n agent_id: channel.agent_id, conversation_id: conversationId,\n }).select(\"id, direction, content, conversation_id, created_at\").single();\n agentResponse = outMsg;\n incrementUsage(supabase, channel.store_id, { messages_out: 1, agent_invocations: 1 }).catch(() => {});\n }\n } catch (err) { log.error({ err: (err as Error).message }, \"webchat agent error\"); }\n }\n\n jsonResponse(res, 201, { success: true, message, agent_response: agentResponse, conversation_id: conversationId }, webchatCors);\n return true;\n }\n\n // GET /webchat/channels/:id/history\n const webchatHistoryMatch = pathname.match(/^\\/webchat\\/channels\\/([a-f0-9-]+)\\/history$/);\n if (webchatHistoryMatch && req.method === \"GET\") {\n const clientIp = req.headers[\"x-forwarded-for\"]?.toString().split(\",\")[0]?.trim() || req.socket.remoteAddress || \"unknown\";\n if (sendIpRateLimit(res, clientIp, webchatCors)) return true;\n\n const channelId = webchatHistoryMatch[1];\n const senderId = url.searchParams.get(\"sender_id\") || \"\";\n const reqConvId = url.searchParams.get(\"conversation_id\") || \"\";\n if (!senderId) { jsonResponse(res, 400, { error: \"sender_id query parameter required\" }, webchatCors); return true; }\n\n const supabase = getServiceClient();\n const { data: wcChannel } = await supabase.from(\"channels\").select(\"id, type\").eq(\"id\", channelId).eq(\"type\", \"webchat\").single();\n if (!wcChannel) { jsonResponse(res, 404, { error: \"Webchat channel not found\" }, webchatCors); return true; }\n\n if (!/^[a-zA-Z0-9_-]+$/.test(senderId)) { jsonResponse(res, 400, { error: \"Invalid sender_id format\" }, webchatCors); return true; }\n let query = supabase.from(\"channel_messages\")\n .select(\"id, direction, sender_id, sender_name, content, content_type, created_at\")\n .eq(\"channel_id\", channelId);\n if (reqConvId) { query = query.eq(\"conversation_id\", reqConvId).in(\"sender_id\", [senderId, \"agent\"]); }\n else { query = query.in(\"sender_id\", [senderId, \"agent\"]); }\n\n const { data: messages, error: histErr } = await query.order(\"created_at\", { ascending: true }).limit(50);\n if (histErr) { jsonResponse(res, 500, { error: histErr.message }, webchatCors); return true; }\n jsonResponse(res, 200, { success: true, messages: messages || [] }, webchatCors);\n return true;\n }\n\n // GET /webchat/widget.js\n if (pathname === \"/webchat/widget.js\" && req.method === \"GET\") {\n const fs = await import(\"node:fs\");\n const path = await import(\"node:path\");\n const possiblePaths = [\n path.join(import.meta.dirname || __dirname, \"../../dist/webchat/widget.js\"),\n path.join(import.meta.dirname || __dirname, \"../../../dist/webchat/widget.js\"),\n path.join(process.cwd(), \"dist/webchat/widget.js\"),\n ];\n let widgetJs: string | null = null;\n for (const p of possiblePaths) { try { widgetJs = fs.readFileSync(p, \"utf-8\"); break; } catch { /* try next */ } }\n if (widgetJs) {\n res.writeHead(200, { \"Content-Type\": \"application/javascript\", \"Cache-Control\": \"public, max-age=3600\", ...webchatCors });\n res.end(widgetJs);\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/javascript\", ...webchatCors });\n res.end('console.warn(\"[WhaleChat] Widget JS not built. Run: npx esbuild src/webchat/widget.ts --bundle --minify --outfile=dist/webchat/widget.js\");');\n }\n return true;\n }\n\n return false;\n}\n\n// Billing and node route handling is in the main index.ts to keep this file under 300 lines\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"server-routes-public.js","names":["randomUUID","createLogger","getServiceClient","checkPlanLimits","incrementUsage","verifyGuestApprovalSignature","executeInlineChain","jsonResponse","readBody","safeCompare","getClientIp","sendIpRateLimit","getSseClients","sendWorkflowSSE","safeSseWrite","MAX_SSE_CLIENTS_PER_RUN","MAX_SSE_TOTAL_CLIENTS","getTotalSseClients","log","webchatAgentInvoker","setWebchatAgentInvoker","invoker","SUPABASE_SERVICE_ROLE_KEY","process","env","SERVICE_ROLE_JWT","FLY_INTERNAL_SECRET","handleSseStreamRoute","req","res","pathname","corsHeaders","method","match","runId","split","authHeader","headers","authorization","token","startsWith","substring","isInternal","error","sb","data","user","authUser","authError","auth","getUser","sseRun","from","select","eq","single","membership","store_id","id","sseClients","existingClients","get","size","writeHead","Connection","run","stepRuns","order","ascending","type","steps","has","set","Set","add","cleanup","clearInterval","heartbeat","clients","delete","setInterval","on","handleGuestApprovalRoute","guestApprovalMatch","clientIp","stepRunId","urlParams","URL","url","host","searchParams","action","expires","sig","Date","guestSupabase","approval","limit","length","status","isApprove","guestResult","guestErr","rpc","p_approval_id","p_store_id","p_response","p_response_data","guest","p_responded_by","success","message","run_id","err","end","handleWebchatRoutes","webchatCors","webchatMsgMatch","rawBody","channelId","wcBody","JSON","parse","content","supabase","channel","planCheck","allowed","reason","senderId","sender_id","conversationId","conversation_id","thirtyMinAgo","now","toISOString","recent","gt","not","msgErr","insert","channel_id","direction","sender_name","content_type","metadata","source","ip","widget_version","agent_id","messages_in","catch","p_channel_id","agentResponse","result","response","outMsg","auto_response","messages_out","agent_invocations","agent_response","webchatHistoryMatch","reqConvId","wcChannel","test","query","in","messages","histErr","fs","path","possiblePaths","join","import","meta","dirname","__dirname","cwd","widgetJs","p","readFileSync"],"sources":["../../src/server/server-routes-public.ts"],"sourcesContent":["// server/server-routes-public.ts — Public/unauthenticated route handlers\n// SSE streaming, guest approvals, webchat, billing, node routes\n// Extracted from index.ts for modularity.\n\nimport http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { createLogger } from \"./lib/logger.js\";\nimport { getServiceClient } from \"./lib/supabase-client.js\";\nimport { checkPlanLimits, incrementUsage } from \"./handlers/billing.js\";\nimport { handleBillingRoutes } from \"./handlers/billing.js\";\nimport { handleNodeRoutes } from \"./handlers/nodes.js\";\nimport { verifyGuestApprovalSignature, executeInlineChain } from \"./handlers/workflows.js\";\nimport { jsonResponse, readBody, safeCompare, getClientIp } from \"./server-helpers.js\";\nimport { sendIpRateLimit } from \"./server-rate-limit.js\";\nimport { getSseClients, sendWorkflowSSE, safeSseWrite, MAX_SSE_CLIENTS_PER_RUN, MAX_SSE_TOTAL_CLIENTS, getTotalSseClients } from \"./server-sse.js\";\n\nconst log = createLogger(\"server-routes-public\");\n\n// Webchat agent invoker — set later to avoid circular deps\nlet webchatAgentInvoker: ((\n supabase: SupabaseClient, agentId: string, message: string, storeId: string, conversationId: string, senderContext?: any,\n) => Promise<{ success: boolean; response?: string; error?: string }>) | null = null;\n\nexport function setWebchatAgentInvoker(invoker: typeof webchatAgentInvoker): void {\n webchatAgentInvoker = invoker;\n}\n\n// Env secrets (needed for auth checks)\nconst SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;\nconst SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || \"\";\nconst FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || \"\";\n\n/**\n * Handle SSE workflow stream route.\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleSseStreamRoute(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n if (!(req.method === \"GET\" && pathname.match(/^\\/workflows\\/runs\\/[a-f0-9-]+\\/stream$/))) return false;\n\n const runId = pathname.split(\"/\")[3];\n const authHeader = req.headers.authorization;\n const token = authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : \"\";\n const isInternal = safeCompare(token, FLY_INTERNAL_SECRET) || safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);\n\n if (!isInternal && !token) { jsonResponse(res, 401, { error: \"Missing authorization\" }, corsHeaders); return true; }\n\n if (!isInternal) {\n const sb = getServiceClient();\n const { data: { user: authUser }, error: authError } = await sb.auth.getUser(token);\n if (authError || !authUser) { jsonResponse(res, 401, { error: \"Invalid or expired token\" }, corsHeaders); return true; }\n const { data: sseRun } = await sb.from(\"workflow_runs\").select(\"store_id\").eq(\"id\", runId).single();\n if (sseRun) {\n const { data: membership } = await sb.from(\"store_members\").select(\"id\").eq(\"store_id\", sseRun.store_id).eq(\"user_id\", authUser.id).single();\n if (!membership) { jsonResponse(res, 403, { error: \"Not authorized to view this run\" }, corsHeaders); return true; }\n }\n }\n\n const sseClients = getSseClients();\n const existingClients = sseClients.get(runId)?.size || 0;\n if (existingClients >= MAX_SSE_CLIENTS_PER_RUN) { jsonResponse(res, 429, { error: \"Too many SSE clients for this run\" }, corsHeaders); return true; }\n if (getTotalSseClients() >= MAX_SSE_TOTAL_CLIENTS) { jsonResponse(res, 429, { error: \"Too many total SSE connections\" }, corsHeaders); return true; }\n\n res.writeHead(200, { \"Content-Type\": \"text/event-stream\", \"Cache-Control\": \"no-cache\", Connection: \"keep-alive\", ...corsHeaders });\n\n const sb = getServiceClient();\n const { data: run } = await sb.from(\"workflow_runs\")\n .select(\"id, workflow_id, status, trigger_type, current_step_key, error_message, error_step_key, started_at, completed_at, duration_ms\")\n .eq(\"id\", runId).single();\n const { data: stepRuns } = await sb.from(\"workflow_step_runs\")\n .select(\"id, step_key, step_type, status, error_message, duration_ms, started_at, completed_at\")\n .eq(\"run_id\", runId).order(\"created_at\", { ascending: true });\n\n sendWorkflowSSE(res, { type: \"snapshot\", run, steps: stepRuns || [] });\n\n if (!sseClients.has(runId)) sseClients.set(runId, new Set());\n sseClients.get(runId)!.add(res);\n\n const cleanup = () => {\n clearInterval(heartbeat);\n const clients = sseClients.get(runId);\n if (clients) { clients.delete(res); if (clients.size === 0) sseClients.delete(runId); }\n };\n\n const heartbeat = setInterval(() => {\n if (!safeSseWrite(res, `: heartbeat\\n\\n`, cleanup)) clearInterval(heartbeat);\n }, 15_000);\n\n req.on(\"close\", cleanup);\n req.on(\"error\", cleanup);\n return true;\n}\n\n/**\n * Handle guest approval route.\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleGuestApprovalRoute(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n const guestApprovalMatch = pathname.match(/^\\/approvals\\/guest\\/([a-f0-9-]+)$/);\n if (!(guestApprovalMatch && req.method === \"GET\")) return false;\n\n const clientIp = getClientIp(req);\n if (sendIpRateLimit(res, clientIp, corsHeaders)) return true;\n\n const stepRunId = guestApprovalMatch[1];\n const urlParams = new URL(req.url || \"\", `http://${req.headers.host}`).searchParams;\n const action = urlParams.get(\"action\") || \"\";\n const expires = urlParams.get(\"expires\") || \"\";\n const sig = urlParams.get(\"sig\") || \"\";\n\n if (!action || !expires || !sig) { jsonResponse(res, 400, { error: \"Missing action, expires, or sig parameter\" }, corsHeaders); return true; }\n if (new Date(expires) < new Date()) { jsonResponse(res, 410, { error: \"This approval link has expired\" }, corsHeaders); return true; }\n if (!verifyGuestApprovalSignature(stepRunId, action, expires, sig)) { jsonResponse(res, 403, { error: \"Invalid signature\" }, corsHeaders); return true; }\n\n const guestSupabase = getServiceClient();\n const { data: approval } = await guestSupabase.from(\"workflow_approval_requests\").select(\"id, store_id, run_id, status\").eq(\"step_run_id\", stepRunId).limit(1);\n if (!approval?.length) { jsonResponse(res, 404, { error: \"Approval not found\" }, corsHeaders); return true; }\n if (approval[0].status !== \"pending\") { jsonResponse(res, 409, { error: `Approval already ${approval[0].status}` }, corsHeaders); return true; }\n\n const isApprove = action === \"approve\" || action === \"approved\";\n const { data: guestResult, error: guestErr } = await guestSupabase.rpc(\"respond_to_approval\", {\n p_approval_id: approval[0].id, p_store_id: approval[0].store_id,\n p_response: isApprove ? \"approved\" : \"rejected\", p_response_data: { guest: true, action }, p_responded_by: null,\n });\n\n if (guestErr) { jsonResponse(res, 500, { success: false, error: guestErr.message }, corsHeaders); return true; }\n\n if (guestResult?.success && approval[0].run_id) {\n try { await executeInlineChain(guestSupabase, approval[0].run_id); } catch (err) { log.error({ err: (err as Error).message, runId: approval[0].run_id }, \"inline chain failed after guest approval\"); }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\", ...corsHeaders });\n res.end(`<!DOCTYPE html><html><body style=\"font-family:system-ui;text-align:center;padding:40px\">\n <h2>${isApprove ? \"Approved\" : \"Rejected\"}</h2>\n <p>Your response has been recorded. You can close this window.</p>\n </body></html>`);\n return true;\n}\n\n/**\n * Handle webchat routes (messages, history, widget.js).\n * Returns true if route was handled, false otherwise.\n */\nexport async function handleWebchatRoutes(\n req: http.IncomingMessage, res: http.ServerResponse,\n pathname: string, url: URL, corsHeaders: Record<string, string>,\n): Promise<boolean> {\n const webchatCors = { ...corsHeaders, \"Access-Control-Allow-Origin\": \"*\" };\n\n // POST /webchat/channels/:id/messages\n const webchatMsgMatch = pathname.match(/^\\/webchat\\/channels\\/([a-f0-9-]+)\\/messages$/);\n if (webchatMsgMatch && req.method === \"POST\") {\n const clientIp = getClientIp(req);\n if (sendIpRateLimit(res, clientIp, webchatCors)) return true;\n\n let rawBody: string;\n try { rawBody = await readBody(req); } catch { jsonResponse(res, 413, { error: \"Request body too large\" }, webchatCors); return true; }\n\n const channelId = webchatMsgMatch[1];\n let wcBody: any;\n try { wcBody = JSON.parse(rawBody); } catch { jsonResponse(res, 400, { error: \"Invalid JSON\" }, webchatCors); return true; }\n if (!wcBody.content || typeof wcBody.content !== \"string\") { jsonResponse(res, 400, { error: \"content (string) is required\" }, webchatCors); return true; }\n if (wcBody.content.length > 5000) { jsonResponse(res, 400, { error: \"Message too long (max 5000 characters)\" }, webchatCors); return true; }\n\n const supabase = getServiceClient();\n const { data: channel } = await supabase.from(\"channels\").select(\"id, store_id, node_id, agent_id, type, config\").eq(\"id\", channelId).eq(\"type\", \"webchat\").single();\n if (!channel) { jsonResponse(res, 404, { error: \"Webchat channel not found\" }, webchatCors); return true; }\n\n try {\n const planCheck = await checkPlanLimits(supabase, channel.store_id, \"message\");\n if (!planCheck.allowed) { jsonResponse(res, 429, { error: planCheck.reason || \"Plan limit reached\" }, webchatCors); return true; }\n } catch { /* billing tables may not exist yet */ }\n\n const senderId = (wcBody.sender_id as string) || \"anonymous\";\n let conversationId: string = (wcBody.conversation_id as string) || \"\";\n if (!conversationId) {\n const thirtyMinAgo = new Date(Date.now() - 30 * 60 * 1000).toISOString();\n const { data: recent } = await supabase.from(\"channel_messages\").select(\"conversation_id\")\n .eq(\"channel_id\", channelId).eq(\"sender_id\", senderId).gt(\"created_at\", thirtyMinAgo)\n .not(\"conversation_id\", \"is\", null).order(\"created_at\", { ascending: false }).limit(1);\n conversationId = (recent?.length && recent[0].conversation_id) || randomUUID();\n }\n\n const { data: message, error: msgErr } = await supabase.from(\"channel_messages\").insert({\n store_id: channel.store_id, channel_id: channelId, direction: \"inbound\",\n sender_id: senderId, sender_name: wcBody.sender_name || \"Visitor\",\n content: wcBody.content, content_type: \"text\",\n metadata: { source: \"webchat\", ip: clientIp, widget_version: \"1.0.0\" },\n agent_id: channel.agent_id, conversation_id: conversationId,\n }).select(\"id, direction, content, conversation_id, created_at\").single();\n if (msgErr) { jsonResponse(res, 500, { error: msgErr.message }, webchatCors); return true; }\n\n incrementUsage(supabase, channel.store_id, { messages_in: 1 }).catch(() => {});\n try { await supabase.rpc(\"increment_channel_stats\", { p_channel_id: channelId }); } catch { /* ok */ }\n\n let agentResponse: any = null;\n if (channel.agent_id && webchatAgentInvoker) {\n try {\n const result = await webchatAgentInvoker(supabase, channel.agent_id, wcBody.content, channel.store_id, conversationId);\n if (result.success && result.response) {\n const { data: outMsg } = await supabase.from(\"channel_messages\").insert({\n store_id: channel.store_id, channel_id: channelId, direction: \"outbound\",\n sender_id: \"agent\", sender_name: \"AI Agent\",\n content: result.response, content_type: \"text\",\n metadata: { agent_id: channel.agent_id, auto_response: true, source: \"webchat\" },\n agent_id: channel.agent_id, conversation_id: conversationId,\n }).select(\"id, direction, content, conversation_id, created_at\").single();\n agentResponse = outMsg;\n incrementUsage(supabase, channel.store_id, { messages_out: 1, agent_invocations: 1 }).catch(() => {});\n }\n } catch (err) { log.error({ err: (err as Error).message }, \"webchat agent error\"); }\n }\n\n jsonResponse(res, 201, { success: true, message, agent_response: agentResponse, conversation_id: conversationId }, webchatCors);\n return true;\n }\n\n // GET /webchat/channels/:id/history\n const webchatHistoryMatch = pathname.match(/^\\/webchat\\/channels\\/([a-f0-9-]+)\\/history$/);\n if (webchatHistoryMatch && req.method === \"GET\") {\n const clientIp = getClientIp(req);\n if (sendIpRateLimit(res, clientIp, webchatCors)) return true;\n\n const channelId = webchatHistoryMatch[1];\n const senderId = url.searchParams.get(\"sender_id\") || \"\";\n const reqConvId = url.searchParams.get(\"conversation_id\") || \"\";\n if (!senderId) { jsonResponse(res, 400, { error: \"sender_id query parameter required\" }, webchatCors); return true; }\n\n const supabase = getServiceClient();\n const { data: wcChannel } = await supabase.from(\"channels\").select(\"id, type\").eq(\"id\", channelId).eq(\"type\", \"webchat\").single();\n if (!wcChannel) { jsonResponse(res, 404, { error: \"Webchat channel not found\" }, webchatCors); return true; }\n\n if (!/^[a-zA-Z0-9_-]+$/.test(senderId)) { jsonResponse(res, 400, { error: \"Invalid sender_id format\" }, webchatCors); return true; }\n let query = supabase.from(\"channel_messages\")\n .select(\"id, direction, sender_id, sender_name, content, content_type, created_at\")\n .eq(\"channel_id\", channelId);\n if (reqConvId) { query = query.eq(\"conversation_id\", reqConvId).in(\"sender_id\", [senderId, \"agent\"]); }\n else { query = query.in(\"sender_id\", [senderId, \"agent\"]); }\n\n const { data: messages, error: histErr } = await query.order(\"created_at\", { ascending: true }).limit(50);\n if (histErr) { jsonResponse(res, 500, { error: histErr.message }, webchatCors); return true; }\n jsonResponse(res, 200, { success: true, messages: messages || [] }, webchatCors);\n return true;\n }\n\n // GET /webchat/widget.js\n if (pathname === \"/webchat/widget.js\" && req.method === \"GET\") {\n const fs = await import(\"node:fs\");\n const path = await import(\"node:path\");\n const possiblePaths = [\n path.join(import.meta.dirname || __dirname, \"../../dist/webchat/widget.js\"),\n path.join(import.meta.dirname || __dirname, \"../../../dist/webchat/widget.js\"),\n path.join(process.cwd(), \"dist/webchat/widget.js\"),\n ];\n let widgetJs: string | null = null;\n for (const p of possiblePaths) { try { widgetJs = fs.readFileSync(p, \"utf-8\"); break; } catch { /* try next */ } }\n if (widgetJs) {\n res.writeHead(200, { \"Content-Type\": \"application/javascript\", \"Cache-Control\": \"public, max-age=3600\", ...webchatCors });\n res.end(widgetJs);\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/javascript\", ...webchatCors });\n res.end('console.warn(\"[WhaleChat] Widget JS not built. Run: npx esbuild src/webchat/widget.ts --bundle --minify --outfile=dist/webchat/widget.js\");');\n }\n return true;\n }\n\n return false;\n}\n\n// Billing and node route handling is in the main index.ts to keep this file under 300 lines\n"],"mappings":"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","ignoreList":[]}
|