@zackbart/connecta 0.15.1 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. package/AGENTS.md +40 -20
  2. package/CHANGELOG.md +653 -0
  3. package/README.md +25 -5
  4. package/bin/connecta.mjs +44 -3
  5. package/dist/access-tokens.d.ts +0 -1
  6. package/dist/access-tokens.js +0 -1
  7. package/dist/activity.d.ts +50 -2
  8. package/dist/activity.js +34 -1
  9. package/dist/apps-shell.d.ts +0 -1
  10. package/dist/apps-shell.js +0 -1
  11. package/dist/auth/bearer.d.ts +0 -1
  12. package/dist/auth/bearer.js +0 -1
  13. package/dist/auth/clerk.d.ts +0 -1
  14. package/dist/auth/clerk.js +45 -9
  15. package/dist/auth/downstream-oauth.d.ts +0 -1
  16. package/dist/auth/downstream-oauth.js +0 -1
  17. package/dist/call-admission.d.ts +0 -1
  18. package/dist/call-admission.js +0 -1
  19. package/dist/catalog-drift.d.ts +99 -0
  20. package/dist/catalog-drift.js +251 -0
  21. package/dist/catalog-fingerprint.d.ts +0 -1
  22. package/dist/catalog-fingerprint.js +0 -1
  23. package/dist/catalog-limits.d.ts +0 -1
  24. package/dist/catalog-limits.js +0 -1
  25. package/dist/catalog-service.d.ts +0 -1
  26. package/dist/catalog-service.js +41 -5
  27. package/dist/catalog.d.ts +11 -1
  28. package/dist/catalog.js +20 -1
  29. package/dist/concurrency.d.ts +0 -1
  30. package/dist/concurrency.js +0 -1
  31. package/dist/connector-scope.d.ts +0 -1
  32. package/dist/connector-scope.js +0 -1
  33. package/dist/connectors/api.d.ts +29 -21
  34. package/dist/connectors/api.js +45 -19
  35. package/dist/connectors/guarded-fetch.d.ts +106 -0
  36. package/dist/connectors/guarded-fetch.js +289 -0
  37. package/dist/connectors/remote-mcp.d.ts +0 -1
  38. package/dist/connectors/remote-mcp.js +0 -1
  39. package/dist/credentials.d.ts +0 -1
  40. package/dist/credentials.js +0 -1
  41. package/dist/errors.d.ts +30 -3
  42. package/dist/errors.js +1 -1
  43. package/dist/execute.d.ts +0 -1
  44. package/dist/execute.js +0 -1
  45. package/dist/executor-admission.d.ts +11 -1
  46. package/dist/executor-admission.js +28 -1
  47. package/dist/executor-result.d.ts +0 -1
  48. package/dist/executor-result.js +0 -1
  49. package/dist/executors/quickjs-child.d.ts +0 -1
  50. package/dist/executors/quickjs-child.js +0 -1
  51. package/dist/executors/quickjs-protocol.d.ts +0 -1
  52. package/dist/executors/quickjs-protocol.js +0 -1
  53. package/dist/executors/quickjs-runtime.d.ts +0 -1
  54. package/dist/executors/quickjs-runtime.js +0 -1
  55. package/dist/executors/quickjs.d.ts +0 -1
  56. package/dist/executors/quickjs.js +2 -1
  57. package/dist/favicon.d.ts +0 -1
  58. package/dist/favicon.js +0 -1
  59. package/dist/index.d.ts +2 -3
  60. package/dist/index.js +24 -7
  61. package/dist/invocation.d.ts +0 -1
  62. package/dist/invocation.js +0 -1
  63. package/dist/json-schema.d.ts +0 -1
  64. package/dist/json-schema.js +0 -1
  65. package/dist/mcp-result.d.ts +0 -1
  66. package/dist/mcp-result.js +0 -1
  67. package/dist/meta-tools.d.ts +0 -1
  68. package/dist/meta-tools.js +0 -1
  69. package/dist/node.d.ts +0 -1
  70. package/dist/node.js +0 -1
  71. package/dist/operator-ui/generated.d.ts +2 -3
  72. package/dist/operator-ui/generated.js +3 -4
  73. package/dist/operator-ui/model.d.ts +10 -1
  74. package/dist/operator-ui/model.js +0 -1
  75. package/dist/operator-ui/view.d.ts +167 -0
  76. package/dist/operator-ui/view.js +270 -0
  77. package/dist/providers/cloudflare.d.ts +0 -1
  78. package/dist/providers/cloudflare.js +261 -299
  79. package/dist/providers/linear.d.ts +26 -5
  80. package/dist/providers/linear.js +32 -61
  81. package/dist/providers/mixpanel.d.ts +35 -4
  82. package/dist/providers/mixpanel.js +53 -79
  83. package/dist/providers/notion.d.ts +0 -1
  84. package/dist/providers/notion.js +87 -42
  85. package/dist/providers/stripe.d.ts +13 -1
  86. package/dist/providers/stripe.js +31 -60
  87. package/dist/registry.d.ts +34 -2
  88. package/dist/registry.js +85 -5
  89. package/dist/retired-toolkits.d.ts +0 -1
  90. package/dist/retired-toolkits.js +0 -1
  91. package/dist/routes/access-tokens.d.ts +0 -1
  92. package/dist/routes/access-tokens.js +0 -1
  93. package/dist/routes/activity.d.ts +0 -1
  94. package/dist/routes/activity.js +0 -1
  95. package/dist/routes/credentials.d.ts +0 -1
  96. package/dist/routes/credentials.js +0 -1
  97. package/dist/routes/mcp.d.ts +0 -1
  98. package/dist/routes/mcp.js +0 -1
  99. package/dist/routes/oauth.d.ts +0 -1
  100. package/dist/routes/oauth.js +0 -1
  101. package/dist/routes/shared.d.ts +2 -1
  102. package/dist/routes/shared.js +0 -1
  103. package/dist/routes/ui.d.ts +0 -1
  104. package/dist/routes/ui.js +0 -1
  105. package/dist/server.d.ts +0 -1
  106. package/dist/server.js +11 -1
  107. package/dist/skills.d.ts +0 -1
  108. package/dist/skills.js +0 -1
  109. package/dist/storage/file.d.ts +0 -1
  110. package/dist/storage/file.js +0 -1
  111. package/dist/storage/memory.d.ts +0 -1
  112. package/dist/storage/memory.js +0 -1
  113. package/dist/timeout.d.ts +0 -1
  114. package/dist/timeout.js +0 -1
  115. package/dist/tool-safety.d.ts +0 -1
  116. package/dist/tool-safety.js +0 -1
  117. package/dist/types.d.ts +45 -1
  118. package/dist/types.js +0 -1
  119. package/dist/ui.d.ts +0 -1
  120. package/dist/ui.js +13 -137
  121. package/dist/validate.d.ts +13 -15
  122. package/dist/validate.js +24 -11
  123. package/dist/version.d.ts +1 -2
  124. package/dist/version.js +1 -2
  125. package/documentation/architecture.md +186 -5
  126. package/documentation/auth.md +11 -0
  127. package/documentation/call-admission.md +142 -6
  128. package/documentation/cloudflare.md +92 -10
  129. package/documentation/code-first-exploration.md +2 -2
  130. package/documentation/code-mode.md +14 -14
  131. package/documentation/connector-guides.md +172 -5
  132. package/documentation/connectors.md +89 -0
  133. package/documentation/linear.md +20 -2
  134. package/documentation/mcp-ui-design.md +2 -2
  135. package/documentation/meta-tools.md +7 -1
  136. package/documentation/mixpanel.md +42 -9
  137. package/documentation/notion.md +23 -2
  138. package/documentation/operations.md +325 -5
  139. package/documentation/operator-ui.md +120 -5
  140. package/documentation/provider-audit.md +160 -0
  141. package/documentation/provider-conventions.md +667 -0
  142. package/documentation/request-admission.md +167 -5
  143. package/documentation/rich-output-design.md +1 -2
  144. package/documentation/stripe.md +15 -0
  145. package/documentation/upgrading.md +454 -0
  146. package/ethos.md +14 -9
  147. package/examples/worker/README.md +102 -12
  148. package/examples/worker/src/index.ts +46 -1
  149. package/examples/worker/wrangler.jsonc +14 -1
  150. package/package.json +10 -6
  151. package/templates/node/.dockerignore +10 -0
  152. package/templates/node/.env.example +40 -3
  153. package/templates/node/AGENTS.md +16 -1
  154. package/templates/node/Dockerfile +49 -0
  155. package/templates/node/README.md +117 -2
  156. package/templates/node/docker-compose.yml +39 -0
  157. package/templates/node/package.json +1 -1
  158. package/templates/node/src/file-activity.ts +182 -0
  159. package/templates/node/src/index.ts +80 -4
  160. package/assets/connecta-clay-hero.png +0 -0
  161. package/dist/access-tokens.d.ts.map +0 -1
  162. package/dist/access-tokens.js.map +0 -1
  163. package/dist/activity.d.ts.map +0 -1
  164. package/dist/activity.js.map +0 -1
  165. package/dist/apps-shell.d.ts.map +0 -1
  166. package/dist/apps-shell.js.map +0 -1
  167. package/dist/auth/bearer.d.ts.map +0 -1
  168. package/dist/auth/bearer.js.map +0 -1
  169. package/dist/auth/clerk.d.ts.map +0 -1
  170. package/dist/auth/clerk.js.map +0 -1
  171. package/dist/auth/downstream-oauth.d.ts.map +0 -1
  172. package/dist/auth/downstream-oauth.js.map +0 -1
  173. package/dist/call-admission.d.ts.map +0 -1
  174. package/dist/call-admission.js.map +0 -1
  175. package/dist/catalog-fingerprint.d.ts.map +0 -1
  176. package/dist/catalog-fingerprint.js.map +0 -1
  177. package/dist/catalog-limits.d.ts.map +0 -1
  178. package/dist/catalog-limits.js.map +0 -1
  179. package/dist/catalog-service.d.ts.map +0 -1
  180. package/dist/catalog-service.js.map +0 -1
  181. package/dist/catalog.d.ts.map +0 -1
  182. package/dist/catalog.js.map +0 -1
  183. package/dist/concurrency.d.ts.map +0 -1
  184. package/dist/concurrency.js.map +0 -1
  185. package/dist/connector-scope.d.ts.map +0 -1
  186. package/dist/connector-scope.js.map +0 -1
  187. package/dist/connectors/api.d.ts.map +0 -1
  188. package/dist/connectors/api.js.map +0 -1
  189. package/dist/connectors/remote-mcp.d.ts.map +0 -1
  190. package/dist/connectors/remote-mcp.js.map +0 -1
  191. package/dist/credentials.d.ts.map +0 -1
  192. package/dist/credentials.js.map +0 -1
  193. package/dist/errors.d.ts.map +0 -1
  194. package/dist/errors.js.map +0 -1
  195. package/dist/execute.d.ts.map +0 -1
  196. package/dist/execute.js.map +0 -1
  197. package/dist/executor-admission.d.ts.map +0 -1
  198. package/dist/executor-admission.js.map +0 -1
  199. package/dist/executor-result.d.ts.map +0 -1
  200. package/dist/executor-result.js.map +0 -1
  201. package/dist/executors/quickjs-child.d.ts.map +0 -1
  202. package/dist/executors/quickjs-child.js.map +0 -1
  203. package/dist/executors/quickjs-protocol.d.ts.map +0 -1
  204. package/dist/executors/quickjs-protocol.js.map +0 -1
  205. package/dist/executors/quickjs-runtime.d.ts.map +0 -1
  206. package/dist/executors/quickjs-runtime.js.map +0 -1
  207. package/dist/executors/quickjs.d.ts.map +0 -1
  208. package/dist/executors/quickjs.js.map +0 -1
  209. package/dist/favicon.d.ts.map +0 -1
  210. package/dist/favicon.js.map +0 -1
  211. package/dist/index.d.ts.map +0 -1
  212. package/dist/index.js.map +0 -1
  213. package/dist/invocation.d.ts.map +0 -1
  214. package/dist/invocation.js.map +0 -1
  215. package/dist/json-schema.d.ts.map +0 -1
  216. package/dist/json-schema.js.map +0 -1
  217. package/dist/mcp-result.d.ts.map +0 -1
  218. package/dist/mcp-result.js.map +0 -1
  219. package/dist/meta-tools.d.ts.map +0 -1
  220. package/dist/meta-tools.js.map +0 -1
  221. package/dist/node.d.ts.map +0 -1
  222. package/dist/node.js.map +0 -1
  223. package/dist/operator-ui/generated.d.ts.map +0 -1
  224. package/dist/operator-ui/generated.js.map +0 -1
  225. package/dist/operator-ui/model.d.ts.map +0 -1
  226. package/dist/operator-ui/model.js.map +0 -1
  227. package/dist/providers/cloudflare.d.ts.map +0 -1
  228. package/dist/providers/cloudflare.js.map +0 -1
  229. package/dist/providers/linear.d.ts.map +0 -1
  230. package/dist/providers/linear.js.map +0 -1
  231. package/dist/providers/mixpanel.d.ts.map +0 -1
  232. package/dist/providers/mixpanel.js.map +0 -1
  233. package/dist/providers/notion.d.ts.map +0 -1
  234. package/dist/providers/notion.js.map +0 -1
  235. package/dist/providers/stripe.d.ts.map +0 -1
  236. package/dist/providers/stripe.js.map +0 -1
  237. package/dist/registry.d.ts.map +0 -1
  238. package/dist/registry.js.map +0 -1
  239. package/dist/retired-toolkits.d.ts.map +0 -1
  240. package/dist/retired-toolkits.js.map +0 -1
  241. package/dist/routes/access-tokens.d.ts.map +0 -1
  242. package/dist/routes/access-tokens.js.map +0 -1
  243. package/dist/routes/activity.d.ts.map +0 -1
  244. package/dist/routes/activity.js.map +0 -1
  245. package/dist/routes/credentials.d.ts.map +0 -1
  246. package/dist/routes/credentials.js.map +0 -1
  247. package/dist/routes/mcp.d.ts.map +0 -1
  248. package/dist/routes/mcp.js.map +0 -1
  249. package/dist/routes/oauth.d.ts.map +0 -1
  250. package/dist/routes/oauth.js.map +0 -1
  251. package/dist/routes/shared.d.ts.map +0 -1
  252. package/dist/routes/shared.js.map +0 -1
  253. package/dist/routes/ui.d.ts.map +0 -1
  254. package/dist/routes/ui.js.map +0 -1
  255. package/dist/server.d.ts.map +0 -1
  256. package/dist/server.js.map +0 -1
  257. package/dist/skills.d.ts.map +0 -1
  258. package/dist/skills.js.map +0 -1
  259. package/dist/storage/file.d.ts.map +0 -1
  260. package/dist/storage/file.js.map +0 -1
  261. package/dist/storage/memory.d.ts.map +0 -1
  262. package/dist/storage/memory.js.map +0 -1
  263. package/dist/timeout.d.ts.map +0 -1
  264. package/dist/timeout.js.map +0 -1
  265. package/dist/tool-safety.d.ts.map +0 -1
  266. package/dist/tool-safety.js.map +0 -1
  267. package/dist/types.d.ts.map +0 -1
  268. package/dist/types.js.map +0 -1
  269. package/dist/ui.d.ts.map +0 -1
  270. package/dist/ui.js.map +0 -1
  271. package/dist/validate.d.ts.map +0 -1
  272. package/dist/validate.js.map +0 -1
  273. package/dist/version.d.ts.map +0 -1
  274. package/dist/version.js.map +0 -1
  275. package/examples/node/README.md +0 -52
  276. package/examples/node/src/index.ts +0 -71
  277. package/src/access-tokens.ts +0 -289
  278. package/src/activity.ts +0 -234
  279. package/src/apps-shell.ts +0 -370
  280. package/src/auth/bearer.ts +0 -61
  281. package/src/auth/clerk.ts +0 -553
  282. package/src/auth/downstream-oauth.ts +0 -575
  283. package/src/call-admission.ts +0 -521
  284. package/src/catalog-fingerprint.ts +0 -52
  285. package/src/catalog-limits.ts +0 -11
  286. package/src/catalog-service.ts +0 -1153
  287. package/src/catalog.ts +0 -790
  288. package/src/concurrency.ts +0 -39
  289. package/src/connector-scope.ts +0 -66
  290. package/src/connectors/api.ts +0 -159
  291. package/src/connectors/remote-mcp.ts +0 -1090
  292. package/src/credentials.ts +0 -428
  293. package/src/errors.ts +0 -364
  294. package/src/execute.ts +0 -1406
  295. package/src/executor-admission.ts +0 -328
  296. package/src/executor-result.ts +0 -107
  297. package/src/executors/quickjs-child.ts +0 -172
  298. package/src/executors/quickjs-protocol.ts +0 -99
  299. package/src/executors/quickjs-runtime.ts +0 -470
  300. package/src/executors/quickjs.ts +0 -776
  301. package/src/favicon.ts +0 -53
  302. package/src/index.ts +0 -666
  303. package/src/invocation.ts +0 -655
  304. package/src/json-schema.ts +0 -11
  305. package/src/mcp-result.ts +0 -43
  306. package/src/meta-tools.ts +0 -1607
  307. package/src/node.ts +0 -206
  308. package/src/operator-ui/browser.css +0 -423
  309. package/src/operator-ui/browser.ts +0 -1281
  310. package/src/operator-ui/generated.ts +0 -4
  311. package/src/operator-ui/model.ts +0 -111
  312. package/src/providers/cloudflare.ts +0 -3999
  313. package/src/providers/linear.ts +0 -302
  314. package/src/providers/mixpanel.ts +0 -229
  315. package/src/providers/notion.ts +0 -1879
  316. package/src/providers/stripe.ts +0 -307
  317. package/src/registry.ts +0 -1085
  318. package/src/retired-toolkits.ts +0 -14
  319. package/src/routes/access-tokens.ts +0 -115
  320. package/src/routes/activity.ts +0 -215
  321. package/src/routes/credentials.ts +0 -254
  322. package/src/routes/mcp.ts +0 -429
  323. package/src/routes/oauth.ts +0 -322
  324. package/src/routes/shared.ts +0 -247
  325. package/src/routes/ui.ts +0 -152
  326. package/src/server.ts +0 -195
  327. package/src/skills.ts +0 -271
  328. package/src/storage/file.ts +0 -123
  329. package/src/storage/memory.ts +0 -44
  330. package/src/timeout.ts +0 -84
  331. package/src/tool-safety.ts +0 -15
  332. package/src/types.ts +0 -523
  333. package/src/ui.ts +0 -744
  334. package/src/validate.ts +0 -387
  335. package/src/version.ts +0 -7
@@ -1,4 +1,5 @@
1
1
  import { remoteMcp, } from "../connectors/remote-mcp.js";
2
+ import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
2
3
  /** Stripe publishes one hosted MCP endpoint; the credential selects the mode. */
3
4
  export const STRIPE_MCP_ENDPOINT = "https://mcp.stripe.com/";
4
5
  /**
@@ -66,60 +67,21 @@ const WRITE_TOOLS = new Map([
66
67
  ["send_stripe_mcp_feedback", "additive"],
67
68
  ]);
68
69
  /**
69
- * Fill in downstream silence; keep reviewed destructive tools fail-closed.
70
+ * The manifest this release reviewed: both lists in one place, which is what
71
+ * makes the classification the connector applies and the drift check that runs
72
+ * beside it the same fact (P13). No schema digests yet — no release has read
73
+ * Stripe's live schemas and written them down, and an invented digest would
74
+ * report a change that never happened. `npm run drift:check -- --record` reads
75
+ * them from a live account and prints the block to paste in
76
+ * ([#351](https://github.com/zackbart/connecta/issues/351)).
70
77
  *
71
- * Silence is what a vetted classification is for, and an explicit downstream
72
- * annotation otherwise wins in both directions. `destructiveHint: true` or
73
- * `readOnlyHint: false` on an allowlisted read name is the downstream telling
74
- * us this release's allowlist is stale; `readOnlyHint: true` on a name no
75
- * release has classified says the same thing from the other side. The single
76
- * place a vetted verdict still overrides the downstream is a name this release
77
- * reviewed and filed destructive: there connecta knows what the tool does, and
78
- * a claim to the contrary is a downstream bug rather than news
79
- * ([#310](https://github.com/zackbart/connecta/issues/310),
80
- * [#315](https://github.com/zackbart/connecta/issues/315)).
78
+ * Exported because the maintainer-run check compares against this manifest and
79
+ * *names* what moved, which the runtime check deliberately cannot.
81
80
  */
82
- function vettedSafety(definition) {
83
- const downstream = definition.annotations ?? {};
84
- if (READ_ONLY_TOOLS.has(definition.name)) {
85
- if (downstream.destructiveHint === true ||
86
- downstream.readOnlyHint === false) {
87
- return definition;
88
- }
89
- return {
90
- ...definition,
91
- annotations: {
92
- ...downstream,
93
- readOnlyHint: true,
94
- destructiveHint: downstream.destructiveHint ?? false,
95
- },
96
- };
97
- }
98
- if (WRITE_TOOLS.get(definition.name) === "destructive") {
99
- return {
100
- ...definition,
101
- annotations: {
102
- ...downstream,
103
- readOnlyHint: false,
104
- destructiveHint: true,
105
- },
106
- };
107
- }
108
- // Maintained additive writes and tools this release has never seen land here
109
- // alike. Fill-in only: a silent tool is not read-only, so drift still fails
110
- // closed onto `call_destructive_tool`, and neither population gets a
111
- // `destructiveHint` it has not earned. A tool that arrives explicitly
112
- // read-only keeps that annotation — on a name no release has reviewed, the
113
- // downstream's own word is the only evidence there is, and rewriting it
114
- // would be an overrule rather than a fill-in.
115
- return {
116
- ...definition,
117
- annotations: {
118
- ...downstream,
119
- readOnlyHint: downstream.readOnlyHint ?? false,
120
- },
121
- };
122
- }
81
+ export const STRIPE_VETTED_CATALOG = vettedCatalog({
82
+ reads: READ_ONLY_TOOLS,
83
+ writes: WRITE_TOOLS,
84
+ });
123
85
  /** Stripe key prefixes carry their own mode; only a clear reading counts. */
124
86
  const LIVE_KEY = /\b(?:sk|rk|pk)_live_/;
125
87
  const TEST_KEY = /\b(?:sk|rk|pk)_test_/;
@@ -189,11 +151,14 @@ ${copy.warning}
189
151
  - Prefer a dedicated tool when one covers the task: \`get_stripe_account_info\` for which account this is, \`get_balance_summary\` for balances, \`create_refund\` for refunds, \`stripe_report\` for reports. One call instead of three, and a refund named \`create_refund\` reads far more clearly in the approval a human sees than the same refund buried in \`stripe_api_write\` arguments.
190
152
  - \`stripe_api_write\` carries the blast radius of the entire write API — every POST, PATCH, PUT, and DELETE, from a customer edit to a subscription cancellation. State the method and path explicitly; expect approval on every call.
191
153
  - Lists are cursor-paginated: \`limit\` defaults to 10 and caps at 100, \`starting_after\` and \`ending_before\` take an object id and are mutually exclusive, and \`has_more\` says whether to continue. Page inside \`execute_code\` and reduce before returning.
154
+ - Resolve ids before acting; never guess one. Stripe ids are typed prefixes — \`cus_\` customer, \`sub_\` subscription, \`ch_\` charge, \`pi_\` payment intent, \`in_\` invoice, \`acct_\` account — and a plausible-looking id belongs to a different object or to nobody. Find the object with \`stripe_api_search\` (or a list endpoint through \`stripe_api_read\`) and carry the \`id\` it returned into the write.
155
+ - This account's tool list is not a fixed set. Stripe gates parts of its MCP catalog by account, integration, and beta enrollment, so search this connector for what it actually exposes rather than assuming a documented tool is here.
192
156
  - Amounts are integers in the currency's minor unit: \`1099\` is 10.99 USD, and zero-decimal currencies like JPY take \`10\` for 10 JPY. Never send a decimal.
193
157
  - Send an \`Idempotency-Key\` on every write you might retry, if the tool accepts it, and reuse the same key for the retry. A retry with a fresh key is a second charge, not a second attempt.
194
158
  - Stripe answers a rate limit with \`429\` and a \`Stripe-Rate-Limited-Reason\` header; back off on that rather than retrying immediately. This account's documented ceiling is ${rate} requests per second, and any single endpoint is capped at 25 per second regardless of mode, so paging one list is the real constraint.
195
159
  - Use \`search_stripe_documentation\` when the shape of an object or a flow is unclear; it is a read and costs nothing but a call.
196
160
  - Treat every create, update, delete, refund, and report run as a write. Connecta routes the maintained write catalog through \`call_destructive_tool\`; newly added tools also fail closed until classified.
161
+ - An \`auth_required\` failure means this connector's Stripe authorization is missing or expired: run \`authorize_connector\` for this connector id, then retry the same call unchanged. A rejected argument or a plan restriction comes back in Stripe's own words instead — read it rather than re-authorizing.
197
162
  ${accountInstructions
198
163
  ? `\n## Account instructions\n\n${accountInstructions}\n`
199
164
  : ""}`;
@@ -218,16 +183,22 @@ export function stripe(id, options) {
218
183
  auth,
219
184
  requireHttps: true,
220
185
  callAdmission: STRIPE_ADMISSION[mode],
221
- usageGuide: usageGuide(mode, purpose, options.instructions),
186
+ usageGuide: {
187
+ content: usageGuide(mode, purpose, options.instructions),
188
+ // Explicit rather than derived: production versus sandbox is the fact an
189
+ // agent must not get wrong, and the derived summary would be the
190
+ // "Mode: … Account purpose: …" line with the operator's prose eating the
191
+ // budget ([#342](https://github.com/zackbart/connecta/issues/342)).
192
+ summary: mode === "production"
193
+ ? "PRODUCTION: writes move real money. Generic api tools, id prefixes, minor units, idempotency."
194
+ : "Sandbox: test data only, never live figures. Generic api tools, id prefixes, minor units.",
195
+ // Not `required`. The four generic tools are the routing decision, and
196
+ // the mode warning already rides the title and description; a guide
197
+ // forced into every call would pay for the same paragraph repeatedly.
198
+ },
222
199
  ...(options.maxResultBytes !== undefined
223
200
  ? { maxResultBytes: options.maxResultBytes }
224
201
  : {}),
225
202
  });
226
- return {
227
- ...connector,
228
- async listTools(ctx) {
229
- return (await connector.listTools(ctx)).map(vettedSafety);
230
- },
231
- };
203
+ return withVettedCatalog(connector, STRIPE_VETTED_CATALOG);
232
204
  }
233
- //# sourceMappingURL=stripe.js.map
@@ -1,4 +1,5 @@
1
- import type { Connector, ConnectorContext, ConnectorStatus, KVStorage, Logger, ToolDef } from "./types.js";
1
+ import type { CatalogDriftReport, Connector, ConnectorContext, ConnectorStatus, KVStorage, Logger, ToolDef } from "./types.js";
2
+ import { type CatalogDriftActivityContext } from "./activity.js";
2
3
  import { type CredentialVault } from "./credentials.js";
3
4
  import { type CallAdmissionPermit, type ConnectorCallAdmissionSnapshot } from "./call-admission.js";
4
5
  /**
@@ -61,6 +62,12 @@ export interface RegistryOptions {
61
62
  * to the default 50_000.
62
63
  */
63
64
  maxResultBytes?: number;
65
+ /**
66
+ * Where payload-free catalog-drift observations go. Present only when the
67
+ * deployment configured an activity store; drift is reported through
68
+ * connector status either way.
69
+ */
70
+ catalogDriftActivity?: Omit<CatalogDriftActivityContext, "logger">;
64
71
  }
65
72
  export type ConnectorOperationOptions = Pick<ConnectorContext, "signal" | "timeoutMs">;
66
73
  /**
@@ -121,6 +128,8 @@ export declare class Registry implements RegistryView {
121
128
  private readonly requestCatalogLoads;
122
129
  /** Deployment-wide observations — every call, whatever view made it. */
123
130
  private readonly health;
131
+ /** Last drift counts reported to activity, per connector, in this runtime. */
132
+ private readonly reportedDrift;
124
133
  private readonly ttlMs;
125
134
  private readonly staleMs;
126
135
  private readonly persistToolCatalog;
@@ -152,6 +161,30 @@ export declare class Registry implements RegistryView {
152
161
  }): Promise<CallAdmissionPermit>;
153
162
  /** Payload-free aggregate state for the open health endpoint. */
154
163
  callAdmissionSnapshot(): Record<string, ConnectorCallAdmissionSnapshot>;
164
+ /**
165
+ * Payload-free drift counts for the open health endpoint, so `connecta
166
+ * doctor` can report a stale allowlist without asking any downstream
167
+ * anything. Only connectors that ship a vetted manifest *and* have already
168
+ * served a refresh *in this runtime* appear — a process or isolate that has
169
+ * answered no catalog request yet honestly reports nothing, and drift is not
170
+ * persisted the way the catalog itself is.
171
+ *
172
+ * Every report is rebuilt by {@link boundedCatalogDrift} on the way out:
173
+ * `Connector.catalogDrift()` is the open plugin seam, and this snapshot is
174
+ * serialized into an unauthenticated response.
175
+ */
176
+ catalogDriftSnapshot(): Record<string, CatalogDriftReport>;
177
+ /**
178
+ * Turn the observation a refresh just took into at most one activity event.
179
+ *
180
+ * Emitted on change rather than on every refresh: an identical report every
181
+ * TTL is a heartbeat, not news, and the current counts are already on
182
+ * connector status. A first observation that is clean is not an event
183
+ * either — nothing moved — but a later return to clean is, because "the
184
+ * drift is gone" is exactly what an operator watching the timeline is
185
+ * waiting for.
186
+ */
187
+ private observeCatalogDrift;
155
188
  /** Reject queued/future downstream admission; active permits release safely. */
156
189
  closeCallAdmission(): void;
157
190
  /**
@@ -216,4 +249,3 @@ export declare class Registry implements RegistryView {
216
249
  /** Drop both in-memory and persisted tool catalogs. */
217
250
  invalidateStored(id: string): Promise<void>;
218
251
  }
219
- //# sourceMappingURL=registry.d.ts.map
package/dist/registry.js CHANGED
@@ -1,6 +1,8 @@
1
+ import { recordCatalogDriftActivity, } from "./activity.js";
1
2
  import { storedCredentialShape, } from "./credentials.js";
2
3
  import { ConnectorCallError } from "./errors.js";
3
4
  import { ConnectorCallAdmissionController, } from "./call-admission.js";
5
+ import { boundedCatalogDrift } from "./catalog-drift.js";
4
6
  import { fingerprintSerializedCatalog, snapshotCatalog, } from "./catalog-fingerprint.js";
5
7
  import { MAX_CATALOG_CHUNK_BYTES, MAX_CATALOG_TOOLS, MAX_SERIALIZED_CATALOG_BYTES, } from "./catalog-limits.js";
6
8
  import { mapSettledWithConcurrency } from "./concurrency.js";
@@ -122,6 +124,8 @@ export class Registry {
122
124
  requestCatalogLoads = new WeakMap();
123
125
  /** Deployment-wide observations — every call, whatever view made it. */
124
126
  health = new HealthLog();
127
+ /** Last drift counts reported to activity, per connector, in this runtime. */
128
+ reportedDrift = new Map();
125
129
  ttlMs;
126
130
  staleMs;
127
131
  persistToolCatalog;
@@ -247,6 +251,68 @@ export class Registry {
247
251
  admission.snapshot(),
248
252
  ]));
249
253
  }
254
+ /**
255
+ * Payload-free drift counts for the open health endpoint, so `connecta
256
+ * doctor` can report a stale allowlist without asking any downstream
257
+ * anything. Only connectors that ship a vetted manifest *and* have already
258
+ * served a refresh *in this runtime* appear — a process or isolate that has
259
+ * answered no catalog request yet honestly reports nothing, and drift is not
260
+ * persisted the way the catalog itself is.
261
+ *
262
+ * Every report is rebuilt by {@link boundedCatalogDrift} on the way out:
263
+ * `Connector.catalogDrift()` is the open plugin seam, and this snapshot is
264
+ * serialized into an unauthenticated response.
265
+ */
266
+ catalogDriftSnapshot() {
267
+ const snapshot = {};
268
+ for (const connector of this.connectors.values()) {
269
+ const report = boundedCatalogDrift(connector.catalogDrift?.());
270
+ if (report)
271
+ snapshot[connector.id] = report;
272
+ }
273
+ return snapshot;
274
+ }
275
+ /**
276
+ * Turn the observation a refresh just took into at most one activity event.
277
+ *
278
+ * Emitted on change rather than on every refresh: an identical report every
279
+ * TTL is a heartbeat, not news, and the current counts are already on
280
+ * connector status. A first observation that is clean is not an event
281
+ * either — nothing moved — but a later return to clean is, because "the
282
+ * drift is gone" is exactly what an operator watching the timeline is
283
+ * waiting for.
284
+ */
285
+ observeCatalogDrift(connector) {
286
+ const report = boundedCatalogDrift(connector.catalogDrift?.());
287
+ if (!report)
288
+ return;
289
+ const previous = this.reportedDrift.get(connector.id);
290
+ // Bounded counts, so a seam returning NaN cannot make every refresh look
291
+ // like a change and emit an event per refresh forever.
292
+ const counts = {
293
+ unclassifiedTools: report.unclassifiedTools,
294
+ unservedTools: report.unservedTools,
295
+ annotationConflicts: report.annotationConflicts,
296
+ schemaChanges: report.schemaChanges,
297
+ };
298
+ const unchanged = previous !== undefined &&
299
+ previous.unclassifiedTools === counts.unclassifiedTools &&
300
+ previous.unservedTools === counts.unservedTools &&
301
+ previous.annotationConflicts === counts.annotationConflicts &&
302
+ previous.schemaChanges === counts.schemaChanges;
303
+ if (unchanged)
304
+ return;
305
+ const clean = counts.unclassifiedTools === 0 &&
306
+ counts.unservedTools === 0 &&
307
+ counts.annotationConflicts === 0 &&
308
+ counts.schemaChanges === 0;
309
+ this.reportedDrift.set(connector.id, counts);
310
+ if (previous === undefined && clean)
311
+ return;
312
+ recordCatalogDriftActivity(this.opts.catalogDriftActivity
313
+ ? { ...this.opts.catalogDriftActivity, logger: this.opts.logger }
314
+ : undefined, { connectorId: connector.id, ...counts });
315
+ }
250
316
  /** Reject queued/future downstream admission; active permits release safely. */
251
317
  closeCallAdmission() {
252
318
  for (const admission of this.callAdmission.values())
@@ -535,6 +601,10 @@ export class Registry {
535
601
  return connector.staticTools;
536
602
  const generation = this.catalogGeneration(id);
537
603
  const tools = await connector.listTools(this.contextFor(id, baseUrl, requestScope, callOptions));
604
+ // The listing a maintained proxy just served is also the only catalog
605
+ // comparison connecta ever makes. It rides this refresh whether or not the
606
+ // result reaches a cache, because what drifted drifted.
607
+ this.observeCatalogDrift(connector);
538
608
  // The caller that began this refresh may still use its result, but a
539
609
  // credential/OAuth change that landed while listTools was in flight means
540
610
  // the listing must not enter either shared cache layer.
@@ -719,20 +789,31 @@ export class Registry {
719
789
  if (!connector)
720
790
  return { state: "error", message: "Unknown connector" };
721
791
  const ctx = this.contextFor(id, baseUrl, requestScope, callOptions);
792
+ // Whatever the state turns out to be, it carries the drift the last
793
+ // refresh saw. Reading it is a lookup, not a probe: a connector that has
794
+ // listed nothing yet reports nothing, and status never lists on its own to
795
+ // make the field appear.
796
+ // The report is rebuilt rather than spread through: what the seam returned
797
+ // is third-party output, and status is read by the operator UI and copied
798
+ // into responses.
799
+ const withDrift = (status) => {
800
+ const report = boundedCatalogDrift(connector.catalogDrift?.());
801
+ return report ? { ...status, catalogDrift: report } : status;
802
+ };
722
803
  if (connector.status) {
723
804
  try {
724
- return await connector.status(ctx);
805
+ return withDrift(await connector.status(ctx));
725
806
  }
726
807
  catch (err) {
727
- return { state: "error", message: msg(err) };
808
+ return withDrift({ state: "error", message: msg(err) });
728
809
  }
729
810
  }
730
811
  try {
731
812
  await this.getTools(id, baseUrl, requestScope, callOptions);
732
- return { state: "ok" };
813
+ return withDrift({ state: "ok" });
733
814
  }
734
815
  catch (err) {
735
- return { state: "error", message: msg(err) };
816
+ return withDrift({ state: "error", message: msg(err) });
736
817
  }
737
818
  }
738
819
  markCatalogInvalid(id) {
@@ -763,4 +844,3 @@ export class Registry {
763
844
  await this.deleteStoredCatalog(id);
764
845
  }
765
846
  }
766
- //# sourceMappingURL=registry.js.map
@@ -1,3 +1,2 @@
1
1
  /** Fail loudly when JavaScript callers pass the retired audience-scoping keys. */
2
2
  export declare function assertNoRetiredToolkitOptions(source: string, options: object): void;
3
- //# sourceMappingURL=retired-toolkits.d.ts.map
@@ -6,4 +6,3 @@ export function assertNoRetiredToolkitOptions(source, options) {
6
6
  throw new Error(`${source} options \`toolkits\` and \`unscoped\` were removed in issue ` +
7
7
  "#178. Deploy one connecta instance per audience instead; see ethos.md.");
8
8
  }
9
- //# sourceMappingURL=retired-toolkits.js.map
@@ -4,4 +4,3 @@ import { type RouteContext } from "./shared.js";
4
4
  * is deliberately never an administrator credential and cannot reach here.
5
5
  */
6
6
  export declare function routeAccessTokens(context: RouteContext): Promise<Response | null>;
7
- //# sourceMappingURL=access-tokens.d.ts.map
@@ -81,4 +81,3 @@ export async function routeAccessTokens(context) {
81
81
  return privateJson({ error: msg(error) }, { status: 400 });
82
82
  }
83
83
  }
84
- //# sourceMappingURL=access-tokens.js.map
@@ -1,3 +1,2 @@
1
1
  import { type RouteContext } from "./shared.js";
2
2
  export declare function routeActivity(context: RouteContext): Promise<Response | null>;
3
- //# sourceMappingURL=activity.d.ts.map
@@ -167,4 +167,3 @@ export async function routeActivity(context) {
167
167
  return privateJson({ error: "activity history is temporarily unavailable" }, { status: 503 });
168
168
  }
169
169
  }
170
- //# sourceMappingURL=activity.js.map
@@ -1,3 +1,2 @@
1
1
  import { type RouteContext } from "./shared.js";
2
2
  export declare function routeCredentials(context: RouteContext): Promise<Response | null>;
3
- //# sourceMappingURL=credentials.d.ts.map
@@ -167,4 +167,3 @@ export async function routeCredentials(context) {
167
167
  }
168
168
  return handleCredentialRequest(context, connectorId, match[2]);
169
169
  }
170
- //# sourceMappingURL=credentials.js.map
@@ -5,4 +5,3 @@ export declare const MCP_CORS_HEADERS: {
5
5
  "Access-Control-Allow-Headers": string;
6
6
  };
7
7
  export declare function createMcpRoute(opts: ServerOptions): (context: RouteContext) => Promise<Response | null>;
8
- //# sourceMappingURL=mcp.d.ts.map
@@ -338,4 +338,3 @@ export function createMcpRoute(opts) {
338
338
  }
339
339
  };
340
340
  }
341
- //# sourceMappingURL=mcp.js.map
@@ -1,4 +1,3 @@
1
1
  import { type RouteContext } from "./shared.js";
2
2
  export declare function routeOAuthManagement(context: RouteContext): Promise<Response | null>;
3
3
  export declare function routeOAuthCallback(context: RouteContext): Promise<Response | null>;
4
- //# sourceMappingURL=oauth.d.ts.map
@@ -260,4 +260,3 @@ export async function routeOAuthCallback(context) {
260
260
  return html(`Authorization failed: ${msg(err)}`, 500, opts.branding);
261
261
  }
262
262
  }
263
- //# sourceMappingURL=oauth.js.map
@@ -28,6 +28,8 @@ export interface ServerOptions {
28
28
  maxEmittedBlocks?: number;
29
29
  /** Required sandbox backing the execute_code meta-tool. */
30
30
  executor: Executor;
31
+ /** Sanitized identity of the configured sandbox, when it has one. */
32
+ executorName?: string;
31
33
  /** Global FIFO boundary for all non-preflight `/mcp` requests. */
32
34
  requestAdmission: AdmissionController;
33
35
  /** Encrypted connector-credential storage backing the Credentials page. */
@@ -80,4 +82,3 @@ export declare function authorizeUiAdmin(request: Request, baseUrl: string, auth
80
82
  }>;
81
83
  export declare function isSameOrigin(request: Request, baseUrl: string): boolean;
82
84
  export declare function withSecurityHeaders(response: Response, requestUrl: URL, path: string): Response;
83
- //# sourceMappingURL=shared.d.ts.map
@@ -137,4 +137,3 @@ export function withSecurityHeaders(response, requestUrl, path) {
137
137
  headers,
138
138
  });
139
139
  }
140
- //# sourceMappingURL=shared.js.map
@@ -1,3 +1,2 @@
1
1
  import { type RouteContext } from "./shared.js";
2
2
  export declare function routeUi(context: RouteContext): Promise<Response | null>;
3
- //# sourceMappingURL=ui.d.ts.map
package/dist/routes/ui.js CHANGED
@@ -121,4 +121,3 @@ export async function routeUi(context) {
121
121
  eligibleClerkOperator ? opts.credentialVault : undefined, Boolean(opts.activity?.list), credentialManagement, defer, eligibleClerkOperator, opts.discoveryConcurrency, accessTokenManagement);
122
122
  return privateJson(data);
123
123
  }
124
- //# sourceMappingURL=ui.js.map
package/dist/server.d.ts CHANGED
@@ -8,4 +8,3 @@ export type { ServerOptions } from "./routes/shared.js";
8
8
  * wrapper is applied to every response.
9
9
  */
10
10
  export declare function createFetchHandler(opts: ServerOptions): (request: Request, runtimeContext?: RuntimeExecutionContext) => Promise<Response>;
11
- //# sourceMappingURL=server.d.ts.map
package/dist/server.js CHANGED
@@ -103,6 +103,17 @@ export function createFetchHandler(opts) {
103
103
  status: "ok",
104
104
  connectors: registry.listConnectors().length,
105
105
  server: opts.serverInfo,
106
+ // Which sandbox, not how it is tuned: `connecta doctor` reports the
107
+ // executor it just exercised rather than assuming one, and a
108
+ // deployment whose executor identifies as nothing omits the key
109
+ // instead of inviting a guess (#368).
110
+ ...(opts.executorName !== undefined
111
+ ? { executor: { name: opts.executorName } }
112
+ : {}),
113
+ // Counts only, from refreshes that already happened — the endpoint
114
+ // asks no downstream anything, and `connecta doctor` reads it to
115
+ // report a stale allowlist without a probe of its own (#343).
116
+ catalogDrift: registry.catalogDriftSnapshot(),
106
117
  admission: {
107
118
  policy: "global-fifo",
108
119
  requests: opts.requestAdmission.snapshot(),
@@ -158,4 +169,3 @@ export function createFetchHandler(opts) {
158
169
  return withSecurityHeaders(await route(), url, path);
159
170
  };
160
171
  }
161
- //# sourceMappingURL=server.js.map
package/dist/skills.d.ts CHANGED
@@ -38,4 +38,3 @@ export type SkillLookup = {
38
38
  * silent fallback to the generic guide.
39
39
  */
40
40
  export declare function resolveSkill(name: string, connectors: readonly Connector[]): SkillLookup;
41
- //# sourceMappingURL=skills.d.ts.map
package/dist/skills.js CHANGED
@@ -234,4 +234,3 @@ export function resolveSkill(name, connectors) {
234
234
  message: `Unknown skill "${name}". Available skills: ${available()}.`,
235
235
  };
236
236
  }
237
- //# sourceMappingURL=skills.js.map
@@ -9,4 +9,3 @@ export interface FileStorageOptions {
9
9
  * subpath so the main entry stays Workers-clean.
10
10
  */
11
11
  export declare function fileStorage(path: string, opts?: FileStorageOptions): KVStorage;
12
- //# sourceMappingURL=file.d.ts.map
@@ -101,4 +101,3 @@ export function fileStorage(path, opts = {}) {
101
101
  },
102
102
  };
103
103
  }
104
- //# sourceMappingURL=file.js.map
@@ -1,4 +1,3 @@
1
1
  import type { KVStorage } from "../types.js";
2
2
  /** In-memory KV store with expiry. The default for dev and Node. */
3
3
  export declare function memoryStorage(): KVStorage;
4
- //# sourceMappingURL=memory.d.ts.map
@@ -36,4 +36,3 @@ export function memoryStorage() {
36
36
  },
37
37
  };
38
38
  }
39
- //# sourceMappingURL=memory.js.map
package/dist/timeout.d.ts CHANGED
@@ -18,4 +18,3 @@ export declare function withTimeout<T>(promise: Promise<T>, ms: number, label: s
18
18
  * any in-flight work that honors the signal.
19
19
  */
20
20
  export declare function withAbortableTimeout<T>(operation: (signal: AbortSignal) => Promise<T>, ms: number, label: string): Promise<T>;
21
- //# sourceMappingURL=timeout.d.ts.map
package/dist/timeout.js CHANGED
@@ -63,4 +63,3 @@ export function withAbortableTimeout(operation, ms, label) {
63
63
  });
64
64
  });
65
65
  }
66
- //# sourceMappingURL=timeout.js.map
@@ -7,4 +7,3 @@ import type { ToolDef } from "./types.js";
7
7
  * approval-visible call path.
8
8
  */
9
9
  export declare function isExplicitlyReadOnly(definition: ToolDef): boolean;
10
- //# sourceMappingURL=tool-safety.d.ts.map
@@ -9,4 +9,3 @@ export function isExplicitlyReadOnly(definition) {
9
9
  return (definition.annotations?.readOnlyHint === true &&
10
10
  definition.annotations?.destructiveHint !== true);
11
11
  }
12
- //# sourceMappingURL=tool-safety.js.map
package/dist/types.d.ts CHANGED
@@ -159,11 +159,40 @@ export interface ConnectorContext {
159
159
  timeoutMs?: number;
160
160
  }
161
161
  type ConnectorStatusState = "ok" | "auth_required" | "error";
162
+ /**
163
+ * How far a downstream catalog has moved away from the manifest a release
164
+ * reviewed. Four numbers and nothing else: names, schemas, and prose stay out
165
+ * of every surface this rides on, so a drift report can never become a payload
166
+ * ([#343](https://github.com/zackbart/connecta/issues/343)).
167
+ */
168
+ export interface CatalogDriftCounts {
169
+ /** Live tools no release classified. Each one fails closed at call time. */
170
+ unclassifiedTools: number;
171
+ /** Classified names this catalog no longer serves — plan gating included. */
172
+ unservedTools: number;
173
+ /** Explicit downstream annotations that contradict a vetted verdict. */
174
+ annotationConflicts: number;
175
+ /** Tools whose reviewed schema digest no longer matches what arrived. */
176
+ schemaChanges: number;
177
+ }
178
+ /** One drift observation, taken while serving a catalog refresh. */
179
+ export interface CatalogDriftReport extends CatalogDriftCounts {
180
+ /** When the observation was taken; never when a probe was scheduled. */
181
+ observedAt: string;
182
+ }
162
183
  export interface ConnectorStatus {
163
184
  state: ConnectorStatusState;
164
185
  /** When state === "auth_required", the URL the operator should open. */
165
186
  authorizationUrl?: string;
166
187
  message?: string;
188
+ /**
189
+ * Drift observed the last time this connector served a catalog refresh *in
190
+ * this runtime*. Absent until one has happened — status reports what a
191
+ * refresh saw, and never asks a downstream a question of its own. The
192
+ * observation is not persisted the way the catalog is, so absence means this
193
+ * isolate or process has seen nothing, not that nothing drifted.
194
+ */
195
+ catalogDrift?: CatalogDriftReport;
167
196
  }
168
197
  /** The whole plugin contract — the one open seam. */
169
198
  export interface Connector {
@@ -212,6 +241,15 @@ export interface Connector {
212
241
  * fetched lazily over the network and are not known at construction time.
213
242
  */
214
243
  staticTools?: ToolDef[];
244
+ /**
245
+ * Optional: the drift this connector saw the last time it listed tools,
246
+ * or undefined when it has not listed any yet. Implemented by maintained
247
+ * hosted-MCP proxies, which compare the live catalog with the manifest a
248
+ * release reviewed *while* serving a refresh the deployment already asked
249
+ * for. It is a getter over an observation, never a probe: calling it makes
250
+ * no request, touches no credential, and returns counts only.
251
+ */
252
+ catalogDrift?(): CatalogDriftReport | undefined;
215
253
  listTools(ctx: ConnectorContext): Promise<ToolDef[]>;
216
254
  callTool(name: string, args: unknown, ctx: ConnectorContext): Promise<unknown>;
217
255
  /**
@@ -313,6 +351,13 @@ export interface ExecutorProvider {
313
351
  * NEVER back this with an unsandboxed eval — the code is untrusted.
314
352
  */
315
353
  export interface Executor {
354
+ /**
355
+ * What `/health` and `connecta doctor` call this sandbox. Optional, and
356
+ * sanitized and bounded before it is reported. A class-shaped executor gets
357
+ * its constructor name for free, but that is runtime metadata a bundler may
358
+ * rewrite; set this to say the same thing minification-proof.
359
+ */
360
+ readonly name?: string;
316
361
  execute(code: string, providers: ExecutorProvider[]): Promise<ExecuteResult>;
317
362
  /** Release runtime resources. Node's built-in pool implements this. */
318
363
  close?(): void | Promise<void>;
@@ -465,4 +510,3 @@ export interface InboundAuth {
465
510
  authorize(request: Request, baseUrl: string): AuthResult | Promise<AuthResult>;
466
511
  }
467
512
  export {};
468
- //# sourceMappingURL=types.d.ts.map
package/dist/types.js CHANGED
@@ -1,3 +1,2 @@
1
1
  // Core contracts for connecta. Web-API only — no node: imports here.
2
2
  export {};
3
- //# sourceMappingURL=types.js.map
package/dist/ui.d.ts CHANGED
@@ -115,4 +115,3 @@ export declare function buildUiData(registry: Registry, baseUrl: string, serverI
115
115
  * and activity data arrives only through the authenticated `/ui/*` APIs.
116
116
  */
117
117
  export declare function renderUiHtml(uiAuth?: UiAuthConfig, mcpUrl?: string, branding?: ConnectaBranding, nonce?: string, page?: OperatorPage): string;
118
- //# sourceMappingURL=ui.d.ts.map