@zackbart/connecta 0.15.1 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +40 -20
- package/CHANGELOG.md +653 -0
- package/README.md +25 -5
- package/bin/connecta.mjs +44 -3
- package/dist/access-tokens.d.ts +0 -1
- package/dist/access-tokens.js +0 -1
- package/dist/activity.d.ts +50 -2
- package/dist/activity.js +34 -1
- package/dist/apps-shell.d.ts +0 -1
- package/dist/apps-shell.js +0 -1
- package/dist/auth/bearer.d.ts +0 -1
- package/dist/auth/bearer.js +0 -1
- package/dist/auth/clerk.d.ts +0 -1
- package/dist/auth/clerk.js +45 -9
- package/dist/auth/downstream-oauth.d.ts +0 -1
- package/dist/auth/downstream-oauth.js +0 -1
- package/dist/call-admission.d.ts +0 -1
- package/dist/call-admission.js +0 -1
- package/dist/catalog-drift.d.ts +99 -0
- package/dist/catalog-drift.js +251 -0
- package/dist/catalog-fingerprint.d.ts +0 -1
- package/dist/catalog-fingerprint.js +0 -1
- package/dist/catalog-limits.d.ts +0 -1
- package/dist/catalog-limits.js +0 -1
- package/dist/catalog-service.d.ts +0 -1
- package/dist/catalog-service.js +41 -5
- package/dist/catalog.d.ts +11 -1
- package/dist/catalog.js +20 -1
- package/dist/concurrency.d.ts +0 -1
- package/dist/concurrency.js +0 -1
- package/dist/connector-scope.d.ts +0 -1
- package/dist/connector-scope.js +0 -1
- package/dist/connectors/api.d.ts +29 -21
- package/dist/connectors/api.js +45 -19
- package/dist/connectors/guarded-fetch.d.ts +106 -0
- package/dist/connectors/guarded-fetch.js +289 -0
- package/dist/connectors/remote-mcp.d.ts +0 -1
- package/dist/connectors/remote-mcp.js +0 -1
- package/dist/credentials.d.ts +0 -1
- package/dist/credentials.js +0 -1
- package/dist/errors.d.ts +30 -3
- package/dist/errors.js +1 -1
- package/dist/execute.d.ts +0 -1
- package/dist/execute.js +0 -1
- package/dist/executor-admission.d.ts +11 -1
- package/dist/executor-admission.js +28 -1
- package/dist/executor-result.d.ts +0 -1
- package/dist/executor-result.js +0 -1
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-child.js +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -1
- package/dist/executors/quickjs-protocol.js +0 -1
- package/dist/executors/quickjs-runtime.d.ts +0 -1
- package/dist/executors/quickjs-runtime.js +0 -1
- package/dist/executors/quickjs.d.ts +0 -1
- package/dist/executors/quickjs.js +2 -1
- package/dist/favicon.d.ts +0 -1
- package/dist/favicon.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -7
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +0 -1
- package/dist/json-schema.d.ts +0 -1
- package/dist/json-schema.js +0 -1
- package/dist/mcp-result.d.ts +0 -1
- package/dist/mcp-result.js +0 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +0 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/operator-ui/generated.d.ts +2 -3
- package/dist/operator-ui/generated.js +3 -4
- package/dist/operator-ui/model.d.ts +10 -1
- package/dist/operator-ui/model.js +0 -1
- package/dist/operator-ui/view.d.ts +167 -0
- package/dist/operator-ui/view.js +270 -0
- package/dist/providers/cloudflare.d.ts +0 -1
- package/dist/providers/cloudflare.js +261 -299
- package/dist/providers/linear.d.ts +26 -5
- package/dist/providers/linear.js +32 -61
- package/dist/providers/mixpanel.d.ts +35 -4
- package/dist/providers/mixpanel.js +53 -79
- package/dist/providers/notion.d.ts +0 -1
- package/dist/providers/notion.js +87 -42
- package/dist/providers/stripe.d.ts +13 -1
- package/dist/providers/stripe.js +31 -60
- package/dist/registry.d.ts +34 -2
- package/dist/registry.js +85 -5
- package/dist/retired-toolkits.d.ts +0 -1
- package/dist/retired-toolkits.js +0 -1
- package/dist/routes/access-tokens.d.ts +0 -1
- package/dist/routes/access-tokens.js +0 -1
- package/dist/routes/activity.d.ts +0 -1
- package/dist/routes/activity.js +0 -1
- package/dist/routes/credentials.d.ts +0 -1
- package/dist/routes/credentials.js +0 -1
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +0 -1
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +0 -1
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +0 -1
- package/dist/routes/ui.d.ts +0 -1
- package/dist/routes/ui.js +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +11 -1
- package/dist/skills.d.ts +0 -1
- package/dist/skills.js +0 -1
- package/dist/storage/file.d.ts +0 -1
- package/dist/storage/file.js +0 -1
- package/dist/storage/memory.d.ts +0 -1
- package/dist/storage/memory.js +0 -1
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -1
- package/dist/tool-safety.d.ts +0 -1
- package/dist/tool-safety.js +0 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +13 -137
- package/dist/validate.d.ts +13 -15
- package/dist/validate.js +24 -11
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/documentation/architecture.md +186 -5
- package/documentation/auth.md +11 -0
- package/documentation/call-admission.md +142 -6
- package/documentation/cloudflare.md +92 -10
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +14 -14
- package/documentation/connector-guides.md +172 -5
- package/documentation/connectors.md +89 -0
- package/documentation/linear.md +20 -2
- package/documentation/mcp-ui-design.md +2 -2
- package/documentation/meta-tools.md +7 -1
- package/documentation/mixpanel.md +42 -9
- package/documentation/notion.md +23 -2
- package/documentation/operations.md +325 -5
- package/documentation/operator-ui.md +120 -5
- package/documentation/provider-audit.md +160 -0
- package/documentation/provider-conventions.md +667 -0
- package/documentation/request-admission.md +167 -5
- package/documentation/rich-output-design.md +1 -2
- package/documentation/stripe.md +15 -0
- package/documentation/upgrading.md +454 -0
- package/ethos.md +14 -9
- package/examples/worker/README.md +102 -12
- package/examples/worker/src/index.ts +46 -1
- package/examples/worker/wrangler.jsonc +14 -1
- package/package.json +10 -6
- package/templates/node/.dockerignore +10 -0
- package/templates/node/.env.example +40 -3
- package/templates/node/AGENTS.md +16 -1
- package/templates/node/Dockerfile +49 -0
- package/templates/node/README.md +117 -2
- package/templates/node/docker-compose.yml +39 -0
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +182 -0
- package/templates/node/src/index.ts +80 -4
- package/assets/connecta-clay-hero.png +0 -0
- package/dist/access-tokens.d.ts.map +0 -1
- package/dist/access-tokens.js.map +0 -1
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js.map +0 -1
- package/dist/apps-shell.d.ts.map +0 -1
- package/dist/apps-shell.js.map +0 -1
- package/dist/auth/bearer.d.ts.map +0 -1
- package/dist/auth/bearer.js.map +0 -1
- package/dist/auth/clerk.d.ts.map +0 -1
- package/dist/auth/clerk.js.map +0 -1
- package/dist/auth/downstream-oauth.d.ts.map +0 -1
- package/dist/auth/downstream-oauth.js.map +0 -1
- package/dist/call-admission.d.ts.map +0 -1
- package/dist/call-admission.js.map +0 -1
- package/dist/catalog-fingerprint.d.ts.map +0 -1
- package/dist/catalog-fingerprint.js.map +0 -1
- package/dist/catalog-limits.d.ts.map +0 -1
- package/dist/catalog-limits.js.map +0 -1
- package/dist/catalog-service.d.ts.map +0 -1
- package/dist/catalog-service.js.map +0 -1
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js.map +0 -1
- package/dist/concurrency.d.ts.map +0 -1
- package/dist/concurrency.js.map +0 -1
- package/dist/connector-scope.d.ts.map +0 -1
- package/dist/connector-scope.js.map +0 -1
- package/dist/connectors/api.d.ts.map +0 -1
- package/dist/connectors/api.js.map +0 -1
- package/dist/connectors/remote-mcp.d.ts.map +0 -1
- package/dist/connectors/remote-mcp.js.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js.map +0 -1
- package/dist/executor-admission.d.ts.map +0 -1
- package/dist/executor-admission.js.map +0 -1
- package/dist/executor-result.d.ts.map +0 -1
- package/dist/executor-result.js.map +0 -1
- package/dist/executors/quickjs-child.d.ts.map +0 -1
- package/dist/executors/quickjs-child.js.map +0 -1
- package/dist/executors/quickjs-protocol.d.ts.map +0 -1
- package/dist/executors/quickjs-protocol.js.map +0 -1
- package/dist/executors/quickjs-runtime.d.ts.map +0 -1
- package/dist/executors/quickjs-runtime.js.map +0 -1
- package/dist/executors/quickjs.d.ts.map +0 -1
- package/dist/executors/quickjs.js.map +0 -1
- package/dist/favicon.d.ts.map +0 -1
- package/dist/favicon.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js.map +0 -1
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js.map +0 -1
- package/dist/mcp-result.d.ts.map +0 -1
- package/dist/mcp-result.js.map +0 -1
- package/dist/meta-tools.d.ts.map +0 -1
- package/dist/meta-tools.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/operator-ui/generated.d.ts.map +0 -1
- package/dist/operator-ui/generated.js.map +0 -1
- package/dist/operator-ui/model.d.ts.map +0 -1
- package/dist/operator-ui/model.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/linear.d.ts.map +0 -1
- package/dist/providers/linear.js.map +0 -1
- package/dist/providers/mixpanel.d.ts.map +0 -1
- package/dist/providers/mixpanel.js.map +0 -1
- package/dist/providers/notion.d.ts.map +0 -1
- package/dist/providers/notion.js.map +0 -1
- package/dist/providers/stripe.d.ts.map +0 -1
- package/dist/providers/stripe.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/retired-toolkits.d.ts.map +0 -1
- package/dist/retired-toolkits.js.map +0 -1
- package/dist/routes/access-tokens.d.ts.map +0 -1
- package/dist/routes/access-tokens.js.map +0 -1
- package/dist/routes/activity.d.ts.map +0 -1
- package/dist/routes/activity.js.map +0 -1
- package/dist/routes/credentials.d.ts.map +0 -1
- package/dist/routes/credentials.js.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/mcp.js.map +0 -1
- package/dist/routes/oauth.d.ts.map +0 -1
- package/dist/routes/oauth.js.map +0 -1
- package/dist/routes/shared.d.ts.map +0 -1
- package/dist/routes/shared.js.map +0 -1
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/storage/file.d.ts.map +0 -1
- package/dist/storage/file.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/timeout.d.ts.map +0 -1
- package/dist/timeout.js.map +0 -1
- package/dist/tool-safety.d.ts.map +0 -1
- package/dist/tool-safety.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/examples/node/README.md +0 -52
- package/examples/node/src/index.ts +0 -71
- package/src/access-tokens.ts +0 -289
- package/src/activity.ts +0 -234
- package/src/apps-shell.ts +0 -370
- package/src/auth/bearer.ts +0 -61
- package/src/auth/clerk.ts +0 -553
- package/src/auth/downstream-oauth.ts +0 -575
- package/src/call-admission.ts +0 -521
- package/src/catalog-fingerprint.ts +0 -52
- package/src/catalog-limits.ts +0 -11
- package/src/catalog-service.ts +0 -1153
- package/src/catalog.ts +0 -790
- package/src/concurrency.ts +0 -39
- package/src/connector-scope.ts +0 -66
- package/src/connectors/api.ts +0 -159
- package/src/connectors/remote-mcp.ts +0 -1090
- package/src/credentials.ts +0 -428
- package/src/errors.ts +0 -364
- package/src/execute.ts +0 -1406
- package/src/executor-admission.ts +0 -328
- package/src/executor-result.ts +0 -107
- package/src/executors/quickjs-child.ts +0 -172
- package/src/executors/quickjs-protocol.ts +0 -99
- package/src/executors/quickjs-runtime.ts +0 -470
- package/src/executors/quickjs.ts +0 -776
- package/src/favicon.ts +0 -53
- package/src/index.ts +0 -666
- package/src/invocation.ts +0 -655
- package/src/json-schema.ts +0 -11
- package/src/mcp-result.ts +0 -43
- package/src/meta-tools.ts +0 -1607
- package/src/node.ts +0 -206
- package/src/operator-ui/browser.css +0 -423
- package/src/operator-ui/browser.ts +0 -1281
- package/src/operator-ui/generated.ts +0 -4
- package/src/operator-ui/model.ts +0 -111
- package/src/providers/cloudflare.ts +0 -3999
- package/src/providers/linear.ts +0 -302
- package/src/providers/mixpanel.ts +0 -229
- package/src/providers/notion.ts +0 -1879
- package/src/providers/stripe.ts +0 -307
- package/src/registry.ts +0 -1085
- package/src/retired-toolkits.ts +0 -14
- package/src/routes/access-tokens.ts +0 -115
- package/src/routes/activity.ts +0 -215
- package/src/routes/credentials.ts +0 -254
- package/src/routes/mcp.ts +0 -429
- package/src/routes/oauth.ts +0 -322
- package/src/routes/shared.ts +0 -247
- package/src/routes/ui.ts +0 -152
- package/src/server.ts +0 -195
- package/src/skills.ts +0 -271
- package/src/storage/file.ts +0 -123
- package/src/storage/memory.ts +0 -44
- package/src/timeout.ts +0 -84
- package/src/tool-safety.ts +0 -15
- package/src/types.ts +0 -523
- package/src/ui.ts +0 -744
- package/src/validate.ts +0 -387
- package/src/version.ts +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,659 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.16.1 — 2026-08-13
|
|
6
|
+
|
|
7
|
+
This is the cleanup that follows 0.16.0 out the door: the packaging housekeeping
|
|
8
|
+
the pre-release smoke gauntlet turned up, one provider tool Cloudflare
|
|
9
|
+
deprecated out from under us, a discovery answer that told a plain lie, and the
|
|
10
|
+
upgrade runbook an existing deployment never had. Two things break, both on
|
|
11
|
+
Cloudflare and both named here rather than left to the section below:
|
|
12
|
+
`list_zone_settings` is gone from the `cloudflare()` named surface, and
|
|
13
|
+
Cloudflare's 404 arrives as `not_found` instead of `connector_call_failed`.
|
|
14
|
+
Nothing else does — no wire shape changes, no construction contract moves, no
|
|
15
|
+
other code reclassified, and the per-setting operations `list_zone_settings`
|
|
16
|
+
sat beside are the supported ones and are untouched. A deployment that writes
|
|
17
|
+
no `api()` connectors, branches on no error code, and never asked an agent for
|
|
18
|
+
a whole zone's settings in one call upgrades without reading further.
|
|
19
|
+
|
|
20
|
+
Three things are additions rather than repairs, and they are the reason this
|
|
21
|
+
release is worth reading rather than just installing: a new
|
|
22
|
+
`ConnectorCallErrorCode` member, `not_found`, with a rule for when a connector
|
|
23
|
+
may mint it; a `"./package.json"` entry in the `exports` map, so the installed
|
|
24
|
+
manifest resolves; and `@cloudflare/codemode` declared as an optional peer at
|
|
25
|
+
`^0.4.4 || ^0.5.0`. Strict semver would read those three as a minor, and would
|
|
26
|
+
read the two Cloudflare changes above as more than that. This ships as a patch
|
|
27
|
+
deliberately: every addition is opt-in at the point a deployment chooses to
|
|
28
|
+
read it, and the tool removal and the 404 reclassification ride along in the
|
|
29
|
+
same patch on purpose — both are scoped to one provider, both have a stated
|
|
30
|
+
replacement, and both carry a version boundary in
|
|
31
|
+
[`documentation/upgrading.md`](./documentation/upgrading.md). Holding them for
|
|
32
|
+
a minor would mean shipping a release that keeps calling an endpoint its
|
|
33
|
+
provider deprecated. The one install-time consequence is spelled out next.
|
|
34
|
+
|
|
35
|
+
One thing to check before upgrading a Worker: `@cloudflare/codemode` is now a
|
|
36
|
+
declared peer, so if your `package.json` holds it at a version outside
|
|
37
|
+
`^0.4.4 || ^0.5.0` — a `0.3.x`, or a `0.4` below `0.4.4` — npm stops the
|
|
38
|
+
upgrade with an `ERESOLVE` conflict rather than installing. Move it into the
|
|
39
|
+
range this release is tested against, or pass `--legacy-peer-deps` if you have
|
|
40
|
+
a reason to run outside it. A version already inside the range, and a range
|
|
41
|
+
loose enough for npm to pick one that is, both resolve exactly as before.
|
|
42
|
+
|
|
43
|
+
Alongside it, the upgrade path an existing deployment takes gets written down.
|
|
44
|
+
`connecta init` was the golden path for a new deployment and the whole story
|
|
45
|
+
for an old one, which is a gap with a shape: `init` refuses to merge into an
|
|
46
|
+
existing path — the guard that keeps an initializer from eating a connector
|
|
47
|
+
set — so an agent pointed at a deployment two releases behind had to
|
|
48
|
+
reconstruct the procedure from release prose written for the maintainer. Both
|
|
49
|
+
interesting failures there were silent too. It overwrites the configuration the
|
|
50
|
+
deployment exists for, or it "fixes" a construction throw by weakening a
|
|
51
|
+
fail-closed default and ships something quieter and wrong.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- **`not_found`, for a downstream that answered and had nothing to give.** A
|
|
56
|
+
hand-written connector meeting a 404 had exactly one honest code,
|
|
57
|
+
`connector_call_failed`, which also means "the call blew up" — so a program
|
|
58
|
+
inside `execute_code` could not tell a clean absence from a broken connector,
|
|
59
|
+
and a loop over ids had to abort where it should have skipped one. The new
|
|
60
|
+
code earns its place the way every code has to: it changes what the caller
|
|
61
|
+
does next. You do not wait, you do not go to `authorize_connector`, you do
|
|
62
|
+
not repair the arguments — you re-address. It is non-retryable, carries no
|
|
63
|
+
recovery envelope, derives no activity friction class, and is exported from
|
|
64
|
+
the root entry as part of `ConnectorCallErrorCode`.
|
|
65
|
+
|
|
66
|
+
The qualifier is the interesting half, and it is now written down in
|
|
67
|
+
[H11](./documentation/provider-conventions.md#h11--errors-are-mapped-to-what-the-caller-does-next):
|
|
68
|
+
map a status to `not_found` only where the provider tells absence apart from
|
|
69
|
+
a permission gap. Cloudflare does — a token that may not touch a resource is
|
|
70
|
+
refused with 401 or 403 — so its 404 is now `not_found` instead of
|
|
71
|
+
`connector_call_failed`. Notion does not: `object_not_found` means both "it
|
|
72
|
+
is gone" and "it was never shared with this integration", so it deliberately
|
|
73
|
+
stays generic with a message that says so. The hosted-MCP proxy path mints
|
|
74
|
+
the code never, because `P1` forbids re-shaping downstream framing and
|
|
75
|
+
provider prose is never parsed to invent a classification (#373).
|
|
76
|
+
|
|
77
|
+
- **An upgrade runbook for existing deployments.**
|
|
78
|
+
[`documentation/upgrading.md`](./documentation/upgrading.md) is written for
|
|
79
|
+
the agent sitting inside a generated deployment it did not create: read the
|
|
80
|
+
exact pin and the template generation it implies, regenerate that generation
|
|
81
|
+
with `npx @zackbart/connecta@<pin> init` to get a real merge base, three-way
|
|
82
|
+
reconcile the scaffolding against the current template while `src/index.ts`
|
|
83
|
+
stays the deployment's own, cross the version boundaries that break
|
|
84
|
+
construction, and finish where `init` finishes — typecheck, start,
|
|
85
|
+
`connecta doctor`, then a program that exercises the deployment's *own*
|
|
86
|
+
connectors, which doctor deliberately knows nothing about. The migration
|
|
87
|
+
notes are per boundary and derived from this file: the 0.16.0 `api()`
|
|
88
|
+
construction contract (with the one safe answer for an unannotated tool
|
|
89
|
+
written down — `readOnlyHint: false`, which is the routing it already had),
|
|
90
|
+
the `linear()`, `mixpanel()`, and Cloudflare provider changes, redirect
|
|
91
|
+
refusal and the response ceilings, and the fail-closed shipped defaults; then
|
|
92
|
+
0.14's annotation-precedence change, 0.13's rewritten guide summaries, the
|
|
93
|
+
0.11.0 executor requirement, 0.7.0's `verifyState` requirement and
|
|
94
|
+
core-owned routes for the pre-template deployments that still have to cross
|
|
95
|
+
them, and every removed option that throws with its migration. It closes with five refusals, because each is somebody's plausible
|
|
96
|
+
shortcut: no re-init over the top, no weakening a fail-closed default to get
|
|
97
|
+
green, no pinning back, no vendored internals, no second project shape.
|
|
98
|
+
Reachable from the README, from `operations.md`, and — absolutely, because
|
|
99
|
+
that reader has no copy of this repository — from the template's `AGENTS.md`
|
|
100
|
+
(#380).
|
|
101
|
+
- **A suite that keeps the guide honest.** `test/upgrade-guide.test.ts` pins
|
|
102
|
+
every claim its reader cannot check: the generated file inventory against
|
|
103
|
+
`templates/node/`, the seven tool names against the CLI's own list, each
|
|
104
|
+
named version boundary against a release that shipped, each removed option
|
|
105
|
+
against the release section that names its issue, the bump target against
|
|
106
|
+
this package's version, and the three places the guide is linked from. A template that gains a file now fails `npm run check` rather than
|
|
107
|
+
leaving an agent to guess which of the two is wrong (#380).
|
|
108
|
+
- **`@cloudflare/codemode` is a declared optional peer.** Every Workers
|
|
109
|
+
deployment installs the executor behind `execute_code` by hand, and until now
|
|
110
|
+
the only version range anywhere was a devDependency no consumer can read — a
|
|
111
|
+
fresh install resolved a minor ahead of what this repository tests, silently.
|
|
112
|
+
The manifest now publishes `^0.4.4 || ^0.5.0` for it, optional like
|
|
113
|
+
`@clerk/backend` and `quickjs-emscripten`, so a supported version installs in
|
|
114
|
+
silence and an unsupported one stops the install with something to act on
|
|
115
|
+
instead of becoming skew a Worker discovers in production. It still installs
|
|
116
|
+
with nothing: a default `npm install @zackbart/connecta` pulls no executor,
|
|
117
|
+
and the package smoke proves that, both halves of the range behavior, and
|
|
118
|
+
that the version this repository develops against stays inside the range it
|
|
119
|
+
publishes (#376).
|
|
120
|
+
|
|
121
|
+
### Changed
|
|
122
|
+
|
|
123
|
+
- **Cloudflare's 404 is `not_found`.** A deployment branching on
|
|
124
|
+
`connector_call_failed` to detect an unknown zone or account id should read
|
|
125
|
+
`not_found` instead; retryability, the message, and its pointer to
|
|
126
|
+
`list_zones` / `list_accounts` are unchanged (#373).
|
|
127
|
+
- `cloudflare()` no longer names a bulk zone-settings read.
|
|
128
|
+
`GET /zones/{zoneId}/settings` and its `PATCH` sibling are published as
|
|
129
|
+
`deprecated: true`, Cloudflare offers no bulk replacement, and the tool that
|
|
130
|
+
wrapped the read projected nothing — it took a zone id and grew the payload
|
|
131
|
+
by wrapping an unpaginated array in a page object. Read one setting with
|
|
132
|
+
`get_zone_setting` and write one with `update_zone_setting`, both on the
|
|
133
|
+
supported `/zones/{zoneId}/settings/{settingId}` operations. An operator who
|
|
134
|
+
still wants the whole set can name the deprecated path explicitly through
|
|
135
|
+
`cloudflare_api_get`. The named surface is 47 tools plus the three escape
|
|
136
|
+
hatches ([#361](https://github.com/zackbart/connecta/issues/361)).
|
|
137
|
+
- The Cloudflare touched-endpoint manifest drops the deprecated row with the
|
|
138
|
+
tool, so `npm run drift:check -- --specs` is quiet about zone settings
|
|
139
|
+
because nothing calls the endpoint, not because a maintainer signed off on
|
|
140
|
+
calling it anyway.
|
|
141
|
+
|
|
142
|
+
### Fixed
|
|
143
|
+
|
|
144
|
+
- **A search for a connector's own name stops claiming the deployment has no
|
|
145
|
+
such capability.** A connector's `id` — the address prefix an agent already
|
|
146
|
+
holds — and its `title` are displayed, never indexed, so `search_tools({
|
|
147
|
+
query: "inventory" })` against a connector called `inventory` matched no tool
|
|
148
|
+
and was answered with "No matching capability is configured in this
|
|
149
|
+
deployment", which was plainly false. Connector identity stays out of the
|
|
150
|
+
lexical index, because putting it in would move ranking for every query that
|
|
151
|
+
already matches tools; instead an unscoped miss whose terms name configured
|
|
152
|
+
connectors says so, names up to three of them by ID, and sends the caller to
|
|
153
|
+
a scoped browse. A term that matches nothing in the deployment still gets the
|
|
154
|
+
original sentence, unchanged. One `queryAnalysis.guidance` string differs; no
|
|
155
|
+
ranking, result, or field changed (#372).
|
|
156
|
+
- **Every relative link in the shipped Markdown resolves for the reader who
|
|
157
|
+
installed the package.** Ten of them pointed at `eval/`, `test/`, `scripts/`,
|
|
158
|
+
and the README hero — repository paths the tarball has never carried and, per
|
|
159
|
+
#346, should not start carrying. The link gate could not see any of them: it
|
|
160
|
+
read only `documentation/` targets, so the whole class was invisible and grew
|
|
161
|
+
with every trim. The policy is now stated once in the operations guide and
|
|
162
|
+
enforced over *every* relative link in packed Markdown: it either resolves
|
|
163
|
+
inside the tarball or it is cited as an absolute
|
|
164
|
+
`https://github.com/zackbart/connecta/blob/main/...` URL, which an outside
|
|
165
|
+
reader can follow and which `check:docs` resolves back to the checkout, so a
|
|
166
|
+
citation still fails when the file it names moves. The ten links were
|
|
167
|
+
rewritten that way, the README hero now loads from
|
|
168
|
+
`raw.githubusercontent.com` and still renders on npmjs.com, and the
|
|
169
|
+
repository reader loses no citation (#378).
|
|
170
|
+
- **`@zackbart/connecta/package.json` resolves.** The `exports` map listed
|
|
171
|
+
every code subpath and nothing else, so a bundler plugin, framework build
|
|
172
|
+
step, or version probe reaching for the installed manifest — a thing the
|
|
173
|
+
ecosystem broadly expects to work — got `ERR_PACKAGE_PATH_NOT_EXPORTED`
|
|
174
|
+
instead of the file. The manifest is now exported. It is a data file, so this
|
|
175
|
+
widens the published surface by exactly zero code paths: the root entry's
|
|
176
|
+
Workers purity boundary and the optional-peer subpaths are untouched. The
|
|
177
|
+
package-surface gate now asserts the whole subpath set, manifest included, so
|
|
178
|
+
neither this entry nor an unwanted one can arrive unnoticed (#374).
|
|
179
|
+
- **The published-surface rule says what it actually forbids.** `AGENTS.md`
|
|
180
|
+
claimed platform-specific storage adapters live in `examples/`, "not the
|
|
181
|
+
package", while the tarball has always carried `examples/worker` — Cloudflare
|
|
182
|
+
KV and D1 adapters included — because that example is the Workers starting
|
|
183
|
+
template a consumer copies. The invariant was never in danger: nothing under
|
|
184
|
+
`examples/` appears in the `exports` map, so those adapters are reference
|
|
185
|
+
source and not an importable subpath. The wording now draws the line where
|
|
186
|
+
the gates draw it — a platform-bound adapter must not reach `src/` or the
|
|
187
|
+
`exports` map — and says why the example ships, in `AGENTS.md`, the
|
|
188
|
+
operations guide, and the `scripts/check-package.mjs` comment. A new
|
|
189
|
+
assertion in `test/package-surface.test.ts` holds the instruction file and
|
|
190
|
+
the exports map to the same story (#377).
|
|
191
|
+
|
|
192
|
+
## 0.16.0 — 2026-08-12
|
|
193
|
+
|
|
194
|
+
This is the agent-efficiency refocus. One release, sixteen merges, and a single
|
|
195
|
+
question asked of every tool description, schema, discovery result, and error
|
|
196
|
+
message in the package: what does this cost the model that has to read it?
|
|
197
|
+
Where operator convenience and agent cost disagreed, the agent-facing contract
|
|
198
|
+
won. The work lands on two pillars — excellent curated providers, and a
|
|
199
|
+
footgun-free path for everything else — plus an operator boundary that finally
|
|
200
|
+
describes the surface it guards, exactly two deployment shapes instead of four,
|
|
201
|
+
and an operator UI that is a component app rather than string-built HTML.
|
|
202
|
+
|
|
203
|
+
What breaks, breaks loudly, and mostly at construction rather than at 2 a.m.
|
|
204
|
+
`api()` now requires a `description` and an explicit
|
|
205
|
+
`annotations.readOnlyHint` on every tool and refuses an `inputSchema` it cannot
|
|
206
|
+
compile; `strictValidation` is gone because fail-closed is the only behavior
|
|
207
|
+
left for it to switch. `linear()` requires an explicit `access` mode.
|
|
208
|
+
`mixpanel()` no longer declares a call-admission budget. `cloudflare()` checks
|
|
209
|
+
an overridden `baseUrl` where it is written. The Cloudflare connection ships 52
|
|
210
|
+
named tools instead of 55, having been measured against its own escape hatches
|
|
211
|
+
rather than assumed to beat them. And Cloudflare and Notion now refuse a
|
|
212
|
+
redirect and cap the response they will read, which is visible only to a
|
|
213
|
+
deployment that was downloading something enormous through a tool call. Each
|
|
214
|
+
of those has a one-line migration, spelled out below.
|
|
215
|
+
|
|
216
|
+
A deployment that writes no `api()` connectors and runs none of the five
|
|
217
|
+
prebuilt connections can upgrade without editing anything. Nothing in the core
|
|
218
|
+
runtime surface moved: the seven meta-tools, the executor contract, the storage
|
|
219
|
+
interfaces, the route table, and the wire shapes are where they were. The
|
|
220
|
+
tarball is half the size, the guides are all written, and `connecta init` now
|
|
221
|
+
produces a project that runs under `docker compose up` without becoming a
|
|
222
|
+
second project shape.
|
|
223
|
+
|
|
224
|
+
`api()` stops being forgiving. A hand-written tool now declares what it does
|
|
225
|
+
and whether calling it needs a human, and any `inputSchema` it ships is one
|
|
226
|
+
Connecta can actually enforce — all three checked at construction, where a
|
|
227
|
+
deployment can still refuse to boot, rather than discovered by an agent at
|
|
228
|
+
2 a.m. The warn-once-then-pass-raw-arguments-through behavior behind an
|
|
229
|
+
unenforceable schema is gone, and with it the `strictValidation` option that
|
|
230
|
+
existed only to turn it off.
|
|
231
|
+
|
|
232
|
+
That construction contract breaks `api()` authors and nobody else. Migration is
|
|
233
|
+
mechanical: give every tool a non-empty `description` and an explicit
|
|
234
|
+
`annotations.readOnlyHint` — `true` for a read, `false` for work that should
|
|
235
|
+
cross `call_destructive_tool` — then delete `strictValidation`, which is now
|
|
236
|
+
the only behavior. A tool that used to ship unannotated becomes
|
|
237
|
+
`readOnlyHint: false`, which is exactly the routing it already got.
|
|
238
|
+
Hosted-MCP proxies are untouched: `remoteMcp()` relays a downstream's names,
|
|
239
|
+
descriptions, schemas, and annotations as they arrive, and an unannotated or
|
|
240
|
+
contradictory downstream tool still fails closed onto `call_destructive_tool`.
|
|
241
|
+
Connecta infers read-only behavior from nothing, anywhere.
|
|
242
|
+
|
|
243
|
+
The maintained Cloudflare connection ships the second break. Its named surface
|
|
244
|
+
was measured against its own escape hatches instead of being assumed to beat
|
|
245
|
+
them, and three tools came out. Every named tool now carries a recorded `keep`,
|
|
246
|
+
`prune`, or `improve` verdict backed by per-tool numbers: catalog tokens, rank
|
|
247
|
+
in a real `search_tools` call for a representative operator request, whether
|
|
248
|
+
classes of argument mistake are refused before the round trip, and whether the
|
|
249
|
+
handler projects Cloudflare's object or hands it back whole. The evidence, the
|
|
250
|
+
tasks, and the reason for every removal — including the one removed for pair
|
|
251
|
+
symmetry rather than for a measured defect — are in
|
|
252
|
+
[`eval/current-version/results/issue-350-evidence.md`](./eval/current-version/results/issue-350-evidence.md).
|
|
253
|
+
**A deployment that calls `set_r2_cors`, `delete_r2_cors`, or `get_r2_metrics`
|
|
254
|
+
has to change.** No capability is lost: `get_r2_cors` still reads a bucket's
|
|
255
|
+
policy, and the usage guide now names the replacement routes —
|
|
256
|
+
`cloudflare_api_mutate` at
|
|
257
|
+
`PUT`/`DELETE /accounts/{accountId}/r2/buckets/{bucketName}/cors`, and
|
|
258
|
+
`cloudflare_api_get` at `/accounts/{accountId}/r2/metrics`. Every other
|
|
259
|
+
Cloudflare tool, argument, projection, and annotation is unchanged.
|
|
260
|
+
|
|
261
|
+
All five maintained prebuilt connections have been audited against the written
|
|
262
|
+
provider conventions, one report per provider, with a verdict for every
|
|
263
|
+
applicable convention. Nineteen misses were found and fixed. Sixteen of them
|
|
264
|
+
were a guide, a title, or a schema description failing to say something the
|
|
265
|
+
implementation already did correctly — the conventions were mostly not asking
|
|
266
|
+
for different behavior, they were asking for the behavior to reach the agent.
|
|
267
|
+
|
|
268
|
+
Three of them did change behavior, and two of those break a deployment:
|
|
269
|
+
`linear()` now requires an `access` mode, and `mixpanel()` no longer declares a
|
|
270
|
+
call-admission budget. Both failures are loud — one at construction, one as an
|
|
271
|
+
absent ceiling an operator can restore in one option. Everything else is a
|
|
272
|
+
smaller catalog, a better summary, and a guide that says what it always meant.
|
|
273
|
+
|
|
274
|
+
Underneath all of that, the two hand-written providers stopped each keeping
|
|
275
|
+
their own copy of the same transport safety machinery. Cloudflare and Notion
|
|
276
|
+
now send every request through one guarded transport that owns URL
|
|
277
|
+
confinement, redirect refusal, bounded response reads, and network-failure
|
|
278
|
+
normalization, and owns no opinion at all about what a status code means.
|
|
279
|
+
|
|
280
|
+
Consolidating it was not free, and three of the differences are visible from
|
|
281
|
+
outside. A 3xx from either provider is refused now rather than followed, which
|
|
282
|
+
is what both used to do by default — a redirect is an instruction to re-send
|
|
283
|
+
the connector's credential to whatever origin `Location` names, and neither
|
|
284
|
+
API has a legitimate one to send. Both providers now cap what they will read,
|
|
285
|
+
at 8 MiB for Cloudflare and 4 MiB for Notion, so a `cloudflare_api_get`
|
|
286
|
+
downloading an R2 object or a Worker script larger than 8 MiB fails instead of
|
|
287
|
+
returning it. And `cloudflare()`'s optional `baseUrl` is checked where it is
|
|
288
|
+
written: a non-loopback plain-http origin, URL-embedded credentials, or a
|
|
289
|
+
query or fragment throws at construction, so a deployment pointed at an http
|
|
290
|
+
proxy stops booting rather than sending it a token.
|
|
291
|
+
|
|
292
|
+
The repository now models exactly the two deployments it actually has: a Node
|
|
293
|
+
one and a Worker one. `connecta init` still copies the same template, but that
|
|
294
|
+
template now carries its own `Dockerfile` and `docker-compose.yml`, so the
|
|
295
|
+
generated project runs from `npm start` locally and from `docker compose up`
|
|
296
|
+
in production without becoming a second project shape. The two near-identical
|
|
297
|
+
Node scaffolds that sat beside it — `examples/node` and `examples/docker`, the
|
|
298
|
+
latter of which built the Connecta repository rather than a consumer project —
|
|
299
|
+
are gone. Existing deployments can ignore all of this; nothing in the package's
|
|
300
|
+
runtime surface moved.
|
|
301
|
+
|
|
302
|
+
The three maintained hosted-MCP connections now notice when the catalog they
|
|
303
|
+
were reviewed against moves. Each ships a vetted manifest — the tool names and
|
|
304
|
+
classifications a release read, plus schema digests once a release records
|
|
305
|
+
them — and compares it with the live listing *inside* a catalog refresh the
|
|
306
|
+
deployment already asked for. Nothing new is requested: no scheduled job, no
|
|
307
|
+
background poll, no credential probe, which is the boundary that keeps this
|
|
308
|
+
from being the proactive liveness checking connecta removed. What comes out is
|
|
309
|
+
four counts — unclassified additions, names no longer served, explicit
|
|
310
|
+
annotation conflicts, schema changes — on connector status, on `/health`, and
|
|
311
|
+
in `connecta doctor`, plus one payload-free activity event per change in those
|
|
312
|
+
counts for stores that implement the new optional `recordCatalogDrift`. The
|
|
313
|
+
observation is per runtime and is not persisted, so status, `/health`, and
|
|
314
|
+
doctor answer for the isolate or process that served the refresh — an empty
|
|
315
|
+
report means that runtime has observed nothing, and the activity event is the
|
|
316
|
+
durable half. A deployment can ignore all of it: an unclassified tool already
|
|
317
|
+
failed closed onto `call_destructive_tool` before anyone counted it.
|
|
318
|
+
|
|
319
|
+
The other half of that story is a command, not a surface. `npm run drift:check`
|
|
320
|
+
is maintainer tooling — it ships nowhere, runs on a laptop before a release, and
|
|
321
|
+
answers the question the runtime counts deliberately cannot: *which* tool moved.
|
|
322
|
+
It diffs each hosted-MCP catalog against the same vetted manifest the connector
|
|
323
|
+
classifies from, using the maintainer's own credential, and it compares the
|
|
324
|
+
handful of endpoints Cloudflare and Notion actually call against those
|
|
325
|
+
providers' published OpenAPI documents — reporting a gone path, a gone method, a
|
|
326
|
+
new deprecation, or a changed contract, and ignoring the two thousand operations
|
|
327
|
+
connecta never touches. No credential goes near CI, nothing is scheduled,
|
|
328
|
+
nothing files itself, and a published specification is drift evidence only: it
|
|
329
|
+
never generates a tool and never becomes a runtime input.
|
|
330
|
+
|
|
331
|
+
Both deployment shapes now carry the operator feature set the operator pages
|
|
332
|
+
were built for. A fresh `connecta init` used to produce a deployment with a
|
|
333
|
+
Credentials page and no vault, a Tokens page and no issuance, and an Activity
|
|
334
|
+
page with nothing behind it — pages for things that deployment could not do.
|
|
335
|
+
The Node template now ships sign-in, vault, tokens, and activity as four
|
|
336
|
+
clearly-marked commented blocks in `src/index.ts`, each one an environment
|
|
337
|
+
variable and an uncommented block away, plus a deployment-owned
|
|
338
|
+
`src/file-activity.ts` that is compiled rather than commented. The Worker
|
|
339
|
+
example wires the first three outright and comments the fourth, which needs a
|
|
340
|
+
D1 database nobody can create for you. Existing deployments can ignore this
|
|
341
|
+
entirely: nothing in the package's runtime surface moved, and both READMEs
|
|
342
|
+
walk through the enablement.
|
|
343
|
+
|
|
344
|
+
Finally, the tarball is half of what it was, and nothing that left it was
|
|
345
|
+
reachable. `exports` resolves only into `dist/`, so the packed `src/` was
|
|
346
|
+
never imported by anything — it was there to back the source and declaration
|
|
347
|
+
maps, and all three went together. Out with them, and out with the 230 KB
|
|
348
|
+
README hero image, which npmjs.com renders from the repository anyway. An
|
|
349
|
+
install unpacks to 1.8 MB instead of 3.8 MB. The code, the types, the CLI, the
|
|
350
|
+
template, the Worker example, and every guide are exactly where they were —
|
|
351
|
+
and there are four more guides than there were mid-release, because the four
|
|
352
|
+
stubs `check:package` had been excluding got written instead.
|
|
353
|
+
|
|
354
|
+
Which is the quiet half of this release. The five prebuilt connections used to
|
|
355
|
+
encode five sets of private judgment about what a good provider surface looks
|
|
356
|
+
like; that judgment is now two written convention sets, H1–H14 for hand-written
|
|
357
|
+
`api()` surfaces and P1–P13 for `remoteMcp()` proxies, each rule carrying its
|
|
358
|
+
reason and the agent cost it reduces. The placeholder guides in
|
|
359
|
+
`documentation/` — which covered, with some irony, the load-bearing subsystems,
|
|
360
|
+
while the newest features had the best docs — are written against the code as
|
|
361
|
+
it is, and none is left. And the ethos bullet that promised
|
|
362
|
+
"observable, never administrable" was retired for one that is true: operator
|
|
363
|
+
routes manage authentication material for capabilities declared in deployment
|
|
364
|
+
configuration, and a suite now snapshots every declared structure and demands
|
|
365
|
+
it back byte-identical after each operator mutation.
|
|
366
|
+
|
|
367
|
+
### Added
|
|
368
|
+
|
|
369
|
+
- **Two written provider convention sets.**
|
|
370
|
+
[`documentation/provider-conventions.md`](./documentation/provider-conventions.md)
|
|
371
|
+
states H1–H14 for hand-written `api()` surfaces, where Connecta owns every
|
|
372
|
+
name, schema, projection, and error, and P1–P13 for `remoteMcp()` proxies,
|
|
373
|
+
where the downstream owns the catalog and Connecta owns the endpoint,
|
|
374
|
+
credential, classification, guide, and budget. Every convention carries its
|
|
375
|
+
rule, its reason, and which of the four agent costs it reduces — discovery
|
|
376
|
+
tokens, wrong-tool selection, argument retries, result size — and names the
|
|
377
|
+
budgets at which the surface itself starts dropping characters: 160 for a
|
|
378
|
+
tool description in search, 240 in describe, 1,024 bytes per compact schema,
|
|
379
|
+
120 for a guide summary. A description longer than its budget is written for
|
|
380
|
+
nobody (#339).
|
|
381
|
+
- **The core subsystem guides, written.** `architecture.md`,
|
|
382
|
+
`request-admission.md`, `call-admission.md`, and `operations.md` were
|
|
383
|
+
identical seven-line placeholders pointing at git history; they now describe
|
|
384
|
+
the code as it is — the two lifetimes, the ordered route table and why each position is
|
|
385
|
+
behavior rather than taste, the import-graph purity rule and what it actually
|
|
386
|
+
prevents, both admission pools and why `/mcp` admits before it authenticates,
|
|
387
|
+
and the connector-partitioned downstream policy. `operations.md` also carries
|
|
388
|
+
the test map AGENTS.md had been deferring since the docs restructure: all 61
|
|
389
|
+
suites plus the two browser specs, with each Node-only suite's reason for not
|
|
390
|
+
running in workerd, so "this suite exists" and "this suite is justified" are
|
|
391
|
+
one lookup. `connector-guides.md` gains the general authoring half #339 left
|
|
392
|
+
open, including the `required` flag in full. With no stubs left, the four
|
|
393
|
+
`!documentation/…` negations in `files` went too (#348).
|
|
394
|
+
- **A maintainer-run provider drift check.** `npm run drift:check` diffs the
|
|
395
|
+
live Linear, Stripe, and Mixpanel catalogs against their vetted manifests by
|
|
396
|
+
name — added, no longer served, annotation conflicts, and schema changes — and
|
|
397
|
+
cross-checks its totals against the runtime `detectCatalogDrift()`, because
|
|
398
|
+
two readings of one manifest that disagree mean one of them is lying. Its
|
|
399
|
+
second half compares committed touched-endpoint manifests
|
|
400
|
+
(`scripts/drift/cloudflare-endpoints.json`, `scripts/drift/notion-endpoints.json`:
|
|
401
|
+
method, path, reviewed spec revision, reviewed deprecation, contract digest)
|
|
402
|
+
with each provider's published OpenAPI document, and `--record` refreshes
|
|
403
|
+
them. Deprecation is reported as a transition in either direction, so a
|
|
404
|
+
reviewed one stops being news. A missing credential, an unreachable
|
|
405
|
+
specification, or a `--provider` the selected half does not check stops the
|
|
406
|
+
run and says which one.
|
|
407
|
+
Written up in
|
|
408
|
+
[`documentation/provider-conventions.md`](./documentation/provider-conventions.md#the-maintainer-run-drift-check)
|
|
409
|
+
(#351).
|
|
410
|
+
- **Hosted-provider drift detection at refresh.** Linear, Stripe, and Mixpanel
|
|
411
|
+
each ship a vetted manifest and compare it with the live catalog while
|
|
412
|
+
serving a refresh that was going to happen anyway. `ConnectorStatus` gains
|
|
413
|
+
`catalogDrift` (four counts and the time they were observed), `/health` gains
|
|
414
|
+
the same per connector, `connecta doctor` reports it without failing on it,
|
|
415
|
+
and `ActivitySink` gains an optional `recordCatalogDrift` that receives one
|
|
416
|
+
payload-free event per change in the counts. Both read surfaces report what
|
|
417
|
+
the answering runtime observed — the observation is isolate-local, not
|
|
418
|
+
persisted — and both project the counts rather than echo the connector seam.
|
|
419
|
+
The policy is written up in
|
|
420
|
+
[`documentation/provider-conventions.md`](./documentation/provider-conventions.md#the-runtime-drift-policy)
|
|
421
|
+
(#343).
|
|
422
|
+
- **The Node template is Docker-ready.** `Dockerfile`, `docker-compose.yml`,
|
|
423
|
+
and `.dockerignore` ship with `connecta init`. The image installs
|
|
424
|
+
`@zackbart/connecta` from the registry like any other consumer, runs as the
|
|
425
|
+
non-root `node` user with state on a named volume, probes the always-open
|
|
426
|
+
`/health` route, and keeps Node in the foreground so `compose down` stops it
|
|
427
|
+
promptly. `PUBLIC_URL` and `CONNECTA_STATE_FILE` now configure the generated
|
|
428
|
+
`src/index.ts`, which is what makes one source serve both run paths (#344).
|
|
429
|
+
- **The package smoke exercises the generated container.** `check:package`
|
|
430
|
+
builds and runs the initialized deployment through Compose and points
|
|
431
|
+
`connecta doctor` at it; it fails rather than skips when Docker is missing
|
|
432
|
+
in CI (#344).
|
|
433
|
+
- **A deterministic named-surface measurement lane.**
|
|
434
|
+
`npm --prefix eval/current-version run report:cloudflare-surface` measures the
|
|
435
|
+
maintained Cloudflare connection one tool at a time and writes a JSON and
|
|
436
|
+
Markdown artifact. It needs no model, no network, and no credential: the real
|
|
437
|
+
constructor, schemas, validation path, handlers, and catalog service run, and
|
|
438
|
+
only `fetch` is a probe that records the request (#350).
|
|
439
|
+
- **Five provider audit reports** in
|
|
440
|
+
[`documentation/provider-audit.md`](./documentation/provider-audit.md), with
|
|
441
|
+
a verdict per convention, the fix for every miss, and every accepted
|
|
442
|
+
exception recorded with its argument (#342).
|
|
443
|
+
- **A convention test over the shipped surface.**
|
|
444
|
+
`test/provider-conventions.test.ts` walks both `api()` providers on every run
|
|
445
|
+
and enforces the mechanically checkable bar — naming, description budgets,
|
|
446
|
+
closed schemas described at every depth, compact-render budgets, declared
|
|
447
|
+
outputs, structured guides, and credential tests — so a convention met once
|
|
448
|
+
stays met. The one accepted gap, the undescribed name/value members of
|
|
449
|
+
Cloudflare's escape-hatch request parts, is listed by path in the suite with
|
|
450
|
+
its argument rather than left for a shallower check to miss (#342).
|
|
451
|
+
- **Guide coverage the schemas cannot carry.** Stripe and Mixpanel guides now
|
|
452
|
+
name their id-resolution rules, say the hosted catalog is not a fixed set, and
|
|
453
|
+
give the `auth_required` → `authorize_connector` recovery route. Notion's
|
|
454
|
+
guide states that it deliberately has no raw-REST escape hatch (#342).
|
|
455
|
+
- **A guarded fetch transport for hand-written connectors.** One factory
|
|
456
|
+
supplies the machinery every `api()` HTTP surface was re-deriving: strict
|
|
457
|
+
base-origin and path confinement checked after URL normalization, encoded
|
|
458
|
+
query and JSON body construction, `ctx.signal` propagation, a required
|
|
459
|
+
response-byte ceiling enforced while reading, a flat refusal to follow a
|
|
460
|
+
redirect or to let a request header shadow an authentication one, and an
|
|
461
|
+
unreachable provider normalized to a retryable `unavailable`. Authentication
|
|
462
|
+
and status interpretation stay in provider callbacks — the helper never
|
|
463
|
+
guesses what a 403 means. Cloudflare and Notion both run on it; it is held
|
|
464
|
+
internal this release rather than exported, and
|
|
465
|
+
[`documentation/connectors.md`](./documentation/connectors.md#the-guarded-fetch-transport)
|
|
466
|
+
records why (#341).
|
|
467
|
+
- **The operator feature set in both deployment shapes.** The Node template
|
|
468
|
+
gains commented, documented configuration for Clerk operator sign-in, the
|
|
469
|
+
credential vault, access-token issuance, and payload-free activity, the four
|
|
470
|
+
environment variables they read (passed through Compose and defaulted in the
|
|
471
|
+
Dockerfile so the container works the moment a block is uncommented), and
|
|
472
|
+
`src/file-activity.ts` — a deployment-owned `ActivityStore` that appends one
|
|
473
|
+
JSON line per call and rewrites the log back down to the newest 5,000 once it
|
|
474
|
+
runs a slack window past that, repairing a torn trailing line on the way in
|
|
475
|
+
rather than appending onto it. The Worker example wires the credential vault
|
|
476
|
+
to a new `CREDENTIAL_ENCRYPTION_KEY` secret beside the Clerk and access-token
|
|
477
|
+
configuration it already had, and carries the D1 activity wiring and its
|
|
478
|
+
binding as commented lines rather than as README-only instructions. Both
|
|
479
|
+
READMEs walk through enabling each half — including the part neither vault
|
|
480
|
+
can supply, a connector that declares a `credential` slot, which is what puts
|
|
481
|
+
the Credentials page in the nav — and both say why `connecta doctor` reports
|
|
482
|
+
none of it: doctor holds a bearer, and a client key does not get to learn a
|
|
483
|
+
deployment's configuration topology (#345).
|
|
484
|
+
|
|
485
|
+
### Changed
|
|
486
|
+
|
|
487
|
+
- **The operator boundary is stated as authentication material.** "Observable,
|
|
488
|
+
never administrable" had stopped describing the surface — operator routes
|
|
489
|
+
rotate credentials, issue and revoke access tokens, and drive downstream
|
|
490
|
+
OAuth, each under its own accepted decision. The ethos bullet, the invariant,
|
|
491
|
+
and a new decisions row now say the true thing: operator routes may manage
|
|
492
|
+
authentication material for capabilities *declared* in deployment
|
|
493
|
+
configuration, and may never change the connector set, the declared tool
|
|
494
|
+
catalog or annotations, requested OAuth scopes, admission policy,
|
|
495
|
+
authorization rules, or caller tool scope. The word "declared" is doing work
|
|
496
|
+
twice over — a broader-scoped replacement token widens downstream reach and
|
|
497
|
+
no browser page can honestly promise otherwise, and a remote MCP server's
|
|
498
|
+
catalog is discovered rather than declared, so storing a credential can take
|
|
499
|
+
an `mcp()` connector from no tools to N. That is discovery arriving, which is
|
|
500
|
+
exactly why those routes call `invalidateStored()`.
|
|
501
|
+
`test/operator-boundary.test.ts` snapshots every declared structure, drives
|
|
502
|
+
each operator mutation route against both a static and a re-listing
|
|
503
|
+
connector, and requires the snapshot back byte-identical; a second case
|
|
504
|
+
proves the snapshot can fail. No runtime behavior changed (#338).
|
|
505
|
+
- **The operator UI is a component app.** The hand-written DOM layer is gone,
|
|
506
|
+
replaced by a small Preact app compiled by the same esbuild step and inlined
|
|
507
|
+
into a shell that is now a mount point rather than a page. Nothing builds
|
|
508
|
+
HTML from strings any more, so the escaping every rendered value used to
|
|
509
|
+
depend on is structural; the served markup is identical on all four pages and
|
|
510
|
+
still carries no operator data. Credential, token, and OAuth flows gained
|
|
511
|
+
deliberate loading, error, empty, and success states — a failed save keeps
|
|
512
|
+
the form and what was typed in it, a failed list offers a retry, and an empty
|
|
513
|
+
collection says what would fill it. Each connector card also reads the drift
|
|
514
|
+
the last catalog refresh saw (#343) as four category counts, with `clean`,
|
|
515
|
+
`warning`, and "not observed in this runtime" kept as three distinct answers
|
|
516
|
+
— no tool name, schema, or payload rides that panel. Preact rides in as a
|
|
517
|
+
`devDependency` inlined into the committed bundle and never reaches a
|
|
518
|
+
deployment's dependency tree (#347).
|
|
519
|
+
|
|
520
|
+
- **`api()` enforces its construction contract.** Every tool requires a
|
|
521
|
+
non-empty `description` and an explicit boolean `annotations.readOnlyHint`;
|
|
522
|
+
a missing or non-boolean classification throws with the address that needs
|
|
523
|
+
fixing. The classification is never inferred from a tool name, description,
|
|
524
|
+
schema, HTTP method, or the other annotations (#340).
|
|
525
|
+
- **An unenforceable `inputSchema` fails at construction.** A schema the
|
|
526
|
+
validator cannot compile throws when the connector is built, whether or not
|
|
527
|
+
`validateArgs` is on — opting out of enforcement is not opting out of the
|
|
528
|
+
schema being real. A schema that only reveals itself on first use, such as an
|
|
529
|
+
unresolvable `$ref`, now fails that call as non-retryable `invalid_args`
|
|
530
|
+
instead of forwarding raw arguments to the handler (#340).
|
|
531
|
+
- **`linear()` requires `access`.** There is no safe default between Linear's
|
|
532
|
+
two endpoints: `"read-write"` hands out writes nobody asked for, and
|
|
533
|
+
`"read-only"` breaks a writing deployment at Linear, at runtime, where no
|
|
534
|
+
agent can repair it. Construction now throws naming both options. Add
|
|
535
|
+
`access: "read-write"` to keep an existing deployment's behavior (#342).
|
|
536
|
+
- **`mixpanel()` declares no call-admission budget.** The old hardcoded 600
|
|
537
|
+
calls per hour transcribed a limit Mixpanel meters *per user*, which a
|
|
538
|
+
per-runtime counter cannot approximate in either direction. Supply
|
|
539
|
+
`callAdmission` explicitly if the account needs a ceiling, as Linear already
|
|
540
|
+
did (#342).
|
|
541
|
+
- **`mixpanel()` titles itself by region.** The default title is now
|
|
542
|
+
`Mixpanel (us)`, `(eu)`, or `(in)`, and the guide opens with the residency,
|
|
543
|
+
because a project lives in exactly one and search never shows a description.
|
|
544
|
+
An unknown region throws at construction (#342).
|
|
545
|
+
- **Provider guides are structured everywhere.** All five declare an explicit
|
|
546
|
+
`summary` instead of leaning on the guide's first line, which was truncating
|
|
547
|
+
the routing fact at 120 characters on three of them (#342).
|
|
548
|
+
- **Smaller discovery payloads.** Over-budget tool descriptions
|
|
549
|
+
(`cloudflare_api_get`, `cloudflare_api_mutate`, `create_dns_record`, Notion's
|
|
550
|
+
`search`) were trimmed to the 240-character describe budget, and shared
|
|
551
|
+
property descriptions were cut so `cloudflare_api_upload` and
|
|
552
|
+
`query_data_source` render inside the 1,024-byte compact budget instead of
|
|
553
|
+
degrading and costing a describe round trip (#342).
|
|
554
|
+
- **Cloudflare and Notion never follow a redirect.** Both used `fetch`'s
|
|
555
|
+
default `redirect: "follow"` and now send `redirect: "manual"`; a 3xx fails
|
|
556
|
+
as non-retryable `connector_call_failed` instead of re-sending the
|
|
557
|
+
connector's credential to whatever origin the `Location` names (#341).
|
|
558
|
+
- **Cloudflare and Notion bound the response they will read.** 8 MiB and
|
|
559
|
+
4 MiB respectively, enforced against a declared `Content-Length` before the
|
|
560
|
+
first byte and again while the body streams. Both are ceilings on absurdity
|
|
561
|
+
rather than quotas — anything near them was already past whatever
|
|
562
|
+
`maxResultBytes` the deployment set — but a `cloudflare_api_get` reading an
|
|
563
|
+
R2 object or Worker script past 8 MiB now fails as non-retryable instead of
|
|
564
|
+
returning it (#341).
|
|
565
|
+
- **`cloudflare()` checks its `baseUrl` at construction.** A non-loopback
|
|
566
|
+
plain-http origin, URL-embedded credentials, or a query or fragment throws
|
|
567
|
+
where the connector is written rather than on the first call. A deployment
|
|
568
|
+
overriding `baseUrl` with an http proxy must move it to https or bind it to
|
|
569
|
+
loopback; the default Cloudflare base is unaffected (#341).
|
|
570
|
+
|
|
571
|
+
### Fixed
|
|
572
|
+
|
|
573
|
+
- **`connecta doctor` names the sandbox that actually ran the program.** It
|
|
574
|
+
printed "QuickJS executed" at every deployment it had ever checked, including
|
|
575
|
+
the Worker example, whose sandbox is a Dynamic Worker — the one field the
|
|
576
|
+
Worker README says doctor confirms, reported wrong. The deployment now says
|
|
577
|
+
what its executor is: `/health` carries the configured executor's name when
|
|
578
|
+
it has one (an explicit `name`, else a class-shaped executor's constructor
|
|
579
|
+
name), sanitized and bounded because it lands in a public response body and
|
|
580
|
+
an operator's terminal. Doctor reports that name, and a deployment whose
|
|
581
|
+
executor identifies as nothing gets `code executed` rather than a guess. The
|
|
582
|
+
Node template still reads `QuickJS executed`; the Worker example now reads
|
|
583
|
+
`DynamicWorkerExecutor executed` (#368).
|
|
584
|
+
- **The Node template's `.env.example` ships an empty `CONNECTA_TOKEN`.**
|
|
585
|
+
`docker-compose.yml` has always promised to refuse a deployment with no
|
|
586
|
+
inbound auth, but its `${CONNECTA_TOKEN:?…}` guard only fires on unset or
|
|
587
|
+
empty — and the file it reads shipped `replace-me`, which is neither. Copying
|
|
588
|
+
`.env.example` and running the README's Docker block therefore produced a
|
|
589
|
+
healthy, port-published deployment whose bearer token was a string published
|
|
590
|
+
in this repository. The value is now empty, so both Compose and `npm start`
|
|
591
|
+
refuse until an operator sets one (#367).
|
|
592
|
+
- **The Worker example names the optional peer it imports.**
|
|
593
|
+
`examples/worker` wires `clerkAuth` by default and calls itself the starting
|
|
594
|
+
template for a deployment, but its README listed only `@cloudflare/codemode`
|
|
595
|
+
as an extra install. `@clerk/backend` is an optional peer that never installs
|
|
596
|
+
with Connecta, and `auth/clerk` imports it at the top level, so a copied
|
|
597
|
+
deployment following the README verbatim died at
|
|
598
|
+
`Could not resolve "@clerk/backend"` before it ever reached Cloudflare. The
|
|
599
|
+
deploy section now carries the whole install line for a copy in its own
|
|
600
|
+
repository (#367).
|
|
601
|
+
- **A malformed Clerk publishable key fails like a configuration mistake.**
|
|
602
|
+
`clerkAuth` derives its Frontend API origin by base64-decoding
|
|
603
|
+
`publishableKey` and used to hand a bad key straight to `atob`, so the
|
|
604
|
+
placeholder the Workers example ships raised a bare `InvalidCharacterError`
|
|
605
|
+
from inside the returned object — and, on a deployment that builds per
|
|
606
|
+
request, turned every route including `/health` into a 500 whose stack named
|
|
607
|
+
base64 instead of the environment variable. The key's shape is now checked
|
|
608
|
+
where `allowedDomains` is, at construction, and the throw names the option.
|
|
609
|
+
It does not quote the rejected value back: the usual way to land here is
|
|
610
|
+
pasting the secret key into the publishable slot (#366).
|
|
611
|
+
- **Notion declares the `required` lists it was missing.** `search`,
|
|
612
|
+
`list_users`, `get_self`, and `create_page` now say which arguments a call
|
|
613
|
+
must carry, so a malformed call is refused locally instead of at Notion. The
|
|
614
|
+
fail-closed schema handling those lists rely on is the package default as of
|
|
615
|
+
#340 (#342).
|
|
616
|
+
- **Cloudflare's cursor pagination says so in the schema.**
|
|
617
|
+
`list_zone_rulesets`, `list_kv_keys`, `list_r2_buckets`, and
|
|
618
|
+
`list_r2_objects` now state on both the `cursor` argument and the
|
|
619
|
+
`nextCursor` result that they page by cursor and return no `page` object —
|
|
620
|
+
previously only the usage guide said it (#342).
|
|
621
|
+
- **Nested schema properties describe themselves.** The six fields inside
|
|
622
|
+
`bulk_write_kv_values`'s `entries[]` — including the expiry pair, whose units
|
|
623
|
+
and 60-second floor were the entire question — and Notion's
|
|
624
|
+
`sorts[].direction` were shipping bare types, because H5's description rule
|
|
625
|
+
had only ever been read at the top level (#342).
|
|
626
|
+
|
|
627
|
+
### Removed
|
|
628
|
+
|
|
629
|
+
- **`ApiOptions.strictValidation`.** Fail-closed schema handling is the only
|
|
630
|
+
behavior, so the opt-in has nothing left to switch. Delete the option;
|
|
631
|
+
nothing else changes (#340).
|
|
632
|
+
- **Three Cloudflare named tools; the connection ships 52, down from 55.**
|
|
633
|
+
`set_r2_cors` declared a free-form rule body, so its schema validated the ids
|
|
634
|
+
and waved through the part of the call that fails, and `get_r2_metrics` put
|
|
635
|
+
one account id into a path and returned the response unprojected — both
|
|
636
|
+
measurably weaker than the raw call that replaces them. `delete_r2_cors`
|
|
637
|
+
measured clean and went anyway, to keep the CORS write pair together: with
|
|
638
|
+
the write unnamed, a named delete would leave half of policy management on
|
|
639
|
+
each route. All three are one raw call away, and the guide says which one
|
|
640
|
+
(#350).
|
|
641
|
+
- **`examples/node` and `examples/docker`.** Both were diffs from the
|
|
642
|
+
template. `examples/` is the Worker deployment now, and the root
|
|
643
|
+
`.dockerignore` that existed only for the repository-context Docker build
|
|
644
|
+
went with them (#344).
|
|
645
|
+
- **`src/`, `.js.map`, `.d.ts.map`, and `assets/` — from the tarball only.**
|
|
646
|
+
All of them are still in the repository; none of them ships. The published
|
|
647
|
+
package is 167 files and 550 KB, down from 357 and 1.1 MB. The stub guides
|
|
648
|
+
left with them and came back written (#348), which is why the file count is
|
|
649
|
+
four higher than the trim alone left it.
|
|
650
|
+
Stepping into Connecta's TypeScript from an installed copy no longer works;
|
|
651
|
+
the emitted JavaScript and the `.d.ts` files beside it do. `check:package`
|
|
652
|
+
now fails on a packed `src/`, `.map`, or `assets/` path, derives the shipped
|
|
653
|
+
guide list from which guides are still stubs, so filling one in ships it, and
|
|
654
|
+
refuses a packed document whose relative link lands on a guide the tarball
|
|
655
|
+
does not carry — the three that pointed at `operations.md` now name it
|
|
656
|
+
instead (#346).
|
|
657
|
+
|
|
5
658
|
## 0.15.1 — 2026-08-12
|
|
6
659
|
|
|
7
660
|
The Cloudflare connection now supports legacy user-scoped Global API Keys as
|