@zackbart/connecta 0.34.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. package/CHANGELOG.md +393 -0
  2. package/README.md +62 -105
  3. package/SECURITY.md +3 -2
  4. package/bin/connecta.mjs +41 -16
  5. package/bin/version.mjs +1 -1
  6. package/dist/access-tokens.d.ts +2 -1
  7. package/dist/access-tokens.js +66 -30
  8. package/dist/activity.d.ts +1 -1
  9. package/dist/activity.js +2 -0
  10. package/dist/agent-config.d.ts +23 -0
  11. package/dist/agent-config.js +59 -0
  12. package/dist/agent-description.js +16 -0
  13. package/dist/agent-identity.js +4 -4
  14. package/dist/agent-observation.js +39 -0
  15. package/dist/auth/clerk-sdk/client.d.ts +2 -0
  16. package/dist/auth/clerk-sdk/generated.js +554 -563
  17. package/dist/auth/clerk-transport.js +70 -3
  18. package/dist/auth/clerk.d.ts +13 -0
  19. package/dist/auth/clerk.js +653 -246
  20. package/dist/auth/cloudflare-access.js +46 -42
  21. package/dist/auth/downstream-client-metadata.js +2 -2
  22. package/dist/auth/downstream-oauth.js +2051 -1160
  23. package/dist/auth/downstream-revocation.js +88 -88
  24. package/dist/auth/native-call.js +20 -0
  25. package/dist/auth/native.js +184 -0
  26. package/dist/auth/oauth-start-reset.js +11 -5
  27. package/dist/auth/oauth-token-response.js +121 -102
  28. package/dist/auth/oauth-v2-migration.js +97 -78
  29. package/dist/auth/renewable-grant.js +10 -0
  30. package/dist/auth/static-oauth.js +663 -271
  31. package/dist/auth/vercel-agent.js +266 -0
  32. package/dist/auth-admission.js +204 -0
  33. package/dist/auth-elicitation.js +350 -241
  34. package/dist/authorization-handoff.js +164 -90
  35. package/dist/call-admission-context.js +3 -10
  36. package/dist/call-admission.js +2 -0
  37. package/dist/call-classification.js +9 -0
  38. package/dist/call-recovery.js +32 -13
  39. package/dist/canonical-json.js +8 -0
  40. package/dist/catalog-cache.js +369 -213
  41. package/dist/catalog-service.js +659 -530
  42. package/dist/catalog.js +5 -1
  43. package/dist/concurrency.js +0 -25
  44. package/dist/config-defaults.d.ts +1 -0
  45. package/dist/config-defaults.js +1 -0
  46. package/dist/config-schema.d.ts +3 -1
  47. package/dist/config-schema.js +13 -3
  48. package/dist/config.d.ts +40 -6
  49. package/dist/config.js +40 -26
  50. package/dist/connector-caller.d.ts +4 -0
  51. package/dist/connector-caller.js +17 -4
  52. package/dist/connectors/api-connector.d.ts +15 -7
  53. package/dist/connectors/api-connector.js +147 -57
  54. package/dist/connectors/guarded-fetch.d.ts +51 -17
  55. package/dist/connectors/guarded-fetch.js +215 -121
  56. package/dist/connectors/negotiation-cache.js +20 -10
  57. package/dist/connectors/option-shapes.js +1 -1
  58. package/dist/connectors/remote-mcp.d.ts +12 -30
  59. package/dist/connectors/remote-mcp.js +960 -564
  60. package/dist/d1.js +10 -243
  61. package/dist/derived-context.js +5 -0
  62. package/dist/describe-config.d.ts +5 -1
  63. package/dist/describe-config.js +3 -0
  64. package/dist/downstream-input.js +347 -260
  65. package/dist/errors.d.ts +87 -6
  66. package/dist/errors.js +114 -4
  67. package/dist/execute.js +87 -50
  68. package/dist/executor-admission.js +3 -0
  69. package/dist/executors/quickjs.js +163 -112
  70. package/dist/guarded-transport.js +50 -0
  71. package/dist/guest-runtime.js +1 -1
  72. package/dist/http/client.js +439 -0
  73. package/dist/http/errors.js +558 -0
  74. package/dist/http/fields.js +49 -0
  75. package/dist/http/hatch-paging.js +318 -0
  76. package/dist/http/hatch.js +1279 -0
  77. package/dist/http/json-schema.js +267 -0
  78. package/dist/http/node-transport.js +241 -0
  79. package/dist/http/oauth.js +162 -0
  80. package/dist/http/paging.js +228 -0
  81. package/dist/http/provider.js +221 -0
  82. package/dist/http/safety.js +82 -0
  83. package/dist/http/services.js +79 -0
  84. package/dist/http/tools.js +383 -0
  85. package/dist/http/vendor-index.js +138 -0
  86. package/dist/http/vendor.js +448 -0
  87. package/dist/http/write-request.js +66 -0
  88. package/dist/http-policy.d.ts +11 -0
  89. package/dist/http-policy.js +45 -0
  90. package/dist/inbound-credential.js +1 -1
  91. package/dist/index.d.ts +2 -2
  92. package/dist/index.js +4 -0
  93. package/dist/invocation-auth.js +30 -19
  94. package/dist/invocation.js +221 -87
  95. package/dist/mcp-result.js +0 -4
  96. package/dist/membership.d.ts +4 -0
  97. package/dist/meta-output.js +1 -1
  98. package/dist/meta-tools.js +534 -408
  99. package/dist/native-recovery.js +52 -0
  100. package/dist/native-tools.js +382 -0
  101. package/dist/node.d.ts +4 -3
  102. package/dist/node.js +45 -8
  103. package/dist/oauth-handoff.js +177 -104
  104. package/dist/oauth-partition.js +6 -20
  105. package/dist/oauth-sealing.js +6 -7
  106. package/dist/operation-vocabulary.js +101 -0
  107. package/dist/operator-record.d.ts +2 -2
  108. package/dist/operator-record.js +17 -4
  109. package/dist/operator-ui/agents.d.ts +5 -4
  110. package/dist/operator-ui/agents.js +17 -7
  111. package/dist/operator-ui/config-summary.js +8 -4
  112. package/dist/operator-ui/connection-map.js +9 -6
  113. package/dist/operator-ui/contract.d.ts +7 -3
  114. package/dist/operator-ui/endpoints.js +5 -14
  115. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  116. package/dist/operator-ui/fix-prompts.js +0 -8
  117. package/dist/operator-ui/generated.js +3 -3
  118. package/dist/operator-ui/health.js +52 -0
  119. package/dist/operator-ui/model.d.ts +2 -3
  120. package/dist/operator-ui/overview.js +11 -19
  121. package/dist/operator-ui/setup-commands.js +0 -4
  122. package/dist/operator-ui/view.d.ts +5 -29
  123. package/dist/operator-ui/view.js +3 -59
  124. package/dist/program-writes.js +47 -26
  125. package/dist/provider-call-facts.d.ts +115 -0
  126. package/dist/provider-call-facts.js +182 -0
  127. package/dist/provider-call.d.ts +112 -0
  128. package/dist/provider-call.js +271 -0
  129. package/dist/provider.d.ts +71 -32
  130. package/dist/provider.js +134 -40
  131. package/dist/providers/_shared/google/hatch.js +91 -0
  132. package/dist/providers/_shared/google/kit.js +537 -0
  133. package/dist/providers/_shared/google/result-size.js +15 -2
  134. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  135. package/dist/providers/_shared/google/service-account.js +8 -4
  136. package/dist/providers/_shared/google/workspace.d.ts +8 -209
  137. package/dist/providers/_shared/google/workspace.js +7 -426
  138. package/dist/providers/_shared/rest/compact-index.js +86 -0
  139. package/dist/providers/_shared/rest/dispatch.js +3 -23
  140. package/dist/providers/_shared/rest/kit.js +546 -0
  141. package/dist/providers/_shared/rest/operation-index.js +230 -14
  142. package/dist/providers/_shared/rest/response-media.js +11 -0
  143. package/dist/providers/_shared/rest/tools.js +101 -78
  144. package/dist/providers/_shared/rest/value-safety.js +353 -195
  145. package/dist/providers/_shared/sensitive-fields.js +27 -0
  146. package/dist/providers/breeze/api.js +584 -0
  147. package/dist/providers/breeze/index.d.ts +3 -3
  148. package/dist/providers/breeze/index.js +67 -1420
  149. package/dist/providers/breeze/openapi.generated.js +60 -0
  150. package/dist/providers/breeze/skill.generated.js +2 -6
  151. package/dist/providers/breeze/tools.js +696 -0
  152. package/dist/providers/ccb/api.js +496 -0
  153. package/dist/providers/ccb/index.d.ts +17 -37
  154. package/dist/providers/ccb/index.js +77 -1702
  155. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  156. package/dist/providers/ccb/lib/constants.js +74 -0
  157. package/dist/providers/ccb/lib/guide.js +9 -0
  158. package/dist/providers/ccb/lib/verdicts.js +387 -0
  159. package/dist/providers/ccb/openapi.generated.js +397 -0
  160. package/dist/providers/ccb/safety.js +295 -0
  161. package/dist/providers/ccb/skill.generated.js +2 -6
  162. package/dist/providers/ccb/tools.js +853 -0
  163. package/dist/providers/cloudflare/api.js +1066 -0
  164. package/dist/providers/cloudflare/index.d.ts +7 -22
  165. package/dist/providers/cloudflare/index.js +80 -194
  166. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  167. package/dist/providers/cloudflare/lib/config.js +2 -0
  168. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  169. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  170. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  171. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  172. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  173. package/dist/providers/cloudflare/openapi.generated.js +3299 -3208
  174. package/dist/providers/cloudflare/{value-safety.js → safety.js} +538 -18
  175. package/dist/providers/cloudflare/skill.generated.js +2 -10
  176. package/dist/providers/cloudflare/tools.js +360 -0
  177. package/dist/providers/docs/api.js +51 -0
  178. package/dist/providers/docs/index.d.ts +1 -12
  179. package/dist/providers/docs/index.js +53 -1165
  180. package/dist/providers/docs/lib/constants.d.ts +18 -0
  181. package/dist/providers/docs/lib/constants.js +18 -0
  182. package/dist/providers/docs/lib/discovery.js +26 -0
  183. package/dist/providers/docs/lib/requests.js +48 -0
  184. package/dist/providers/docs/lib/schemas.js +168 -0
  185. package/dist/providers/docs/openapi.generated.js +16 -0
  186. package/dist/providers/docs/safety.js +54 -0
  187. package/dist/providers/docs/skill.generated.js +2 -6
  188. package/dist/providers/docs/tools.js +802 -0
  189. package/dist/providers/drive/api.js +177 -0
  190. package/dist/providers/drive/index.d.ts +1 -12
  191. package/dist/providers/drive/index.js +38 -1448
  192. package/dist/providers/drive/lib/constants.d.ts +6 -0
  193. package/dist/providers/drive/lib/constants.js +6 -0
  194. package/dist/providers/drive/lib/contracts.js +532 -0
  195. package/dist/providers/drive/lib/hatch.js +197 -0
  196. package/dist/providers/drive/openapi.generated.js +77 -0
  197. package/dist/providers/drive/safety.js +90 -0
  198. package/dist/providers/drive/skill.generated.js +2 -6
  199. package/dist/providers/drive/tools.js +1290 -0
  200. package/dist/providers/forms/api.js +71 -0
  201. package/dist/providers/forms/index.d.ts +1 -12
  202. package/dist/providers/forms/index.js +49 -1145
  203. package/dist/providers/forms/lib/constants.d.ts +14 -0
  204. package/dist/providers/forms/lib/constants.js +19 -0
  205. package/dist/providers/forms/lib/hatch.js +72 -0
  206. package/dist/providers/forms/openapi.generated.js +23 -0
  207. package/dist/providers/forms/safety.js +34 -0
  208. package/dist/providers/forms/skill.generated.js +2 -8
  209. package/dist/providers/forms/tools.js +1024 -0
  210. package/dist/providers/github/api.js +150 -0
  211. package/dist/providers/github/index.d.ts +4 -5
  212. package/dist/providers/github/index.js +30 -87
  213. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  214. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  215. package/dist/providers/github/lib/discovery.js +132 -0
  216. package/dist/providers/github/lib/operations.js +58 -0
  217. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  218. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  219. package/dist/providers/github/openapi.generated.js +1216 -0
  220. package/dist/providers/github/safety.js +216 -0
  221. package/dist/providers/github/skill.generated.js +2 -5
  222. package/dist/providers/github/tools.js +506 -0
  223. package/dist/providers/gmail/api.js +114 -0
  224. package/dist/providers/gmail/index.d.ts +1 -12
  225. package/dist/providers/gmail/index.js +73 -1621
  226. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  227. package/dist/providers/gmail/lib/constants.js +16 -0
  228. package/dist/providers/gmail/lib/index.js +173 -0
  229. package/dist/providers/gmail/lib/schemas.js +176 -0
  230. package/dist/providers/gmail/lib/threading.js +120 -0
  231. package/dist/providers/gmail/openapi.generated.js +92 -0
  232. package/dist/providers/gmail/safety.js +21 -0
  233. package/dist/providers/gmail/skill.generated.js +2 -6
  234. package/dist/providers/gmail/tools.js +1435 -0
  235. package/dist/providers/overflow/api.js +1008 -0
  236. package/dist/providers/overflow/index.d.ts +3 -17
  237. package/dist/providers/overflow/index.js +60 -1488
  238. package/dist/providers/overflow/skill.generated.js +2 -5
  239. package/dist/providers/overflow/tools.js +873 -0
  240. package/dist/providers/planning-center/api.js +467 -0
  241. package/dist/providers/planning-center/index.d.ts +6 -35
  242. package/dist/providers/planning-center/index.js +69 -2445
  243. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  244. package/dist/providers/planning-center/lib/constants.js +83 -0
  245. package/dist/providers/planning-center/lib/discovery.js +40 -0
  246. package/dist/providers/planning-center/lib/guide.js +39 -0
  247. package/dist/providers/planning-center/lib/json-api.js +83 -0
  248. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  249. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  250. package/dist/providers/planning-center/safety.js +188 -0
  251. package/dist/providers/planning-center/skill.generated.js +2 -27
  252. package/dist/providers/planning-center/tools.js +1010 -0
  253. package/dist/providers/sheets/api.js +133 -0
  254. package/dist/providers/sheets/index.d.ts +4 -16
  255. package/dist/providers/sheets/index.js +61 -1172
  256. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  257. package/dist/providers/sheets/lib/constants.js +14 -0
  258. package/dist/providers/sheets/lib/hatch.js +163 -0
  259. package/dist/providers/sheets/lib/requests.js +105 -0
  260. package/dist/providers/sheets/lib/schemas.js +138 -0
  261. package/dist/providers/sheets/openapi.generated.js +30 -0
  262. package/dist/providers/sheets/safety.js +27 -0
  263. package/dist/providers/sheets/skill.generated.js +2 -7
  264. package/dist/providers/sheets/tools.js +734 -0
  265. package/dist/providers/slides/api.js +147 -0
  266. package/dist/providers/slides/index.d.ts +2 -10
  267. package/dist/providers/slides/index.js +48 -2555
  268. package/dist/providers/slides/lib/constants.d.ts +11 -0
  269. package/dist/providers/slides/lib/constants.js +11 -0
  270. package/dist/providers/slides/lib/requests.js +60 -0
  271. package/dist/providers/slides/lib/schemas.js +565 -0
  272. package/dist/providers/slides/openapi.generated.js +18 -0
  273. package/dist/providers/slides/skill.generated.js +2 -6
  274. package/dist/providers/slides/tools.js +1968 -0
  275. package/dist/providers/stripe/api.js +401 -0
  276. package/dist/providers/stripe/index.d.ts +7 -27
  277. package/dist/providers/stripe/index.js +75 -191
  278. package/dist/providers/stripe/lib/config.d.ts +4 -0
  279. package/dist/providers/stripe/lib/config.js +2 -0
  280. package/dist/providers/stripe/openapi.generated.js +4 -3
  281. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  282. package/dist/providers/stripe/skill.generated.js +2 -10
  283. package/dist/providers/stripe/tools.js +77 -0
  284. package/dist/providers/tithely/api.js +531 -0
  285. package/dist/providers/tithely/index.d.ts +19 -0
  286. package/dist/providers/tithely/index.js +86 -965
  287. package/dist/providers/tithely/skill.generated.js +2 -5
  288. package/dist/providers/tithely/tools.js +426 -0
  289. package/dist/providers/vercel/api.js +551 -0
  290. package/dist/providers/vercel/index.d.ts +11 -25
  291. package/dist/providers/vercel/index.js +67 -261
  292. package/dist/providers/vercel/lib/config.d.ts +2 -0
  293. package/dist/providers/vercel/lib/config.js +2 -0
  294. package/dist/providers/vercel/lib/index.js +117 -0
  295. package/dist/providers/vercel/lib/logs.js +100 -0
  296. package/dist/providers/vercel/lib/pin.js +270 -0
  297. package/dist/providers/vercel/openapi.generated.js +398 -376
  298. package/dist/providers/vercel/{value-safety.js → safety.js} +261 -42
  299. package/dist/providers/vercel/skill.generated.js +2 -7
  300. package/dist/providers/vercel/tools.js +642 -0
  301. package/dist/redaction-identity.js +47 -0
  302. package/dist/redaction-marker.js +125 -0
  303. package/dist/registry.d.ts +30 -28
  304. package/dist/registry.js +446 -413
  305. package/dist/routes/access-tokens.js +1 -1
  306. package/dist/routes/actor-labels.js +1 -1
  307. package/dist/routes/connect.js +1 -1
  308. package/dist/routes/dispatch.js +103 -0
  309. package/dist/routes/mcp.js +170 -79
  310. package/dist/routes/oauth.js +3 -1
  311. package/dist/routes/operator.js +2 -2
  312. package/dist/routes/shared.d.ts +5 -4
  313. package/dist/routes/shared.js +244 -177
  314. package/dist/routes/skills.js +10 -8
  315. package/dist/routes/ui-config.js +27 -3
  316. package/dist/routes/ui-data.js +29 -22
  317. package/dist/routes/ui.js +1 -1
  318. package/dist/runtime/call-admission.js +0 -26
  319. package/dist/runtime/call-entry.js +30 -0
  320. package/dist/runtime/call.js +556 -0
  321. package/dist/runtime/connector-scope.js +7 -0
  322. package/dist/runtime/credential-probe.js +34 -0
  323. package/dist/runtime/executor.js +40 -0
  324. package/dist/runtime/native-storage.js +63 -0
  325. package/dist/runtime/registry.js +27 -0
  326. package/dist/runtime/request-scope.js +72 -0
  327. package/dist/runtime/run.js +15 -7
  328. package/dist/runtime/shared-read.js +34 -5
  329. package/dist/runtime/storage.js +34 -21
  330. package/dist/sent-secrets.d.ts +194 -37
  331. package/dist/sent-secrets.js +1743 -340
  332. package/dist/server.js +5 -56
  333. package/dist/skills.js +330 -224
  334. package/dist/sqlite.js +15 -14
  335. package/dist/storage/d1-copy.js +255 -0
  336. package/dist/storage/d1-driver.js +15 -0
  337. package/dist/storage/keys.js +28 -0
  338. package/dist/storage/sql-driver.js +88 -0
  339. package/dist/storage/sql-native.js +544 -0
  340. package/dist/storage/sql-schema.d.ts +6 -0
  341. package/dist/storage/sql-schema.js +15 -0
  342. package/dist/storage/sql.d.ts +14 -20
  343. package/dist/storage/sql.js +29 -535
  344. package/dist/timeout.js +0 -26
  345. package/dist/tool-safety.js +20 -10
  346. package/dist/types.d.ts +11 -99
  347. package/dist/upward.js +3 -0
  348. package/dist/usage-guide.js +3 -1
  349. package/dist/validate.d.ts +4 -2
  350. package/dist/validate.js +86 -9
  351. package/dist/version.d.ts +1 -1
  352. package/dist/version.js +1 -1
  353. package/dist/worker.js +312 -292
  354. package/dist/workspace-subject.js +5 -1
  355. package/dist/write-outcome.js +454 -34
  356. package/documentation/README.md +27 -7
  357. package/documentation/architecture.md +2550 -186
  358. package/documentation/auth.md +821 -98
  359. package/documentation/code-mode.md +56 -21
  360. package/documentation/deploying.md +164 -20
  361. package/documentation/hosted-mcp-migration.md +460 -0
  362. package/documentation/integrating.md +144 -105
  363. package/documentation/meta-tools.md +411 -34
  364. package/documentation/operating.md +28 -4
  365. package/documentation/operator-tests.md +11 -2
  366. package/documentation/operator-ui.md +103 -33
  367. package/documentation/provider-auth-migration.md +38 -63
  368. package/documentation/provider-migration-0.29.md +10 -5
  369. package/documentation/provider-migration-0.35.md +975 -0
  370. package/documentation/providers.md +965 -0
  371. package/examples/worker/AGENTS.md +23 -9
  372. package/examples/worker/README.md +254 -135
  373. package/examples/worker/alchemy.run.ts +116 -0
  374. package/examples/worker/gitignore +10 -0
  375. package/examples/worker/src/connecta.config.ts +23 -21
  376. package/examples/worker/wrangler.jsonc +14 -5
  377. package/guides/connecting-agents.md +157 -0
  378. package/guides/how-it-works.md +156 -0
  379. package/guides/safety-and-trust.md +153 -0
  380. package/package.json +27 -42
  381. package/templates/node/.env.example +3 -0
  382. package/templates/node/README.md +22 -2
  383. package/templates/node/docker-compose.yml +1 -0
  384. package/templates/node/package.json +3 -2
  385. package/templates/node/src/connecta.config.ts +8 -0
  386. package/dist/catalog-drift.d.ts +0 -134
  387. package/dist/catalog-drift.js +0 -493
  388. package/dist/providers/_shared/request-token.js +0 -83
  389. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  390. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  391. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  392. package/dist/providers/basecamp/index.d.ts +0 -43
  393. package/dist/providers/basecamp/index.js +0 -997
  394. package/dist/providers/basecamp/skill.generated.js +0 -9
  395. package/dist/providers/cloudflare/rest.d.ts +0 -37
  396. package/dist/providers/cloudflare/rest.js +0 -1078
  397. package/dist/providers/github/hosted.js +0 -218
  398. package/dist/providers/github/rest.js +0 -321
  399. package/dist/providers/infisical/index.d.ts +0 -7
  400. package/dist/providers/infisical/index.js +0 -713
  401. package/dist/providers/infisical/skill.generated.js +0 -8
  402. package/dist/providers/linear/index.d.ts +0 -55
  403. package/dist/providers/linear/index.js +0 -352
  404. package/dist/providers/linear/skill.generated.js +0 -8
  405. package/dist/providers/mixpanel/index.d.ts +0 -57
  406. package/dist/providers/mixpanel/index.js +0 -468
  407. package/dist/providers/mixpanel/operations.js +0 -20
  408. package/dist/providers/mixpanel/rest.js +0 -603
  409. package/dist/providers/mixpanel/skill.generated.js +0 -10
  410. package/dist/providers/mixpanel/value-safety.js +0 -16
  411. package/dist/providers/notion/index.d.ts +0 -65
  412. package/dist/providers/notion/index.js +0 -368
  413. package/dist/providers/notion/openapi.generated.js +0 -75
  414. package/dist/providers/notion/rest.d.ts +0 -24
  415. package/dist/providers/notion/rest.js +0 -1226
  416. package/dist/providers/notion/skill.generated.js +0 -11
  417. package/dist/providers/notion/value-safety.js +0 -56
  418. package/dist/providers/revenuecat/index.d.ts +0 -49
  419. package/dist/providers/revenuecat/index.js +0 -557
  420. package/dist/providers/revenuecat/skill.generated.js +0 -11
  421. package/dist/providers/stripe/rest.d.ts +0 -14
  422. package/dist/providers/stripe/rest.js +0 -402
  423. package/dist/providers/vercel/rest.d.ts +0 -20
  424. package/dist/providers/vercel/rest.js +0 -1020
  425. package/dist/providers/wispr-flow/index.d.ts +0 -14
  426. package/dist/providers/wispr-flow/index.js +0 -117
  427. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  428. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -0,0 +1,496 @@
1
+ import { CCB_MEDIA_TYPE, CCB_ENVIRONMENTS, CCB_READ_SCOPES, CCB_WRITE_SCOPES, CCB_SENSITIVE_FIELDS, } from "./lib/constants.js";
2
+ // Pushpay ChMS v2 JSON contracts, OAuth, status meanings, admission and privacy.
3
+ // The legacy per-church XML API is outside this provider's scope.
4
+ import { Effect, Schema } from "effect";
5
+ import { ConnectorCallError } from "../../errors.js";
6
+ import { OperationIndex } from "../_shared/rest/operation-index.js";
7
+ import { checked, indexedVendor } from "../_shared/rest/kit.js";
8
+ import { valueSafety } from "../_shared/rest/value-safety.js";
9
+ import { restSafety } from "../../http/safety.js";
10
+ import { openapi } from "./openapi.generated.js";
11
+ import { CCB_VALUE_SAFETY } from "./safety.js";
12
+ import { CCB_VERDICTS } from "./lib/verdicts.js";
13
+ export { CCB_VERDICTS };
14
+ import { bearer } from "../../http/oauth.js";
15
+ import { get } from "../../http/vendor.js";
16
+ export const authenticate = bearer;
17
+ const SCOPE_SHAPE = /^(read|write|delete):[a-z_]+$/;
18
+ /** CCB's own minimum, which is also the cheapest honest first read. */
19
+ export const DEFAULT_PER_PAGE = 25;
20
+ /**
21
+ * A ceiling on absurdity rather than a budget: at 100 rows per page the
22
+ * fattest documented list (individuals with addresses) stays far below it.
23
+ */
24
+ export const CCB_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
25
+ /**
26
+ * CCB meters the v2 API per endpoint and per API client: one request a second
27
+ * sustained with a burst of 60 (docs.pushpay.io/chms-v2/docs/general). Three
28
+ * endpoints are stricter and allow no burst — `/individuals/{id}` at one a
29
+ * second, `/scheduling/categories/{id}/schedules` at one per two seconds, and
30
+ * `/search/individuals/results` at one per five.
31
+ *
32
+ * What ships is one rolling window of 60 calls per 60 seconds, partitioned by
33
+ * endpoint (method plus path template), which is the documented default
34
+ * transcribed as faithfully as one rule can: it never admits more than the
35
+ * token bucket would in any minute, because a bucket of 60 refilling at one a
36
+ * second can pass up to 120 in a minute and the window passes 60. Partitioning
37
+ * matters — a single connector-wide window would throttle a healthy program
38
+ * that touches ten endpoints to a tenth of what CCB allows.
39
+ *
40
+ * What it cannot express is the three no-burst overrides: this release
41
+ * enforces one rule, and a rule has one budget for every partition. Those are
42
+ * left to CCB's own 429, which carries `retry-after` and maps to a
43
+ * `rate_limited` failure with that wait; the guide says to space those calls.
44
+ * No `maxConcurrency` is declared: per-endpoint concurrency would not keep a
45
+ * fast loop under one a second, and the window already bounds the burst.
46
+ *
47
+ * Per runtime, and per API client only as far as one runtime is the whole
48
+ * client: other deployments, isolates, or integrations using the same client
49
+ * spend from CCB's bucket without spending from this window.
50
+ */
51
+ export const CCB_ADMISSION = {
52
+ rules: [
53
+ {
54
+ budget: { kind: "rolling-window", maxCalls: 60, windowMs: 60_000 },
55
+ partitionKey: ({ toolName, args }) => endpointPartition(toolName, args),
56
+ },
57
+ ],
58
+ };
59
+ function asRecord(value) {
60
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
61
+ }
62
+ function asArray(value) {
63
+ return Array.isArray(value) ? value : [];
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Admission partitions
67
+ // ---------------------------------------------------------------------------
68
+ /** The method and path template each named tool calls. */
69
+ const NAMED_ENDPOINTS = {
70
+ get_me: "GET /me",
71
+ list_individuals: "GET /individuals",
72
+ get_individual: "GET /individuals/{id}",
73
+ list_families: "GET /families",
74
+ get_family: "GET /families/{id}",
75
+ list_groups: "GET /groups",
76
+ get_group: "GET /groups/{id}",
77
+ list_group_members: "GET /groups/{id}/members",
78
+ list_individual_groups: "GET /individuals/{id}/groups",
79
+ list_events: "GET /events",
80
+ get_event: "GET /events/{id}",
81
+ get_event_attendance: "GET /events/{id}/attendance/{occurrence}",
82
+ list_event_attendees: "GET /events/{id}/attendance/{occurrence}/attendees",
83
+ list_individual_notes: "GET /individuals/{id}/notes",
84
+ get_giving_metrics: (args) => args["familyId"] !== undefined ? "GET /families/{id}/metrics/giving" : "GET /individuals/{id}/metrics/giving",
85
+ search_records: (args) => `POST /search/${typeof args["domain"] === "string" ? args["domain"] : "?"}/results`,
86
+ };
87
+ /** `/individuals/123/notes` → `/individuals/{id}/notes`; the key never holds an id. */
88
+ function pathTemplate(path) {
89
+ return path
90
+ .split("/")
91
+ .map((segment) => (/^\d+$/.test(segment) ? "{id}" : segment))
92
+ .join("/");
93
+ }
94
+ const MAX_PARTITION_KEY_CHARS = 120;
95
+ /**
96
+ * The CCB endpoint one call will spend from, as a bounded, id-free key. Runs
97
+ * before argument validation, so it reads arguments defensively and never
98
+ * throws: a malformed hatch path falls into one shared partition and is then
99
+ * refused by the handler.
100
+ */
101
+ function endpointPartition(toolName, raw) {
102
+ const args = asRecord(raw);
103
+ const named = NAMED_ENDPOINTS[toolName];
104
+ let key;
105
+ if (typeof named === "string")
106
+ key = named;
107
+ else if (named)
108
+ key = named(args);
109
+ else {
110
+ const method = toolName === "ccb_api_read"
111
+ ? typeof args["method"] === "string"
112
+ ? args["method"]
113
+ : "GET"
114
+ : typeof args["method"] === "string"
115
+ ? args["method"]
116
+ : "?";
117
+ const path = typeof args["path"] === "string" ? args["path"] : "";
118
+ key = `${method} ${pathTemplate(path)}`;
119
+ }
120
+ // ASCII-only after templating in every realistic case; the slice keeps an
121
+ // absurd path inside the admission controller's 128-byte key limit anyway.
122
+ return [...key]
123
+ .filter((c) => c.charCodeAt(0) < 128)
124
+ .join("")
125
+ .slice(0, MAX_PARTITION_KEY_CHARS);
126
+ }
127
+ export function resolveScopes(options) {
128
+ if (options.scopes !== undefined && options.access !== undefined) {
129
+ throw new Error("ccb() takes access or scopes, not both: scopes is the exact list and replaces access.");
130
+ }
131
+ if (options.scopes === undefined) {
132
+ const access = options.access ?? "read";
133
+ if (access !== "read" && access !== "read-write") {
134
+ throw new Error('ccb() access must be "read" or "read-write".');
135
+ }
136
+ return access === "read" ? CCB_READ_SCOPES : [...CCB_READ_SCOPES, ...CCB_WRITE_SCOPES];
137
+ }
138
+ if (!Array.isArray(options.scopes) || options.scopes.length === 0) {
139
+ throw new Error("ccb() scopes must be a non-empty list.");
140
+ }
141
+ const seen = new Set();
142
+ for (const scope of options.scopes) {
143
+ if (typeof scope !== "string" || !SCOPE_SHAPE.test(scope)) {
144
+ throw new Error(`ccb() scope "${String(scope)}" is not a CCB scope; CCB scopes look like read:individuals.`);
145
+ }
146
+ if (seen.has(scope))
147
+ throw new Error(`ccb() scope "${scope}" is listed twice.`);
148
+ seen.add(scope);
149
+ }
150
+ return [...options.scopes];
151
+ }
152
+ export const SEARCH_DOMAINS = [
153
+ "assignments",
154
+ "categories",
155
+ "department_detail",
156
+ "groups",
157
+ "individual_event_attendance",
158
+ "individual_groups",
159
+ "individuals",
160
+ "organizers",
161
+ "positions",
162
+ "schedules",
163
+ "schedules_totals",
164
+ "scheduling_files",
165
+ "scheduling_individuals",
166
+ "songs",
167
+ "volunteers",
168
+ ];
169
+ const summaries = {
170
+ "GET /individuals": "List people (person profiles, individuals), search names, email and phone",
171
+ "GET /individuals/{id}": "Get a person profile (individual) for identity or update reconciliation",
172
+ "PUT /individuals/{id}": "Update or change a person's email, edit an individual profile, name or change phone number",
173
+ "POST /individuals": "Create or add a person profile, new individual",
174
+ "POST /individuals/{id}/notes": "Add or create a pastoral note for a person (individual)",
175
+ "GET /families": "List households and families",
176
+ "GET /groups/{id}/members": "List church group members and leaders, roster",
177
+ "POST /groups/{id}/members": "Add person to group, create group membership",
178
+ "PUT /groups/{group_id}/members/roles": "Change group role, update member or leader roles",
179
+ "POST /events/{id}/attendance/{occurrence}": "Record attendance, take attendance for an event occurrence",
180
+ "GET /individuals/{id}/metrics/giving": "Get individual giving metrics, donations and contributions counts",
181
+ "GET /families/{id}/metrics/giving": "Get family giving metrics, donations and contributions counts",
182
+ "POST /search/individuals/results": "Search people and individual profiles with advanced configuration and filters",
183
+ "GET /campuses": "List church campuses, timezone and public gift message",
184
+ };
185
+ const details = JSON.parse(openapi.details);
186
+ // These thirteen wildcard-labelled schemas describe twelve JSON objects and
187
+ // one JSON array. Their byte-pinned contracts were reviewed for JSON dispatch.
188
+ const jsonBodies = new Set([
189
+ "POST /forms/{id}/responses",
190
+ "PUT /individuals/{id}/groups/{group_id}",
191
+ "PUT /individuals/{id}/privacy_settings",
192
+ "POST /church/privacy_defaults",
193
+ "PUT /messages/{id}",
194
+ "POST /messages/{id}/comments",
195
+ "PUT /messages/{id}/comments/{comment_id}",
196
+ "POST /scheduling/categories/{id}/notifications",
197
+ "PUT /individuals/{id}/assignments",
198
+ "PUT /scheduling/families/{id}/assignments",
199
+ "PUT /individuals/{id}/groups/bulk",
200
+ "POST /search/save",
201
+ "PUT /search/save/{id}",
202
+ ]);
203
+ for (const [i, row] of details.o.entries()) {
204
+ const op = openapi.ops[i];
205
+ if (jsonBodies.has(`${op[0]} ${op[1]}`)) {
206
+ if (!row || !row[1] || row[1][0] !== "*/*")
207
+ throw new Error("CCB JSON request review is stale.");
208
+ row[1][0] = "application/json";
209
+ }
210
+ }
211
+ for (const row of details.o) {
212
+ if (row)
213
+ for (const parameter of row[0])
214
+ if (!parameter[4])
215
+ parameter[4] =
216
+ {
217
+ id: "Record id from a prior read; resolve the target before acting.",
218
+ page: "Vendor page number restored from the signed continuation.",
219
+ per_page: "Page size: 25, 50, 75 or 100; defaults to 25.",
220
+ name: "Partial name search.",
221
+ }[parameter[0]] ?? `${parameter[0].replaceAll("_", " ")} ${parameter[1]} parameter from the vendor contract.`;
222
+ }
223
+ export const CCB_INDEX = new OperationIndex({
224
+ ...openapi,
225
+ details: JSON.stringify(details),
226
+ // The public campus directory is church setup; retain both resource
227
+ // words so conversational searches distinguish it from campus subresources.
228
+ tags: [...openapi.tags, "church campuses"],
229
+ ops: openapi.ops.map((row) => {
230
+ const summary = summaries[`${row[0]} ${row[1]}`];
231
+ const label = summary ? `${summary}; ${row[3]}` : row[3];
232
+ const tag = row[0] === "GET" && row[1] === "/campuses" ? openapi.tags.length : row[4];
233
+ return row[5] === undefined
234
+ ? [row[0], row[1], row[2], label, tag]
235
+ : [row[0], row[1], row[2], label, tag, row[5]];
236
+ }),
237
+ }, { vendor: "ccb", title: "CCB" });
238
+ export const getMe = get("getMe", "/me", { success: Schema.Unknown });
239
+ export const CcbApi = indexedVendor("CCB", CCB_INDEX, [getMe]);
240
+ const safety = valueSafety(CCB_VALUE_SAFETY, () => CCB_INDEX);
241
+ export const CCB_PAGE_HEADERS = ["x-page", "x-next-page", "x-total-pages", "x-total"];
242
+ export function ccbPageInfo(headers, page, size, rows) {
243
+ const number = (name) => {
244
+ const raw = headers[name];
245
+ if (raw === undefined || raw === "")
246
+ return undefined;
247
+ if (!/^(0|[1-9]\d*)$/.test(raw) || !Number.isSafeInteger(Number(raw)))
248
+ throw new ConnectorCallError("connector_call_failed", "CCB returned invalid paging metadata.", {
249
+ retryable: false,
250
+ });
251
+ return Number(raw);
252
+ };
253
+ const current = number("x-page") ?? page;
254
+ if (current !== page)
255
+ throw new ConnectorCallError("connector_call_failed", "CCB returned a different page than requested.", {
256
+ retryable: false,
257
+ });
258
+ let next;
259
+ if (Object.hasOwn(headers, "x-next-page"))
260
+ next = number("x-next-page") ?? null;
261
+ else {
262
+ const pages = number("x-total-pages");
263
+ next = pages === undefined ? (rows >= size ? page + 1 : null) : page < pages ? page + 1 : null;
264
+ }
265
+ if (next !== null && (!rows || next <= page))
266
+ throw new ConnectorCallError("connector_call_failed", "CCB returned a nonadvancing or empty continuing page.", {
267
+ retryable: false,
268
+ });
269
+ return next;
270
+ }
271
+ const pageAdapter = {
272
+ param: "page",
273
+ in: "query",
274
+ headers: CCB_PAGE_HEADERS,
275
+ decode: (cursor) => {
276
+ const value = Number(cursor);
277
+ if (!/^[1-9]\d*$/.test(String(cursor)) || !Number.isSafeInteger(value))
278
+ throw new ConnectorCallError("invalid_args", "This CCB cursor contains no valid page number.");
279
+ return value;
280
+ },
281
+ next: (data, call) => {
282
+ const rows = Array.isArray(data)
283
+ ? data
284
+ : Array.isArray(asRecord(data)["items"])
285
+ ? asRecord(data)["items"]
286
+ : undefined;
287
+ if (!rows && !Object.hasOwn(call.headers, "x-next-page") && !Object.hasOwn(call.headers, "x-total-pages"))
288
+ return undefined;
289
+ return ccbPageInfo(call.headers, Number(call.query["page"] ?? 1), Number(call.query["per_page"] ?? 25), rows?.length ?? 1);
290
+ },
291
+ };
292
+ export const CCB_PAGES = Object.fromEntries(CCB_INDEX.ops
293
+ .filter((op) => CCB_VERDICTS[`${op.method} ${op.path}`] === "read" &&
294
+ op.path !== "/search/schedules_totals/results" &&
295
+ CCB_INDEX.contract(op).parameters.some((p) => p.in === "query" && p.name === "page"))
296
+ .map((op) => [`${op.method} ${op.path}`, pageAdapter]));
297
+ export const CCB_NAMED = {
298
+ "GET /me": "get_me",
299
+ "GET /individuals": "list_individuals",
300
+ "GET /individuals/{id}": "get_individual",
301
+ "GET /families": "list_families",
302
+ "GET /families/{id}": "get_family",
303
+ "GET /groups": "list_groups",
304
+ "GET /groups/{id}": "get_group",
305
+ "GET /groups/{id}/members": "list_group_members",
306
+ "GET /individuals/{id}/groups": "list_individual_groups",
307
+ "GET /events": "list_events",
308
+ "GET /events/{id}": "get_event",
309
+ "GET /events/{id}/attendance/{occurrence}": "get_event_attendance",
310
+ "GET /events/{id}/attendance/{occurrence}/attendees": "list_event_attendees",
311
+ "GET /individuals/{id}/notes": "list_individual_notes",
312
+ "GET /individuals/{id}/metrics/giving": "get_giving_metrics",
313
+ "GET /families/{id}/metrics/giving": "get_giving_metrics",
314
+ ...Object.fromEntries(SEARCH_DOMAINS.map((domain) => [`POST /search/${domain}/results`, "search_records"])),
315
+ };
316
+ function pathProblem(path) {
317
+ return !path.startsWith("/") ||
318
+ path.startsWith("//") ||
319
+ /[%;\\?#]/.test(path) ||
320
+ path.split("/").some((p) => p === "." || p === "..") ||
321
+ /^\/oauth(?:\/|$)/i.test(path)
322
+ ? "CCB paths must be canonical indexed API paths; OAuth and encoded or traversal paths are refused."
323
+ : undefined;
324
+ }
325
+ function bodyRefusal(op) {
326
+ const content = CCB_INDEX.bodyType(op);
327
+ return content && !/^application\/(?:[^/]+\+)?json$/.test(content)
328
+ ? `CCB's JSON hatch cannot send ${content} request bodies; use the vendor application for this operation.`
329
+ : undefined;
330
+ }
331
+ export const ccbBinding = ({ connection, options, }) => ({
332
+ review: "CCB v2 uses JSON bodies, repeated form-array query parameters and deep-object bracket keys on its fixed environment origin. The index, safety and OAuth grant own admission and dispatch.",
333
+ refusal: (op) => safety.refusal(op.method, op.path) ?? bodyRefusal(op),
334
+ refuse: (call) => {
335
+ const denied = safety.refusal(call.method, call.op.path);
336
+ if (denied)
337
+ return denied;
338
+ const path = pathProblem(call.path);
339
+ if (path)
340
+ return path;
341
+ if (CCB_VERDICTS[`${call.method} ${call.op.path}`] !== "read" &&
342
+ !resolveScopes(options).some((scope) => !scope.startsWith("read:")))
343
+ return "This CCB connection has only read scopes; writes are refused.";
344
+ const size = call.query["per_page"];
345
+ if (size !== undefined && !/^(25|50|75|100)$/.test(String(size)))
346
+ return "CCB per_page must be one of 25, 50, 75, 100.";
347
+ const page = call.query["page"];
348
+ if (page !== undefined && (!/^[1-9]\d*$/.test(String(page)) || !Number.isSafeInteger(Number(page))))
349
+ return "CCB page must be a positive whole number.";
350
+ return bodyRefusal(call.op);
351
+ },
352
+ send: (call, settings) => connection.sendPath({
353
+ method: call.method,
354
+ path: call.path,
355
+ template: call.op.path,
356
+ query: queryPairs(call.query),
357
+ ...(call.body === undefined ? {} : { json: JSON.stringify(call.body) }),
358
+ }, settings),
359
+ });
360
+ function queryPairs(query) {
361
+ const out = [];
362
+ const add = (name, value) => {
363
+ if (Array.isArray(value))
364
+ for (const item of value)
365
+ add(name, item);
366
+ else if (value !== null && typeof value === "object")
367
+ for (const [key, item] of Object.entries(value))
368
+ add(`${name}[${key}]`, item);
369
+ else if (value !== undefined)
370
+ out.push([name, String(value ?? "")]);
371
+ };
372
+ for (const [name, value] of Object.entries(query))
373
+ add(name, value);
374
+ return out;
375
+ }
376
+ /** Uniform v2 privacy review, including the legacy hatches' unindexed paths. */
377
+ export function ccbSafety(options) {
378
+ return {
379
+ reviewed: restSafety(safety, CCB_INDEX),
380
+ sensitiveFields: { names: CCB_SENSITIVE_FIELDS, choice: options.sensitiveFields ?? "drop" },
381
+ };
382
+ }
383
+ export function callCcb(connection, request) {
384
+ return Effect.gen(function* () {
385
+ const query = Object.fromEntries(Object.entries(request.query ?? {}).filter(([, value]) => value !== undefined));
386
+ const op = yield* checked(() => {
387
+ const problem = pathProblem(request.path);
388
+ if (problem)
389
+ throw new ConnectorCallError("invalid_args", problem);
390
+ const { op } = CCB_INDEX.resolve(request.method, request.path);
391
+ CCB_INDEX.check(op, query, request.body);
392
+ return op;
393
+ });
394
+ const answer = yield* connection.sendPath({
395
+ method: request.method,
396
+ path: request.path,
397
+ template: op.path,
398
+ query: queryPairs(query),
399
+ ...(request.body === undefined ? {} : { json: JSON.stringify(request.body) }),
400
+ }, { responseHeaders: CCB_PAGE_HEADERS });
401
+ return { body: answer.data, headers: new Headers(answer.headers) };
402
+ });
403
+ }
404
+ export function oauth(options) {
405
+ const endpoints = CCB_ENVIRONMENTS[options.environment];
406
+ return {
407
+ authorizationEndpoint: endpoints.authorizationEndpoint,
408
+ tokenEndpoint: `${endpoints.apiOrigin}/oauth/token`,
409
+ clientId: options.clientId,
410
+ clientSecret: options.clientSecret,
411
+ scope: resolveScopes(options).join(" "),
412
+ authorizationParams: {
413
+ ...(options.mode === "identity" ? { resource_owner_auth: "true" } : {}),
414
+ ...(options.subdomain?.trim() ? { subdomain: options.subdomain.trim() } : {}),
415
+ },
416
+ tokenRequestHeaders: { Accept: CCB_MEDIA_TYPE },
417
+ apiOrigins: [endpoints.apiOrigin],
418
+ };
419
+ }
420
+ function errorDetail(payload, status) {
421
+ const root = asRecord(payload);
422
+ const parts = [];
423
+ for (const key of ["message", "error_description", "error"]) {
424
+ const value = root[key];
425
+ if (typeof value === "string" && value.trim()) {
426
+ parts.push(value.trim());
427
+ break;
428
+ }
429
+ }
430
+ for (const item of asArray(root["errors"]).slice(0, 5)) {
431
+ if (typeof item === "string" && item.trim())
432
+ parts.push(item.trim());
433
+ else {
434
+ const message = asRecord(item)["message"];
435
+ if (typeof message === "string" && message.trim())
436
+ parts.push(message.trim());
437
+ }
438
+ }
439
+ const detail = parts.join("; ").slice(0, 500);
440
+ return detail ? `CCB HTTP ${status}: ${detail}${/[.!?]$/.test(detail) ? "" : "."}` : `CCB returned HTTP ${status}.`;
441
+ }
442
+ export const errors = {
443
+ meanings: { unknownId: "not_found", provesAbsence: true, conflicts: [] },
444
+ bodyFailures: {
445
+ statusOnly: [],
446
+ review: "An incomplete response body does not establish malformed JSON. Preserve CCB OAuth and write settlement semantics.",
447
+ readFailed: "CCB's response body could not be read completely.",
448
+ },
449
+ numericFacts: {
450
+ retryAfterMs: {
451
+ header: "retry-after",
452
+ format: "retry-after",
453
+ review: "HTTP Retry-After delay for failure recovery.",
454
+ },
455
+ resetAfterMs: {
456
+ header: "x-ratelimit-reset",
457
+ format: "epoch-seconds",
458
+ review: "CCB endpoint rate-limit reset time in epoch seconds.",
459
+ },
460
+ bodyRetryAfterMs: {
461
+ path: ["retry_after"],
462
+ format: "seconds",
463
+ review: "CCB rate-limit response body delay in seconds.",
464
+ },
465
+ },
466
+ provider: "CCB",
467
+ facts: () => ({}),
468
+ detail: ({ body, status }) => errorDetail(body, status),
469
+ unreadable: "CCB returned a successful response that is not JSON.",
470
+ statuses: {
471
+ 401: () => ({
472
+ code: "auth_required",
473
+ words: (detail) => `${detail} CCB rejected the connection's access token. Call authorize_connector for this connector.`,
474
+ advice: ", then retry",
475
+ }),
476
+ 403: () => ({
477
+ code: "provider_permission_denied",
478
+ retryable: false,
479
+ words: (detail) => `${detail} The grant lacks this endpoint's scope, or (Identity Auth) the signed-in person lacks the permission in CCB. Ask the CCB administrator to grant this endpoint's scope or the signed-in person's permission. Re-authorizing alone will not fix it.`,
480
+ }),
481
+ 404: () => ({
482
+ code: "not_found",
483
+ words: (detail) => `${detail} Re-read the id from its list tool; CCB reports a permission gap as 403, so this record does not exist.`,
484
+ }),
485
+ 412: () => ({ code: "invalid_args" }),
486
+ 429: ({ retryAfterMs, numbers }) => {
487
+ const wait = retryAfterMs ?? numbers["resetAfterMs"] ?? numbers["bodyRetryAfterMs"];
488
+ return {
489
+ code: "rate_limited",
490
+ retryAfterMs: wait,
491
+ words: (detail) => `${detail} CCB limits each endpoint per API client.`,
492
+ advice: "; wait before calling this endpoint again",
493
+ };
494
+ },
495
+ },
496
+ };
@@ -1,37 +1,6 @@
1
+ import { CCB_ENVIRONMENTS } from "./lib/constants.js";
1
2
  import type { ConnectorCallAdmissionPolicy } from "../../types.js";
2
- /** CCB's v2 media type. The API and its token endpoint both require it. */
3
- export declare const CCB_MEDIA_TYPE = "application/vnd.ccbchurch.v2+json";
4
- /**
5
- * The two published environments. Credentials do not cross: sandbox clients
6
- * work only against the sandbox hosts and production clients only against
7
- * production, so the environment is part of the client, not a preference.
8
- */
9
- export declare const CCB_ENVIRONMENTS: {
10
- readonly production: {
11
- readonly apiOrigin: "https://api.ccbchurch.com";
12
- readonly authorizationEndpoint: "https://oauth.ccbchurch.com/oauth/authorize";
13
- };
14
- readonly sandbox: {
15
- readonly apiOrigin: "https://api-beta.ccbchurch.com";
16
- readonly authorizationEndpoint: "https://beta-oauth.ccbchurch.com/oauth/authorize";
17
- };
18
- };
19
- /**
20
- * The read scopes the named tools and the search hatch need, from the
21
- * `security` requirements of the operations they call (spec revision recorded
22
- * in the drift manifest). `read:campuses` and `read:church` are there so the
23
- * ids every projection carries — campus, membership type — can be resolved
24
- * through `ccb_api_get`. Request these on Pushpay's API access form.
25
- */
26
- export declare const CCB_READ_SCOPES: readonly string[];
27
- /**
28
- * What `access: "read-write"` adds: the writes of the everyday staff jobs —
29
- * profiles, groups, events and attendance, form responses, notes, process
30
- * queues, scheduling. No `delete:` scope, nothing financial, no background
31
- * checks, and no privacy settings: those are deliberate, so they are only
32
- * ever requested through an explicit `scopes` list.
33
- */
34
- export declare const CCB_WRITE_SCOPES: readonly string[];
3
+ export { CCB_ENVIRONMENTS, CCB_MEDIA_TYPE, CCB_READ_SCOPES, CCB_WRITE_SCOPES, CCB_SENSITIVE_FIELDS, } from "./lib/constants.js";
35
4
  /** How the grant acts: for the whole church, or as one signed-in person. */
36
5
  export type CcbMode = "system" | "identity";
37
6
  /** Which Pushpay environment the client was issued for. */
@@ -73,15 +42,15 @@ export interface CcbOptions {
73
42
  clientSecret: string;
74
43
  /**
75
44
  * `"read"` (default) requests {@link CCB_READ_SCOPES} and ships no write
76
- * tool; `"read-write"` adds {@link CCB_WRITE_SCOPES} and the approval-gated
77
- * `ccb_api_mutate`. Exclusive with `scopes`.
45
+ * tool; `"read-write"` adds {@link CCB_WRITE_SCOPES} and `ccb_api_write`.
46
+ * The host may ask the user to confirm a write. Exclusive with `scopes`.
78
47
  */
79
48
  access?: "read" | "read-write";
80
49
  /**
81
50
  * The exact scope list to request, replacing `access`: narrower (drop
82
51
  * `read:individual_notes`) or wider (add `read:background_checks` for the
83
52
  * hatch). Must be a subset of what Pushpay granted the client. Any `write:`
84
- * or `delete:` scope ships `ccb_api_mutate`.
53
+ * or `delete:` scope ships `ccb_api_write`.
85
54
  */
86
55
  scopes?: readonly string[];
87
56
  /**
@@ -98,6 +67,17 @@ export interface CcbOptions {
98
67
  callAdmission?: ConnectorCallAdmissionPolicy;
99
68
  /** Connector-specific inline result limit; omit to inherit the deployment. */
100
69
  maxResultBytes?: number;
70
+ /** Serve only read-classified tools on every endpoint. Defaults to false. */
71
+ readOnly?: boolean;
72
+ /**
73
+ * Whether results may carry {@link CCB_SENSITIVE_FIELDS}: allergies,
74
+ * giving numbers and dates, envelope ids, statement dates, attendance
75
+ * prayer requests and meeting notes, and form payment details. `"drop"`
76
+ * (default) removes them wherever they appear in every result: the named
77
+ * tools, the named reads, `search_records`, `ccb_api_read`, and `ccb_api_write`
78
+ * replies. `"return"` lets the hatches return those allowed fields; named projections stay narrow. Credentials and private file destinations are always withheld. Only deployment code decides; no tool argument can.
79
+ */
80
+ sensitiveFields?: "drop" | "return";
101
81
  }
102
- /** A maintained Church Community Builder (Pushpay ChMS) v2 connection. */
82
+ /** A maintained Church Community Builder (Pushpay ChMS) v2 connection on the provider kit. */
103
83
  export declare const ccb: import("../../provider.js").ProviderFactory<CcbOptions>;