@zackbart/connecta 0.22.3 → 0.24.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/AGENTS.md +5 -0
- package/CHANGELOG.md +82 -0
- package/README.md +19 -11
- package/dist/activity-friction.d.ts +3 -0
- package/dist/activity-friction.js +19 -0
- package/dist/activity.d.ts +11 -2
- package/dist/activity.js +15 -19
- package/dist/auth/downstream-oauth.d.ts +2 -1
- package/dist/auth/downstream-oauth.js +10 -1
- package/dist/branding.d.ts +67 -0
- package/dist/branding.js +176 -0
- package/dist/catalog-service.d.ts +1 -6
- package/dist/catalog-service.js +3 -53
- package/dist/connectors/remote-mcp.js +3 -5
- package/dist/credential-contract.d.ts +24 -0
- package/dist/credential-contract.js +1 -0
- package/dist/credential-rules.d.ts +85 -0
- package/dist/credential-rules.js +107 -0
- package/dist/credentials.d.ts +4 -100
- package/dist/credentials.js +3 -107
- package/dist/errors.d.ts +1 -1
- package/dist/execute.d.ts +5 -52
- package/dist/execute.js +40 -347
- package/dist/executors/quickjs-protocol.d.ts +0 -7
- package/dist/executors/quickjs-protocol.js +2 -10
- package/dist/executors/quickjs.js +1 -1
- package/dist/index.d.ts +23 -56
- package/dist/index.js +30 -58
- package/dist/invocation.d.ts +0 -33
- package/dist/invocation.js +56 -124
- package/dist/meta-tools.d.ts +7 -6
- package/dist/meta-tools.js +14 -21
- package/dist/module-contracts.d.ts +19 -0
- package/dist/module-contracts.js +1 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/model.d.ts +6 -3
- package/dist/operator-ui/view.d.ts +2 -18
- package/dist/operator-ui/view.js +3 -20
- package/dist/registry.d.ts +4 -1
- package/dist/registry.js +8 -6
- package/dist/routes/activity.js +1 -1
- package/dist/routes/credentials.js +5 -2
- package/dist/routes/mcp.js +7 -51
- package/dist/routes/oauth-management.d.ts +2 -0
- package/dist/routes/oauth-management.js +108 -0
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +21 -121
- package/dist/routes/shared.d.ts +19 -17
- package/dist/routes/shared.js +48 -44
- package/dist/routes/ui.js +36 -33
- package/dist/server.d.ts +1 -2
- package/dist/server.js +7 -45
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +55 -19
- package/dist/types.d.ts +3 -15
- package/dist/ui.d.ts +15 -70
- package/dist/ui.js +176 -317
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +31 -26
- package/documentation/auth.md +65 -111
- package/documentation/call-admission.md +10 -11
- package/documentation/cloudflare.md +1 -1
- package/documentation/code-mode.md +65 -260
- package/documentation/connectors.md +8 -6
- package/documentation/linear.md +1 -1
- package/documentation/meta-tools.md +37 -18
- package/documentation/mixpanel.md +1 -1
- package/documentation/notion.md +2 -2
- package/documentation/operations.md +19 -23
- package/documentation/operator-ui.md +82 -104
- package/documentation/optional-modules-upgrade.md +243 -0
- package/documentation/provider-conventions.md +7 -5
- package/documentation/revenuecat.md +1 -1
- package/documentation/storage-and-credentials.md +59 -40
- package/documentation/stripe.md +1 -1
- package/documentation/upgrading.md +83 -8
- package/ethos.md +36 -43
- package/examples/worker/AGENTS.md +3 -1
- package/examples/worker/README.md +68 -84
- package/examples/worker/src/d1-activity.ts +1 -1
- package/examples/worker/src/index.ts +11 -6
- package/package.json +18 -2
- package/templates/node/AGENTS.md +8 -6
- package/templates/node/README.md +56 -67
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +1 -1
- package/templates/node/src/index.ts +11 -12
- package/dist/access-tokens.d.ts +0 -31
- package/dist/access-tokens.js +0 -236
- package/dist/apps-shell.d.ts +0 -37
- package/dist/apps-shell.js +0 -174
- package/dist/routes/access-tokens.d.ts +0 -6
- package/dist/routes/access-tokens.js +0 -83
package/dist/version.js
CHANGED
|
@@ -66,24 +66,21 @@ read top to bottom.
|
|
|
66
66
|
| --- | --- | --- |
|
|
67
67
|
| 0 | HTTPS upgrade | 308 to `publicUrl` when it is HTTPS and the request arrived over HTTP. Path and query are *assigned* onto the configured URL, never resolved against it, so a `//host` pathname cannot replace the deployment origin. `/health` is exempt: a loopback container probe must not depend on public DNS and TLS. `/ui` is canonicalized to `/` while upgrading. |
|
|
68
68
|
| 0 | Cloudflare Access (Worker deployment, when enabled) | Edge admission before this route table. Managed OAuth owns its challenge and discovery metadata; an admitted direct invocation carries trusted identity in `ctx.access`. |
|
|
69
|
-
| 1 |
|
|
70
|
-
| 2 | `OPTIONS` |
|
|
71
|
-
| 3 | `/.well-known/*` | Auth
|
|
72
|
-
| 4 | `/health` | Open
|
|
73
|
-
| 5 | `/oauth/callback/<connectorId>` |
|
|
74
|
-
| 6 | `/
|
|
75
|
-
| 7 |
|
|
76
|
-
|
|
77
|
-
| 9 | connector `handleRequest` | Registration order, open. Dispatched only after every built-in misses, so a connector can *add* a route and never shadow one of connecta's. First non-null response wins; a throw is a 500, not a fall-through. |
|
|
78
|
-
| 10 | — | 404. |
|
|
69
|
+
| 1 | Mounted UI routes | The optional UI handles its shells, assets, data, details, and auth mutations before wildcard OPTIONS. Mutation routes refuse preflight rather than inheriting MCP CORS. No UI module means none of these routes. |
|
|
70
|
+
| 2 | `OPTIONS` | Auth metadata gets a chance, otherwise MCP CORS preflight. |
|
|
71
|
+
| 3 | `/.well-known/*` | Auth metadata, or 404. |
|
|
72
|
+
| 4 | `/health` | Open payload-free health, executor, admission, and deployment metadata; reserved routes reflect installed modules. |
|
|
73
|
+
| 5 | `/oauth/callback/<connectorId>` | Core downstream OAuth completion, state verification and personal ownership checks; independent of UI. |
|
|
74
|
+
| 6 | `/mcp` | Admission before auth, then a request-local MCP server. |
|
|
75
|
+
| 7 | Other paths | 404. Custom HTTP routes belong to the deployment. |
|
|
76
|
+
|
|
79
77
|
|
|
80
78
|
Every response leaves through `withSecurityHeaders`: `nosniff`, a no-referrer
|
|
81
|
-
policy, HSTS on HTTPS,
|
|
82
|
-
and framing denial. `test/server-route-contracts.test.ts` pins this ordering
|
|
79
|
+
policy, HSTS on HTTPS, while the UI module adds a nonce-based script CSP and framing denial to its shells. `test/server-route-contracts.test.ts` pins this ordering
|
|
83
80
|
and the exact refusal bodies; it exists because the ordering is invisible in
|
|
84
81
|
any one file and a reordering reads like a harmless refactor.
|
|
85
82
|
|
|
86
|
-
`/mcp` itself is
|
|
83
|
+
`/mcp` itself is five steps, in this order and for these reasons:
|
|
87
84
|
|
|
88
85
|
1. **Admit.** One permit from the deployment-wide FIFO pool, taken before auth
|
|
89
86
|
so an unauthenticated flood costs a permit rather than a Clerk lookup
|
|
@@ -102,8 +99,7 @@ any one file and a reordering reads like a harmless refactor.
|
|
|
102
99
|
than silently serving the full registry. Retiring a scoping boundary into
|
|
103
100
|
fail-open is the one outcome worse than the 404.
|
|
104
101
|
5. **Serve.** A fresh `McpServer` per request, the seven meta-tools registered
|
|
105
|
-
against the registry
|
|
106
|
-
`resources/list` deliberately answering with nothing), and the response
|
|
102
|
+
against the registry and the response
|
|
107
103
|
handed back.
|
|
108
104
|
|
|
109
105
|
## Layers below the meta-tools
|
|
@@ -115,7 +111,7 @@ owns or hands out, and a change usually belongs in exactly one of them:
|
|
|
115
111
|
| --- | --- |
|
|
116
112
|
| `src/registry.ts` | The connector set, identity-scoped views, personal storage partitions, address resolution, catalog TTL/persistence/completeness, refresh single-flight, connector health, per-connector call limiters, and drift. Construction-time refusals live here. |
|
|
117
113
|
| `src/catalog-service.ts` | Request-local tool listing, search, and describe. It coalesces reads inside one request and opts agent reads into the runtime's deferred catalog channel when one exists. |
|
|
118
|
-
| `src/invocation.ts` | One tool call: argument validation, call admission,
|
|
114
|
+
| `src/invocation.ts` | One tool call: argument validation, call admission, one-attempt timeout, provider retry hints, result unwrapping, size capping, and the activity record. |
|
|
119
115
|
| `src/catalog.ts` | Ranking, description summarizing, and the compact schema renderer discovery shows. |
|
|
120
116
|
| `src/result-shapes.ts` | Bounded runtime-only inference and merging for output shapes learned from successful read-only calls whose providers declared none. |
|
|
121
117
|
|
|
@@ -127,6 +123,19 @@ read-only check. `test/execute.test.ts` asserts that parity directly, because
|
|
|
127
123
|
the alternative — a sandbox path that quietly diverges — is how generated code
|
|
128
124
|
would mint a capability.
|
|
129
125
|
|
|
126
|
+
## Optional deployment modules
|
|
127
|
+
|
|
128
|
+
`createConnecta` takes closed typed `ui`, `vault`, and `activity` slots. Factories
|
|
129
|
+
live at `/ui`, `/credentials`, and `/activity`; bearer auth lives at
|
|
130
|
+
`/auth/bearer`. Root exports the contracts, never these implementations. There
|
|
131
|
+
is no module array, runtime registration, or plugin lifecycle.
|
|
132
|
+
|
|
133
|
+
Core keeps connector discovery, the executor contract, invocation, permissions,
|
|
134
|
+
and OAuth callback verification together. Optional modules contribute no
|
|
135
|
+
runtime work when omitted. The UI supplies credential handoff URLs only while
|
|
136
|
+
mounted. Status reads never initiate OAuth, and each lazy details request owns
|
|
137
|
+
its downstream scope. See [operator UI](./operator-ui.md).
|
|
138
|
+
|
|
130
139
|
## Import-graph purity
|
|
131
140
|
|
|
132
141
|
Nothing reachable from `src/index.ts` may import a `node:` builtin. The core is
|
|
@@ -144,8 +153,8 @@ specific to a direct Worker invocation carrying `ctx.access`.
|
|
|
144
153
|
|
|
145
154
|
`test/purity.test.ts` walks the relative-import graph from `src/index.ts` and
|
|
146
155
|
fails on (a) any `node:` specifier in a reachable file and (b) the Node
|
|
147
|
-
adapter, file storage, QuickJS parent or child,
|
|
148
|
-
reachable at all. `test/package-surface.test.ts` and
|
|
156
|
+
adapter, file storage, QuickJS parent or child, auth adapters, UI bundle,
|
|
157
|
+
encrypted vault implementation, or activity implementation being reachable at all. `test/package-surface.test.ts` and
|
|
149
158
|
`scripts/check-package.mjs` guard the other half — that the published tarball
|
|
150
159
|
matches the same boundary.
|
|
151
160
|
|
|
@@ -162,8 +171,7 @@ src/
|
|
|
162
171
|
server.ts route ordering, HTTPS upgrade, security wrapper
|
|
163
172
|
routes/ one file per surface; shared.ts holds the auth gate
|
|
164
173
|
meta-tools.ts the six non-execute meta-tools over the registry
|
|
165
|
-
execute.ts execute_code, the sandbox host bridge,
|
|
166
|
-
apps-shell.ts the one build-time MCP Apps template
|
|
174
|
+
execute.ts execute_code, the sandbox host bridge, emitted media
|
|
167
175
|
skills.ts MCP instructions, the usage skill, connector guides
|
|
168
176
|
registry.ts connector set, addresses, health, call limiters
|
|
169
177
|
catalog-service.ts request-local catalog access, search, and describe
|
|
@@ -172,8 +180,7 @@ src/
|
|
|
172
180
|
invocation.ts one tool call, end to end
|
|
173
181
|
catalog-drift.ts vetted manifests and the counts a refresh produces
|
|
174
182
|
credentials.ts the AES-GCM connector vault over KVStorage
|
|
175
|
-
|
|
176
|
-
activity.ts payload-free event contracts + best-effort recorder
|
|
183
|
+
activity.ts optional history factory and best-effort recorder
|
|
177
184
|
call-admission.ts connector-partitioned downstream permits and budgets
|
|
178
185
|
executor-admission.ts the portable bounded queue both pools use
|
|
179
186
|
ui.ts the served operator shell and /ui/data payload
|
|
@@ -194,8 +201,7 @@ src/
|
|
|
194
201
|
authenticated subject. Anything cached per request still dies with it.
|
|
195
202
|
Putting a downstream client or credential on the wrong side of those lines
|
|
196
203
|
is the highest-severity mistake available here.
|
|
197
|
-
- **Route order is behavior.** Moving a
|
|
198
|
-
hands a connector the ability to shadow it. Moving a mutation route below the
|
|
204
|
+
- **Route order is behavior.** Moving a mutation route below the
|
|
199
205
|
wildcard `OPTIONS` opts it into CORS preflight.
|
|
200
206
|
- **Admission runs before auth, on purpose.** Reordering them to "authenticate
|
|
201
207
|
first" makes the cheapest possible attack the most expensive request.
|
|
@@ -203,8 +209,7 @@ src/
|
|
|
203
209
|
the connector limiters, then the executor. Node's `listen()` calls it on
|
|
204
210
|
SIGTERM/SIGINT.
|
|
205
211
|
- **Structural mistakes throw at construction.** A duplicate connector id, an
|
|
206
|
-
invalid admission rule, `accessTokens`
|
|
207
|
-
executor: all refuse to boot. A deployment that starts in the wrong shape is
|
|
212
|
+
invalid admission rule, removed `accessTokens` option, or missing executor: all refuse to boot. A deployment that starts in the wrong shape is
|
|
208
213
|
worse than one that does not start.
|
|
209
214
|
|
|
210
215
|
## Tests that enforce this
|
package/documentation/auth.md
CHANGED
|
@@ -1,67 +1,60 @@
|
|
|
1
1
|
# Inbound auth
|
|
2
2
|
|
|
3
|
-
Inbound auth decides who may reach the MCP endpoint.
|
|
4
|
-
|
|
5
|
-
Access
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Inbound auth decides who may reach the MCP endpoint. Import configured bearer
|
|
4
|
+
support from `@zackbart/connecta/auth/bearer`, Clerk from `/auth/clerk`, or
|
|
5
|
+
Cloudflare Access from `/auth/cloudflare-access`. Providers may be combined;
|
|
6
|
+
static bearers are checked first, then other providers in configuration order.
|
|
7
|
+
Connecta no longer issues `cta_` tokens or serves token-management routes.
|
|
8
8
|
|
|
9
9
|
## Principals, visibility, and operators
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
results such as `get_result` pages. The principal is the human owner of personal
|
|
11
|
+
The actor identifies the caller in activity. The subject owns transient results
|
|
12
|
+
such as `get_result` pages. The principal is the human owner of personal
|
|
14
13
|
connector auth. An interactive Clerk or Access user supplies all three. A
|
|
15
|
-
Cloudflare service identity has an actor and subject but no principal.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
14
|
+
Cloudflare service identity has an actor and subject but no principal.
|
|
15
|
+
|
|
16
|
+
`identity.connectorAccess` returns `"all"` or declared connector ids. It governs
|
|
17
|
+
discovery and use, and defaults to all connectors. Visibility alone grants no
|
|
18
|
+
authentication-management permission. Two independent resolvers return
|
|
19
|
+
`"all"`, `"none"`, or declared connector ids:
|
|
20
|
+
|
|
21
|
+
- `credentialAdministration` allows an interactive human to manage shared
|
|
22
|
+
credentials and shared OAuth grants.
|
|
23
|
+
- `personalConnection` allows an interactive human to manage their own
|
|
24
|
+
credentials and OAuth grants on personal connectors.
|
|
25
|
+
|
|
26
|
+
Both default to `"none"`. Each action requires visibility and the relevant
|
|
27
|
+
permission. Personal actions also require a stable namespaced principal and
|
|
28
|
+
always use that principal's partition. Resolver exceptions and unknown ids
|
|
29
|
+
fail closed. Permissions come from authenticated identity, never caller input.
|
|
30
|
+
|
|
31
|
+
The management resolvers receive `Readonly<AuthenticatedIdentity>`.
|
|
32
|
+
`identity.activityAccess` receives `Readonly<IdentityReference>` with `id` and
|
|
33
|
+
`namespace`, and controls reading global activity. Its default admits
|
|
34
|
+
interactive humans, so team deployments should set it explicitly if the event
|
|
35
|
+
stream should be restricted. It replaces `operatorAccess`; there is no general
|
|
36
|
+
administrator role or token-management authority.
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
createConnecta({
|
|
40
40
|
auth: cloudflareAccessAuth(),
|
|
41
41
|
identity: {
|
|
42
42
|
connectorAccess: ({ principal }) =>
|
|
43
|
-
principal?.id === "
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
principal?.id === "owner-id" ? "all" : ["shared_docs", "personal_linear"],
|
|
44
|
+
credentialAdministration: ({ principal }) =>
|
|
45
|
+
principal?.id === "owner-id" ? "all" : "none",
|
|
46
|
+
personalConnection: () => ["personal_linear"],
|
|
47
|
+
activityAccess: ({ id }) => id === "owner-id",
|
|
47
48
|
},
|
|
48
|
-
connectors
|
|
49
|
-
remoteMcp("shared_docs", { url: "https://example.com/mcp" }),
|
|
50
|
-
remoteMcp("personal_linear", {
|
|
51
|
-
url: "https://mcp.linear.app/mcp",
|
|
52
|
-
authScope: "personal",
|
|
53
|
-
auth: { type: "oauth" },
|
|
54
|
-
}),
|
|
55
|
-
],
|
|
49
|
+
connectors,
|
|
56
50
|
executor,
|
|
57
51
|
});
|
|
58
52
|
```
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
storage.
|
|
54
|
+
Built-in Clerk and Access providers supply identity namespaces. A custom
|
|
55
|
+
interactive provider must set `activityActorNamespace` before its users can
|
|
56
|
+
own personal auth. Keep the namespace and principal ids stable across upgrades;
|
|
57
|
+
changing them selects different personal storage partitions.
|
|
65
58
|
|
|
66
59
|
## Cloudflare Access on Workers
|
|
67
60
|
|
|
@@ -92,12 +85,11 @@ also means it is deliberately not a Node or `cloudflared` origin adapter, and
|
|
|
92
85
|
it does not survive a Service Binding hop: those shapes need their own explicit
|
|
93
86
|
trust boundary.
|
|
94
87
|
|
|
95
|
-
A human identity gets
|
|
96
|
-
|
|
97
|
-
identity
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
email domains, groups, or device posture into a second policy layer.
|
|
88
|
+
A human identity gets a code-derived MCP view. Managing connection auth requires
|
|
89
|
+
an explicit `credentialAdministration` or `personalConnection` grant. An Access
|
|
90
|
+
service identity has no human principal and cannot mutate connection auth.
|
|
91
|
+
Access decides admission and identity; Connecta configuration selects connector
|
|
92
|
+
access and these narrower permissions.
|
|
101
93
|
|
|
102
94
|
Protect the Worker with a Worker-level Access application whose destination is
|
|
103
95
|
`{ "type": "worker", "worker_id": "<the Worker script tag>" }`. A traditional
|
|
@@ -133,14 +125,12 @@ through the
|
|
|
133
125
|
|
|
134
126
|
Worker-level Access runs before every connecta route. Consequently:
|
|
135
127
|
|
|
136
|
-
- `/health`, operator pages, downstream OAuth callbacks,
|
|
137
|
-
routes, and `/mcp` all require Access unless a more-specific hostname/path
|
|
128
|
+
- `/health`, operator pages, downstream OAuth callbacks, and `/mcp` all require Access unless a more-specific hostname/path
|
|
138
129
|
policy says otherwise;
|
|
139
|
-
- a static
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
OAuth discovery paths when Managed OAuth is enabled.
|
|
130
|
+
- a static Connecta bearer is not a standalone edge credential, because Cloudflare rejects them before connecta sees them; and
|
|
131
|
+
- custom public webhooks belong to the deployment outside Connecta and need
|
|
132
|
+
their own Access routing policy. Keep Connecta's OAuth discovery paths
|
|
133
|
+
protected when Managed OAuth is enabled.
|
|
144
134
|
|
|
145
135
|
The [Worker example](../examples/worker/) carries the complete deployment shape
|
|
146
136
|
and the [upgrade guide](./upgrading.md#0200--0212) gives the reversible Clerk
|
|
@@ -157,57 +147,21 @@ publishable slot, and a startup error is a log line. A deployment that builds
|
|
|
157
147
|
per request, as the Workers shape does, sees the same error on its first
|
|
158
148
|
request instead of a base64 stack on every route.
|
|
159
149
|
|
|
160
|
-
##
|
|
150
|
+
## Human authentication management
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
|
|
152
|
+
Credential and OAuth mutation require an admitted interactive human, connector
|
|
153
|
+
visibility, the appropriate shared or personal permission, and an exact
|
|
154
|
+
same-origin `Origin` for browser requests. A configured MCP bearer never becomes
|
|
155
|
+
a browser management credential.
|
|
164
156
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
});
|
|
172
|
-
```
|
|
157
|
+
With `ui: operatorUi()` and a vault, static credential recovery can return a
|
|
158
|
+
secret-free handoff to the connection UI. Without the UI, that recovery is
|
|
159
|
+
`unavailable`; Connecta does not return a link to a missing page. An authorized
|
|
160
|
+
interactive MCP caller can still start downstream OAuth through
|
|
161
|
+
`authorize_connector` without the UI. Core owns the callback and verifies state
|
|
162
|
+
and principal ownership independently of the optional browser application.
|
|
173
163
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
secure.
|
|
179
|
-
|
|
180
|
-
Each token has an immutable ID. Activity records store that ID and resolve its
|
|
181
|
-
current friendly name only while an authorized operator reads activity.
|
|
182
|
-
Revoked records remain as metadata tombstones so historical calls keep their
|
|
183
|
-
friendly attribution. New tokens also retain the creating principal. Their MCP
|
|
184
|
-
requests use that principal's connector visibility and personal auth while the
|
|
185
|
-
token itself remains the activity actor and result owner.
|
|
186
|
-
|
|
187
|
-
Access tokens authenticate MCP clients; they are never operator credentials.
|
|
188
|
-
Creation, rename, and revocation require the same eligible human identity and
|
|
189
|
-
same-origin mutation boundary as connector credentials. `maxActive` defaults
|
|
190
|
-
to 100 and can be set from 1 through 1,000.
|
|
191
|
-
|
|
192
|
-
Issuance and revocation inherit the consistency guarantees of the configured
|
|
193
|
-
storage adapter. Use strongly consistent storage when either change must take
|
|
194
|
-
effect globally without a convergence window.
|
|
195
|
-
|
|
196
|
-
Human credential mutation is a separate, narrower boundary. The
|
|
197
|
-
`/credentials` shell contains no secret data before authentication, and the
|
|
198
|
-
mutation API requires same-origin requests from an admitted interactive human.
|
|
199
|
-
That human may mutate only visible connector slots. An MCP bearer is never
|
|
200
|
-
treated as a browser credential, even when it can call every connector.
|
|
201
|
-
|
|
202
|
-
This split is visible in recovery:
|
|
203
|
-
|
|
204
|
-
- a bearer-authenticated agent may receive `recovery: "operator_config"` and
|
|
205
|
-
pass its `operatorUrl` to a human;
|
|
206
|
-
- an interactive human with connector access opens that URL, signs in, and updates the
|
|
207
|
-
credential; and
|
|
208
|
-
- a bearer-only deployment still returns the handoff honestly, but mutation
|
|
209
|
-
remains unavailable until interactive user auth is configured.
|
|
210
|
-
|
|
211
|
-
See [meta-tools](./meta-tools.md#authorization-recovery) for the stable recovery
|
|
212
|
-
envelope and [storage and credentials](./storage-and-credentials.md) for vault
|
|
213
|
-
rules.
|
|
164
|
+
See [meta-tools](./meta-tools.md#authorization-recovery) and
|
|
165
|
+
[storage and credentials](./storage-and-credentials.md). The
|
|
166
|
+
[upgrade guide](./upgrading.md#0240-optional-modules) covers moving clients
|
|
167
|
+
off removed Connecta-issued tokens before changing deployment configuration.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Downstream call admission
|
|
2
2
|
|
|
3
3
|
One admitted MCP request can fan out into many downstream calls. A program
|
|
4
|
-
calls tools from loops, from `connecta.
|
|
4
|
+
calls tools from loops, from parallel `connecta.call` calls, and from branches the caller
|
|
5
5
|
never saw. The deployment-wide request pool
|
|
6
6
|
([request admission](./request-admission.md)) bounds the envelope; it cannot
|
|
7
7
|
see anything inside it. A provider that publishes "60 requests per minute"
|
|
@@ -76,16 +76,15 @@ not be a way to reset a live budget. Exhausted partition capacity is
|
|
|
76
76
|
|
|
77
77
|
The registry owns the limiter, and `InvocationService.invoke` acquires a permit
|
|
78
78
|
immediately before `Connector.callTool` and releases it in `finally`. Both call
|
|
79
|
-
paths
|
|
80
|
-
|
|
79
|
+
paths, top-level `call_tool` and program calls through `connecta.call`,
|
|
80
|
+
reach that same seam, so a program cannot buy itself a
|
|
81
81
|
second limit by taking the other route.
|
|
82
82
|
|
|
83
|
-
- **A retry is another
|
|
84
|
-
entry
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
outcome and the attempt count.
|
|
83
|
+
- **A caller retry is another call.** It reacquires and can consume another
|
|
84
|
+
budget entry. Connecta returns retry hints without waiting or retrying.
|
|
85
|
+
- **A proactive short-window `rate_limited` refusal** returns its retry hint
|
|
86
|
+
without waiting or dispatching. Activity records one failed admission attempt;
|
|
87
|
+
a caller may reissue after the window.
|
|
89
88
|
- **A queued cancellation consumes nothing.** It is removed from the queue with
|
|
90
89
|
no rolling-window entry charged.
|
|
91
90
|
- **Caller cancellation is terminal.** It is non-retryable, releases its
|
|
@@ -114,7 +113,7 @@ from "we are throttling ourselves".
|
|
|
114
113
|
## Enforcement scope
|
|
115
114
|
|
|
116
115
|
This is deliberately **per-runtime**. It completely contains fan-out inside one
|
|
117
|
-
request, including
|
|
116
|
+
request, including parallel `connecta.call` calls in one Worker isolate. A rolling
|
|
118
117
|
budget is exact inside one Node process or Worker isolate, and best-effort
|
|
119
118
|
across isolates, replicas, and restarts.
|
|
120
119
|
|
|
@@ -139,5 +138,5 @@ typed error code.
|
|
|
139
138
|
| Invariant | Suite |
|
|
140
139
|
| --- | --- |
|
|
141
140
|
| Independent partitions, exact rolling-window reset and retry, queued cancellation charging no budget, synchronous cancel during partition derivation, validated values snapshotted rather than read from mutable config, bounded partition state and contained `partitionKey` failures, empty and multi-rule policies refused | `test/call-admission.test.ts` (controller) |
|
|
142
|
-
| One base-registry limiter shared by direct and program calls,
|
|
141
|
+
| One base-registry limiter shared by direct and program calls, promise concurrency with input order preserved, cancellation threading, no dispatch or retry or health poisoning after cancellation, retry hints returned without waiting or poisoning health, payload-free `/health` aggregates | `test/call-admission.test.ts` (integration, Node + Workers) |
|
|
143
142
|
| Where provider budgets are allowed to come from at all | [provider conventions P12](./provider-conventions.md#p12--declare-an-admission-budget-only-when-the-provider-documents-a-number), [provider audit](https://github.com/zackbart/connecta/blob/main/records/provider-audit.md) |
|
|
@@ -135,7 +135,7 @@ Dashboard and API tabs.
|
|
|
135
135
|
|
|
136
136
|
`verify_api_token` needs no permission beyond the token existing. In legacy
|
|
137
137
|
mode, `verify_global_api_key` reads `/user` to confirm the email and key pair.
|
|
138
|
-
The
|
|
138
|
+
The connection UI Test action at `/` runs the matching check before storage.
|
|
139
139
|
|
|
140
140
|
Cloudflare rate-limits *authentication failures* aggressively and separately
|
|
141
141
|
from the global limit: a few requests with a bad token return HTTP 429 with
|