@zackbart/connecta 0.15.1 → 0.16.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 (332) hide show
  1. package/AGENTS.md +28 -15
  2. package/CHANGELOG.md +466 -0
  3. package/README.md +19 -4
  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 +0 -1
  27. package/dist/catalog.d.ts +0 -1
  28. package/dist/catalog.js +0 -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 +0 -1
  42. package/dist/errors.js +0 -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 +250 -276
  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 +58 -8
  129. package/documentation/code-mode.md +12 -12
  130. package/documentation/connector-guides.md +172 -5
  131. package/documentation/connectors.md +89 -0
  132. package/documentation/linear.md +20 -2
  133. package/documentation/mcp-ui-design.md +2 -2
  134. package/documentation/mixpanel.md +42 -9
  135. package/documentation/notion.md +16 -0
  136. package/documentation/operations.md +283 -5
  137. package/documentation/operator-ui.md +120 -5
  138. package/documentation/provider-audit.md +160 -0
  139. package/documentation/provider-conventions.md +631 -0
  140. package/documentation/request-admission.md +167 -5
  141. package/documentation/rich-output-design.md +1 -2
  142. package/documentation/stripe.md +15 -0
  143. package/ethos.md +13 -8
  144. package/examples/worker/README.md +96 -12
  145. package/examples/worker/src/index.ts +46 -1
  146. package/examples/worker/wrangler.jsonc +14 -1
  147. package/package.json +4 -5
  148. package/templates/node/.dockerignore +10 -0
  149. package/templates/node/.env.example +40 -3
  150. package/templates/node/AGENTS.md +11 -1
  151. package/templates/node/Dockerfile +49 -0
  152. package/templates/node/README.md +117 -2
  153. package/templates/node/docker-compose.yml +39 -0
  154. package/templates/node/package.json +1 -1
  155. package/templates/node/src/file-activity.ts +182 -0
  156. package/templates/node/src/index.ts +80 -4
  157. package/assets/connecta-clay-hero.png +0 -0
  158. package/dist/access-tokens.d.ts.map +0 -1
  159. package/dist/access-tokens.js.map +0 -1
  160. package/dist/activity.d.ts.map +0 -1
  161. package/dist/activity.js.map +0 -1
  162. package/dist/apps-shell.d.ts.map +0 -1
  163. package/dist/apps-shell.js.map +0 -1
  164. package/dist/auth/bearer.d.ts.map +0 -1
  165. package/dist/auth/bearer.js.map +0 -1
  166. package/dist/auth/clerk.d.ts.map +0 -1
  167. package/dist/auth/clerk.js.map +0 -1
  168. package/dist/auth/downstream-oauth.d.ts.map +0 -1
  169. package/dist/auth/downstream-oauth.js.map +0 -1
  170. package/dist/call-admission.d.ts.map +0 -1
  171. package/dist/call-admission.js.map +0 -1
  172. package/dist/catalog-fingerprint.d.ts.map +0 -1
  173. package/dist/catalog-fingerprint.js.map +0 -1
  174. package/dist/catalog-limits.d.ts.map +0 -1
  175. package/dist/catalog-limits.js.map +0 -1
  176. package/dist/catalog-service.d.ts.map +0 -1
  177. package/dist/catalog-service.js.map +0 -1
  178. package/dist/catalog.d.ts.map +0 -1
  179. package/dist/catalog.js.map +0 -1
  180. package/dist/concurrency.d.ts.map +0 -1
  181. package/dist/concurrency.js.map +0 -1
  182. package/dist/connector-scope.d.ts.map +0 -1
  183. package/dist/connector-scope.js.map +0 -1
  184. package/dist/connectors/api.d.ts.map +0 -1
  185. package/dist/connectors/api.js.map +0 -1
  186. package/dist/connectors/remote-mcp.d.ts.map +0 -1
  187. package/dist/connectors/remote-mcp.js.map +0 -1
  188. package/dist/credentials.d.ts.map +0 -1
  189. package/dist/credentials.js.map +0 -1
  190. package/dist/errors.d.ts.map +0 -1
  191. package/dist/errors.js.map +0 -1
  192. package/dist/execute.d.ts.map +0 -1
  193. package/dist/execute.js.map +0 -1
  194. package/dist/executor-admission.d.ts.map +0 -1
  195. package/dist/executor-admission.js.map +0 -1
  196. package/dist/executor-result.d.ts.map +0 -1
  197. package/dist/executor-result.js.map +0 -1
  198. package/dist/executors/quickjs-child.d.ts.map +0 -1
  199. package/dist/executors/quickjs-child.js.map +0 -1
  200. package/dist/executors/quickjs-protocol.d.ts.map +0 -1
  201. package/dist/executors/quickjs-protocol.js.map +0 -1
  202. package/dist/executors/quickjs-runtime.d.ts.map +0 -1
  203. package/dist/executors/quickjs-runtime.js.map +0 -1
  204. package/dist/executors/quickjs.d.ts.map +0 -1
  205. package/dist/executors/quickjs.js.map +0 -1
  206. package/dist/favicon.d.ts.map +0 -1
  207. package/dist/favicon.js.map +0 -1
  208. package/dist/index.d.ts.map +0 -1
  209. package/dist/index.js.map +0 -1
  210. package/dist/invocation.d.ts.map +0 -1
  211. package/dist/invocation.js.map +0 -1
  212. package/dist/json-schema.d.ts.map +0 -1
  213. package/dist/json-schema.js.map +0 -1
  214. package/dist/mcp-result.d.ts.map +0 -1
  215. package/dist/mcp-result.js.map +0 -1
  216. package/dist/meta-tools.d.ts.map +0 -1
  217. package/dist/meta-tools.js.map +0 -1
  218. package/dist/node.d.ts.map +0 -1
  219. package/dist/node.js.map +0 -1
  220. package/dist/operator-ui/generated.d.ts.map +0 -1
  221. package/dist/operator-ui/generated.js.map +0 -1
  222. package/dist/operator-ui/model.d.ts.map +0 -1
  223. package/dist/operator-ui/model.js.map +0 -1
  224. package/dist/providers/cloudflare.d.ts.map +0 -1
  225. package/dist/providers/cloudflare.js.map +0 -1
  226. package/dist/providers/linear.d.ts.map +0 -1
  227. package/dist/providers/linear.js.map +0 -1
  228. package/dist/providers/mixpanel.d.ts.map +0 -1
  229. package/dist/providers/mixpanel.js.map +0 -1
  230. package/dist/providers/notion.d.ts.map +0 -1
  231. package/dist/providers/notion.js.map +0 -1
  232. package/dist/providers/stripe.d.ts.map +0 -1
  233. package/dist/providers/stripe.js.map +0 -1
  234. package/dist/registry.d.ts.map +0 -1
  235. package/dist/registry.js.map +0 -1
  236. package/dist/retired-toolkits.d.ts.map +0 -1
  237. package/dist/retired-toolkits.js.map +0 -1
  238. package/dist/routes/access-tokens.d.ts.map +0 -1
  239. package/dist/routes/access-tokens.js.map +0 -1
  240. package/dist/routes/activity.d.ts.map +0 -1
  241. package/dist/routes/activity.js.map +0 -1
  242. package/dist/routes/credentials.d.ts.map +0 -1
  243. package/dist/routes/credentials.js.map +0 -1
  244. package/dist/routes/mcp.d.ts.map +0 -1
  245. package/dist/routes/mcp.js.map +0 -1
  246. package/dist/routes/oauth.d.ts.map +0 -1
  247. package/dist/routes/oauth.js.map +0 -1
  248. package/dist/routes/shared.d.ts.map +0 -1
  249. package/dist/routes/shared.js.map +0 -1
  250. package/dist/routes/ui.d.ts.map +0 -1
  251. package/dist/routes/ui.js.map +0 -1
  252. package/dist/server.d.ts.map +0 -1
  253. package/dist/server.js.map +0 -1
  254. package/dist/skills.d.ts.map +0 -1
  255. package/dist/skills.js.map +0 -1
  256. package/dist/storage/file.d.ts.map +0 -1
  257. package/dist/storage/file.js.map +0 -1
  258. package/dist/storage/memory.d.ts.map +0 -1
  259. package/dist/storage/memory.js.map +0 -1
  260. package/dist/timeout.d.ts.map +0 -1
  261. package/dist/timeout.js.map +0 -1
  262. package/dist/tool-safety.d.ts.map +0 -1
  263. package/dist/tool-safety.js.map +0 -1
  264. package/dist/types.d.ts.map +0 -1
  265. package/dist/types.js.map +0 -1
  266. package/dist/ui.d.ts.map +0 -1
  267. package/dist/ui.js.map +0 -1
  268. package/dist/validate.d.ts.map +0 -1
  269. package/dist/validate.js.map +0 -1
  270. package/dist/version.d.ts.map +0 -1
  271. package/dist/version.js.map +0 -1
  272. package/examples/node/README.md +0 -52
  273. package/examples/node/src/index.ts +0 -71
  274. package/src/access-tokens.ts +0 -289
  275. package/src/activity.ts +0 -234
  276. package/src/apps-shell.ts +0 -370
  277. package/src/auth/bearer.ts +0 -61
  278. package/src/auth/clerk.ts +0 -553
  279. package/src/auth/downstream-oauth.ts +0 -575
  280. package/src/call-admission.ts +0 -521
  281. package/src/catalog-fingerprint.ts +0 -52
  282. package/src/catalog-limits.ts +0 -11
  283. package/src/catalog-service.ts +0 -1153
  284. package/src/catalog.ts +0 -790
  285. package/src/concurrency.ts +0 -39
  286. package/src/connector-scope.ts +0 -66
  287. package/src/connectors/api.ts +0 -159
  288. package/src/connectors/remote-mcp.ts +0 -1090
  289. package/src/credentials.ts +0 -428
  290. package/src/errors.ts +0 -364
  291. package/src/execute.ts +0 -1406
  292. package/src/executor-admission.ts +0 -328
  293. package/src/executor-result.ts +0 -107
  294. package/src/executors/quickjs-child.ts +0 -172
  295. package/src/executors/quickjs-protocol.ts +0 -99
  296. package/src/executors/quickjs-runtime.ts +0 -470
  297. package/src/executors/quickjs.ts +0 -776
  298. package/src/favicon.ts +0 -53
  299. package/src/index.ts +0 -666
  300. package/src/invocation.ts +0 -655
  301. package/src/json-schema.ts +0 -11
  302. package/src/mcp-result.ts +0 -43
  303. package/src/meta-tools.ts +0 -1607
  304. package/src/node.ts +0 -206
  305. package/src/operator-ui/browser.css +0 -423
  306. package/src/operator-ui/browser.ts +0 -1281
  307. package/src/operator-ui/generated.ts +0 -4
  308. package/src/operator-ui/model.ts +0 -111
  309. package/src/providers/cloudflare.ts +0 -3999
  310. package/src/providers/linear.ts +0 -302
  311. package/src/providers/mixpanel.ts +0 -229
  312. package/src/providers/notion.ts +0 -1879
  313. package/src/providers/stripe.ts +0 -307
  314. package/src/registry.ts +0 -1085
  315. package/src/retired-toolkits.ts +0 -14
  316. package/src/routes/access-tokens.ts +0 -115
  317. package/src/routes/activity.ts +0 -215
  318. package/src/routes/credentials.ts +0 -254
  319. package/src/routes/mcp.ts +0 -429
  320. package/src/routes/oauth.ts +0 -322
  321. package/src/routes/shared.ts +0 -247
  322. package/src/routes/ui.ts +0 -152
  323. package/src/server.ts +0 -195
  324. package/src/skills.ts +0 -271
  325. package/src/storage/file.ts +0 -123
  326. package/src/storage/memory.ts +0 -44
  327. package/src/timeout.ts +0 -84
  328. package/src/tool-safety.ts +0 -15
  329. package/src/types.ts +0 -523
  330. package/src/ui.ts +0 -744
  331. package/src/validate.ts +0 -387
  332. package/src/version.ts +0 -7
package/AGENTS.md CHANGED
@@ -42,18 +42,21 @@ exports.
42
42
  before building something new; "we already decided not to" is a real answer
43
43
  there, and its removed/provisional verdicts override anything staler.
44
44
  - [`documentation/`](./documentation/) — per-subsystem guides for agents
45
- working on the repo. **Currently stubs**: the old manual (`docs/`) was
46
- retired in the phase-1 docs restructure and each guide is being rewritten as
47
- the ideas settle. Until a guide is filled in, the subsystem's prior manual
48
- text lives in git history (`docs/<name>.md`) consult it there when you need
49
- the old rationale, but treat `ethos.md` as the authority where they disagree.
45
+ working on the repo. All of them are written now
46
+ ([#348](https://github.com/zackbart/connecta/issues/348)); the retired manual
47
+ (`docs/<name>.md`) survives only in git history, which is worth mining for
48
+ rationale a rewrite dropped and worth nothing where it disagrees with
49
+ `ethos.md`. Start with `architecture.md`, then the guide for the subsystem
50
+ you are changing.
50
51
  - [`README.md`](./README.md) — the human-facing overview.
51
52
  - [`templates/node/`](./templates/node/) — the one standalone Node deployment
52
- shape copied by `connecta init`. Keep it small and prescribed; examples may
53
- demonstrate alternatives, but they must not become competing scaffolds.
53
+ shape copied by `connecta init`, Docker-ready rather than Docker-only. Keep
54
+ it small and prescribed. There are exactly two deployment shapes, this one
55
+ and [`examples/worker/`](./examples/worker/); a third scaffold that is a
56
+ diff away from one of them is the shape
57
+ [#344](https://github.com/zackbart/connecta/issues/344) deleted.
54
58
 
55
- **Read `ethos.md` and the subsystem's guide (or its git-history predecessor)
56
- before changing a subsystem.**
59
+ **Read `ethos.md` and the subsystem's guide before changing a subsystem.**
57
60
 
58
61
  ## Deployment setup
59
62
 
@@ -61,9 +64,12 @@ before changing a subsystem.**
61
64
  pins the generated deployment to the CLI package's exact version, restores the
62
65
  template `.gitignore`, and refuses to merge into an existing path.
63
66
  `connecta doctor` verifies a running deployment's health, executor, and exact
64
- seven-tool surface. Setup changes must keep the root README, template, Docker
65
- example, and `scripts/check-package.mjs` smoke aligned; do not add a second
66
- initializer or another “recommended” project shape.
67
+ seven-tool surface. The template carries its own `Dockerfile` and
68
+ `docker-compose.yml`, so the generated project is the container: setup changes
69
+ must keep the root README, the template (source, container files, and README),
70
+ and the `scripts/check-package.mjs` smoke — which builds and runs that
71
+ container when Docker is available — aligned. Do not add a second initializer,
72
+ a second container recipe, or another “recommended” project shape.
67
73
 
68
74
  ## Where new code goes
69
75
 
@@ -91,9 +97,9 @@ in `WORKERS_SUITES`, Node-bound suites in `NODE_ONLY_SUITES` with a reason. The
91
97
  `node` project runs both lists; the `workers` project re-runs the portable list
92
98
  inside workerd. `test/suite-partition.test.ts` walks the directory and fails on
93
99
  an unclassified, double-classified, stale, or reasonless entry. New behavior
94
- also gets a row in the test map in
95
- [`documentation/operations.md`](./documentation/operations.md) once that guide
96
- is rewritten; until then the row waits with the guide.
100
+ also gets a row in the test map in `documentation/operations.md`, which
101
+ classifies every suite — one missing from it is either new and undocumented or
102
+ dead, and neither is a state to leave the repository in.
97
103
 
98
104
  ## Conventions
99
105
 
@@ -109,6 +115,13 @@ is rewritten; until then the row waits with the guide.
109
115
  - **CHANGELOG.** Each release opens with a narrative paragraph — what this
110
116
  release is, what breaks, what a deployment can ignore — then
111
117
  `### Added` / `### Changed` / `### Fixed`.
118
+ - **Provider drift.** Before tagging a release, run `npm run drift:check` with
119
+ local provider credentials exported. It diffs each hosted-MCP catalog against
120
+ its vetted manifest and each hand-written provider's touched endpoints against
121
+ the provider's published OpenAPI document. Findings are read by a human and
122
+ become GitHub issues — no credential goes near CI, and nothing files itself.
123
+ See
124
+ [`documentation/provider-conventions.md`](./documentation/provider-conventions.md#the-maintainer-run-drift-check).
112
125
  - **Releases.** `npm run release:check`, tag `v<version>` matching
113
126
  `package.json` exactly (the publish workflow verifies this and fails
114
127
  otherwise), and publishing fires on GitHub **Release publication**, not on the
package/CHANGELOG.md CHANGED
@@ -2,6 +2,472 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.16.0 — 2026-08-12
6
+
7
+ This is the agent-efficiency refocus. One release, sixteen merges, and a single
8
+ question asked of every tool description, schema, discovery result, and error
9
+ message in the package: what does this cost the model that has to read it?
10
+ Where operator convenience and agent cost disagreed, the agent-facing contract
11
+ won. The work lands on two pillars — excellent curated providers, and a
12
+ footgun-free path for everything else — plus an operator boundary that finally
13
+ describes the surface it guards, exactly two deployment shapes instead of four,
14
+ and an operator UI that is a component app rather than string-built HTML.
15
+
16
+ What breaks, breaks loudly, and mostly at construction rather than at 2 a.m.
17
+ `api()` now requires a `description` and an explicit
18
+ `annotations.readOnlyHint` on every tool and refuses an `inputSchema` it cannot
19
+ compile; `strictValidation` is gone because fail-closed is the only behavior
20
+ left for it to switch. `linear()` requires an explicit `access` mode.
21
+ `mixpanel()` no longer declares a call-admission budget. `cloudflare()` checks
22
+ an overridden `baseUrl` where it is written. The Cloudflare connection ships 52
23
+ named tools instead of 55, having been measured against its own escape hatches
24
+ rather than assumed to beat them. And Cloudflare and Notion now refuse a
25
+ redirect and cap the response they will read, which is visible only to a
26
+ deployment that was downloading something enormous through a tool call. Each
27
+ of those has a one-line migration, spelled out below.
28
+
29
+ A deployment that writes no `api()` connectors and runs none of the five
30
+ prebuilt connections can upgrade without editing anything. Nothing in the core
31
+ runtime surface moved: the seven meta-tools, the executor contract, the storage
32
+ interfaces, the route table, and the wire shapes are where they were. The
33
+ tarball is half the size, the guides are all written, and `connecta init` now
34
+ produces a project that runs under `docker compose up` without becoming a
35
+ second project shape.
36
+
37
+ `api()` stops being forgiving. A hand-written tool now declares what it does
38
+ and whether calling it needs a human, and any `inputSchema` it ships is one
39
+ Connecta can actually enforce — all three checked at construction, where a
40
+ deployment can still refuse to boot, rather than discovered by an agent at
41
+ 2 a.m. The warn-once-then-pass-raw-arguments-through behavior behind an
42
+ unenforceable schema is gone, and with it the `strictValidation` option that
43
+ existed only to turn it off.
44
+
45
+ That construction contract breaks `api()` authors and nobody else. Migration is
46
+ mechanical: give every tool a non-empty `description` and an explicit
47
+ `annotations.readOnlyHint` — `true` for a read, `false` for work that should
48
+ cross `call_destructive_tool` — then delete `strictValidation`, which is now
49
+ the only behavior. A tool that used to ship unannotated becomes
50
+ `readOnlyHint: false`, which is exactly the routing it already got.
51
+ Hosted-MCP proxies are untouched: `remoteMcp()` relays a downstream's names,
52
+ descriptions, schemas, and annotations as they arrive, and an unannotated or
53
+ contradictory downstream tool still fails closed onto `call_destructive_tool`.
54
+ Connecta infers read-only behavior from nothing, anywhere.
55
+
56
+ The maintained Cloudflare connection ships the second break. Its named surface
57
+ was measured against its own escape hatches instead of being assumed to beat
58
+ them, and three tools came out. Every named tool now carries a recorded `keep`,
59
+ `prune`, or `improve` verdict backed by per-tool numbers: catalog tokens, rank
60
+ in a real `search_tools` call for a representative operator request, whether
61
+ classes of argument mistake are refused before the round trip, and whether the
62
+ handler projects Cloudflare's object or hands it back whole. The evidence, the
63
+ tasks, and the reason for every removal — including the one removed for pair
64
+ symmetry rather than for a measured defect — are in
65
+ [`eval/current-version/results/issue-350-evidence.md`](./eval/current-version/results/issue-350-evidence.md).
66
+ **A deployment that calls `set_r2_cors`, `delete_r2_cors`, or `get_r2_metrics`
67
+ has to change.** No capability is lost: `get_r2_cors` still reads a bucket's
68
+ policy, and the usage guide now names the replacement routes —
69
+ `cloudflare_api_mutate` at
70
+ `PUT`/`DELETE /accounts/{accountId}/r2/buckets/{bucketName}/cors`, and
71
+ `cloudflare_api_get` at `/accounts/{accountId}/r2/metrics`. Every other
72
+ Cloudflare tool, argument, projection, and annotation is unchanged.
73
+
74
+ All five maintained prebuilt connections have been audited against the written
75
+ provider conventions, one report per provider, with a verdict for every
76
+ applicable convention. Nineteen misses were found and fixed. Sixteen of them
77
+ were a guide, a title, or a schema description failing to say something the
78
+ implementation already did correctly — the conventions were mostly not asking
79
+ for different behavior, they were asking for the behavior to reach the agent.
80
+
81
+ Three of them did change behavior, and two of those break a deployment:
82
+ `linear()` now requires an `access` mode, and `mixpanel()` no longer declares a
83
+ call-admission budget. Both failures are loud — one at construction, one as an
84
+ absent ceiling an operator can restore in one option. Everything else is a
85
+ smaller catalog, a better summary, and a guide that says what it always meant.
86
+
87
+ Underneath all of that, the two hand-written providers stopped each keeping
88
+ their own copy of the same transport safety machinery. Cloudflare and Notion
89
+ now send every request through one guarded transport that owns URL
90
+ confinement, redirect refusal, bounded response reads, and network-failure
91
+ normalization, and owns no opinion at all about what a status code means.
92
+
93
+ Consolidating it was not free, and three of the differences are visible from
94
+ outside. A 3xx from either provider is refused now rather than followed, which
95
+ is what both used to do by default — a redirect is an instruction to re-send
96
+ the connector's credential to whatever origin `Location` names, and neither
97
+ API has a legitimate one to send. Both providers now cap what they will read,
98
+ at 8 MiB for Cloudflare and 4 MiB for Notion, so a `cloudflare_api_get`
99
+ downloading an R2 object or a Worker script larger than 8 MiB fails instead of
100
+ returning it. And `cloudflare()`'s optional `baseUrl` is checked where it is
101
+ written: a non-loopback plain-http origin, URL-embedded credentials, or a
102
+ query or fragment throws at construction, so a deployment pointed at an http
103
+ proxy stops booting rather than sending it a token.
104
+
105
+ The repository now models exactly the two deployments it actually has: a Node
106
+ one and a Worker one. `connecta init` still copies the same template, but that
107
+ template now carries its own `Dockerfile` and `docker-compose.yml`, so the
108
+ generated project runs from `npm start` locally and from `docker compose up`
109
+ in production without becoming a second project shape. The two near-identical
110
+ Node scaffolds that sat beside it — `examples/node` and `examples/docker`, the
111
+ latter of which built the Connecta repository rather than a consumer project —
112
+ are gone. Existing deployments can ignore all of this; nothing in the package's
113
+ runtime surface moved.
114
+
115
+ The three maintained hosted-MCP connections now notice when the catalog they
116
+ were reviewed against moves. Each ships a vetted manifest — the tool names and
117
+ classifications a release read, plus schema digests once a release records
118
+ them — and compares it with the live listing *inside* a catalog refresh the
119
+ deployment already asked for. Nothing new is requested: no scheduled job, no
120
+ background poll, no credential probe, which is the boundary that keeps this
121
+ from being the proactive liveness checking connecta removed. What comes out is
122
+ four counts — unclassified additions, names no longer served, explicit
123
+ annotation conflicts, schema changes — on connector status, on `/health`, and
124
+ in `connecta doctor`, plus one payload-free activity event per change in those
125
+ counts for stores that implement the new optional `recordCatalogDrift`. The
126
+ observation is per runtime and is not persisted, so status, `/health`, and
127
+ doctor answer for the isolate or process that served the refresh — an empty
128
+ report means that runtime has observed nothing, and the activity event is the
129
+ durable half. A deployment can ignore all of it: an unclassified tool already
130
+ failed closed onto `call_destructive_tool` before anyone counted it.
131
+
132
+ The other half of that story is a command, not a surface. `npm run drift:check`
133
+ is maintainer tooling — it ships nowhere, runs on a laptop before a release, and
134
+ answers the question the runtime counts deliberately cannot: *which* tool moved.
135
+ It diffs each hosted-MCP catalog against the same vetted manifest the connector
136
+ classifies from, using the maintainer's own credential, and it compares the
137
+ handful of endpoints Cloudflare and Notion actually call against those
138
+ providers' published OpenAPI documents — reporting a gone path, a gone method, a
139
+ new deprecation, or a changed contract, and ignoring the two thousand operations
140
+ connecta never touches. No credential goes near CI, nothing is scheduled,
141
+ nothing files itself, and a published specification is drift evidence only: it
142
+ never generates a tool and never becomes a runtime input.
143
+
144
+ Both deployment shapes now carry the operator feature set the operator pages
145
+ were built for. A fresh `connecta init` used to produce a deployment with a
146
+ Credentials page and no vault, a Tokens page and no issuance, and an Activity
147
+ page with nothing behind it — pages for things that deployment could not do.
148
+ The Node template now ships sign-in, vault, tokens, and activity as four
149
+ clearly-marked commented blocks in `src/index.ts`, each one an environment
150
+ variable and an uncommented block away, plus a deployment-owned
151
+ `src/file-activity.ts` that is compiled rather than commented. The Worker
152
+ example wires the first three outright and comments the fourth, which needs a
153
+ D1 database nobody can create for you. Existing deployments can ignore this
154
+ entirely: nothing in the package's runtime surface moved, and both READMEs
155
+ walk through the enablement.
156
+
157
+ Finally, the tarball is half of what it was, and nothing that left it was
158
+ reachable. `exports` resolves only into `dist/`, so the packed `src/` was
159
+ never imported by anything — it was there to back the source and declaration
160
+ maps, and all three went together. Out with them, and out with the 230 KB
161
+ README hero image, which npmjs.com renders from the repository anyway. An
162
+ install unpacks to 1.8 MB instead of 3.8 MB. The code, the types, the CLI, the
163
+ template, the Worker example, and every guide are exactly where they were —
164
+ and there are four more guides than there were mid-release, because the four
165
+ stubs `check:package` had been excluding got written instead.
166
+
167
+ Which is the quiet half of this release. The five prebuilt connections used to
168
+ encode five sets of private judgment about what a good provider surface looks
169
+ like; that judgment is now two written convention sets, H1–H14 for hand-written
170
+ `api()` surfaces and P1–P13 for `remoteMcp()` proxies, each rule carrying its
171
+ reason and the agent cost it reduces. The placeholder guides in
172
+ `documentation/` — which covered, with some irony, the load-bearing subsystems,
173
+ while the newest features had the best docs — are written against the code as
174
+ it is, and none is left. And the ethos bullet that promised
175
+ "observable, never administrable" was retired for one that is true: operator
176
+ routes manage authentication material for capabilities declared in deployment
177
+ configuration, and a suite now snapshots every declared structure and demands
178
+ it back byte-identical after each operator mutation.
179
+
180
+ ### Added
181
+
182
+ - **Two written provider convention sets.**
183
+ [`documentation/provider-conventions.md`](./documentation/provider-conventions.md)
184
+ states H1–H14 for hand-written `api()` surfaces, where Connecta owns every
185
+ name, schema, projection, and error, and P1–P13 for `remoteMcp()` proxies,
186
+ where the downstream owns the catalog and Connecta owns the endpoint,
187
+ credential, classification, guide, and budget. Every convention carries its
188
+ rule, its reason, and which of the four agent costs it reduces — discovery
189
+ tokens, wrong-tool selection, argument retries, result size — and names the
190
+ budgets at which the surface itself starts dropping characters: 160 for a
191
+ tool description in search, 240 in describe, 1,024 bytes per compact schema,
192
+ 120 for a guide summary. A description longer than its budget is written for
193
+ nobody (#339).
194
+ - **The core subsystem guides, written.** `architecture.md`,
195
+ `request-admission.md`, `call-admission.md`, and `operations.md` were
196
+ identical seven-line placeholders pointing at git history; they now describe
197
+ the code as it is — the two lifetimes, the ordered route table and why each position is
198
+ behavior rather than taste, the import-graph purity rule and what it actually
199
+ prevents, both admission pools and why `/mcp` admits before it authenticates,
200
+ and the connector-partitioned downstream policy. `operations.md` also carries
201
+ the test map AGENTS.md had been deferring since the docs restructure: all 61
202
+ suites plus the two browser specs, with each Node-only suite's reason for not
203
+ running in workerd, so "this suite exists" and "this suite is justified" are
204
+ one lookup. `connector-guides.md` gains the general authoring half #339 left
205
+ open, including the `required` flag in full. With no stubs left, the four
206
+ `!documentation/…` negations in `files` went too (#348).
207
+ - **A maintainer-run provider drift check.** `npm run drift:check` diffs the
208
+ live Linear, Stripe, and Mixpanel catalogs against their vetted manifests by
209
+ name — added, no longer served, annotation conflicts, and schema changes — and
210
+ cross-checks its totals against the runtime `detectCatalogDrift()`, because
211
+ two readings of one manifest that disagree mean one of them is lying. Its
212
+ second half compares committed touched-endpoint manifests
213
+ (`scripts/drift/cloudflare-endpoints.json`, `scripts/drift/notion-endpoints.json`:
214
+ method, path, reviewed spec revision, reviewed deprecation, contract digest)
215
+ with each provider's published OpenAPI document, and `--record` refreshes
216
+ them. Deprecation is reported as a transition in either direction, so a
217
+ reviewed one stops being news. A missing credential, an unreachable
218
+ specification, or a `--provider` the selected half does not check stops the
219
+ run and says which one.
220
+ Written up in
221
+ [`documentation/provider-conventions.md`](./documentation/provider-conventions.md#the-maintainer-run-drift-check)
222
+ (#351).
223
+ - **Hosted-provider drift detection at refresh.** Linear, Stripe, and Mixpanel
224
+ each ship a vetted manifest and compare it with the live catalog while
225
+ serving a refresh that was going to happen anyway. `ConnectorStatus` gains
226
+ `catalogDrift` (four counts and the time they were observed), `/health` gains
227
+ the same per connector, `connecta doctor` reports it without failing on it,
228
+ and `ActivitySink` gains an optional `recordCatalogDrift` that receives one
229
+ payload-free event per change in the counts. Both read surfaces report what
230
+ the answering runtime observed — the observation is isolate-local, not
231
+ persisted — and both project the counts rather than echo the connector seam.
232
+ The policy is written up in
233
+ [`documentation/provider-conventions.md`](./documentation/provider-conventions.md#the-runtime-drift-policy)
234
+ (#343).
235
+ - **The Node template is Docker-ready.** `Dockerfile`, `docker-compose.yml`,
236
+ and `.dockerignore` ship with `connecta init`. The image installs
237
+ `@zackbart/connecta` from the registry like any other consumer, runs as the
238
+ non-root `node` user with state on a named volume, probes the always-open
239
+ `/health` route, and keeps Node in the foreground so `compose down` stops it
240
+ promptly. `PUBLIC_URL` and `CONNECTA_STATE_FILE` now configure the generated
241
+ `src/index.ts`, which is what makes one source serve both run paths (#344).
242
+ - **The package smoke exercises the generated container.** `check:package`
243
+ builds and runs the initialized deployment through Compose and points
244
+ `connecta doctor` at it; it fails rather than skips when Docker is missing
245
+ in CI (#344).
246
+ - **A deterministic named-surface measurement lane.**
247
+ `npm --prefix eval/current-version run report:cloudflare-surface` measures the
248
+ maintained Cloudflare connection one tool at a time and writes a JSON and
249
+ Markdown artifact. It needs no model, no network, and no credential: the real
250
+ constructor, schemas, validation path, handlers, and catalog service run, and
251
+ only `fetch` is a probe that records the request (#350).
252
+ - **Five provider audit reports** in
253
+ [`documentation/provider-audit.md`](./documentation/provider-audit.md), with
254
+ a verdict per convention, the fix for every miss, and every accepted
255
+ exception recorded with its argument (#342).
256
+ - **A convention test over the shipped surface.**
257
+ `test/provider-conventions.test.ts` walks both `api()` providers on every run
258
+ and enforces the mechanically checkable bar — naming, description budgets,
259
+ closed schemas described at every depth, compact-render budgets, declared
260
+ outputs, structured guides, and credential tests — so a convention met once
261
+ stays met. The one accepted gap, the undescribed name/value members of
262
+ Cloudflare's escape-hatch request parts, is listed by path in the suite with
263
+ its argument rather than left for a shallower check to miss (#342).
264
+ - **Guide coverage the schemas cannot carry.** Stripe and Mixpanel guides now
265
+ name their id-resolution rules, say the hosted catalog is not a fixed set, and
266
+ give the `auth_required` → `authorize_connector` recovery route. Notion's
267
+ guide states that it deliberately has no raw-REST escape hatch (#342).
268
+ - **A guarded fetch transport for hand-written connectors.** One factory
269
+ supplies the machinery every `api()` HTTP surface was re-deriving: strict
270
+ base-origin and path confinement checked after URL normalization, encoded
271
+ query and JSON body construction, `ctx.signal` propagation, a required
272
+ response-byte ceiling enforced while reading, a flat refusal to follow a
273
+ redirect or to let a request header shadow an authentication one, and an
274
+ unreachable provider normalized to a retryable `unavailable`. Authentication
275
+ and status interpretation stay in provider callbacks — the helper never
276
+ guesses what a 403 means. Cloudflare and Notion both run on it; it is held
277
+ internal this release rather than exported, and
278
+ [`documentation/connectors.md`](./documentation/connectors.md#the-guarded-fetch-transport)
279
+ records why (#341).
280
+ - **The operator feature set in both deployment shapes.** The Node template
281
+ gains commented, documented configuration for Clerk operator sign-in, the
282
+ credential vault, access-token issuance, and payload-free activity, the four
283
+ environment variables they read (passed through Compose and defaulted in the
284
+ Dockerfile so the container works the moment a block is uncommented), and
285
+ `src/file-activity.ts` — a deployment-owned `ActivityStore` that appends one
286
+ JSON line per call and rewrites the log back down to the newest 5,000 once it
287
+ runs a slack window past that, repairing a torn trailing line on the way in
288
+ rather than appending onto it. The Worker example wires the credential vault
289
+ to a new `CREDENTIAL_ENCRYPTION_KEY` secret beside the Clerk and access-token
290
+ configuration it already had, and carries the D1 activity wiring and its
291
+ binding as commented lines rather than as README-only instructions. Both
292
+ READMEs walk through enabling each half — including the part neither vault
293
+ can supply, a connector that declares a `credential` slot, which is what puts
294
+ the Credentials page in the nav — and both say why `connecta doctor` reports
295
+ none of it: doctor holds a bearer, and a client key does not get to learn a
296
+ deployment's configuration topology (#345).
297
+
298
+ ### Changed
299
+
300
+ - **The operator boundary is stated as authentication material.** "Observable,
301
+ never administrable" had stopped describing the surface — operator routes
302
+ rotate credentials, issue and revoke access tokens, and drive downstream
303
+ OAuth, each under its own accepted decision. The ethos bullet, the invariant,
304
+ and a new decisions row now say the true thing: operator routes may manage
305
+ authentication material for capabilities *declared* in deployment
306
+ configuration, and may never change the connector set, the declared tool
307
+ catalog or annotations, requested OAuth scopes, admission policy,
308
+ authorization rules, or caller tool scope. The word "declared" is doing work
309
+ twice over — a broader-scoped replacement token widens downstream reach and
310
+ no browser page can honestly promise otherwise, and a remote MCP server's
311
+ catalog is discovered rather than declared, so storing a credential can take
312
+ an `mcp()` connector from no tools to N. That is discovery arriving, which is
313
+ exactly why those routes call `invalidateStored()`.
314
+ `test/operator-boundary.test.ts` snapshots every declared structure, drives
315
+ each operator mutation route against both a static and a re-listing
316
+ connector, and requires the snapshot back byte-identical; a second case
317
+ proves the snapshot can fail. No runtime behavior changed (#338).
318
+ - **The operator UI is a component app.** The hand-written DOM layer is gone,
319
+ replaced by a small Preact app compiled by the same esbuild step and inlined
320
+ into a shell that is now a mount point rather than a page. Nothing builds
321
+ HTML from strings any more, so the escaping every rendered value used to
322
+ depend on is structural; the served markup is identical on all four pages and
323
+ still carries no operator data. Credential, token, and OAuth flows gained
324
+ deliberate loading, error, empty, and success states — a failed save keeps
325
+ the form and what was typed in it, a failed list offers a retry, and an empty
326
+ collection says what would fill it. Each connector card also reads the drift
327
+ the last catalog refresh saw (#343) as four category counts, with `clean`,
328
+ `warning`, and "not observed in this runtime" kept as three distinct answers
329
+ — no tool name, schema, or payload rides that panel. Preact rides in as a
330
+ `devDependency` inlined into the committed bundle and never reaches a
331
+ deployment's dependency tree (#347).
332
+
333
+ - **`api()` enforces its construction contract.** Every tool requires a
334
+ non-empty `description` and an explicit boolean `annotations.readOnlyHint`;
335
+ a missing or non-boolean classification throws with the address that needs
336
+ fixing. The classification is never inferred from a tool name, description,
337
+ schema, HTTP method, or the other annotations (#340).
338
+ - **An unenforceable `inputSchema` fails at construction.** A schema the
339
+ validator cannot compile throws when the connector is built, whether or not
340
+ `validateArgs` is on — opting out of enforcement is not opting out of the
341
+ schema being real. A schema that only reveals itself on first use, such as an
342
+ unresolvable `$ref`, now fails that call as non-retryable `invalid_args`
343
+ instead of forwarding raw arguments to the handler (#340).
344
+ - **`linear()` requires `access`.** There is no safe default between Linear's
345
+ two endpoints: `"read-write"` hands out writes nobody asked for, and
346
+ `"read-only"` breaks a writing deployment at Linear, at runtime, where no
347
+ agent can repair it. Construction now throws naming both options. Add
348
+ `access: "read-write"` to keep an existing deployment's behavior (#342).
349
+ - **`mixpanel()` declares no call-admission budget.** The old hardcoded 600
350
+ calls per hour transcribed a limit Mixpanel meters *per user*, which a
351
+ per-runtime counter cannot approximate in either direction. Supply
352
+ `callAdmission` explicitly if the account needs a ceiling, as Linear already
353
+ did (#342).
354
+ - **`mixpanel()` titles itself by region.** The default title is now
355
+ `Mixpanel (us)`, `(eu)`, or `(in)`, and the guide opens with the residency,
356
+ because a project lives in exactly one and search never shows a description.
357
+ An unknown region throws at construction (#342).
358
+ - **Provider guides are structured everywhere.** All five declare an explicit
359
+ `summary` instead of leaning on the guide's first line, which was truncating
360
+ the routing fact at 120 characters on three of them (#342).
361
+ - **Smaller discovery payloads.** Over-budget tool descriptions
362
+ (`cloudflare_api_get`, `cloudflare_api_mutate`, `create_dns_record`, Notion's
363
+ `search`) were trimmed to the 240-character describe budget, and shared
364
+ property descriptions were cut so `cloudflare_api_upload` and
365
+ `query_data_source` render inside the 1,024-byte compact budget instead of
366
+ degrading and costing a describe round trip (#342).
367
+ - **Cloudflare and Notion never follow a redirect.** Both used `fetch`'s
368
+ default `redirect: "follow"` and now send `redirect: "manual"`; a 3xx fails
369
+ as non-retryable `connector_call_failed` instead of re-sending the
370
+ connector's credential to whatever origin the `Location` names (#341).
371
+ - **Cloudflare and Notion bound the response they will read.** 8 MiB and
372
+ 4 MiB respectively, enforced against a declared `Content-Length` before the
373
+ first byte and again while the body streams. Both are ceilings on absurdity
374
+ rather than quotas — anything near them was already past whatever
375
+ `maxResultBytes` the deployment set — but a `cloudflare_api_get` reading an
376
+ R2 object or Worker script past 8 MiB now fails as non-retryable instead of
377
+ returning it (#341).
378
+ - **`cloudflare()` checks its `baseUrl` at construction.** A non-loopback
379
+ plain-http origin, URL-embedded credentials, or a query or fragment throws
380
+ where the connector is written rather than on the first call. A deployment
381
+ overriding `baseUrl` with an http proxy must move it to https or bind it to
382
+ loopback; the default Cloudflare base is unaffected (#341).
383
+
384
+ ### Fixed
385
+
386
+ - **`connecta doctor` names the sandbox that actually ran the program.** It
387
+ printed "QuickJS executed" at every deployment it had ever checked, including
388
+ the Worker example, whose sandbox is a Dynamic Worker — the one field the
389
+ Worker README says doctor confirms, reported wrong. The deployment now says
390
+ what its executor is: `/health` carries the configured executor's name when
391
+ it has one (an explicit `name`, else a class-shaped executor's constructor
392
+ name), sanitized and bounded because it lands in a public response body and
393
+ an operator's terminal. Doctor reports that name, and a deployment whose
394
+ executor identifies as nothing gets `code executed` rather than a guess. The
395
+ Node template still reads `QuickJS executed`; the Worker example now reads
396
+ `DynamicWorkerExecutor executed` (#368).
397
+ - **The Node template's `.env.example` ships an empty `CONNECTA_TOKEN`.**
398
+ `docker-compose.yml` has always promised to refuse a deployment with no
399
+ inbound auth, but its `${CONNECTA_TOKEN:?…}` guard only fires on unset or
400
+ empty — and the file it reads shipped `replace-me`, which is neither. Copying
401
+ `.env.example` and running the README's Docker block therefore produced a
402
+ healthy, port-published deployment whose bearer token was a string published
403
+ in this repository. The value is now empty, so both Compose and `npm start`
404
+ refuse until an operator sets one (#367).
405
+ - **The Worker example names the optional peer it imports.**
406
+ `examples/worker` wires `clerkAuth` by default and calls itself the starting
407
+ template for a deployment, but its README listed only `@cloudflare/codemode`
408
+ as an extra install. `@clerk/backend` is an optional peer that never installs
409
+ with Connecta, and `auth/clerk` imports it at the top level, so a copied
410
+ deployment following the README verbatim died at
411
+ `Could not resolve "@clerk/backend"` before it ever reached Cloudflare. The
412
+ deploy section now carries the whole install line for a copy in its own
413
+ repository (#367).
414
+ - **A malformed Clerk publishable key fails like a configuration mistake.**
415
+ `clerkAuth` derives its Frontend API origin by base64-decoding
416
+ `publishableKey` and used to hand a bad key straight to `atob`, so the
417
+ placeholder the Workers example ships raised a bare `InvalidCharacterError`
418
+ from inside the returned object — and, on a deployment that builds per
419
+ request, turned every route including `/health` into a 500 whose stack named
420
+ base64 instead of the environment variable. The key's shape is now checked
421
+ where `allowedDomains` is, at construction, and the throw names the option.
422
+ It does not quote the rejected value back: the usual way to land here is
423
+ pasting the secret key into the publishable slot (#366).
424
+ - **Notion declares the `required` lists it was missing.** `search`,
425
+ `list_users`, `get_self`, and `create_page` now say which arguments a call
426
+ must carry, so a malformed call is refused locally instead of at Notion. The
427
+ fail-closed schema handling those lists rely on is the package default as of
428
+ #340 (#342).
429
+ - **Cloudflare's cursor pagination says so in the schema.**
430
+ `list_zone_rulesets`, `list_kv_keys`, `list_r2_buckets`, and
431
+ `list_r2_objects` now state on both the `cursor` argument and the
432
+ `nextCursor` result that they page by cursor and return no `page` object —
433
+ previously only the usage guide said it (#342).
434
+ - **Nested schema properties describe themselves.** The six fields inside
435
+ `bulk_write_kv_values`'s `entries[]` — including the expiry pair, whose units
436
+ and 60-second floor were the entire question — and Notion's
437
+ `sorts[].direction` were shipping bare types, because H5's description rule
438
+ had only ever been read at the top level (#342).
439
+
440
+ ### Removed
441
+
442
+ - **`ApiOptions.strictValidation`.** Fail-closed schema handling is the only
443
+ behavior, so the opt-in has nothing left to switch. Delete the option;
444
+ nothing else changes (#340).
445
+ - **Three Cloudflare named tools; the connection ships 52, down from 55.**
446
+ `set_r2_cors` declared a free-form rule body, so its schema validated the ids
447
+ and waved through the part of the call that fails, and `get_r2_metrics` put
448
+ one account id into a path and returned the response unprojected — both
449
+ measurably weaker than the raw call that replaces them. `delete_r2_cors`
450
+ measured clean and went anyway, to keep the CORS write pair together: with
451
+ the write unnamed, a named delete would leave half of policy management on
452
+ each route. All three are one raw call away, and the guide says which one
453
+ (#350).
454
+ - **`examples/node` and `examples/docker`.** Both were diffs from the
455
+ template. `examples/` is the Worker deployment now, and the root
456
+ `.dockerignore` that existed only for the repository-context Docker build
457
+ went with them (#344).
458
+ - **`src/`, `.js.map`, `.d.ts.map`, and `assets/` — from the tarball only.**
459
+ All of them are still in the repository; none of them ships. The published
460
+ package is 167 files and 550 KB, down from 357 and 1.1 MB. The stub guides
461
+ left with them and came back written (#348), which is why the file count is
462
+ four higher than the trim alone left it.
463
+ Stepping into Connecta's TypeScript from an installed copy no longer works;
464
+ the emitted JavaScript and the `.d.ts` files beside it do. `check:package`
465
+ now fails on a packed `src/`, `.map`, or `assets/` path, derives the shipped
466
+ guide list from which guides are still stubs, so filling one in ships it, and
467
+ refuses a packed document whose relative link lands on a guide the tarball
468
+ does not carry — the three that pointed at `operations.md` now name it
469
+ instead (#346).
470
+
5
471
  ## 0.15.1 — 2026-08-12
6
472
 
7
473
  The Cloudflare connection now supports legacy user-scoped Global API Keys as
package/README.md CHANGED
@@ -57,8 +57,12 @@ Point an MCP client at `http://localhost:8787/mcp` with
57
57
  ```text
58
58
  my-connecta/
59
59
  ├── src/index.ts # connectors, auth, storage, public URL
60
+ ├── src/file-activity.ts # deployment-owned activity store, wired on request
60
61
  ├── package.json # exact Connecta and QuickJS versions
61
62
  ├── tsconfig.json
63
+ ├── Dockerfile # the same source, containerized
64
+ ├── docker-compose.yml # one service, state on a named volume
65
+ ├── .dockerignore
62
66
  ├── .env.example
63
67
  ├── .gitignore
64
68
  ├── AGENTS.md
@@ -66,6 +70,13 @@ my-connecta/
66
70
  └── README.md
67
71
  ```
68
72
 
73
+ The same project runs as a long-lived container without changing a line of it:
74
+
75
+ ```sh
76
+ cp .env.example .env # set CONNECTA_TOKEN
77
+ docker compose up -d --build
78
+ ```
79
+
69
80
  For an agent setting this up, the contract is:
70
81
 
71
82
  1. Edit `src/index.ts`; do not copy Connecta internals into the deployment.
@@ -81,6 +92,12 @@ For an agent setting this up, the contract is:
81
92
  the exact seven-tool model-facing surface, then executes a harmless sandbox
82
93
  program. The bearer stays in the environment rather than command history.
83
94
 
95
+ The operator surface is the same in both shapes and off until you say so:
96
+ Clerk sign-in, the credential vault, access-token issuance, and payload-free
97
+ activity ship as commented configuration, each one a variable and an
98
+ uncommented block away. The generated `README.md` walks through all four, and
99
+ the [Worker example](./examples/worker/) does the same for KV and D1.
100
+
84
101
  The template refuses to merge into an existing directory, so initialization
85
102
  cannot overwrite another project. Its generated programs have no filesystem,
86
103
  environment, arbitrary network, imports, or timers; only explicitly read-only
@@ -88,11 +105,9 @@ connector tools are reachable. Unannotated or write-capable calls stay
88
105
  individual and cross `call_destructive_tool`, where the MCP host can ask the
89
106
  operator for approval.
90
107
 
91
- Other supported deployment shapes:
108
+ There are two deployment shapes and no others:
92
109
 
93
- - [Prescribed Node template](./templates/node/)
94
- - [Node repository example](./examples/node/)
95
- - [Code-first Docker deployment (repository-only)](https://github.com/zackbart/connecta/tree/main/examples/docker)
110
+ - [Node, local or Docker](./templates/node/) — what `init` copies
96
111
  - [Cloudflare Worker deployment](./examples/worker/)
97
112
  - [Subsystem documentation](./documentation/)
98
113