Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

All notable changes to this package are documented here.

## 0.22.1 — 2026-08-31

This patch adds a maintained Vercel connection over the public REST API. It is
a new opt-in provider subpath: existing imports, connector declarations,
credentials, and deployment behavior do not change. Deployments that do not
import the Vercel provider can ignore this release.

### Added

- **Maintained Vercel REST connection.** `@zackbart/connecta/providers/vercel`
ships 18 projected project, deployment, log, domain, environment-variable,
and lifecycle tools plus separate GET, JSON-mutation, and upload hatches. It
uses one operator-managed access token, defaults account calls to an optional
team, never decrypts environment values in named reads, and adds no Vercel
SDK dependency.

## 0.22.0 — 2026-08-31

This release lets one deployment serve several authenticated people without
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ flowchart TB
Explicit["call_destructive_tool<br/>one visible call per write<br/>your client can ask you first"]
end

Integrations["The integrations you chose<br/>Linear · Stripe · Notion · your HTTP API · any MCP server"]
Integrations["The integrations you chose<br/>Linear · Stripe · Notion · Vercel · your HTTP API · any MCP server"]

Client -->|"one connection"| Sandbox
Client --> Explicit
Expand Down Expand Up @@ -63,8 +63,8 @@ Fifty issues in, one small object out. Your context window notices.
- **Wrap any HTTP API by hand.** A few lines per tool. No OpenAPI conversion —
generated tool sprawl is the problem, not the fix.
- **Use maintained connections** for Cloudflare, Linear, Mixpanel, Notion,
RevenueCat, and Stripe — known endpoints, auth defaults, and vetted read/write
classifications, imported one at a time.
RevenueCat, Stripe, and Vercel — known endpoints, auth defaults, and vetted
read/write classifications, imported one at a time.
- **Let the agent work in code.** Search, chain, filter, join, and reduce
inside the sandbox instead of round-tripping every call through the model.
- **Teach undeclared result shapes by using them.** Successful read-only calls
Expand Down
4 changes: 2 additions & 2 deletions documentation/connector-guides.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ few things both shapes fully own:

- [Hand-written HTTP providers](./provider-conventions.md#hand-written-http-providers)
(H1–H14) — `api()` surfaces where Connecta owns every name, schema,
projection, and error. Cloudflare and Notion.
projection, and error. Cloudflare, Notion, and Vercel.
- [Hosted-MCP proxies](./provider-conventions.md#hosted-mcp-proxies) (P1–P13) —
`remoteMcp()` wrappers where the downstream owns the catalog and Connecta
owns the endpoint, credential, classification, guide, and budget. Linear,
Stripe, and Mixpanel.
Stripe, Mixpanel, and RevenueCat.

Both sets are judged by one measure: what the convention saves the model that
interacts with connecta, priced in discovery tokens, wrong-tool selection,
Expand Down
14 changes: 8 additions & 6 deletions documentation/connectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Maintained provider guides:
- [Notion](./notion.md)
- [RevenueCat](./revenuecat.md)
- [Stripe](./stripe.md)
- [Vercel](./vercel.md)

## The `api()` construction contract

Expand Down Expand Up @@ -226,12 +227,13 @@ into a result or a typed failure. That split is not fastidiousness. Notion's
cannot fix it — while Cloudflare's means a token scope, and the two want
opposite next moves. A helper that guessed would be wrong for one of them.

Cloudflare and Notion both run on it. Their existing suites carried over
unchanged, which proves the migration kept the behavior those suites cover —
not that nothing changed. Three things did, and the changelog names them: a
3xx is refused where both providers used to follow it, both now fail past
their byte ceiling, and `cloudflare()`'s `baseUrl` is validated at
construction. Each suite gained one test for the ceiling, because the one
Cloudflare, Notion, and Vercel run on it. The first two existing suites carried
over unchanged when the helper was extracted, which proves that migration kept
the behavior those suites cover — not that nothing changed. Three things did,
and the changelog names them: a 3xx is refused where both providers used to
follow it, both now fail past their byte ceiling, and `cloudflare()`'s
`baseUrl` is validated at construction. Each suite gained one test for the
ceiling, because the one
guard the helper was written to add is the one a provider's own mapper can
most easily disarm: a bare `catch` around `response.json()` swallows the
transport's refusal along with a parse error, and turns a response nobody was
Expand Down
3 changes: 2 additions & 1 deletion documentation/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ in.
| `operator-boundary.test.ts` | the operator row of the decisions table, after every mutation route: authentication material managed without moving a declared structure, and the one honest exception — a credential write making a remote catalog appear, which is discovery arriving, not an operator editing the deployment |
| `operator-store.test.ts` | `src/operator-ui/app/store.ts` against a fake browser: the Clerk listener, ambient Access requests without a browser-readable token, `gate()`, the generation fence, and the request path |
| `provider-conventions.test.ts` | the conventions a test can hold: hand-written providers refusing schemas they cannot enforce (H5), their compact discovery schemas staying complete (H7), Cloudflare stating its second pagination convention in the schema (H10), and Notion saying it has no escape hatch (H14) |
| `provider-registry.test.ts` | all six maintained providers inside real deployments: boot, description, address, catalog, storage, credential, admission, and activity isolation; plus provider-specific discovery and guide contracts |
| `provider-registry.test.ts` | all seven maintained providers inside real deployments: boot, description, address, catalog, storage, credential, admission, and activity isolation; plus provider-specific discovery and guide contracts |
| `registry.test.ts` | construction and id validation, startup warnings, address resolution, version 2 catalog TTL/persistence/completeness, agent-only stale-while-revalidate with cross-request single-flight shared with blocking reads in both start orders, owned teardown, invalidation/fingerprint guards, blocking diagnostics, and broken-connector isolation |
| `remote-mcp.test.ts` | `remoteMcp()` against an in-process server through the `_transportFactory` seam: passthrough, downstream `isError`, Workers-safe output-schema validation, request-scoped client reuse and at-most-once scope close; plus the real transport's manual redirect policy, destination guard, credential containment, and downstream session termination |
| `remote-mcp-credential.test.ts` | `remoteMcp()` drawing a static key from `/credentials`: the declared slot and its refusal of named fields and bad header names, header framing (bearer, bare, and the two `Basic` forms) observed on the wire, an empty slot failing as `auth_required` rather than reaching the downstream, a value carrying a control character refused before framing and absent from every surface — `call_tool`, `status`, the Test result, the payload-free activity event, and the thrown error — rotation replacing the cached client and a connect already in flight while a wiped value fails the next call, the Test action's catalog probe and scope close, the cleartext-destination warning, and the vault and `authorize_connector` handoff end to end |
Expand All @@ -274,6 +274,7 @@ in.
| `ui-credentials.test.ts` | credential-management routes: save, test, delete, validation, authentication, same-origin checks, and multi-field credential shapes |
| `ui.test.ts` | the server shell and remaining `/ui/*` routes: gated `/ui/data` with broken-connector isolation and registry-owned catalog-observation containment, plus the URL safety gates |
| `validate.test.ts` | `validateToolInput()` — a returned (not thrown) `invalid_args` naming the path, `additionalProperties: false` enforcement, per-schema validator caching, and an unusable schema passed through with one warning |
| `vercel-provider.test.ts` | `vercel()` construction, team scoping, project and deployment projections, finite build and runtime logs, value-safe environment variables, domains, lifecycle writes, REST hatches, typed failures, and credential test |

### Node-bound (`NODE_ONLY_SUITES`)

Expand Down
10 changes: 5 additions & 5 deletions documentation/provider-conventions.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Provider conventions

The six maintained prebuilt connections grew one at a time, and until now
The seven maintained prebuilt connections grew one at a time, and until now
"excellent provider" meant whatever the last author thought. This document
writes the judgment down so it can be argued with, audited, and reused.

There are two genuinely different provider shapes, and one convention set
cannot honestly cover both:

- **Hand-written HTTP providers** — `api()` surfaces where Connecta owns every
tool name, schema, projection, and error. Today: Cloudflare, Notion.
tool name, schema, projection, and error. Today: Cloudflare, Notion, Vercel.
- **Hosted-MCP proxies** — `remoteMcp()` wrappers around a server somebody else
operates, where the names, schemas, results, and error prose arrive as they
are. Today: Linear, Stripe, Mixpanel, RevenueCat.
Expand Down Expand Up @@ -85,7 +85,7 @@ other source with no description or no `inputSchema`.
## Hand-written HTTP providers

Connecta owns the whole surface here, which means every miss is ours. These
apply to `api()`-based prebuilt connections (Cloudflare, Notion) and are the
apply to `api()`-based prebuilt connections (Cloudflare, Notion, Vercel) and are the
bar any future one is written to.

None of them asks an author to re-derive transport safety. URL confinement,
Expand Down Expand Up @@ -646,11 +646,11 @@ evidence and nothing else: no tool is generated from one, which is the
## What the audit checks

The provider audit ([#342](https://github.com/zackbart/connecta/issues/342))
runs this document against each of the six providers and returns a verdict per
runs this document against each of the seven providers and returns a verdict per
convention: **meets**, **misses** (with the fix), or **not applicable** (with
the reason). A convention is never quietly skipped, and an accepted miss is
recorded as a provider-specific exception with its argument, not left blank.
Its six reports live in [provider-audit.md](https://github.com/zackbart/connecta/blob/main/records/provider-audit.md), and the
Its seven reports live in [provider-audit.md](https://github.com/zackbart/connecta/blob/main/records/provider-audit.md), and the
mechanically checkable half of the hand-written bar runs on every test run in
[`test/provider-conventions.test.ts`](https://github.com/zackbart/connecta/blob/main/test/provider-conventions.test.ts) —
so a convention that was met once stays met, or fails loudly.
Expand Down
10 changes: 5 additions & 5 deletions documentation/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ exist so far:
| --- | --- | --- |
| **pre-template** | before 0.10.2 | no `connecta init` existed; hand-written, or copied from the retired `examples/node` |
| **A** | 0.10.2 – 0.15.1 | `.env.example`, `.gitignore`, `AGENTS.md`, `CLAUDE.md`, `README.md`, `package.json`, `src/index.ts`, `tsconfig.json` |
| **B** | 0.16.0 – 0.22.0 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |
| **B** | 0.16.0 – 0.22.1 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |

Generation A is a decade in template years and identifying it precisely does
not matter, because you are about to reconstruct it exactly rather than guess
Expand Down Expand Up @@ -106,7 +106,7 @@ know what to preserve, once to know what to re-verify at the end.
### Bump the pin and install

```sh
npm pkg set dependencies.@zackbart/connecta=0.22.0
npm pkg set dependencies.@zackbart/connecta=0.22.1
npm install
```

Expand All @@ -130,7 +130,7 @@ Generate the *current* template beside the base you already made, into the same
`$SCRATCH`:

```sh
(cd "$SCRATCH" && npx @zackbart/connecta@0.22.0 init current)
(cd "$SCRATCH" && npx @zackbart/connecta@0.22.1 init current)
```

You now have a three-way merge with a real base: `$SCRATCH/base` is what this
Expand Down Expand Up @@ -186,7 +186,7 @@ A deployment older than 0.10.2 has no base to diff against. Do not try to
manufacture one. Instead:

1. `SCRATCH=$(mktemp -d)`, then
`(cd "$SCRATCH" && npx @zackbart/connecta@0.22.0 init current)` — there is no
`(cd "$SCRATCH" && npx @zackbart/connecta@0.22.1 init current)` — there is no
`base` leg here, only the current template to read from.
2. Copy `$SCRATCH/current` into the deployment file by file, **skipping
`src/index.ts`**.
Expand All @@ -207,7 +207,7 @@ first, so cross them bottom-up: start at the oldest one still above this
deployment's pin and work back up the page, because each boundary assumes the
older ones are already done.

### 0.21.2 → 0.22.0
### 0.21.2 → 0.22.1

Connector and user policy remain config-as-code. If `identity.connectorAccess`
is configured, every interactive human may now manage the authentication of
Expand Down
Loading