@zackbart/connecta 0.38.0 → 0.39.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 +63 -0
- package/README.md +3 -2
- package/bin/version.mjs +1 -1
- package/dist/agent-routes.js +231 -0
- package/dist/auth/downstream-oauth/consent.js +519 -0
- package/dist/auth/downstream-oauth/grant-store.js +439 -0
- package/dist/auth/downstream-oauth/refresh-coordinator.js +562 -0
- package/dist/auth/downstream-oauth/refresh-records.js +447 -0
- package/dist/auth/downstream-oauth/sdk-hooks.js +242 -0
- package/dist/auth/downstream-oauth.js +66 -2382
- package/dist/auth/native.js +27 -0
- package/dist/auth/oauth-grant.js +13 -0
- package/dist/auth/static-oauth.js +153 -131
- package/dist/auth-elicitation.js +7 -1
- package/dist/authorization-handoff.js +11 -5
- package/dist/catalog-cache.js +130 -43
- package/dist/catalog-policy.js +18 -0
- package/dist/catalog-service.js +284 -47
- package/dist/catalog.js +18 -2
- package/dist/config.d.ts +16 -11
- package/dist/config.js +9 -6
- package/dist/connector-caller.d.ts +1 -1
- package/dist/connector-health.js +59 -0
- package/dist/connector-status.js +117 -0
- package/dist/connectors/api-connector.d.ts +7 -2
- package/dist/connectors/api-connector.js +7 -4
- package/dist/connectors/negotiation-cache.js +22 -4
- package/dist/connectors/remote-mcp/call.js +164 -0
- package/dist/connectors/remote-mcp/catalog.js +278 -0
- package/dist/connectors/remote-mcp/config.js +263 -0
- package/dist/connectors/remote-mcp/connection.js +671 -0
- package/dist/connectors/remote-mcp/errors.js +488 -0
- package/dist/connectors/remote-mcp/oauth.js +469 -0
- package/dist/connectors/remote-mcp/resources.js +473 -0
- package/dist/connectors/remote-mcp/runtime.js +1 -0
- package/dist/connectors/remote-mcp/transport.js +544 -0
- package/dist/connectors/remote-mcp.js +59 -2863
- package/dist/credential-contract.d.ts +23 -0
- package/dist/credential-reads.js +17 -0
- package/dist/credential-verification.js +53 -0
- package/dist/credentials.d.ts +7 -0
- package/dist/credentials.js +60 -25
- package/dist/describe-config.d.ts +12 -2
- package/dist/describe-config.js +2 -0
- package/dist/discovery-health.js +199 -0
- package/dist/downstream-input.js +2 -0
- package/dist/errors.d.ts +55 -17
- package/dist/errors.js +95 -41
- package/dist/execute.js +152 -114
- package/dist/executor-result.js +3 -1
- package/dist/guest-functions.js +83 -0
- package/dist/guest-runtime.js +60 -19
- package/dist/guest-types.d.ts +19 -5
- package/dist/http/argument-problems.js +35 -0
- package/dist/http/errors.js +5 -4
- package/dist/http/fields.js +192 -13
- package/dist/http/hatch-response.js +73 -0
- package/dist/http/hatch.js +88 -23
- package/dist/http/oauth.js +3 -2
- package/dist/http/provider.js +32 -4
- package/dist/http/safety.js +8 -0
- package/dist/http/tools.js +44 -23
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -2
- package/dist/invocation.js +21 -6
- package/dist/membership.d.ts +13 -5
- package/dist/membership.js +34 -2
- package/dist/meta-tools.js +23 -8
- package/dist/native-recovery.js +4 -16
- package/dist/native-tools.js +4 -1
- package/dist/oauth-sealing.js +10 -0
- package/dist/operation-vocabulary.js +135 -13
- package/dist/operator-record.d.ts +2 -2
- package/dist/operator-record.js +1 -0
- package/dist/operator-ui/contract.d.ts +10 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/model.d.ts +22 -1
- package/dist/providers/_shared/rest/operation-index.js +48 -50
- package/dist/providers/_shared/rest/value-safety.js +80 -0
- package/dist/providers/breeze/api.js +7 -1
- package/dist/providers/breeze/skill.generated.js +1 -1
- package/dist/providers/breeze/tools.js +4 -3
- package/dist/providers/ccb/api.js +2 -1
- package/dist/providers/ccb/index.js +5 -0
- package/dist/providers/ccb/skill.generated.js +1 -1
- package/dist/providers/cloudflare/api.js +8 -1
- package/dist/providers/cloudflare/skill.generated.js +1 -1
- package/dist/providers/docs/lib/schemas.js +24 -22
- package/dist/providers/docs/safety.js +2 -0
- package/dist/providers/docs/skill.generated.js +1 -1
- package/dist/providers/docs/tools.js +2 -4
- package/dist/providers/drive/api.js +1 -0
- package/dist/providers/drive/lib/contracts.js +8 -5
- package/dist/providers/drive/skill.generated.js +1 -1
- package/dist/providers/drive/tools.js +11 -16
- package/dist/providers/forms/api.js +1 -0
- package/dist/providers/forms/skill.generated.js +1 -1
- package/dist/providers/forms/tools.js +10 -7
- package/dist/providers/github/api.js +1 -0
- package/dist/providers/github/lib/discovery.js +1 -1
- package/dist/providers/github/skill.generated.js +1 -1
- package/dist/providers/github/tools.js +61 -17
- package/dist/providers/gmail/lib/schemas.js +60 -50
- package/dist/providers/gmail/skill.generated.js +1 -1
- package/dist/providers/gmail/tools.js +7 -5
- package/dist/providers/granola/index.js +2 -0
- package/dist/providers/granola/skill.generated.js +1 -1
- package/dist/providers/overflow/api.js +7 -1
- package/dist/providers/overflow/skill.generated.js +1 -1
- package/dist/providers/planning-center/api.js +3 -1
- package/dist/providers/planning-center/lib/constants.d.ts +1 -1
- package/dist/providers/planning-center/skill.generated.js +1 -1
- package/dist/providers/quickbooks/safety.js +80 -39
- package/dist/providers/quickbooks/skill.generated.js +1 -1
- package/dist/providers/sheets/api.js +1 -0
- package/dist/providers/sheets/skill.generated.js +1 -1
- package/dist/providers/sheets/tools.js +13 -14
- package/dist/providers/slides/skill.generated.js +1 -1
- package/dist/providers/slides/tools.js +15 -13
- package/dist/providers/stripe/skill.generated.js +1 -1
- package/dist/providers/tithely/api.js +3 -1
- package/dist/providers/tithely/skill.generated.js +1 -1
- package/dist/providers/vercel/api.js +1 -1
- package/dist/providers/vercel/skill.generated.js +1 -1
- package/dist/providers/vercel/tools.js +4 -3
- package/dist/registry.d.ts +10 -4
- package/dist/registry.js +41 -13
- package/dist/routes/credentials.js +129 -60
- package/dist/routes/dispatch.js +5 -1
- package/dist/routes/mcp.js +30 -14
- package/dist/routes/operator.js +2 -2
- package/dist/routes/shared.d.ts +6 -1
- package/dist/routes/shared.js +7 -1
- package/dist/routes/ui-config.js +2 -2
- package/dist/routes/ui-data.js +126 -20
- package/dist/routes/ui.js +16 -0
- package/dist/runtime/call.js +7 -2
- package/dist/runtime/native-storage.js +9 -0
- package/dist/runtime/request-reads.js +182 -0
- package/dist/runtime/request-scope.js +16 -0
- package/dist/runtime/storage.js +12 -0
- package/dist/skills.js +37 -20
- package/dist/storage/keys.js +53 -3
- package/dist/storage/memory.js +8 -2
- package/dist/storage/sql-native.js +27 -0
- package/dist/storage/sql.js +12 -2
- package/dist/storage-digest.js +32 -0
- package/dist/timeout.js +8 -0
- package/dist/types.d.ts +33 -0
- package/dist/usage-guide.js +16 -35
- package/dist/validate.d.ts +3 -0
- package/dist/validate.js +220 -158
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/write-outcome.js +0 -3
- package/documentation/README.md +13 -13
- package/documentation/architecture.md +350 -19
- package/documentation/auth.md +217 -63
- package/documentation/code-mode.md +122 -39
- package/documentation/deploying.md +6 -3
- package/documentation/integrating.md +15 -1
- package/documentation/meta-tools.md +220 -46
- package/documentation/migration-0.33.md +5 -1
- package/documentation/migration-0.34.md +3 -1
- package/documentation/operator-tests.md +1 -1
- package/documentation/operator-ui.md +105 -12
- package/documentation/pool-membership-upgrade.md +44 -0
- package/documentation/providers.md +105 -0
- package/examples/worker/AGENTS.md +10 -10
- package/examples/worker/README.md +4 -3
- package/examples/worker/src/connecta.config.ts +1 -0
- package/guides/connecting-agents.md +2 -1
- package/guides/how-it-works.md +4 -2
- package/package.json +1 -1
- package/templates/node/AGENTS.md +13 -12
- package/templates/node/package.json +1 -1
- package/templates/node/src/connecta.config.ts +1 -0
|
@@ -49,7 +49,12 @@ write tools from `search_tools` results and describe, and refuses every write
|
|
|
49
49
|
call. Connector `readOnly` applies the same restriction on every endpoint; effective read-only is endpoint OR connector. Neither setting changes connector visibility or read grants. Guides
|
|
50
50
|
(`queryAnalysis.guideSummary`, `skills`, `connecta.skill`, skill
|
|
51
51
|
`resources/read`) are documentation and may name tools the endpoint refuses. The four tools with structured-only success results
|
|
52
|
-
advertise `outputSchema`.
|
|
52
|
+
advertise `outputSchema`. `search_tools`'s schema defines its typed failure,
|
|
53
|
+
including every authorization-handoff field, once under `$defs.failure`;
|
|
54
|
+
`catalogErrors[]` references it through `allOf` with `connector` required, and
|
|
55
|
+
`queryAnalysis.catalogError` references it directly. The schema declares no
|
|
56
|
+
`$schema`, and validators for drafts 4, 7, 2019-09 and 2020-12 accept the same
|
|
57
|
+
pages. The two direct-call tools omit it because their default
|
|
53
58
|
mode returns native `content`. Default-mode successes declare
|
|
54
59
|
`_meta["dev.connecta/format"]: "json" | "text"`; value mode places the value in
|
|
55
60
|
`data` and declares `format` in its complete result envelope.
|
|
@@ -134,16 +139,25 @@ Live connector probing is not a fourth: the operator pages and `/health` own it.
|
|
|
134
139
|
|
|
135
140
|
## Discovery context
|
|
136
141
|
|
|
137
|
-
The deployment-derived `execute_code` description carries a
|
|
138
|
-
inventory before any catalog search — registry order
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
The deployment-derived `execute_code` description carries a connector
|
|
143
|
+
inventory before any catalog search — registry order and each canonical id,
|
|
144
|
+
with no second name minted for programs. An entry adds the configured title
|
|
145
|
+
only when it says more than the id: a title whose words the id already spells,
|
|
146
|
+
such as `Google Calendar` for `google_calendar`, is dropped. Titles normalize
|
|
147
|
+
whitespace and cap at 48 UTF-8 bytes. A connector with a guide says how to
|
|
148
|
+
fetch it: `read first: skills({name:"connector:<id>"})` for a required guide,
|
|
149
|
+
`guide: skills({name:"connector:<id>"})` otherwise. For example:
|
|
150
|
+
`Connectors: crm (Customer CRM; read first: skills({name:"connector:crm"})), tickets.`
|
|
151
|
+
|
|
152
|
+
The complete line caps at 1,024 UTF-8 bytes, which names every connector of a
|
|
153
|
+
typical deployment. Past the cap, detail degrades before names do: titles are
|
|
154
|
+
dropped first, then optional guide pointers. Only when bare ids and required
|
|
155
|
+
guide pointers still exceed it do whole entries give way, in registry order, to
|
|
156
|
+
an exact `+N more` count. The inventory reads only the configured registry: no
|
|
157
|
+
catalog load, no credential probe, no live status, no capability, and no
|
|
158
|
+
replacement for canonical discovery or addressing. Search pages carry the same
|
|
159
|
+
bounded title once per connector in `connectors[<id>].title`, so choosing an
|
|
160
|
+
account or environment costs no provider read.
|
|
147
161
|
|
|
148
162
|
Read-only lookup belongs in `connecta.search` inside the program; top-level
|
|
149
163
|
`search_tools` stays for explicit catalog inspection and approval-required
|
|
@@ -171,6 +185,56 @@ read/write filter. On `approvalRequired` searches the returned discovery tool
|
|
|
171
185
|
is still a read. Hidden tools, missing grants and read-only restrictions remain
|
|
172
186
|
in force. Browsing does not consult operation vocabulary.
|
|
173
187
|
|
|
188
|
+
When a matched operation's call is fully determined, the first page also
|
|
189
|
+
carries it in `readyCalls`, so a program can call it without operation search or
|
|
190
|
+
details:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"readyCalls": [
|
|
195
|
+
{
|
|
196
|
+
"address": "notes.notes_api_read",
|
|
197
|
+
"args": { "path": "/v1/notes" },
|
|
198
|
+
"classification": "read",
|
|
199
|
+
"summary": "List notes"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Pass `args` unchanged to `connecta.call(address, args)` or `call_tool`. An
|
|
206
|
+
operation is fully determined only when it is a reviewed read served by the
|
|
207
|
+
hatch's `_api_read` tool itself (no named tool), uses GET, the read tool's
|
|
208
|
+
default method, and declares no path template, required parameter or required
|
|
209
|
+
body. Anything needing an id, a method choice or an argument the agent must
|
|
210
|
+
fill in stays behind `_api_search` and `_api_details`. Ready calls pass the same
|
|
211
|
+
endpoint, connector read-only, safety, hidden-tool and grant checks as the
|
|
212
|
+
vocabulary match, through a visible read tool in the caller's view. They are
|
|
213
|
+
computed offline from the construction-time index, read no account data, and
|
|
214
|
+
start no authorization.
|
|
215
|
+
|
|
216
|
+
A ready call must also be what the query names. Each path segment, and the
|
|
217
|
+
operationId without its action and version words, is one whole resource name:
|
|
218
|
+
`event_destinations` is the name "event destination", never "event". Every
|
|
219
|
+
query word other than an action (`list`, `get`, `count`, `show`, `create`,
|
|
220
|
+
`update`, `delete` and their vocabulary aliases) must belong to a resource name
|
|
221
|
+
whose words the query states in order, with singular/plural normalization and
|
|
222
|
+
the provider's declared synonyms. Version segments such as `v1` never count, and
|
|
223
|
+
a summary may supply only actions. A query with no object word gets no ready
|
|
224
|
+
call. Ready calls are omitted entirely when the top result is an exact tool name
|
|
225
|
+
or address, or a complete match on an authored tool, not the hatch's own search
|
|
226
|
+
or read tool, whose name adds nothing to the query: each of its name words is an
|
|
227
|
+
action or a query word, up to plural/singular and declared synonyms. For
|
|
228
|
+
example, `list teams` returns `list_teams` and no ready call, even when other
|
|
229
|
+
operations mention teams in their summaries, while `list projects` still offers
|
|
230
|
+
`/v10/projects` beside `list_project_env_vars`, whose name adds `env` and `vars`.
|
|
231
|
+
Each hatch offers only its top-ranked operation: a last path segment naming the
|
|
232
|
+
resource first, then the fewest resource words the query did not ask for, then
|
|
233
|
+
the shortest path. A connector offers at most one ready call and a page at most
|
|
234
|
+
three, in connector order. Later pages carry none. A ready
|
|
235
|
+
call keeps its read tool's `guideRequired` and `guideRequiredReasons`, and its
|
|
236
|
+
connector appears in `connectors`.
|
|
237
|
+
|
|
174
238
|
Vocabulary is bounded: queries at most 200 characters and eight terms; each
|
|
175
239
|
hatch caches at most 8,192 rows and 2,097,152 characters, with at most 1,024
|
|
176
240
|
characters per row and 128 query intersections. Longer queries and vocabulary
|
|
@@ -281,9 +345,11 @@ guide's first meaningful body paragraph. `required: true` is reserved for
|
|
|
281
345
|
generic API wrappers and cross-operation conventions a complete downstream
|
|
282
346
|
schema cannot express.
|
|
283
347
|
|
|
284
|
-
|
|
285
|
-
`guideSummary
|
|
286
|
-
`
|
|
348
|
+
Describe results carry a `guide: "connector:<id>"` pointer and a
|
|
349
|
+
`guideSummary`; a search page carries both once per connector in
|
|
350
|
+
`connectors[<id>]`. A matching tool row or description also carries
|
|
351
|
+
`guideRequired: true` and `guideRequiredReasons` when Connecta can prove review
|
|
352
|
+
is necessary:
|
|
287
353
|
|
|
288
354
|
| Reason | Raised by | Survives exact schema expansion |
|
|
289
355
|
| -------------------- | ------------------------------------ | -------------------------------------------------------- |
|
|
@@ -297,8 +363,17 @@ is merely told to fetch the guide first, for any reason listed. Otherwise the
|
|
|
297
363
|
bounded summary decides — connector-specific sequencing, units, pagination,
|
|
298
364
|
aliases, and generic API conventions still need the guide when they affect the
|
|
299
365
|
task, while a complete and unambiguous one-read schema proceeds directly. Guide
|
|
300
|
-
lookup
|
|
301
|
-
callers never manufacture `connector:<id>` from an
|
|
366
|
+
lookup uses an exact name returned by `skills({})`, search, describe, or the
|
|
367
|
+
`execute_code` inventory; callers never manufacture `connector:<id>` from an
|
|
368
|
+
unmarked connector. A bare connector id, such as `skills({ name: "crm" })` or
|
|
369
|
+
`connecta.skill("crm")`, also serves that connector's guide. Built-in skill
|
|
370
|
+
names stay reserved: `usage` and `investigate` always fetch the built-in skill,
|
|
371
|
+
even when a connector has that id, whose guide stays at `connector:usage` or
|
|
372
|
+
`connector:investigate`. A bare id naming a connector without a guide fails with
|
|
373
|
+
`Connector "<id>" has no usage guide.`; any other unknown name fails as an
|
|
374
|
+
unknown skill. Names containing `:`, including URIs, never fall back to a bare
|
|
375
|
+
id. MCP `skills/get` resolves names the same way; `resources/read` accepts only
|
|
376
|
+
document URIs.
|
|
302
377
|
|
|
303
378
|
A connector-scoped lexical miss keeps that connector's guide metadata under
|
|
304
379
|
`queryAnalysis`. This matters for generic wrappers whose broad tool name
|
|
@@ -307,12 +382,29 @@ disappearing with the zero-tool page.
|
|
|
307
382
|
|
|
308
383
|
Two built-in skills are byte-identical across deployments. `usage` is fetched
|
|
309
384
|
only for missing guidance or program repair, and owns program selection detail, examples, runtime
|
|
310
|
-
differences, and repair guidance; `investigate` is on-demand
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
385
|
+
differences, and repair guidance; `investigate` is domain-neutral on-demand
|
|
386
|
+
guidance for an investigation that spans several services — shared guidance,
|
|
387
|
+
not a saved workflow and not a source of deployment-specific ids. `skills`
|
|
388
|
+
lists it; the `execute_code` description does not advertise it. The always-loaded instructions and tool definitions keep
|
|
314
389
|
route selection, the fail-closed boundary, and the minimum guest syntax, so a
|
|
315
390
|
client that never fetches a skill can still write a valid first program.
|
|
391
|
+
|
|
392
|
+
The server instructions state the complete routing rule once. Some clients
|
|
393
|
+
drop server instructions, so each tool description stays sufficient for its own
|
|
394
|
+
correct use without restating that rule: `call_tool` names its scope (one
|
|
395
|
+
known-address read) and points other read work to `execute_code`;
|
|
396
|
+
`search_tools` names its scope (catalog inspection, or finding a write) and
|
|
397
|
+
points read work into a program; `execute_code` opens with the terse
|
|
398
|
+
three-route lead (`One known read: call_tool. One known write:
|
|
399
|
+
call_destructive_tool. Everything else: execute_code.`, or the read-only
|
|
400
|
+
two-route form). The `usage` skill points to those two sources instead of
|
|
401
|
+
repeating them.
|
|
402
|
+
|
|
403
|
+
Tool descriptions and output schemas carry deployment configuration only: the
|
|
404
|
+
connector inventory, budgets, the endpoint's read-only setting, and whether any
|
|
405
|
+
visible connector has a guide. No catalog outcome, call, authorization state,
|
|
406
|
+
or other live status reaches `tools/list` or the instructions, so the
|
|
407
|
+
always-loaded surface stays byte-stable for a client's prompt cache.
|
|
316
408
|
The instructions are the same on every endpoint except one addition: at
|
|
317
409
|
`/mcp/<pool>` and `/agent/<pool>`, a pool that sets a
|
|
318
410
|
[`description`](./auth.md#pools) has it appended after `This endpoint: `, so
|
|
@@ -618,7 +710,7 @@ a fixed warning without storage error prose. Never repeat a write to recover out
|
|
|
618
710
|
page. Select tool rows from `page.tools`.
|
|
619
711
|
With the same schema format, schema-key option, and scoped registry, both paths
|
|
620
712
|
return identical data. Top-level search omits schemas unless requested; programs
|
|
621
|
-
default to
|
|
713
|
+
default to TypeScript signatures and schema-key metadata.
|
|
622
714
|
|
|
623
715
|
```json
|
|
624
716
|
{
|
|
@@ -627,12 +719,12 @@ default to JSON schemas and schema-key metadata.
|
|
|
627
719
|
{
|
|
628
720
|
"name": "get_ticket",
|
|
629
721
|
"address": "tickets.get_ticket",
|
|
630
|
-
"connectorTitle": "Tickets",
|
|
631
722
|
"classification": "read",
|
|
632
723
|
"schemaFormat": "json",
|
|
633
724
|
"inputSchema": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] }
|
|
634
725
|
}
|
|
635
726
|
],
|
|
727
|
+
"connectors": { "tickets": { "title": "Tickets", "guide": "connector:tickets", "guideSummary": "Ticket ids and states." } },
|
|
636
728
|
"total": 1,
|
|
637
729
|
"offset": 0,
|
|
638
730
|
"limit": 8,
|
|
@@ -652,8 +744,26 @@ and connector id, never connector-supplied error text. Other failures retain
|
|
|
652
744
|
`retryAfterMs`. A scoped search also keeps its bounded failure subset under
|
|
653
745
|
`queryAnalysis.catalogError` for clients that already use it.
|
|
654
746
|
|
|
655
|
-
|
|
656
|
-
|
|
747
|
+
An unscoped search gives each connector at most 5 seconds (or
|
|
748
|
+
`discovery.probeTimeoutMs` when shorter) and ends within a 9-second discovery
|
|
749
|
+
budget. A connector that recently timed out or failed slowly is skipped for up
|
|
750
|
+
to 60 seconds: its entry keeps the recorded code with `retryable: true`,
|
|
751
|
+
`retryAfterMs`, and the message `Connector "X" was skipped because its catalog
|
|
752
|
+
lookup failed recently (CODE). Search with connector "X" to try it now.` A
|
|
753
|
+
scoped search always probes. Records are kept per owner, admitted endpoint and
|
|
754
|
+
described connector configuration. A healthy connector whose catalog always
|
|
755
|
+
takes more than 5 seconds can stay out of unscoped search; search it with
|
|
756
|
+
`connector`, or let any longer-deadline operation warm its complete catalog.
|
|
757
|
+
See [Discovery health](./architecture.md#storage-credentials-and-connectors).
|
|
758
|
+
|
|
759
|
+
Tool rows carry the address, stored classification, and tool-specific
|
|
760
|
+
`guideRequired` and `guideRequiredReasons`. Facts shared by every row of one
|
|
761
|
+
connector appear once per page in `connectors`, keyed by the connector id that
|
|
762
|
+
prefixes each row's address: the configured display `title` when present and
|
|
763
|
+
`guide` and `guideSummary` when the connector has a guide. The map names only
|
|
764
|
+
connectors with a row or ready call on this page and is omitted when none has
|
|
765
|
+
such facts.
|
|
766
|
+
Requested schemas have
|
|
657
767
|
`schemaFormat: "json"` for JSON Schema values or `schemaFormat: "text"` for
|
|
658
768
|
compact schema strings and TypeScript signatures. Compact schemas are text;
|
|
659
769
|
`inputSchema.properties` is meaningful only in JSON mode. Pagination counts
|
|
@@ -666,7 +776,19 @@ rare domain terms above ubiquitous action terms. Exact tool names and canonical
|
|
|
666
776
|
addresses rank first, so `get_issue` beats `get_issue_status` even when a
|
|
667
777
|
connector is named `issue`. Exact configured connector IDs, full display titles,
|
|
668
778
|
and recognized service names rank next. Complete lexical matches then precede
|
|
669
|
-
partial matches,
|
|
779
|
+
partial matches. Within a tier, a query whose first word outside connector names
|
|
780
|
+
is `list`, `get`, `find`, `search`, `show`, `read`, `fetch`, or `count` ranks
|
|
781
|
+
read rows before write rows; writes stay on the page. Score and catalog order
|
|
782
|
+
break the remaining ties.
|
|
783
|
+
|
|
784
|
+
A maintained provider may declare `searchSynonyms`: groups of single lowercase
|
|
785
|
+
words its users and its vendor use for the same record, such as `household`
|
|
786
|
+
and `family` for Church Community Builder. A query word then matches that
|
|
787
|
+
provider's tools and operation vocabulary through any word in its group, as an
|
|
788
|
+
ordinary whole-token match ranked below the word itself. Synonyms never widen
|
|
789
|
+
another connector's matches. Church Community Builder declares
|
|
790
|
+
`person`/`individual` and `household`/`family`; Granola declares
|
|
791
|
+
`meeting`/`note`.
|
|
670
792
|
An exact connector ID or title query browses that connector's tools, even when
|
|
671
793
|
individual tool names or descriptions mention that identity. Connector identity
|
|
672
794
|
terms that never occur in its tools need not be repeated in every tool description.
|
|
@@ -1027,28 +1149,77 @@ A remote MCP tool's advertised `inputSchema` is checked in the shared invocation
|
|
|
1027
1149
|
path before admission and provider dispatch, so a mismatch is the non-retryable
|
|
1028
1150
|
`invalid_args` identically on `call_tool`, `call_destructive_tool`,
|
|
1029
1151
|
generated-code failures, and rejected promises. The error names the connector and
|
|
1030
|
-
operation and carries
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1152
|
+
operation and carries one recovery envelope, `validation`:
|
|
1153
|
+
|
|
1154
|
+
```json
|
|
1155
|
+
{
|
|
1156
|
+
"issues": [
|
|
1157
|
+
{ "path": "/limit", "expected": "at least 5", "received": "4" },
|
|
1158
|
+
{ "path": "/mode", "expected": "one of \"fast\", \"safe\"", "received": "string" },
|
|
1159
|
+
{ "path": "/<key>", "expected": "one of the accepted keys: mode, limit" }
|
|
1160
|
+
],
|
|
1161
|
+
"acceptedKeys": ["mode", "limit"],
|
|
1162
|
+
"example": { "mode": "fast", "limit": 5 }
|
|
1163
|
+
}
|
|
1164
|
+
```
|
|
1165
|
+
|
|
1166
|
+
Every finding is listed, and the message repeats them, so one corrected call
|
|
1167
|
+
fixes them all.
|
|
1168
|
+
|
|
1169
|
+
A refusal contains only names and literals the published schema declares at
|
|
1170
|
+
non-sensitive positions, numbers allowed by the bound rule below, and fixed
|
|
1171
|
+
placeholder text. It never contains a submitted string or object key, in the
|
|
1172
|
+
message, a finding, `acceptedKeys` or the example. A position is sensitive when
|
|
1173
|
+
it or an ancestor is `writeOnly`; a named tool's input schema marks each request
|
|
1174
|
+
secret that way. API hatch findings name only the operation contract's
|
|
1175
|
+
properties and enum members, as `*_api_details` publishes them.
|
|
1176
|
+
|
|
1177
|
+
- `path` is a JSON Pointer naming declared properties and array indices. The
|
|
1178
|
+
first key the schema does not declare (a misspelled argument, a map key)
|
|
1179
|
+
reads `<key>` and ends the path, e.g. `/headers/<key>`.
|
|
1180
|
+
- `expected` states the constraint that failed, then every other constraint
|
|
1181
|
+
the position declares: bounds, property and item counts, `multipleOf`,
|
|
1182
|
+
`pattern`, `format`, `uniqueItems`, enum members, `dependentRequired`
|
|
1183
|
+
(`string (required with tags)`). A sensitive position never renders an enum,
|
|
1184
|
+
`const` or pattern literal. Each position gets one finding.
|
|
1185
|
+
- `received` is the submitted JSON type, `missing`, or, for a numeric bound at
|
|
1186
|
+
a non-sensitive position of a named tool, the submitted number.
|
|
1187
|
+
|
|
1188
|
+
At most eight findings are returned, each field clipped (path and expected 256
|
|
1189
|
+
characters, received 64), and `truncated: true` says something was omitted or
|
|
1190
|
+
clipped.
|
|
1191
|
+
|
|
1192
|
+
`example` is one valid call synthesized from the published schema and checked
|
|
1193
|
+
against the same validator. It never copies a submitted value, and a sensitive
|
|
1194
|
+
position never renders a schema literal (`enum`, `const`, `default`,
|
|
1195
|
+
`examples`). Complex or unsatisfiable schemas get `exampleUnavailable` instead.
|
|
1196
|
+
Synthesis detects recursive references and shares a 128-node work budget.
|
|
1197
|
+
Invocation uses only this schema example, never a connector's copy of the
|
|
1198
|
+
call, unless the connector states `exampleUnavailable`. API hatches
|
|
1199
|
+
(`*_api_read`, `*_api_write`) always do: their generic schema says nothing
|
|
1200
|
+
about an operation's arguments, so the reason points to the operation's
|
|
1201
|
+
`*_api_details`.
|
|
1202
|
+
|
|
1203
|
+
`acceptedKeys` names the tool's top-level arguments. `conditionalRequirements`
|
|
1204
|
+
lists known `dependentRequired` and `dependentSchemas` requirements by
|
|
1205
|
+
property name; `if`/`then`/`else` conditions are schema subtrees and are not
|
|
1206
|
+
rendered. The envelope has a 4 KiB budget:
|
|
1207
|
+
optional detail, then the example, then trailing findings are dropped whole,
|
|
1208
|
+
with `truncated: true`. A `repair` object a custom connector passes contributes
|
|
1209
|
+
its received types and schema facts. A custom connector's own findings must
|
|
1210
|
+
follow the same rule. Operator records contain only checked failure facts,
|
|
1211
|
+
never findings or examples.
|
|
1034
1212
|
|
|
1035
1213
|
`nextAction` points to discovery scoped to the same connector and tool name when
|
|
1036
1214
|
the compact schema is needed, routed like any other miss: a program to
|
|
1037
1215
|
`connecta.search`, a top-level call to `search_tools`. `retry` says to correct
|
|
1038
|
-
the listed arguments and reissue the original operation.
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
`repair`
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
Its `example` is synthesized without submitted values and checked against the
|
|
1046
|
-
same validator. Complex or unsatisfiable schemas get `exampleUnavailable`
|
|
1047
|
-
rather than an invalid example. Synthesis detects recursive references and
|
|
1048
|
-
shares a 128-node work budget. Alternative branches do not emit dependency
|
|
1049
|
-
advice unless the branch condition is known. Repair detail has a 4 KiB budget; oversized
|
|
1050
|
-
detail is withheld whole with `truncated: true`. Operator records still contain
|
|
1051
|
-
only checked failure facts, never findings or examples.
|
|
1216
|
+
the listed arguments and reissue the original operation. What the local
|
|
1217
|
+
validator declines to evaluate is [code mode](./code-mode.md#errors)'s `E8`.
|
|
1218
|
+
|
|
1219
|
+
Earlier releases returned `validation.issues[].code` (the schema keyword)
|
|
1220
|
+
and a separate `repair` object. Both are gone from responses; a custom
|
|
1221
|
+
connector may still pass `code` and `repair` to `ConnectorCallError`, which
|
|
1222
|
+
folds `repair` into `validation`.
|
|
1052
1223
|
|
|
1053
1224
|
Unknown-address errors list `configuredConnectors` from the current endpoint's
|
|
1054
1225
|
scoped registry, including an empty list when none are accessible. They never
|
|
@@ -1146,7 +1317,9 @@ its code and message for diagnostics but is `retryable: false` with
|
|
|
1146
1317
|
a program's `writes.unknown`. An HTTP refusal of the call's own write stays
|
|
1147
1318
|
known only under the refusal rules above and a complete ledger proving the
|
|
1148
1319
|
refusal covers the whole call; its recovery advice and program accounting both
|
|
1149
|
-
report failure.
|
|
1320
|
+
report failure. A `remoteMcp()` write answered with a 4xx (other than 401, 403,
|
|
1321
|
+
408 or 429) whose body is not a JSON-RPC error is unknown, never a refusal: a
|
|
1322
|
+
gateway may have answered after the server acted. Partial or unknown ledgers remain conservative. An auth failure after entering a write with
|
|
1150
1323
|
no call-owned dispatch reports an unknown outcome and requires reconciliation,
|
|
1151
1324
|
including credential refusals, static-OAuth refresh failures, and `remoteMcp()`
|
|
1152
1325
|
connect or initialize 401s before `tools/call`. A non-auth refusal before
|
|
@@ -1311,7 +1484,7 @@ window, a native `tools/list` carries a 300-second private cache hint, against
|
|
|
1311
1484
|
an hour on meta endpoints. This hint does not guarantee that a host refreshes
|
|
1312
1485
|
its cached annotations; the stale-approval race is accepted on writable pools.
|
|
1313
1486
|
|
|
1314
|
-
**Listing.** `tools/list` is one page with no cursor (Eve 0.
|
|
1487
|
+
**Listing.** `tools/list` is one page with no cursor (Eve 0.90 reads only the
|
|
1315
1488
|
first page). A pool listing more than 1,000 tools fails `tools/list` with a
|
|
1316
1489
|
JSON-RPC error asking the operator to narrow the pool; nothing is silently
|
|
1317
1490
|
dropped. A connector whose catalog cannot load is left out of that listing
|
|
@@ -1328,7 +1501,8 @@ never repeat a write; page a truncated result as its notice says. A pool
|
|
|
1328
1501
|
**Recovery.** Repair and validation fields retain the exact constraint details.
|
|
1329
1502
|
Discovery `nextAction` points to the host's tool search (`host: "search"`), with
|
|
1330
1503
|
only a `query` argument. Retry actions and retry text name the native tool,
|
|
1331
|
-
never a meta wrapper
|
|
1504
|
+
never a meta wrapper; a program on a native pool sees the same native wording
|
|
1505
|
+
in a failure it catches. An unknown name is reported as sent. Auth actions carry `authorizationUrl` or `operatorUrl`;
|
|
1332
1506
|
give the returned URL and instructions to the user or operator. Capable modern
|
|
1333
1507
|
clients may resume native auth and downstream form/URL input with the same
|
|
1334
1508
|
wire name, arguments and returned `requestState`. Changed names, targets or
|
|
@@ -40,6 +40,10 @@ the sections in order, then [verify](#verify).
|
|
|
40
40
|
| `DELETE /ui/credentials/<id>` on an empty slot answering 204 | 409 `{ "problem": "credential_required" }` |
|
|
41
41
|
| The `agent_not_maintainer` denial reason | Removed; agents are refused at human endpoints before admission |
|
|
42
42
|
|
|
43
|
+
This guide records the 0.33 migration. Current versions require every pool to
|
|
44
|
+
list only people or only agents. If a 0.33 deployment combined them, follow
|
|
45
|
+
[Split mixed pools](./pool-membership-upgrade.md) as well.
|
|
46
|
+
|
|
43
47
|
## Maintainers and pool members
|
|
44
48
|
|
|
45
49
|
0.32 combined an identity resolver, a top-level `grant`, and pool `grant`
|
|
@@ -349,4 +353,4 @@ pools: {
|
|
|
349
353
|
absent: search finds none of their tools and a call fails
|
|
350
354
|
`unknown_address`. The same holds in any pool without an owner, even one
|
|
351
355
|
that lists a Workspace connector with a subject mapping.
|
|
352
|
-
6. Confirm each `<agent>-<user>` pool lists
|
|
356
|
+
6. Confirm each `<agent>-<user>` pool lists only the agent in `members` (the current construction rule).
|
|
@@ -39,7 +39,9 @@ If an agent needs to act as Alice, put that access in her personal pool and set
|
|
|
39
39
|
to use. Confirm the pool's tools and members before adding an owner. Follow
|
|
40
40
|
[the agent pool layout](./auth.md#organizing-an-agents-pools) for the full
|
|
41
41
|
configuration. People in the same pool, agents in owned pools and connectors
|
|
42
|
-
with a fixed `subject` address keep their behavior.
|
|
42
|
+
with a fixed `subject` address keep their behavior. Current versions also
|
|
43
|
+
require each pool to list only people or only agents; see
|
|
44
|
+
[Split mixed pools](./pool-membership-upgrade.md).
|
|
43
45
|
|
|
44
46
|
## Optional settings and development tooling
|
|
45
47
|
|
|
@@ -24,7 +24,7 @@ committed through the deployment's own store, so the contract's `agents` and
|
|
|
24
24
|
last seen are fixed. The restricted state is the member fixture from
|
|
25
25
|
`test/fixtures/operator-contract-v2.ts`, and the endpoint and matrix variants
|
|
26
26
|
use its maintainer fixture, which covers every runs-as kind and agent pools,
|
|
27
|
-
with `test/fixtures/operator-console.ts` crowding the team pool so its avatar
|
|
27
|
+
with `test/fixtures/operator-console.ts` crowding the people-only team pool so its avatar
|
|
28
28
|
stack collapses to "+3".
|
|
29
29
|
Collections use their corresponding browser types. Real contract serialization,
|
|
30
30
|
member projection and secret withholding are exercised through
|
|
@@ -113,6 +113,12 @@ Pool endpoint rows show the effective surface (`meta` or `native`) and whether
|
|
|
113
113
|
code is on. These are read-only facts from deployment configuration; change
|
|
114
114
|
`surface` and `executeCode` in deployment code.
|
|
115
115
|
|
|
116
|
+
Plain `/mcp` is routed by sign-in: the `/mcp` row and matrix column show the
|
|
117
|
+
whole catalog maintainers receive, and a pool row shows what its people
|
|
118
|
+
receive at both `/mcp/<pool>` and, when they belong to no other pool, plain
|
|
119
|
+
`/mcp`. A note above the rows says so. People in several pools appear in
|
|
120
|
+
`config.peopleInSeveralPools`; plain `/mcp` refuses them.
|
|
121
|
+
|
|
116
122
|
One row each for `/mcp` and every pool: the path, a read-only pill on a
|
|
117
123
|
read-only endpoint, a copyable URL, who can use it, its connectors as colored
|
|
118
124
|
monograms (four, then "+N"), its tool count over a read and write bar, and a
|
|
@@ -121,7 +127,9 @@ Setup button.
|
|
|
121
127
|
- Who can use it is `root.maintainers` on `/mcp` and the pool's `members`
|
|
122
128
|
elsewhere, as an avatar stack named on hover and to screen readers (label,
|
|
123
129
|
raw id when the label is null, or agent name). Four show, then a "+N"
|
|
124
|
-
button. A pool
|
|
130
|
+
button. A pool lists only people or only agents. An agent pool's row
|
|
131
|
+
still shows two URLs labeled People and Agents; the People URL
|
|
132
|
+
(`/mcp/<pool>`) admits no one, because the pool has no people.
|
|
125
133
|
- Expanding a row lists everyone by name, then each connector with what it
|
|
126
134
|
runs as and its tools, write tools amber with a pencil. Runs-as comes from
|
|
127
135
|
the endpoint's matrix cell: "Shared · saved <date>", "Shared · connected
|
|
@@ -194,8 +202,9 @@ tabs:
|
|
|
194
202
|
annotation badges (Destructive, Open world), filtered by search and All,
|
|
195
203
|
Read and Write. A tool opens its schema in a side drawer.
|
|
196
204
|
- **Connection.** An Authentication card (mode, OAuth client mechanism, who
|
|
197
|
-
manages it, OAuth actions, and the credential card
|
|
198
|
-
field states, and Replace, Test and Remove); a
|
|
205
|
+
manages it, the last verification, OAuth actions, and the credential card
|
|
206
|
+
with masked last four, field states, and Replace, Test and Remove); a
|
|
207
|
+
Diagnostics card of tiles
|
|
199
208
|
(catalog age and last call) with a fix prompt beside each
|
|
200
209
|
problem; and a Configuration card. Its badges name the kind (Remote MCP,
|
|
201
210
|
HTTP API or Custom), provider, auth scope, endpoint host and usage guide.
|
|
@@ -340,10 +349,12 @@ connections**, has no tabs; its heading shows the signed-in email when the
|
|
|
340
349
|
sign-in exposes one (Clerk's primary email), and its top bar shows branding and
|
|
341
350
|
an **Account** button with Sign out or Change token. It lists:
|
|
342
351
|
|
|
343
|
-
- **Your endpoints**: one card per
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
352
|
+
- **Your endpoints**: one card per address with a copy button and **Client
|
|
353
|
+
setup**. A member of exactly one pool sees one card for plain `/mcp`, named
|
|
354
|
+
after the pool it serves; a member of several pools sees one
|
|
355
|
+
`/mcp/<pool>` card per pool. For example, Bob, only in pool `team`, copies
|
|
356
|
+
`https://connecta.example.com/mcp` into an MCP client and authenticates as
|
|
357
|
+
Bob.
|
|
347
358
|
- **Your accounts**: the personal connectors in their pools, each with a
|
|
348
359
|
monogram, tool count, one status badge in an aligned column, and only the
|
|
349
360
|
controls its `manage.actions` lists. A saved credential that no longer fits
|
|
@@ -415,7 +426,8 @@ without this capability contribute an unconfirmed count of zero. For example,
|
|
|
415
426
|
The maintainer view carries:
|
|
416
427
|
|
|
417
428
|
- `config`, the construction-time `describeConfig()` snapshot, including
|
|
418
|
-
`maintainers
|
|
429
|
+
`maintainers`, each pool's `members`, `peopleInSeveralPools` (non-maintainer
|
|
430
|
+
people plain `/mcp` refuses because they are in several pools), and `configSources`, which labels
|
|
419
431
|
each serialized leaf as `default` or `config` from option presence rather
|
|
420
432
|
than equality with the default. Factory descriptions carry relative
|
|
421
433
|
`optionSources` paths so resolved module and transport defaults retain their
|
|
@@ -488,7 +500,9 @@ The maintainer view carries:
|
|
|
488
500
|
The member view is exactly that member's projection: `config`,
|
|
489
501
|
`configSources` and `root` are `null`, `live.connectors`, `agents` and
|
|
490
502
|
`matrix` are empty, and `live.activity` is `"forbidden"`. `pools` lists only
|
|
491
|
-
their pools, each with `owner: null` and `members: []`.
|
|
503
|
+
their pools, each with `owner: null` and `members: []`. With exactly one pool,
|
|
504
|
+
its `humanPath` is `/mcp`, the address that serves them that pool, and the
|
|
505
|
+
member's catalog reads carry that pool as plain `/mcp` would. `connectors` lists
|
|
492
506
|
each connector in those pools with its title, the member's pools that serve
|
|
493
507
|
it, its auth scope, the tools those pools grant with their classification,
|
|
494
508
|
`connection` (their own partition's state and problem code for a personal
|
|
@@ -556,6 +570,58 @@ the config snapshot, and never treats a `per_caller` overlay as an error.
|
|
|
556
570
|
complete classified tools with input/output schemas, registration path, catalog
|
|
557
571
|
age, and activity-derived last-call facts under the reader's disclosure policy.
|
|
558
572
|
A failed or timed-out connector releases its own scope; siblings finish independently.
|
|
573
|
+
The status and catalog observation has its own deadline: 8 seconds, or
|
|
574
|
+
`discovery.probeTimeoutMs` when that is shorter, in which case the whole row
|
|
575
|
+
uses that one deadline. The 8-second value is fixed, not configured; agent
|
|
576
|
+
discovery keeps the full `discovery.probeTimeoutMs`. When the deadline ends
|
|
577
|
+
first, the downstream read is aborted and the row returns `status: "error"`
|
|
578
|
+
with `problem: "connector_timeout"` in the row and its overlay. The row still
|
|
579
|
+
carries its credential card and auth permissions, so a slow connector's slot
|
|
580
|
+
stays manageable. Any other failure keeps `connector_unavailable`. The
|
|
581
|
+
connector renders as **Not responding**, with fixed copy, a fix prompt and
|
|
582
|
+
Refresh.
|
|
583
|
+
**Stored status.** Each live `GET /ui/connectors/:id` records one status
|
|
584
|
+
observation for that connector and viewer partition before it answers: its
|
|
585
|
+
state, problem code, tool count and observation time. Authored static catalogs
|
|
586
|
+
such as `api()` connectors are recorded too, since their status still checks
|
|
587
|
+
auth. The record lives in the `connector-health:v1:` family under the same
|
|
588
|
+
owner partition as the catalog cache (principal, subject, caller identity and
|
|
589
|
+
pool, endpoint, described configuration and package version), so a personal
|
|
590
|
+
connector's observation is one person's. It also carries the catalog
|
|
591
|
+
generation read before the probe, through the request's read memo that the
|
|
592
|
+
catalog listing reuses. It holds no tools, schemas, status prose or
|
|
593
|
+
credential facts. It expires 120 seconds after it was observed, and lapses at
|
|
594
|
+
once when a credential change, OAuth connect or disconnect, or invalidation
|
|
595
|
+
rotates the generation. A read that ends at the row's own deadline, including
|
|
596
|
+
a configured `discovery.probeTimeoutMs` shorter than 8 seconds, records
|
|
597
|
+
`connector_timeout` before it answers. An observation is written only while
|
|
598
|
+
the caller is still waiting: a request its caller has already left starts no
|
|
599
|
+
write. A write that has started is never raced against a deadline or
|
|
600
|
+
detached, because a storage write cannot be withdrawn once sent. The request,
|
|
601
|
+
whether it times out or its caller leaves meanwhile, settles only after that
|
|
602
|
+
write does, bounded by the storage layer like every other awaited write, so
|
|
603
|
+
nothing commits after the request ends.
|
|
604
|
+
|
|
605
|
+
`GET /ui/connectors/:id?observation=stored` answers from a current observation
|
|
606
|
+
without probing the downstream. The row and overlay carry `observedAgeMs`, the
|
|
607
|
+
stored `status`, `problem` and `toolCount`, and `tools: []`; the tools stay in
|
|
608
|
+
the catalog cache. The credential card, drift, permissions and any
|
|
609
|
+
authorization link are computed fresh on every request. Without a current
|
|
610
|
+
observation the route does the live read and records it, with no
|
|
611
|
+
`observedAgeMs`. Nothing is refreshed after the response: no deferred work and
|
|
612
|
+
no `ctx.waitUntil`.
|
|
613
|
+
|
|
614
|
+
The browser asks each connector for its stored observation on the page load
|
|
615
|
+
that follows admission, and fixes the observation time once as each stored
|
|
616
|
+
row lands. The list card and the connector page mark a stored row the same
|
|
617
|
+
way, "Stored status, checked … ago", with an age that keeps counting, and
|
|
618
|
+
show its tools as awaiting the live read rather than as none. The browser then
|
|
619
|
+
sends one plain live read per stored row, through the same queue of eight
|
|
620
|
+
detail reads. A stored `connector_timeout` row is not read again on its own;
|
|
621
|
+
its mark says to Refresh, and it waits for Refresh like a live timeout.
|
|
622
|
+
Refresh, a single connector's read, recovery retries and OAuth polls always
|
|
623
|
+
read live.
|
|
624
|
+
|
|
559
625
|
The summary and each detail carry `viewerKey` for the principal admitted to that
|
|
560
626
|
request. The browser publishes the detail and overlay atomically only when that
|
|
561
627
|
key matches admission. A changed viewer key, including an Access switch between
|
|
@@ -568,7 +634,7 @@ screen. The first answer for the new viewer triggers readmission, which clears
|
|
|
568
634
|
everything retained.
|
|
569
635
|
Config observations never
|
|
570
636
|
overwrite a completed detail row. Each connector opens at most one live observation
|
|
571
|
-
per page load; the summary `/ui/data` performs no downstream probes.
|
|
637
|
+
per page load, after its stored read; the summary `/ui/data` performs no downstream probes.
|
|
572
638
|
|
|
573
639
|
`GET /ui/api/config?connector=<id>` narrows the same contract to one connector
|
|
574
640
|
before status and catalog probes. For a maintainer, config, provenance, live
|
|
@@ -628,8 +694,23 @@ bounded at 2, 2, 4 and 8 seconds; a later focus return can try again after backo
|
|
|
628
694
|
|
|
629
695
|
Connector Refresh, focus recovery and mutation follow-ups read only affected
|
|
630
696
|
connectors. Focus probes unhealthy rows, never healthy siblings. All detail reads
|
|
631
|
-
share
|
|
697
|
+
in one tab share an eight-request limit and coalesce per connector, so a page of
|
|
698
|
+
up to eight connectors loads in one round. The limit is fixed, not configured.
|
|
699
|
+
It bounds how many connectors one tab waits on at once; a tab still reads each
|
|
700
|
+
connector once per load, so the limit adds no requests to any one connector.
|
|
701
|
+
Detail reads do not consume `admission.requests` permits, which govern `/mcp`
|
|
702
|
+
only. They still share isolate CPU and memory, D1, and downstream account quotas
|
|
703
|
+
with agent traffic; each tab adds up to eight concurrent downstream reads, and
|
|
704
|
+
several connectors on one vendor account share that vendor's rate limit. Over HTTP/1.1 the browser itself allows about six
|
|
705
|
+
connections per origin.
|
|
706
|
+
Failures retry only their
|
|
632
707
|
connector with the same bounded backoff; recovery never replays a mutation.
|
|
708
|
+
A `connector_timeout` row is parked instead. It spends its automatic retry
|
|
709
|
+
budget, and focus and visibility returns skip it. Only Refresh, a full refresh
|
|
710
|
+
or a mutation follow-up reads it again, so an outage holds a detail slot once
|
|
711
|
+
per explicit request, never repeatedly. An OAuth start's consent-return poll is
|
|
712
|
+
the exception: a timeout during its 30-second window keeps polling, and success
|
|
713
|
+
still stops it.
|
|
633
714
|
Mutations cancel affected reads and advance their publication fence both at
|
|
634
715
|
dispatch and on settlement, including failure. Follow-ups require an observation
|
|
635
716
|
started after settlement, so a Refresh or retry started during the write cannot
|
|
@@ -638,9 +719,21 @@ while identity and full refresh revisions fence the complete view. An explicit
|
|
|
638
719
|
OAuth start polls only that connector every two seconds for up to 30 seconds.
|
|
639
720
|
Concurrent authorizations retain independent cancellation and publication. Success,
|
|
640
721
|
failed reads, disconnect, navigation, unmount and identity reset stop the matching
|
|
641
|
-
poll. Recovery never starts authorization. A scoped result cannot confirm identity,
|
|
722
|
+
poll; a `connector_timeout` result does not. Recovery never starts authorization. A scoped result cannot confirm identity,
|
|
642
723
|
role, token slots or any other deployment-wide admission fact.
|
|
643
724
|
|
|
725
|
+
A credential connector's `/ui/data` and `/ui/connectors/<id>` row carries
|
|
726
|
+
`verification: { outcome, observedAt }` when a record of the stored save
|
|
727
|
+
exists (see [last verification](./auth.md#test-then-save-and-last-verification)).
|
|
728
|
+
The auth facts show it as **Last verified**: Verified, Saved without a test,
|
|
729
|
+
Rejected, Missing permission, Service unreachable, Test timed out or Test
|
|
730
|
+
failed, with its time. A maintainer's credential form on a testable connector
|
|
731
|
+
saves through **Test and save** (`verify: "test"`). A failed test leaves the
|
|
732
|
+
form open with fixed copy for its failure class, and adds **Save without
|
|
733
|
+
testing**, a save without `verify`. Test shows the same per-class copy and reloads
|
|
734
|
+
the connector so its last verification updates. The member page's
|
|
735
|
+
credential form saves without a test and offers Test once a value is stored.
|
|
736
|
+
|
|
644
737
|
Unreadable credential metadata uses `configured: null`, including named fields,
|
|
645
738
|
and renders as unavailable with a retry prompt. It does not claim that the slot
|
|
646
739
|
is empty. Overview, Endpoints, Connectors, connector
|