@zackbart/connecta 0.28.0 → 0.29.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 (320) hide show
  1. package/CHANGELOG.md +961 -5
  2. package/README.md +62 -39
  3. package/bin/connecta.mjs +110 -139
  4. package/bin/meta-tool-names.d.mts +2 -0
  5. package/bin/meta-tool-names.mjs +9 -0
  6. package/bin/version.mjs +3 -0
  7. package/dist/access-tokens.js +53 -63
  8. package/dist/activity-request.js +8 -0
  9. package/dist/activity.d.ts +76 -42
  10. package/dist/activity.js +110 -42
  11. package/dist/auth/clerk-sdk/client.d.ts +65 -0
  12. package/dist/auth/clerk-sdk/client.js +5 -0
  13. package/dist/auth/clerk-sdk/generated.js +1845 -0
  14. package/dist/auth/clerk-transport.js +19 -0
  15. package/dist/auth/clerk.d.ts +17 -7
  16. package/dist/auth/clerk.js +189 -107
  17. package/dist/auth/cloudflare-access.js +25 -26
  18. package/dist/auth/downstream-client-metadata.d.ts +29 -0
  19. package/dist/auth/downstream-client-metadata.js +133 -0
  20. package/dist/auth/downstream-oauth.js +1632 -1509
  21. package/dist/auth/downstream-revocation.js +106 -0
  22. package/dist/auth/oauth-token-response.js +231 -0
  23. package/dist/auth/oauth-v2-migration.js +116 -0
  24. package/dist/auth/static-oauth.js +526 -0
  25. package/dist/auth-elicitation.js +283 -0
  26. package/dist/branding.d.ts +8 -16
  27. package/dist/branding.js +26 -59
  28. package/dist/byte-read-response.js +39 -0
  29. package/dist/call-admission.js +12 -16
  30. package/dist/catalog-cache.js +739 -0
  31. package/dist/catalog-drift.d.ts +50 -15
  32. package/dist/catalog-drift.js +365 -128
  33. package/dist/catalog-fingerprint.js +2 -4
  34. package/dist/catalog-freshness.js +13 -0
  35. package/dist/catalog-limits.js +2 -2
  36. package/dist/catalog-service.js +368 -224
  37. package/dist/catalog.js +43 -84
  38. package/dist/concurrency.js +3 -4
  39. package/dist/config-defaults.d.ts +39 -0
  40. package/dist/config-defaults.js +46 -0
  41. package/dist/config-schema.d.ts +181 -0
  42. package/dist/config-schema.js +435 -0
  43. package/dist/config-value-sources.js +102 -0
  44. package/dist/config.d.ts +631 -0
  45. package/dist/config.js +503 -0
  46. package/dist/connector-access.d.ts +1 -0
  47. package/dist/connector-access.js +13 -15
  48. package/dist/connector-caller.d.ts +8 -0
  49. package/dist/connector-caller.js +15 -6
  50. package/dist/connector-scope.js +1 -1
  51. package/dist/connectors/api-connector.d.ts +220 -0
  52. package/dist/connectors/api-connector.js +214 -0
  53. package/dist/connectors/api.d.ts +8 -71
  54. package/dist/connectors/api.js +13 -99
  55. package/dist/connectors/guarded-fetch.d.ts +144 -0
  56. package/dist/connectors/guarded-fetch.js +108 -25
  57. package/dist/connectors/negotiation-cache.js +46 -0
  58. package/dist/connectors/option-shapes.js +27 -0
  59. package/dist/connectors/remote-mcp.d.ts +30 -4
  60. package/dist/connectors/remote-mcp.js +1780 -351
  61. package/dist/connectors/resource-uri.js +335 -0
  62. package/dist/credential-contract.d.ts +10 -0
  63. package/dist/credential-rules.js +1 -3
  64. package/dist/credential-url.js +108 -0
  65. package/dist/credentials.d.ts +6 -1
  66. package/dist/credentials.js +27 -18
  67. package/dist/d1.d.ts +130 -0
  68. package/dist/d1.js +290 -0
  69. package/dist/describe-config.d.ts +165 -0
  70. package/dist/describe-config.js +315 -0
  71. package/dist/described.js +106 -0
  72. package/dist/downstream-input-context.js +119 -0
  73. package/dist/downstream-input.js +323 -0
  74. package/dist/errors.d.ts +97 -20
  75. package/dist/errors.js +158 -80
  76. package/dist/execute.js +453 -305
  77. package/dist/executor-admission.d.ts +1 -0
  78. package/dist/executor-admission.js +11 -15
  79. package/dist/executor-contract.d.ts +20 -0
  80. package/dist/executor-contract.js +48 -0
  81. package/dist/executor-result.js +24 -9
  82. package/dist/executors/quickjs-child.js +3 -4
  83. package/dist/executors/quickjs-runtime.js +147 -59
  84. package/dist/executors/quickjs.js +29 -35
  85. package/dist/favicon.js +1 -2
  86. package/dist/fix-prompt.js +1 -3
  87. package/dist/guest-runtime.js +188 -0
  88. package/dist/guest-types.d.ts +176 -0
  89. package/dist/guest-types.js +1 -0
  90. package/dist/html-security.js +24 -0
  91. package/dist/identity.js +1 -3
  92. package/dist/inbound-credential.js +52 -0
  93. package/dist/index.d.ts +25 -257
  94. package/dist/index.js +65 -478
  95. package/dist/invocation-auth.js +69 -0
  96. package/dist/invocation.js +230 -73
  97. package/dist/json-schema.d.ts +1 -1
  98. package/dist/mcp-client-context.js +35 -0
  99. package/dist/mcp-result.js +11 -7
  100. package/dist/meta-output.js +76 -0
  101. package/dist/meta-tool-names.d.ts +2 -0
  102. package/dist/meta-tool-names.js +3 -0
  103. package/dist/meta-tools.js +285 -209
  104. package/dist/module-contracts.d.ts +8 -23
  105. package/dist/node.d.ts +0 -2
  106. package/dist/node.js +2 -2
  107. package/dist/oauth-callback-outcome.js +1 -3
  108. package/dist/oauth-handoff.js +117 -0
  109. package/dist/oauth-partition.js +17 -0
  110. package/dist/oauth-sealing.js +20 -0
  111. package/dist/operator-record.d.ts +137 -0
  112. package/dist/operator-record.js +420 -0
  113. package/dist/operator-ui/assets.js +31 -0
  114. package/dist/operator-ui/contract.d.ts +72 -0
  115. package/dist/operator-ui/contract.js +1 -0
  116. package/dist/operator-ui/fix-prompts.d.ts +18 -0
  117. package/dist/operator-ui/generated.js +5 -4
  118. package/dist/operator-ui/model.d.ts +12 -87
  119. package/dist/operator-ui/model.js +2 -9
  120. package/dist/operator-ui/setup-commands.js +1 -3
  121. package/dist/operator-ui/view.d.ts +323 -0
  122. package/dist/operator-ui/view.js +62 -189
  123. package/dist/page-styles.js +2 -3
  124. package/dist/program-source.js +14 -2
  125. package/dist/{exempt-writes.js → program-writes.js} +55 -18
  126. package/dist/provider.d.ts +142 -0
  127. package/dist/provider.js +187 -0
  128. package/dist/providers/_shared/google/result-size.js +57 -0
  129. package/dist/providers/_shared/google/service-account.d.ts +58 -0
  130. package/dist/providers/_shared/google/service-account.js +500 -0
  131. package/dist/providers/_shared/google/workspace.d.ts +276 -0
  132. package/dist/providers/_shared/google/workspace.js +518 -0
  133. package/dist/providers/basecamp/index.d.ts +43 -0
  134. package/dist/providers/basecamp/index.js +997 -0
  135. package/dist/providers/basecamp/skill.generated.js +9 -0
  136. package/dist/providers/breeze/index.d.ts +34 -0
  137. package/dist/providers/breeze/index.js +1446 -0
  138. package/dist/providers/breeze/skill.generated.js +9 -0
  139. package/dist/providers/ccb/index.d.ts +103 -0
  140. package/dist/providers/ccb/index.js +1725 -0
  141. package/dist/providers/ccb/skill.generated.js +9 -0
  142. package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
  143. package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
  144. package/dist/providers/cloudflare/skill.generated.js +10 -0
  145. package/dist/providers/docs/index.d.ts +54 -0
  146. package/dist/providers/docs/index.js +1237 -0
  147. package/dist/providers/docs/skill.generated.js +9 -0
  148. package/dist/providers/drive/index.d.ts +53 -0
  149. package/dist/providers/drive/index.js +1523 -0
  150. package/dist/providers/drive/skill.generated.js +9 -0
  151. package/dist/providers/forms/index.d.ts +54 -0
  152. package/dist/providers/forms/index.js +1217 -0
  153. package/dist/providers/forms/skill.generated.js +11 -0
  154. package/dist/providers/github/auth.d.ts +32 -0
  155. package/dist/providers/github/auth.js +361 -0
  156. package/dist/providers/github/hosted.js +218 -0
  157. package/dist/providers/github/index.d.ts +13 -0
  158. package/dist/providers/github/index.js +140 -0
  159. package/dist/providers/github/key.js +100 -0
  160. package/dist/providers/github/rest.js +321 -0
  161. package/dist/providers/github/scope.d.ts +29 -0
  162. package/dist/providers/github/scope.js +124 -0
  163. package/dist/providers/github/skill.generated.js +8 -0
  164. package/dist/providers/gmail/index.d.ts +51 -0
  165. package/dist/providers/gmail/index.js +1436 -0
  166. package/dist/providers/gmail/skill.generated.js +9 -0
  167. package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
  168. package/dist/providers/linear/index.js +352 -0
  169. package/dist/providers/linear/skill.generated.js +8 -0
  170. package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
  171. package/dist/providers/mixpanel/index.js +416 -0
  172. package/dist/providers/mixpanel/skill.generated.js +9 -0
  173. package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
  174. package/dist/providers/{notion.js → notion/index.js} +226 -239
  175. package/dist/providers/notion/skill.generated.js +10 -0
  176. package/dist/providers/overflow/index.d.ts +60 -0
  177. package/dist/providers/overflow/index.js +1535 -0
  178. package/dist/providers/overflow/skill.generated.js +8 -0
  179. package/dist/providers/planning-center/index.d.ts +59 -0
  180. package/dist/providers/planning-center/index.js +2199 -0
  181. package/dist/providers/planning-center/skill.generated.js +10 -0
  182. package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
  183. package/dist/providers/revenuecat/index.js +557 -0
  184. package/dist/providers/revenuecat/skill.generated.js +11 -0
  185. package/dist/providers/sheets/index.d.ts +54 -0
  186. package/dist/providers/sheets/index.js +1237 -0
  187. package/dist/providers/sheets/skill.generated.js +10 -0
  188. package/dist/providers/slides/index.d.ts +53 -0
  189. package/dist/providers/slides/index.js +2645 -0
  190. package/dist/providers/slides/skill.generated.js +9 -0
  191. package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
  192. package/dist/providers/stripe/index.js +266 -0
  193. package/dist/providers/stripe/skill.generated.js +11 -0
  194. package/dist/providers/tithely/index.d.ts +49 -0
  195. package/dist/providers/tithely/index.js +1003 -0
  196. package/dist/providers/tithely/skill.generated.js +8 -0
  197. package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
  198. package/dist/providers/vercel/index.js +1038 -0
  199. package/dist/providers/vercel/mcp-ownership.js +212 -0
  200. package/dist/providers/vercel/skill.generated.js +11 -0
  201. package/dist/registry.d.ts +108 -171
  202. package/dist/registry.js +513 -925
  203. package/dist/request-state.js +21 -0
  204. package/dist/resource-read.js +100 -0
  205. package/dist/result-shapes.js +17 -49
  206. package/dist/retired-toolkits.js +1 -1
  207. package/dist/routes/access-tokens.js +3 -6
  208. package/dist/routes/activity-context.js +21 -0
  209. package/dist/routes/activity-disclosure.js +40 -0
  210. package/dist/routes/activity.js +59 -21
  211. package/dist/routes/actor-labels.js +3 -50
  212. package/dist/routes/connect.js +221 -0
  213. package/dist/routes/credentials.js +15 -27
  214. package/dist/routes/mcp.js +356 -130
  215. package/dist/routes/oauth-client-metadata.js +15 -0
  216. package/dist/routes/oauth-management.js +45 -107
  217. package/dist/routes/oauth.js +136 -57
  218. package/dist/routes/operator.js +3 -3
  219. package/dist/routes/shared.d.ts +25 -64
  220. package/dist/routes/shared.js +160 -80
  221. package/dist/routes/skills.js +30 -0
  222. package/dist/routes/ui-config.js +225 -0
  223. package/dist/routes/ui-data.js +40 -35
  224. package/dist/routes/ui.js +66 -56
  225. package/dist/runtime/admission.js +4 -2
  226. package/dist/runtime/call-admission.js +3 -1
  227. package/dist/runtime/connector-scope.js +1 -4
  228. package/dist/runtime/run.js +10 -39
  229. package/dist/runtime/services.js +12 -117
  230. package/dist/runtime/shared-read.js +1 -3
  231. package/dist/runtime/storage.js +8 -1
  232. package/dist/sent-secrets.d.ts +52 -0
  233. package/dist/sent-secrets.js +474 -0
  234. package/dist/server.js +28 -71
  235. package/dist/skills.js +406 -174
  236. package/dist/sqlite.d.ts +48 -0
  237. package/dist/sqlite.js +166 -0
  238. package/dist/storage/keys.js +428 -0
  239. package/dist/storage/memory.js +7 -0
  240. package/dist/storage/sql.d.ts +66 -0
  241. package/dist/storage/sql.js +534 -0
  242. package/dist/timeout.js +4 -2
  243. package/dist/tool-name.js +17 -0
  244. package/dist/tool-safety.d.ts +9 -35
  245. package/dist/tool-safety.js +20 -40
  246. package/dist/types.d.ts +320 -54
  247. package/dist/types.js +0 -1
  248. package/dist/ui.d.ts +7 -19
  249. package/dist/ui.js +76 -90
  250. package/dist/url-safety.js +3 -6
  251. package/dist/usage-guide.js +137 -0
  252. package/dist/validate.d.ts +7 -0
  253. package/dist/validate.js +309 -47
  254. package/dist/version.d.ts +1 -7
  255. package/dist/version.js +3 -7
  256. package/dist/worker.d.ts +11 -0
  257. package/dist/worker.js +434 -0
  258. package/documentation/architecture.md +665 -230
  259. package/documentation/auth.md +962 -458
  260. package/documentation/code-mode.md +501 -312
  261. package/documentation/meta-tools.md +449 -200
  262. package/documentation/operator-tests.md +93 -0
  263. package/documentation/provider-migration-0.29.md +60 -0
  264. package/examples/worker/AGENTS.md +34 -12
  265. package/examples/worker/README.md +286 -255
  266. package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
  267. package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
  268. package/examples/worker/src/connecta.config.ts +151 -0
  269. package/examples/worker/src/index.ts +14 -197
  270. package/examples/worker/wrangler.jsonc +15 -35
  271. package/package.json +125 -35
  272. package/templates/node/.dockerignore +1 -2
  273. package/templates/node/.env.example +20 -21
  274. package/templates/node/AGENTS.md +21 -17
  275. package/templates/node/Dockerfile +3 -5
  276. package/templates/node/README.md +133 -58
  277. package/templates/node/docker-compose.yml +11 -12
  278. package/templates/node/package.json +4 -2
  279. package/templates/node/src/connecta.config.ts +119 -0
  280. package/templates/node/src/index.ts +9 -154
  281. package/templates/node/src/provision-token.ts +17 -0
  282. package/AGENTS.md +0 -170
  283. package/dist/artifacts/connector.d.ts +0 -58
  284. package/dist/artifacts/connector.js +0 -730
  285. package/dist/artifacts/document.js +0 -86
  286. package/dist/artifacts/guide.js +0 -140
  287. package/dist/artifacts/html-scan.js +0 -329
  288. package/dist/artifacts/json.js +0 -78
  289. package/dist/artifacts/kv-store.d.ts +0 -20
  290. package/dist/artifacts/kv-store.js +0 -140
  291. package/dist/artifacts/markdown.js +0 -478
  292. package/dist/artifacts/module.d.ts +0 -37
  293. package/dist/artifacts/module.js +0 -66
  294. package/dist/artifacts/operations.d.ts +0 -197
  295. package/dist/artifacts/operations.js +0 -1002
  296. package/dist/artifacts/refresh.d.ts +0 -55
  297. package/dist/artifacts/refresh.js +0 -236
  298. package/dist/artifacts/routes.js +0 -206
  299. package/dist/artifacts/types.d.ts +0 -214
  300. package/dist/artifacts/types.js +0 -22
  301. package/dist/artifacts/validate.d.ts +0 -62
  302. package/dist/artifacts/validate.js +0 -651
  303. package/dist/artifacts.d.ts +0 -6
  304. package/dist/artifacts.js +0 -9
  305. package/dist/auth/bearer.d.ts +0 -11
  306. package/dist/auth/bearer.js +0 -50
  307. package/dist/providers/linear.js +0 -217
  308. package/dist/providers/mixpanel.js +0 -247
  309. package/dist/providers/revenuecat.js +0 -317
  310. package/dist/providers/stripe.js +0 -253
  311. package/dist/providers/vercel.js +0 -1253
  312. package/dist/storage/file.d.ts +0 -15
  313. package/dist/storage/file.js +0 -455
  314. package/ethos.md +0 -93
  315. package/examples/worker/src/cloudflare-kv.ts +0 -43
  316. package/examples/worker/src/d1-activity-row.ts +0 -155
  317. package/examples/worker/src/d1-activity.ts +0 -147
  318. package/examples/worker/src/d1-storage.ts +0 -138
  319. package/examples/worker/src/r2-artifact-blobs.ts +0 -29
  320. package/templates/node/src/file-activity.ts +0 -182
@@ -1,7 +1,6 @@
1
+ import type { CatalogDriftActivityContext } from "./activity.js";
1
2
  import type { CredentialVault } from "./credential-contract.js";
2
- import type { CatalogDriftReport, Connector, ConnectorContext, ConnectorStatus, KVStorage, Logger, ToolDef } from "./types.js";
3
- import { type DeferredWork } from "./connector-scope.js";
4
- import { type CatalogDriftActivityContext } from "./activity.js";
3
+ import type { Connector, ConnectorContext, ConnectorStatus, KVStorage, Logger, ToolDef } from "./types.js";
5
4
  import { type CallAdmissionPermit, type ConnectorCallAdmissionSnapshot } from "./call-admission.js";
6
5
  import { type ConnectorCaller } from "./connector-caller.js";
7
6
  /**
@@ -26,7 +25,7 @@ export declare const MIN_MAX_RESULT_BYTES = 1;
26
25
  /**
27
26
  * The one definition of a usable `maxResultBytes`: a finite whole number of at
28
27
  * least {@link MIN_MAX_RESULT_BYTES} bytes. Shared by all three intake points
29
- * — `calls.maxResultBytes`, the per-connector override, and `get_result`'s
28
+ * — `calls.maxResultBytes`, the per-connector override, and `connecta.result`'s
30
29
  * `maxBytes` argument — so a value that is valid at one is valid at all.
31
30
  *
32
31
  * Everything else is rejected rather than coerced, because each rejected shape
@@ -38,14 +37,17 @@ export declare const MIN_MAX_RESULT_BYTES = 1;
38
37
  export declare function isValidMaxResultBytes(value: number): boolean;
39
38
  /**
40
39
  * Resolve a configured cap against the value it inherits, dropping anything
41
- * `isValidMaxResultBytes` rejects. Operator-facing surfaces pair this with a
42
- * startup warning (see `Registry.checkResultCaps`) so the fallback is never
43
- * silent; the resolution itself stays total so no call site has to cope with
44
- * a broken cap.
40
+ * `isValidMaxResultBytes` rejects. Construction already refuses an unusable
41
+ * cap (`Registry.assertResultCaps`); the resolution stays total so no call
42
+ * site has to cope with a broken one.
45
43
  */
46
44
  export declare function resolveMaxResultBytes(value: number | undefined, inherited: number): number;
47
45
  export interface RegistryOptions {
46
+ publicUrl?: string | undefined;
47
+ oauthClientName?: string | undefined;
48
+ classification?: Readonly<Record<string, Readonly<Record<string, "read" | "write">>>> | undefined;
48
49
  storage: KVStorage;
50
+ catalogStorage?: KVStorage;
49
51
  logger: Logger;
50
52
  credentialVault?: CredentialVault | undefined;
51
53
  credentialUi?: boolean | undefined;
@@ -53,33 +55,22 @@ export interface RegistryOptions {
53
55
  credentialOwner?: string | undefined;
54
56
  /** Internal child registries skip deployment-wide construction warnings. */
55
57
  constructionChecks?: boolean | undefined;
58
+ catalogDriftActivity?: Omit<CatalogDriftActivityContext, "logger"> | undefined;
56
59
  toolCacheTtlSeconds?: number | undefined;
57
- persistToolCatalog?: boolean | undefined;
58
- toolCatalogStaleSeconds?: number | undefined;
60
+ catalogMinTtlSeconds?: number | undefined;
61
+ catalogMaxTtlSeconds?: number | undefined;
59
62
  /**
60
- * Cap on inline result size before truncation + get_result paging. Must be a
61
- * whole number of bytes >= 1; anything else warns at startup and falls back
62
- * to the default 24_000.
63
+ * Cap on inline result size before truncation + connecta.result paging. Must be a
64
+ * whole number of bytes >= 1; anything else throws at construction. Default
65
+ * 24_000.
63
66
  */
64
67
  maxResultBytes?: number | undefined;
65
68
  results?: {
66
69
  maxStashBytes?: number;
67
70
  maxStashEntries?: number;
68
71
  } | undefined;
69
- /**
70
- * Where payload-free catalog-drift observations go. Present only when the
71
- * deployment configured an activity store; drift is reported through
72
- * connector status either way.
73
- */
74
- catalogDriftActivity?: Omit<CatalogDriftActivityContext, "logger"> | undefined;
75
- }
76
- export type ConnectorOperationOptions = Pick<ConnectorContext, "signal" | "timeoutMs">;
77
- /** Agent-only catalog behavior. This never enters a ConnectorContext. */
78
- export interface CatalogReadOptions {
79
- defer?: DeferredWork;
80
- /** Fresh deadline for a deferred refresh; never an inbound signal. */
81
- refreshTimeoutMs: number;
82
72
  }
73
+ export type ConnectorOperationOptions = Pick<ConnectorContext, "signal" | "timeoutMs" | "defer">;
83
74
  /**
84
75
  * The registry surface a per-connection MCP server consumes: every meta-tool
85
76
  * (`src/meta-tools.ts`) and the `execute_code` sandbox bridge (`src/execute.ts`)
@@ -89,17 +80,28 @@ export interface CatalogReadOptions {
89
80
  * consume registry behavior without depending on the concrete implementation
90
81
  * or its construction-only methods.
91
82
  */
83
+ /** Host-admitted identity and endpoint bindings for result paging. */
84
+ export interface ResultIdentity {
85
+ subject: string | null;
86
+ principal: string | null;
87
+ endpoint: string;
88
+ origin: string | null;
89
+ }
92
90
  export interface RegistryView {
93
91
  credentialUiAvailable(): boolean;
94
92
  /** Deployment-wide result-size cap threaded to the meta-tools. */
95
93
  readonly maxResultBytes: number;
96
94
  listConnectors(): Connector[];
95
+ /** Whole-connector permission for downstream skill files, which have no tool grants. */
96
+ canReadConnectorSkills(id: string): boolean;
97
97
  getConnector(id: string): Connector | undefined;
98
+ /** Only whole-connector grants authorize resource reads. */
99
+ getResourceConnector(id: string): Connector | undefined;
98
100
  resolveAddress(address: string): {
99
101
  connector: Connector;
100
102
  toolName: string;
101
103
  } | null;
102
- getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, readOptions?: CatalogReadOptions): Promise<ToolDef[]>;
104
+ getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ToolDef[]>;
103
105
  contextFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): ConnectorContext;
104
106
  /** Acquire the connector's shared downstream-call permit. */
105
107
  admitCall(id: string, input: {
@@ -108,18 +110,23 @@ export interface RegistryView {
108
110
  signal?: AbortSignal;
109
111
  }): Promise<CallAdmissionPermit>;
110
112
  resultsStorage(): KVStorage;
111
- /** Reserve runtime-wide capacity before writing a paging envelope's chunks. */
112
- stashResult(key: string, chunks: readonly string[], ttlSeconds: number): Promise<boolean>;
113
+ resultIdentity(): ResultIdentity;
114
+ /** Recheck live auth/grants and pool admission before exposing stored data. */
115
+ recheckResultAccess(address: string, classification: "read" | "write", signal?: AbortSignal): Promise<boolean>;
116
+ /** Reserve deployment-wide capacity before writing a paging envelope's chunks. */
117
+ stashResult(id: string, chunks: readonly string[], ttlSeconds: number): Promise<boolean>;
113
118
  /** Local declared-vs-stored credential mismatch, with no downstream I/O. */
114
119
  credentialDriftFor(id: string): Promise<string | undefined>;
115
120
  /** Value-free shape learned from successful calls, never a provider declaration. */
116
121
  observedOutputSchema(connectorId: string, definition: ToolDef): ToolDef["outputSchema"] | undefined;
117
122
  /** Passively learn one successful unwrapped result; failures stay isolated. */
118
123
  observeOutputShape(connectorId: string, definition: ToolDef, value: unknown): void;
124
+ /** Age of the complete cached catalog; null for static or unobserved catalogs. */
125
+ catalogAgeMs(id: string): number | null;
119
126
  statusFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ConnectorStatus>;
120
127
  invalidateStored(id: string): Promise<void>;
121
- /** Bind returned OAuth state to this view's personal storage partition. */
122
- bindOAuthHandoff(id: string, authorizationUrl: string): Promise<void>;
128
+ /** Bind returned OAuth state to its initiating user for either owner scope. */
129
+ bindOAuthHandoff(id: string, authorizationUrl: string, principalKey?: string): Promise<void>;
123
130
  }
124
131
  /**
125
132
  * Connector id → the only tool names this view may see on it. A connector
@@ -133,42 +140,37 @@ export interface RegistryScope {
133
140
  guardedToolAccess?: ToolAccess;
134
141
  subjectKey?: string;
135
142
  principalKey?: string;
143
+ endpoint?: string;
144
+ origin?: string | null;
145
+ currentResultAccess?: (address: string, classification: "read" | "write", signal?: AbortSignal) => Promise<boolean>;
136
146
  /** The admitted caller, readable only by built-in connectors; see connector-caller.ts. */
137
147
  caller?: ConnectorCaller;
138
148
  }
139
149
  /**
140
- * Holds the connector set, resolves addresses, and caches per-connector tool
141
- * lists in memory with a TTL. Connector failures are isolated: a broken
150
+ * Holds the connector set, resolves addresses, and coalesces tool listings
151
+ * within one request. Remote MCP clients own persisted response caching. Connector failures are isolated: a broken
142
152
  * connector surfaces status "error"; the rest keep working.
143
153
  */
144
154
  export declare class Registry implements RegistryView {
145
155
  private readonly opts;
146
156
  private readonly connectors;
147
157
  private readonly callAdmission;
148
- private readonly cache;
149
- private readonly invalidated;
150
- /** Per-connector epoch preventing a pre-invalidation refresh from publishing. */
151
- private readonly catalogGenerations;
152
- /** Serialize persisted catalog set/delete operations within this isolate. */
153
- private readonly catalogMutations;
154
- /** Same-request cold loads share one read without retaining the request.
155
- * See documentation/architecture.md#the-two-lifetimes. */
158
+ /** Coalesce listings only within one request and authorization partition. */
156
159
  private readonly requestCatalogLoads;
157
- /** One live refresh per connector across agent and operator requests. */
158
- private readonly catalogRefreshes;
160
+ private readonly catalogObservedAt;
159
161
  /** Last payload-free agent catalog access in this runtime. */
160
162
  private readonly catalogAccess;
161
- /** Last drift counts reported to activity, per connector, in this runtime. */
162
- private readonly reportedDrift;
163
+ /** Count-only intake findings, including catalogs loaded from storage. */
164
+ private droppedToolNames;
165
+ /**
166
+ * Schema digest verification per reviewed facts array. Only the registry's
167
+ * own deep-frozen arrays are keys, so an entry stays true while they live.
168
+ */
169
+ private readonly verifiedFacts;
163
170
  private readonly observedOutputSchemas;
164
- private readonly ttlMs;
165
- private readonly staleMs;
166
- private readonly persistToolCatalog;
167
171
  /** Result-size guard cap threaded to the meta-tools. */
168
172
  readonly maxResultBytes: number;
169
- /** Only keys, byte counts, and expiry survive requests; never write promises. */
170
- private readonly resultStash;
171
- private resultStashBytes;
173
+ private readonly classification;
172
174
  private readonly configuredConnectors;
173
175
  private readonly personalRegistries;
174
176
  private readonly oauthPartition;
@@ -187,22 +189,20 @@ export declare class Registry implements RegistryView {
187
189
  * cannot check it, and a catalog that drifts later cannot widen a grant.
188
190
  */
189
191
  noteAbsentGrant(connectorId: string, toolName: string): void;
190
- private oauthHandoffKey;
191
192
  storeOAuthHandoff(connectorId: string, state: string, principalKey: string): Promise<void>;
192
193
  oauthCallbackView(connectorId: string, state: string | null): Promise<{
193
194
  registry: RegistryView;
194
195
  principalKey?: string;
195
196
  } | null>;
196
- clearOAuthHandoff(connectorId: string, state: string | null): Promise<void>;
197
+ consumeOAuthHandoff(connectorId: string, state: string | null, principalKey: string): Promise<boolean>;
197
198
  /**
198
- * Warn once per unusable result cap, at construction time — the same
199
- * "runs fine but is surely unintended" channel as the insecure-config
200
- * warnings in `createConnecta`. A rejected cap can't be honoured, and
201
- * honouring it *approximately* is exactly the inversion issue #32 is about,
202
- * so the value is dropped in favour of what it inherits and the operator is
203
- * told which one is actually in force.
199
+ * Refuse an unusable result cap at construction, like every other
200
+ * structural mistake (INV-11). A rejected cap can't be honoured, and
201
+ * honouring it *approximately* is exactly the inversion issue #32 is about;
202
+ * falling back with a warning let a deployment boot on a value nobody
203
+ * chose.
204
204
  */
205
- private checkResultCaps;
205
+ private assertResultCaps;
206
206
  /**
207
207
  * Warn once per convention violation at construction time. Static only —
208
208
  * never calls listTools() (remote connectors are lazy/network); tool-level
@@ -211,7 +211,9 @@ export declare class Registry implements RegistryView {
211
211
  private checkConventions;
212
212
  listConnectors(): Connector[];
213
213
  getConnector(id: string): Connector | undefined;
214
- contextFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): ConnectorContext;
214
+ getResourceConnector(id: string): Connector | undefined;
215
+ canReadConnectorSkills(id: string): boolean;
216
+ contextFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, scope?: RegistryScope): ConnectorContext;
215
217
  admitCall(id: string, input: {
216
218
  toolName: string;
217
219
  args: unknown;
@@ -220,48 +222,39 @@ export declare class Registry implements RegistryView {
220
222
  /** Connector totals across root and personal controllers; health removes ids. */
221
223
  callAdmissionSnapshot(): Record<string, ConnectorCallAdmissionSnapshot>;
222
224
  /**
223
- * Payload-free drift counts for the open health endpoint, so `connecta
224
- * doctor` can report a stale allowlist without asking any downstream
225
- * anything. Only connectors that ship a vetted manifest *and* have already
226
- * served a refresh *in this runtime* appear — a process or isolate that has
227
- * answered no catalog request yet honestly reports nothing, and drift is not
228
- * persisted the way the catalog itself is.
229
- *
230
- * Every report is rebuilt by {@link boundedCatalogDrift} on the way out:
231
- * `Connector.catalogDrift()` is the open plugin seam, and this snapshot is
232
- * serialized into an unauthenticated response.
225
+ * The drift a connector last showed in this runtime: the registry's own
226
+ * observation against a connector's `classification`, otherwise whatever
227
+ * the connector's `catalogDrift()` seam reports, bounded either way.
233
228
  */
234
- catalogDriftSnapshot(): Record<string, CatalogDriftReport>;
235
- /**
236
- * Turn the observation a refresh just took into at most one activity event.
237
- *
238
- * Emitted on change rather than on every refresh: an identical report every
239
- * TTL is a heartbeat, not news, and the current counts are already on
240
- * connector status. A first observation that is clean is not an event
241
- * either — nothing moved — but a later return to clean is, because "the
242
- * drift is gone" is exactly what an operator watching the timeline is
243
- * waiting for.
244
- */
245
- private observeCatalogDrift;
229
+ private catalogDriftOf;
246
230
  /** Reject queued/future downstream admission; active permits release safely. */
247
231
  closeCallAdmission(): void;
248
232
  /**
249
- * Reserve capacity and write one ASCII paging envelope in this runtime.
233
+ * Reserve capacity and write one ASCII paging envelope.
234
+ *
235
+ * `chunks[n]` lands on `resultKeys.chunk(id, n)` inside `partition` — the
236
+ * layout connecta.result reads back, so a page fetches only the chunks it covers
237
+ * instead of the whole stored result (issue #540). Chunking is a read-cost
238
+ * decision, not a capacity one: however many keys an envelope occupies, it
239
+ * is one stash entry charged its total ASCII length.
250
240
  *
251
- * `chunks[0]` lands on `<prefix><key>` and `chunks[n]` on `<prefix><key>#<n>`
252
- * — the layout get_result reads back, so a page fetches only the chunks it
253
- * covers instead of the whole stored result (issue #540). Chunking is a
254
- * read-cost decision, not a capacity one: however many keys an envelope
255
- * occupies, it is one stash entry charged its total ASCII length.
241
+ * The bounds are the deployment's, not this isolate's. Every charge is a
242
+ * row in one ledger record in storage, booked by compare-and-set before any
243
+ * chunk is written, so every isolate and process sharing the store sees the
244
+ * same entries and bytes. A charge leaves the ledger just after its
245
+ * result's deadline, which every chunk's TTL ends by; the storage TTL
246
+ * reclaims the rows themselves.
256
247
  */
257
- stashResult(key: string, chunks: readonly string[], ttlSeconds: number, prefix?: string): Promise<boolean>;
248
+ stashResult(id: string, chunks: readonly string[], ttlSeconds: number, partition?: string): Promise<boolean>;
258
249
  /**
259
- * Storage namespaced to the meta-tool result store (`results:` prefix), kept
260
- * separate from any connector's `conn:<id>:` namespace. Backs get_result.
250
+ * Storage namespaced to the root result partition, kept separate from any
251
+ * connector's namespace. Backs connecta.result.
261
252
  */
253
+ resultIdentity(): ResultIdentity;
254
+ recheckResultAccess(_address: string, _classification: "read" | "write", _signal?: AbortSignal): Promise<boolean>;
262
255
  resultsStorage(): KVStorage;
263
256
  credentialUiAvailable(): boolean;
264
- bindOAuthHandoff(): Promise<void>;
257
+ bindOAuthHandoff(id: string, authorizationUrl: string, principalKey?: string): Promise<void>;
265
258
  observedOutputSchema(connectorId: string, definition: ToolDef): ToolDef["outputSchema"] | undefined;
266
259
  observeOutputShape(connectorId: string, definition: ToolDef, value: unknown): void;
267
260
  /** Resolve "<connectorId>.<toolName>" → connector + tool name. */
@@ -269,89 +262,33 @@ export declare class Registry implements RegistryView {
269
262
  connector: Connector;
270
263
  toolName: string;
271
264
  } | null;
272
- private catalogKey;
273
- private catalogChunkKey;
274
- private validCatalogTools;
275
- private validCatalogManifest;
276
- private parseCatalogManifest;
277
- private splitCatalogChunks;
278
- private readCatalog;
279
- private storeCatalog;
280
- private deleteCatalog;
281
- private catalogGeneration;
282
- private advanceCatalogGeneration;
265
+ /** Compare only the fingerprints accepted in this exact cache partition. */
266
+ private recordCatalogDrift;
267
+ private loadDownstreamTools;
268
+ /** The served catalog excludes control-character names; raw caches stay complete. */
269
+ private acceptToolNames;
270
+ /** Observe intake once, never while serving an older cached listing. */
271
+ private observeDroppedToolNames;
283
272
  /**
284
- * Keep this isolate's writes and invalidations ordered. Without the queue, an
285
- * old refresh can finish its storage.set after a credential change deletes
286
- * the catalog and resurrect the pre-change listing.
273
+ * One connector's catalog as served: the cached downstream facts, classified
274
+ * on every read by the connector's `classification`, into fresh objects.
275
+ * Safety is derived here and nowhere else, so no cache layer can carry a
276
+ * stale verdict — from an older review, an older release, or a stale
277
+ * fallback — and nothing a caller or decorator does to a served tool reaches
278
+ * the next read.
287
279
  */
288
- private enqueueCatalogMutation;
289
- private refreshToolsWithContext;
290
- /**
291
- * Whether a refresh may still enter the shared cache layers: its generation
292
- * is current, and the flight it runs in has been neither abandoned nor
293
- * outlived its bound. Asked at each publication point, since listing and
294
- * snapshotting both yield, and a late result must never overwrite the one a
295
- * fresh attempt published in the meantime.
296
- */
297
- private mayPublish;
298
- /**
299
- * Publish one shared refresh before starting its connector work. The first
300
- * caller owns the scope and signal, and the flight lives `boundMs` from now
301
- * at most; every later caller joins the result without gaining access to
302
- * that context. A flight found past its bound is abandoned here, and this
303
- * caller starts the fresh attempt.
304
- */
305
- private startCatalogRefresh;
306
- /**
307
- * Give up on a flight that outlived its bound. Later readers start a fresh
308
- * attempt, its joiners are told to, and nothing its owner lists from now on
309
- * reaches a cache. The owner's work is left alone: it belongs to another
310
- * request, which nothing here may reach into, and it can no longer publish.
311
- */
312
- private abandonCatalogRefresh;
313
- /**
314
- * Wait on another caller's flight, no longer than its bound. Succeeds with
315
- * its tools, or with `undefined` when it will not answer for this caller —
316
- * past its bound, when this waiter abandons it, or failed for its owner
317
- * alone — so the caller makes a fresh attempt. The timer is this waiter's
318
- * own: on workerd it is what keeps a request that waits on another alive,
319
- * and bounded.
320
- */
321
- private joinCatalogRefresh;
322
- /** Force a live listTools refresh and replace both catalog cache layers. */
323
- private refreshTools;
324
- private observeCatalogAccess;
325
- /**
326
- * Start or join one shared refresh. A newly deferred task owns its scope,
327
- * deadline, and teardown; no inbound signal or request scope crosses into it.
328
- */
329
- private deferCatalogRefresh;
330
- /** Cached listTools with in-memory + persisted serializable catalog layers. */
331
280
  private loadTools;
332
- /**
333
- * Coalesce one connector's catalog traversal inside one inbound request. The
334
- * WeakMap neither roots the request scope nor lets its connector context
335
- * escape into another request; settled entries are also removed eagerly.
336
- *
337
- * The read owns its signal, and each caller waits under its own: one that
338
- * is cancelled while others wait leaves with its own failure, and the read
339
- * is cancelled only when every caller has gone (src/runtime/shared-read.ts).
340
- *
341
- * The deployment-wide flight below this layer coalesces the actual live
342
- * refresh across requests. Its owner's context governs the listing, and its
343
- * owner's deadline bounds it; later callers join only its result, never its
344
- * request scope, and a failure that was the owner's alone sends them to a
345
- * fresh attempt rather than to them.
346
- */
347
- getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, readOptions?: CatalogReadOptions): Promise<ToolDef[]>;
281
+ private publishUnreviewedTool;
282
+ /** Construction-only view for the secret-free static config description. */
283
+ describeStaticTools(id: string): ToolDef[] | undefined;
284
+ private validateClassification;
285
+ getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, scope?: RegistryScope): Promise<ToolDef[]>;
348
286
  credentialDriftFor(id: string): Promise<string | undefined>;
287
+ /** Age of a complete cache entry; reads never refresh it. */
288
+ catalogAgeMs(id: string): number | null;
349
289
  /** Best-effort connector status for the operator UI. */
350
- statusFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ConnectorStatus>;
351
- private markCatalogInvalid;
352
- private deleteStoredCatalog;
353
- /** Drop a connector's cached tool list (e.g. after auth completes). */
290
+ statusFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, scope?: RegistryScope): Promise<ConnectorStatus>;
291
+ /** Rotate the storage generation; in-flight old readers cannot republish it. */
354
292
  invalidate(id: string): void;
355
- /** Drop both in-memory and persisted tool catalogs. */
356
293
  invalidateStored(id: string): Promise<void>;
357
294
  }