@zackbart/connecta 0.40.0 → 0.42.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 +148 -0
- package/bin/connecta.mjs +26 -17
- package/bin/meta-tool-names.d.mts +3 -1
- package/bin/meta-tool-names.mjs +4 -1
- package/bin/version.mjs +1 -1
- package/dist/activity.d.ts +32 -5
- package/dist/activity.js +32 -6
- package/dist/advertised-schema.js +15 -0
- package/dist/agent-observation.js +24 -2
- package/dist/agent-routes.js +33 -44
- package/dist/auth/clerk.d.ts +6 -1
- package/dist/auth/clerk.js +16 -0
- package/dist/auth/cloudflare-access.js +49 -7
- package/dist/auth/downstream-oauth/consent.js +79 -29
- package/dist/auth/downstream-oauth/grant-store.js +58 -7
- package/dist/auth/downstream-oauth/refresh-coordinator.js +4 -1
- package/dist/auth/downstream-oauth/refresh-records.js +6 -5
- package/dist/auth/downstream-oauth.js +15 -4
- package/dist/auth/oauth-request-not-sent.js +4 -0
- package/dist/auth/static-oauth.js +77 -39
- package/dist/auth-elicitation.js +118 -61
- package/dist/authorization-handoff.js +36 -3
- package/dist/catalog-cache.js +352 -43
- package/dist/catalog-freshness.js +25 -0
- package/dist/catalog-service.js +408 -78
- package/dist/catalog.js +216 -62
- package/dist/config-defaults.d.ts +2 -1
- package/dist/config-defaults.js +4 -1
- package/dist/config.d.ts +53 -21
- package/dist/config.js +56 -17
- package/dist/connectors/remote-mcp/call.js +1 -1
- package/dist/connectors/remote-mcp/catalog.js +52 -28
- package/dist/connectors/remote-mcp/connection.js +113 -22
- package/dist/connectors/remote-mcp/oauth.js +2 -2
- package/dist/connectors/remote-mcp/resources.js +5 -2
- package/dist/connectors/remote-mcp/transport.js +24 -6
- package/dist/connectors/remote-mcp.js +14 -5
- package/dist/credential-contract.d.ts +3 -1
- package/dist/describe-config.d.ts +4 -2
- package/dist/describe-config.js +1 -0
- package/dist/discovery-health.js +26 -11
- package/dist/downstream-input.js +11 -2
- package/dist/errors.d.ts +60 -4
- package/dist/errors.js +88 -3
- package/dist/execute.js +491 -202
- package/dist/executor-admission.js +2 -0
- package/dist/executor-contract.js +6 -0
- package/dist/executor-result.js +3 -3
- package/dist/executors/quickjs-child.js +14 -5
- package/dist/executors/quickjs-runtime.d.ts +2 -0
- package/dist/executors/quickjs-runtime.js +37 -20
- package/dist/executors/quickjs.js +24 -7
- package/dist/guarded-transport.js +2 -0
- package/dist/guest-functions.js +5 -4
- package/dist/guest-runtime.js +37 -1
- package/dist/guest-types.d.ts +18 -0
- package/dist/http/client.js +14 -2
- package/dist/http/errors.js +9 -4
- package/dist/http/fields.js +17 -5
- package/dist/http/hatch.js +11 -3
- package/dist/http/node-transport.js +110 -4
- package/dist/http/oauth.js +17 -6
- package/dist/http/paging.js +1 -1
- package/dist/http/provider.js +2 -6
- package/dist/http/vendor.js +6 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -21
- package/dist/invocation-failure.js +28 -0
- package/dist/invocation.js +167 -64
- package/dist/membership.d.ts +1 -1
- package/dist/meta-output.js +24 -18
- package/dist/meta-tool-names.d.ts +1 -1
- package/dist/meta-tool-names.js +1 -1
- package/dist/meta-tools.js +286 -73
- package/dist/module-contracts.d.ts +3 -1
- package/dist/native-recovery.js +4 -1
- package/dist/native-tools.js +177 -55
- package/dist/node.d.ts +7 -0
- package/dist/node.js +85 -4
- package/dist/oauth-handoff.js +53 -43
- package/dist/operation-activity.js +104 -0
- package/dist/operation-vocabulary.js +6 -0
- package/dist/operator-record.d.ts +9 -1
- package/dist/operator-record.js +16 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/program-result.js +2 -0
- package/dist/program-source.js +1 -1
- package/dist/program-writes.js +112 -19
- package/dist/provider.d.ts +1 -14
- package/dist/provider.js +0 -3
- package/dist/providers/_shared/google/kit.js +2 -2
- package/dist/providers/_shared/google/workspace.d.ts +1 -1
- package/dist/providers/breeze/api.js +2 -2
- package/dist/providers/breeze/index.js +1 -1
- package/dist/providers/breeze/skill.generated.js +1 -1
- package/dist/providers/ccb/api.js +2 -2
- package/dist/providers/ccb/index.js +1 -1
- package/dist/providers/ccb/skill.generated.js +1 -1
- package/dist/providers/cloudflare/api.js +2 -2
- package/dist/providers/cloudflare/index.js +3 -1
- package/dist/providers/cloudflare/skill.generated.js +1 -1
- package/dist/providers/docs/index.js +1 -1
- package/dist/providers/docs/skill.generated.js +1 -1
- package/dist/providers/drive/index.js +1 -1
- package/dist/providers/drive/skill.generated.js +1 -1
- package/dist/providers/forms/index.js +2 -1
- package/dist/providers/forms/skill.generated.js +1 -1
- package/dist/providers/github/api.js +98 -6
- package/dist/providers/github/index.js +8 -3
- package/dist/providers/github/lib/auth.d.ts +3 -1
- package/dist/providers/github/lib/auth.js +43 -12
- package/dist/providers/github/lib/discovery.js +11 -1
- package/dist/providers/github/lib/operations.js +8 -0
- package/dist/providers/github/safety.js +39 -0
- package/dist/providers/github/skill.generated.js +1 -1
- package/dist/providers/github/tools.js +12 -5
- package/dist/providers/gmail/index.js +2 -1
- package/dist/providers/gmail/skill.generated.js +1 -1
- package/dist/providers/granola/index.js +1 -1
- package/dist/providers/granola/skill.generated.js +1 -1
- package/dist/providers/overflow/index.js +3 -1
- package/dist/providers/overflow/skill.generated.js +1 -1
- package/dist/providers/planning-center/index.js +12 -6
- 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/api.js +28 -25
- package/dist/providers/quickbooks/index.js +3 -6
- package/dist/providers/quickbooks/lib/writes.js +55 -0
- package/dist/providers/quickbooks/safety.js +17 -5
- package/dist/providers/quickbooks/skill.generated.js +1 -1
- package/dist/providers/sheets/index.js +2 -1
- package/dist/providers/sheets/skill.generated.js +1 -1
- package/dist/providers/slides/index.js +3 -3
- package/dist/providers/slides/skill.generated.js +1 -1
- package/dist/providers/stripe/index.js +2 -2
- package/dist/providers/stripe/skill.generated.js +1 -1
- package/dist/providers/tithely/index.js +2 -1
- package/dist/providers/tithely/skill.generated.js +1 -1
- package/dist/providers/vercel/api.js +3 -2
- package/dist/providers/vercel/skill.generated.js +1 -1
- package/dist/registry.d.ts +36 -4
- package/dist/registry.js +142 -30
- package/dist/resource-read.js +21 -2
- package/dist/result-preview.js +210 -0
- package/dist/result-seal.js +168 -0
- package/dist/route-names.js +53 -0
- package/dist/routes/activity-context.js +1 -0
- package/dist/routes/activity-disclosure.js +26 -4
- package/dist/routes/activity.js +2 -1
- package/dist/routes/connect.js +21 -13
- package/dist/routes/mcp.js +83 -35
- package/dist/routes/shared.d.ts +6 -0
- package/dist/routes/ui-config.js +1 -1
- package/dist/routes/ui-data.js +3 -2
- package/dist/runtime/call.js +15 -10
- package/dist/runtime/native-storage.js +12 -0
- package/dist/runtime/request-reads.js +66 -14
- package/dist/runtime/request-scope.js +38 -2
- package/dist/runtime/run.js +4 -1
- package/dist/sent-secrets.d.ts +20 -0
- package/dist/sent-secrets.js +49 -1
- package/dist/skill-origin.js +16 -0
- package/dist/skills.js +213 -57
- package/dist/storage/d1-driver.js +33 -5
- package/dist/storage/keys.js +16 -7
- package/dist/storage/sql-native.js +60 -3
- package/dist/storage/sql.js +6 -0
- package/dist/timing-trace.js +84 -0
- package/dist/tool-safety.d.ts +33 -0
- package/dist/tool-safety.js +51 -15
- package/dist/types.d.ts +36 -0
- package/dist/url-safety.js +38 -20
- package/dist/usage-guide.js +14 -13
- package/dist/utility-recovery.js +33 -0
- package/dist/validate.js +29 -10
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.js +60 -15
- package/documentation/architecture.md +152 -43
- package/documentation/auth.md +160 -53
- package/documentation/code-mode.md +396 -119
- package/documentation/deploying.md +35 -10
- package/documentation/hosted-mcp-migration.md +9 -3
- package/documentation/integrating.md +27 -5
- package/documentation/meta-tools.md +761 -157
- package/documentation/operating.md +91 -4
- package/documentation/operator-ui.md +51 -2
- package/documentation/providers.md +34 -20
- package/examples/worker/README.md +3 -3
- package/guides/how-it-works.md +2 -1
- package/guides/safety-and-trust.md +1 -3
- package/package.json +10 -8
- package/templates/node/AGENTS.md +3 -3
- package/templates/node/README.md +1 -1
- package/templates/node/package.json +1 -1
|
@@ -240,7 +240,7 @@ An admitted non-preflight `/mcp` request then takes five steps in
|
|
|
240
240
|
5. **Serve.** Refuse `?toolkit=` with a 404 — the toolkits are gone
|
|
241
241
|
([#178](https://github.com/zackbart/connecta/issues/178)) but their URLs were
|
|
242
242
|
handed out, and retiring a scoping boundary into fail-open is worse than any
|
|
243
|
-
404 — then register the
|
|
243
|
+
404 — then register the meta-tools on a fresh `McpServer`
|
|
244
244
|
(`test/server.test.ts`).
|
|
245
245
|
|
|
246
246
|
### Modern request metadata and transport refusals
|
|
@@ -358,6 +358,13 @@ reader. `program-result.ts` owns executor-independent byte limits;
|
|
|
358
358
|
values through provider preludes. Cursors hold only an ID and offset for the
|
|
359
359
|
current run. Result bytes, expiry, authority and capacity charges stay in the
|
|
360
360
|
existing storage and ledger; no executor-specific store or storage key is added.
|
|
361
|
+
`result-seal.ts` keeps a run's results unreadable to other requests until they pass
|
|
362
|
+
its final secret set ([`R4a`](./code-mode.md#results-and-projection)): chunk 0 waits in a
|
|
363
|
+
request-owned ledger, and absence of chunk 0 is the refusal, so every exit leaves
|
|
364
|
+
unpublished entries unreadable with no further write. Sealing waits for the work that can
|
|
365
|
+
add to the set (`HeldResults.track` for the run's host calls, `RequestOwner.credentialReads`
|
|
366
|
+
for credential reads, which outlast a caller that stopped waiting), then publishes each
|
|
367
|
+
entry that passes. Stored bytes are never rewritten.
|
|
361
368
|
|
|
362
369
|
## Admission, in two places
|
|
363
370
|
|
|
@@ -749,8 +756,8 @@ the search returns, never raced or detached, since a storage write cannot be
|
|
|
749
756
|
withdrawn once sent. The budget bounds when health work starts, not when it
|
|
750
757
|
finishes, so slow storage can carry a search past it by one operation's
|
|
751
758
|
latency. A scoped search,
|
|
752
|
-
`connecta.describe
|
|
753
|
-
`
|
|
759
|
+
`connecta.describe` and tool calls keep the full `discovery.probeTimeoutMs`,
|
|
760
|
+
as does a native `tools/list` for a connector with no stale catalog. A probe that times out on its own deadline, or a
|
|
754
761
|
retryable failure that itself took at least one second or named its own wait,
|
|
755
762
|
writes a record in the `connector-health:v1:` family: the connecta
|
|
756
763
|
classification code, observation time, retry time (60 seconds later, or the
|
|
@@ -800,7 +807,56 @@ retain a complete private fallback, and static catalogs remain
|
|
|
800
807
|
in configuration. After a transient first-page tool listing failure, ordinary calls
|
|
801
808
|
may use a complete catalog for up to five minutes after its expiry in the same
|
|
802
809
|
auth partition. Partial walks, permission and auth failures do not use this
|
|
803
|
-
fallback
|
|
810
|
+
fallback, and a refusal keeps later failures from using it until a listing succeeds.
|
|
811
|
+
Resources require unexpired inventories.
|
|
812
|
+
|
|
813
|
+
**Stale listings.** Discovery alone may list a tool catalog up to 24 hours past
|
|
814
|
+
its expiry (`STALE_DISCOVERY_MS`), so chunks and manifests keep that storage TTL
|
|
815
|
+
and a publish deletes the revision it supersedes. Each discovery first peeks the
|
|
816
|
+
entry without a connection (`Connector.peekCatalog`, or the retained custom
|
|
817
|
+
catalog once its listing has failed): storage reads only, through the listing's
|
|
818
|
+
address, fingerprint, generation and credential fences (INV-5, INV-8, INV-10). A
|
|
819
|
+
peek takes no probe slot, and a listing that follows it in the request takes what
|
|
820
|
+
it read, so a resolver still runs once and the entry is read once. A current peek
|
|
821
|
+
skips the probe queue. A stale one stands in for a probe that did not answer, on
|
|
822
|
+
the failures [meta-tools](./meta-tools.md#lexical-discovery) lists, marked in host-only
|
|
823
|
+
provenance (`markCatalogStale`). It stays out of the request's retained catalogs,
|
|
824
|
+
so `resolve` and every call read the live one. A probe that exhausts its own
|
|
825
|
+
deadline hands one refresh to `defer`: a listing in a new request scope, with its
|
|
826
|
+
own signal and transport, closed in that scope and settling the health record it
|
|
827
|
+
leased. Nothing of the original request reaches it (INV-7). One clock, started as
|
|
828
|
+
it is scheduled, bounds its whole tail at 20 seconds, inside Workers' `waitUntil`:
|
|
829
|
+
queueing and the claim spend it, the listing gets what remains less a second for
|
|
830
|
+
settlement and two for cleanup, and a claim that spends it all dispatches nothing.
|
|
831
|
+
Only the request whose settlement wrote the health record takes that refresh;
|
|
832
|
+
settlement and the claim are compare-and-set against the record the request read,
|
|
833
|
+
including creating an absent one, so concurrent failures start one refresh.
|
|
834
|
+
|
|
835
|
+
A peek read before a wait is not served after it. Once a probe or a slot has kept
|
|
836
|
+
the request waiting, the entry is read again through every fence, so an invalidation
|
|
837
|
+
or a refusal in the meantime retires it, in this isolate or another.
|
|
838
|
+
|
|
839
|
+
**Refusal fences.** `auth_required`, `downstream_oauth_required` or
|
|
840
|
+
`provider_permission_denied` from a listing or its handshake writes one key
|
|
841
|
+
(`fenceTools`) in the namespace of the catalog's current generation, addressed by
|
|
842
|
+
the owner partition and credential identity, or by the auth partition alone on a
|
|
843
|
+
shared connector, whose credential gets one answer whoever asks. A tool listing that
|
|
844
|
+
sees it misses, fresh or stale, so `peekTools` and the five-minute fallback have
|
|
845
|
+
nothing to serve; both also read it fresh before serving an expired entry. A listing
|
|
846
|
+
that succeeds lifts by compare-and-set only the fence it first saw, so a refusal
|
|
847
|
+
that lands while it runs stays. The key outlives every entry it guards
|
|
848
|
+
(`CATALOG_FENCE_TTL_SECONDS`) and the generation's rotation discards it with them.
|
|
849
|
+
It adds no round trip to a read: it travels in the catalog snapshot or the manifest
|
|
850
|
+
read. Timeouts and retryable failures write nothing here, and neither does a
|
|
851
|
+
caller-local refusal repeated within one request.
|
|
852
|
+
|
|
853
|
+
The 24-hour limit stays because of these. Everything that can end a caller's access
|
|
854
|
+
and that Connecta can observe (a refusal, a credential change, a disconnect, an
|
|
855
|
+
invalidation) now retires the catalog at once. What remains is a revocation behind a
|
|
856
|
+
connector that has not answered since: tool names and schemas that caller was
|
|
857
|
+
already shown, marked stale, granting nothing, for at most a day. The first answer
|
|
858
|
+
ends it.
|
|
859
|
+
|
|
804
860
|
Host-only provenance carries each catalog's original fetch time, TTL and expiry,
|
|
805
861
|
and whether it was a fallback, through classification and request-local copies.
|
|
806
862
|
Zero TTL and stale fallbacks cannot authorize post-entry auth recovery.
|
|
@@ -808,8 +864,8 @@ Zero TTL and stale fallbacks cannot authorize post-entry auth recovery.
|
|
|
808
864
|
A manifest is published by CAS only after every UTF-8 chunk is written. It
|
|
809
865
|
records the original fetch time, absolute expiry, revision, fingerprint, and
|
|
810
866
|
monotonic stamp. Readers verify all chunks and fingerprint before accepting it.
|
|
811
|
-
Freshness expires at the bounded TTL; tool facts remain for the
|
|
812
|
-
|
|
867
|
+
Freshness expires at the bounded TTL; tool facts remain for the 24-hour stale
|
|
868
|
+
listing limit, of which calls may use five minutes, and generations expire after 48 hours; invalidation
|
|
813
869
|
rotates the generation, and old chunks expire without becoming reachable
|
|
814
870
|
again. Remote clients pin that generation before listing, including SDK cache
|
|
815
871
|
refreshes. Each new listing pins the current generation, so a live client can
|
|
@@ -1042,7 +1098,15 @@ run of K = 8 consecutive UTF-16 units of a registered form of a value at least K
|
|
|
1042
1098
|
long, in the raw text or any JSON-decoded layer; text cut where the cut can end
|
|
1043
1099
|
inside a form loses that unfinished tail, however short.** Runs formed from
|
|
1044
1100
|
placeholder text and kept text or numbers are covered too; the placeholder
|
|
1045
|
-
itself is reserved replacement text.
|
|
1101
|
+
itself is reserved replacement text. The guarantee excludes an occurrence made
|
|
1102
|
+
entirely of reserved replacement text, including a run across the seam between
|
|
1103
|
+
adjacent markers, whether or not the registered form contains a complete
|
|
1104
|
+
`[redacted]`. For example, register `secretsecret` and `ted][red`, then redact
|
|
1105
|
+
`["secretsecret", "secretsecret"]`: the returned leaves may be
|
|
1106
|
+
`["[redacted]", "[redacted]"]`. Their joined projection spells the second
|
|
1107
|
+
registered value using only reserved replacement text; no original secret
|
|
1108
|
+
units survive. An occurrence that includes retained original text stays covered.
|
|
1109
|
+
Registered forms are
|
|
1046
1110
|
the raw value, its URL/form encodings (either percent hex case), base64 and
|
|
1047
1111
|
base64url, and the `Bearer `/`token ` framings. The framing words are public, so
|
|
1048
1112
|
no indexed run starts inside them; a run reaching K units of the value is
|
|
@@ -1344,15 +1408,15 @@ guide (G) violations before writing. It derives `drift.json` version 2's
|
|
|
1344
1408
|
`generated` block from kit operations and evidence digests, and the guide's
|
|
1345
1409
|
`## Conventions` from definition declarations into `skill.generated.ts`.
|
|
1346
1410
|
The generator requires `fixtures.ts` to export `createAuthored()` with a
|
|
1347
|
-
nonempty offline `staticTools` catalog
|
|
1348
|
-
|
|
1349
|
-
tools
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
reports a nonzero explicit refusal count with singular/plural
|
|
1354
|
-
points to the actual prefixed details tool with method/path lookup;
|
|
1355
|
-
embeds the refusal table. Unreviewed operations remain refused.
|
|
1411
|
+
nonempty offline `staticTools` catalog, which the installed inventory lists.
|
|
1412
|
+
Conventions render only provider-specific declarations: the vendor envelope
|
|
1413
|
+
root, the hatch's tools and refusal count, the `idempotencyKey` rule where a
|
|
1414
|
+
provider has one, and the Errors line. Paging, `fields`, withheld-value and
|
|
1415
|
+
write-once rules live at the agent's point of use, and
|
|
1416
|
+
`test/provider-conventions.test.ts` asserts each paged tool's continuation there.
|
|
1417
|
+
The Hatch line reports a nonzero explicit refusal count with singular/plural
|
|
1418
|
+
wording and points to the actual prefixed details tool with method/path lookup;
|
|
1419
|
+
it never embeds the refusal table. Unreviewed operations remain refused.
|
|
1356
1420
|
`ProviderContext.usageGuide` selects a guide's `<!-- when: <key> -->` blocks
|
|
1357
1421
|
with the definition's `blocks`. Maintained drift records use version 2;
|
|
1358
1422
|
`providers:check` retains version-1 endpoint/manual record parsing for historical
|
|
@@ -1712,9 +1776,13 @@ a table.
|
|
|
1712
1776
|
Remote MCP tools classify from server annotations and deployment policy.
|
|
1713
1777
|
Only `readOnlyHint === true` with `destructiveHint !== true` establishes a
|
|
1714
1778
|
source read; missing or contradictory hints mean write. Deployment overrides
|
|
1715
|
-
in `ConnectaConfig.classification` choose effective `read`, `write`, or `hidden
|
|
1716
|
-
|
|
1717
|
-
|
|
1779
|
+
in `ConnectaConfig.classification` choose effective `read`, `write`, or `hidden`,
|
|
1780
|
+
except that `read` cannot change a tool the source explicitly declares a write:
|
|
1781
|
+
a host may resend a read-annotated call, so that tool stays a write unless the
|
|
1782
|
+
deployment accepts that with `read-repeatable`. They cannot
|
|
1783
|
+
relax source replay safety. Effective or source write makes a call
|
|
1784
|
+
write-like on every resend and recovery path. Source facts, including whether a
|
|
1785
|
+
source write was declared or only silent, travel in
|
|
1718
1786
|
private metadata with host-owned tool clones and stay out of persisted catalogs.
|
|
1719
1787
|
A leftover `classify` throws and names `ConnectaConfig.classification`.
|
|
1720
1788
|
There are no hosted review maps, pins, drift comparisons or review UI fields.
|
|
@@ -2005,18 +2073,18 @@ storage is the root's namespaced to its principal.
|
|
|
2005
2073
|
|
|
2006
2074
|
### What runs on Effect
|
|
2007
2075
|
|
|
2008
|
-
| Area | Shape
|
|
2009
|
-
| ---------------------------------------------------------------------- |
|
|
2010
|
-
| Requests (`src/server.ts`, `src/routes/mcp.ts`, `src/routes/oauth.ts`) | One fiber per `fetch`, tied to `request.signal`. An `/mcp` request's admission permit and every `McpServer` it builds live in a Scope the response carries out, closed when the body ends, fails, or is cancelled, when the signal aborts, when its admitted-request lifetime ends in that request, or at once if the handler fails first. If workerd runs none of those callbacks, the next request reclaims only the expired admission record; it cannot close another request's Scope. The OAuth callback is uninterruptible: a single-use code's exchange and catalog invalidation are one commitment.
|
|
2011
|
-
| Admission (`executor-admission.ts`, `call-admission.ts`) | Queued waiters are Deferreds settled by whoever removes them from the queue; a wait is one flat race of grant, Clock timeout, and signal. The uncontended path stays synchronous. Two controllers, as [#453](https://github.com/zackbart/connecta/issues/453) requires.
|
|
2012
|
-
| One tool call (`invocation.ts`) | One fiber: resolution, the read-only and schema refusals, admission, and the downstream attempt sit under a single `withDeadlineEffect`, whose expiry interrupts the call wherever it is. The permit is an `acquireRelease`; the connector call is `Effect.tryPromise` over the unchanged `Connector`.
|
|
2013
|
-
| `execute_code` (`execute.ts`) | One fiber whose Scope owns the run's signal and executor lease, so a result, a throw, the watchdog, and cancellation all release the lease and abort the signal the same way. Public executor methods stay Promise-shaped; registered built-in execution composes directly as an Effect under the signal and `execute.watchdogMs`. Queued acquisition retains its Promise request handoff. Each guest host call is a fiber of its own.
|
|
2014
|
-
| Discovery (`catalog-service.ts`) | A request-scoped cache: one shared read per connector (`runtime/shared-read.ts`), settled by the read itself and carrying its own signal and the probe timeout whichever asker starts it. Each asker waits under its own deadline and signal, so one that times out or is cancelled fails alone, and the read is cancelled only once every asker has gone. Fan-out is `Effect.forEach` under the discovery concurrency; unscoped search
|
|
2015
|
-
| Registry (`registry.ts`) | The result stash is a program over `Storage`. Same-request catalog loads share one read the way discovery's do. Remote MCP caching uses the SDK ResponseCacheStore adapter over SQL-backed KV, with no cross-request catalog flight.
|
|
2016
|
-
| Remote MCP (`connectors/remote-mcp.ts`, `connectors/remote-mcp/`) | Each request scope's state holds a Scope, each connection is a lease forked from it, and a connect in flight is a Deferred carrying the client it connected. Closing a session and the transport are each bounded to a second.
|
|
2017
|
-
| Downstream OAuth (`auth/downstream-oauth*`, `auth/static-oauth.ts`) | A refresh flight is a Deferred. Before the first durable coordinator write (claim CAS) is submitted, call/request closure stops preparation without a CAS, token request or state change. Submission transfers renewal to the storage coordinator under its own 35-second preparation deadline and 20-second token-request/body deadline, followed by the fenced rotation commit through the runtime deferred-work hook. A closed caller promptly fails without consuming the result, marking its ledger renewed or sending/resending a resource request.
|
|
2018
|
-
| Operator and activity data (`routes/operator.ts`) | Each JSON route is one program run by `serveOperator` behind the Promise `handle()`. Reads run under the request's signal; writes do not, so a vault write or OAuth disconnect that started reaches its cache invalidation.
|
|
2019
|
-
| QuickJS pool (`executors/quickjs.ts`, Node only) | Each child is a scoped resource whose release sends SIGTERM, then SIGKILL after a second; crash respawn backoff is a `Schedule`.
|
|
2076
|
+
| Area | Shape |
|
|
2077
|
+
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
2078
|
+
| Requests (`src/server.ts`, `src/routes/mcp.ts`, `src/routes/oauth.ts`) | One fiber per `fetch`, tied to `request.signal`. An `/mcp` request's admission permit and every `McpServer` it builds live in a Scope the response carries out, closed when the body ends, fails, or is cancelled, when the signal aborts, when its admitted-request lifetime ends in that request, or at once if the handler fails first. If workerd runs none of those callbacks, the next request reclaims only the expired admission record; it cannot close another request's Scope. The OAuth callback is uninterruptible: a single-use code's exchange and catalog invalidation are one commitment. |
|
|
2079
|
+
| Admission (`executor-admission.ts`, `call-admission.ts`) | Queued waiters are Deferreds settled by whoever removes them from the queue; a wait is one flat race of grant, Clock timeout, and signal. The uncontended path stays synchronous. Two controllers, as [#453](https://github.com/zackbart/connecta/issues/453) requires. |
|
|
2080
|
+
| One tool call (`invocation.ts`) | One fiber: resolution, the read-only and schema refusals, admission, and the downstream attempt sit under a single `withDeadlineEffect`, whose expiry interrupts the call wherever it is. The permit is an `acquireRelease`; the connector call is `Effect.tryPromise` over the unchanged `Connector`. |
|
|
2081
|
+
| `execute_code` (`execute.ts`) | One fiber whose Scope owns the run's signal and executor lease, so a result, a throw, the watchdog, and cancellation all release the lease and abort the signal the same way. Public executor methods stay Promise-shaped; registered built-in execution composes directly as an Effect under the signal and `execute.watchdogMs`. Queued acquisition retains its Promise request handoff. Each guest host call is a fiber of its own. |
|
|
2082
|
+
| Discovery (`catalog-service.ts`) | A request-scoped cache: one shared read per connector (`runtime/shared-read.ts`), settled by the read itself and carrying its own signal and the probe timeout whichever asker starts it. Each asker waits under its own deadline and signal, so one that times out or is cancelled fails alone, and the read is cancelled only once every asker has gone. Fan-out is `Effect.forEach` under the discovery concurrency, which an unscoped search or native listing applies only to connectors it must ask; those add a cached-catalog peek and stale listing, and unscoped search the discovery budget and health record (`discovery-health.ts`). |
|
|
2083
|
+
| Registry (`registry.ts`) | The result stash is a program over `Storage`. Same-request catalog loads share one read the way discovery's do. Remote MCP caching uses the SDK ResponseCacheStore adapter over SQL-backed KV, with no cross-request catalog flight. |
|
|
2084
|
+
| Remote MCP (`connectors/remote-mcp.ts`, `connectors/remote-mcp/`) | Each request scope's state holds a Scope, each connection is a lease forked from it, and a connect in flight is a Deferred carrying the client it connected. Closing a session and the transport are each bounded to a second. |
|
|
2085
|
+
| Downstream OAuth (`auth/downstream-oauth*`, `auth/static-oauth.ts`) | A refresh flight is a Deferred. Before the first durable coordinator write (claim CAS) is submitted, call/request closure stops preparation without a CAS, token request or state change. Submission transfers renewal to the storage coordinator under its own 35-second preparation deadline and 20-second token-request/body deadline, followed by the fenced rotation commit through the runtime deferred-work hook. A closed caller promptly fails without consuming the result, marking its ledger renewed or sending/resending a resource request. |
|
|
2086
|
+
| Operator and activity data (`routes/operator.ts`) | Each JSON route is one program run by `serveOperator` behind the Promise `handle()`. Reads run under the request's signal; writes do not, so a vault write or OAuth disconnect that started reaches its cache invalidation. |
|
|
2087
|
+
| QuickJS pool (`executors/quickjs.ts`, Node only) | Each child is a scoped resource whose release sends SIGTERM, then SIGKILL after a second; crash respawn backoff is a `Schedule`. |
|
|
2020
2088
|
|
|
2021
2089
|
### Native registry and request services (contributor)
|
|
2022
2090
|
|
|
@@ -2336,8 +2404,11 @@ late publication from an invalidated request unreachable. Missing chunks,
|
|
|
2336
2404
|
expired entries, storage errors, or a failed page trigger a fresh complete
|
|
2337
2405
|
listing. A transient first-page tool-listing failure may use a complete catalog
|
|
2338
2406
|
within five minutes of expiry in the same auth partition. Partial walks and
|
|
2339
|
-
auth or permission failures refuse fallback
|
|
2340
|
-
|
|
2407
|
+
auth or permission failures refuse fallback, and a refusal fences later fallback
|
|
2408
|
+
until a listing succeeds; resources require unexpired inventories, and stale
|
|
2409
|
+
fallback cannot authorize post-entry auth recovery.
|
|
2410
|
+
Discovery's [stale listing](#storage-credentials-and-connectors) reads the same
|
|
2411
|
+
entries and answers no call.
|
|
2341
2412
|
|
|
2342
2413
|
**Repeated reads share one request's memo.** `src/runtime/request-reads.ts`
|
|
2343
2414
|
gives each request owner a memo of storage reads, emptied when the request
|
|
@@ -2596,11 +2667,9 @@ this declaration keep parameter-based continuation.
|
|
|
2596
2667
|
An explicit initialAnchor adapter on parameter-based paging can retain a numeric
|
|
2597
2668
|
timestamp as a first-page time-window anchor; opaque string continuations still
|
|
2598
2669
|
require a signed token.
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
`page.in` specifies. `kit.hatch.paging` still validates declared mode values as
|
|
2603
|
-
a sanity check; it does not select the generated continuation instruction.
|
|
2670
|
+
A read tool's input schema states how to continue: tools that take `cursor`
|
|
2671
|
+
restore `page.nextCursor` as that top-level argument; tools without it restore
|
|
2672
|
+
the token in `query[page.param]` or `body[page.param]`, as `page.in` specifies.
|
|
2604
2673
|
An unsafe continuation keeps the safe page data with `hasMore: true` and no
|
|
2605
2674
|
`nextCursor`.
|
|
2606
2675
|
A reviewed `HatchBinding` can supply vendor encoding/origin routing through
|
|
@@ -2649,7 +2718,8 @@ contracts, `Summary` annotations and lenient success schemas become the
|
|
|
2649
2718
|
index's parameters, bodies, summaries and declared fields (optional
|
|
2650
2719
|
`OpenApiData.fields`). Kit facts carry the vendor's declared
|
|
2651
2720
|
`VendorErrors.meanings` and an `idempotencyKey` checked against the write
|
|
2652
|
-
builders at construction
|
|
2721
|
+
builders at construction; the generated Conventions state the key rule only where
|
|
2722
|
+
a provider has one, and the Errors line always.
|
|
2653
2723
|
|
|
2654
2724
|
Hatch request paths and query keys/values refuse any containment of the shared
|
|
2655
2725
|
`[redacted]` marker, including decoded spellings. Body fields and kit write
|
|
@@ -2660,8 +2730,7 @@ Admission iteratively visits keys and values before the write program runs;
|
|
|
2660
2730
|
it checks agent arguments, not whole bodies later composed from internal
|
|
2661
2731
|
reads. The kit connection also checks actual typed path parameters and query
|
|
2662
2732
|
values before transport. Legacy non-kit tools retain their link-only admission;
|
|
2663
|
-
arbitrary binary/base64 bytes are not decoded by this scalar rule.
|
|
2664
|
-
sets `refusesWithheld` for the standard hatch, enabling the generated convention.
|
|
2733
|
+
arbitrary binary/base64 bytes are not decoded by this scalar rule.
|
|
2665
2734
|
Declared error-code facts use the closed `ConnectorCallErrorCode` set at
|
|
2666
2735
|
construction (INV-11); classification callbacks are not run at construction.
|
|
2667
2736
|
|
|
@@ -3362,7 +3431,7 @@ compiling and configuring the real thing.
|
|
|
3362
3431
|
is not a declared refusal standing for the whole call makes the call
|
|
3363
3432
|
unknown, never retryable, with no wait and no resend or key-reuse advice;
|
|
3364
3433
|
while any such 401 is unrenewed the verdict keeps an authorization code,
|
|
3365
|
-
so invocation keeps the
|
|
3434
|
+
so invocation keeps the authorization handoff and picks its
|
|
3366
3435
|
reconcile-first words. Its code and words are the failure's when that is an
|
|
3367
3436
|
authorization verdict, else the 401's own recorded verdict, else
|
|
3368
3437
|
`auth_required`, with a sentence saying the write was sent before the
|
|
@@ -3772,6 +3841,16 @@ change. All 88 declarations still exclude Effect and have complete references.
|
|
|
3772
3841
|
|
|
3773
3842
|
### Native remote MCP programs (contributor)
|
|
3774
3843
|
|
|
3844
|
+
Legacy session termination may read a token before rotation and send its DELETE
|
|
3845
|
+
on the wire after rotation. This is accepted only for bounded, headers-only
|
|
3846
|
+
termination of the old session, never for application traffic (`tools/call`,
|
|
3847
|
+
`tools/list`, or other RPCs). Connection scope close retains the same cleanup
|
|
3848
|
+
completion after revocation; later connector close joins it so the runtime's
|
|
3849
|
+
deferred hook (Workers `waitUntil`) owns the bounded tail. Abandoned leases from
|
|
3850
|
+
rotation and failed connects, and authorization exchange transports, retain their
|
|
3851
|
+
cleanup in that same request state. Termination and local close keep their
|
|
3852
|
+
existing one-second budgets; the caller-facing close window remains 100 ms.
|
|
3853
|
+
|
|
3775
3854
|
Remote MCP connection joins, credential and epoch checks, catalog intake,
|
|
3776
3855
|
negotiation, calls, resources, Skills, auth and status compose native programs.
|
|
3777
3856
|
`connectors/remote-mcp.ts` keeps the published options, the redirect guard and
|
|
@@ -3908,7 +3987,8 @@ physical-attempt and body/admission suites remain compatibility evidence.
|
|
|
3908
3987
|
|
|
3909
3988
|
The standard hatch privately registers bounded vendor operation text against its
|
|
3910
3989
|
ApiTool identity; `apiConnector` transfers those facts to the constructed
|
|
3911
|
-
connector
|
|
3990
|
+
connector, and a provider that wraps that connector carries them to its outer
|
|
3991
|
+
object with `carryConnectorVocabulary`. `operation-vocabulary.ts` contains only pure lexical/cache logic and
|
|
3912
3992
|
types. Catalog discovery consumes those facts after loading and classifying a
|
|
3913
3993
|
complete visible catalog. It never imports a provider or an operation index,
|
|
3914
3994
|
parses operation contracts, invokes a handler, or authenticates. Matching requires
|
|
@@ -3918,3 +3998,32 @@ cache. Exact authored names and complete authored matches precede API pointers;
|
|
|
3918
3998
|
ordinary result limits, offsets, catalog failure disclosure and byte bounds apply.
|
|
3919
3999
|
The published discovery contract states compilation, query and cache bounds.
|
|
3920
4000
|
No request identity, signal, credential or promise enters a vocabulary cache.
|
|
4001
|
+
|
|
4002
|
+
SQL catalog locating snapshots derive at most two manifest candidates from the
|
|
4003
|
+
stored generation alongside negotiation and generation rows. These candidates
|
|
4004
|
+
are request-local hints with exact config, owner and credential partitions.
|
|
4005
|
+
Complete chunk verification and a separate later primary generation and identity
|
|
4006
|
+
fence decide acceptance. OAuth invocation and dispatch reads stay separate.
|
|
4007
|
+
|
|
4008
|
+
SQL result stashes write at most 64 trailing rows per awaited transaction, with one
|
|
4009
|
+
expiry sweep per batch. Header publication follows confirmed trailing writes in a
|
|
4010
|
+
separate transaction; uncertain writes retain their ledger charge until expiry.
|
|
4011
|
+
Custom storage keeps sequential writes.
|
|
4012
|
+
|
|
4013
|
+
Admission observation sampling retains at most 256 scalar deadlines per live
|
|
4014
|
+
physical storage identity in an isolate. Only a recent valid stored timestamp
|
|
4015
|
+
or confirmed CAS populates it, for at most one minute. This telemetry cache
|
|
4016
|
+
never answers token admission; every request still checks current credentials.
|
|
4017
|
+
|
|
4018
|
+
### Lexical token reuse (contributor)
|
|
4019
|
+
|
|
4020
|
+
Search may retain four complete accepted catalog token indexes, bounded by an
|
|
4021
|
+
8 MiB estimate including key text, token strings, postings and structural slots.
|
|
4022
|
+
Identity includes complete served content (including schemas, classification and
|
|
4023
|
+
order), connector, physical store, owner partition/revisions and the downstream catalog
|
|
4024
|
+
generation observed by the current successful listing. The generation marker
|
|
4025
|
+
is request-local primitive evidence; it grants no cache acceptance or authority. Only immutable
|
|
4026
|
+
strings and numeric positions cross requests. Search views map positions to the
|
|
4027
|
+
current request's definitions after owner visibility, classification, redaction
|
|
4028
|
+
and endpoint restrictions; no query results are retained. Partial failed
|
|
4029
|
+
catalogs cannot enter this cache. Eviction changes cost only, never results.
|