@zackbart/connecta 0.34.1 → 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 (429) hide show
  1. package/CHANGELOG.md +363 -0
  2. package/README.md +62 -106
  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 +12 -7
  53. package/dist/connectors/api-connector.js +142 -56
  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/remote-mcp.d.ts +10 -30
  58. package/dist/connectors/remote-mcp.js +955 -563
  59. package/dist/d1.js +10 -243
  60. package/dist/derived-context.js +5 -0
  61. package/dist/describe-config.d.ts +3 -1
  62. package/dist/describe-config.js +2 -0
  63. package/dist/downstream-input.js +347 -260
  64. package/dist/errors.d.ts +87 -6
  65. package/dist/errors.js +114 -4
  66. package/dist/execute.js +87 -50
  67. package/dist/executor-admission.js +3 -0
  68. package/dist/executors/quickjs.js +163 -112
  69. package/dist/guarded-transport.js +50 -0
  70. package/dist/guest-runtime.js +1 -1
  71. package/dist/http/client.js +439 -0
  72. package/dist/http/errors.js +558 -0
  73. package/dist/http/fields.js +49 -0
  74. package/dist/http/hatch-paging.js +318 -0
  75. package/dist/http/hatch.js +1279 -0
  76. package/dist/http/json-schema.js +267 -0
  77. package/dist/http/node-transport.js +241 -0
  78. package/dist/http/oauth.js +162 -0
  79. package/dist/http/paging.js +228 -0
  80. package/dist/http/provider.js +221 -0
  81. package/dist/http/safety.js +82 -0
  82. package/dist/http/services.js +79 -0
  83. package/dist/http/tools.js +383 -0
  84. package/dist/http/vendor-index.js +138 -0
  85. package/dist/http/vendor.js +448 -0
  86. package/dist/http/write-request.js +66 -0
  87. package/dist/http-policy.d.ts +11 -0
  88. package/dist/http-policy.js +45 -0
  89. package/dist/inbound-credential.js +1 -1
  90. package/dist/index.d.ts +2 -2
  91. package/dist/index.js +4 -0
  92. package/dist/invocation-auth.js +30 -19
  93. package/dist/invocation.js +218 -85
  94. package/dist/mcp-result.js +0 -4
  95. package/dist/membership.d.ts +4 -0
  96. package/dist/meta-output.js +1 -1
  97. package/dist/meta-tools.js +531 -406
  98. package/dist/native-recovery.js +52 -0
  99. package/dist/native-tools.js +382 -0
  100. package/dist/node.d.ts +4 -3
  101. package/dist/node.js +45 -8
  102. package/dist/oauth-handoff.js +177 -104
  103. package/dist/oauth-partition.js +6 -20
  104. package/dist/oauth-sealing.js +6 -7
  105. package/dist/operation-vocabulary.js +101 -0
  106. package/dist/operator-record.d.ts +2 -2
  107. package/dist/operator-record.js +17 -4
  108. package/dist/operator-ui/agents.d.ts +5 -4
  109. package/dist/operator-ui/agents.js +17 -7
  110. package/dist/operator-ui/config-summary.js +5 -4
  111. package/dist/operator-ui/connection-map.js +7 -5
  112. package/dist/operator-ui/contract.d.ts +7 -3
  113. package/dist/operator-ui/endpoints.js +4 -13
  114. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  115. package/dist/operator-ui/fix-prompts.js +0 -8
  116. package/dist/operator-ui/generated.js +3 -3
  117. package/dist/operator-ui/model.d.ts +2 -3
  118. package/dist/operator-ui/overview.js +5 -2
  119. package/dist/operator-ui/setup-commands.js +0 -4
  120. package/dist/operator-ui/view.d.ts +2 -25
  121. package/dist/operator-ui/view.js +2 -76
  122. package/dist/program-writes.js +47 -26
  123. package/dist/provider-call-facts.d.ts +115 -0
  124. package/dist/provider-call-facts.js +182 -0
  125. package/dist/provider-call.d.ts +112 -0
  126. package/dist/provider-call.js +271 -0
  127. package/dist/provider.d.ts +65 -31
  128. package/dist/provider.js +116 -39
  129. package/dist/providers/_shared/google/hatch.js +91 -0
  130. package/dist/providers/_shared/google/kit.js +537 -0
  131. package/dist/providers/_shared/google/result-size.js +15 -2
  132. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  133. package/dist/providers/_shared/google/service-account.js +8 -4
  134. package/dist/providers/_shared/google/workspace.d.ts +6 -210
  135. package/dist/providers/_shared/google/workspace.js +6 -425
  136. package/dist/providers/_shared/rest/compact-index.js +86 -0
  137. package/dist/providers/_shared/rest/dispatch.js +3 -23
  138. package/dist/providers/_shared/rest/kit.js +546 -0
  139. package/dist/providers/_shared/rest/operation-index.js +230 -14
  140. package/dist/providers/_shared/rest/response-media.js +11 -0
  141. package/dist/providers/_shared/rest/tools.js +101 -78
  142. package/dist/providers/_shared/rest/value-safety.js +353 -195
  143. package/dist/providers/_shared/sensitive-fields.js +27 -0
  144. package/dist/providers/breeze/api.js +584 -0
  145. package/dist/providers/breeze/index.d.ts +1 -3
  146. package/dist/providers/breeze/index.js +67 -1420
  147. package/dist/providers/breeze/openapi.generated.js +60 -0
  148. package/dist/providers/breeze/skill.generated.js +2 -6
  149. package/dist/providers/breeze/tools.js +696 -0
  150. package/dist/providers/ccb/api.js +496 -0
  151. package/dist/providers/ccb/index.d.ts +15 -37
  152. package/dist/providers/ccb/index.js +77 -1702
  153. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  154. package/dist/providers/ccb/lib/constants.js +74 -0
  155. package/dist/providers/ccb/lib/guide.js +9 -0
  156. package/dist/providers/ccb/lib/verdicts.js +387 -0
  157. package/dist/providers/ccb/openapi.generated.js +397 -0
  158. package/dist/providers/ccb/safety.js +295 -0
  159. package/dist/providers/ccb/skill.generated.js +2 -6
  160. package/dist/providers/ccb/tools.js +853 -0
  161. package/dist/providers/cloudflare/api.js +1066 -0
  162. package/dist/providers/cloudflare/index.d.ts +5 -22
  163. package/dist/providers/cloudflare/index.js +79 -197
  164. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  165. package/dist/providers/cloudflare/lib/config.js +2 -0
  166. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  167. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  168. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  169. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  170. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  171. package/dist/providers/cloudflare/openapi.generated.js +4 -3
  172. package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
  173. package/dist/providers/cloudflare/skill.generated.js +2 -10
  174. package/dist/providers/cloudflare/tools.js +360 -0
  175. package/dist/providers/docs/api.js +51 -0
  176. package/dist/providers/docs/index.d.ts +1 -12
  177. package/dist/providers/docs/index.js +53 -1165
  178. package/dist/providers/docs/lib/constants.d.ts +18 -0
  179. package/dist/providers/docs/lib/constants.js +18 -0
  180. package/dist/providers/docs/lib/discovery.js +26 -0
  181. package/dist/providers/docs/lib/requests.js +48 -0
  182. package/dist/providers/docs/lib/schemas.js +168 -0
  183. package/dist/providers/docs/openapi.generated.js +16 -0
  184. package/dist/providers/docs/safety.js +54 -0
  185. package/dist/providers/docs/skill.generated.js +2 -6
  186. package/dist/providers/docs/tools.js +802 -0
  187. package/dist/providers/drive/api.js +177 -0
  188. package/dist/providers/drive/index.d.ts +1 -12
  189. package/dist/providers/drive/index.js +38 -1448
  190. package/dist/providers/drive/lib/constants.d.ts +6 -0
  191. package/dist/providers/drive/lib/constants.js +6 -0
  192. package/dist/providers/drive/lib/contracts.js +532 -0
  193. package/dist/providers/drive/lib/hatch.js +197 -0
  194. package/dist/providers/drive/openapi.generated.js +77 -0
  195. package/dist/providers/drive/safety.js +90 -0
  196. package/dist/providers/drive/skill.generated.js +2 -6
  197. package/dist/providers/drive/tools.js +1290 -0
  198. package/dist/providers/forms/api.js +71 -0
  199. package/dist/providers/forms/index.d.ts +1 -12
  200. package/dist/providers/forms/index.js +49 -1145
  201. package/dist/providers/forms/lib/constants.d.ts +14 -0
  202. package/dist/providers/forms/lib/constants.js +19 -0
  203. package/dist/providers/forms/lib/hatch.js +72 -0
  204. package/dist/providers/forms/openapi.generated.js +23 -0
  205. package/dist/providers/forms/safety.js +34 -0
  206. package/dist/providers/forms/skill.generated.js +2 -8
  207. package/dist/providers/forms/tools.js +1024 -0
  208. package/dist/providers/github/api.js +150 -0
  209. package/dist/providers/github/index.d.ts +4 -5
  210. package/dist/providers/github/index.js +30 -87
  211. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  212. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  213. package/dist/providers/github/lib/discovery.js +132 -0
  214. package/dist/providers/github/lib/operations.js +58 -0
  215. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  216. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  217. package/dist/providers/github/openapi.generated.js +1216 -0
  218. package/dist/providers/github/safety.js +216 -0
  219. package/dist/providers/github/skill.generated.js +2 -5
  220. package/dist/providers/github/tools.js +506 -0
  221. package/dist/providers/gmail/api.js +114 -0
  222. package/dist/providers/gmail/index.d.ts +1 -12
  223. package/dist/providers/gmail/index.js +73 -1621
  224. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  225. package/dist/providers/gmail/lib/constants.js +16 -0
  226. package/dist/providers/gmail/lib/index.js +173 -0
  227. package/dist/providers/gmail/lib/schemas.js +176 -0
  228. package/dist/providers/gmail/lib/threading.js +120 -0
  229. package/dist/providers/gmail/openapi.generated.js +92 -0
  230. package/dist/providers/gmail/safety.js +21 -0
  231. package/dist/providers/gmail/skill.generated.js +2 -6
  232. package/dist/providers/gmail/tools.js +1435 -0
  233. package/dist/providers/overflow/api.js +1008 -0
  234. package/dist/providers/overflow/index.d.ts +1 -17
  235. package/dist/providers/overflow/index.js +60 -1488
  236. package/dist/providers/overflow/skill.generated.js +2 -5
  237. package/dist/providers/overflow/tools.js +873 -0
  238. package/dist/providers/planning-center/api.js +467 -0
  239. package/dist/providers/planning-center/index.d.ts +4 -35
  240. package/dist/providers/planning-center/index.js +69 -2445
  241. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  242. package/dist/providers/planning-center/lib/constants.js +83 -0
  243. package/dist/providers/planning-center/lib/discovery.js +40 -0
  244. package/dist/providers/planning-center/lib/guide.js +39 -0
  245. package/dist/providers/planning-center/lib/json-api.js +83 -0
  246. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  247. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  248. package/dist/providers/planning-center/safety.js +188 -0
  249. package/dist/providers/planning-center/skill.generated.js +2 -27
  250. package/dist/providers/planning-center/tools.js +1010 -0
  251. package/dist/providers/sheets/api.js +133 -0
  252. package/dist/providers/sheets/index.d.ts +4 -16
  253. package/dist/providers/sheets/index.js +61 -1172
  254. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  255. package/dist/providers/sheets/lib/constants.js +14 -0
  256. package/dist/providers/sheets/lib/hatch.js +163 -0
  257. package/dist/providers/sheets/lib/requests.js +105 -0
  258. package/dist/providers/sheets/lib/schemas.js +138 -0
  259. package/dist/providers/sheets/openapi.generated.js +30 -0
  260. package/dist/providers/sheets/safety.js +27 -0
  261. package/dist/providers/sheets/skill.generated.js +2 -7
  262. package/dist/providers/sheets/tools.js +734 -0
  263. package/dist/providers/slides/api.js +147 -0
  264. package/dist/providers/slides/index.d.ts +2 -10
  265. package/dist/providers/slides/index.js +48 -2555
  266. package/dist/providers/slides/lib/constants.d.ts +11 -0
  267. package/dist/providers/slides/lib/constants.js +11 -0
  268. package/dist/providers/slides/lib/requests.js +60 -0
  269. package/dist/providers/slides/lib/schemas.js +565 -0
  270. package/dist/providers/slides/openapi.generated.js +18 -0
  271. package/dist/providers/slides/skill.generated.js +2 -6
  272. package/dist/providers/slides/tools.js +1968 -0
  273. package/dist/providers/stripe/api.js +401 -0
  274. package/dist/providers/stripe/index.d.ts +5 -27
  275. package/dist/providers/stripe/index.js +74 -210
  276. package/dist/providers/stripe/lib/config.d.ts +4 -0
  277. package/dist/providers/stripe/lib/config.js +2 -0
  278. package/dist/providers/stripe/openapi.generated.js +4 -3
  279. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  280. package/dist/providers/stripe/skill.generated.js +2 -11
  281. package/dist/providers/stripe/tools.js +77 -0
  282. package/dist/providers/tithely/api.js +531 -0
  283. package/dist/providers/tithely/index.d.ts +17 -0
  284. package/dist/providers/tithely/index.js +86 -965
  285. package/dist/providers/tithely/skill.generated.js +2 -5
  286. package/dist/providers/tithely/tools.js +426 -0
  287. package/dist/providers/vercel/api.js +551 -0
  288. package/dist/providers/vercel/index.d.ts +9 -25
  289. package/dist/providers/vercel/index.js +66 -260
  290. package/dist/providers/vercel/lib/config.d.ts +2 -0
  291. package/dist/providers/vercel/lib/config.js +2 -0
  292. package/dist/providers/vercel/lib/index.js +117 -0
  293. package/dist/providers/vercel/lib/logs.js +100 -0
  294. package/dist/providers/vercel/lib/pin.js +270 -0
  295. package/dist/providers/vercel/openapi.generated.js +10 -5
  296. package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
  297. package/dist/providers/vercel/skill.generated.js +2 -7
  298. package/dist/providers/vercel/tools.js +642 -0
  299. package/dist/redaction-identity.js +47 -0
  300. package/dist/redaction-marker.js +125 -0
  301. package/dist/registry.d.ts +21 -15
  302. package/dist/registry.js +409 -376
  303. package/dist/routes/access-tokens.js +1 -1
  304. package/dist/routes/actor-labels.js +1 -1
  305. package/dist/routes/connect.js +1 -1
  306. package/dist/routes/dispatch.js +103 -0
  307. package/dist/routes/mcp.js +170 -79
  308. package/dist/routes/oauth.js +3 -1
  309. package/dist/routes/operator.js +2 -2
  310. package/dist/routes/shared.d.ts +5 -4
  311. package/dist/routes/shared.js +244 -177
  312. package/dist/routes/skills.js +10 -8
  313. package/dist/routes/ui-config.js +27 -3
  314. package/dist/routes/ui-data.js +21 -20
  315. package/dist/routes/ui.js +1 -1
  316. package/dist/runtime/call-admission.js +0 -26
  317. package/dist/runtime/call-entry.js +30 -0
  318. package/dist/runtime/call.js +556 -0
  319. package/dist/runtime/connector-scope.js +7 -0
  320. package/dist/runtime/credential-probe.js +34 -0
  321. package/dist/runtime/executor.js +40 -0
  322. package/dist/runtime/native-storage.js +63 -0
  323. package/dist/runtime/registry.js +27 -0
  324. package/dist/runtime/request-scope.js +72 -0
  325. package/dist/runtime/run.js +15 -7
  326. package/dist/runtime/shared-read.js +34 -5
  327. package/dist/runtime/storage.js +34 -21
  328. package/dist/sent-secrets.d.ts +194 -37
  329. package/dist/sent-secrets.js +1743 -340
  330. package/dist/server.js +5 -56
  331. package/dist/skills.js +322 -222
  332. package/dist/sqlite.js +15 -14
  333. package/dist/storage/d1-copy.js +255 -0
  334. package/dist/storage/d1-driver.js +15 -0
  335. package/dist/storage/keys.js +28 -0
  336. package/dist/storage/sql-driver.js +88 -0
  337. package/dist/storage/sql-native.js +544 -0
  338. package/dist/storage/sql-schema.d.ts +6 -0
  339. package/dist/storage/sql-schema.js +15 -0
  340. package/dist/storage/sql.d.ts +14 -20
  341. package/dist/storage/sql.js +29 -535
  342. package/dist/timeout.js +0 -26
  343. package/dist/tool-safety.js +20 -10
  344. package/dist/types.d.ts +7 -109
  345. package/dist/upward.js +3 -0
  346. package/dist/usage-guide.js +3 -1
  347. package/dist/validate.d.ts +4 -2
  348. package/dist/validate.js +86 -9
  349. package/dist/version.d.ts +1 -1
  350. package/dist/version.js +1 -1
  351. package/dist/worker.js +312 -292
  352. package/dist/workspace-subject.js +5 -1
  353. package/dist/write-outcome.js +454 -34
  354. package/documentation/README.md +27 -7
  355. package/documentation/architecture.md +2547 -226
  356. package/documentation/auth.md +821 -98
  357. package/documentation/code-mode.md +49 -16
  358. package/documentation/deploying.md +164 -20
  359. package/documentation/hosted-mcp-migration.md +460 -0
  360. package/documentation/integrating.md +129 -144
  361. package/documentation/meta-tools.md +409 -32
  362. package/documentation/operating.md +27 -3
  363. package/documentation/operator-tests.md +3 -0
  364. package/documentation/operator-ui.md +68 -45
  365. package/documentation/provider-auth-migration.md +16 -63
  366. package/documentation/provider-migration-0.29.md +10 -5
  367. package/documentation/provider-migration-0.35.md +975 -0
  368. package/documentation/providers.md +965 -0
  369. package/examples/worker/AGENTS.md +23 -9
  370. package/examples/worker/README.md +254 -135
  371. package/examples/worker/alchemy.run.ts +116 -0
  372. package/examples/worker/gitignore +10 -0
  373. package/examples/worker/src/connecta.config.ts +23 -21
  374. package/examples/worker/wrangler.jsonc +14 -5
  375. package/guides/connecting-agents.md +157 -0
  376. package/guides/how-it-works.md +156 -0
  377. package/guides/safety-and-trust.md +153 -0
  378. package/package.json +27 -46
  379. package/templates/node/.env.example +3 -0
  380. package/templates/node/README.md +22 -2
  381. package/templates/node/docker-compose.yml +1 -0
  382. package/templates/node/package.json +3 -2
  383. package/templates/node/src/connecta.config.ts +8 -0
  384. package/dist/catalog-drift.d.ts +0 -138
  385. package/dist/catalog-drift.js +0 -578
  386. package/dist/providers/_shared/request-token.js +0 -83
  387. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  388. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  389. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  390. package/dist/providers/basecamp/index.d.ts +0 -45
  391. package/dist/providers/basecamp/index.js +0 -997
  392. package/dist/providers/basecamp/skill.generated.js +0 -9
  393. package/dist/providers/cloudflare/rest.d.ts +0 -37
  394. package/dist/providers/cloudflare/rest.js +0 -1097
  395. package/dist/providers/github/hosted.js +0 -218
  396. package/dist/providers/github/rest.js +0 -321
  397. package/dist/providers/infisical/index.d.ts +0 -7
  398. package/dist/providers/infisical/index.js +0 -713
  399. package/dist/providers/infisical/skill.generated.js +0 -8
  400. package/dist/providers/intercom/index.d.ts +0 -24
  401. package/dist/providers/intercom/index.js +0 -121
  402. package/dist/providers/intercom/skill.generated.js +0 -8
  403. package/dist/providers/linear/index.d.ts +0 -55
  404. package/dist/providers/linear/index.js +0 -537
  405. package/dist/providers/linear/skill.generated.js +0 -8
  406. package/dist/providers/mixpanel/index.d.ts +0 -59
  407. package/dist/providers/mixpanel/index.js +0 -472
  408. package/dist/providers/mixpanel/operations.js +0 -20
  409. package/dist/providers/mixpanel/rest.js +0 -603
  410. package/dist/providers/mixpanel/skill.generated.js +0 -10
  411. package/dist/providers/mixpanel/value-safety.js +0 -16
  412. package/dist/providers/notion/index.d.ts +0 -67
  413. package/dist/providers/notion/index.js +0 -368
  414. package/dist/providers/notion/openapi.generated.js +0 -75
  415. package/dist/providers/notion/rest.d.ts +0 -24
  416. package/dist/providers/notion/rest.js +0 -1226
  417. package/dist/providers/notion/skill.generated.js +0 -11
  418. package/dist/providers/notion/value-safety.js +0 -56
  419. package/dist/providers/revenuecat/index.d.ts +0 -51
  420. package/dist/providers/revenuecat/index.js +0 -697
  421. package/dist/providers/revenuecat/skill.generated.js +0 -11
  422. package/dist/providers/stripe/rest.d.ts +0 -14
  423. package/dist/providers/stripe/rest.js +0 -402
  424. package/dist/providers/vercel/rest.d.ts +0 -20
  425. package/dist/providers/vercel/rest.js +0 -1020
  426. package/dist/providers/wispr-flow/index.d.ts +0 -14
  427. package/dist/providers/wispr-flow/index.js +0 -117
  428. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  429. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -1,48 +1,41 @@
1
+ import { confinementBase, REDIRECT_STATUSES, BODILESS_STATUSES } from "../http-policy.js";
2
+ export { retryAfterMs } from "../http-policy.js";
3
+ import { callerSignal, duringViewCall, settleOnClose, viewSignal } from "../runtime/call.js";
1
4
  /**
2
5
  * The safety machinery every hand-written HTTP surface needs, extracted once
3
6
  * (#341): path confinement, encoded query and framed bodies, per-request
4
7
  * credential headers applied last, a refused redirect, a bounded read, and
5
- * network-failure normalization. It owns no *meaning* — it never reads a status
6
- * code and never invents an auth scheme, because the same 403 means an ungranted
8
+ * network-failure normalization. It owns no vendor-specific meaning and never
9
+ * invents an auth scheme, because the same 403 means an ungranted
7
10
  * capability at one provider and a token scope at another, and those want
8
11
  * opposite next moves. The provider's `authenticate` supplies headers and its
9
- * mapper turns one `GuardedResponse` into a result or a typed failure.
12
+ * mapper turns one `GuardedResponse` into a result or a typed failure. Core
13
+ * then settles retry advice and write outcome from the served classification
14
+ * and dispatch facts, consistently across every provider (INV-9).
10
15
  *
11
16
  * Not exported this release: the migrations proved the shape preserves behavior
12
17
  * for connectors that already had this machinery, not that it is the right
13
18
  * public surface. Web APIs only.
14
19
  */
15
20
  import { ConnectorCallError, unavailableCallError } from "../errors.js";
21
+ import { assertProviderCallOpen, dispatchProviderRequest, handoffProviderRequest, isRecordingFetch, recordProviderResponse, providerRequest, responseProviderRequest, vendorRefusal, } from "../provider-call.js";
22
+ import { providerCallFailure, providerCallResult } from "../write-outcome.js";
16
23
  import { sentSecretsFor } from "../sent-secrets.js";
17
- /** Parse delta-seconds or an HTTP-date into a non-negative wait window. */
18
- export function retryAfterMs(headers) {
19
- const raw = headers.get("retry-after");
20
- if (!raw)
21
- return undefined;
22
- const seconds = Number(raw.trim());
23
- if (Number.isFinite(seconds)) {
24
- return seconds < 0 ? undefined : Math.trunc(seconds * 1000);
25
- }
26
- // Require the HTTP-date shape, so Date.parse cannot reinterpret "-1" as
27
- // a calendar date on runtimes that accept loose date strings.
28
- if (!/^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/.test(raw.trim()))
29
- return undefined;
30
- const date = Date.parse(raw);
31
- return Number.isFinite(date) ? Math.max(0, date - Date.now()) : undefined;
32
- }
33
24
  /**
34
25
  * The transport half of a guarded connector that authenticates through its
35
26
  * own `api()` OAuth grant: no header of the helper's making, and every request
36
27
  * sent through `ctx.oauth.fetch`, which adds the calling owner's bearer token,
37
28
  * refuses any origin outside the grant's `apiOrigins`, and spends one
38
- * coordinated refresh and one replay on a 401 before answering
39
- * `auth_required`. Spread it into the options:
29
+ * coordinated refresh on a 401: a read is replayed once before answering
30
+ * `auth_required`, and a write is never sent again (INV-9). Spread it into
31
+ * the options:
40
32
  * `guardedFetch({ provider, baseUrl, maxResponseBytes, ...oauthBearer(provider) })`.
41
33
  *
42
34
  * Confinement still happens here first, so a request reaches the grant only
43
35
  * once it is provably beneath `baseUrl`; the grant's origin check is the second
44
36
  * fence, not the only one.
45
37
  */
38
+ const oauthSenders = new WeakSet();
46
39
  export function oauthBearer(provider) {
47
40
  const send = (url, init, ctx) => {
48
41
  const grant = ctx.oauth;
@@ -53,37 +46,10 @@ export function oauthBearer(provider) {
53
46
  }
54
47
  return grant.fetch(url, init);
55
48
  };
49
+ oauthSenders.add(send);
56
50
  return { authenticate: () => ({}), fetch: send };
57
51
  }
58
- /** Statuses that instruct a client to re-send somewhere else. Never followed. */
59
- const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
60
- /** Statuses the HTTP spec defines as carrying no body at all. */
61
- const BODILESS_STATUSES = new Set([204, 205, 304]);
62
52
  const decoder = new TextDecoder();
63
- /**
64
- * A base URL is deployment configuration, so a bad one is a structural mistake
65
- * and throws where it is written rather than on the first call that uses it.
66
- */
67
- function confinementBase(provider, baseUrl) {
68
- let base;
69
- try {
70
- base = new URL(baseUrl);
71
- }
72
- catch {
73
- throw new Error(`${provider} baseUrl must be an absolute URL.`);
74
- }
75
- const loopback = base.hostname === "localhost" || base.hostname === "127.0.0.1" || base.hostname === "[::1]";
76
- if (base.protocol !== "https:" && !(base.protocol === "http:" && loopback)) {
77
- throw new Error(`${provider} baseUrl must be https (http is allowed only for a loopback proxy or test double).`);
78
- }
79
- if (base.username || base.password) {
80
- throw new Error(`${provider} baseUrl must not embed URL credentials; authentication belongs in headers.`);
81
- }
82
- if (base.search || base.hash) {
83
- throw new Error(`${provider} baseUrl must not carry a query or fragment.`);
84
- }
85
- return base;
86
- }
87
53
  /**
88
54
  * Resolve a provider-relative path beneath the base and prove it stayed there.
89
55
  *
@@ -132,13 +98,32 @@ function readableBody(response) {
132
98
  return body && typeof body.getReader === "function" ? body : null;
133
99
  }
134
100
  /** Read a stream to the ceiling and stop there — never past it. */
135
- async function drain(provider, stream, limit) {
101
+ function ownedReader(stream, signal) {
136
102
  const reader = stream.getReader();
103
+ void reader.closed.catch(() => { });
104
+ const abort = () => {
105
+ void reader.cancel().catch(() => { });
106
+ };
107
+ signal.addEventListener("abort", abort, { once: true });
108
+ if (signal.aborted)
109
+ abort();
110
+ return {
111
+ reader,
112
+ close: () => {
113
+ signal.removeEventListener("abort", abort);
114
+ reader.releaseLock();
115
+ },
116
+ };
117
+ }
118
+ async function drain(provider, stream, limit, signal) {
119
+ const { reader, close } = ownedReader(stream, signal);
137
120
  const chunks = [];
138
121
  let total = 0;
139
122
  try {
140
123
  while (true) {
141
124
  const { done, value } = await reader.read();
125
+ if (signal.aborted)
126
+ throw signal.reason;
142
127
  if (done)
143
128
  break;
144
129
  if (!value)
@@ -152,7 +137,7 @@ async function drain(provider, stream, limit) {
152
137
  }
153
138
  }
154
139
  finally {
155
- reader.releaseLock();
140
+ close();
156
141
  }
157
142
  const body = new Uint8Array(total);
158
143
  let offset = 0;
@@ -174,7 +159,7 @@ async function drain(provider, stream, limit) {
174
159
  * with a parse error and turns a response nobody was allowed to read into an
175
160
  * empty success.
176
161
  */
177
- function boundedResponse(provider, response, limit) {
162
+ function boundedResponse(provider, response, limit, signal) {
178
163
  if (BODILESS_STATUSES.has(response.status)) {
179
164
  const emptyJson = async () => undefined;
180
165
  return {
@@ -195,7 +180,7 @@ function boundedResponse(provider, response, limit) {
195
180
  const prefix = async (maxBytes) => {
196
181
  const keep = Math.min(Math.max(0, Math.trunc(maxBytes)), limit);
197
182
  if (stream)
198
- return await readPrefix(stream, keep);
183
+ return await readPrefix(stream, keep, signal);
199
184
  // A runtime with no body stream buffers the body regardless; the
200
185
  // ceiling still bounds what is accepted.
201
186
  const buffer = new Uint8Array(await response.arrayBuffer());
@@ -207,7 +192,7 @@ function boundedResponse(provider, response, limit) {
207
192
  let read;
208
193
  const bytes = () => {
209
194
  read ??= stream
210
- ? drain(provider, stream, limit)
195
+ ? drain(provider, stream, limit, signal)
211
196
  : response.arrayBuffer().then((buffer) => {
212
197
  if (buffer.byteLength > limit) {
213
198
  throw oversized(provider, limit, `${buffer.byteLength} bytes`);
@@ -232,7 +217,7 @@ function boundedResponse(provider, response, limit) {
232
217
  ok: response.ok,
233
218
  headers: response.headers,
234
219
  cancel: async () => {
235
- await response.body?.cancel();
220
+ await (stream ?? response.body)?.cancel();
236
221
  },
237
222
  bytes,
238
223
  text,
@@ -248,14 +233,16 @@ function boundedResponse(provider, response, limit) {
248
233
  * A BYOB reader could stop at `keep + 1` exactly, but not every runtime's
249
234
  * fetch body offers one, and one chunk is a bounded overrun.
250
235
  */
251
- async function readPrefix(stream, keep) {
252
- const reader = stream.getReader();
236
+ async function readPrefix(stream, keep, signal) {
237
+ const { reader, close } = ownedReader(stream, signal);
253
238
  const chunks = [];
254
239
  let total = 0;
255
240
  let truncated = false;
256
241
  try {
257
242
  while (true) {
258
243
  const { done, value } = await reader.read();
244
+ if (signal.aborted)
245
+ throw signal.reason;
259
246
  if (done)
260
247
  break;
261
248
  if (!value)
@@ -273,7 +260,7 @@ async function readPrefix(stream, keep) {
273
260
  await reader.cancel().catch(() => { });
274
261
  }
275
262
  finally {
276
- reader.releaseLock();
263
+ close();
277
264
  }
278
265
  const bytes = new Uint8Array(total);
279
266
  let offset = 0;
@@ -293,6 +280,15 @@ async function jsonResult(read) {
293
280
  return { parseError: cause };
294
281
  }
295
282
  }
283
+ // Each response a mapper reads, and the ledger entry of the request it answered.
284
+ const answeredRequests = new WeakMap();
285
+ /**
286
+ * Test-only legacy response lookup for renewal-provenance fixtures outside
287
+ * the kit. Production renewal uses the kit ledger. Undefined for other objects.
288
+ */
289
+ export function answeredRequest(response) {
290
+ return answeredRequests.get(response);
291
+ }
296
292
  /**
297
293
  * Build the transport a connector sends every request through. `maxResponseBytes`
298
294
  * is required rather than defaulted: what counts as an absurd response is a fact
@@ -303,84 +299,182 @@ export function guardedFetch(options) {
303
299
  if (!Number.isInteger(limit) || limit < 1) {
304
300
  throw new Error(`${provider} maxResponseBytes must be a whole number of bytes >= 1; received ${String(limit)}.`);
305
301
  }
302
+ const authFirst = options.authBeforeExecution;
303
+ if (authFirst &&
304
+ (typeof authFirst.evidence !== "string" || !authFirst.evidence.trim() || typeof authFirst.matches !== "function")) {
305
+ throw new Error(`${provider} authBeforeExecution needs nonempty evidence and a narrow matches predicate.`);
306
+ }
306
307
  const base = confinementBase(provider, options.baseUrl);
307
308
  // "" for a root base, so joining never doubles the separator.
308
309
  const basePath = base.pathname.replace(/\/+$/, "");
309
310
  const constantHeaders = { ...options.headers };
310
311
  const send = options.fetch ?? ((url, init) => fetch(url, init));
311
- return async function guarded(request, ctx, map) {
312
- if (request.body !== undefined && request.rawBody !== undefined) {
313
- throw new Error(`A ${provider} request cannot carry both a JSON body and a raw body.`);
314
- }
315
- const url = confinedUrl(provider, base, basePath, request);
316
- options.admit?.(url, request);
317
- const headers = { ...constantHeaders };
318
- for (const [name, value] of Object.entries(request.headers ?? {})) {
319
- if (value !== undefined)
320
- headers[name] = value;
321
- }
322
- if (request.body !== undefined && !hasHeader(headers, "content-type")) {
323
- headers["Content-Type"] = "application/json";
312
+ // The reviewed predicate is trusted code; one that throws proves nothing.
313
+ const authenticatedFirst = (response, request) => {
314
+ try {
315
+ return (authFirst?.matches({ status: 401, headers: response.headers, method: request.method, path: request.path }) ===
316
+ true);
324
317
  }
325
- // Authentication is applied last and may not be shadowed. A caller-shaped
326
- // header that reaches this point wearing the credential's name is a bug
327
- // worth failing on, not a precedence question worth resolving quietly.
328
- for (const [name, value] of Object.entries(await options.authenticate(ctx))) {
329
- const shadow = hasHeader(headers, name);
330
- if (shadow) {
331
- throw new ConnectorCallError("invalid_args", `A ${provider} request may not set the ${shadow} header; authentication is connector-owned.`);
332
- }
333
- headers[name] = value;
334
- sentSecretsFor(ctx).header(value);
318
+ catch {
319
+ return false;
335
320
  }
321
+ };
322
+ return async function guarded(request, ctx, map) {
323
+ const auxiliary = options.auxiliary === true || request.auxiliary === true;
324
+ // A call that already ended sends nothing more, not even a credential read.
325
+ assertProviderCallOpen(ctx, provider, auxiliary);
326
+ const signal = viewSignal(ctx, auxiliary);
327
+ let dispatch = providerRequest(ctx, auxiliary, provider, {
328
+ method: request.method,
329
+ ...(request.classification ? { classification: request.classification } : {}),
330
+ ...(request.idempotencyKey === undefined ? {} : { key: request.idempotencyKey }),
331
+ });
336
332
  let response;
333
+ let result;
337
334
  try {
338
- const init = {
339
- method: request.method,
340
- headers,
341
- ...(request.body !== undefined
342
- ? { body: JSON.stringify(request.body) }
343
- : request.rawBody !== undefined
344
- ? { body: request.rawBody }
345
- : {}),
346
- // A redirect is an instruction to re-send the credential to whatever
347
- // origin `Location` names, and a confinement a redirect can undo was
348
- // never one. Refused below rather than followed.
349
- redirect: "manual",
350
- ...(ctx.signal ? { signal: ctx.signal } : {}),
351
- };
352
- sentSecretsFor(ctx).request(url, init);
353
- for (const [name, value] of Object.entries(request.visibleHeaders ?? {})) {
335
+ // Own the whole helper, including refusal cleanup between I/O and the
336
+ // mapper. Settle its ledger outside the race so revocation cannot skip
337
+ // the dispatched write's final verdict.
338
+ result = await settleOnClose(ctx, () => requestOnce(request, ctx, map), auxiliary);
339
+ }
340
+ catch (error) {
341
+ // Auxiliary preparation has always refused an ended request in the
342
+ // provider's words, even if closure wins the whole-helper race first.
343
+ const source = callerSignal(ctx);
344
+ if (auxiliary || !(source?.aborted && error === source.reason))
345
+ assertProviderCallOpen(ctx, provider, auxiliary);
346
+ // No rejection proves a dispatched write unsent: fetch may have made
347
+ // several attempts behind it (a 421 or HTTP/2 refused-stream resend, a
348
+ // retrying dispatcher), whatever the last one reports.
349
+ throw providerCallFailure(ctx, { title: provider }, vendorRefusal(error, dispatch), {
350
+ dispatched: dispatch.dispatched && !auxiliary,
351
+ ...(response ? { status: response.status } : {}),
352
+ fallback: dispatch.classification ?? "write",
353
+ repeatable: request.idempotencyKey !== undefined,
354
+ authBeforeExecution: dispatch.authBeforeExecution === true,
355
+ ...(auxiliary ? {} : { request: dispatch }),
356
+ });
357
+ }
358
+ const unknown = providerCallResult(ctx, dispatch.classification ?? "write", dispatch);
359
+ if (unknown)
360
+ throw unknown;
361
+ return result;
362
+ async function requestOnce(request, ctx, map) {
363
+ if (request.body !== undefined && request.rawBody !== undefined) {
364
+ throw new Error(`A ${provider} request cannot carry both a JSON body and a raw body.`);
365
+ }
366
+ const url = confinedUrl(provider, base, basePath, request);
367
+ options.admit?.(url, request);
368
+ const headers = { ...constantHeaders };
369
+ for (const [name, value] of Object.entries(request.headers ?? {})) {
370
+ if (value !== undefined) {
371
+ const previous = hasHeader(headers, name);
372
+ if (previous)
373
+ delete headers[previous];
374
+ headers[name] = value;
375
+ }
376
+ }
377
+ if (request.body !== undefined && !hasHeader(headers, "content-type")) {
378
+ headers["Content-Type"] = "application/json";
379
+ }
380
+ // Authentication is applied last and may not be shadowed. A caller-shaped
381
+ // header that reaches this point wearing the credential's name is a bug
382
+ // worth failing on, not a precedence question worth resolving quietly.
383
+ let authentication;
384
+ try {
385
+ authentication = await duringViewCall(ctx, () => Promise.resolve(options.authenticate(ctx)), auxiliary);
386
+ }
387
+ catch (error) {
388
+ assertProviderCallOpen(ctx, provider, auxiliary);
389
+ throw error;
390
+ }
391
+ for (const [name, value] of Object.entries(authentication)) {
354
392
  const shadow = hasHeader(headers, name);
355
393
  if (shadow) {
356
- throw new ConnectorCallError("invalid_args", `A ${provider} request sets the ${shadow} header twice.`);
394
+ throw new ConnectorCallError("invalid_args", `A ${provider} request may not set the ${shadow.toLowerCase()} header; authentication is connector-owned.`);
357
395
  }
358
396
  headers[name] = value;
397
+ sentSecretsFor(ctx).header(value);
398
+ }
399
+ try {
400
+ const body = request.body !== undefined ? JSON.stringify(request.body) : request.rawBody;
401
+ const init = {
402
+ method: request.method,
403
+ headers,
404
+ ...(body !== undefined ? { body } : {}),
405
+ // A redirect is an instruction to re-send the credential to whatever
406
+ // origin `Location` names, and a confinement a redirect can undo was
407
+ // never one. Refused below rather than followed.
408
+ redirect: "manual",
409
+ signal,
410
+ };
411
+ sentSecretsFor(ctx).request(url, init);
412
+ for (const [name, value] of Object.entries(request.visibleHeaders ?? {})) {
413
+ const shadow = hasHeader(headers, name);
414
+ if (shadow) {
415
+ throw new ConnectorCallError("invalid_args", `A ${provider} request sets the ${shadow.toLowerCase()} header twice.`);
416
+ }
417
+ headers[name] = value;
418
+ }
419
+ if (oauthSenders.has(send) && isRecordingFetch(ctx.oauth?.fetch))
420
+ handoffProviderRequest(init, dispatch);
421
+ else
422
+ dispatchProviderRequest(ctx, dispatch, headers, init.method);
423
+ response = await duringViewCall(ctx, async () => {
424
+ const answer = await send(url.toString(), init, ctx);
425
+ // A custom transport may ignore cancellation. Its late response
426
+ // owns no live mapper or body after revocation.
427
+ if (signal.aborted) {
428
+ void answer.body?.cancel().catch(() => { });
429
+ throw signal.reason;
430
+ }
431
+ return answer;
432
+ }, auxiliary);
433
+ const answered = responseProviderRequest(response, dispatch);
434
+ if (answered)
435
+ dispatch = answered;
436
+ else
437
+ recordProviderResponse(dispatch, response.status);
438
+ }
439
+ catch (cause) {
440
+ // A cancelled wait is the caller's own reason, not a network failure.
441
+ if (signal.aborted && cause === signal.reason)
442
+ throw cause;
443
+ if (cause instanceof ConnectorCallError)
444
+ throw cause;
445
+ throw unavailableCallError(cause, url.href, `Could not reach the ${provider} API.`, signal);
446
+ }
447
+ if (response.status === 401 && authenticatedFirst(response, request))
448
+ dispatch.authBeforeExecution = true;
449
+ if (REDIRECT_STATUSES.has(response.status)) {
450
+ await response.body?.cancel().catch(() => { });
451
+ throw new ConnectorCallError("connector_call_failed", `${provider} answered HTTP ${response.status} with a redirect; this connector talks to exactly one origin and never forwards its credential to another.`, { retryable: false });
452
+ }
453
+ const declared = Number(response.headers.get("content-length"));
454
+ // A prefix read takes only what it was asked for, so a long body is not
455
+ // a reason to refuse it; the ceiling still bounds what is read. A HEAD
456
+ // response has no body: its Content-Length describes the GET
457
+ // representation, which is exactly what a HEAD asks about.
458
+ if (Number.isFinite(declared) &&
459
+ declared > limit &&
460
+ request.method !== "HEAD" &&
461
+ !(request.prefixOnly && response.ok)) {
462
+ await response.body?.cancel().catch(() => { });
463
+ throw oversized(provider, limit, `a declared ${declared} bytes`);
464
+ }
465
+ const answer = boundedResponse(provider, response, limit, signal);
466
+ answeredRequests.set(answer, dispatch);
467
+ const abort = () => {
468
+ void response?.body?.cancel().catch(() => { });
469
+ };
470
+ signal.addEventListener("abort", abort, { once: true });
471
+ try {
472
+ return await duringViewCall(ctx, () => Promise.resolve(map(answer, ctx)), auxiliary);
473
+ }
474
+ finally {
475
+ signal.removeEventListener("abort", abort);
359
476
  }
360
- response = await send(url.toString(), init, ctx);
361
- }
362
- catch (cause) {
363
- if (cause instanceof ConnectorCallError)
364
- throw cause;
365
- throw unavailableCallError(cause, url.href, `Could not reach the ${provider} API.`, ctx.signal);
366
- }
367
- if (REDIRECT_STATUSES.has(response.status)) {
368
- await response.body?.cancel().catch(() => { });
369
- throw new ConnectorCallError("connector_call_failed", `${provider} answered HTTP ${response.status} with a redirect; this connector talks to exactly one origin and never forwards its credential to another.`, { retryable: false });
370
- }
371
- const declared = Number(response.headers.get("content-length"));
372
- // A prefix read takes only what it was asked for, so a long body is not
373
- // a reason to refuse it; the ceiling still bounds what is read. A HEAD
374
- // response has no body: its Content-Length describes the GET
375
- // representation, which is exactly what a HEAD asks about.
376
- if (Number.isFinite(declared) &&
377
- declared > limit &&
378
- request.method !== "HEAD" &&
379
- !(request.prefixOnly && response.ok)) {
380
- await response.body?.cancel().catch(() => { });
381
- throw oversized(provider, limit, `a declared ${declared} bytes`);
382
477
  }
383
- return await map(boundedResponse(provider, response, limit), ctx);
384
478
  };
385
479
  }
386
480
  /** The stored spelling of a header already present, case-insensitively. */
@@ -1,13 +1,18 @@
1
+ import { runEdge } from "../runtime/run.js";
2
+ import { authFlow, authProgram, registerAuth, authStorage } from "../auth/native.js";
1
3
  import { isSpecType } from "@modelcontextprotocol/client";
2
4
  import { failureRecord, logFailure } from "../operator-record.js";
3
5
  import { sentSecretsForRequest } from "../sent-secrets.js";
4
6
  import { assertDownstreamOutputSafe } from "../downstream-input-context.js";
5
7
  import { negotiationKeys, NEGOTIATION_TTL_SECONDS } from "../storage/keys.js";
6
8
  /** Verdicts carry data only. Clients, signals and secrets remain request-local. */
7
- export async function readNegotiation(ctx, digest) {
9
+ export function readNegotiation(ctx, digest) {
10
+ return runEdge(authProgram(readNegotiationNative, [ctx, digest]));
11
+ }
12
+ const readNegotiationNative = /* @__PURE__ */ registerAuth(readNegotiation, (ctx, digest) => authFlow(function* () {
8
13
  let prior;
9
14
  try {
10
- const raw = await ctx.storage.get(negotiationKeys.verdict(digest));
15
+ const raw = (yield authStorage(ctx.storage, "get", [negotiationKeys.verdict(digest)]));
11
16
  if (!raw)
12
17
  return;
13
18
  const value = JSON.parse(raw);
@@ -21,26 +26,31 @@ export async function readNegotiation(ctx, digest) {
21
26
  catch (error) {
22
27
  logFailure(ctx.logger, "negotiation cache read failed", failureRecord({}, error));
23
28
  }
24
- // Privacy refusals are not cache misses and must not enter cache diagnostics.
25
29
  if (prior)
26
30
  assertDownstreamOutputSafe(ctx.requestScope ?? ctx, prior);
27
31
  return prior;
32
+ }));
33
+ export function storeNegotiation(ctx, digest, prior) {
34
+ return runEdge(authProgram(storeNegotiationNative, [ctx, digest, prior]));
28
35
  }
29
- export async function storeNegotiation(ctx, digest, prior) {
36
+ const storeNegotiationNative = /* @__PURE__ */ registerAuth(storeNegotiation, (ctx, digest, prior) => authFlow(function* () {
30
37
  if (ctx.signal?.aborted)
31
38
  return;
32
39
  assertDownstreamOutputSafe(ctx.requestScope ?? ctx, prior);
33
- // DiscoverResult instructions, metadata and capability keys can echo auth.
34
40
  const clean = sentSecretsForRequest(ctx.requestScope ?? ctx).redactCredentials(prior);
35
41
  if (clean.kind === "modern" && !isSpecType.DiscoverResult(clean.discover))
36
42
  return;
37
43
  try {
38
- await ctx.storage.set(negotiationKeys.verdict(digest), JSON.stringify({
39
- prior: clean,
40
- expiresAt: Date.now() + NEGOTIATION_TTL_SECONDS * 1000,
41
- }), { ttlSeconds: NEGOTIATION_TTL_SECONDS });
44
+ (yield authStorage(ctx.storage, "set", [
45
+ negotiationKeys.verdict(digest),
46
+ JSON.stringify({
47
+ prior: clean,
48
+ expiresAt: Date.now() + NEGOTIATION_TTL_SECONDS * 1000,
49
+ }),
50
+ { ttlSeconds: NEGOTIATION_TTL_SECONDS },
51
+ ]));
42
52
  }
43
53
  catch (error) {
44
54
  logFailure(ctx.logger, "negotiation cache write failed", failureRecord({}, error));
45
55
  }
46
- }
56
+ }));
@@ -1,7 +1,7 @@
1
1
  import { type RemoteOAuthClient } from "../auth/downstream-client-metadata.js";
2
2
  import type { FetchLike, Transport } from "@modelcontextprotocol/client";
3
3
  import { ConnectorCallError } from "../errors.js";
4
- import type { Connector, ConnectorCallAdmissionPolicy, ConnectorContext, ConnectorCredentialConfig, ConnectorUsageGuide, Logger, ToolClassification } from "../types.js";
4
+ import type { Connector, ConnectorCallAdmissionPolicy, ConnectorContext, ConnectorCredentialConfig, ConnectorUsageGuide, Logger } from "../types.js";
5
5
  /**
6
6
  * A static downstream credential supplied through the connection in the
7
7
  * operator UI rather than baked into deployment source.
@@ -29,7 +29,7 @@ interface RemoteMcpCredentialAuth {
29
29
  * an empty string) sends the stored value verbatim, for an endpoint that
30
30
  * reads a bare key. A scheme whose last token is `Basic` declares
31
31
  * HTTP Basic credentials: the stored `user:secret` is base64-encoded first,
32
- * so `"Basic"` produces `Basic <base64>` and Mixpanel's documented
32
+ * so `"Basic"` produces `Basic <base64>` and a nested
33
33
  * `"Bearer Basic"` produces `Bearer Basic <base64>`.
34
34
  */
35
35
  scheme?: string | null;
@@ -52,20 +52,6 @@ export type RemoteMcpAuth = {
52
52
  /** Space-separated default scopes when the resource server does not advertise them. */
53
53
  scope?: string;
54
54
  };
55
- /**
56
- * Apply a maintained provider's slot copy and header framing to credential
57
- * auth the deployment left bare.
58
- *
59
- * A provider knows what its own key is called and how the endpoint expects it
60
- * framed; a deployment that states either one keeps its answer. Every other
61
- * auth shape passes through untouched, so a provider can hand this its whole
62
- * `auth` option without branching first.
63
- */
64
- export declare function withCredentialDefaults(auth: RemoteMcpAuth, defaults: {
65
- credential: ConnectorCredentialConfig;
66
- /** Provider framing; omit to leave the `Bearer` default in place. */
67
- scheme?: string | null;
68
- }): RemoteMcpAuth;
69
55
  export type RemoteMcpRedirectPolicy = "none" | "same-origin";
70
56
  export interface RemoteMcpOptions {
71
57
  url: string;
@@ -96,20 +82,12 @@ export interface RemoteMcpOptions {
96
82
  skills?: boolean;
97
83
  auth?: RemoteMcpAuth;
98
84
  /**
99
- * Reviewed read/write verdicts for this downstream's tools, by exact name.
100
- * Validated at construction. A listed read fills downstream silence but
101
- * never overrules an explicit write annotation; a listed write or
102
- * destructive tool stays a write whatever the downstream claims; an unlisted
103
- * tool is read-only only when it says so explicitly; a listed tool whose
104
- * `schemaDigest` no longer matches, or cannot be checked, is served as a
105
- * write. Setting it also reports
106
- * catalog drift against the list: unclassified, unserved, contradicted, and
107
- * schema-changed tools, as counts. The connector carries it as
108
- * `classification`, and its `listTools` returns the downstream's listing
109
- * unclassified: the registry classifies every read. Omit it to keep the
110
- * downstream's own annotations, which still fail closed.
85
+ * Non-secret resource context headers. Never credentials: use auth for those.
86
+ * Auth-owned, HTTP transport/session and OAuth client-auth headers are
87
+ * reserved. Cannot be combined with inline headers auth. Sent only at the
88
+ * resource URL path; echoed values are redacted at eight characters or more.
111
89
  */
112
- classify?: ToolClassification | undefined;
90
+ headers?: Record<string, string>;
113
91
  /**
114
92
  * Downstream MCP version-negotiation mode. Defaults to `"auto"`, which
115
93
  * probes with `server/discover` and falls back to the legacy lifecycle when
@@ -123,7 +101,9 @@ export interface RemoteMcpOptions {
123
101
  * rejected. `"same-origin"` follows at most five redirects while preserving
124
102
  * standard 301/302/303/307/308 method semantics. Cross-origin redirects and
125
103
  * HTTPS downgrades are always refused, so credentials never cross the
126
- * configured request's origin.
104
+ * configured request's origin. A write is never sent to a redirect target
105
+ * under either policy: a redirect answering a write fails it as an unknown
106
+ * outcome (INV-9), so set `url` to the endpoint that answers directly.
127
107
  */
128
108
  redirects?: RemoteMcpRedirectPolicy;
129
109
  /**