@zackbart/connecta 0.29.0 → 0.31.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.
- package/CHANGELOG.md +99 -0
- package/README.md +126 -134
- package/bin/connecta.mjs +13 -2
- package/bin/version.mjs +1 -1
- package/dist/argument-redaction.js +230 -0
- package/dist/auth-elicitation.js +14 -9
- package/dist/authorization-handoff.js +111 -0
- package/dist/call-recovery.js +25 -0
- package/dist/catalog-cache.js +2 -2
- package/dist/catalog-service.js +103 -63
- package/dist/config-schema.d.ts +14 -7
- package/dist/config-schema.js +29 -10
- package/dist/config.d.ts +2 -0
- package/dist/config.js +12 -7
- package/dist/connectors/guarded-fetch.d.ts +9 -1
- package/dist/connectors/guarded-fetch.js +17 -5
- package/dist/connectors/negotiation-cache.js +1 -1
- package/dist/downstream-input-context.js +9 -0
- package/dist/downstream-input.js +13 -11
- package/dist/errors.d.ts +38 -12
- package/dist/errors.js +19 -9
- package/dist/execute.js +375 -43
- package/dist/executor-result.js +11 -9
- package/dist/executors/quickjs-child.js +12 -5
- package/dist/executors/quickjs-protocol.js +5 -6
- package/dist/executors/quickjs-runtime.js +6 -1
- package/dist/executors/quickjs.js +20 -4
- package/dist/guest-runtime.js +52 -2
- package/dist/guest-types.d.ts +47 -5
- package/dist/index.d.ts +1 -1
- package/dist/invocation.js +72 -14
- package/dist/meta-output.js +0 -15
- package/dist/meta-tools.js +166 -95
- package/dist/oauth-handoff.js +88 -11
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/view.d.ts +9 -0
- package/dist/operator-ui/view.js +11 -0
- package/dist/program-result.js +5 -0
- package/dist/program-writes.js +7 -48
- package/dist/provider.d.ts +8 -6
- package/dist/provider.js +3 -4
- package/dist/providers/_shared/google/workspace.d.ts +1 -1
- package/dist/providers/_shared/request-token.js +83 -0
- package/dist/providers/_shared/rest/dispatch.js +41 -0
- package/dist/providers/_shared/rest/operation-index.d.ts +133 -0
- package/dist/providers/_shared/rest/operation-index.js +527 -0
- package/dist/providers/_shared/rest/tools.d.ts +141 -0
- package/dist/providers/_shared/rest/tools.js +569 -0
- package/dist/providers/_shared/rest/value-safety.d.ts +151 -0
- package/dist/providers/_shared/rest/value-safety.js +580 -0
- package/dist/providers/cloudflare/graphql.js +385 -0
- package/dist/providers/cloudflare/index.d.ts +47 -51
- package/dist/providers/cloudflare/index.js +188 -1997
- package/dist/providers/cloudflare/openapi.generated.js +3347 -0
- package/dist/providers/cloudflare/rest.d.ts +37 -0
- package/dist/providers/cloudflare/rest.js +1056 -0
- package/dist/providers/cloudflare/skill.generated.js +7 -4
- package/dist/providers/cloudflare/value-safety.js +1247 -0
- package/dist/providers/infisical/index.d.ts +7 -0
- package/dist/providers/infisical/index.js +713 -0
- package/dist/providers/infisical/skill.generated.js +8 -0
- package/dist/providers/notion/index.d.ts +35 -31
- package/dist/providers/notion/index.js +60 -1499
- package/dist/providers/notion/openapi.generated.js +75 -0
- package/dist/providers/notion/rest.d.ts +24 -0
- package/dist/providers/notion/rest.js +1067 -0
- package/dist/providers/notion/skill.generated.js +5 -4
- package/dist/providers/notion/value-safety.js +31 -0
- package/dist/providers/stripe/index.d.ts +26 -20
- package/dist/providers/stripe/index.js +103 -130
- package/dist/providers/stripe/openapi.generated.js +649 -0
- package/dist/providers/stripe/rest.d.ts +14 -0
- package/dist/providers/stripe/rest.js +395 -0
- package/dist/providers/stripe/skill.generated.js +7 -5
- package/dist/providers/stripe/value-safety.js +705 -0
- package/dist/providers/vercel/index.d.ts +31 -22
- package/dist/providers/vercel/index.js +96 -853
- package/dist/providers/vercel/openapi.generated.js +456 -0
- package/dist/providers/vercel/rest.d.ts +20 -0
- package/dist/providers/vercel/rest.js +1002 -0
- package/dist/providers/vercel/skill.generated.js +4 -5
- package/dist/providers/vercel/value-safety.js +328 -0
- package/dist/registry.d.ts +8 -6
- package/dist/registry.js +134 -61
- package/dist/resource-read.js +4 -1
- package/dist/routes/mcp.js +11 -2
- package/dist/sent-secrets.d.ts +54 -13
- package/dist/sent-secrets.js +770 -231
- package/dist/skills.js +26 -16
- package/dist/sqlite.js +21 -6
- package/dist/storage/keys.js +20 -5
- package/dist/storage/memory.js +9 -4
- package/dist/storage/sql.js +18 -9
- package/dist/types.d.ts +17 -3
- package/dist/usage-guide.js +49 -40
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.js +2 -1
- package/dist/write-outcome.js +47 -0
- package/documentation/README.md +64 -0
- package/documentation/architecture.md +241 -97
- package/documentation/auth.md +138 -5
- package/documentation/code-mode.md +224 -107
- package/documentation/deploying.md +146 -0
- package/documentation/integrating.md +170 -0
- package/documentation/meta-tools.md +142 -30
- package/documentation/operating.md +135 -0
- package/documentation/operator-tests.md +4 -0
- package/documentation/operator-ui.md +132 -0
- package/documentation/provider-auth-migration.md +307 -0
- package/documentation/provider-migration-0.29.md +22 -5
- package/examples/worker/README.md +9 -2
- package/package.json +9 -2
- package/templates/node/README.md +9 -2
- package/templates/node/package.json +1 -1
- package/dist/providers/vercel/mcp-ownership.js +0 -212
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Operating an endpoint
|
|
2
|
+
|
|
3
|
+
Use this guide as an agent connected to an existing Connecta endpoint. Setup
|
|
4
|
+
and credentials are the deployment operator's responsibility; use
|
|
5
|
+
[Deploying Connecta](./deploying.md) if you are that operator.
|
|
6
|
+
[All agent routes](./README.md) are in the index.
|
|
7
|
+
|
|
8
|
+
## Choose the call path
|
|
9
|
+
|
|
10
|
+
Connecta exposes six top-level tools. Read [the tool table](./meta-tools.md#the-six-tools)
|
|
11
|
+
for exact arguments and result envelopes. Follow the endpoint's supplied
|
|
12
|
+
instructions and `skills` usage guide for deployment-specific context.
|
|
13
|
+
|
|
14
|
+
| Work | Use |
|
|
15
|
+
| ------------------------------------------------------------------ | --------------------------------------------------------- |
|
|
16
|
+
| One known read, with usable arguments and a small result | `call_tool` |
|
|
17
|
+
| Discover a tool, chain calls, combine services, or reduce a result | `execute_code` |
|
|
18
|
+
| One write on a read-only endpoint | `call_destructive_tool` |
|
|
19
|
+
| Obtain connector instructions | `skills` with the returned guide name |
|
|
20
|
+
| Start a required authentication handoff | `authorize_connector`, using the returned recovery action |
|
|
21
|
+
|
|
22
|
+
The endpoint's trust is part of its tool descriptions. On a `trusted` endpoint,
|
|
23
|
+
programs may write within the caller's grants, and `execute_code` is annotated
|
|
24
|
+
as a write. On `read-only`, every write is a separate top-level call. The host
|
|
25
|
+
controls approval. Never change pool, identity, or trust to work around a refusal.
|
|
26
|
+
[Routing between the call surfaces](./meta-tools.md#routing-between-the-call-surfaces)
|
|
27
|
+
owns the full decision rules.
|
|
28
|
+
|
|
29
|
+
## Discover before guessing
|
|
30
|
+
|
|
31
|
+
Use two to four distinctive action/object terms for each operation, and name
|
|
32
|
+
the connector when it is obvious. Read `catalogErrors`, `absence`, classification,
|
|
33
|
+
and required inputs before selecting a result. An empty search may mean a
|
|
34
|
+
failed catalog or a service outside the caller's grants.
|
|
35
|
+
|
|
36
|
+
For normal reads, keep discovery, calls, and reduction in one program when the
|
|
37
|
+
schemas suffice; return the answer rather than catalog matches. Use top-level
|
|
38
|
+
`search_tools` for catalog inspection or to discover a write on a read-only
|
|
39
|
+
endpoint, then dispatch each write with `call_destructive_tool`. An unfamiliar
|
|
40
|
+
read result may return a bounded sample for inspection before the next program.
|
|
41
|
+
|
|
42
|
+
Use the exact returned `address`, including punctuation. A TypeScript signature
|
|
43
|
+
is guidance for writing JavaScript; do not paste types into executable code.
|
|
44
|
+
If a schema is truncated or exact constraints matter, describe the address with
|
|
45
|
+
`format: "json"`. Read a returned `guide` through `skills` or
|
|
46
|
+
`connecta.skill` before relying on provider-specific conventions.
|
|
47
|
+
[Discovery context](./meta-tools.md#discovery-context) and
|
|
48
|
+
[guest search](./code-mode.md#connectasearch) define these results.
|
|
49
|
+
|
|
50
|
+
## Call, combine, and reduce
|
|
51
|
+
|
|
52
|
+
A program is one JavaScript `async` arrow expression. It has the `connecta`
|
|
53
|
+
guest API and captured console output, with no portable imports, filesystem,
|
|
54
|
+
network access, or credentials. Downstream calls return an envelope; read its
|
|
55
|
+
`data` rather than treating the envelope as the provider's result.
|
|
56
|
+
|
|
57
|
+
This illustrative tracker has a `list_issues` read accepting `state` and
|
|
58
|
+
returning `data.nodes`. Discover its address, call it, and group the identifiers
|
|
59
|
+
in one program:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
async () => {
|
|
63
|
+
const page = await connecta.search({
|
|
64
|
+
connector: "tracker",
|
|
65
|
+
query: "list issues",
|
|
66
|
+
safety: "readOnly",
|
|
67
|
+
});
|
|
68
|
+
if (page.catalogErrors.length || page.absence) {
|
|
69
|
+
return { gap: page.catalogErrors, absence: page.absence };
|
|
70
|
+
}
|
|
71
|
+
const tool = page.tools.find(t => t.name === "list_issues");
|
|
72
|
+
if (!tool) return { gap: "list_issues unavailable" };
|
|
73
|
+
const { data, format } = await connecta.call(tool.address, {
|
|
74
|
+
state: "started",
|
|
75
|
+
});
|
|
76
|
+
if (format !== "json" || !Array.isArray(data?.nodes)) {
|
|
77
|
+
return { gap: "Expected a JSON issues collection" };
|
|
78
|
+
}
|
|
79
|
+
const byOwner = Object.create(null);
|
|
80
|
+
for (const issue of data.nodes) {
|
|
81
|
+
const owner = issue.assignee?.name ?? "unassigned";
|
|
82
|
+
(byOwner[owner] ??= []).push(issue.identifier);
|
|
83
|
+
}
|
|
84
|
+
return byOwner;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`tracker.list_issues` is illustrative, not a built-in address. Discover the real
|
|
89
|
+
connector's schemas and pagination before adapting this program. Keep loops and
|
|
90
|
+
parallel work bounded. [Parallel calls](./code-mode.md#parallel-calls),
|
|
91
|
+
[results and projection](./code-mode.md#results-and-projection), and
|
|
92
|
+
[cancellation and limits](./code-mode.md#cancellation-and-limits) own those rules.
|
|
93
|
+
|
|
94
|
+
Discovery may label an output schema `observed`. It records field names and
|
|
95
|
+
broad types from successful reads in bounded runtime memory, with no scalar
|
|
96
|
+
values. Treat it as evidence, not a provider contract; handle missing fields.
|
|
97
|
+
|
|
98
|
+
## Large results and resources
|
|
99
|
+
|
|
100
|
+
Direct calls may return a preview and a result handle. Page the handle through
|
|
101
|
+
`connecta.result` in a program using the returned offset and byte limits, or
|
|
102
|
+
reduce the data in the original program. Handles are short-lived and bound to
|
|
103
|
+
the admitted caller, endpoint/pool, and current grants. Never invent one or pass
|
|
104
|
+
it between identities. [Paging](./meta-tools.md#paging-with-connectaresult)
|
|
105
|
+
owns the envelope and expiry rules.
|
|
106
|
+
|
|
107
|
+
For resources, use the exposed resource inventory and `connecta.read`; do not
|
|
108
|
+
fetch an arbitrary URL. [Resource reads](./code-mode.md#connectaread) describe
|
|
109
|
+
which URIs may be read. Connector guides and native skills are described in
|
|
110
|
+
[skills](./meta-tools.md#connector-guides-and-skills).
|
|
111
|
+
|
|
112
|
+
## Recover without replaying a write
|
|
113
|
+
|
|
114
|
+
Read typed failures and their `nextAction`. Authorization recovery can point
|
|
115
|
+
to consent, operator credential setup, or deployment configuration. Discovery
|
|
116
|
+
and status do not begin consent on their own. Follow
|
|
117
|
+
[authorization recovery](./meta-tools.md#authorization-recovery),
|
|
118
|
+
[routing recovery](./meta-tools.md#routing-recovery), and
|
|
119
|
+
[argument recovery](./meta-tools.md#argument-recovery) for the specific failure.
|
|
120
|
+
|
|
121
|
+
A dispatched write is never automatically replayed. An ambiguous timeout may
|
|
122
|
+
mean the provider applied it; inspect state or ask for the missing decision
|
|
123
|
+
before issuing it again. [Retry semantics](./code-mode.md#retry-semantics) and
|
|
124
|
+
[writes](./code-mode.md#writes) describe program outcomes and write accounting.
|
|
125
|
+
|
|
126
|
+
## Implementation and evidence
|
|
127
|
+
|
|
128
|
+
The endpoint's built-in [usage skill](https://github.com/zackbart/connecta/blob/main/src/skills.ts)
|
|
129
|
+
is maintained alongside [meta-tools](https://github.com/zackbart/connecta/blob/main/src/meta-tools.ts)
|
|
130
|
+
and [execution](https://github.com/zackbart/connecta/blob/main/src/execute.ts).
|
|
131
|
+
[Usage-guide tests](https://github.com/zackbart/connecta/blob/main/test/usage-guide.test.ts),
|
|
132
|
+
[direct-call tests](https://github.com/zackbart/connecta/blob/main/test/meta-tools-call.test.ts),
|
|
133
|
+
and [guest-contract tests](https://github.com/zackbart/connecta/blob/main/test/guest-api-contract.test.ts)
|
|
134
|
+
check the contracts. Executor-specific evidence is indexed in
|
|
135
|
+
[code-mode verification](./code-mode.md#verification).
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Operator UI tests
|
|
2
2
|
|
|
3
|
+
Use this repository-maintenance guide when changing operator pages, data routes,
|
|
4
|
+
or browser evidence. Read the [operator UI contract](./operator-ui.md) first.
|
|
5
|
+
[The agent index](./README.md) routes deployment and endpoint tasks.
|
|
6
|
+
|
|
3
7
|
`test/fixtures/operator-visual.ts` owns the visual data. It builds the config,
|
|
4
8
|
live overlay, viewer, and legacy auth details through the current server routes,
|
|
5
9
|
using the types in `src/operator-ui/contract.ts` and `model.ts`. Collections use
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Operator UI
|
|
2
|
+
|
|
3
|
+
Use this guide to enable or maintain the optional operator interface. For
|
|
4
|
+
client tool calls use [Operating an endpoint](./operating.md); for identities,
|
|
5
|
+
credential ownership, and grants use [Auth](./auth.md).
|
|
6
|
+
[All agent routes](./README.md) are in the index.
|
|
7
|
+
|
|
8
|
+
## Task routes
|
|
9
|
+
|
|
10
|
+
| Task | Read |
|
|
11
|
+
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
12
|
+
| Enable UI, vault, or history in a deployment | [Setup](#setup), then the platform template |
|
|
13
|
+
| Consume config, provenance, status, or activity | [Operator data contract](#operator-data-contract) |
|
|
14
|
+
| Change a UI page or data route | [Source and tests](#source-and-tests), [browser verification](./operator-tests.md) |
|
|
15
|
+
| Diagnose permission refusals | [Management permissions](./auth.md#management-permissions), [activity disclosure below](#operator-data-contract) |
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
Set `ui: operatorUi()` using `@zackbart/connecta/ui`. Branding belongs in
|
|
20
|
+
`operatorUi({ branding })`; the [Node template](../templates/node/README.md#select-optional-modules)
|
|
21
|
+
and [Worker example](../examples/worker/README.md#select-optional-modules)
|
|
22
|
+
own the runnable configuration, variables, and branding shape. The UI is an
|
|
23
|
+
explicit optional import and stays outside the root package import graph.
|
|
24
|
+
|
|
25
|
+
Overview, Connectors, Tools, Access, Activity, and Config show only what the
|
|
26
|
+
caller may inspect. Connector detail tabs cover configuration, schemas,
|
|
27
|
+
authentication, activity, and diagnostics. Config labels values as default or
|
|
28
|
+
configured. Deployment code owns connectors, grants, pools, and classification;
|
|
29
|
+
the UI changes only authorized authentication material.
|
|
30
|
+
|
|
31
|
+
Install the vault for declared credential slots and activity history for
|
|
32
|
+
persisted call records. Neither module grants permission to manage or read
|
|
33
|
+
it. Credential administration, personal connection, access-token management,
|
|
34
|
+
and activity access are separate identity decisions, denied by default where
|
|
35
|
+
specified in [auth](./auth.md#management-permissions). Machine tokens never
|
|
36
|
+
grant interactive credential or token management authority.
|
|
37
|
+
|
|
38
|
+
## Operator data contract
|
|
39
|
+
|
|
40
|
+
`GET /ui/api/config`, owned by `operatorUi()`, returns `OperatorUiContract`
|
|
41
|
+
from `connecta/ui`. `src/operator-ui/contract.ts` is also the browser's type
|
|
42
|
+
source. The response has `schemaVersion: 1`, `config`, `configSources`, `live`, and `you`.
|
|
43
|
+
`config` is the construction-time `describeConfig()` snapshot, filtered to
|
|
44
|
+
visible connectors, granted tools, classification overrides, and admitted
|
|
45
|
+
pools. Pool tools are the intersection with the caller's identity grants.
|
|
46
|
+
`configSources` labels each serialized leaf as `default` or `config`, based on
|
|
47
|
+
option presence rather than equality with the default. Factory descriptions carry
|
|
48
|
+
relative `optionSources` paths so resolved module and transport defaults retain
|
|
49
|
+
their provenance. The snapshot copies only resolved values; the UI consumes
|
|
50
|
+
these presence facts separately. Its paths use connector
|
|
51
|
+
ids and pool names and are filtered after disclosure; hidden values leave no
|
|
52
|
+
provenance keys. It contains no source code or credential material.
|
|
53
|
+
Every response is private, `no-store` JSON. Only GET is allowed, with the
|
|
54
|
+
same auth gate and identity partition as `/ui/data` and `/ui/connectors/:id`.
|
|
55
|
+
|
|
56
|
+
`live.connectors` carries status and problem codes, complete registry tools
|
|
57
|
+
with their final read/write classification, catalog age in milliseconds, and
|
|
58
|
+
last-call time/outcome. Catalog descriptions and schemas are allowed for an
|
|
59
|
+
authenticated reader; grammar-failing names and addresses become `<withheld>`.
|
|
60
|
+
`auth.registrationPath` reports the selected downstream OAuth client mechanism when known.
|
|
61
|
+
Status prose, error text, credential values or suffixes, arguments, results,
|
|
62
|
+
and code are excluded. Static and unobserved catalogs have a null age;
|
|
63
|
+
persisted catalogs retain their original fetch time. Probes run with bounded
|
|
64
|
+
concurrency and the configured probe deadline, and release their scopes.
|
|
65
|
+
|
|
66
|
+
Last-call lookup requires the existing activity permission and read gate. It
|
|
67
|
+
scans up to 1,000 recent rows, filters connector/tool grants, and restricts
|
|
68
|
+
personal connectors to the caller's activity identity. Each retained fact
|
|
69
|
+
copies a validated timestamp and outcome only. A null call means unknown or
|
|
70
|
+
absent in that window, not proof of no calls. `live.activity` distinguishes
|
|
71
|
+
available, unconfigured, forbidden, and unavailable history. `you` names no
|
|
72
|
+
identity or auth material; it reports grants, root and admitted-pool trust,
|
|
73
|
+
and effective activity, token, and per-connector auth permissions.
|
|
74
|
+
|
|
75
|
+
`connecta doctor --config` fetches this authenticated contract and prints only
|
|
76
|
+
`config` as indented JSON. It requires the UI module and the existing doctor
|
|
77
|
+
authentication environment variables; it runs no diagnostic program, follows
|
|
78
|
+
no redirects, and prints no raw HTTP failure body.
|
|
79
|
+
|
|
80
|
+
The operator shell uses React, TanStack Router/Query/Table, Radix, cmdk and
|
|
81
|
+
Tailwind v4. Inter, CSS, JavaScript and dependency notices are hashed assets
|
|
82
|
+
under `/ui/assets/*`, served identically with immutable cache headers on Node
|
|
83
|
+
and Workers. HTML contains only mount points and escaped inert configuration;
|
|
84
|
+
it remains uncached. `generated.ts` is ignored and generated before build and
|
|
85
|
+
test; `check:operator-ui` detects stale assets and shared page styles. The UI
|
|
86
|
+
stays behind `./ui`, outside the root import graph. The identity-fenced store
|
|
87
|
+
owns authenticated reads and existing mutations. Overview, Connectors, connector
|
|
88
|
+
detail, Tools, Access and Config consume the typed contract. Activity retains
|
|
89
|
+
its authenticated data routes. Connector detail tabs live
|
|
90
|
+
in the URL hash; Activity filters live in the query string and apply to loaded
|
|
91
|
+
history. Both `/ui/activity` and `/ui/api/activity` require Activity access and
|
|
92
|
+
pass the optional activity `readGate`. Interactive operators and machine callers
|
|
93
|
+
admitted by `identity.activityAccess` share the same history disclosure rules.
|
|
94
|
+
Connector/tool grants and grants for the recorded pool filter each event. Shared
|
|
95
|
+
connector history can include other principals' events, with recorded request
|
|
96
|
+
IDs, validated client name/version and package version, and actor kind, ID and
|
|
97
|
+
namespace. Interactive reads may also add directory actor labels; machine reads
|
|
98
|
+
never add them. Personal connector history is owner-only: the event must have a
|
|
99
|
+
checked `principal` actor basis and actor ID/namespace matching the reader's
|
|
100
|
+
admitted principal. Rows without a provable personal owner are withheld. Activity
|
|
101
|
+
carries no arguments, results, code or raw downstream errors. The last-call
|
|
102
|
+
overlay uses the same event filter but returns only timestamp and outcome.
|
|
103
|
+
Calls group only by recorded request ids, with missing ids shown as
|
|
104
|
+
separate calls. Classification and result size are shown only when recorded. The verdict is
|
|
105
|
+
captured after registry resolution, and result size counts UTF-8 bytes of the
|
|
106
|
+
downstream value before paging or truncation. Nullable SQL columns preserve old
|
|
107
|
+
rows. Catalog changes use the same paging envelope with `kind: "catalog_drift"`,
|
|
108
|
+
`source: "catalog_refresh"` and a checked `catalog_changed` fact containing only
|
|
109
|
+
added, removed and changed tool counts. The first complete catalog is a baseline;
|
|
110
|
+
one refresh-publication hook emits each later change. It includes the request's
|
|
111
|
+
id and typed actor when available, otherwise a fresh id and system actor. No
|
|
112
|
+
names, descriptions or schemas enter the event. Private catalog changes require
|
|
113
|
+
a matching principal owner even when the connector uses shared auth. Empty credential declarations
|
|
114
|
+
report `credential_required` before running a connector status or catalog probe.
|
|
115
|
+
The Access adapter reports inbound provider kinds, admitted pools, grants, trust
|
|
116
|
+
and endpoint setup; token controls retain their existing permission gate.
|
|
117
|
+
Configuration remains in deployment code. The UI mutates only credentials,
|
|
118
|
+
OAuth connections and client tokens through the existing routes.
|
|
119
|
+
|
|
120
|
+
## Source and tests
|
|
121
|
+
|
|
122
|
+
The contract type is [contract.ts](https://github.com/zackbart/connecta/blob/main/src/operator-ui/contract.ts).
|
|
123
|
+
[UI routes](https://github.com/zackbart/connecta/blob/main/src/routes/ui.ts) and
|
|
124
|
+
[UI implementation](https://github.com/zackbart/connecta/blob/main/src/ui.ts)
|
|
125
|
+
serve the authenticated shell and data. The browser lives in
|
|
126
|
+
[src/operator-ui](https://github.com/zackbart/connecta/tree/main/src/operator-ui).
|
|
127
|
+
[UI tests](https://github.com/zackbart/connecta/blob/main/test/ui.test.ts),
|
|
128
|
+
[credential-route tests](https://github.com/zackbart/connecta/blob/main/test/ui-credentials.test.ts),
|
|
129
|
+
[config snapshot tests](https://github.com/zackbart/connecta/blob/main/test/describe-config.test.ts),
|
|
130
|
+
and [browser flows](https://github.com/zackbart/connecta/blob/main/test/browser/operator-ui.spec.ts)
|
|
131
|
+
defend filtering and behavior. Use [Operator UI tests](./operator-tests.md)
|
|
132
|
+
for the browser state matrix and Linux snapshot procedure.
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# Provider auth migration
|
|
2
|
+
|
|
3
|
+
Use this upgrade guide when moving a Stripe, Notion, Vercel, or Cloudflare
|
|
4
|
+
deployment from 0.30 to 0.31, where `auth` selects each provider's
|
|
5
|
+
implementation ([#801](https://github.com/zackbart/connecta/issues/801)).
|
|
6
|
+
The [0.31.0 release notes](https://github.com/zackbart/connecta/blob/main/release-notes/0.31.0.md) summarize the change.
|
|
7
|
+
[Deployment upgrades](./deploying.md#upgrade-an-existing-deployment) cover other
|
|
8
|
+
version changes; [integrating services](./integrating.md) covers new connectors.
|
|
9
|
+
|
|
10
|
+
A dual provider requires `auth`. `{ type: "oauth" }` connects the vendor's
|
|
11
|
+
hosted MCP server, OAuth only. A key type connects Connecta's REST connector
|
|
12
|
+
with an operator-managed credential. There is no default, and one connector id
|
|
13
|
+
uses one implementation: configure two ids for both. The
|
|
14
|
+
[decision record](https://github.com/zackbart/connecta/blob/main/decisions/0005-auth-selects-implementation.md)
|
|
15
|
+
explains why.
|
|
16
|
+
|
|
17
|
+
## Stripe
|
|
18
|
+
|
|
19
|
+
Stripe's hosted MCP server stops accepting secret keys and untagged
|
|
20
|
+
restricted keys on 2026-10-31; Stripe still documents agent-tagged restricted
|
|
21
|
+
keys for it. Connecta's hosted Stripe connection is OAuth only either way, and
|
|
22
|
+
every key, tagged or not, uses the REST connector. Every `stripe()` call must
|
|
23
|
+
now name `auth`:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
connectors: [
|
|
27
|
+
stripe("stripe", {
|
|
28
|
+
purpose: "Organization billing",
|
|
29
|
+
auth: { type: "oauth" },
|
|
30
|
+
}),
|
|
31
|
+
stripe("stripe_live", {
|
|
32
|
+
purpose: "Live billing",
|
|
33
|
+
auth: { type: "apiKey" },
|
|
34
|
+
mode: "production",
|
|
35
|
+
}),
|
|
36
|
+
stripe("stripe_sandbox", {
|
|
37
|
+
purpose: "Rehearsal",
|
|
38
|
+
auth: { type: "apiKey" },
|
|
39
|
+
mode: "sandbox",
|
|
40
|
+
}),
|
|
41
|
+
stripe("stripe_merchant", {
|
|
42
|
+
purpose: "One connected merchant",
|
|
43
|
+
auth: { type: "apiKey" },
|
|
44
|
+
mode: "production",
|
|
45
|
+
connectedAccount: "acct_…",
|
|
46
|
+
}),
|
|
47
|
+
];
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| 0.30 configuration | Now |
|
|
51
|
+
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
|
|
52
|
+
| No `auth`, or `auth: { type: "oauth" }` | `auth: { type: "oauth" }`. Same endpoint, reviewed catalog, guide conventions, and grant. |
|
|
53
|
+
| `auth: { type: "headers", headers }` with `mode` | `auth: { type: "apiKey" }` with `mode`. Paste the key into the connection in the operator UI; literal keys are gone. |
|
|
54
|
+
| `auth: { type: "credential" }` with `mode` | `auth: { type: "apiKey" }` with `mode`. A key stored for the same connector id carries over; run its Test action. |
|
|
55
|
+
| `connectedAccount` with `headers` auth | `connectedAccount` with `auth: { type: "apiKey" }`; it now works with an operator-managed key. |
|
|
56
|
+
| `mode` or `connectedAccount` with OAuth | Refused by name at construction, as before. |
|
|
57
|
+
|
|
58
|
+
The key connector keeps Stripe's tool names (`stripe_api_search`,
|
|
59
|
+
`stripe_api_details`, `stripe_api_read`, `stripe_api_write`,
|
|
60
|
+
`get_stripe_account_info`, and `get_balance_summary`) with Connecta's own
|
|
61
|
+
contracts: search finds operations in a pinned API index, every call is
|
|
62
|
+
checked against that index before it is sent, results arrive as
|
|
63
|
+
`{ status, data, page? }`, and POST writes send the caller's `idempotencyKey`
|
|
64
|
+
or a generated one as `Idempotency-Key` and return it (DELETE sends none).
|
|
65
|
+
Every request, v1 and v2, sends `Stripe-Version: 2026-09-30.endive`, the
|
|
66
|
+
version of the pinned index, whatever the account's default API version, so
|
|
67
|
+
response shapes and accepted parameters follow that version. Check fields
|
|
68
|
+
your programs rely on with `stripe_api_details`.
|
|
69
|
+
A key whose `sk_live_`/`rk_live_` or `sk_test_`/`rk_test_` prefix contradicts
|
|
70
|
+
`mode` is refused before any request. Organization keys (`sk_org_…`) need a
|
|
71
|
+
`Stripe-Context` header the connector does not send; use an account key.
|
|
72
|
+
|
|
73
|
+
Lost on the key path: natural-language Sigma (`stripe_analytics`), metrics,
|
|
74
|
+
documentation search, the implementation planner, reports, and feedback exist
|
|
75
|
+
only on the hosted OAuth connection. Programs calling those tools on a key
|
|
76
|
+
connector need an OAuth connector beside it. The
|
|
77
|
+
[Stripe skill](https://github.com/zackbart/connecta/blob/main/src/providers/stripe/SKILL.md)
|
|
78
|
+
owns the conventions for both.
|
|
79
|
+
|
|
80
|
+
## Notion
|
|
81
|
+
|
|
82
|
+
Every `notion()` call must now name `auth`. 0.30 defaulted to hosted MCP and
|
|
83
|
+
selected the REST interface with `surface: "api"`; `surface` is gone:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
connectors: [
|
|
87
|
+
notion("notion", { purpose: "Workspace content as the signed-in user", auth: { type: "oauth" } }),
|
|
88
|
+
notion("notion_bot", { purpose: "Internal integration content", auth: { type: "token" } }),
|
|
89
|
+
]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| 0.30 configuration | Now |
|
|
93
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
94
|
+
| No `surface`, or `surface: "mcp"` | `auth: { type: "oauth" }`. Same endpoint, reviewed catalog, grant, and optional `callAdmission`. |
|
|
95
|
+
| `surface: "api"` | `auth: { type: "token" }`. The integration token stored for the same connector id carries over; run its Test action. |
|
|
96
|
+
| `credentialLabel` or `defaultPageSize` | Token only, as before. Under OAuth they are refused by name at construction. |
|
|
97
|
+
| `integration_search`, `_get_page`, `_get_page_content`, `_get_data_source_schema`, `_query_data_source`, `_create_page`, `_append_blocks` | Unchanged names and contracts. `integration_append_blocks` also takes `checklist`. |
|
|
98
|
+
| `integration_get_database` | `notion_api_read` `GET /v1/databases/{database_id}`. |
|
|
99
|
+
| `integration_get_page_property` | `notion_api_read` `GET /v1/pages/{page_id}/properties/{property_id}`; `truncated_properties` names it. |
|
|
100
|
+
| `integration_list_users`, `integration_get_self` | `notion_api_read` `GET /v1/users` or `GET /v1/users/me`. |
|
|
101
|
+
| `integration_list_comments`, `integration_add_comment` | `notion_api_read` `GET /v1/comments`; `notion_api_write` `POST /v1/comments`. |
|
|
102
|
+
| `integration_update_page_properties`, `integration_trash_page` | `notion_api_write` `PATCH /v1/pages/{page_id}` with `properties`, or `in_trash` to trash or restore. |
|
|
103
|
+
|
|
104
|
+
The token connector gains Connecta's generic REST tools over Notion's pinned
|
|
105
|
+
API index (`notion_api_search`, `notion_api_details`, `notion_api_read`,
|
|
106
|
+
`notion_api_write`), so every public operation is reachable with the bot's
|
|
107
|
+
token: views, page moves and Markdown, meeting notes, custom agents and
|
|
108
|
+
sessions, file uploads by `external_url`, and data source changes. Every call
|
|
109
|
+
is checked against the index before it is sent, and results arrive as
|
|
110
|
+
`{ status, data, page? }`. The read-only POST queries (search, data source,
|
|
111
|
+
meeting notes, agents, sessions, and session events) use `notion_api_read`;
|
|
112
|
+
`page.in: "body"` says their cursor goes back in the body. Notion's OAuth token
|
|
113
|
+
endpoints and multipart file sends are refused. The 0.29 reconciliation table
|
|
114
|
+
and the `surface: "api"` complement rules no longer apply to Notion.
|
|
115
|
+
|
|
116
|
+
Lost per mode. A token connector acts as the integration bot, never as a
|
|
117
|
+
person, and has none of the hosted MCP's search across connected apps, page
|
|
118
|
+
duplication, team and skill search, attachment downloads, or page-to-skill
|
|
119
|
+
conversion. An OAuth connector acts as the user, and has none of the generic
|
|
120
|
+
REST tools or the `integration_*` projections and authoring helpers. Configure
|
|
121
|
+
both ids when a deployment needs both; a failed call is never retried on the
|
|
122
|
+
other. The [Notion skill](https://github.com/zackbart/connecta/blob/main/src/providers/notion/SKILL.md)
|
|
123
|
+
owns the conventions for both.
|
|
124
|
+
|
|
125
|
+
## Vercel
|
|
126
|
+
|
|
127
|
+
Every `vercel()` call must now name `auth`. `surface` is gone, and so are the
|
|
128
|
+
0.29 ownership rules that made the REST complement refuse whatever the hosted
|
|
129
|
+
server also covered: each implementation is complete on its own.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
connectors: [
|
|
133
|
+
vercel("vercel", { purpose: "Deployment diagnosis", auth: { type: "oauth" } }),
|
|
134
|
+
vercel("vercel_rest", { purpose: "Production apps", auth: { type: "token" }, teamId: "team_…" }),
|
|
135
|
+
]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
| 0.30 configuration | Now |
|
|
139
|
+
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
140
|
+
| No `surface`, or `surface: "mcp"` | `auth: { type: "oauth" }`. Same endpoint, reviewed catalog, and grant. |
|
|
141
|
+
| `surface: "api"` with `teamId` or `baseUrl` | `auth: { type: "token" }` with the same options. A token stored for the same connector id carries over; run its Test action. |
|
|
142
|
+
| `defaultPageSize` | Removed (it already had no effect). Pass `limit` in `query`, and follow `page.next` as `page.param`. |
|
|
143
|
+
| `teamId` or `baseUrl` with OAuth | Refused by name at construction. |
|
|
144
|
+
| `vercel_api_get`, `vercel_api_mutate` | `vercel_api_read` and `vercel_api_write`: `query` is a JSON object, not name/value pairs, and `teamId: null` replaces `personalAccount: true`. |
|
|
145
|
+
| `verify_project_domain`, `remove_project_domain`, `delete_deployment` | `vercel_api_write` with the operation from `vercel_api_search`, such as `DELETE /v13/deployments/{id}`. |
|
|
146
|
+
| `vercel_api_upload` with any path and headers | `vercel_api_upload` on octet-stream operations in the index (`POST /v2/files`, project avatars, Remote Cache artifacts); Connecta computes `x-vercel-digest`. |
|
|
147
|
+
|
|
148
|
+
The token connector serves `vercel_api_search`, `vercel_api_details`,
|
|
149
|
+
`vercel_api_read`, and `vercel_api_write` over Vercel's OpenAPI document,
|
|
150
|
+
pinned by content hash because Vercel does not version it. Every call is
|
|
151
|
+
checked against the pinned index before it is sent, and results arrive as
|
|
152
|
+
`{ status, data, page? }`. It adds `list_teams`, the value-safe environment
|
|
153
|
+
variable tools (`list_project_env_vars`, `upsert_project_env_var`,
|
|
154
|
+
`update_project_env_var`, `delete_project_env_var`),
|
|
155
|
+
`get_deployment_build_logs` (build events, never following), `get_runtime_logs`
|
|
156
|
+
(the runtime stream, stopped after `waitMs` or `maxRows`), and
|
|
157
|
+
`vercel_api_upload`.
|
|
158
|
+
|
|
159
|
+
Value safety follows a reviewed table (`src/providers/vercel/value-safety.ts`).
|
|
160
|
+
Every operation whose response schema in the pinned spec may carry a credential
|
|
161
|
+
or a stored secret has a verdict: refused (credential minting, Connect
|
|
162
|
+
authorization, decrypted environment values, Global Config items and tokens,
|
|
163
|
+
domain transfer codes, KMS signing), redacted at reviewed field paths
|
|
164
|
+
(environment values, protection-bypass secrets, deploy hook URLs, drain and
|
|
165
|
+
webhook headers and destination URLs beyond their origin, external route and
|
|
166
|
+
redirect destinations beyond their origin, the args and values of every header,
|
|
167
|
+
cookie, and query rule (route transforms and conditions, firewall conditions), team invite codes, synced Global Config items, URL credentials, and signing
|
|
168
|
+
secrets, including the one a new webhook or drain returns at creation), or
|
|
169
|
+
safe with a reason. Detection reads field names, field descriptions, and
|
|
170
|
+
operation descriptions, so a project transfer request (whose code lets another
|
|
171
|
+
team claim the project) is refused too. A test fails when
|
|
172
|
+
a newly flagged operation has no verdict. A key-name heuristic covers every
|
|
173
|
+
other body as defense in depth. Secret-family failures carry fixed messages
|
|
174
|
+
instead of Vercel's text, and every other reviewed operation also withholds that
|
|
175
|
+
text ([value safety](#value-safety-on-every-key-connector)). Read or rotate withheld secrets in the Vercel
|
|
176
|
+
dashboard. A domain move-out is refused because its answer is a transfer token.
|
|
177
|
+
|
|
178
|
+
Lost on the token path: documentation search, runtime error clusters, toolbar
|
|
179
|
+
threads, agent runs, web analytics summaries, purchase quotes and guided
|
|
180
|
+
purchases, `deploy_to_vercel`, and access grants for protected URLs exist only
|
|
181
|
+
on the hosted OAuth connection. Programs calling those tools need an OAuth
|
|
182
|
+
connector beside the token connector.
|
|
183
|
+
|
|
184
|
+
The hosted connection now lists `filter_project_envs`, `get_project_env`,
|
|
185
|
+
`create_project_env`, and `edit_project_env`, which 0.29 hid. The two reads can
|
|
186
|
+
return decrypted values, so they are reviewed as writes and the pool trust
|
|
187
|
+
policy gates them. Vercel admits only reviewed and approved MCP clients to its
|
|
188
|
+
hosted server; if authorization is refused for that reason, the deployment
|
|
189
|
+
needs Vercel's approval or a token connector. The
|
|
190
|
+
[Vercel skill](https://github.com/zackbart/connecta/blob/main/src/providers/vercel/SKILL.md)
|
|
191
|
+
owns the conventions for both.
|
|
192
|
+
|
|
193
|
+
## Cloudflare
|
|
194
|
+
|
|
195
|
+
Every `cloudflare()` call must now name `auth`. 0.30 defaulted to hosted MCP
|
|
196
|
+
when `surface` was omitted; that default is gone with `surface` itself:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
connectors: [
|
|
200
|
+
cloudflare("cloudflare", {
|
|
201
|
+
purpose: "Estate changes",
|
|
202
|
+
auth: { type: "oauth" },
|
|
203
|
+
}),
|
|
204
|
+
cloudflare("cloudflare_api", {
|
|
205
|
+
purpose: "Production DNS and Workers",
|
|
206
|
+
auth: { type: "apiToken" },
|
|
207
|
+
accountId: "<account id>",
|
|
208
|
+
zoneId: "<zone id>",
|
|
209
|
+
pin: { accountIds: ["<account id>"] },
|
|
210
|
+
}),
|
|
211
|
+
cloudflare("cloudflare_legacy", {
|
|
212
|
+
purpose: "Legacy zones behind a user key",
|
|
213
|
+
auth: { type: "globalApiKey" },
|
|
214
|
+
pin: { zoneIds: ["<zone id>"] },
|
|
215
|
+
}),
|
|
216
|
+
];
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| 0.30 configuration | Now |
|
|
220
|
+
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
221
|
+
| No `surface`, or `surface: "mcp"`, with OAuth | `auth: { type: "oauth" }`. Same endpoint, catalog, and grant. |
|
|
222
|
+
| `surface: "mcp"` with `auth: { type: "credential" }` | `auth: { type: "apiToken" }`: bearer tokens no longer reach `mcp.cloudflare.com`. A token stored for the same connector id carries over. |
|
|
223
|
+
| `surface: "api"` (API token) | `auth: { type: "apiToken" }` with the same `accountId`, `zoneId`, `baseUrl`, and `maxConcurrency`. |
|
|
224
|
+
| `surface: "api"`, `authentication: "globalApiKey"` | `auth: { type: "globalApiKey" }` plus `pin: { accountIds, zoneIds }`, or `unpinned: true` to accept the user's whole estate. |
|
|
225
|
+
| `credential` override | Removed; the credential slot's copy is fixed. |
|
|
226
|
+
| `callAdmission` with hosted MCP | Unchanged under `auth: { type: "oauth" }`. |
|
|
227
|
+
|
|
228
|
+
The key connector is complete on its own. JSON writes that 0.30 refused on an
|
|
229
|
+
API token (they belonged to hosted `execute`) go through
|
|
230
|
+
`cloudflare_api_write`, checked against a pinned API index before they are
|
|
231
|
+
sent. The 23 hand-written reads (`get_zone`, `list_dns_records`,
|
|
232
|
+
`list_r2_objects`, `list_pages_deployments`, and the rest) are replaced by
|
|
233
|
+
`cloudflare_api_read` on the same paths; results are Cloudflare's own
|
|
234
|
+
`result`, unprojected, so programs pass `select` instead of reading the old
|
|
235
|
+
projections. `list_accounts`, `list_zones`, and `cloudflare_api_upload` keep
|
|
236
|
+
their names (upload now takes `parts` for multipart); `verify_api_token` and
|
|
237
|
+
`verify_global_api_key` become `verify_credential`; `cloudflare_api_get` and
|
|
238
|
+
`cloudflare_api_mutate` become `cloudflare_api_read` and `cloudflare_api_write`.
|
|
239
|
+
`graphql_query` is new.
|
|
240
|
+
|
|
241
|
+
Credentials stay in the dashboard. The key connector refuses every operation
|
|
242
|
+
that mints, rotates, or returns a credential (API tokens, Access service
|
|
243
|
+
tokens, R2 temporary credentials, signing keys, direct-upload URLs, deploy
|
|
244
|
+
hooks) and redacts stored secrets on every result. A pinned connector refuses
|
|
245
|
+
operations that name no account or zone unless they are reviewed safe, such
|
|
246
|
+
as `/certificates` and `/memberships/{id}`.
|
|
247
|
+
|
|
248
|
+
Read-only pools: hosted `execute` is always a write, even for a program that
|
|
249
|
+
only reads, so a read-only pool on an OAuth connector reaches only `search`.
|
|
250
|
+
Use an API-token connector for read-only API access.
|
|
251
|
+
|
|
252
|
+
Lost on each path. OAuth has no index validation, named tools, GraphQL tool,
|
|
253
|
+
upload tool, or pin; Cloudflare's OAuth grant is the only boundary. A key has
|
|
254
|
+
no hosted `search` over Cloudflare's live OpenAPI document; the pinned index
|
|
255
|
+
replaces it and `providers:check` reports when it falls behind. A Global API
|
|
256
|
+
Key cannot reach R2, which accepts API tokens only. The
|
|
257
|
+
[Cloudflare skill](https://github.com/zackbart/connecta/blob/main/src/providers/cloudflare/SKILL.md)
|
|
258
|
+
owns the conventions for both.
|
|
259
|
+
|
|
260
|
+
## Value safety on every key connector
|
|
261
|
+
|
|
262
|
+
All four key connectors now share one value-safety mechanism: a reviewed
|
|
263
|
+
table per vendor over every operation the detector flags in the pinned spec,
|
|
264
|
+
one redaction pass on every result, and one error policy
|
|
265
|
+
([architecture](./architecture.md#value-safety-for-rest-vendors)). Results
|
|
266
|
+
lose fields they returned before. A `"[redacted]"` value is never the real
|
|
267
|
+
one; read or rotate withheld secrets in the vendor's dashboard.
|
|
268
|
+
|
|
269
|
+
- **Stripe** refuses operations that hand out a credential: ephemeral keys,
|
|
270
|
+
Terminal connection tokens, account links, Express login links, account and
|
|
271
|
+
customer sessions, billing portal sessions, file link creation, Financial
|
|
272
|
+
Connections session creation, and the meter event session. Results redact
|
|
273
|
+
client secrets (PaymentIntents, SetupIntents, Checkout and Identity
|
|
274
|
+
sessions, Sources, Financial Connections, invoice confirmation secrets),
|
|
275
|
+
webhook and event destination signing secrets, Apps secret payloads,
|
|
276
|
+
app-install authorization codes, Terminal Wi-Fi passwords, forwarded
|
|
277
|
+
request header values, and Issuing card numbers and CVCs; webhook, file
|
|
278
|
+
link, and pre-signed import URLs keep only their scheme and host, and the
|
|
279
|
+
rules follow each object into expansions, lists, and events (an expanded
|
|
280
|
+
File's links, an event's `previous_attributes`). Identity verification
|
|
281
|
+
URLs are unchanged. A Checkout Session's URL is returned whole only for a
|
|
282
|
+
guest payment session (`mode: "payment"`, no `customer` or
|
|
283
|
+
`customer_account`, no customer creation, no saved payment method options);
|
|
284
|
+
any other session returns only its scheme and host, because its page can
|
|
285
|
+
show, reuse, or remove a customer's saved payment methods. v2 account
|
|
286
|
+
links and Terminal onboarding links are refused too. Issuing `number` and
|
|
287
|
+
`cvc` expansions are refused on every Issuing path, not only cards.
|
|
288
|
+
Failures of credential-bearing operations keep Stripe's type, code, and
|
|
289
|
+
param but not its message. Create client-side sessions and links from your
|
|
290
|
+
own server code.
|
|
291
|
+
- **Notion** results withhold the signature, credential, and security-token
|
|
292
|
+
parameters of pre-signed file URLs, so a returned file URL no longer
|
|
293
|
+
downloads; credential-named fields, including database properties named
|
|
294
|
+
like credentials, read as `"[redacted]"`. Failures of the OAuth, file
|
|
295
|
+
upload, bot user, and agent operations keep Notion's code but not its
|
|
296
|
+
message.
|
|
297
|
+
- **Vercel** replaces environment values with `"[redacted]"` instead of
|
|
298
|
+
dropping the field, and withholds Vercel's error text for every reviewed
|
|
299
|
+
operation and every operation whose request takes a credential-named
|
|
300
|
+
field, not only secret families. Audit event invite codes, integration
|
|
301
|
+
drain headers, and route header values are redacted too.
|
|
302
|
+
- **Cloudflare** redacts Hyperdrive database passwords, RealtimeKit storage
|
|
303
|
+
credentials, transform-rule header values, and dispatch binding values,
|
|
304
|
+
and reduces notification, RealtimeKit, and data security webhook
|
|
305
|
+
destinations to their scheme and host. A credential-named field now loses
|
|
306
|
+
its whole value, not only its strings (a `cookies` list, a variable named
|
|
307
|
+
`API_KEY`).
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
# Notion, Vercel and Cloudflare migration for 0.29
|
|
2
2
|
|
|
3
|
+
Use this upgrade guide for an existing deployment.
|
|
4
|
+
[Deployment upgrades](./deploying.md#upgrade-an-existing-deployment) cover other
|
|
5
|
+
version changes; [integrating services](./integrating.md) covers new connectors.
|
|
6
|
+
[The agent index](./README.md) routes package maintenance separately.
|
|
7
|
+
|
|
3
8
|
This is the Phase 1 item 5d migration input for [Phase 5 release #709](https://github.com/zackbart/connecta/issues/709).
|
|
4
9
|
Deploy it with the consolidated 0.29 release, not while the rework is in progress.
|
|
5
10
|
BePresent and One&Many use Notion and Cloudflare; their actual grants and
|
|
6
11
|
connector ids must be checked in deployment configuration before that release.
|
|
7
12
|
The provider audit establishes available auth modes, not production OAuth grants.
|
|
8
13
|
|
|
14
|
+
Cloudflare's part of this guide is superseded: `cloudflare()` now selects its
|
|
15
|
+
implementation by `auth` and its key connector is complete on its own. Follow
|
|
16
|
+
the [provider auth migration](./provider-auth-migration.md#cloudflare) for
|
|
17
|
+
Cloudflare; the Cloudflare lines below record the 0.29 transition only.
|
|
18
|
+
|
|
9
19
|
All three providers now default to hosted MCP. `surface: "api"` explicitly
|
|
10
20
|
selects a REST complement and accepts only its API-specific options. The old
|
|
11
21
|
Vercel/Cloudflare API modes are no longer complete alternatives; Notion retains
|
|
@@ -22,6 +32,11 @@ connectors: [
|
|
|
22
32
|
]
|
|
23
33
|
```
|
|
24
34
|
|
|
35
|
+
Notion has since moved to auth-selected implementations: `surface` is gone,
|
|
36
|
+
and `auth: { type: "oauth" }` or `{ type: "token" }` selects hosted MCP or the
|
|
37
|
+
REST connector. Upgrade with the
|
|
38
|
+
[provider auth migration](./provider-auth-migration.md#notion); the rest of
|
|
39
|
+
this paragraph records the 0.29 rules.
|
|
25
40
|
Notion preserves headless/internal-integration capabilities. Add explicit
|
|
26
41
|
`surface: "api"` to retain that identity and migrate old REST names to
|
|
27
42
|
`integration_*`, for example `search` to `integration_search`, `create_page`
|
|
@@ -45,7 +60,9 @@ include `cf-r2-jurisdiction` only when the bucket needs it. This remains a write
|
|
|
45
60
|
`execute` remains a write even when its program only calls GET.
|
|
46
61
|
Trusted pools may execute writes; read-only pools use direct host-approved writes.
|
|
47
62
|
|
|
48
|
-
|
|
63
|
+
Vercel's `surface` and ownership rules were later replaced: `auth` now selects
|
|
64
|
+
the implementation. See the [provider auth migration](./provider-auth-migration.md#vercel).
|
|
65
|
+
The 0.29 Vercel guidance follows for history. For Vercel, authorize the owning teams in hosted OAuth, migrate discovery/logs,
|
|
49
66
|
domain listing/adding, deployment cancellation and file uploads to live MCP
|
|
50
67
|
schemas, and keep the independently authorized REST complement for value-safe
|
|
51
68
|
project environment variables (including `upsert: false` create-only writes), domain verification/removal and deployment
|
|
@@ -54,7 +71,7 @@ category. Raw hatches refuse all published REST counterparts, including project
|
|
|
54
71
|
creation/update. Do not copy REST argument
|
|
55
72
|
shapes into vendor tools, even when a tool name is unchanged.
|
|
56
73
|
|
|
57
|
-
|
|
58
|
-
[Notion](
|
|
59
|
-
[
|
|
60
|
-
[
|
|
74
|
+
Every provider's table is retired with `surface`; the provider auth migration
|
|
75
|
+
maps their names ([Notion](./provider-auth-migration.md#notion),
|
|
76
|
+
[Cloudflare](./provider-auth-migration.md#cloudflare),
|
|
77
|
+
[Vercel](./provider-auth-migration.md#vercel)).
|