@jskit-ai/agent-docs 0.1.241 → 0.1.243

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 (131) hide show
  1. package/guide/agent/app-extras/assistant-conversation.md +4 -2
  2. package/guide/agent/app-extras/assistant.md +3 -1
  3. package/guide/agent/app-extras/realtime.md +12 -3
  4. package/guide/agent/app-setup/database-layer.md +1 -1
  5. package/guide/agent/app-setup/existing-application-migration.md +0 -7
  6. package/guide/agent/framework/application-operations.md +1 -1
  7. package/guide/agent/framework/crud-operations.md +9 -9
  8. package/guide/agent/framework/ui-operations.md +6 -30
  9. package/guide/agent/index.md +2 -0
  10. package/package.json +2 -3
  11. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  12. package/patterns/feature-package/example/booking-engine/src/server/actions.js +0 -2
  13. package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +1 -1
  14. package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +1 -1
  15. package/patterns/minimal-foundation/example/AGENTS.md +19 -0
  16. package/patterns/minimal-foundation/example/package.json +3 -3
  17. package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +3 -11
  18. package/patterns/minimal-foundation/example/src/main.js +0 -2
  19. package/patterns/shell-foundation/PATTERN.md +11 -20
  20. package/patterns/shell-foundation/example/AGENTS.md +19 -0
  21. package/patterns/shell-foundation/example/package.json +4 -4
  22. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  23. package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +3 -11
  24. package/patterns/shell-foundation/example/src/components/ShellLayout.vue +1 -0
  25. package/patterns/shell-foundation/example/src/main.js +0 -2
  26. package/patterns/shell-foundation/example/src/pages/home/settings.vue +2 -2
  27. package/reference/autogen/KERNEL_MAP.md +16 -147
  28. package/reference/autogen/PATTERN_INDEX.md +37 -37
  29. package/reference/autogen/packages/agent-docs.md +1 -9
  30. package/reference/autogen/packages/assistant-core.md +102 -68
  31. package/reference/autogen/packages/assistant-runtime.md +29 -15
  32. package/reference/autogen/packages/assistant-voice-sherpa.md +2 -1
  33. package/reference/autogen/packages/assistant-voice.md +8 -11
  34. package/reference/autogen/packages/auth-core.md +1 -1
  35. package/reference/autogen/packages/auth-provider-local-core.md +1 -1
  36. package/reference/autogen/packages/auth-provider-local-db-core.md +1 -1
  37. package/reference/autogen/packages/auth-provider-oidc-core.md +1 -1
  38. package/reference/autogen/packages/auth-provider-supabase-core.md +1 -1
  39. package/reference/autogen/packages/auth-web.md +1 -2
  40. package/reference/autogen/packages/connector-google-calendar.md +6 -2
  41. package/reference/autogen/packages/connectors-catalog.md +26 -7
  42. package/reference/autogen/packages/connectors-core.md +14 -3
  43. package/reference/autogen/packages/connectors-web.md +6 -1
  44. package/reference/autogen/packages/console-core.md +1 -1
  45. package/reference/autogen/packages/console-web.md +1 -1
  46. package/reference/autogen/packages/crud-core.md +1 -1
  47. package/reference/autogen/packages/database-runtime-mysql.md +1 -1
  48. package/reference/autogen/packages/database-runtime-postgres.md +1 -1
  49. package/reference/autogen/packages/database-runtime.md +2 -86
  50. package/reference/autogen/packages/http-runtime.md +6 -92
  51. package/reference/autogen/packages/http-web.md +29 -49
  52. package/reference/autogen/packages/json-rest-api-core.md +1 -1
  53. package/reference/autogen/packages/kernel.md +108 -405
  54. package/reference/autogen/packages/mobile-capacitor.md +11 -1
  55. package/reference/autogen/packages/oidc-issuer-core.md +1 -1
  56. package/reference/autogen/packages/payments-core.md +12 -4
  57. package/reference/autogen/packages/payments-web.md +1 -1
  58. package/reference/autogen/packages/realtime.md +7 -5
  59. package/reference/autogen/packages/resource-core.md +1 -4
  60. package/reference/autogen/packages/resource-crud-core.md +4 -3
  61. package/reference/autogen/packages/rewarded-core.md +1 -1
  62. package/reference/autogen/packages/rewarded-web.md +1 -1
  63. package/reference/autogen/packages/shell-web.md +114 -49
  64. package/reference/autogen/packages/storage-runtime.md +1 -1
  65. package/reference/autogen/packages/uploads-image-web.md +1 -1
  66. package/reference/autogen/packages/uploads-runtime.md +1 -1
  67. package/reference/autogen/packages/users-core.md +1 -1
  68. package/reference/autogen/packages/users-web.md +1 -2
  69. package/reference/autogen/packages/workspaces-core.md +3 -1
  70. package/reference/autogen/packages/workspaces-web.md +1 -1
  71. package/reference/autogen/tooling/config-eslint.md +1 -1
  72. package/reference/autogen/tooling/jskit-catalog.md +8 -9
  73. package/reference/autogen/tooling/jskit-release.md +3 -4
  74. package/reference/autogen/tooling/testUtils.md +1 -28
  75. package/skills/jskit/SKILL.md +8 -6
  76. package/skills/jskit/references/app-operations.md +1 -1
  77. package/skills/jskit/references/crud-form-actions.md +62 -0
  78. package/skills/jskit/references/crud-operations.md +9 -9
  79. package/skills/jskit/references/existing-application-migration.md +0 -7
  80. package/{patterns → skills/jskit/references/heuristics}/INDEX.md +24 -38
  81. package/{patterns → skills/jskit/references/heuristics}/child-cruds.md +2 -0
  82. package/{patterns → skills/jskit/references/heuristics}/client-requests.md +2 -0
  83. package/{patterns → skills/jskit/references/heuristics}/crud-authoring.md +2 -0
  84. package/{patterns → skills/jskit/references/heuristics}/crud-links.md +2 -0
  85. package/{patterns → skills/jskit/references/heuristics}/crud-repository-mapping.md +3 -1
  86. package/{patterns → skills/jskit/references/heuristics}/filters.md +3 -1
  87. package/{patterns → skills/jskit/references/heuristics}/live-actions.md +2 -0
  88. package/{patterns → skills/jskit/references/heuristics}/page-redirects.md +2 -0
  89. package/{patterns → skills/jskit/references/heuristics}/page-scaffolding.md +5 -3
  90. package/{patterns → skills/jskit/references/heuristics}/placements.md +2 -0
  91. package/{patterns → skills/jskit/references/heuristics}/row-policies.md +2 -0
  92. package/{patterns → skills/jskit/references/heuristics}/server-search.md +2 -0
  93. package/{patterns → skills/jskit/references/heuristics}/surfaces.md +5 -3
  94. package/{patterns → skills/jskit/references/heuristics}/ui-contract.md +3 -1
  95. package/{patterns → skills/jskit/references/heuristics}/ui-testing.md +2 -0
  96. package/skills/jskit/references/pattern-index.md +37 -37
  97. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +19 -0
  98. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +3 -3
  99. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +3 -11
  100. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/main.js +0 -2
  101. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +11 -20
  102. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +19 -0
  103. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +4 -4
  104. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  105. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +3 -11
  106. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/ShellLayout.vue +1 -0
  107. package/skills/jskit/references/patterns/app/shell-foundation/example/src/main.js +0 -2
  108. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings.vue +2 -2
  109. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  110. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  111. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  112. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  113. package/skills/jskit/references/patterns/connectors/oauth-connection/PATTERN.md +27 -610
  114. package/skills/jskit/references/patterns/connectors/paddle-catalogue/example/create-products.js +2 -1
  115. package/skills/jskit/references/patterns/connectors/redshift-queries/PATTERN.md +1 -1
  116. package/skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md +11 -1
  117. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
  118. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  119. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  120. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  121. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
  122. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +0 -2
  123. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +1 -1
  124. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +1 -1
  125. package/skills/jskit/references/patterns/shell/application-shell/PATTERN.md +18 -4
  126. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/index.vue +15 -5
  127. package/skills/jskit/references/patterns/shell/application-shell/example/tests/e2e/adaptive-shell.spec.ts +1 -1
  128. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
  129. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
  130. package/skills/jskit/references/ui-operations.md +6 -30
  131. package/templates/app/AGENTS.md +0 -38
@@ -41,89 +41,6 @@ callback listener. Never copy that identity policy into a public web route.
41
41
  - Failed or cancelled replacement consent preserves an existing grant.
42
42
  - Reduced permission grants remain reduced; source edits do not grant access.
43
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
44
  ## Framework APIs
128
45
 
129
46
  Import configuration validation, `createConnectionService`, environment
@@ -181,6 +98,33 @@ comma-separated permissions. Oura handles reduced callback scopes and rotated
181
98
  refresh tokens. Some providers do not return a refresh token; expired access
182
99
  then needs consent again. Provider PKCE enforcement needs provider evidence.
183
100
 
101
+ ## Provider specifics
102
+
103
+ Each provider's guide in the packaged `docs/` folder of
104
+ `@jskit-ai/connectors-catalog` holds its OAuth registration, portable
105
+ configuration and runtime composition:
106
+
107
+ - `docs/shopify.md`
108
+ - `docs/hubspot.md`
109
+ - `docs/linear.md`
110
+ - `docs/twitch.md`
111
+ - `docs/slack.md`
112
+ - `docs/microsoft-oauth.md`
113
+ - `docs/xero.md`
114
+ - `docs/wave.md`
115
+ - `docs/zoho-crm.md`
116
+ - `docs/zoho-books.md`
117
+ - `docs/lightspeed.md`
118
+ - `docs/databricks.md`
119
+ - `docs/microsoft-fabric.md`
120
+ - `docs/salesforce.md`
121
+ - `docs/google-ads.md`
122
+ - `docs/linkedin.md`
123
+ - `docs/tiktok.md`
124
+ - `docs/snowflake.md`
125
+ - `docs/gemini-enterprise.md`
126
+ - `docs/workday.md`
127
+
184
128
  ## Shared connection from an Env refresh token
185
129
 
186
130
  When the application's host already holds a long-lived grant for the shared
@@ -206,170 +150,6 @@ replace that value instead." A revoked token fails with "The refresh token in
206
150
  Env no longer works; replace that Env value." The refresh token must come from
207
151
  the same client as `registrationRef`; non-JSKIT apps read the variable directly.
208
152
 
209
- ## Twitch composition
210
-
211
- Use `twitchProvider` from `@jskit-ai/connectors-catalog/server/twitch` in the
212
- provider array above and the portable JSON in `docs/twitch.md`. Start with
213
- `user:read:email` and `user:read:follows` for `profile.read` and
214
- `channels.followed`; remove any permission whose operation is not used.
215
- Its normal operations verify the token before data access. The provider also
216
- exposes `token.validate` for Twitch's required startup/hourly validation of
217
- maintained sessions, including idle connections:
218
-
219
- ```js
220
- // Run from the host's startup and scheduled-job paths. Contexts are derived
221
- // by its existing authorization owner, never from caller-supplied user IDs.
222
- for (const context of maintainedTwitchContexts) {
223
- try {
224
- await connections.invoke({ context, integrationId: "twitch", operation: "token.validate" });
225
- } catch (error) {
226
- await reportConnectionFailure(context, error);
227
- }
228
- }
229
- ```
230
-
231
- The host supplies `maintainedTwitchContexts` and `reportConnectionFailure`;
232
- these are not JSKIT exports. Its scheduler must prevent overlapping runs and
233
- surface reconnect state. Merely saving configuration installs no scheduled
234
- job. Neither the provider nor this composition implements application login.
235
- Twitch requires an application-specific registration: do not reuse one editor
236
- client ID across independent generated apps. Register the application's own callback URL. The runtime handles array/string token
237
- scopes and Client-ID headers; do not duplicate those details in app scaffolding.
238
-
239
- ## Slack composition
240
-
241
- Import `slackProvider` from `@jskit-ai/connectors-catalog/server/slack` and include
242
- it in the provider array used for parsing and `createConnectionService`.
243
- Set `settings.actor` to `user` or `bot`, independently of application ownership.
244
- Use an own confidential registration and a real registered HTTPS callback;
245
- 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)
246
- contains a complete portable JSON file and manual/API registration instructions.
247
-
248
- For channel listing, request `channels:read` and call:
249
-
250
- ```js
251
- const firstPage = await connections.invoke({
252
- context: authenticatedContext,
253
- integrationId: "slack",
254
- operation: "channels.list",
255
- input: { limit: 50, exclude_archived: true }
256
- });
257
- // Retain next_cursor even when filtering leaves this page empty.
258
- const nextCursor = firstPage.response_metadata?.next_cursor;
259
- ```
260
-
261
- The host supplies `authenticatedContext`; user request parameters cannot select
262
- another owner. The library selects `user_scope` versus `scope`, extracts the
263
- requested token identity, checks Slack's HTTP-200 errors and refreshes rotating
264
- grants under the file lock. Do not duplicate that code in generated handlers.
265
- Add the corresponding read permission before using `groups.list`,
266
- `directMessages.list` or `groupMessages.list`. `auth.test` returns identity.
267
-
268
- An individually owned bot connection still acts as the installed workspace bot.
269
- It is not a personal account or an application login. Actor changes require
270
- reconnection and remove incompatible form scopes. Captured permission choices
271
- do not imply implemented operations: history, sends, events, organization-wide
272
- installs and Sign in with Slack remain outside this fragment. The application implements and registers its own callback.
273
-
274
- ## Microsoft document composition
275
-
276
- Import `microsoftWordProvider` or `microsoftPowerPointProvider` from the matching
277
- `@jskit-ai/connectors-catalog/server/microsoft-word` or
278
- `@jskit-ai/connectors-catalog/server/microsoft-powerpoint` export. Use that provider
279
- in the composition above and its packaged guide's JSON. A `files` slot requests
280
- `Files.Read` and, for refresh capability, `offline_access`. Set `settings.tenantId`
281
- to an allowed audience or directory GUID matching the registration. The shared
282
- library uses it for authorization, token exchange and refresh; changing the
283
- tenant requires reconnecting. Never build token URLs from unvalidated user input.
284
-
285
- After consent and verification, the host can call the same service:
286
-
287
- ```js
288
- const page = await connections.invoke({
289
- context, integrationId: "files", operation: "items.list",
290
- input: { folderId, pageSize: 25, nextLink }
291
- });
292
- const file = await connections.invoke({
293
- context, integrationId: "files", operation: "items.get", input: { itemId }
294
- });
295
- ```
296
-
297
- The host supplies authenticated `context`, an optional `folderId`/`nextLink`
298
- and the chosen `itemId`. Pass the original folder ID with every continuation.
299
- Keep `page["@odata.nextLink"]` even if `page.value` is empty: the adapter filters
300
- an upstream page by file extension, so the next page can contain matching files.
301
- Display folder and file metadata through the app's existing UI. The returned
302
- `file` is metadata, not document contents; returned web URLs do not authorize
303
- additional downloads. These adapters implement no document editing, recursive
304
- crawl or app login. Leave paging and named-operation HTTP ownership in JSKIT;
305
- the app owns its file selection, presentation and access policy.
306
-
307
- ## Xero composition
308
-
309
- Import `xeroProvider` from `@jskit-ai/connectors-catalog/server/xero` and use
310
- the exact portable configuration in `docs/xero.md`. Its registration requires
311
- `tokenEndpointAuthMethod: "client_secret_basic"`; code exchange and refresh
312
- stay in JSKIT. Use an HTTPS callback or Xero's permitted `http://localhost`
313
- callback for local CLI work; `127.0.0.1` is not accepted by this provider.
314
-
315
- ```js
316
- const tenants = await connections.invoke({
317
- context, integrationId: "xero", operation: "connections.list"
318
- });
319
- // The app displays permitted ORGANISATION entries, takes an explicit choice,
320
- // and authorises that choice against its own workspace/account policy.
321
- const tenantId = await choosePermittedOrganisation(tenants, context);
322
- const contacts = await connections.invoke({
323
- context, integrationId: "xero", operation: "contacts.list",
324
- input: { tenantId, page: 1, pageSize: 50 }
325
- });
326
- ```
327
-
328
- `choosePermittedOrganisation` is application-owned selection and policy, not a
329
- JSKIT export. Never select the first tenant automatically or trust a submitted
330
- ID merely because it has UUID syntax. Runtime reads additionally check that the
331
- current token still has an ORGANISATION connection before sending a tenant
332
- header. This does not replace the application's own authorisation boundary.
333
- The same pattern applies to `organisation.read` and `invoices.list` with their
334
- required read scopes. Follow page numbers explicitly; the library performs no
335
- automatic crawl, calculations, writes or login. Present private data only to
336
- the authorised caller. Refresh and encrypted file state remain library code.
337
-
338
- The guide covers the manual developer-app setup, connection tiers and
339
- application callback requirements. The application supplies its own registration.
340
-
341
- ## Wave composition
342
-
343
- Import `waveProvider` from `@jskit-ai/connectors-catalog/server/wave` into the
344
- same provider array and use `docs/wave.md` for portable JSON and registration
345
- setup. Keep `client_secret_post` authentication. Grant `user:read` for verification,
346
- `business:read` for selection, and the matching customer/invoice read permission.
347
-
348
- ```js
349
- const businesses = await connections.invoke({
350
- context, integrationId: "wave", operation: "businesses.list",
351
- input: { page: 1, pageSize: 20 }
352
- });
353
- const businessId = await choosePermittedBusiness(businesses.data.businesses, context);
354
- const customers = await connections.invoke({
355
- context, integrationId: "wave", operation: "customers.list",
356
- input: { businessId, page: 1, pageSize: 20 }
357
- });
358
- ```
359
-
360
- `choosePermittedBusiness` is the host's selection and authorization function,
361
- not a JSKIT export. Do not default to the first business or trust an incoming
362
- business ID without policy checks. Preserve `pageInfo` and nullable edge nodes;
363
- advance only when the caller requests another page. `invoice:write` alone cannot
364
- authorize invoice reads. Results with GraphQL errors are rejected even if they
365
- contain partial data. The library sends fixed queries and owns token refresh,
366
- including Wave's original redirect URI, under encrypted file storage.
367
-
368
- Wave OAuth business access requires Pro or Advisor, and use for other customers
369
- requires provider approval. This is a data connection, not login. The application must implement and register an actual
370
- served callback. Do not replace OAuth with a personal full-access token for
371
- customer applications or copy protocol logic into generated routes.
372
-
373
153
  ## Verification
374
154
 
375
155
  Focused tests simulate consent and provider responses with real temporary
@@ -384,366 +164,3 @@ Do not implement OAuth protocol logic in copied scaffolding, put client secrets
384
164
  in browser code, assume requested permissions were all granted, or label a
385
165
  saved registration as a connected account. Do not create a database solely
386
166
  for connector configuration or runtime state.
387
-
388
-
389
- ## Zoho CRM composition
390
-
391
- Import `zohoCrmProvider` from `@jskit-ai/connectors-catalog/server/zoho-crm` and
392
- pass it to the existing connection service. Follow the packaged
393
- `docs/zoho-crm.md` for registration, references and portable configuration.
394
- Choose the account's data center and CRM environment explicitly. Do not follow
395
- callback-supplied hosts or choose another organisation on the user's behalf.
396
-
397
- ```js
398
- const page = await connections.invoke({
399
- context: authenticatedOwner,
400
- integrationId: "crm",
401
- operation: "leads.list",
402
- input: { fields: "Last_Name,Email", per_page: 50, page: 1 }
403
- });
404
- ```
405
-
406
- The library owns comma-separated scopes, PKCE, token exchange/refresh, API-domain
407
- validation and `Zoho-oauthtoken` headers. `users.current` verifies the connection;
408
- `contacts.list`, `accounts.list` and `deals.list` are also available. Keep page
409
- tokens associated with the same authenticated owner and query, and request later
410
- pages explicitly. HTTP204 becomes an empty page. The host owns data presentation,
411
- record access policy and the OAuth callback. Reference secrets instead of putting
412
- them in JSON; use the same file and connection service for a trusted CLI.
413
-
414
- A shared connection shares one organisation's CRM access. Personal connections
415
- require the host's per-user policy. The application owns its registration and callback. These data scopes do not
416
- implement app sign-in or promise independent provider quotas.
417
-
418
-
419
- ## Zoho Books composition
420
-
421
- Import `zohoBooksProvider` from `@jskit-ai/connectors-catalog/server/zoho-books`
422
- and use the same connection service, file store and owner policy above. See
423
- `docs/zoho-books.md` for the JSON and regional client setup. Match the selected
424
- region to the account. Keep `ZohoBooks.settings.READ` for verification.
425
-
426
- ```js
427
- const result = await connections.invoke({
428
- context: authenticatedOwner, integrationId: "books", operation: "organizations.list"
429
- });
430
- // Present active organisations from result.organizations. The application
431
- // validates the user's choice and any narrower organisation access policy.
432
- const invoices = await connections.invoke({
433
- context: authenticatedOwner, integrationId: "books", operation: "invoices.list",
434
- input: { organization_id: selectedOrganizationId, page: 1, per_page: 50 }
435
- });
436
- ```
437
-
438
- Never pick the first or default organisation automatically. A configured
439
- `settings.organizationId` fixes the organisation and can supply the operation's
440
- ID; an input attempting to override it fails. With no configured ID the caller
441
- must supply one. Zoho enforces resource access; the host must enforce any
442
- narrower per-user policy, especially when deliberately sharing one connection.
443
- `organizations.list` verifies access to a configured active organisation but
444
- returns the account's organisation list for discovery. It does not select one.
445
-
446
- The library owns regional OAuth, PKCE, refresh, API-domain validation and token
447
- headers. Lists make one request and preserve `page_context`; use its
448
- `has_more_page` value for explicit continued paging. IDs stay strings. The host
449
- owns callbacks, presentation and selection. Configuration save does not grant
450
- provider access or implement app login. Registrations remain application-owned.
451
-
452
-
453
- ## Lightspeed X-Series composition
454
-
455
- Import `lightspeedProvider` from `@jskit-ai/connectors-catalog/server/lightspeed`
456
- and give it to the existing connection service. Use the JSON and provider setup
457
- in `docs/lightspeed.md`. The store prefix is required and fixed before consent;
458
- never route credentials using a callback-supplied domain. Keep `products:read`
459
- for verification and pass `verificationInput: { page_size: 1 }` when starting it.
460
-
461
- ```js
462
- const products = await connections.invoke({
463
- context: authenticatedOwner, integrationId: "retail", operation: "products.list",
464
- input: { page_size: 50, deleted: false }
465
- });
466
- ```
467
-
468
- `customers.list` and `outlets.list` use the same paging inputs with their own read
469
- scopes. Request subsequent pages explicitly with version bounds. Preserve null
470
- customer values and avoid assuming a full page means more records certainly exist.
471
- The library pins the current API version, validates store-bound token responses,
472
- and persists each rotated refresh token before reading data. It sends PKCE;
473
- provider enforcement has not been proven with a live client. Do not add retries
474
- around authorization codes, refresh or interrupted requests.
475
-
476
- The host owns authenticated subjects, shared-store access, callback routes and
477
- rendering. CLI and UI use the same configuration; no database is required for
478
- editor configuration. Each application supplies its own registration and callback; app sign-in is a separate concern. Extra
479
- scope selections do not create write operations or independent provider quotas.
480
- ## Databricks user consent and service accounts
481
-
482
- Import `databricksProvider` from `@jskit-ai/connectors-catalog/server/databricks`.
483
- Read `docs/databricks.md` for the two portable configurations. A custom OAuth app
484
- uses `authorization_code`, `client_secret_post`, a callback reference and
485
- `all-apis offline_access`. A service principal uses `client_credentials`,
486
- `client_secret_basic` and its Databricks OAuth secret reference; it has no
487
- callback or user refresh token. Use `jobs` for a suitably scoped service secret.
488
- Service principals cannot use `per-user` ownership.
489
-
490
- Compose the ordinary connections service/Feature and file store. Call
491
- `connectClientCredentials` or the `connectors.verifyClientCredentials` action
492
- to verify a service principal. User access still uses `beginAuthorization` and
493
- `completeAuthorization`. The library owns token requests, renewal, secret
494
- resolution, state, grant checks and persistence; do not generate replacements
495
- in the application. The app owns routes, binding values and trusted identity.
496
-
497
- `jobs.list` reads one page with `limit`, `name`, `expand_tasks` and `page_token`.
498
- `jobs.get` reads one job with a safe numeric `job_id` and optional continuation
499
- token. Empty lists may omit `jobs`; nested job arrays may need further pages.
500
- No job execution, SQL query, compute startup or write operation is implemented.
501
- Source permission changes to a service account require reconnecting. The
502
- runtime renews only its prior grant and commits renewal even if a later API
503
- read fails. Never supply an arbitrary request URL or reuse a service grant as
504
- an app user's connection.
505
-
506
- Both flows pin requests to the configured per-workspace origin. The application
507
- implements and registers its own user-consent callback. Its registration belongs
508
- to its Databricks account; it is not automatically universal across customer
509
- accounts. Follow the guide for admin provisioning and direct CLI wiring.
510
- Application login remains separate.
511
-
512
- ## Microsoft Fabric GraphQL
513
-
514
- Import `microsoftFabricProvider` from
515
- `@jskit-ai/connectors-catalog/server/microsoft-fabric`. Read the package's
516
- `docs/microsoft-fabric.md` before wiring it. Use its portable configuration with
517
- an exact directory GUID, Application (client) ID, secret reference and the
518
- existing GraphQL API endpoint. Do not reuse the ordinary Microsoft Graph
519
- providers or their permissions: Fabric uses a different resource.
520
-
521
- User consent uses `authorization_code`, the confidential `client_secret_post`
522
- method, a callback reference, delegated
523
- `https://analysis.windows.net/powerbi/api/GraphQLApi.Execute.All` and optional
524
- `offline_access`. Service accounts use `client_credentials`, the same client
525
- authentication method, and `https://api.fabric.microsoft.com/.default`. They
526
- have no callback, user refresh token or per-user ownership. Switching grants
527
- in the shared UI removes incompatible scopes; choose the new permission before
528
- saving. The CLI parser enforces the same contract.
529
-
530
- Reuse `createConnectionService` or `ConnectorsFeature`, the file connection store
531
- and existing authorization/reference resolver. Call `connectClientCredentials`
532
- or `connectors.verifyClientCredentials` for a service account; use the ordinary
533
- authorization start/callback methods for user consent. The library owns token
534
- exchange, renewal, locking, scope validation and encrypted storage. The app owns
535
- the authenticated owner mapping and its allowed GraphQL documents.
536
-
537
- Verification runs `connection.check`, a fixed root `__typename` query. It does
538
- not establish access to every table. `schema.types` uses explicit introspection,
539
- which a Fabric workspace administrator must enable; an exported SDL is an
540
- alternative for authoring. `graphql.execute` accepts a document, optional JSON
541
- variables and an operation name and returns one response. It can execute writes.
542
- Keep documents in app server code, validate the permitted variables, and use
543
- the shared authorization callback to restrict each operation. Do not present
544
- this as a read-only proxy or accept arbitrary documents from app users. Request
545
- pagination in the app's chosen document; no automatic traversal is implemented.
546
-
547
- GraphQL errors, including partial successes, fail without exposing provider
548
- messages. A failed mutation may have changed data; the runtime does not replay
549
- it. Cancellation is local interruption, not proof of remote rollback. Token
550
- renewal persists before the document executes, including when that execution
551
- fails. Changing tenant, API endpoint, client or grant requires reconnecting.
552
-
553
- User consent returns to the application's own implemented and registered callback.
554
- Service access has no callback. Entra registrations, tenant enablement, API
555
- permissions and source access remain administrator-owned provisioning. Distinct registration names do not isolate Fabric capacity. The application
556
- owns login separately and keeps its client secret in private Env.
557
-
558
-
559
- ## Salesforce composition
560
-
561
- Use `salesforceProvider` from `@jskit-ai/connectors-catalog/server/salesforce`
562
- and the portable JSON in `docs/salesforce.md`. Read that guide before provisioning
563
- an External Client App. Production/Developer Edition and Sandbox have distinct
564
- My Domain formats. Client credentials remain in references; the runtime pins
565
- consent, token exchange and APIs to that org and handles undated/rotating grants.
566
- The ordinary file service, Env resolver and application owner policy above apply.
567
-
568
- After consent, `limits.read` verifies API access. A server action can expose an
569
- approved query through the same library:
570
-
571
- ```js
572
- const result = await connections.invoke({
573
- context: authenticatedContext, integrationId: "crm", operation: "query.read",
574
- input: { q: "SELECT Id, Name FROM Account ORDER BY Id LIMIT 20" }, signal
575
- });
576
- ```
577
-
578
- The application supplies the trusted context and abort signal. It authorizes
579
- objects, fields and any query parameters in its existing action/policy; avoid
580
- an unrestricted query endpoint. `api` can authorize writes even though these
581
- operations only read. Do not use provider connection identity as application
582
- login. For metadata, call `objects.list` and `objects.describe` with an object
583
- API name. Keep a returned `nextRecordsUrl` with its original owner/query and pass
584
- it only to `query.next`. No automatic paging is installed.
585
-
586
- Map `connector_cursor_expired` to restarting the authorized query and
587
- `connector_reconnect_required` to the existing connection UI. Do not retry a
588
- failed operation in a loop. Register the application's implemented callback and
589
- follow provider requirements for distributing an app across customer orgs.
590
- Separate registrations do not divide an org's API allocation.
591
-
592
- ## Google Ads composition
593
-
594
- Use `googleAdsProvider` from `@jskit-ai/connectors-catalog/server/google-ads`
595
- with the same file service and owner policy. Start from the actual portable JSON
596
- in `docs/google-ads.md`. Setup needs a Web OAuth client in a Cloud project
597
- with the required Google Ads API access level. Developer tokens were retired
598
- on September 9, 2026; do not add a developer-token reference or pilot selector.
599
- The app owns its registration and grants. This does not establish app login
600
- or make arbitrary reports public.
601
-
602
- `customers.listAccessible` verifies the grant and returns directly accessible
603
- customer resource names. It does not list every manager descendant. Use
604
- `customers.listClients` for an authorized manager's hierarchy metadata, keeping
605
- the operation customer ID separate from optional `settings.loginCustomerId`.
606
- For a useful campaign report, the existing server action can call:
607
-
608
- ```js
609
- const report = await connections.invoke({
610
- context: authenticatedContext,
611
- integrationId: "ads",
612
- operation: "reports.search",
613
- input: {
614
- customerId: authorizedCustomerId,
615
- query: "SELECT campaign.id, campaign.name, metrics.impressions, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_7_DAYS LIMIT 100"
616
- },
617
- signal
618
- });
619
- ```
620
-
621
- Derive `authorizedCustomerId` from the app's existing account-access policy.
622
- Authorize fields, date ranges and filters too; do not send arbitrary browser/AI
623
- GAQL to a public server route. The library passes the operation and input
624
- snapshot to the host policy before credentials or API requests. Google's
625
- `adwords` permission may allow writes, despite this operation set's reads.
626
-
627
- Render `report.results ?? []`; retain integer strings and cost micros without
628
- rounding. Keep `nextPageToken` with the exact query/customer/owner for an explicit
629
- next call. No automatic page loop or SearchStream endpoint is installed. API
630
- errors can reflect developer approval, account relationships or quotas even
631
- after valid OAuth consent. Map `connector_api_access_invalid` to API setup,
632
- `connector_scope_missing` and `connector_reconnect_required` to consent recovery,
633
- and `connector_rate_limited` to the app's bounded usage policy. Never solve API
634
- approval by repeatedly asking the user to reconnect.
635
-
636
- The provider guide includes console clicks, API/CLI automation feasibility,
637
- application-owned callback configuration and account quota boundaries.
638
- Different client IDs do not automatically separate developer-token capacity;
639
- approved pilot projects can have usage caps while organization/account limits
640
- still apply. The CLI uses exactly this library and file configuration without
641
- Vibe64. No generated app or live provider operation is required to validate the
642
- configuration, run the focused provider tests or read this source pattern.
643
-
644
- ## LinkedIn composition
645
-
646
- Use `linkedinProvider` from `@jskit-ai/connectors-catalog/server/linkedin` and
647
- `docs/linkedin.md`. Both `openid` and `profile` are required; request `email`
648
- only when needed. `profile.read` accepts no input and reads the connected
649
- member's userinfo. Optional email fields may be absent. The fragment discards
650
- ID tokens and does not implement app login or member posting; preserving
651
- `w_member_social` in configuration does not provide a publishing operation.
652
- Ordinary expiry requires reconnect unless LinkedIn approved programmatic
653
- refresh. Keep the confidential client secret on the backend, including when
654
- composing a CLI; the separately enabled native flow is not implemented.
655
- Implement and register the application's callback using its assigned app URL
656
- or explicit host override. Operator setup belongs to the application developer.
657
-
658
- ## TikTok composition
659
-
660
- Use `tiktokProvider` from `@jskit-ai/connectors-catalog/server/tiktok` and the
661
- packaged `docs/tiktok.md`. The portable `clientId` field stores TikTok's Client
662
- key. The adapter sends `client_key` during authorize/token exchanges, comma
663
- separated scopes, and requires a static HTTPS Web callback under 512 characters.
664
- The CLI uses that same callback-owning backend and file runtime; do not embed
665
- its secret into distributed clients or assume HTTP loopback/native support.
666
-
667
- `profile.read` verifies basic access. `profile.extended`, `profile.stats` and
668
- `videos.list` require their respective optional permissions. Handle declined
669
- permissions as unavailable operations; never substitute the builder's account
670
- for an app user's connection. Video reads use explicit pages with string IDs;
671
- the runtime implements no posting or Research API. Refresh rotates credentials
672
- and may reduce permissions. Local disconnect does not revoke access at TikTok.
673
- The application owns its callback and allowed return destination. App login
674
- remains a separate concern from this data connection.
675
-
676
- ## Snowflake account OAuth
677
-
678
- Use `snowflakeProvider` from `@jskit-ai/connectors-catalog/server/snowflake` and
679
- `docs/snowflake.md`. Its portable settings are `accountUrl` and optional `role`.
680
- The shared form and CLI parser derive compatible scope choices from the role.
681
- Omit the role for the connected user's default and retain `refresh_token`;
682
- otherwise include the exact required role scope returned by `getProviderScopes`.
683
- Do not hand-encode a space-containing role twice. Changing role/account requires
684
- new consent. The registration supports confidential client secret POST or Basic;
685
- PKCE remains enabled for both.
686
-
687
- The useful operation is `databases.list` with `showLimit`, `like`, `startsWith`,
688
- `fromName` and `history`. It reads one metadata page and pins the configured role
689
- in the request header. Do not turn user text into SQL or infer table access from
690
- successful metadata verification. HTTP 202 remains an explicit incomplete
691
- response, with no polling implementation in this fragment.
692
-
693
- An administrator creates the custom OAuth integration inside each customer's
694
- Snowflake account. AI can assist through authorized SQL/CLI provisioning, but
695
- reader credentials do not grant that authority. Keep secret results out of chat.
696
- Register the application's callback and update that registration and its
697
- environment binding when the callback domain changes. Compute billing belongs
698
- to the Snowflake account. Use application authorization, reference resolution
699
- and durable storage; the editor does not hold the grant.
700
-
701
- ## Gemini Enterprise search
702
-
703
- Use `geminiEnterpriseProvider` from
704
- `@jskit-ai/connectors-catalog/server/gemini-enterprise` with the existing core
705
- connection service. `docs/gemini-enterprise.md` contains the portable file and
706
- provider setup worksheet. Store `projectId`, `location` (`global`, `us`, `eu`)
707
- and `engineId` as settings, with a confidential Google OAuth registration and
708
- the `https://www.googleapis.com/auth/cloud-platform` scope. The settings choose
709
- the API origin and the engine under `default_collection`; callers cannot change
710
- the target or supply a source identity in an operation request.
711
-
712
- `engine.get` checks metadata access. `search` accepts `query`, `pageSize` (1–25,
713
- default 10) and optional `pageToken`. Reuse the same query/page size while
714
- paginating. The result is Google's JSON envelope, not a generated answer. Treat
715
- document snippets and `redirectUri` as untrusted data; do not follow returned URLs
716
- automatically. Search permission and source access are separate from engine
717
- metadata permission. Shared and assistant modes act as one connected Google
718
- account, so authorize every caller before exposing that account's search results.
719
- This fragment implements no per-user Google identity, Workforce Identity, widget,
720
- resource ingestion, app login or chat sessions.
721
-
722
- The application implements and registers its own callback. A callback domain
723
- change requires updating its provider registration and environment binding.
724
- Independent Google Cloud registration projects can separate some quotas, but
725
- engine billing and limits also depend on the project hosting the engine. Don't
726
- claim two OAuth client IDs isolate all paid/free consumption. An authorized AI
727
- can help prepare resource/IAM configuration; Google Auth Platform client setup,
728
- verification, consent and licensing remain explicit operator/provider tasks.
729
-
730
- ## Workday composition
731
-
732
- Import `workdayProvider` from `@jskit-ai/connectors-catalog/server/workday` and
733
- use the portable file and administrator steps in `docs/workday.md`. This is a
734
- per-user tenant connection with three endpoint fields, Client ID and secret and
735
- callback references. Its confidential flow omits PKCE and URL scope strings;
736
- Staffing functional areas and user domain permissions are configured in Workday.
737
- Keep that provider exception inside the library. Other providers retain S256.
738
-
739
- Use `workers.me` for the connected worker and `workers.list` for explicit pages
740
- with limit, offset, optional name/worker-ID search and visibility flags. The
741
- library selects Staffing v7 on the configured API host, path prefix and tenant;
742
- never substitute another user's token or derive ownership from request input.
743
- An account without a visible worker record cannot pass the initial check.
744
-
745
- Every customer tenant needs its own registration and the application's actual
746
- callback URL. Distinct client IDs do not imply separate tenant quotas.
747
- The CLI composes the same server APIs and encrypted file store. App login,
748
- Workday Extend, ISU, SOAP, writes and bulk sync are outside
749
- this initial fragment. Consent and live tenant testing require separate access.
@@ -1,4 +1,4 @@
1
- import { paddleProvider } from "../../../src/server/paddle.js";
1
+ import { paddleProvider } from "@jskit-ai/connectors-catalog/server/paddle";
2
2
 
3
3
  // Application-owned composition: pass an application-mode connection runtime.
4
4
  // An assistant host must approve the complete batch before calling this recipe.
@@ -13,6 +13,7 @@ async function createProductsWithPrices({ runtime, context, integrationId, items
13
13
  !item.product || !item.price || Object.hasOwn(item.price, "product_id")) {
14
14
  throw new TypeError("Each item needs product and price inputs; the new product supplies product_id.");
15
15
  }
16
+ // Shape validation only: the sandbox settings and placeholder product_id are never sent.
16
17
  paddleProvider.operations["products.create"].request(item.product, { environment: "sandbox" });
17
18
  paddleProvider.operations["prices.create"].request({ ...item.price, product_id: `pro_${"a".repeat(26)}` }, { environment: "sandbox" });
18
19
  }