@jskit-ai/connectors-catalog 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. package/README.md +192 -0
  2. package/docs/ai-upstream-notices.md +51 -0
  3. package/docs/ai.md +191 -0
  4. package/docs/airtable.md +130 -0
  5. package/docs/algolia.md +190 -0
  6. package/docs/amazon-redshift.md +229 -0
  7. package/docs/amplitude.md +210 -0
  8. package/docs/apify.md +162 -0
  9. package/docs/apollo-io.md +200 -0
  10. package/docs/asana.md +126 -0
  11. package/docs/ashby.md +188 -0
  12. package/docs/atlassian.md +224 -0
  13. package/docs/attention.md +162 -0
  14. package/docs/aws-athena.md +150 -0
  15. package/docs/aws-credentials.md +75 -0
  16. package/docs/aws-s3.md +193 -0
  17. package/docs/bigquery.md +146 -0
  18. package/docs/brevo.md +122 -0
  19. package/docs/calendly.md +158 -0
  20. package/docs/canva.md +191 -0
  21. package/docs/chargebee.md +192 -0
  22. package/docs/clay.md +194 -0
  23. package/docs/clickhouse.md +242 -0
  24. package/docs/confidence-exp.md +74 -0
  25. package/docs/confidence-flags.md +75 -0
  26. package/docs/confidence-oauth.md +137 -0
  27. package/docs/contentful.md +123 -0
  28. package/docs/databricks.md +180 -0
  29. package/docs/dbt-semantic-layer.md +175 -0
  30. package/docs/elevenlabs.md +102 -0
  31. package/docs/figma.md +132 -0
  32. package/docs/firebase-cloud-messaging.md +262 -0
  33. package/docs/firecrawl.md +137 -0
  34. package/docs/fireflies.md +95 -0
  35. package/docs/fireworks-ai.md +53 -0
  36. package/docs/gatewayapi.md +113 -0
  37. package/docs/gemini-enterprise.md +224 -0
  38. package/docs/github-api.md +133 -0
  39. package/docs/gitlab-api.md +138 -0
  40. package/docs/gmail.md +133 -0
  41. package/docs/gong.md +205 -0
  42. package/docs/google-ads.md +156 -0
  43. package/docs/google-analytics.md +202 -0
  44. package/docs/google-docs.md +105 -0
  45. package/docs/google-drive.md +108 -0
  46. package/docs/google-maps-platform.md +208 -0
  47. package/docs/google-oauth.md +123 -0
  48. package/docs/google-search-console.md +124 -0
  49. package/docs/google-sheets.md +94 -0
  50. package/docs/google-slides.md +95 -0
  51. package/docs/granola.md +178 -0
  52. package/docs/hex.md +161 -0
  53. package/docs/heygen.md +124 -0
  54. package/docs/hubspot.md +142 -0
  55. package/docs/incident-io.md +118 -0
  56. package/docs/inngest.md +178 -0
  57. package/docs/klipy.md +149 -0
  58. package/docs/lexware.md +144 -0
  59. package/docs/lightspeed.md +193 -0
  60. package/docs/linear.md +137 -0
  61. package/docs/linkedin.md +196 -0
  62. package/docs/logo-dev.md +152 -0
  63. package/docs/mailgun.md +153 -0
  64. package/docs/mapbox.md +174 -0
  65. package/docs/microsoft-excel.md +97 -0
  66. package/docs/microsoft-fabric.md +249 -0
  67. package/docs/microsoft-oauth.md +143 -0
  68. package/docs/microsoft-onedrive.md +76 -0
  69. package/docs/microsoft-onenote.md +75 -0
  70. package/docs/microsoft-outlook.md +90 -0
  71. package/docs/microsoft-powerpoint.md +119 -0
  72. package/docs/microsoft-sharepoint.md +75 -0
  73. package/docs/microsoft-teams.md +72 -0
  74. package/docs/microsoft-word.md +119 -0
  75. package/docs/miro.md +117 -0
  76. package/docs/n8n.md +169 -0
  77. package/docs/notion.md +137 -0
  78. package/docs/oura.md +161 -0
  79. package/docs/paddle.md +168 -0
  80. package/docs/perplexity.md +85 -0
  81. package/docs/pipedrive.md +120 -0
  82. package/docs/polar.md +63 -0
  83. package/docs/posthog.md +227 -0
  84. package/docs/prestashop.md +151 -0
  85. package/docs/replicate.md +60 -0
  86. package/docs/resend.md +153 -0
  87. package/docs/salesforce.md +234 -0
  88. package/docs/sanity.md +122 -0
  89. package/docs/semrush.md +276 -0
  90. package/docs/sentry.md +112 -0
  91. package/docs/sevdesk.md +107 -0
  92. package/docs/shopify.md +206 -0
  93. package/docs/slack.md +257 -0
  94. package/docs/snowflake.md +271 -0
  95. package/docs/storyblok.md +130 -0
  96. package/docs/stripe.md +77 -0
  97. package/docs/supabase.md +51 -0
  98. package/docs/tally.md +105 -0
  99. package/docs/telegram.md +165 -0
  100. package/docs/tiktok.md +201 -0
  101. package/docs/twilio.md +284 -0
  102. package/docs/twitch.md +428 -0
  103. package/docs/wave.md +440 -0
  104. package/docs/wix.md +1249 -0
  105. package/docs/wiz.md +177 -0
  106. package/docs/woocommerce.md +400 -0
  107. package/docs/wordpress-com.md +358 -0
  108. package/docs/wordpress-self-hosted.md +252 -0
  109. package/docs/workday.md +292 -0
  110. package/docs/x-twitter.md +188 -0
  111. package/docs/xero.md +429 -0
  112. package/docs/zoho-books.md +214 -0
  113. package/docs/zoho-crm.md +192 -0
  114. package/package.json +153 -0
  115. package/patterns/ai-connections/PATTERN.md +84 -0
  116. package/patterns/ai-connections/example/ai-model.js +11 -0
  117. package/patterns/ai-connections/example/perplexity-answer.js +29 -0
  118. package/patterns/api-key-connection/PATTERN.md +368 -0
  119. package/patterns/api-key-connection/example/connections.js +18 -0
  120. package/patterns/api-key-connection/example/integrations.json +19 -0
  121. package/patterns/assistant-mcp/PATTERN.md +110 -0
  122. package/patterns/assistant-mcp/example/integrations.json +13 -0
  123. package/patterns/assistant-mcp-oauth/PATTERN.md +235 -0
  124. package/patterns/assistant-mcp-oauth/example/integrations.json +102 -0
  125. package/patterns/aws-storage-queries/PATTERN.md +169 -0
  126. package/patterns/aws-storage-queries/example/formats/data-formats.js +35 -0
  127. package/patterns/aws-storage-queries/example/formats/package-lock.json +49 -0
  128. package/patterns/aws-storage-queries/example/formats/package.json +12 -0
  129. package/patterns/aws-storage-queries/example/formats/verify-formats.mjs +37 -0
  130. package/patterns/aws-storage-queries/example/integrations.json +38 -0
  131. package/patterns/aws-storage-queries/example/s3-transfer.js +34 -0
  132. package/patterns/event-delivery/PATTERN.md +151 -0
  133. package/patterns/event-delivery/example/integrations.json +17 -0
  134. package/patterns/firebase-messaging/PATTERN.md +156 -0
  135. package/patterns/firebase-messaging/example/server/notifications.js +23 -0
  136. package/patterns/google-ads-search/PATTERN.md +92 -0
  137. package/patterns/google-ads-search/example/ads-setup.js +25 -0
  138. package/patterns/oauth-connection/PATTERN.md +724 -0
  139. package/patterns/oauth-connection/example/integrations.json +20 -0
  140. package/patterns/paddle-catalogue/PATTERN.md +78 -0
  141. package/patterns/paddle-catalogue/example/create-products.js +38 -0
  142. package/patterns/public-image/PATTERN.md +84 -0
  143. package/patterns/public-image/example/integrations.json +13 -0
  144. package/patterns/public-image/example/logo-url.js +16 -0
  145. package/patterns/redshift-queries/PATTERN.md +150 -0
  146. package/patterns/redshift-queries/example/integrations.json +33 -0
  147. package/patterns/source-scanning/PATTERN.md +83 -0
  148. package/patterns/source-scanning/example/source-scanner.js +13 -0
  149. package/src/client/firebase-cloud-messaging.js +10 -0
  150. package/src/client/google-analytics.js +72 -0
  151. package/src/client/google-maps-platform.js +39 -0
  152. package/src/client/logo-dev.js +36 -0
  153. package/src/server/ai.js +46 -0
  154. package/src/server/airtable.js +67 -0
  155. package/src/server/algolia.js +63 -0
  156. package/src/server/amazon-redshift.js +96 -0
  157. package/src/server/amplitude.js +31 -0
  158. package/src/server/apify.js +68 -0
  159. package/src/server/apollo-io.js +85 -0
  160. package/src/server/asana.js +64 -0
  161. package/src/server/ashby.js +61 -0
  162. package/src/server/atlassian.js +32 -0
  163. package/src/server/attention.js +93 -0
  164. package/src/server/aws-athena.js +82 -0
  165. package/src/server/aws-s3.js +49 -0
  166. package/src/server/awsTransport.js +75 -0
  167. package/src/server/bigquery.js +97 -0
  168. package/src/server/brevo.js +97 -0
  169. package/src/server/calendly.js +77 -0
  170. package/src/server/canva.js +13 -0
  171. package/src/server/chargebee.js +88 -0
  172. package/src/server/clay.js +78 -0
  173. package/src/server/clickhouse.js +66 -0
  174. package/src/server/confidence.js +29 -0
  175. package/src/server/contentful.js +40 -0
  176. package/src/server/databricks.js +55 -0
  177. package/src/server/dbt-semantic-layer.js +95 -0
  178. package/src/server/elevenlabs.js +81 -0
  179. package/src/server/figma.js +24 -0
  180. package/src/server/firebase-cloud-messaging.js +111 -0
  181. package/src/server/firecrawl.js +70 -0
  182. package/src/server/fireflies.js +31 -0
  183. package/src/server/fireworks-ai.js +16 -0
  184. package/src/server/gatewayapi.js +48 -0
  185. package/src/server/gemini-enterprise.js +47 -0
  186. package/src/server/github-api.js +90 -0
  187. package/src/server/gitlab-api.js +67 -0
  188. package/src/server/gmail.js +60 -0
  189. package/src/server/gong.js +52 -0
  190. package/src/server/google-ads-search.js +134 -0
  191. package/src/server/google-ads.js +80 -0
  192. package/src/server/google-docs.js +36 -0
  193. package/src/server/google-drive.js +71 -0
  194. package/src/server/google-maps-platform.js +90 -0
  195. package/src/server/google-search-console.js +31 -0
  196. package/src/server/google-sheets.js +60 -0
  197. package/src/server/google-slides.js +36 -0
  198. package/src/server/google.js +61 -0
  199. package/src/server/granola.js +115 -0
  200. package/src/server/graphqlOperation.js +15 -0
  201. package/src/server/hex.js +29 -0
  202. package/src/server/heygen.js +54 -0
  203. package/src/server/hubspot.js +85 -0
  204. package/src/server/incident-io.js +68 -0
  205. package/src/server/inngest.js +86 -0
  206. package/src/server/jsonOperation.js +34 -0
  207. package/src/server/klipy.js +34 -0
  208. package/src/server/lexware.js +59 -0
  209. package/src/server/lightspeed.js +82 -0
  210. package/src/server/linear.js +52 -0
  211. package/src/server/linkedin.js +74 -0
  212. package/src/server/mailgun.js +76 -0
  213. package/src/server/mapbox.js +46 -0
  214. package/src/server/mcpRegistration.js +41 -0
  215. package/src/server/mcpTransport.js +60 -0
  216. package/src/server/microsoft-excel.js +67 -0
  217. package/src/server/microsoft-fabric.js +81 -0
  218. package/src/server/microsoft-onedrive.js +58 -0
  219. package/src/server/microsoft-onenote.js +52 -0
  220. package/src/server/microsoft-outlook.js +58 -0
  221. package/src/server/microsoft-powerpoint.js +5 -0
  222. package/src/server/microsoft-sharepoint.js +46 -0
  223. package/src/server/microsoft-teams.js +29 -0
  224. package/src/server/microsoft-word.js +5 -0
  225. package/src/server/microsoft.js +88 -0
  226. package/src/server/miro.js +29 -0
  227. package/src/server/n8n.js +78 -0
  228. package/src/server/notion.js +76 -0
  229. package/src/server/oura.js +48 -0
  230. package/src/server/paddle.js +83 -0
  231. package/src/server/perplexity.js +15 -0
  232. package/src/server/pipedrive.js +95 -0
  233. package/src/server/polar.js +20 -0
  234. package/src/server/posthog.js +44 -0
  235. package/src/server/prestashop.js +42 -0
  236. package/src/server/replicate.js +42 -0
  237. package/src/server/resend.js +93 -0
  238. package/src/server/salesforce.js +84 -0
  239. package/src/server/sanity.js +31 -0
  240. package/src/server/semrush.js +359 -0
  241. package/src/server/sentry.js +30 -0
  242. package/src/server/sevdesk.js +20 -0
  243. package/src/server/shopify.js +99 -0
  244. package/src/server/slack.js +143 -0
  245. package/src/server/snowflake.js +139 -0
  246. package/src/server/storyblok.js +49 -0
  247. package/src/server/stripe.js +13 -0
  248. package/src/server/supabase.js +13 -0
  249. package/src/server/tally.js +78 -0
  250. package/src/server/telegram.js +55 -0
  251. package/src/server/tiktok.js +86 -0
  252. package/src/server/twilio.js +90 -0
  253. package/src/server/twitch.js +409 -0
  254. package/src/server/wave.js +520 -0
  255. package/src/server/wix.js +1048 -0
  256. package/src/server/wiz.js +117 -0
  257. package/src/server/woocommerce.js +412 -0
  258. package/src/server/wordpress-com.js +236 -0
  259. package/src/server/wordpress-self-hosted.js +134 -0
  260. package/src/server/workday.js +136 -0
  261. package/src/server/x-twitter.js +110 -0
  262. package/src/server/xero.js +397 -0
  263. package/src/server/zoho-books.js +90 -0
  264. package/src/server/zoho-crm.js +89 -0
  265. package/src/server/zohoOAuth.js +21 -0
  266. package/src/shared/ai-models.json +8049 -0
  267. package/src/shared/ai.js +63 -0
  268. package/src/shared/algolia.js +29 -0
  269. package/src/shared/amazon-redshift.js +51 -0
  270. package/src/shared/amplitude.js +28 -0
  271. package/src/shared/atlassian.js +43 -0
  272. package/src/shared/aws.js +72 -0
  273. package/src/shared/canva.js +66 -0
  274. package/src/shared/chargebee.js +26 -0
  275. package/src/shared/clickhouse.js +38 -0
  276. package/src/shared/confidence.js +28 -0
  277. package/src/shared/databricks.js +33 -0
  278. package/src/shared/dbt-semantic-layer.js +32 -0
  279. package/src/shared/definitions.js +140 -0
  280. package/src/shared/figma.js +21 -0
  281. package/src/shared/firebase-cloud-messaging.js +45 -0
  282. package/src/shared/gemini-enterprise.js +33 -0
  283. package/src/shared/gong.js +33 -0
  284. package/src/shared/google-ads-search.js +31 -0
  285. package/src/shared/google-ads.js +28 -0
  286. package/src/shared/google-maps-platform.js +28 -0
  287. package/src/shared/google.js +133 -0
  288. package/src/shared/granola.js +25 -0
  289. package/src/shared/hex.js +28 -0
  290. package/src/shared/inngest.js +35 -0
  291. package/src/shared/lightspeed.js +75 -0
  292. package/src/shared/linkedin.js +27 -0
  293. package/src/shared/logo-dev.js +21 -0
  294. package/src/shared/mapbox.js +38 -0
  295. package/src/shared/mcp.js +92 -0
  296. package/src/shared/microsoft-fabric.js +47 -0
  297. package/src/shared/microsoft.js +231 -0
  298. package/src/shared/miro.js +27 -0
  299. package/src/shared/oura.js +23 -0
  300. package/src/shared/posthog.js +33 -0
  301. package/src/shared/prestashop.js +23 -0
  302. package/src/shared/salesforce.js +36 -0
  303. package/src/shared/semrush.js +24 -0
  304. package/src/shared/shopify.js +51 -0
  305. package/src/shared/siteUrl.js +12 -0
  306. package/src/shared/slack.js +88 -0
  307. package/src/shared/snowflake.js +55 -0
  308. package/src/shared/tiktok.js +22 -0
  309. package/src/shared/tokens.js +747 -0
  310. package/src/shared/twilio.js +41 -0
  311. package/src/shared/twitch.js +49 -0
  312. package/src/shared/wave.js +52 -0
  313. package/src/shared/wix.js +40 -0
  314. package/src/shared/wiz.js +41 -0
  315. package/src/shared/wordpress-com.js +30 -0
  316. package/src/shared/wordpress.js +69 -0
  317. package/src/shared/workday.js +50 -0
  318. package/src/shared/x-twitter.js +19 -0
  319. package/src/shared/xero.js +46 -0
  320. package/src/shared/zoho-books.js +39 -0
  321. package/src/shared/zoho-crm.js +43 -0
  322. package/src/shared/zoho-regions.js +12 -0
  323. package/test/ai.test.js +136 -0
  324. package/test/airtable.test.js +125 -0
  325. package/test/algolia.test.js +207 -0
  326. package/test/amazon-redshift.test.js +272 -0
  327. package/test/amplitude.test.js +239 -0
  328. package/test/apify.test.js +93 -0
  329. package/test/apollo-io.test.js +125 -0
  330. package/test/asana.test.js +99 -0
  331. package/test/ashby.test.js +97 -0
  332. package/test/atlassian.test.js +249 -0
  333. package/test/attention.test.js +79 -0
  334. package/test/aws.test.js +405 -0
  335. package/test/brevo.test.js +71 -0
  336. package/test/calendly.test.js +136 -0
  337. package/test/canva.test.js +258 -0
  338. package/test/chargebee.test.js +195 -0
  339. package/test/clickhouse.test.js +278 -0
  340. package/test/confidence.test.js +205 -0
  341. package/test/databricks.test.js +253 -0
  342. package/test/dbt-semantic-layer.test.js +221 -0
  343. package/test/designMcp.test.js +336 -0
  344. package/test/elevenlabs.test.js +52 -0
  345. package/test/firebase-cloud-messaging.test.js +242 -0
  346. package/test/firecrawl.test.js +66 -0
  347. package/test/gemini-enterprise.test.js +218 -0
  348. package/test/github-api.test.js +167 -0
  349. package/test/gitlab-api.test.js +160 -0
  350. package/test/gong.test.js +192 -0
  351. package/test/google-ads.test.js +350 -0
  352. package/test/google-maps-platform.test.js +191 -0
  353. package/test/google.test.js +710 -0
  354. package/test/granola.test.js +240 -0
  355. package/test/hex.test.js +253 -0
  356. package/test/heygen.test.js +121 -0
  357. package/test/hubspot.test.js +103 -0
  358. package/test/inngest.test.js +219 -0
  359. package/test/lightspeed.test.js +250 -0
  360. package/test/linear.test.js +146 -0
  361. package/test/linkedin.test.js +243 -0
  362. package/test/logo-dev.test.js +79 -0
  363. package/test/mailgun.test.js +107 -0
  364. package/test/mapbox.test.js +181 -0
  365. package/test/mcp.test.js +227 -0
  366. package/test/microsoft-fabric.test.js +258 -0
  367. package/test/microsoft.test.js +554 -0
  368. package/test/n8nOAuth.test.js +188 -0
  369. package/test/notionOAuth.test.js +183 -0
  370. package/test/oura.test.js +211 -0
  371. package/test/paddleCatalogue.test.js +51 -0
  372. package/test/paddlePermissions.test.js +101 -0
  373. package/test/perplexityComposition.test.js +39 -0
  374. package/test/pipedriveOAuth.test.js +140 -0
  375. package/test/posthog.test.js +200 -0
  376. package/test/prestashop.test.js +207 -0
  377. package/test/resend.test.js +163 -0
  378. package/test/salesforce.test.js +276 -0
  379. package/test/semrush.test.js +479 -0
  380. package/test/sentry.test.js +35 -0
  381. package/test/shopify.test.js +247 -0
  382. package/test/slack.test.js +320 -0
  383. package/test/snowflake.test.js +391 -0
  384. package/test/tally.test.js +75 -0
  385. package/test/telegram.test.js +58 -0
  386. package/test/tiktok.test.js +243 -0
  387. package/test/tokens.test.js +1079 -0
  388. package/test/twilio.test.js +221 -0
  389. package/test/twitch.test.js +573 -0
  390. package/test/wave.test.js +678 -0
  391. package/test/wix.test.js +1099 -0
  392. package/test/wiz.test.js +185 -0
  393. package/test/wordpress-com.test.js +469 -0
  394. package/test/wordpress.test.js +660 -0
  395. package/test/workday.test.js +314 -0
  396. package/test/x-twitter.test.js +256 -0
  397. package/test/xero.test.js +700 -0
  398. package/test/zoho-books.test.js +253 -0
  399. package/test/zoho-crm.test.js +223 -0
@@ -0,0 +1,724 @@
1
+ ---
2
+ id: connectors/oauth-connection
3
+ title: OAuth connections with portable files
4
+ summary: Compose provider consent, verification and encrypted file persistence from an application server or CLI.
5
+ keywords: connectors, integrations, oauth, shopify, assistant permissions, workday, staffing, tiktok, linkedin, google ads, gaql, developer token, salesforce, soql, databricks, fabric, graphql, service principal, client credentials, wordpress, twitch, microsoft, word, powerpoint, xero, wave, zoho, crm, books, accounting, files, cli, consent
6
+ requires: @jskit-ai/connectors-core, @jskit-ai/connectors-catalog
7
+ ---
8
+
9
+ # OAuth connections with portable files
10
+
11
+ ## Use when
12
+
13
+ Use an own OAuth web-client registration to connect accounts from an existing
14
+ application or operator CLI. The same library owns state, code exchange,
15
+ verification and token handling. WordPress.com illustrates composition here;
16
+ follow each selected provider's setup guide and scopes.
17
+
18
+ ## Do not use when
19
+
20
+ This runtime accepts application-owned registrations; managed gateway
21
+ assignments are invalid configuration. Native public clients are not covered by
22
+ this pattern. A shared provider account is not each user's personal
23
+ account. An OAuth data connection does not create the application's login.
24
+
25
+ ## Product decisions
26
+
27
+ Choose the integration's ownership mode, scopes and callback owner. Shared
28
+ connections require membership checks before mapping to a stable shared subject.
29
+ Personal connections use the existing authenticated user's stable identity.
30
+ The callback must recover that same owner; do not accept owner IDs from a URL.
31
+ An operator CLI can use its trusted process-owner policy and a registered local
32
+ callback listener. Never copy that identity policy into a public web route.
33
+
34
+ ## Invariants
35
+
36
+ - The UI and CLI edit the same `integrations.json` and shared validation schema.
37
+ - Client secrets, tokens and pending attempts stay outside exported source.
38
+ - File runtime state is encrypted with a durable operator-owned key.
39
+ - Saving configuration is not consent; provider verification precedes Connected.
40
+ - Callbacks must match their registered destination, pending state and owner.
41
+ - Failed or cancelled replacement consent preserves an existing grant.
42
+ - Reduced permission grants remain reduced; source edits do not grant access.
43
+
44
+ ## Shopify product operations and assistant permissions
45
+
46
+ Import `shopifyProvider` from `@jskit-ai/connectors-catalog/server/shopify` and read
47
+ the packaged `docs/shopify.md`. The supported new-app flow is an installed app in
48
+ the **same Shopify organization** as its store, with `grantType: "client_credentials"`.
49
+ There is no callback in this flow. Put the client secret in an environment
50
+ reference and configure the permanent `shopDomain`, not a custom storefront URL.
51
+ Call `connectClientCredentials` before the named product operations. Existing
52
+ Admin API tokens use `connectApiKey` instead. Other merchants need the unfinished
53
+ Shopify installation/consent flow; do not pretend client credentials cover them.
54
+
55
+ The runtime sends Shopify's header and GraphQL Admin API 2026-07 requests. It
56
+ supports bounded product listing, creation, update and deletion. Create defaults
57
+ to draft. Use Product GIDs; price/SKU/variants and publication are separate work.
58
+ Do not retry a mutation blindly after timeout. A store connection is not shopper
59
+ login or an individual staff member's authorized session.
60
+
61
+ Construct assistant-facing services with `executionMode: "assistant"`; the
62
+ host's trusted authorization callback receives `{ assistantPermission, input }`.
63
+ It must verify real human approval and return `approved: true` for `ask`, together
64
+ with the checked owner identity. The shared runtime denies `never` and does not
65
+ accept a browser-supplied approval flag. `always` still checks application access.
66
+ The host must bind approval to the exact request and supply its existing decision
67
+ UI/storage; the library does not create another approval system.
68
+
69
+ The portable `assistantPolicy` holds enablement, a default and action overrides.
70
+ It is independent of credentials, provider scopes and connection sharing. Host
71
+ workspace policy may further restrict it. Use `authorizeAssistantAction` only
72
+ before a host-owned lifecycle operation such as enabling or claiming a store;
73
+ it authorizes but does not execute that action. The captured remaining action
74
+ choices do not mean variant/discount/store lifecycle adapters are implemented.
75
+ The application owns its registration and token storage. The editor's
76
+ Connect/approval journey must invoke that application's setup operations.
77
+
78
+ ## HubSpot account connections
79
+
80
+ Import `hubspotProvider` from `@jskit-ai/connectors-catalog/server/hubspot`.
81
+ Use the packaged `docs/hubspot.md` registration instructions. Configure an own
82
+ registration with `clientId`, `clientSecretRef: "env:HUBSPOT_CLIENT_SECRET"`,
83
+ `callbackUrlRef: "env:HUBSPOT_CALLBACK_URL"` and
84
+ `tokenEndpointAuthMethod: "client_secret_post"`. Select scopes `oauth` and
85
+ `crm.objects.contacts.read`; the integration's authentication is
86
+ `{ "method": "oauth2", "registrationRef": "hubspot" }` when that registration
87
+ is named `hubspot`.
88
+
89
+ Use `beginAuthorization`, the existing application's callback route and
90
+ `completeAuthorization`, then `contacts.list` with optional `limit`, `after`
91
+ and `archived`. Verification reads contacts. The provider implements confidential
92
+ code exchange, scope-array normalization and refresh through HubSpot's current
93
+ token endpoint; do not build another token exchange or gateway.
94
+
95
+ For `per-user`, the application's authenticated identity owns each local grant.
96
+ HubSpot installations normally expose account-level CRM access; this mode does
97
+ not itself enforce HubSpot record ownership or implement application login.
98
+ For `shared`, only authorized app administrators can connect the shared account.
99
+ Use the API-key pattern instead for a static/private token, retaining the
100
+ `crm.objects.contacts.read` configuration permission. Disconnect is local;
101
+ provider installation removal is separate.
102
+
103
+ ## Linear account connections
104
+
105
+ Import `linearProvider` from `@jskit-ai/connectors-catalog/server/linear` and
106
+ follow `docs/linear.md` to create the project's own registration. Store its
107
+ Client ID in configuration, Client Secret in `env:LINEAR_CLIENT_SECRET`, and
108
+ callback in `env:LINEAR_CALLBACK_URL`; select `client_secret_post`.
109
+ Use authentication `{ "method": "oauth2", "registrationRef": "linear" }`
110
+ when the registration is named `linear`, and keep `scopes: ["read"]`.
111
+
112
+ The application calls `beginAuthorization`, handles its registered callback with
113
+ `completeAuthorization`, then invokes `profile.read` or `issues.list` (optional
114
+ `first` and `after`). The provider owns S256, scope delimiter normalization and
115
+ rotating refresh. The caller owns authorization and subject identity. Shared
116
+ connections belong to the application's authorized administrator; per-user
117
+ connections belong to the signed-in application user. Connecting Linear does not
118
+ implement application login. This flow acts as the consenting Linear user.
119
+
120
+ The same grant supports `tools.list` and `tools.call` against Linear's fixed MCP
121
+ endpoint. Authorize each tool and its arguments before invocation; tools can
122
+ write if the provider permissions allow it. No second MCP registration or Vibe64
123
+ gateway is needed. For personal keys use the API-key pattern, keep the `read`
124
+ configuration scope and restrict the actual key in Linear. Disconnect deletes
125
+ the local grant; provider revocation remains a separate account action.
126
+
127
+ ## Framework APIs
128
+
129
+ Import configuration validation, `createConnectionService`, environment
130
+ resolution and the file storage/protection exports from connectors-core.
131
+ The selected catalogue provider supplies the protocol and operation contracts.
132
+
133
+ ## Example files
134
+
135
+ Use the packaged `docs/wordpress-com.md` guide in `@jskit-ai/connectors-catalog`.
136
+ `example/integrations.json` supplies its portable configuration. Replace the
137
+ placeholder with the provider's assigned Client ID, then compose the ordinary
138
+ package APIs in an application module:
139
+
140
+ ```js
141
+ import { readFile } from "node:fs/promises";
142
+ import { parseIntegrationConfiguration } from "@jskit-ai/connectors-core/shared/configuration";
143
+ import { createConnectionService, createEnvironmentReferenceResolver } from "@jskit-ai/connectors-core/server";
144
+ import { createFileConnectionStore, createCredentialProtection } from "@jskit-ai/connectors-core/server/file-storage";
145
+ import { wordpressComProvider } from "@jskit-ai/connectors-catalog/server/wordpress-com";
146
+
147
+ const providers = [wordpressComProvider];
148
+ const configuration = parseIntegrationConfiguration(await readFile("integrations.json", "utf8"), { providers });
149
+ const protection = createCredentialProtection({
150
+ keys: { current: Buffer.from(process.env.CONNECTOR_STORAGE_KEY, "base64") }, activeKeyId: "current"
151
+ });
152
+ const connections = createConnectionService({
153
+ configuration, providers,
154
+ store: createFileConnectionStore({ directory: process.env.CONNECTOR_STATE_DIRECTORY, protection }),
155
+ resolveReference: createEnvironmentReferenceResolver(), authorize: applicationConnectionPolicy
156
+ });
157
+ ```
158
+
159
+ `applicationConnectionPolicy` checks the authenticated caller and requested
160
+ operation, then returns `{ applicationId, subjectId }`. Keep the state directory
161
+ outside source and preserve its encryption key across restarts/backups.
162
+
163
+ 1. Call `beginAuthorization({ context, integrationId })` and open the returned
164
+ `authorizationUrl` in the user's browser. A resource-specific provider may
165
+ also require `verificationInput`, validated before consent starts.
166
+ 2. At the application's registered callback, recover authenticated `context`
167
+ and call `completeAuthorization({ context, integrationId, callbackUrl })`.
168
+ Route errors through ordinary application error handling.
169
+ 3. Call `invoke({ context, integrationId, operation, input })` for a named
170
+ provider operation. Provider responses stay subject to application policy.
171
+ 4. `cancelAuthorization({ context, integrationId, state })` abandons a pending
172
+ attempt. `disconnect({ context, integrationId })` removes local access and
173
+ pending attempts. It does not revoke provider-wide access.
174
+
175
+ ## Variation points
176
+
177
+ Google, Microsoft, Oura and WordPress.com have different scope and token
178
+ contracts. Use their provider exports instead of inferring these from fields.
179
+ WordPress.com verifies token ownership/scopes from its profile and requests
180
+ comma-separated permissions. Oura handles reduced callback scopes and rotated
181
+ refresh tokens. Some providers do not return a refresh token; expired access
182
+ then needs consent again. Provider PKCE enforcement needs provider evidence.
183
+
184
+ ## Twitch composition
185
+
186
+ Use `twitchProvider` from `@jskit-ai/connectors-catalog/server/twitch` in the
187
+ provider array above and the portable JSON in `docs/twitch.md`. Start with
188
+ `user:read:email` and `user:read:follows` for `profile.read` and
189
+ `channels.followed`; remove any permission whose operation is not used.
190
+ Its normal operations verify the token before data access. The provider also
191
+ exposes `token.validate` for Twitch's required startup/hourly validation of
192
+ maintained sessions, including idle connections:
193
+
194
+ ```js
195
+ // Run from the host's startup and scheduled-job paths. Contexts are derived
196
+ // by its existing authorization owner, never from caller-supplied user IDs.
197
+ for (const context of maintainedTwitchContexts) {
198
+ try {
199
+ await connections.invoke({ context, integrationId: "twitch", operation: "token.validate" });
200
+ } catch (error) {
201
+ await reportConnectionFailure(context, error);
202
+ }
203
+ }
204
+ ```
205
+
206
+ The host supplies `maintainedTwitchContexts` and `reportConnectionFailure`;
207
+ these are not JSKIT exports. Its scheduler must prevent overlapping runs and
208
+ surface reconnect state. Merely saving configuration installs no scheduled
209
+ job. Neither the provider nor this composition implements application login.
210
+ Twitch requires an application-specific registration: do not reuse one editor
211
+ client ID across independent generated apps. Register the application's own callback URL. The runtime handles array/string token
212
+ scopes and Client-ID headers; do not duplicate those details in app scaffolding.
213
+
214
+ ## Slack composition
215
+
216
+ Import `slackProvider` from `@jskit-ai/connectors-catalog/server/slack` and include
217
+ it in the provider array used for parsing and `createConnectionService`.
218
+ Set `settings.actor` to `user` or `bot`, independently of application ownership.
219
+ Use an own confidential registration and a real registered HTTPS callback;
220
+ plain HTTP loopback is not supported by Slack. The [Slack guide](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/slack.md)
221
+ contains a complete portable JSON file and manual/API registration instructions.
222
+
223
+ For channel listing, request `channels:read` and call:
224
+
225
+ ```js
226
+ const firstPage = await connections.invoke({
227
+ context: authenticatedContext,
228
+ integrationId: "slack",
229
+ operation: "channels.list",
230
+ input: { limit: 50, exclude_archived: true }
231
+ });
232
+ // Retain next_cursor even when filtering leaves this page empty.
233
+ const nextCursor = firstPage.response_metadata?.next_cursor;
234
+ ```
235
+
236
+ The host supplies `authenticatedContext`; user request parameters cannot select
237
+ another owner. The library selects `user_scope` versus `scope`, extracts the
238
+ requested token identity, checks Slack's HTTP-200 errors and refreshes rotating
239
+ grants under the file lock. Do not duplicate that code in generated handlers.
240
+ Add the corresponding read permission before using `groups.list`,
241
+ `directMessages.list` or `groupMessages.list`. `auth.test` returns identity.
242
+
243
+ An individually owned bot connection still acts as the installed workspace bot.
244
+ It is not a personal account or an application login. Actor changes require
245
+ reconnection and remove incompatible form scopes. Captured permission choices
246
+ do not imply implemented operations: history, sends, events, organization-wide
247
+ installs and Sign in with Slack remain outside this fragment. The application implements and registers its own callback.
248
+
249
+ ## Microsoft document composition
250
+
251
+ Import `microsoftWordProvider` or `microsoftPowerPointProvider` from the matching
252
+ `@jskit-ai/connectors-catalog/server/microsoft-word` or
253
+ `@jskit-ai/connectors-catalog/server/microsoft-powerpoint` export. Use that provider
254
+ in the composition above and its packaged guide's JSON. A `files` slot requests
255
+ `Files.Read` and, for refresh capability, `offline_access`. Set `settings.tenantId`
256
+ to an allowed audience or directory GUID matching the registration. The shared
257
+ library uses it for authorization, token exchange and refresh; changing the
258
+ tenant requires reconnecting. Never build token URLs from unvalidated user input.
259
+
260
+ After consent and verification, the host can call the same service:
261
+
262
+ ```js
263
+ const page = await connections.invoke({
264
+ context, integrationId: "files", operation: "items.list",
265
+ input: { folderId, pageSize: 25, nextLink }
266
+ });
267
+ const file = await connections.invoke({
268
+ context, integrationId: "files", operation: "items.get", input: { itemId }
269
+ });
270
+ ```
271
+
272
+ The host supplies authenticated `context`, an optional `folderId`/`nextLink`
273
+ and the chosen `itemId`. Pass the original folder ID with every continuation.
274
+ Keep `page["@odata.nextLink"]` even if `page.value` is empty: the adapter filters
275
+ an upstream page by file extension, so the next page can contain matching files.
276
+ Display folder and file metadata through the app's existing UI. The returned
277
+ `file` is metadata, not document contents; returned web URLs do not authorize
278
+ additional downloads. These adapters implement no document editing, recursive
279
+ crawl or app login. Leave paging and named-operation HTTP ownership in JSKIT;
280
+ the app owns its file selection, presentation and access policy.
281
+
282
+ ## Xero composition
283
+
284
+ Import `xeroProvider` from `@jskit-ai/connectors-catalog/server/xero` and use
285
+ the exact portable configuration in `docs/xero.md`. Its registration requires
286
+ `tokenEndpointAuthMethod: "client_secret_basic"`; code exchange and refresh
287
+ stay in JSKIT. Use an HTTPS callback or Xero's permitted `http://localhost`
288
+ callback for local CLI work; `127.0.0.1` is not accepted by this provider.
289
+
290
+ ```js
291
+ const tenants = await connections.invoke({
292
+ context, integrationId: "xero", operation: "connections.list"
293
+ });
294
+ // The app displays permitted ORGANISATION entries, takes an explicit choice,
295
+ // and authorises that choice against its own workspace/account policy.
296
+ const tenantId = await choosePermittedOrganisation(tenants, context);
297
+ const contacts = await connections.invoke({
298
+ context, integrationId: "xero", operation: "contacts.list",
299
+ input: { tenantId, page: 1, pageSize: 50 }
300
+ });
301
+ ```
302
+
303
+ `choosePermittedOrganisation` is application-owned selection and policy, not a
304
+ JSKIT export. Never select the first tenant automatically or trust a submitted
305
+ ID merely because it has UUID syntax. Runtime reads additionally check that the
306
+ current token still has an ORGANISATION connection before sending a tenant
307
+ header. This does not replace the application's own authorisation boundary.
308
+ The same pattern applies to `organisation.read` and `invoices.list` with their
309
+ required read scopes. Follow page numbers explicitly; the library performs no
310
+ automatic crawl, calculations, writes or login. Present private data only to
311
+ the authorised caller. Refresh and encrypted file state remain library code.
312
+
313
+ The guide covers the manual developer-app setup, connection tiers and
314
+ application callback requirements. The application supplies its own registration.
315
+
316
+ ## Wave composition
317
+
318
+ Import `waveProvider` from `@jskit-ai/connectors-catalog/server/wave` into the
319
+ same provider array and use `docs/wave.md` for portable JSON and registration
320
+ setup. Keep `client_secret_post` authentication. Grant `user:read` for verification,
321
+ `business:read` for selection, and the matching customer/invoice read permission.
322
+
323
+ ```js
324
+ const businesses = await connections.invoke({
325
+ context, integrationId: "wave", operation: "businesses.list",
326
+ input: { page: 1, pageSize: 20 }
327
+ });
328
+ const businessId = await choosePermittedBusiness(businesses.data.businesses, context);
329
+ const customers = await connections.invoke({
330
+ context, integrationId: "wave", operation: "customers.list",
331
+ input: { businessId, page: 1, pageSize: 20 }
332
+ });
333
+ ```
334
+
335
+ `choosePermittedBusiness` is the host's selection and authorization function,
336
+ not a JSKIT export. Do not default to the first business or trust an incoming
337
+ business ID without policy checks. Preserve `pageInfo` and nullable edge nodes;
338
+ advance only when the caller requests another page. `invoice:write` alone cannot
339
+ authorize invoice reads. Results with GraphQL errors are rejected even if they
340
+ contain partial data. The library sends fixed queries and owns token refresh,
341
+ including Wave's original redirect URI, under encrypted file storage.
342
+
343
+ Wave OAuth business access requires Pro or Advisor, and use for other customers
344
+ requires provider approval. This is a data connection, not login. The application must implement and register an actual
345
+ served callback. Do not replace OAuth with a personal full-access token for
346
+ customer applications or copy protocol logic into generated routes.
347
+
348
+ ## Verification
349
+
350
+ Focused tests simulate consent and provider responses with real temporary
351
+ encrypted text storage. They cover restart, cancellation, scope reduction,
352
+ ownership, refresh/reconnect and errors. Editor tests verify JSON fields and
353
+ persistence. These checks do not generate or run sample applications or use
354
+ real provider credentials.
355
+
356
+ ## Avoid
357
+
358
+ Do not implement OAuth protocol logic in copied scaffolding, put client secrets
359
+ in browser code, assume requested permissions were all granted, or label a
360
+ saved registration as a connected account. Do not create a database solely
361
+ for connector configuration or runtime state.
362
+
363
+
364
+ ## Zoho CRM composition
365
+
366
+ Import `zohoCrmProvider` from `@jskit-ai/connectors-catalog/server/zoho-crm` and
367
+ pass it to the existing connection service. Follow the packaged
368
+ `docs/zoho-crm.md` for registration, references and portable configuration.
369
+ Choose the account's data center and CRM environment explicitly. Do not follow
370
+ callback-supplied hosts or choose another organisation on the user's behalf.
371
+
372
+ ```js
373
+ const page = await connections.invoke({
374
+ context: authenticatedOwner,
375
+ integrationId: "crm",
376
+ operation: "leads.list",
377
+ input: { fields: "Last_Name,Email", per_page: 50, page: 1 }
378
+ });
379
+ ```
380
+
381
+ The library owns comma-separated scopes, PKCE, token exchange/refresh, API-domain
382
+ validation and `Zoho-oauthtoken` headers. `users.current` verifies the connection;
383
+ `contacts.list`, `accounts.list` and `deals.list` are also available. Keep page
384
+ tokens associated with the same authenticated owner and query, and request later
385
+ pages explicitly. HTTP204 becomes an empty page. The host owns data presentation,
386
+ record access policy and the OAuth callback. Reference secrets instead of putting
387
+ them in JSON; use the same file and connection service for a trusted CLI.
388
+
389
+ A shared connection shares one organisation's CRM access. Personal connections
390
+ require the host's per-user policy. The application owns its registration and callback. These data scopes do not
391
+ implement app sign-in or promise independent provider quotas.
392
+
393
+
394
+ ## Zoho Books composition
395
+
396
+ Import `zohoBooksProvider` from `@jskit-ai/connectors-catalog/server/zoho-books`
397
+ and use the same connection service, file store and owner policy above. See
398
+ `docs/zoho-books.md` for the JSON and regional client setup. Match the selected
399
+ region to the account. Keep `ZohoBooks.settings.READ` for verification.
400
+
401
+ ```js
402
+ const result = await connections.invoke({
403
+ context: authenticatedOwner, integrationId: "books", operation: "organizations.list"
404
+ });
405
+ // Present active organisations from result.organizations. The application
406
+ // validates the user's choice and any narrower organisation access policy.
407
+ const invoices = await connections.invoke({
408
+ context: authenticatedOwner, integrationId: "books", operation: "invoices.list",
409
+ input: { organization_id: selectedOrganizationId, page: 1, per_page: 50 }
410
+ });
411
+ ```
412
+
413
+ Never pick the first or default organisation automatically. A configured
414
+ `settings.organizationId` fixes the organisation and can supply the operation's
415
+ ID; an input attempting to override it fails. With no configured ID the caller
416
+ must supply one. Zoho enforces resource access; the host must enforce any
417
+ narrower per-user policy, especially when deliberately sharing one connection.
418
+ `organizations.list` verifies access to a configured active organisation but
419
+ returns the account's organisation list for discovery. It does not select one.
420
+
421
+ The library owns regional OAuth, PKCE, refresh, API-domain validation and token
422
+ headers. Lists make one request and preserve `page_context`; use its
423
+ `has_more_page` value for explicit continued paging. IDs stay strings. The host
424
+ owns callbacks, presentation and selection. Configuration save does not grant
425
+ provider access or implement app login. Registrations remain application-owned.
426
+
427
+
428
+ ## Lightspeed X-Series composition
429
+
430
+ Import `lightspeedProvider` from `@jskit-ai/connectors-catalog/server/lightspeed`
431
+ and give it to the existing connection service. Use the JSON and provider setup
432
+ in `docs/lightspeed.md`. The store prefix is required and fixed before consent;
433
+ never route credentials using a callback-supplied domain. Keep `products:read`
434
+ for verification and pass `verificationInput: { page_size: 1 }` when starting it.
435
+
436
+ ```js
437
+ const products = await connections.invoke({
438
+ context: authenticatedOwner, integrationId: "retail", operation: "products.list",
439
+ input: { page_size: 50, deleted: false }
440
+ });
441
+ ```
442
+
443
+ `customers.list` and `outlets.list` use the same paging inputs with their own read
444
+ scopes. Request subsequent pages explicitly with version bounds. Preserve null
445
+ customer values and avoid assuming a full page means more records certainly exist.
446
+ The library pins the current API version, validates store-bound token responses,
447
+ and persists each rotated refresh token before reading data. It sends PKCE;
448
+ provider enforcement has not been proven with a live client. Do not add retries
449
+ around authorization codes, refresh or interrupted requests.
450
+
451
+ The host owns authenticated subjects, shared-store access, callback routes and
452
+ rendering. CLI and UI use the same configuration; no database is required for
453
+ editor configuration. Each application supplies its own registration and callback; app sign-in is a separate concern. Extra
454
+ scope selections do not create write operations or independent provider quotas.
455
+ ## Databricks user consent and service accounts
456
+
457
+ Import `databricksProvider` from `@jskit-ai/connectors-catalog/server/databricks`.
458
+ Read `docs/databricks.md` for the two portable configurations. A custom OAuth app
459
+ uses `authorization_code`, `client_secret_post`, a callback reference and
460
+ `all-apis offline_access`. A service principal uses `client_credentials`,
461
+ `client_secret_basic` and its Databricks OAuth secret reference; it has no
462
+ callback or user refresh token. Use `jobs` for a suitably scoped service secret.
463
+ Service principals cannot use `per-user` ownership.
464
+
465
+ Compose the ordinary connections service/Feature and file store. Call
466
+ `connectClientCredentials` or the `connectors.verifyClientCredentials` action
467
+ to verify a service principal. User access still uses `beginAuthorization` and
468
+ `completeAuthorization`. The library owns token requests, renewal, secret
469
+ resolution, state, grant checks and persistence; do not generate replacements
470
+ in the application. The app owns routes, binding values and trusted identity.
471
+
472
+ `jobs.list` reads one page with `limit`, `name`, `expand_tasks` and `page_token`.
473
+ `jobs.get` reads one job with a safe numeric `job_id` and optional continuation
474
+ token. Empty lists may omit `jobs`; nested job arrays may need further pages.
475
+ No job execution, SQL query, compute startup or write operation is implemented.
476
+ Source permission changes to a service account require reconnecting. The
477
+ runtime renews only its prior grant and commits renewal even if a later API
478
+ read fails. Never supply an arbitrary request URL or reuse a service grant as
479
+ an app user's connection.
480
+
481
+ Both flows pin requests to the configured per-workspace origin. The application
482
+ implements and registers its own user-consent callback. Its registration belongs
483
+ to its Databricks account; it is not automatically universal across customer
484
+ accounts. Follow the guide for admin provisioning and direct CLI wiring.
485
+ Application login remains separate.
486
+
487
+ ## Microsoft Fabric GraphQL
488
+
489
+ Import `microsoftFabricProvider` from
490
+ `@jskit-ai/connectors-catalog/server/microsoft-fabric`. Read the package's
491
+ `docs/microsoft-fabric.md` before wiring it. Use its portable configuration with
492
+ an exact directory GUID, Application (client) ID, secret reference and the
493
+ existing GraphQL API endpoint. Do not reuse the ordinary Microsoft Graph
494
+ providers or their permissions: Fabric uses a different resource.
495
+
496
+ User consent uses `authorization_code`, the confidential `client_secret_post`
497
+ method, a callback reference, delegated
498
+ `https://analysis.windows.net/powerbi/api/GraphQLApi.Execute.All` and optional
499
+ `offline_access`. Service accounts use `client_credentials`, the same client
500
+ authentication method, and `https://api.fabric.microsoft.com/.default`. They
501
+ have no callback, user refresh token or per-user ownership. Switching grants
502
+ in the shared UI removes incompatible scopes; choose the new permission before
503
+ saving. The CLI parser enforces the same contract.
504
+
505
+ Reuse `createConnectionService` or `ConnectorsFeature`, the file connection store
506
+ and existing authorization/reference resolver. Call `connectClientCredentials`
507
+ or `connectors.verifyClientCredentials` for a service account; use the ordinary
508
+ authorization start/callback methods for user consent. The library owns token
509
+ exchange, renewal, locking, scope validation and encrypted storage. The app owns
510
+ the authenticated owner mapping and its allowed GraphQL documents.
511
+
512
+ Verification runs `connection.check`, a fixed root `__typename` query. It does
513
+ not establish access to every table. `schema.types` uses explicit introspection,
514
+ which a Fabric workspace administrator must enable; an exported SDL is an
515
+ alternative for authoring. `graphql.execute` accepts a document, optional JSON
516
+ variables and an operation name and returns one response. It can execute writes.
517
+ Keep documents in app server code, validate the permitted variables, and use
518
+ the shared authorization callback to restrict each operation. Do not present
519
+ this as a read-only proxy or accept arbitrary documents from app users. Request
520
+ pagination in the app's chosen document; no automatic traversal is implemented.
521
+
522
+ GraphQL errors, including partial successes, fail without exposing provider
523
+ messages. A failed mutation may have changed data; the runtime does not replay
524
+ it. Cancellation is local interruption, not proof of remote rollback. Token
525
+ renewal persists before the document executes, including when that execution
526
+ fails. Changing tenant, API endpoint, client or grant requires reconnecting.
527
+
528
+ User consent returns to the application's own implemented and registered callback.
529
+ Service access has no callback. Entra registrations, tenant enablement, API
530
+ permissions and source access remain administrator-owned provisioning. Distinct registration names do not isolate Fabric capacity. The application
531
+ owns login separately and keeps its client secret in private Env.
532
+
533
+
534
+ ## Salesforce composition
535
+
536
+ Use `salesforceProvider` from `@jskit-ai/connectors-catalog/server/salesforce`
537
+ and the portable JSON in `docs/salesforce.md`. Read that guide before provisioning
538
+ an External Client App. Production/Developer Edition and Sandbox have distinct
539
+ My Domain formats. Client credentials remain in references; the runtime pins
540
+ consent, token exchange and APIs to that org and handles undated/rotating grants.
541
+ The ordinary file service, Env resolver and application owner policy above apply.
542
+
543
+ After consent, `limits.read` verifies API access. A server action can expose an
544
+ approved query through the same library:
545
+
546
+ ```js
547
+ const result = await connections.invoke({
548
+ context: authenticatedContext, integrationId: "crm", operation: "query.read",
549
+ input: { q: "SELECT Id, Name FROM Account ORDER BY Id LIMIT 20" }, signal
550
+ });
551
+ ```
552
+
553
+ The application supplies the trusted context and abort signal. It authorizes
554
+ objects, fields and any query parameters in its existing action/policy; avoid
555
+ an unrestricted query endpoint. `api` can authorize writes even though these
556
+ operations only read. Do not use provider connection identity as application
557
+ login. For metadata, call `objects.list` and `objects.describe` with an object
558
+ API name. Keep a returned `nextRecordsUrl` with its original owner/query and pass
559
+ it only to `query.next`. No automatic paging is installed.
560
+
561
+ Map `connector_cursor_expired` to restarting the authorized query and
562
+ `connector_reconnect_required` to the existing connection UI. Do not retry a
563
+ failed operation in a loop. Register the application's implemented callback and
564
+ follow provider requirements for distributing an app across customer orgs.
565
+ Separate registrations do not divide an org's API allocation.
566
+
567
+ ## Google Ads composition
568
+
569
+ Use `googleAdsProvider` from `@jskit-ai/connectors-catalog/server/google-ads`
570
+ with the same file service and owner policy. Start from the actual portable JSON
571
+ in `docs/google-ads.md`. Setup needs a Web OAuth client in a Cloud project
572
+ with the required Google Ads API access level. Developer tokens were retired
573
+ on September 9, 2026; do not add a developer-token reference or pilot selector.
574
+ The app owns its registration and grants. This does not establish app login
575
+ or make arbitrary reports public.
576
+
577
+ `customers.listAccessible` verifies the grant and returns directly accessible
578
+ customer resource names. It does not list every manager descendant. Use
579
+ `customers.listClients` for an authorized manager's hierarchy metadata, keeping
580
+ the operation customer ID separate from optional `settings.loginCustomerId`.
581
+ For a useful campaign report, the existing server action can call:
582
+
583
+ ```js
584
+ const report = await connections.invoke({
585
+ context: authenticatedContext,
586
+ integrationId: "ads",
587
+ operation: "reports.search",
588
+ input: {
589
+ customerId: authorizedCustomerId,
590
+ query: "SELECT campaign.id, campaign.name, metrics.impressions, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_7_DAYS LIMIT 100"
591
+ },
592
+ signal
593
+ });
594
+ ```
595
+
596
+ Derive `authorizedCustomerId` from the app's existing account-access policy.
597
+ Authorize fields, date ranges and filters too; do not send arbitrary browser/AI
598
+ GAQL to a public server route. The library passes the operation and input
599
+ snapshot to the host policy before credentials or API requests. Google's
600
+ `adwords` permission may allow writes, despite this operation set's reads.
601
+
602
+ Render `report.results ?? []`; retain integer strings and cost micros without
603
+ rounding. Keep `nextPageToken` with the exact query/customer/owner for an explicit
604
+ next call. No automatic page loop or SearchStream endpoint is installed. API
605
+ errors can reflect developer approval, account relationships or quotas even
606
+ after valid OAuth consent. Map `connector_api_access_invalid` to API setup,
607
+ `connector_scope_missing` and `connector_reconnect_required` to consent recovery,
608
+ and `connector_rate_limited` to the app's bounded usage policy. Never solve API
609
+ approval by repeatedly asking the user to reconnect.
610
+
611
+ The provider guide includes console clicks, API/CLI automation feasibility,
612
+ application-owned callback configuration and account quota boundaries.
613
+ Different client IDs do not automatically separate developer-token capacity;
614
+ approved pilot projects can have usage caps while organization/account limits
615
+ still apply. The CLI uses exactly this library and file configuration without
616
+ Vibe64. No generated app or live provider operation is required to validate the
617
+ configuration, run the focused provider tests or read this source pattern.
618
+
619
+ ## LinkedIn composition
620
+
621
+ Use `linkedinProvider` from `@jskit-ai/connectors-catalog/server/linkedin` and
622
+ `docs/linkedin.md`. Both `openid` and `profile` are required; request `email`
623
+ only when needed. `profile.read` accepts no input and reads the connected
624
+ member's userinfo. Optional email fields may be absent. The fragment discards
625
+ ID tokens and does not implement app login or member posting; preserving
626
+ `w_member_social` in configuration does not provide a publishing operation.
627
+ Ordinary expiry requires reconnect unless LinkedIn approved programmatic
628
+ refresh. Keep the confidential client secret on the backend, including when
629
+ composing a CLI; the separately enabled native flow is not implemented.
630
+ Implement and register the application's callback using its assigned app URL
631
+ or explicit host override. Operator setup belongs to the application developer.
632
+
633
+ ## TikTok composition
634
+
635
+ Use `tiktokProvider` from `@jskit-ai/connectors-catalog/server/tiktok` and the
636
+ packaged `docs/tiktok.md`. The portable `clientId` field stores TikTok's Client
637
+ key. The adapter sends `client_key` during authorize/token exchanges, comma
638
+ separated scopes, and requires a static HTTPS Web callback under 512 characters.
639
+ The CLI uses that same callback-owning backend and file runtime; do not embed
640
+ its secret into distributed clients or assume HTTP loopback/native support.
641
+
642
+ `profile.read` verifies basic access. `profile.extended`, `profile.stats` and
643
+ `videos.list` require their respective optional permissions. Handle declined
644
+ permissions as unavailable operations; never substitute the builder's account
645
+ for an app user's connection. Video reads use explicit pages with string IDs;
646
+ the runtime implements no posting or Research API. Refresh rotates credentials
647
+ and may reduce permissions. Local disconnect does not revoke access at TikTok.
648
+ The application owns its callback and allowed return destination. App login
649
+ remains a separate concern from this data connection.
650
+
651
+ ## Snowflake account OAuth
652
+
653
+ Use `snowflakeProvider` from `@jskit-ai/connectors-catalog/server/snowflake` and
654
+ `docs/snowflake.md`. Its portable settings are `accountUrl` and optional `role`.
655
+ The shared form and CLI parser derive compatible scope choices from the role.
656
+ Omit the role for the connected user's default and retain `refresh_token`;
657
+ otherwise include the exact required role scope returned by `getProviderScopes`.
658
+ Do not hand-encode a space-containing role twice. Changing role/account requires
659
+ new consent. The registration supports confidential client secret POST or Basic;
660
+ PKCE remains enabled for both.
661
+
662
+ The useful operation is `databases.list` with `showLimit`, `like`, `startsWith`,
663
+ `fromName` and `history`. It reads one metadata page and pins the configured role
664
+ in the request header. Do not turn user text into SQL or infer table access from
665
+ successful metadata verification. HTTP 202 remains an explicit incomplete
666
+ response, with no polling implementation in this fragment.
667
+
668
+ An administrator creates the custom OAuth integration inside each customer's
669
+ Snowflake account. AI can assist through authorized SQL/CLI provisioning, but
670
+ reader credentials do not grant that authority. Keep secret results out of chat.
671
+ Register the application's callback and update that registration and its
672
+ environment binding when the callback domain changes. Compute billing belongs
673
+ to the Snowflake account. Use application authorization, reference resolution
674
+ and durable storage; the editor does not hold the grant.
675
+
676
+ ## Gemini Enterprise search
677
+
678
+ Use `geminiEnterpriseProvider` from
679
+ `@jskit-ai/connectors-catalog/server/gemini-enterprise` with the existing core
680
+ connection service. `docs/gemini-enterprise.md` contains the portable file and
681
+ provider setup worksheet. Store `projectId`, `location` (`global`, `us`, `eu`)
682
+ and `engineId` as settings, with a confidential Google OAuth registration and
683
+ the `https://www.googleapis.com/auth/cloud-platform` scope. The settings choose
684
+ the API origin and the engine under `default_collection`; callers cannot change
685
+ the target or supply a source identity in an operation request.
686
+
687
+ `engine.get` checks metadata access. `search` accepts `query`, `pageSize` (1–25,
688
+ default 10) and optional `pageToken`. Reuse the same query/page size while
689
+ paginating. The result is Google's JSON envelope, not a generated answer. Treat
690
+ document snippets and `redirectUri` as untrusted data; do not follow returned URLs
691
+ automatically. Search permission and source access are separate from engine
692
+ metadata permission. Shared and assistant modes act as one connected Google
693
+ account, so authorize every caller before exposing that account's search results.
694
+ This fragment implements no per-user Google identity, Workforce Identity, widget,
695
+ resource ingestion, app login or chat sessions.
696
+
697
+ The application implements and registers its own callback. A callback domain
698
+ change requires updating its provider registration and environment binding.
699
+ Independent Google Cloud registration projects can separate some quotas, but
700
+ engine billing and limits also depend on the project hosting the engine. Don't
701
+ claim two OAuth client IDs isolate all paid/free consumption. An authorized AI
702
+ can help prepare resource/IAM configuration; Google Auth Platform client setup,
703
+ verification, consent and licensing remain explicit operator/provider tasks.
704
+
705
+ ## Workday composition
706
+
707
+ Import `workdayProvider` from `@jskit-ai/connectors-catalog/server/workday` and
708
+ use the portable file and administrator steps in `docs/workday.md`. This is a
709
+ per-user tenant connection with three endpoint fields, Client ID and secret and
710
+ callback references. Its confidential flow omits PKCE and URL scope strings;
711
+ Staffing functional areas and user domain permissions are configured in Workday.
712
+ Keep that provider exception inside the library. Other providers retain S256.
713
+
714
+ Use `workers.me` for the connected worker and `workers.list` for explicit pages
715
+ with limit, offset, optional name/worker-ID search and visibility flags. The
716
+ library selects Staffing v7 on the configured API host, path prefix and tenant;
717
+ never substitute another user's token or derive ownership from request input.
718
+ An account without a visible worker record cannot pass the initial check.
719
+
720
+ Every customer tenant needs its own registration and the application's actual
721
+ callback URL. Distinct client IDs do not imply separate tenant quotas.
722
+ The CLI composes the same server APIs and encrypted file store. App login,
723
+ Workday Extend, ISU, SOAP, writes and bulk sync are outside
724
+ this initial fragment. Consent and live tenant testing require separate access.