@oomol-lab/open-connector 1.9.2 → 1.9.3
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/README.md +4 -2
- package/assets/open-connector/catalog/apps/allratestoday.json +174 -0
- package/assets/open-connector/catalog/apps/slackbot.json +20 -1
- package/assets/open-connector/catalog/apps-index.json +1 -1
- package/package.json +1 -1
- package/src/connection-error.d.ts +7 -0
- package/src/connection-error.js +10 -0
- package/src/connection-service.d.ts +2 -50
- package/src/connection-service.js +6 -130
- package/src/connection-store.d.ts +41 -0
- package/src/connection-store.js +1 -0
- package/src/core/guarded-fetch.d.ts +3 -0
- package/src/core/guarded-fetch.js +8 -1
- package/src/core/provider-network-policy.d.ts +15 -0
- package/src/core/provider-network-policy.js +11 -0
- package/src/core/request.d.ts +18 -14
- package/src/core/request.js +11 -35
- package/src/credential-resolver.d.ts +24 -0
- package/src/credential-resolver.js +131 -0
- package/src/mcp.js +1 -1
- package/src/oauth/oauth-client-config-service.d.ts +1 -1
- package/src/oauth/oauth-client-config-service.js +14 -2
- package/src/oauth/oauth-credential-refresh-service.js +1 -1
- package/src/oauth/oauth-flow-service.d.ts +9 -1
- package/src/oauth/oauth-flow-service.js +11 -1
- package/src/providers/abuseipdb/executors.js +3 -4
- package/src/providers/action-contracts.generated.d.ts +1 -0
- package/src/providers/addressfinder/executors.js +2 -3
- package/src/providers/aeroleads/executors.js +3 -3
- package/src/providers/affinity/runtime.js +6 -7
- package/src/providers/aftership/executors.js +2 -2
- package/src/providers/agent_mail/runtime.js +2 -2
- package/src/providers/agentql/runtime.js +2 -2
- package/src/providers/agenty/runtime.js +5 -6
- package/src/providers/agiled/runtime.d.ts +0 -1
- package/src/providers/agiled/runtime.js +2 -3
- package/src/providers/agility/runtime.js +2 -3
- package/src/providers/ahrefs/runtime.js +3 -3
- package/src/providers/aifinmarket/runtime.js +6 -7
- package/src/providers/airtable/executors.js +3 -3
- package/src/providers/alchemy/runtime.js +2 -2
- package/src/providers/algolia/runtime.js +3 -3
- package/src/providers/aliyun_oss/executors.js +7 -7
- package/src/providers/allratestoday/executors.d.ts +3 -0
- package/src/providers/allratestoday/executors.js +18 -0
- package/src/providers/allratestoday/runtime.d.ts +17 -0
- package/src/providers/allratestoday/runtime.js +104 -0
- package/src/providers/alpaca/runtime.js +2 -3
- package/src/providers/alpha_vantage/runtime.js +2 -2
- package/src/providers/alt_text_ai/runtime.js +2 -2
- package/src/providers/altiria/executors.js +3 -3
- package/src/providers/amap/runtime.js +3 -3
- package/src/providers/ambee/runtime.js +2 -2
- package/src/providers/ambivo/executors.js +3 -3
- package/src/providers/amilia/runtime.js +1 -1
- package/src/providers/amplemarket/runtime.js +2 -2
- package/src/providers/amplitude/runtime.js +3 -3
- package/src/providers/anysearch/runtime.js +4 -4
- package/src/providers/apaleo/runtime.js +2 -2
- package/src/providers/api_sports/executors.js +3 -4
- package/src/providers/apiverve/executors.js +2 -3
- package/src/providers/apollo/executors.js +2 -3
- package/src/providers/appcircle/runtime.js +5 -5
- package/src/providers/appdrag/executors.js +2 -3
- package/src/providers/arcgis_online/executors.js +2 -2
- package/src/providers/auth0_management/runtime.js +2 -3
- package/src/providers/autoblogger/executors.js +3 -3
- package/src/providers/baidu_maps/runtime.js +3 -3
- package/src/providers/baidu_netdisk/runtime-mcp.js +3 -4
- package/src/providers/bark/executors.js +5 -5
- package/src/providers/bitrise/runtime.js +3 -3
- package/src/providers/bouncer/executors.js +3 -4
- package/src/providers/browse_ai/runtime.js +3 -4
- package/src/providers/browserstack/executors.js +6 -7
- package/src/providers/buildkite/runtime.js +3 -3
- package/src/providers/bunnycdn/runtime.js +3 -3
- package/src/providers/businessmap/runtime.js +6 -7
- package/src/providers/buttondown/runtime.js +2 -2
- package/src/providers/byteforms/runtime.js +2 -2
- package/src/providers/calendly/runtime.js +2 -2
- package/src/providers/captainbi/runtime.js +6 -6
- package/src/providers/castingwords/runtime.js +1 -1
- package/src/providers/chatpdf/runtime.js +4 -4
- package/src/providers/check/executors.js +3 -4
- package/src/providers/checkly/executors.js +3 -4
- package/src/providers/chengxin/runtime.js +3 -3
- package/src/providers/cincopa/executors.js +3 -4
- package/src/providers/circle/executors.js +3 -4
- package/src/providers/clearout/executors.js +1 -2
- package/src/providers/clickhelp/runtime.js +5 -5
- package/src/providers/clickhouse/runtime.js +4 -4
- package/src/providers/clinicalkey/runtime.js +3 -3
- package/src/providers/clinicaltrials_gov/runtime.js +4 -5
- package/src/providers/clockify/runtime.js +4 -4
- package/src/providers/close/runtime.js +3 -3
- package/src/providers/cloudconvert/runtime.js +8 -9
- package/src/providers/cloudflare_dns/runtime.js +2 -2
- package/src/providers/cloudflare_email_routing/runtime.js +2 -2
- package/src/providers/cloudflare_r2/runtime.js +5 -5
- package/src/providers/cloudflare_worker/runtime.js +10 -10
- package/src/providers/cloudinary/runtime.js +4 -4
- package/src/providers/cloudlayer/runtime.js +5 -5
- package/src/providers/codacy/runtime.js +2 -2
- package/src/providers/codemagic/runtime.js +2 -2
- package/src/providers/confluence/executors.js +4 -4
- package/src/providers/confluence/runtime.d.ts +0 -1
- package/src/providers/confluence/runtime.js +6 -7
- package/src/providers/contactout/runtime.js +5 -5
- package/src/providers/contentful/runtime.js +2 -2
- package/src/providers/contentstack_content_delivery/runtime.js +1 -1
- package/src/providers/cronly/runtime.js +2 -2
- package/src/providers/crossref/runtime.js +3 -3
- package/src/providers/cutt_ly/runtime.js +3 -3
- package/src/providers/cyberimpact/runtime.js +3 -3
- package/src/providers/dachser/executors.js +2 -2
- package/src/providers/dailybot/runtime.js +1 -1
- package/src/providers/databox/runtime.js +2 -2
- package/src/providers/databricks/runtime.js +2 -2
- package/src/providers/datacite/runtime.js +1 -1
- package/src/providers/datadog/executors.js +3 -4
- package/src/providers/datascope/runtime.js +2 -2
- package/src/providers/daytona/executors.js +3 -3
- package/src/providers/deepgram/runtime.js +2 -2
- package/src/providers/deepl/runtime.js +4 -4
- package/src/providers/detrack/executors.js +5 -5
- package/src/providers/deutschlandgpt/runtime.js +2 -2
- package/src/providers/dialmycalls/runtime.js +4 -4
- package/src/providers/diffbot/executors.js +4 -4
- package/src/providers/digistore24/executors.js +3 -3
- package/src/providers/dingtalk_bot/executors.js +1 -1
- package/src/providers/discourse/executors.d.ts +0 -1
- package/src/providers/discourse/executors.js +6 -7
- package/src/providers/docugenerate/runtime.js +3 -3
- package/src/providers/doppler/runtime.shared.js +3 -3
- package/src/providers/doppler_marketing_automation/runtime.js +4 -4
- package/src/providers/dovetail/runtime.js +2 -2
- package/src/providers/dropcontact/runtime.js +3 -3
- package/src/providers/dub/executors.js +6 -6
- package/src/providers/dumplingai/runtime.js +2 -2
- package/src/providers/elevenlabs/executors.js +4 -4
- package/src/providers/elevenreader/runtime.js +1 -1
- package/src/providers/emailoctopus/runtime.js +4 -4
- package/src/providers/embase/runtime.js +3 -3
- package/src/providers/emelia/executors.js +2 -2
- package/src/providers/enigma/executors.js +3 -3
- package/src/providers/eodhd_apis/executors.js +2 -2
- package/src/providers/eventzilla/runtime.js +3 -4
- package/src/providers/evervault/runtime.js +1 -1
- package/src/providers/excalidraw_mcp/runtime.js +3 -4
- package/src/providers/excel/runtime.js +6 -6
- package/src/providers/expofp/runtime.js +2 -2
- package/src/providers/faktoora/runtime.js +5 -5
- package/src/providers/fast_note_sync/runtime.js +2 -2
- package/src/providers/feathery/executors.js +2 -3
- package/src/providers/feishu_app_bot/executors.js +2 -3
- package/src/providers/feishu_custom_bot/executors.js +2 -3
- package/src/providers/ffhub/executors.js +2 -3
- package/src/providers/fidel_api/executors.js +2 -3
- package/src/providers/files_com/executors.js +2 -3
- package/src/providers/fireberry/runtime.d.ts +0 -1
- package/src/providers/fireberry/runtime.js +3 -4
- package/src/providers/firehydrant/executors.js +2 -3
- package/src/providers/float/executors.js +2 -3
- package/src/providers/flomo/executors.js +5 -6
- package/src/providers/flowiseai/executors.js +2 -3
- package/src/providers/fluxguard/executors.js +2 -3
- package/src/providers/folk/executors.js +2 -3
- package/src/providers/football_data/executors.js +2 -3
- package/src/providers/forem/executors.js +2 -3
- package/src/providers/formbricks/executors.js +2 -3
- package/src/providers/formsite/executors.js +3 -4
- package/src/providers/formspree/executors.js +2 -2
- package/src/providers/freshdesk/executors.js +3 -4
- package/src/providers/freshservice/executors.js +3 -4
- package/src/providers/freshteam/runtime.js +3 -4
- package/src/providers/full_contact/executors.js +3 -3
- package/src/providers/fusion-api/runtime.js +2 -3
- package/src/providers/gagelist/executors.js +3 -3
- package/src/providers/gainsight_nxt/executors.js +2 -2
- package/src/providers/gamma/executors.js +4 -3
- package/src/providers/gangtise/runtime.js +3 -4
- package/src/providers/gatherup/runtime.js +1 -1
- package/src/providers/geckoboard/executors.js +2 -3
- package/src/providers/gemini/runtime.d.ts +0 -1
- package/src/providers/gemini/runtime.js +5 -6
- package/src/providers/genpage/runtime.js +2 -2
- package/src/providers/geokeo/executors.js +4 -4
- package/src/providers/getnote/runtime.js +2 -3
- package/src/providers/github/runtime-shared.js +2 -2
- package/src/providers/glyphic/runtime.js +3 -4
- package/src/providers/gmail/executors.js +125 -27
- package/src/providers/gong/runtime.js +6 -7
- package/src/providers/googlecalendar/runtime-shared.js +3 -4
- package/src/providers/googledrive/runtime-request.js +2 -3
- package/src/providers/googlesheets/runtime-shared.js +3 -4
- package/src/providers/gorgias/runtime.js +4 -4
- package/src/providers/gotify/executors.js +7 -8
- package/src/providers/greenhouse/executors.js +3 -3
- package/src/providers/gumloop/executors.js +2 -3
- package/src/providers/gumroad/executors.js +2 -3
- package/src/providers/habitica/executors.js +2 -3
- package/src/providers/hackerrank_work/executors.js +2 -3
- package/src/providers/harvest/executors.js +3 -4
- package/src/providers/haveibeenpwned/executors.js +2 -3
- package/src/providers/headout/executors.js +3 -4
- package/src/providers/healthchecks_io/executors.js +2 -3
- package/src/providers/helium10/runtime.js +4 -5
- package/src/providers/helpdesk/runtime.js +4 -4
- package/src/providers/home_assistant/runtime-ws.js +9 -10
- package/src/providers/hotjar/executors.js +4 -4
- package/src/providers/httpsms/runtime.js +3 -4
- package/src/providers/hub_planner/executors.js +3 -3
- package/src/providers/hubspot/runtime.js +3 -4
- package/src/providers/humaans/runtime.js +3 -3
- package/src/providers/hunter/runtime.js +3 -3
- package/src/providers/icypeas/executors.js +3 -4
- package/src/providers/ima/runtime.js +7 -7
- package/src/providers/infolobby/runtime.js +6 -6
- package/src/providers/instabot/runtime.js +6 -6
- package/src/providers/instatus/runtime.js +4 -4
- package/src/providers/intuiface/executors.js +3 -3
- package/src/providers/iplocate/runtime.js +4 -5
- package/src/providers/ipregistry/executors.js +2 -2
- package/src/providers/jiminny/runtime.js +4 -4
- package/src/providers/jin10/executors.js +4 -5
- package/src/providers/jira/executors.js +4 -4
- package/src/providers/kaleido/runtime.js +2 -2
- package/src/providers/kandji/runtime.js +2 -2
- package/src/providers/keygen/executors.js +4 -4
- package/src/providers/keyword/runtime.js +2 -2
- package/src/providers/kie_ai/executors.js +1 -1
- package/src/providers/kintone/runtime.js +1 -1
- package/src/providers/kit/runtime.js +2 -2
- package/src/providers/klangio/runtime.js +4 -4
- package/src/providers/klaviyo/executors.js +1 -1
- package/src/providers/klazify/executors.js +3 -3
- package/src/providers/klipfolio/runtime.js +3 -3
- package/src/providers/knack/executors.js +1 -1
- package/src/providers/kommo/runtime.js +2 -2
- package/src/providers/kontent_ai/executors.js +3 -4
- package/src/providers/l2s/executors.js +3 -4
- package/src/providers/latchshot/executors.js +2 -2
- package/src/providers/leadboxer/runtime.js +4 -4
- package/src/providers/leadiq/runtime.js +4 -4
- package/src/providers/linguapop/runtime.js +1 -1
- package/src/providers/lingvanex_translation_api/runtime.js +5 -6
- package/src/providers/lingxing_mcp/runtime.js +3 -4
- package/src/providers/linkup/runtime.js +5 -6
- package/src/providers/liveagent/executors.js +6 -6
- package/src/providers/loops/executors.js +2 -2
- package/src/providers/loyjoy/runtime.js +2 -2
- package/src/providers/loyverse/executors.js +4 -4
- package/src/providers/lusha/runtime.js +3 -3
- package/src/providers/mailbluster/runtime.js +3 -4
- package/src/providers/mailcoach/runtime.js +4 -4
- package/src/providers/mailgenius/executors.js +3 -4
- package/src/providers/mailjet/runtime.js +3 -3
- package/src/providers/mails_so/runtime.js +1 -1
- package/src/providers/mailsoftly/runtime.js +5 -5
- package/src/providers/mailtrap/runtime.js +4 -5
- package/src/providers/manus/runtime.js +3 -3
- package/src/providers/mautic/runtime.js +3 -3
- package/src/providers/megaventory/runtime.js +3 -3
- package/src/providers/memberstack/runtime.js +2 -2
- package/src/providers/mendeley/executors.js +2 -3
- package/src/providers/mindbody/runtime.js +3 -3
- package/src/providers/minerstat/executors.js +3 -3
- package/src/providers/mintlify/runtime.js +3 -3
- package/src/providers/missive/executors.js +3 -5
- package/src/providers/mixpanel/executors.js +3 -3
- package/src/providers/mobile_text_alerts/runtime.js +3 -3
- package/src/providers/mocean/executors.js +3 -3
- package/src/providers/moco/executors.js +5 -5
- package/src/providers/moesif/runtime.js +4 -4
- package/src/providers/monday/runtime-common.js +3 -3
- package/src/providers/monica_crm/runtime.js +4 -4
- package/src/providers/moorcheh/runtime.js +3 -3
- package/src/providers/more_trees/runtime.d.ts +0 -1
- package/src/providers/more_trees/runtime.js +7 -8
- package/src/providers/moxie/runtime.js +2 -2
- package/src/providers/msg91/runtime.js +4 -4
- package/src/providers/mx/runtime.js +1 -1
- package/src/providers/needle/runtime.js +3 -4
- package/src/providers/netlify/runtime.js +2 -3
- package/src/providers/niftyimages/executors.js +2 -2
- package/src/providers/northbeam/runtime.js +1 -1
- package/src/providers/nozbe_teams/executors.js +4 -4
- package/src/providers/npm/runtime.js +4 -4
- package/src/providers/nusii_proposals/runtime.js +2 -2
- package/src/providers/ocr_web_service/executors.js +4 -4
- package/src/providers/octopus_deploy/executors.js +3 -3
- package/src/providers/oksign/runtime.js +3 -4
- package/src/providers/one_drive/executors.js +6 -6
- package/src/providers/one_password_events/runtime.js +1 -1
- package/src/providers/onfleet/runtime.js +3 -3
- package/src/providers/onlyoffice_docspace/runtime.js +4 -4
- package/src/providers/oomnitza/runtime.js +3 -4
- package/src/providers/otter_ai/executors.js +2 -2
- package/src/providers/oura/runtime.js +1 -1
- package/src/providers/paddle/executors.js +3 -3
- package/src/providers/pagerduty/runtime.js +2 -2
- package/src/providers/paradym/runtime.js +4 -4
- package/src/providers/parallel/runtime.js +3 -3
- package/src/providers/partner_stack_partner/runtime.js +1 -1
- package/src/providers/payrexx/runtime.js +5 -6
- package/src/providers/permit_io/runtime.js +2 -2
- package/src/providers/pinboard/executors.js +5 -6
- package/src/providers/pinpoint/runtime.js +2 -2
- package/src/providers/placid/runtime.js +3 -3
- package/src/providers/plain/runtime.js +5 -5
- package/src/providers/planetscale/runtime.js +2 -2
- package/src/providers/planhat/executors.js +6 -6
- package/src/providers/plausible_analytics/runtime.js +3 -3
- package/src/providers/posthog/runtime.js +3 -3
- package/src/providers/predis_ai/executors.js +3 -3
- package/src/providers/printavo/runtime.js +2 -2
- package/src/providers/prospeo/runtime.js +2 -3
- package/src/providers/provider-runtime.d.ts +13 -1
- package/src/providers/provider-runtime.js +25 -10
- package/src/providers/push_by_techulus/executors.js +3 -4
- package/src/providers/pushover/runtime.js +4 -5
- package/src/providers/pushsafer/runtime.js +4 -5
- package/src/providers/pylon/runtime.js +2 -2
- package/src/providers/qase/runtime.js +3 -3
- package/src/providers/qdrant/runtime.js +1 -1
- package/src/providers/qichacha/runtime.js +2 -2
- package/src/providers/qingflow/runtime.js +2 -2
- package/src/providers/quickchart/runtime.js +2 -2
- package/src/providers/quintadb/runtime.js +2 -2
- package/src/providers/quo/runtime.js +2 -2
- package/src/providers/rawg/runtime.js +4 -4
- package/src/providers/razorpay/runtime.js +4 -5
- package/src/providers/readme/runtime.js +6 -6
- package/src/providers/referralhero/runtime.js +3 -3
- package/src/providers/registry.generated.js +1 -0
- package/src/providers/render/executors.js +3 -3
- package/src/providers/respond_io/executors.js +3 -3
- package/src/providers/reversecontact/runtime.js +3 -3
- package/src/providers/ritekit/executors.js +2 -2
- package/src/providers/riveter/executors.js +2 -3
- package/src/providers/rocket_chat/executors.js +3 -4
- package/src/providers/rocket_reach/executors.js +3 -4
- package/src/providers/saucelabs/runtime.js +4 -4
- package/src/providers/scopus/runtime.js +3 -3
- package/src/providers/scrape_do/executors.js +2 -2
- package/src/providers/scraperapi/runtime.js +4 -4
- package/src/providers/scrapfly/executors.js +2 -2
- package/src/providers/scrapingant/executors.js +6 -7
- package/src/providers/scrapingbee/executors.js +3 -3
- package/src/providers/scrapingdog/executors.js +1 -1
- package/src/providers/screenshot_fyi/executors.js +3 -4
- package/src/providers/screenshotbase/runtime.js +3 -3
- package/src/providers/search_api/runtime.js +2 -2
- package/src/providers/securitytrails/executors.js +2 -2
- package/src/providers/semantic_scholar/executors.js +2 -2
- package/src/providers/sendbird/executors.js +2 -2
- package/src/providers/sendfox/executors.js +3 -3
- package/src/providers/sendgrid/executors.js +5 -5
- package/src/providers/sendmator/runtime.js +3 -4
- package/src/providers/seqera/runtime.js +3 -4
- package/src/providers/serveravatar/executors.js +3 -3
- package/src/providers/sheetdb/runtime.js +2 -2
- package/src/providers/short_menu/runtime.js +3 -3
- package/src/providers/shortcut/runtime.js +3 -3
- package/src/providers/shortpixel/runtime.js +2 -2
- package/src/providers/shotstack/runtime.js +4 -4
- package/src/providers/signpath/runtime.js +2 -2
- package/src/providers/signwell/runtime.js +5 -6
- package/src/providers/similarweb_digitalrank_api/runtime.js +3 -3
- package/src/providers/simla/runtime.js +5 -5
- package/src/providers/simplybook_me/executors.js +6 -6
- package/src/providers/sitespeakai/runtime.js +3 -3
- package/src/providers/slickdeals/runtime.js +2 -3
- package/src/providers/smartsuite/runtime.js +3 -3
- package/src/providers/sonarcloud/runtime.js +5 -5
- package/src/providers/sorftime/runtime.js +8 -8
- package/src/providers/spider/runtime.js +2 -2
- package/src/providers/splunk_http_event_collector/runtime.js +7 -8
- package/src/providers/sportsdata/runtime.js +4 -4
- package/src/providers/spyfu/runtime.js +4 -5
- package/src/providers/square/runtime.js +4 -4
- package/src/providers/stannp/runtime.js +2 -2
- package/src/providers/stripe/executors.js +2 -2
- package/src/providers/supermemory/runtime.js +3 -3
- package/src/providers/survey_monkey/runtime.js +3 -3
- package/src/providers/taiga/runtime.js +4 -4
- package/src/providers/talenox/executors.js +4 -4
- package/src/providers/tally/runtime.js +3 -3
- package/src/providers/tavily/runtime.js +3 -4
- package/src/providers/teamcamp/executors.js +2 -2
- package/src/providers/teamtailor/executors.js +2 -2
- package/src/providers/telegram/executors.js +6 -7
- package/src/providers/teltel/executors.js +2 -2
- package/src/providers/templated/executors.js +3 -3
- package/src/providers/tencent_docs/runtime.js +4 -4
- package/src/providers/tencent_maps/runtime.js +3 -3
- package/src/providers/textcortex/runtime.js +3 -3
- package/src/providers/the_cat_api/runtime.js +3 -3
- package/src/providers/the_colony/runtime.js +3 -3
- package/src/providers/the_odds_api/runtime.js +3 -4
- package/src/providers/the_official_board/runtime.js +4 -4
- package/src/providers/thehive/runtime.js +1 -1
- package/src/providers/tikhub/endpoint-catalog.js +2 -3
- package/src/providers/tiktok_business/runtime.js +2 -2
- package/src/providers/timecamp/runtime.js +2 -2
- package/src/providers/timelink/runtime.js +2 -2
- package/src/providers/totp/runtime.js +4 -5
- package/src/providers/trawlingweb/runtime.js +2 -2
- package/src/providers/trilium/runtime.js +2 -2
- package/src/providers/triple_whale/runtime.js +3 -3
- package/src/providers/truvera/runtime.js +2 -2
- package/src/providers/tuskr/runtime.js +2 -2
- package/src/providers/typebot/runtime.js +2 -2
- package/src/providers/typeform/runtime.js +2 -2
- package/src/providers/uptimerobot/executors.js +3 -4
- package/src/providers/v2ex/runtime.js +8 -9
- package/src/providers/valyu/runtime.js +3 -3
- package/src/providers/vapi/runtime.js +4 -4
- package/src/providers/vectorshift/runtime.js +3 -3
- package/src/providers/venafitlsprotectcloud/runtime.js +2 -3
- package/src/providers/venafitlsprotectdatacenter/runtime.js +2 -3
- package/src/providers/vida/runtime.js +4 -4
- package/src/providers/vonage/runtime.js +3 -3
- package/src/providers/walmart_marketplace/runtime.js +5 -5
- package/src/providers/weatherapi/executors.js +3 -4
- package/src/providers/web_of_science/runtime.js +4 -4
- package/src/providers/web_of_science_expanded/runtime.js +9 -9
- package/src/providers/webex/runtime.js +3 -3
- package/src/providers/webinarjam/runtime.js +4 -4
- package/src/providers/webscraping_ai/runtime.js +3 -3
- package/src/providers/webvizio/runtime.js +3 -4
- package/src/providers/wecom_bot/smart-runtime.js +4 -5
- package/src/providers/wecom_mcp/runtime.js +3 -4
- package/src/providers/wejam_ai/runtime.js +3 -3
- package/src/providers/wolfram_alpha_api/runtime.js +3 -3
- package/src/providers/woocommerce/runtime.js +1 -1
- package/src/providers/woodpecker_co/executors.js +3 -4
- package/src/providers/woot/runtime.js +6 -6
- package/src/providers/workable/runtime.js +3 -3
- package/src/providers/workday/runtime.js +4 -4
- package/src/providers/workiom/runtime.js +2 -2
- package/src/providers/workiz/runtime.js +2 -2
- package/src/providers/workpath/executors.js +3 -4
- package/src/providers/worksnaps/executors.js +2 -2
- package/src/providers/y_gy/runtime.js +2 -2
- package/src/providers/zenscrape/runtime.js +3 -3
- package/src/providers/zep/runtime.js +4 -4
- package/src/providers/zeplin/runtime.js +2 -2
- package/src/providers/zhihu/executors.js +6 -6
- package/src/providers/zylvie/runtime.js +4 -4
- package/src/saas/saas-cleanup-service.d.ts +2 -0
- package/src/saas/saas-cleanup-service.js +2 -1
- package/src/saas/saas-execution-service.d.ts +1 -1
- package/src/server/actions/action-runner.js +1 -1
- package/src/server/api/auth.js +3 -0
- package/src/server/api/connection-routes.js +1 -1
- package/src/server/api/console-catalog-routes.js +1 -1
- package/src/server/api/console-oauth-routes.d.ts +3 -1
- package/src/server/api/console-oauth-routes.js +22 -9
- package/src/server/api/oauth-completion-page.d.ts +57 -0
- package/src/server/api/oauth-completion-page.js +135 -10
- package/src/server/api/openapi.d.ts +5 -0
- package/src/server/api/openapi.js +62 -2
- package/src/server/api/runtime-api.d.ts +2 -1
- package/src/server/api/runtime-app-routes.js +1 -1
- package/src/server/api/runtime-execution-routes.js +2 -1
- package/src/server/connect-app.d.ts +4 -0
- package/src/server/connect-app.js +14 -1
- package/src/server/connect-server.d.ts +6 -0
- package/src/server/connect-server.js +114 -4
- package/src/server/connector-runtime.d.ts +6 -8
- package/src/server/connector-runtime.js +8 -28
- package/src/server/proxy/proxy-runner.js +1 -1
- package/src/server/slack-event-verification.d.ts +37 -0
- package/src/server/slack-event-verification.js +91 -0
- package/src/server/storage/connection-request-store.d.ts +1 -1
- package/src/server/storage/connection-store.d.ts +1 -1
- package/src/server/storage/postgres/runtime-store.d.ts +1 -1
- package/src/server/storage/runtime-database.d.ts +1 -1
- package/src/server/storage/saas-project-store.d.ts +1 -1
- package/src/triggers/maintenance.d.ts +2 -0
- package/src/triggers/maintenance.js +2 -1
- package/src/triggers/sources/slack-signature.d.ts +10 -0
- package/src/triggers/sources/slack-signature.js +13 -0
- package/src/triggers/sources/slack.js +9 -11
- package/src/triggers/trigger-runner.js +1 -1
|
@@ -23,6 +23,10 @@ export const oauthCompletionStrings = {
|
|
|
23
23
|
network: "Could not reach Connect. Check your connection and try again.",
|
|
24
24
|
notFound: "This request was not found or has expired. Return to the initiating client.",
|
|
25
25
|
forbidden: "Synchronization was rejected. Check that OOMOL_CONNECT_ORIGIN matches your Console address.",
|
|
26
|
+
refusedBadge: "Not connected",
|
|
27
|
+
cancelledTitle: "Authorization cancelled",
|
|
28
|
+
refusedTitle: "Authorization not completed",
|
|
29
|
+
refusedBody: "Nothing was connected. Close this window to return where you started.",
|
|
26
30
|
},
|
|
27
31
|
"zh-CN": {
|
|
28
32
|
badge: "已连接",
|
|
@@ -43,6 +47,10 @@ export const oauthCompletionStrings = {
|
|
|
43
47
|
network: "无法连接到 Connect,请检查网络后重试。",
|
|
44
48
|
notFound: "授权请求不存在或已过期,请返回发起授权的应用。",
|
|
45
49
|
forbidden: "同步请求被拒绝,请检查 OOMOL_CONNECT_ORIGIN 是否与控制台地址一致。",
|
|
50
|
+
refusedBadge: "未连接",
|
|
51
|
+
cancelledTitle: "已取消授权",
|
|
52
|
+
refusedTitle: "授权未完成",
|
|
53
|
+
refusedBody: "未建立任何连接。关闭此窗口即可返回刚才的应用。",
|
|
46
54
|
},
|
|
47
55
|
"zh-TW": {
|
|
48
56
|
badge: "已連線",
|
|
@@ -63,6 +71,10 @@ export const oauthCompletionStrings = {
|
|
|
63
71
|
network: "無法連線至 Connect,請檢查網路後重試。",
|
|
64
72
|
notFound: "授權請求不存在或已過期,請返回發起授權的應用。",
|
|
65
73
|
forbidden: "同步請求遭拒,請檢查 OOMOL_CONNECT_ORIGIN 是否與控制台位址一致。",
|
|
74
|
+
refusedBadge: "未連線",
|
|
75
|
+
cancelledTitle: "已取消授權",
|
|
76
|
+
refusedTitle: "授權未完成",
|
|
77
|
+
refusedBody: "未建立任何連線。關閉此視窗即可返回剛才的應用。",
|
|
66
78
|
},
|
|
67
79
|
ja: {
|
|
68
80
|
badge: "接続済み",
|
|
@@ -83,6 +95,10 @@ export const oauthCompletionStrings = {
|
|
|
83
95
|
network: "Connect に接続できません。ネットワークを確認して再試行してください。",
|
|
84
96
|
notFound: "リクエストが見つからないか期限切れです。元のアプリに戻ってください。",
|
|
85
97
|
forbidden: "同期が拒否されました。OOMOL_CONNECT_ORIGIN とコンソールのアドレスを確認してください。",
|
|
98
|
+
refusedBadge: "未接続",
|
|
99
|
+
cancelledTitle: "認可をキャンセルしました",
|
|
100
|
+
refusedTitle: "認可は完了しませんでした",
|
|
101
|
+
refusedBody: "接続は作成されていません。このウィンドウを閉じて元のアプリに戻ってください。",
|
|
86
102
|
},
|
|
87
103
|
fr: {
|
|
88
104
|
badge: "Connecté",
|
|
@@ -103,6 +119,10 @@ export const oauthCompletionStrings = {
|
|
|
103
119
|
network: "Connect est inaccessible. Vérifiez votre connexion et réessayez.",
|
|
104
120
|
notFound: "Cette demande est introuvable ou expirée. Revenez à l’application de départ.",
|
|
105
121
|
forbidden: "Synchronisation refusée. Vérifiez que OOMOL_CONNECT_ORIGIN correspond à l’adresse de la Console.",
|
|
122
|
+
refusedBadge: "Non connecté",
|
|
123
|
+
cancelledTitle: "Autorisation annulée",
|
|
124
|
+
refusedTitle: "Autorisation non terminée",
|
|
125
|
+
refusedBody: "Aucune connexion n’a été créée. Fermez cette fenêtre pour revenir à l’application de départ.",
|
|
106
126
|
},
|
|
107
127
|
ru: {
|
|
108
128
|
badge: "Подключено",
|
|
@@ -123,6 +143,10 @@ export const oauthCompletionStrings = {
|
|
|
123
143
|
network: "Нет связи с Connect. Проверьте сеть и повторите попытку.",
|
|
124
144
|
notFound: "Запрос не найден или истёк. Вернитесь в исходное приложение.",
|
|
125
145
|
forbidden: "Синхронизация отклонена. Проверьте соответствие OOMOL_CONNECT_ORIGIN адресу консоли.",
|
|
146
|
+
refusedBadge: "Не подключено",
|
|
147
|
+
cancelledTitle: "Авторизация отменена",
|
|
148
|
+
refusedTitle: "Авторизация не завершена",
|
|
149
|
+
refusedBody: "Подключение не создано. Закройте это окно, чтобы вернуться в исходное приложение.",
|
|
126
150
|
},
|
|
127
151
|
};
|
|
128
152
|
export const oauthCompletionStyles = `
|
|
@@ -239,6 +263,20 @@ a.button{text-decoration:none}
|
|
|
239
263
|
export const oauthCompletionLocaleScript = `const pick=()=>{try{const stored=localStorage.getItem("oomol-connect.lang");if(Object.hasOwn(STR,stored))return stored;}catch{}const langs=navigator.languages&&navigator.languages.length?navigator.languages:[navigator.language||"en"];for(const raw of langs){const l=String(raw).toLowerCase();if(l.startsWith("zh"))return (!l.includes("hans")&&(l.includes("tw")||l.includes("hk")||l.includes("mo")||l.includes("hant")))?"zh-TW":"zh-CN";const primary=l.split("-")[0];if(STR[raw])return raw;if(STR[primary])return primary;}return "en";};`;
|
|
240
264
|
/** Seconds the OAuth completion page counts down before it tries to close its window. */
|
|
241
265
|
export const DEFAULT_OAUTH_CLOSE_DELAY_SECONDS = 5;
|
|
266
|
+
// Shared by every page this module renders: count down, then close the window,
|
|
267
|
+
// or say it can be closed when the browser refuses.
|
|
268
|
+
function oauthCloseWindowScript(closeDelaySeconds) {
|
|
269
|
+
return `const note=document.querySelector("[data-close-note]");
|
|
270
|
+
const button=document.querySelector("[data-t=closeButton]");
|
|
271
|
+
const showManual=()=>{if(note)note.textContent=t.manualClose;};
|
|
272
|
+
// window.close() only works for script-opened windows; on a tab the user
|
|
273
|
+
// navigated to it is a no-op. Attempt it, then fall back to a manual hint.
|
|
274
|
+
const tryClose=()=>{window.close();setTimeout(showManual,300);};
|
|
275
|
+
if(button)button.addEventListener("click",tryClose);
|
|
276
|
+
let remaining=${scriptJson(closeDelaySeconds)};
|
|
277
|
+
const tick=()=>{if(remaining<=0){tryClose();return;}if(note)note.textContent=t.autoClose.replace("%N%",String(remaining));remaining-=1;setTimeout(tick,1000);};
|
|
278
|
+
tick();`;
|
|
279
|
+
}
|
|
242
280
|
export function renderOAuthCompletionPage(service, closeDelaySeconds = DEFAULT_OAUTH_CLOSE_DELAY_SECONDS) {
|
|
243
281
|
const payload = scriptJson({
|
|
244
282
|
type: oauthCompletedType,
|
|
@@ -272,16 +310,7 @@ const t=STR[pick()]||STR.en;
|
|
|
272
310
|
document.documentElement.lang=pick();
|
|
273
311
|
for(const el of document.querySelectorAll("[data-t]")){const key=el.getAttribute("data-t");if(t[key]!=null)el.textContent=t[key];}
|
|
274
312
|
if(t.title)document.title=t.title;
|
|
275
|
-
|
|
276
|
-
const button=document.querySelector("[data-t=closeButton]");
|
|
277
|
-
const showManual=()=>{if(note)note.textContent=t.manualClose;};
|
|
278
|
-
// window.close() only works for script-opened windows; on a tab the user
|
|
279
|
-
// navigated to it is a no-op. Attempt it, then fall back to a manual hint.
|
|
280
|
-
const tryClose=()=>{window.close();setTimeout(showManual,300);};
|
|
281
|
-
if(button)button.addEventListener("click",tryClose);
|
|
282
|
-
let remaining=${scriptJson(closeDelaySeconds)};
|
|
283
|
-
const tick=()=>{if(remaining<=0){tryClose();return;}if(note)note.textContent=t.autoClose.replace("%N%",String(remaining));remaining-=1;setTimeout(tick,1000);};
|
|
284
|
-
tick();
|
|
313
|
+
${oauthCloseWindowScript(closeDelaySeconds)}
|
|
285
314
|
})();</script>
|
|
286
315
|
</body>
|
|
287
316
|
</html>`;
|
|
@@ -289,3 +318,99 @@ tick();
|
|
|
289
318
|
function scriptJson(value) {
|
|
290
319
|
return JSON.stringify(value).replaceAll("<", "\\u003c");
|
|
291
320
|
}
|
|
321
|
+
/** The `type` of the message a refusal page posts to the window that opened it. */
|
|
322
|
+
export const oauthRefusedType = "oauth.refused";
|
|
323
|
+
/**
|
|
324
|
+
* Reads the origins a refusal page may post its result to: a comma-separated
|
|
325
|
+
* list of exact HTTP(S) origins. `*` and anything that is not an origin are
|
|
326
|
+
* rejected, so the result can never be broadcast to an arbitrary opener.
|
|
327
|
+
*/
|
|
328
|
+
export function parseOAuthResultOrigins(value) {
|
|
329
|
+
return normalizeOAuthResultOrigins((value ?? "").split(","));
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The same rules for origins given as a list, such as the `oauthResultOrigins`
|
|
333
|
+
* runtime option: blank entries are skipped and duplicates dropped; anything
|
|
334
|
+
* that is not an exact http(s) origin, `*` included, throws.
|
|
335
|
+
*/
|
|
336
|
+
export function normalizeOAuthResultOrigins(entries) {
|
|
337
|
+
const origins = [];
|
|
338
|
+
for (const raw of entries) {
|
|
339
|
+
const entry = raw.trim().replace(/\/+$/, "");
|
|
340
|
+
if (!entry)
|
|
341
|
+
continue;
|
|
342
|
+
let origin;
|
|
343
|
+
try {
|
|
344
|
+
const url = new URL(entry);
|
|
345
|
+
if (url.protocol === "http:" || url.protocol === "https:")
|
|
346
|
+
origin = url.origin;
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
origin = undefined;
|
|
350
|
+
}
|
|
351
|
+
if (origin !== entry) {
|
|
352
|
+
throw new Error(`OAuth result origin "${entry}" must be an exact http(s) origin such as https://console.example.com.`);
|
|
353
|
+
}
|
|
354
|
+
if (!origins.includes(origin))
|
|
355
|
+
origins.push(origin);
|
|
356
|
+
}
|
|
357
|
+
return origins;
|
|
358
|
+
}
|
|
359
|
+
/** A provider error code that is safe to echo: short and code-shaped, else `provider_error`. */
|
|
360
|
+
export function oauthProviderErrorCode(providerError) {
|
|
361
|
+
return /^[A-Za-z0-9_.-]{1,64}$/.test(providerError) ? providerError : "provider_error";
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* The page a provider's refusal lands on when the authorization has no return
|
|
365
|
+
* address. When this window was opened by a page on an allowed origin, it
|
|
366
|
+
* posts `{ type: "oauth.refused", status, code, state }` to that origin only;
|
|
367
|
+
* either way the shared countdown closes it after `closeDelaySeconds`. Success is never
|
|
368
|
+
* reported this way: the opener learns it from its own server.
|
|
369
|
+
*/
|
|
370
|
+
export function renderOAuthRefusedPage(input) {
|
|
371
|
+
const closeDelaySeconds = input.closeDelaySeconds ?? DEFAULT_OAUTH_CLOSE_DELAY_SECONDS;
|
|
372
|
+
const cancelled = input.code === "access_denied";
|
|
373
|
+
const titleKey = cancelled ? "cancelledTitle" : "refusedTitle";
|
|
374
|
+
const strings = oauthCompletionStrings.en;
|
|
375
|
+
const result = {
|
|
376
|
+
type: oauthRefusedType,
|
|
377
|
+
status: cancelled ? "cancelled" : "error",
|
|
378
|
+
code: input.code,
|
|
379
|
+
state: input.state,
|
|
380
|
+
};
|
|
381
|
+
const codeLine = cancelled ? "" : `\n <p><code>${input.code}</code></p>`;
|
|
382
|
+
const postScript = input.resultOrigins.length > 0 && input.state
|
|
383
|
+
? `if(window.opener){const result=${scriptJson(result)};for(const origin of ${scriptJson(input.resultOrigins)}){try{window.opener.postMessage(result,origin);}catch{}}}\n`
|
|
384
|
+
: "";
|
|
385
|
+
return `<!doctype html>
|
|
386
|
+
<html lang="en">
|
|
387
|
+
<head>
|
|
388
|
+
<meta charset="utf-8">
|
|
389
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
390
|
+
<title>${strings[titleKey]}</title>
|
|
391
|
+
<style>${oauthCompletionStyles}</style>
|
|
392
|
+
</head>
|
|
393
|
+
<body>
|
|
394
|
+
<main class="card" role="status" aria-live="polite">
|
|
395
|
+
<div class="header">
|
|
396
|
+
<span class="badge" data-t="refusedBadge">${strings.refusedBadge}</span>
|
|
397
|
+
<h1 data-t="${titleKey}">${strings[titleKey]}</h1>
|
|
398
|
+
<p data-t="refusedBody">${strings.refusedBody}</p>${codeLine}
|
|
399
|
+
</div>
|
|
400
|
+
<div class="actions">
|
|
401
|
+
<button class="button" type="button" data-t="closeButton">${strings.closeButton}</button>
|
|
402
|
+
<p class="close-note" data-close-note>${strings.autoClose.replace("%N%", String(closeDelaySeconds))}</p>
|
|
403
|
+
</div>
|
|
404
|
+
</main>
|
|
405
|
+
<script>(()=>{
|
|
406
|
+
${postScript}const STR=${scriptJson(oauthCompletionStrings)};
|
|
407
|
+
${oauthCompletionLocaleScript}
|
|
408
|
+
const t=STR[pick()]||STR.en;
|
|
409
|
+
document.documentElement.lang=pick();
|
|
410
|
+
for(const el of document.querySelectorAll("[data-t]")){const key=el.getAttribute("data-t");if(t[key]!=null)el.textContent=t[key];}
|
|
411
|
+
if(t[${scriptJson(titleKey)}])document.title=t[${scriptJson(titleKey)}];
|
|
412
|
+
${oauthCloseWindowScript(closeDelaySeconds)}
|
|
413
|
+
})();</script>
|
|
414
|
+
</body>
|
|
415
|
+
</html>`;
|
|
416
|
+
}
|
|
@@ -43,7 +43,7 @@ const actionFailureMetaSchema = jsonSchema.object({
|
|
|
43
43
|
const oauthClientConfigRequestSchema = jsonSchema.object({
|
|
44
44
|
clientId: jsonSchema.string({ description: "OAuth app client id." }),
|
|
45
45
|
clientSecret: jsonSchema.string({
|
|
46
|
-
description: "OAuth app client secret.
|
|
46
|
+
description: "OAuth app client secret. When updating the default app with the same clientId, omission preserves the stored secret. Required for a new confidential client.",
|
|
47
47
|
}),
|
|
48
48
|
requestedScopes: jsonSchema.array(jsonSchema.string(), {
|
|
49
49
|
minItems: 1,
|
|
@@ -285,6 +285,59 @@ export function createOpenApiDocument(providers, options = {}) {
|
|
|
285
285
|
parameters: [{ name: "service", in: "path", required: true, schema: jsonSchema.string() }],
|
|
286
286
|
errorStatuses: [401, 404],
|
|
287
287
|
}),
|
|
288
|
+
"/v1/providers/slackbot/events/verify": {
|
|
289
|
+
post: {
|
|
290
|
+
tags: ["Triggers"],
|
|
291
|
+
summary: "Verify an inbound Slack Events API request.",
|
|
292
|
+
description: "Requires the dedicated OOMOL_CONNECT_EVENT_VERIFY_TOKEN. The raw Slack request body is verified against the deployment-default slackbot OAuth client configuration, not a connection-specific configuration; no event is stored or scheduled.",
|
|
293
|
+
security: [{ eventVerificationToken: [] }],
|
|
294
|
+
parameters: [
|
|
295
|
+
{
|
|
296
|
+
name: "x-slack-request-timestamp",
|
|
297
|
+
in: "header",
|
|
298
|
+
required: true,
|
|
299
|
+
schema: jsonSchema.string(),
|
|
300
|
+
},
|
|
301
|
+
{ name: "x-slack-signature", in: "header", required: true, schema: jsonSchema.string() },
|
|
302
|
+
],
|
|
303
|
+
requestBody: {
|
|
304
|
+
required: true,
|
|
305
|
+
content: {
|
|
306
|
+
"application/json": { schema: { type: "object", additionalProperties: true } },
|
|
307
|
+
"application/x-www-form-urlencoded": {
|
|
308
|
+
schema: {
|
|
309
|
+
type: "object",
|
|
310
|
+
properties: {
|
|
311
|
+
payload: {
|
|
312
|
+
type: "string",
|
|
313
|
+
description: "URL-encoded JSON block_actions interaction payload.",
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
required: ["payload"],
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
responses: {
|
|
322
|
+
200: jsonResponse(runtimeSuccessSchema({
|
|
323
|
+
type: "object",
|
|
324
|
+
properties: {
|
|
325
|
+
valid: { type: "boolean", const: true },
|
|
326
|
+
appId: { type: "string" },
|
|
327
|
+
challenge: jsonSchema.nullableString("Challenge value returned for Slack URL verification."),
|
|
328
|
+
},
|
|
329
|
+
required: ["valid", "appId", "challenge"],
|
|
330
|
+
})),
|
|
331
|
+
400: jsonResponse(runtimeFailureSchema(), "invalid_event_payload: invalid JSON or unsupported Slack envelope."),
|
|
332
|
+
401: jsonResponse(runtimeFailureSchema(), "unauthorized, invalid_webhook_signature, or invalid_webhook_timestamp."),
|
|
333
|
+
403: jsonResponse(runtimeFailureSchema(), "webhook_app_mismatch."),
|
|
334
|
+
404: jsonResponse(runtimeFailureSchema(), "event_verification_disabled: no dedicated verification token is configured."),
|
|
335
|
+
409: jsonResponse(runtimeFailureSchema(), "event_verification_not_configured: default Slack App ID or Signing Secret is missing."),
|
|
336
|
+
413: jsonResponse(runtimeFailureSchema(), "webhook_request_too_large: the Slack request body exceeds 64 KiB."),
|
|
337
|
+
500: jsonResponse(runtimeFailureSchema(), "Internal verification failure."),
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
288
341
|
"/v1/providers/{service}/triggers/{triggerId}/execute": {
|
|
289
342
|
post: {
|
|
290
343
|
tags: ["Triggers"],
|
|
@@ -369,6 +422,13 @@ export function createOpenApiDocument(providers, options = {}) {
|
|
|
369
422
|
],
|
|
370
423
|
paths,
|
|
371
424
|
components: {
|
|
425
|
+
securitySchemes: {
|
|
426
|
+
eventVerificationToken: {
|
|
427
|
+
type: "http",
|
|
428
|
+
scheme: "bearer",
|
|
429
|
+
description: "Dedicated OOMOL_CONNECT_EVENT_VERIFY_TOKEN; admin and runtime tokens are not accepted.",
|
|
430
|
+
},
|
|
431
|
+
},
|
|
372
432
|
schemas: {
|
|
373
433
|
ActionDefinition: jsonSchema.unknownObject("Public action catalog definition with runtime execution status."),
|
|
374
434
|
LocalAuthSession: jsonSchema.object({
|
|
@@ -1238,7 +1298,7 @@ function createOAuthConfigPath() {
|
|
|
1238
1298
|
put: {
|
|
1239
1299
|
tags: ["OAuth"],
|
|
1240
1300
|
summary: "Upsert local OAuth client configuration.",
|
|
1241
|
-
description: "Open-source users provide their own OAuth app. requestedScopes replaces the default scope list with an explicit selection from the provider's scopes and optionalScopes; default scopes are not added automatically. Omit it to use the defaults without optional scopes. Undeclared scopes are refused. Additional extra fields are declared by provider catalog auth metadata.",
|
|
1301
|
+
description: "Open-source users provide their own OAuth app. requestedScopes replaces the default scope list with an explicit selection from the provider's scopes and optionalScopes; default scopes are not added automatically. Omit it to use the defaults without optional scopes. Undeclared scopes are refused. Additional extra fields are declared by provider catalog auth metadata. For the same clientId, omitted clientSecret and omitted secretExtra keys retain saved secrets. Explicit empty secretExtra values clear optional secrets. Changing clientId requires new secrets.",
|
|
1242
1302
|
requestBody: {
|
|
1243
1303
|
required: true,
|
|
1244
1304
|
content: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { RuntimeActionDefinition, RuntimeProviderDefinition } from "../../catalog-store.ts";
|
|
2
|
-
import type { ConnectionError
|
|
2
|
+
import type { ConnectionError } from "../../connection-error.ts";
|
|
3
|
+
import type { ConnectionSummary, ManagedConnectionSummary } from "../../connection-service.ts";
|
|
3
4
|
import type { ProviderAuthSetup } from "../../core/provider-setup.ts";
|
|
4
5
|
import type { ExecutionResult, ProviderScenario } from "../../core/types.ts";
|
|
5
6
|
import type { OAuthClientConfigSummary } from "../../oauth/oauth-client-config-service.ts";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import { ConnectionError } from "../../connection-
|
|
2
|
+
import { ConnectionError } from "../../connection-error.js";
|
|
3
3
|
import { mapConnectionErrorStatus, serializeRuntimeConnectedApp, writeRuntimeFailure, writeRuntimeSuccess, } from "./runtime-api.js";
|
|
4
4
|
function filterAllowedConnections(policy, connections) {
|
|
5
5
|
return connections.filter((connection) => connection.authType === "no_auth" || policy.evaluateConnection(connection.id).allowed);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import { ConnectionError
|
|
2
|
+
import { ConnectionError } from "../../connection-error.js";
|
|
3
|
+
import { defaultConnectionName } from "../../connection-service.js";
|
|
3
4
|
import { optionalString } from "../../core/cast.js";
|
|
4
5
|
import { ActionInputDepthError, createIdempotencyExpiry, hashActionRequest, hashIdempotencyKey, readIdempotencyKey, } from "../actions/action-idempotency.js";
|
|
5
6
|
import { readRuntimeGrant } from "./auth.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CatalogStore } from "../catalog-store.ts";
|
|
2
2
|
import type { ActionPolicyService } from "../core/action-policy.ts";
|
|
3
3
|
import type { ProviderHttpDispatchOptions } from "../core/provider-http-dispatch.ts";
|
|
4
|
+
import type { ProviderNetworkPolicy } from "../core/provider-network-policy.ts";
|
|
4
5
|
import type { RuntimeLogger, TransitFileUpload } from "../core/types.ts";
|
|
5
6
|
import type { IProviderLoader } from "../providers/provider-loader.ts";
|
|
6
7
|
import type { RuntimeJwtVerifier } from "./api/runtime-jwt.ts";
|
|
@@ -11,6 +12,7 @@ import type { Hono } from "hono";
|
|
|
11
12
|
import { SaasCleanupService } from "../saas/saas-cleanup-service.ts";
|
|
12
13
|
import { TriggerMaintenance } from "../triggers/maintenance.ts";
|
|
13
14
|
export interface ConnectAppOptions {
|
|
15
|
+
network?: ProviderNetworkPolicy;
|
|
14
16
|
catalog: CatalogStore;
|
|
15
17
|
providerLoader: IProviderLoader;
|
|
16
18
|
providerHttpDispatch?: ProviderHttpDispatchOptions;
|
|
@@ -22,6 +24,7 @@ export interface ConnectAppOptions {
|
|
|
22
24
|
secretCodec: ISecretCodec;
|
|
23
25
|
adminToken?: string;
|
|
24
26
|
runtimeToken?: string;
|
|
27
|
+
eventVerifyToken?: string;
|
|
25
28
|
requireRuntimeAuth?: boolean;
|
|
26
29
|
allowedCustomOAuth?: string[];
|
|
27
30
|
verifyRuntimeJwt?: RuntimeJwtVerifier;
|
|
@@ -32,6 +35,7 @@ export interface ConnectAppOptions {
|
|
|
32
35
|
compressApiResponses?: boolean;
|
|
33
36
|
serveDocumentation?: boolean;
|
|
34
37
|
oauthCloseDelaySeconds?: number;
|
|
38
|
+
oauthResultOrigins?: string[];
|
|
35
39
|
}
|
|
36
40
|
export interface ConnectApp {
|
|
37
41
|
saasCleanup: SaasCleanupService;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ConnectionService } from "../connection-service.js";
|
|
2
2
|
import { ActionPolicyService as ExecutionPolicyService } from "../core/action-policy.js";
|
|
3
|
+
import { withProviderNetworkPolicy } from "../core/provider-network-policy.js";
|
|
3
4
|
import { MarketplaceService } from "../marketplace/marketplace-service.js";
|
|
4
5
|
import { OAuthClientConfigService } from "../oauth/oauth-client-config-service.js";
|
|
5
6
|
import { OAuthCredentialRefreshService } from "../oauth/oauth-credential-refresh-service.js";
|
|
@@ -12,9 +13,14 @@ import { SaasProjectService } from "../saas/saas-project-service.js";
|
|
|
12
13
|
import { TriggerMaintenance } from "../triggers/maintenance.js";
|
|
13
14
|
import { TriggerRunner } from "../triggers/trigger-runner.js";
|
|
14
15
|
import { ActionRunner } from "./actions/action-runner.js";
|
|
16
|
+
import { normalizeOAuthResultOrigins } from "./api/oauth-completion-page.js";
|
|
15
17
|
import { ConnectServer } from "./connect-server.js";
|
|
16
18
|
import { RuntimeTokenService } from "./storage/runtime-token-service.js";
|
|
17
19
|
export async function createConnectApp(options) {
|
|
20
|
+
const network = Object.freeze({
|
|
21
|
+
allowPrivateNetwork: options.network?.allowPrivateNetwork ?? false,
|
|
22
|
+
trustedHosts: Object.freeze([...(options.network?.trustedHosts ?? [])]),
|
|
23
|
+
});
|
|
18
24
|
const saasClient = new SaasClient();
|
|
19
25
|
const saasProject = new SaasProjectService({
|
|
20
26
|
catalog: options.catalog,
|
|
@@ -34,7 +40,7 @@ export async function createConnectApp(options) {
|
|
|
34
40
|
store: options.runtimeDatabase.marketplaceStore,
|
|
35
41
|
secretCodec: options.secretCodec,
|
|
36
42
|
});
|
|
37
|
-
await marketplace.initialize();
|
|
43
|
+
await withProviderNetworkPolicy(network, () => marketplace.initialize());
|
|
38
44
|
const runtimeTokens = new RuntimeTokenService(options.runtimeDatabase.runtimeTokenStore, options.logger);
|
|
39
45
|
const hasStoredRuntimeTokens = async () => (await runtimeTokens.listTokens()).length > 0;
|
|
40
46
|
const allowedCustomOAuth = new Set(options.allowedCustomOAuth);
|
|
@@ -74,6 +80,7 @@ export async function createConnectApp(options) {
|
|
|
74
80
|
store: options.runtimeDatabase.triggerStore,
|
|
75
81
|
});
|
|
76
82
|
const triggerMaintenance = new TriggerMaintenance({
|
|
83
|
+
network,
|
|
77
84
|
store: options.runtimeDatabase.triggerStore,
|
|
78
85
|
runner: triggers,
|
|
79
86
|
tokens: options.runtimeDatabase.runtimeTokenStore,
|
|
@@ -84,12 +91,14 @@ export async function createConnectApp(options) {
|
|
|
84
91
|
return {
|
|
85
92
|
triggerMaintenance,
|
|
86
93
|
saasCleanup: new SaasCleanupService({
|
|
94
|
+
network,
|
|
87
95
|
store: options.runtimeDatabase.saasProjectStore,
|
|
88
96
|
requests: options.runtimeDatabase.connectionRequestStore,
|
|
89
97
|
client: saasClient,
|
|
90
98
|
logger: options.logger,
|
|
91
99
|
}),
|
|
92
100
|
app: new ConnectServer({
|
|
101
|
+
network,
|
|
93
102
|
providerHttpDispatch: options.providerHttpDispatch,
|
|
94
103
|
catalog: options.catalog,
|
|
95
104
|
publicOrigin: options.publicOrigin,
|
|
@@ -115,6 +124,7 @@ export async function createConnectApp(options) {
|
|
|
115
124
|
runtimeTokens,
|
|
116
125
|
runtimePolicyStore: options.runtimeDatabase.runtimePolicyStore,
|
|
117
126
|
registerStaticRoutes: options.registerStaticRoutes,
|
|
127
|
+
eventVerifyToken: options.eventVerifyToken,
|
|
118
128
|
auth: {
|
|
119
129
|
adminToken: options.adminToken,
|
|
120
130
|
runtimeToken: options.runtimeToken,
|
|
@@ -132,6 +142,9 @@ export async function createConnectApp(options) {
|
|
|
132
142
|
compressApiResponses: options.compressApiResponses,
|
|
133
143
|
serveDocumentation: options.serveDocumentation,
|
|
134
144
|
oauthCloseDelaySeconds: options.oauthCloseDelaySeconds,
|
|
145
|
+
// Validated here as well as where the environment is read, so a host
|
|
146
|
+
// that passes the option directly gets the same refusal of `*`.
|
|
147
|
+
oauthResultOrigins: normalizeOAuthResultOrigins(options.oauthResultOrigins ?? []),
|
|
135
148
|
}).createApp(),
|
|
136
149
|
runtimeAuthConfigured: Boolean(options.requireRuntimeAuth) ||
|
|
137
150
|
Boolean(options.runtimeToken) ||
|
|
@@ -2,6 +2,7 @@ import type { CatalogStore } from "../catalog-store.ts";
|
|
|
2
2
|
import type { ConnectionService } from "../connection-service.ts";
|
|
3
3
|
import type { ActionSearchIndexProvider } from "../core/action-search.ts";
|
|
4
4
|
import type { ProviderHttpDispatchOptions } from "../core/provider-http-dispatch.ts";
|
|
5
|
+
import type { ProviderNetworkPolicy } from "../core/provider-network-policy.ts";
|
|
5
6
|
import type { RuntimeLogger, TransitFileUpload } from "../core/types.ts";
|
|
6
7
|
import type { MarketplaceService } from "../marketplace/marketplace-service.ts";
|
|
7
8
|
import type { OAuthClientConfigService } from "../oauth/oauth-client-config-service.ts";
|
|
@@ -30,6 +31,7 @@ export declare function preloadOptionalServerModules(): Promise<void>;
|
|
|
30
31
|
* Dependencies required to construct the local connector server.
|
|
31
32
|
*/
|
|
32
33
|
export interface IConnectServerOptions {
|
|
34
|
+
network?: ProviderNetworkPolicy;
|
|
33
35
|
providerHttpDispatch?: ProviderHttpDispatchOptions;
|
|
34
36
|
catalog: CatalogStore;
|
|
35
37
|
/** Public origin of this runtime, used for the HTTP request examples in Action guides. */
|
|
@@ -46,6 +48,8 @@ export interface IConnectServerOptions {
|
|
|
46
48
|
transitFiles: ITransitFileService;
|
|
47
49
|
uploadTransitFile?: (request: Request) => Promise<TransitFileUpload>;
|
|
48
50
|
auth?: LocalAuthOptions;
|
|
51
|
+
/** Dedicated token for inbound provider event verification. */
|
|
52
|
+
eventVerifyToken?: string;
|
|
49
53
|
actionPolicy?: ActionPolicyService;
|
|
50
54
|
runtimePolicyStore: IRuntimePolicyStore;
|
|
51
55
|
actionSearch?: ActionSearchIndexProvider;
|
|
@@ -55,6 +59,8 @@ export interface IConnectServerOptions {
|
|
|
55
59
|
serveDocumentation?: boolean;
|
|
56
60
|
/** Seconds the OAuth completion page waits before closing its window. `0` closes it as soon as it loads. */
|
|
57
61
|
oauthCloseDelaySeconds?: number;
|
|
62
|
+
/** Origins a provider-refusal page may post its result to (`OOMOL_CONNECT_OAUTH_RESULT_ORIGINS`). */
|
|
63
|
+
oauthResultOrigins?: readonly string[];
|
|
58
64
|
marketplace?: MarketplaceService;
|
|
59
65
|
saasProject?: SaasProjectService;
|
|
60
66
|
saas?: SaasExecutionService;
|
|
@@ -4,6 +4,7 @@ import { ActionPolicyService } from "../core/action-policy.js";
|
|
|
4
4
|
import { createActionSearchIndexProvider } from "../core/action-search.js";
|
|
5
5
|
import { optionalRecord } from "../core/cast.js";
|
|
6
6
|
import { withProviderHttpDispatch } from "../core/provider-http-dispatch.js";
|
|
7
|
+
import { withProviderNetworkPolicy } from "../core/provider-network-policy.js";
|
|
7
8
|
import { ProviderDispatchRequestError, toProviderExecutionError } from "../providers/provider-runtime.js";
|
|
8
9
|
import { SaasError } from "../saas/saas-client.js";
|
|
9
10
|
import { ActionRunner } from "./actions/action-runner.js";
|
|
@@ -28,6 +29,7 @@ import { createSaasProjectRoutes } from "./api/saas-project-routes.js";
|
|
|
28
29
|
import { createTransitFileRoutes } from "./api/transit-file-routes.js";
|
|
29
30
|
import { createTriggerRoutes } from "./api/trigger-routes.js";
|
|
30
31
|
import { ProxyRunner } from "./proxy/proxy-runner.js";
|
|
32
|
+
import { readSlackEventRequestBody, verifySlackEventRequest } from "./slack-event-verification.js";
|
|
31
33
|
/**
|
|
32
34
|
* Import and evaluate the modules the /mcp and /docs routes defer to their first request. The Node server never
|
|
33
35
|
* calls this, so its startup graph stays small; Cloudflare Workers call it at app creation so an isolate keeps
|
|
@@ -68,7 +70,7 @@ export class ConnectServer {
|
|
|
68
70
|
const app = new Hono();
|
|
69
71
|
const auth = this.options.auth ?? {};
|
|
70
72
|
app.use("*", async (_context, next) => {
|
|
71
|
-
await withProviderHttpDispatch({ operation: "runtime" }, next, this.options.providerHttpDispatch);
|
|
73
|
+
await withProviderNetworkPolicy(this.options.network ?? {}, () => withProviderHttpDispatch({ operation: "runtime" }, next, this.options.providerHttpDispatch));
|
|
72
74
|
});
|
|
73
75
|
app.use("*", async (context, next) => {
|
|
74
76
|
await next();
|
|
@@ -92,6 +94,84 @@ export class ConnectServer {
|
|
|
92
94
|
app.use("/api/*", compress());
|
|
93
95
|
}
|
|
94
96
|
app.use("*", createLocalAuthMiddleware(auth));
|
|
97
|
+
// Inbound provider event verification. This route authenticates with a dedicated token
|
|
98
|
+
// so a host ingress can delegate signature verification without receiving the admin token.
|
|
99
|
+
app.post("/v1/providers/slackbot/events/verify", async (context) => {
|
|
100
|
+
const expected = this.options.eventVerifyToken?.trim();
|
|
101
|
+
if (!expected)
|
|
102
|
+
return writeRuntimeFailure(context, {
|
|
103
|
+
status: 404,
|
|
104
|
+
errorCode: "event_verification_disabled",
|
|
105
|
+
message: "Event verification is disabled.",
|
|
106
|
+
});
|
|
107
|
+
const authorization = context.req.header("authorization") ?? "";
|
|
108
|
+
const provided = authorization.startsWith("Bearer ") ? authorization.slice(7).trim() : "";
|
|
109
|
+
if (!(await sameSecret(provided, expected)))
|
|
110
|
+
return writeRuntimeFailure(context, {
|
|
111
|
+
status: 401,
|
|
112
|
+
errorCode: "unauthorized",
|
|
113
|
+
message: "A valid event verification token is required.",
|
|
114
|
+
});
|
|
115
|
+
const config = await this.options.oauthClientConfigs.getConfig("slackbot");
|
|
116
|
+
const appId = String(config?.extra?.appId ?? "").trim();
|
|
117
|
+
const signingSecret = String(config?.secretExtra?.signingSecret ?? "").trim();
|
|
118
|
+
if (!appId || !signingSecret)
|
|
119
|
+
return writeRuntimeFailure(context, {
|
|
120
|
+
status: 409,
|
|
121
|
+
errorCode: "event_verification_not_configured",
|
|
122
|
+
message: "Configure the default Slack App ID and Signing Secret.",
|
|
123
|
+
});
|
|
124
|
+
const rawBody = await readSlackEventRequestBody(context.req.raw);
|
|
125
|
+
if (!rawBody)
|
|
126
|
+
return writeRuntimeFailure(context, {
|
|
127
|
+
status: 413,
|
|
128
|
+
errorCode: "webhook_request_too_large",
|
|
129
|
+
message: "Slack request body exceeds 64 KiB.",
|
|
130
|
+
});
|
|
131
|
+
const result = await verifySlackEventRequest({
|
|
132
|
+
timestamp: context.req.header("x-slack-request-timestamp") ?? "",
|
|
133
|
+
signature: context.req.header("x-slack-signature") ?? "",
|
|
134
|
+
rawBody,
|
|
135
|
+
configuredAppId: appId,
|
|
136
|
+
signingSecret,
|
|
137
|
+
contentType: context.req.header("content-type") ?? "",
|
|
138
|
+
});
|
|
139
|
+
if (!result.valid) {
|
|
140
|
+
switch (result.reason) {
|
|
141
|
+
case "body_too_large":
|
|
142
|
+
return writeRuntimeFailure(context, {
|
|
143
|
+
status: 413,
|
|
144
|
+
errorCode: "webhook_request_too_large",
|
|
145
|
+
message: "Slack request body exceeds 64 KiB.",
|
|
146
|
+
});
|
|
147
|
+
case "payload":
|
|
148
|
+
return writeRuntimeFailure(context, {
|
|
149
|
+
status: 400,
|
|
150
|
+
errorCode: "invalid_event_payload",
|
|
151
|
+
message: "Invalid Slack event envelope.",
|
|
152
|
+
});
|
|
153
|
+
case "app":
|
|
154
|
+
return writeRuntimeFailure(context, {
|
|
155
|
+
status: 403,
|
|
156
|
+
errorCode: "webhook_app_mismatch",
|
|
157
|
+
message: "Slack App ID does not match the configured application.",
|
|
158
|
+
});
|
|
159
|
+
case "timestamp":
|
|
160
|
+
return writeRuntimeFailure(context, {
|
|
161
|
+
status: 401,
|
|
162
|
+
errorCode: "invalid_webhook_timestamp",
|
|
163
|
+
message: "Invalid or expired Slack request timestamp.",
|
|
164
|
+
});
|
|
165
|
+
case "signature":
|
|
166
|
+
return writeRuntimeFailure(context, {
|
|
167
|
+
status: 401,
|
|
168
|
+
errorCode: "invalid_webhook_signature",
|
|
169
|
+
message: "Invalid Slack request signature.",
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return writeRuntimeSuccess(context, result);
|
|
174
|
+
});
|
|
95
175
|
// Health and runtime discovery / execution endpoints
|
|
96
176
|
app.get("/v1/health", (context) => writeRuntimeSuccess(context, { ok: true, runtime: "oomol-connect" }));
|
|
97
177
|
app.route("/v1", createRuntimeCatalogRoutes({
|
|
@@ -162,7 +242,10 @@ export class ConnectServer {
|
|
|
162
242
|
app.route("/api", createSaasProjectRoutes({ saasProject: saas }));
|
|
163
243
|
}
|
|
164
244
|
if (saas && this.options.saasOAuth) {
|
|
165
|
-
app.route("/", createSaasOAuthRoutes({
|
|
245
|
+
app.route("/", createSaasOAuthRoutes({
|
|
246
|
+
saasProject: saas,
|
|
247
|
+
saasOAuth: this.options.saasOAuth,
|
|
248
|
+
}));
|
|
166
249
|
}
|
|
167
250
|
app.route("/", createConsoleOAuthRoutes({
|
|
168
251
|
connections: this.options.connections,
|
|
@@ -171,6 +254,7 @@ export class ConnectServer {
|
|
|
171
254
|
saasProject: this.options.saasProject,
|
|
172
255
|
logger: this.options.logger,
|
|
173
256
|
oauthCloseDelaySeconds: this.options.oauthCloseDelaySeconds,
|
|
257
|
+
oauthResultOrigins: this.options.oauthResultOrigins,
|
|
174
258
|
}));
|
|
175
259
|
// Without a console the API owns every unknown path; a console host layers its fallback over these 404s.
|
|
176
260
|
if (this.options.registerStaticRoutes)
|
|
@@ -202,8 +286,18 @@ export class ConnectServer {
|
|
|
202
286
|
if (error.retryAfter)
|
|
203
287
|
context.header("Retry-After", error.retryAfter);
|
|
204
288
|
if (context.req.path.startsWith("/v1/"))
|
|
205
|
-
return writeRuntimeFailure(context, {
|
|
206
|
-
|
|
289
|
+
return writeRuntimeFailure(context, {
|
|
290
|
+
status: error.status,
|
|
291
|
+
errorCode: error.code,
|
|
292
|
+
message: error.message,
|
|
293
|
+
});
|
|
294
|
+
return context.json({
|
|
295
|
+
error: {
|
|
296
|
+
code: error.code,
|
|
297
|
+
message: error.message,
|
|
298
|
+
reason: error.reason,
|
|
299
|
+
},
|
|
300
|
+
}, error.status);
|
|
207
301
|
}
|
|
208
302
|
if (error instanceof HttpRequestError) {
|
|
209
303
|
if (context.req.path.startsWith("/v1/")) {
|
|
@@ -232,3 +326,19 @@ export class ConnectServer {
|
|
|
232
326
|
return app;
|
|
233
327
|
}
|
|
234
328
|
}
|
|
329
|
+
/** Hash both values before a constant-time comparison so length never leaks. */
|
|
330
|
+
async function sameSecret(provided, expected) {
|
|
331
|
+
if (!provided || !expected)
|
|
332
|
+
return false;
|
|
333
|
+
const encoder = new TextEncoder();
|
|
334
|
+
const [left, right] = await Promise.all([
|
|
335
|
+
crypto.subtle.digest("SHA-256", encoder.encode(provided)),
|
|
336
|
+
crypto.subtle.digest("SHA-256", encoder.encode(expected)),
|
|
337
|
+
]);
|
|
338
|
+
const a = new Uint8Array(left);
|
|
339
|
+
const b = new Uint8Array(right);
|
|
340
|
+
let difference = 0;
|
|
341
|
+
for (let index = 0; index < a.length; index += 1)
|
|
342
|
+
difference |= a[index] ^ b[index];
|
|
343
|
+
return difference === 0;
|
|
344
|
+
}
|