@zackbart/connecta 0.24.1 → 0.24.3
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 +169 -0
- package/dist/auth/bearer.js +2 -0
- package/dist/auth/clerk.d.ts +0 -5
- package/dist/auth/clerk.js +21 -8
- package/dist/auth/downstream-oauth.d.ts +12 -1
- package/dist/auth/downstream-oauth.js +147 -35
- package/dist/call-admission.d.ts +4 -0
- package/dist/call-admission.js +26 -0
- package/dist/catalog-drift.js +9 -4
- package/dist/catalog-service.d.ts +2 -0
- package/dist/catalog-service.js +25 -8
- package/dist/catalog.d.ts +2 -0
- package/dist/catalog.js +246 -121
- package/dist/connector-access.d.ts +32 -0
- package/dist/connector-access.js +79 -0
- package/dist/connectors/api.js +11 -1
- package/dist/connectors/guarded-fetch.d.ts +1 -1
- package/dist/connectors/guarded-fetch.js +27 -20
- package/dist/connectors/remote-mcp.js +84 -53
- package/dist/errors.d.ts +17 -0
- package/dist/errors.js +58 -0
- package/dist/execute.js +85 -23
- package/dist/executor-result.js +3 -1
- package/dist/executors/quickjs-child.js +5 -1
- package/dist/executors/quickjs-protocol.d.ts +4 -0
- package/dist/executors/quickjs-runtime.d.ts +1 -1
- package/dist/executors/quickjs-runtime.js +38 -21
- package/dist/executors/quickjs.js +68 -27
- package/dist/index.d.ts +37 -1
- package/dist/index.js +89 -3
- package/dist/invocation.js +134 -93
- package/dist/mcp-result.js +3 -2
- package/dist/meta-tools.js +118 -39
- package/dist/registry.d.ts +29 -1
- package/dist/registry.js +122 -15
- package/dist/routes/credentials.js +1 -0
- package/dist/routes/mcp.d.ts +4 -1
- package/dist/routes/mcp.js +112 -12
- package/dist/routes/oauth-management.js +1 -0
- package/dist/routes/oauth.js +4 -0
- package/dist/routes/shared.d.ts +7 -1
- package/dist/routes/shared.js +12 -13
- package/dist/routes/ui.js +2 -1
- package/dist/server.js +15 -3
- package/dist/skills.js +6 -5
- package/dist/storage/file.d.ts +6 -2
- package/dist/storage/file.js +312 -34
- package/dist/storage/memory.js +12 -1
- package/dist/validate.js +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +30 -9
- package/documentation/auth.md +110 -6
- package/documentation/call-admission.md +24 -8
- package/documentation/code-mode.md +34 -22
- package/documentation/connectors.md +47 -5
- package/documentation/meta-tools.md +74 -6
- package/documentation/operations.md +20 -19
- package/documentation/provider-conventions.md +7 -0
- package/documentation/request-admission.md +38 -4
- package/documentation/storage-and-credentials.md +54 -1
- package/documentation/upgrading.md +21 -5
- package/ethos.md +1 -1
- package/package.json +1 -1
- package/templates/node/package.json +1 -1
|
@@ -84,6 +84,7 @@ optional.
|
|
|
84
84
|
| `executor` | — (required) | the sandbox `execute_code` runs in ([code mode](./code-mode.md#what-an-executor-must-implement)) |
|
|
85
85
|
| `auth?` | none ⇒ open (dev only) | one `InboundAuth` or an array; bearer providers are checked before interactive providers ([inbound auth](./auth.md)) |
|
|
86
86
|
| `identity?` | all visible; auth management denied; interactive activity reads | `{ connectorAccess?, credentialAdministration?, personalConnection?, activityAccess? }` derives separate use and management permissions ([identity](./auth.md#principals-visibility-and-operators)) |
|
|
87
|
+
| `pools?` | none | `{ <name>: { tools, grant? } }` named slices served at `/mcp/<name>`, each intersected with the identity view and denied unless `grant` admits ([pools](./auth.md#pools)) |
|
|
87
88
|
| `storage?` | `memoryStorage()` | connector state, catalogs, and result paging; pass storage explicitly to the optional vault ([storage](./storage-and-credentials.md)) |
|
|
88
89
|
| `publicUrl?` | per-request origin | public base URL; an HTTPS value also redirects inbound HTTP |
|
|
89
90
|
| `logger?` | `console`, prefixed `[connecta]` | `{ debug, info, warn, error }`, or `"silent"` to suppress diagnostic output; independent of activity history |
|
|
@@ -230,30 +231,30 @@ in.
|
|
|
230
231
|
| Suite | Covers |
|
|
231
232
|
| --- | --- |
|
|
232
233
|
| `activity.test.ts` | payload-free delivery: a rejected async write attaches to `waitUntil` instead of throwing, approved destructive calls record under their real entry point, result-size friction records without retaining the result, and a hallucinated connector id or invented identity is clamped so the event still cannot carry a payload |
|
|
233
|
-
| `api-connector.test.ts` | `api()` — kind, description, tool defs, dispatch, default args, unknown tools, handler throws, argument validation, and the construction contract |
|
|
234
|
+
| `api-connector.test.ts` | `api()` — kind, description, tool defs, dispatch, default args, unknown tools, handler throws, argument validation, structured transport diagnostics, and the construction contract |
|
|
234
235
|
| `bearer.test.ts` | constant-time bearer compare, case-insensitive scheme, 401 challenges, and the retired audience options refusing rather than silently unbinding |
|
|
235
236
|
| `branding.test.ts` | branding fallbacks and overrides across the operator shells, OAuth result pages, `/favicon.*`, page titles, and escaping — branding is not an injection vector |
|
|
236
|
-
| `call-admission.test.ts` | connector-scoped per-runtime downstream admission ([call admission](./call-admission.md)): independent partitions, exact rolling-window reset, cancellation that charges no budget, bounded partition state, local-refusal health isolation,
|
|
237
|
-
| `catalog-drift.test.ts` | `vettedCatalog()`, `detectCatalogDrift()`, and `withVettedCatalog()`; drift on the registry surface and on `/health`; the connector seam projected rather than echoed; and the drift types being public |
|
|
238
|
-
| `catalog.test.ts` | lexical ranking and the compact schema renderer
|
|
237
|
+
| `call-admission.test.ts` | connector-scoped per-runtime downstream admission ([call admission](./call-admission.md)): independent partitions, exact rolling-window reset, cancellation that charges no budget, bounded partition state, local-refusal health isolation, direct and program calls sharing the appropriate controller, independent personal budgets, shared budgets, shutdown of both controller kinds, eviction preserving live budgets, and id-free `/health` aggregates |
|
|
238
|
+
| `catalog-drift.test.ts` | `vettedCatalog()`, `detectCatalogDrift()`, and `withVettedCatalog()`; bounded schema-digest depth; drift on the registry surface and on `/health`; the connector seam projected rather than echoed; and the drift types being public |
|
|
239
|
+
| `catalog.test.ts` | lexical ranking and the compact schema renderer: `const`, `allOf` beside siblings, memoized `$ref`, node/depth/byte bounds, truncation flags, declared required-key metadata, typed search argument validation, per-schema caching, and 2020-12 tuples, conditional markers, and dynamic references in search and describe |
|
|
239
240
|
| `clerk.test.ts` | protected-resource metadata, the browser sign-in config, OAuth and session tokens, cached best-effort activity labels with their caps, the hand-applied `azp` rejection, and the `allowedDomains` allowlist including every lookalike that must not be repaired into a match |
|
|
240
241
|
| `cloudflare-access-auth.test.ts` | trusted `ctx.access` human and service identities, absent/error fail-closed behavior, service-token MCP admission without operator mutation, human same-origin mutation, and the Clerk-to-ambient shell switch |
|
|
241
242
|
| `cloudflare-provider.test.ts` | `cloudflare()` API and MCP construction, the code-mode safety manifest, API tool surface, current R2 and KV jurisdictions, useful output declarations, request building, projections including additive provider fields, typed failures, and credential test |
|
|
242
243
|
| `code-first-surface.test.ts` | the seven-tool surface itself — an executor required, every removed option and top-level tool refused, compact always-loaded routing pinned below 1,000 characters, complete on-demand usage served, and no rendering instructions |
|
|
243
244
|
| `codemode-compat.test.ts` | the `Executor` seam staying structurally compatible with `@cloudflare/codemode`'s `DynamicWorkerExecutor`, enforced by `tsc` |
|
|
244
|
-
| `config.test.ts` | the grouped `ConnectaConfig` boundary — each group forwarding to its internals, malformed admission bounds failing construction, and unknown own-properties rejected by their complete path before construction does work |
|
|
245
|
+
| `config.test.ts` | the grouped `ConnectaConfig` boundary — each group forwarding to its internals, malformed admission bounds, result stash limits, and origin lists failing construction, open-connector warnings including static API auth, and unknown own-properties rejected by their complete path before construction does work |
|
|
245
246
|
| `credentials.test.ts` | the pure stored-shape classifier (containment, not equality) and the AES-GCM vault: round-trip, ciphertext bound to its connector id, named field sets, masked metadata, wrong-key rejection, deletion, coexistence with OAuth keys |
|
|
246
247
|
| `d1-activity-example.test.ts` | the Worker example's deployment-owned D1 activity store: actor namespace round-trip, payload-free friction reconstructed from the persisted code, and agreement with the package's friction table |
|
|
247
|
-
| `downstream-oauth.test.ts` | `KvOAuthProvider` round-trips and generation races, runtime-local rotating-token refresh
|
|
248
|
-
| `errors.test.ts` | `ConnectorCallError` codes, retryable defaults and overrides, `retryAfterMs` round-trip, typed-over-heuristic classification, `AbortError` as a retryable timeout, and framing errors |
|
|
249
|
-
| `execute.test.ts` | the code-mode host bridge: identifier sanitization, account titles in program discovery, MCP-result unwrapping, sandbox provider construction, authenticated thrown-failure framing, fail-closed filtering of destructive and unannotated tools, MCP/code-mode invocation parity, and payload-free describe diagnostics |
|
|
248
|
+
| `downstream-oauth.test.ts` | `KvOAuthProvider` round-trips and generation races, two eight-scope waves of runtime-local rotating-token refresh, recovery after abort/redirect/invalidation, bounded token reads and revision churn, refresh failure/retry, `auth_required` versus `error`, `startAuth`/`finishAuth`, callback refusal equality and identity-free 401 versus explicit 403, bounded diagnostics, and HTML escaping |
|
|
249
|
+
| `errors.test.ts` | `ConnectorCallError` codes, retryable defaults and overrides, `retryAfterMs` round-trip, typed-over-heuristic classification, `AbortError` as a retryable timeout, sanitized bounded unavailable diagnostics, and framing errors |
|
|
250
|
+
| `execute.test.ts` | the code-mode host bridge: identifier sanitization, account titles in program discovery, MCP-result unwrapping, sandbox provider construction, authenticated thrown-failure framing, shared discovery/call budgets including pre-dispatch refusals, bounded recent-failure matching, empty terminal errors, logs on thrown executor failures, short-message failure matching, fail-closed filtering of destructive and unannotated tools, MCP/code-mode invocation parity, and payload-free describe diagnostics |
|
|
250
251
|
| `execute-emit.test.ts` | `connecta.emit` (M1–M10) — block validation, budgets, the provider, delivery after the result envelope on success only, and the defaults |
|
|
251
252
|
| `executor-admission.test.ts` | the portable bounded FIFO both pools use: active and queue ceilings, stable retryable overload, queue timeout, cancellation removal, idempotent release, shutdown |
|
|
252
|
-
| `guarded-fetch.test.ts` | the guarded transport — construction, request building, destination confinement,
|
|
253
|
+
| `guarded-fetch.test.ts` | the guarded transport — construction, request building, destination confinement, response handling, bounded no-stream text/JSON reads, sanitized transport diagnostics, and delta-seconds/HTTP-date Retry-After hints |
|
|
253
254
|
| `guest-api-contract.test.ts` | the shared guest contract on the Dynamic Worker, including caught call, typed inline describe recovery, discovery, utility, parallel-call, and budget failure codes; plus the real authority boundary — local `data:` fetch, denied egress, unresolved DNS, empty environment paths, unavailable filesystem/HTTP builtins, and present runtime globals |
|
|
254
|
-
| `identity-scope.test.ts` | identity-derived connector visibility, personal credential isolation, separate shared-auth and personal-auth management permissions, and personal OAuth callback ownership |
|
|
255
|
+
| `identity-scope.test.ts` | identity-derived connector visibility, named pools at `/mcp/<pool>` (grant-gated, intersected with the identity ceiling, identical 404 for undeclared, refused, and throwing grants, construction-time refusals), exact `connector.tool` grants enforced identically across discovery, direct calls, the program host bridge, and the connection UI, fail-closed grant parsing, the once-per-isolate absent-grant warning, personal credential isolation, separate shared-auth and personal-auth management permissions, bearer-subject result isolation without activity namespaces, connector authorization visibility for tool grants, and personal OAuth callback ownership |
|
|
255
256
|
| `linear-provider.test.ts` | the Linear proxy's construction, guide, plan-aware catalog superset, and current workspace, template, and issue-sharing classifications |
|
|
256
|
-
| `meta-tools-call.test.ts` | registry-backed calls: structured errors, truncation and `get_result`, per-connector result bounds, JSON representation failures, MCP content bounds,
|
|
257
|
+
| `meta-tools-call.test.ts` | registry-backed calls: structured errors, truncation and `get_result`, per-connector result bounds, JSON representation failures, MCP content bounds, offset alignment, runtime-wide stash quotas including pending writes and expiry reclamation, and page-proportional decoding |
|
|
257
258
|
| `meta-tools-search.test.ts` | registry-backed discovery: bounded search with page and address maxima, compact and JSON schemas with constraints, typed describe recovery and suggestions, and structured-result compatibility |
|
|
258
259
|
| `meta-tools.test.ts` | the remaining registry-backed meta-tools: the complete on-demand usage skill, connector-guide selection and summary bounds, stored-credential drift, catalog health, authorization, probe timeouts, and unavailable or unknown browse recovery |
|
|
259
260
|
| `mixpanel-provider.test.ts` | the Mixpanel proxy, its conditional-input guide, destructive metadata fill, and complete 64-tool schema-digest manifest |
|
|
@@ -263,21 +264,21 @@ in.
|
|
|
263
264
|
| `optional-modules.test.ts` | absent modules, UI-free OAuth, fast lists and independent detail deadlines, explicit auth-management grants, invalid-resolver refusal, and passive OAuth consent-state protection |
|
|
264
265
|
| `provider-conventions.test.ts` | the conventions a test can hold: hand-written providers refusing schemas they cannot enforce (H5), their compact discovery schemas staying complete (H7), Cloudflare stating its second pagination convention in the schema (H10), and Notion saying it has no escape hatch (H14) |
|
|
265
266
|
| `provider-registry.test.ts` | all seven maintained providers inside real deployments: boot, description, address, catalog, storage, credential, admission, and activity isolation; plus provider-specific discovery and guide contracts |
|
|
266
|
-
| `registry.test.ts` | construction and id validation, startup warnings, address resolution, version 2 catalog TTL/persistence/completeness, agent-only stale-while-revalidate with cross-request single-flight shared with blocking reads in both start orders, owned teardown, invalidation/fingerprint guards, blocking diagnostics,
|
|
267
|
-
| `remote-mcp.test.ts` | `remoteMcp()` against an in-process server through the `_transportFactory` seam: passthrough, downstream `isError`, Workers-safe output-schema validation, request-scoped client reuse and at-most-once scope close; plus the real transport's manual redirect policy, destination guard, credential containment, and
|
|
267
|
+
| `registry.test.ts` | construction and id validation, startup warnings, bounded absent-grant warning state, address resolution, version 2 catalog TTL/persistence/completeness, agent-only stale-while-revalidate with cross-request single-flight shared with blocking reads in both start orders, owned teardown, invalidation/fingerprint guards, blocking diagnostics, broken-connector isolation, and bounded opportunistic memory-storage expiry |
|
|
268
|
+
| `remote-mcp.test.ts` | `remoteMcp()` against an in-process server through the `_transportFactory` seam: passthrough, downstream `isError`, Workers-safe output-schema validation, request-scoped client reuse and at-most-once scope close; plus the real transport's manual redirect policy, destination guard, credential containment, session termination on scope close/rotation/abandonment, bounded JSON-RPC/HTTP error classification, and sanitized transport diagnostics |
|
|
268
269
|
| `remote-mcp-credential.test.ts` | `remoteMcp()` drawing a static key from the connection UI: the declared slot and its refusal of named fields and bad header names, header framing (bearer, bare, and the two `Basic` forms) observed on the wire, an empty slot failing as `auth_required` rather than reaching the downstream, a value carrying a control character refused before framing and absent from every surface — `call_tool`, `status`, the Test result, the payload-free activity event, and the thrown error — rotation replacing the cached client and a connect already in flight while a wiped value fails the next call, the Test action's catalog probe and scope close, the cleartext-destination warning, and the vault and `authorize_connector` handoff end to end |
|
|
269
270
|
| `remote-mcp-pagination.test.ts` | the `tools/list` cursor chain in both directions — exact cursor handoff, first-wins dedup, a failed later page rejecting rather than returning its prefix, the runaway backstops, the tool-metadata re-prime across pages, and paginated catalogs reaching the discovery path |
|
|
270
271
|
| `request-admission.test.ts` | `/mcp` bounded before auth, the stable 503 and `Retry-After`, health and operator responsiveness under saturation, payload-free counters, queued cancellation, shutdown rejection while active work drains, and the separate fallback code pool |
|
|
271
272
|
| `result-shapes.test.ts` | passive output-shape learning: value-free bounded inference, merging, 256-entry LRU eviction, 24-hour expiry, runtime isolation, read-only admission, declared-schema precedence, definition-change invalidation, discovery provenance, and failure isolation |
|
|
272
273
|
| `revenuecat-provider.test.ts` | the RevenueCat proxy's per-project key scoping and account-wide OAuth guides, its purpose-bearing summary, the refund-preference read and argued borderline verdicts in its digest-free manifest, and the deliberately unclassified `render-paywall-screenshot` |
|
|
273
|
-
| `server.test.ts` | end-to-end `/mcp` (401 → compact initialize instructions → seven compact definitions with bounded connector inventory, account titles, on-demand investigation guidance, and no Apps metadata or resource capability → complete usage skill → `call_tool`), conditional guide pointers, open routes, Clerk `.well-known` metadata without network, code mode, removed connector HTTP hooks rejected at construction, and deferred catalog reads through both discovery surfaces |
|
|
274
|
-
| `server-route-contracts.test.ts` | the route contracts `server.ts` must keep byte-identical: built-in routes and unknown-path 404s inside the security wrapper, open data-free shells with framing denied, per-route auth and same-origin requirements with exact 401/403/405 bodies, and OAuth `verifyState`-before-`finishAuth` ordering |
|
|
274
|
+
| `server.test.ts` | end-to-end `/mcp` (401 → compact initialize instructions → seven compact definitions with bounded connector inventory, account titles, on-demand investigation guidance, and no Apps metadata or resource capability → complete usage skill → `call_tool`), fixed seven-tool registration order across requests, conditional guide pointers, open routes, Clerk `.well-known` metadata without network, code mode, removed connector HTTP hooks rejected at construction, and deferred catalog reads through both discovery surfaces |
|
|
275
|
+
| `server-route-contracts.test.ts` | the route contracts `server.ts` must keep byte-identical: Origin refusal before admission/auth/redirects, exact-origin and wildcard CORS, SEP-2243 preflight headers, all pool suffixes behind auth, application overload/shutdown codes, id-free health preserving doctor drift counts, built-in routes and unknown-path 404s inside the security wrapper, open data-free shells with framing denied, per-route auth and same-origin requirements with exact 401/403/405 bodies, and OAuth `verifyState`-before-`finishAuth` ordering |
|
|
275
276
|
| `startup-warnings.test.ts` | every construction-time `logger.warn` and, as importantly, the conditions that must *not* trigger one: open mode with a credential or OAuth connector, `publicUrl` unset beside OAuth, dropped branding and `uiAuth` URLs, a missing `verifyState`, a credential test-hook mismatch, and an unusable `calls.maxResultBytes` |
|
|
276
277
|
| `stripe-provider.test.ts` | the Stripe proxy's mixed-mode OAuth and fixed-mode header contracts, current eleven-tool classifications, admission, exact account selectors, and no-guess rule |
|
|
277
278
|
| `operator-view.test.ts` | the app's pure state rules from `view.ts`: filtering, page routing, capability states, activity summaries, drift display, and identity reset |
|
|
278
279
|
| `ui-credentials.test.ts` | credential-management routes: save, test, delete, validation, authentication, same-origin checks, and multi-field credential shapes |
|
|
279
280
|
| `ui.test.ts` | the server shell and remaining `/ui/*` routes: gated `/ui/data` with broken-connector isolation and registry-owned catalog-observation containment, plus the URL safety gates |
|
|
280
|
-
| `validate.test.ts` | `validateToolInput()` — a returned (not thrown) `invalid_args` naming the path, `additionalProperties: false` enforcement, per-schema validator caching, and an unusable schema passed through with one warning |
|
|
281
|
+
| `validate.test.ts` | `validateToolInput()` — a returned (not thrown) `invalid_args` naming the path, `additionalProperties: false` enforcement, bounded UTF-8 validation detail, per-schema validator caching, and an unusable schema passed through with one warning |
|
|
281
282
|
| `vercel-provider.test.ts` | `vercel()` API and MCP construction, MCP inventory classification, team scoping, project and deployment projections, finite build and runtime logs, value-safe environment variables, domains, lifecycle writes, REST hatches, typed failures, and credential test |
|
|
282
283
|
|
|
283
284
|
### Node-bound (`NODE_ONLY_SUITES`)
|
|
@@ -291,15 +292,15 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
291
292
|
| `doc-links.test.ts` | the documentation checker itself — local file and fragment resolution, repository URLs resolved back to the checkout, duplicate heading slugs, fenced-code exclusion, and useful failures | spawns the Node checker against filesystem fixtures |
|
|
292
293
|
| `doctor-cli.test.ts` | `connecta doctor`'s executor line and credentials end to end — the sandbox the deployment reports is the one named, an unidentifiable executor gets an executor-neutral line, a hostile name is bounded, and a complete Cloudflare Access service-token pair is accepted while a partial pair is refused | spawns the CLI against a Node HTTP deployment over real sockets |
|
|
293
294
|
| `drift-check.test.ts` | the credential-free maintainer drift checker: recorded touched endpoints, heading, table, and inline MCP inventories, setup-only providers, live-schema ownership, a quiet revision bump, clear failures for unavailable inputs, `$ref` traversal, and one well-formed row per endpoint | spawns the checker against filesystem fixtures |
|
|
294
|
-
| `file-storage.test.ts` | `fileStorage()`
|
|
295
|
+
| `file-storage.test.ts` | `fileStorage()` round trips, exclusive writer locks, namespace-aware heartbeat expiry and stale-guard recovery, close/exit cleanup, unique temp files, logical TTL plus physical pruning, and corrupt-file quarantine | exercises the Node filesystem storage adapter |
|
|
295
296
|
| `guest-api-contract-quickjs.test.ts` | the shared guest-contract cases on the real QuickJS executor, including identical caught failure codes and inline describe recovery, its exact absent globals, and blocked runtime imports | runs the contract cases on the Node QuickJS executor |
|
|
296
297
|
| `node.test.ts` | the `listen()` adapter propagating an HTTP client disconnect through the Web `Request` and the MCP handler into a program's connector call, releasing both admission permits | exercises the Node HTTP adapter over real TCP sockets |
|
|
297
298
|
| `packed-links.test.ts` | the packed-link gate itself — shipped targets and repository URLs accepted, relative links into unshipped paths and directories rejected with the citation to write instead, reference definitions seen, fenced examples ignored, the changelog exempt | spawns the Node packed-link gate against filesystem fixtures |
|
|
298
299
|
| `package-surface.test.ts` | the published boundary — built output shipped, the `exports` map carrying exactly the documented subpaths plus `./package.json`, only generic factories, platform storage kept in examples, Clerk and QuickJS behind optional subpaths, dependency-free Cloudflare Access behind its Worker subpath, every provider independently importable, and the Cloudflare API provider free of bare specifiers | walks the package tree with Node filesystem APIs |
|
|
299
300
|
| `purity.test.ts` | the import-graph guardrail ([architecture](./architecture.md#import-graph-purity)) — the core stays Workers-clean | walks the source import graph with Node filesystem APIs |
|
|
300
301
|
| `quickjs-child-entry.test.ts` | a missing QuickJS child entry failing before `fork()`, with the expected path and the bundler-externalization constraint | mocks Node child-process and filesystem APIs |
|
|
301
|
-
| `quickjs-child-stderr.test.ts` | the QuickJS child-process boundary: an explicitly empty environment despite parent secrets and `NODE_OPTIONS`,
|
|
302
|
-
| `quickjs-executor.test.ts` | executable usage example with dependent, missing, and approval-required evidence; the child-process sandbox — code normalization, provider bridges and canonical connector calls, bounded IPC, separate guest-CPU and wall budgets, saturation, cancellation and shutdown, crash and OOM recovery, host-call hangs, stalled-promise detection | runs the Node QuickJS child-process executor |
|
|
302
|
+
| `quickjs-child-stderr.test.ts` | the QuickJS child-process boundary: an explicitly empty environment despite parent secrets and `NODE_OPTIONS`, abnormal exits retaining only an 8 KiB stderr tail in the parent-side diagnostic, host-result serialization failure returning a bounded error reply, streamed logs on real child crashes, bounded parent retention, and log recovery on shutdown, deadline termination, and IPC failures | mocks Node child-process streams and runs the Node QuickJS child-process executor |
|
|
303
|
+
| `quickjs-executor.test.ts` | executable usage example with dependent, missing, and approval-required evidence; the child-process sandbox — code normalization, provider bridges and canonical connector calls, private authenticated-failure transport and bounded error details, bounded IPC, separate guest-CPU and wall budgets, saturation, cancellation and shutdown, crash and OOM recovery, host-call hangs, stalled-promise detection, logs preserved on cancellation after a program starts | runs the Node QuickJS child-process executor |
|
|
303
304
|
| `quickjs-log-limits.test.ts` | bounded `console.*` capture — per-entry cut, cumulative character and transport budgets, escape-heavy floods preserving the guest result | runs the Node QuickJS child-process executor |
|
|
304
305
|
| `suite-partition.test.ts` | this partition, including itself: every `*.test.ts` in exactly one list, stale entries and empty reasons refused | walks the test directory to guard the partition |
|
|
305
306
|
| `template-file-activity.test.ts` | the Node template's own activity store — persistence across restart, torn-line repair, newest-first paging, and compaction past the slack window | runs it against real files |
|
|
@@ -231,6 +231,13 @@ convenient reading. A call that can only fail is refused locally as
|
|
|
231
231
|
`invalid_args` before the round trip. Provider error prose is never parsed to
|
|
232
232
|
invent a classification.
|
|
233
233
|
|
|
234
|
+
An unreachable transport may report `unavailable` with optional sanitized
|
|
235
|
+
`details.host` and `details.code`. The host is an HTTP(S) origin only, at most
|
|
236
|
+
253 UTF-8 bytes; the code is an allowlisted runtime network code or `timeout`,
|
|
237
|
+
at most 32 bytes. Omit what the runtime cannot establish. The typed error
|
|
238
|
+
constructor strips URL credentials, paths, queries, and fragments, and drops
|
|
239
|
+
invalid or oversized fields. Transport diagnostics never enter activity records.
|
|
240
|
+
|
|
234
241
|
**A downstream 404 is `not_found` — when the provider means it.** The code
|
|
235
242
|
exists because the next move is none of the others': you do not wait, you do
|
|
236
243
|
not send the agent to `authorize_connector`, you do not repair the argument
|
|
@@ -15,7 +15,7 @@ it.
|
|
|
15
15
|
|
|
16
16
|
## The pools
|
|
17
17
|
|
|
18
|
-
Every non-preflight `/mcp` request takes one permit from a deployment-wide FIFO
|
|
18
|
+
Every non-preflight `/mcp` or `/mcp/<pool>` request with an admitted Origin takes one permit from a deployment-wide FIFO
|
|
19
19
|
pool. Initialization, discovery, ordinary calls, and `execute_code` all pay it.
|
|
20
20
|
A program then takes a *second* permit from the deliberately smaller code pool,
|
|
21
21
|
so one request cannot trade ordinary capacity for an unbounded number of
|
|
@@ -54,6 +54,38 @@ identity rules give its principals different connector views
|
|
|
54
54
|
([`ethos.md`](../ethos.md)), so a global queue is not pretending to supply
|
|
55
55
|
something it does not.
|
|
56
56
|
|
|
57
|
+
## Origin before admission
|
|
58
|
+
|
|
59
|
+
MCP checks `Origin` before redirects, request admission, auth, and preflight.
|
|
60
|
+
A present, disallowed origin gets HTTP 403 with the exact body
|
|
61
|
+
`{"error":"origin not allowed"}` and `Cache-Control: no-store`. This local
|
|
62
|
+
check consumes no permit or auth lookup, even when the queue is full or closed.
|
|
63
|
+
Requests without Origin, including ordinary non-browser MCP clients, pass.
|
|
64
|
+
`/health`, OAuth callbacks, and auth metadata retain their existing behavior.
|
|
65
|
+
|
|
66
|
+
`allowedOrigins` accepts a list of exact HTTP(S) origins or `"*"`. An explicit
|
|
67
|
+
list replaces the defaults, including loopback; an empty list admits only
|
|
68
|
+
originless clients. By default the configured `publicUrl` origin and HTTP(S)
|
|
69
|
+
loopback origins at any port are admitted. Loopback means `localhost`,
|
|
70
|
+
`127.0.0.0/8`, or `[::1]`. Without `publicUrl`, only loopback is admitted.
|
|
71
|
+
The inbound Host header never chooses a trusted browser origin. Invalid list
|
|
72
|
+
entries, including paths, credentials, and opaque origins, refuse construction.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
createConnecta({
|
|
76
|
+
publicUrl: "https://connecta.example",
|
|
77
|
+
allowedOrigins: ["https://connecta.example", "https://client.example"],
|
|
78
|
+
// …
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
For unrestricted browser access, set `allowedOrigins: "*"` explicitly. Otherwise
|
|
83
|
+
MCP responses reflect an admitted Origin and carry `Vary: Origin`; originless
|
|
84
|
+
and refused requests have no `Access-Control-Allow-Origin`. Allowed preflight
|
|
85
|
+
returns 204 without auth or admission. The SDK validates SEP-2243 parameter
|
|
86
|
+
headers, so preflight echoes valid requested `mcp-param-*` names alongside the
|
|
87
|
+
fixed MCP header list and varies by `Access-Control-Request-Headers` too.
|
|
88
|
+
|
|
57
89
|
## Admission before auth
|
|
58
90
|
|
|
59
91
|
`/mcp` acquires its permit *before* running the auth gate. This looks backwards
|
|
@@ -86,7 +118,7 @@ CORS headers, and a stable JSON-RPC error:
|
|
|
86
118
|
"jsonrpc": "2.0",
|
|
87
119
|
"id": null,
|
|
88
120
|
"error": {
|
|
89
|
-
"code": -
|
|
121
|
+
"code": -31001,
|
|
90
122
|
"message": "Server capacity is exhausted. Retry later.",
|
|
91
123
|
"data": { "code": "server_overloaded", "retryable": true, "retryAfterMs": 1000 }
|
|
92
124
|
}
|
|
@@ -94,8 +126,10 @@ CORS headers, and a stable JSON-RPC error:
|
|
|
94
126
|
```
|
|
95
127
|
|
|
96
128
|
`Retry-After` is that hint rounded up to at least one whole second. It is
|
|
97
|
-
advice, not a reservation. Shutdown uses `-
|
|
98
|
-
is not retryable.
|
|
129
|
+
advice, not a reservation. Shutdown uses `-31002` / `server_shutting_down` and
|
|
130
|
+
is not retryable. These application codes sit outside JSON-RPC's reserved
|
|
131
|
+
range: MCP forbids new allocations in the legacy `-32000..-32019` range.
|
|
132
|
+
Code-pool overload never reaches this layer: it surfaces as
|
|
99
133
|
an ordinary MCP tool error with `executor_overloaded`, `retryable: true`, and
|
|
100
134
|
the executor's own `retryAfterMs`.
|
|
101
135
|
|
|
@@ -43,6 +43,57 @@ permissions default to none. Saving, testing, replacing, or removing a value
|
|
|
43
43
|
never returns it. The vault is read for each call, so a saved replacement takes
|
|
44
44
|
effect without restarting the deployment.
|
|
45
45
|
|
|
46
|
+
## Result storage
|
|
47
|
+
|
|
48
|
+
Direct-call result paging uses the same KV interface with a 15-minute TTL.
|
|
49
|
+
`results.maxStashBytes` defaults to 8 MiB of stored paging envelopes, including
|
|
50
|
+
base64 overhead; `results.maxStashEntries` defaults to 64. Both are
|
|
51
|
+
non-negative safe integers, and zero disables stashing. One registry accounts
|
|
52
|
+
for all subjects and reserves capacity for pending writes. A full stash keeps
|
|
53
|
+
the successful call's preview and returns a paging-unavailable notice, without
|
|
54
|
+
a result id. Expired entries are deleted on later stash attempts before their
|
|
55
|
+
capacity is reused, even when the backend only expires entries on read.
|
|
56
|
+
A deletion failure keeps the reservation. Limits apply to writes by one
|
|
57
|
+
runtime; they do not coordinate other processes or Worker isolates, or count
|
|
58
|
+
entries left by a previous runtime.
|
|
59
|
+
|
|
60
|
+
The memory store also checks up to 16 existing keys on each `set`, rotating
|
|
61
|
+
through live keys so expired entries that nobody reads are eventually removed.
|
|
62
|
+
There are no timers or background sweeps. Paging values use an ASCII base64
|
|
63
|
+
envelope so only the requested bytes need decoding after the KV read. The
|
|
64
|
+
storage adapter's format and interface stay unchanged.
|
|
65
|
+
|
|
66
|
+
## File storage
|
|
67
|
+
|
|
68
|
+
`fileStorage` is a single-process development store. It loads one snapshot and
|
|
69
|
+
rewrites the whole state synchronously on each mutation, including result
|
|
70
|
+
stashes. It acquires an exclusive `<path>.lock` before loading, so a second
|
|
71
|
+
instance or process opening the same path fails with the holder's pid instead
|
|
72
|
+
of overwriting a stale snapshot. An unref'd timer refreshes the lock's mtime
|
|
73
|
+
every 15 seconds. A heartbeat older than 60 seconds expires regardless of pid,
|
|
74
|
+
so a container restart cannot leave a reused pid holding the file forever.
|
|
75
|
+
The lock records the host/PID namespace as well as the pid. Within that same
|
|
76
|
+
namespace, a dead pid permits immediate recovery; a matching current pid is
|
|
77
|
+
live only when the in-process registry owns that lock. Other namespaces and
|
|
78
|
+
older locks without namespace metadata rely on heartbeat expiry.
|
|
79
|
+
|
|
80
|
+
Recovery uses a serialized `.lock.reclaim` guard, which also expires after
|
|
81
|
+
60 seconds if its process crashes or pauses. An incomplete lock likewise
|
|
82
|
+
becomes recoverable after 60 seconds. A holder paused long enough to lose its
|
|
83
|
+
lock fails subsequent writes with "lock was lost". Writes check ownership
|
|
84
|
+
before changing state and again before rename; reads use the loaded snapshot
|
|
85
|
+
without filesystem lock checks. This remains an advisory development store
|
|
86
|
+
on a shared local filesystem, not a distributed storage adapter.
|
|
87
|
+
|
|
88
|
+
The returned store's `close()` releases the lock and refuses further operations.
|
|
89
|
+
Process exit also releases it, including Node `listen()`'s SIGTERM/SIGINT
|
|
90
|
+
shutdown. Each write uses a unique, exclusively created temp file, and the
|
|
91
|
+
state file's JSON format is unchanged.
|
|
92
|
+
|
|
93
|
+
Expired entries are removed before each write. Large direct-call results therefore increase both
|
|
94
|
+
retained state and write cost. Use `execute_code` to reduce read-only results
|
|
95
|
+
before returning them, and choose a storage adapter suited to the deployment.
|
|
96
|
+
|
|
46
97
|
## Storage continuity
|
|
47
98
|
|
|
48
99
|
This module extraction changes no encrypted record keys, owner partitions, or
|
|
@@ -74,7 +125,9 @@ Personal connectors disappear from a request that has no stable human
|
|
|
74
125
|
principal. For a principal that can see one, connecta partitions connector
|
|
75
126
|
storage, encrypted vault records, catalog caches, OAuth generations, and
|
|
76
127
|
observed result shapes under an opaque SHA-256 identity key. Results used by
|
|
77
|
-
`get_result` are partitioned by the authenticated subject
|
|
128
|
+
`get_result` are partitioned by the authenticated subject independently of
|
|
129
|
+
activity configuration. Open deployments and providers that supply no identity
|
|
130
|
+
share one results partition. See [the partition and paging contract](./meta-tools.md#result-representation).
|
|
78
131
|
|
|
79
132
|
Literal `auth: { type: "headers" }` cannot be personal because its secret lives
|
|
80
133
|
in deployment code. `remoteMcp()` refuses that combination at construction.
|
|
@@ -117,7 +117,7 @@ exist so far:
|
|
|
117
117
|
| --- | --- | --- |
|
|
118
118
|
| **pre-template** | before 0.10.2 | no `connecta init` existed; hand-written, or copied from the retired `examples/node` |
|
|
119
119
|
| **A** | 0.10.2 – 0.15.1 | `.env.example`, `.gitignore`, `AGENTS.md`, `CLAUDE.md`, `README.md`, `package.json`, `src/index.ts`, `tsconfig.json` |
|
|
120
|
-
| **B** | 0.16.0 – 0.24.
|
|
120
|
+
| **B** | 0.16.0 – 0.24.3 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |
|
|
121
121
|
|
|
122
122
|
Generation A is a decade in template years and identifying it precisely does
|
|
123
123
|
not matter, because you are about to reconstruct it exactly rather than guess
|
|
@@ -190,7 +190,7 @@ Generate the *current* template beside the base you already made, into the same
|
|
|
190
190
|
`$SCRATCH`:
|
|
191
191
|
|
|
192
192
|
```sh
|
|
193
|
-
(cd "$SCRATCH" && npx @zackbart/connecta@0.24.
|
|
193
|
+
(cd "$SCRATCH" && npx @zackbart/connecta@0.24.3 init current)
|
|
194
194
|
```
|
|
195
195
|
|
|
196
196
|
You now have a three-way merge with a real base: `$SCRATCH/base` is what this
|
|
@@ -246,7 +246,7 @@ A deployment older than 0.10.2 has no base to diff against. Do not try to
|
|
|
246
246
|
manufacture one. Instead:
|
|
247
247
|
|
|
248
248
|
1. `SCRATCH=$(mktemp -d)`, then
|
|
249
|
-
`(cd "$SCRATCH" && npx @zackbart/connecta@0.24.
|
|
249
|
+
`(cd "$SCRATCH" && npx @zackbart/connecta@0.24.3 init current)` — there is no
|
|
250
250
|
`base` leg here, only the current template to read from.
|
|
251
251
|
2. Copy `$SCRATCH/current` into the deployment file by file, **skipping
|
|
252
252
|
`src/index.ts`**.
|
|
@@ -267,7 +267,21 @@ first, so cross them bottom-up: start at the oldest one still above this
|
|
|
267
267
|
deployment's pin and work back up the page, because each boundary assumes the
|
|
268
268
|
older ones are already done.
|
|
269
269
|
|
|
270
|
-
### 0.23.0 → 0.24.
|
|
270
|
+
### 0.23.0 → 0.24.3
|
|
271
|
+
|
|
272
|
+
0.24.3 validates the browser `Origin` header on `/mcp`. A browser MCP client
|
|
273
|
+
hosted on an origin other than `publicUrl` or loopback now gets a 403 until
|
|
274
|
+
the deployment lists it in `allowedOrigins` (or sets `"*"` to keep the old
|
|
275
|
+
open CORS); clients that send no `Origin`, which is every server-side and CLI
|
|
276
|
+
client, are unaffected. The overload and shutdown JSON-RPC error codes moved
|
|
277
|
+
from `-32001`/`-32002` to `-31001`/`-31002`; the `data.code` strings are
|
|
278
|
+
unchanged. See [request admission](./request-admission.md#origin-before-admission).
|
|
279
|
+
`fileStorage` now holds an exclusive lock on its state file: a second process
|
|
280
|
+
opening the same file fails at construction, so a deployment that shared one
|
|
281
|
+
file between two processes must give each its own. The returned store gained
|
|
282
|
+
`close()`. `get_result` stashes are bounded per runtime by the new `results`
|
|
283
|
+
config (8 MiB and 64 entries by default) and partitioned by any authenticated
|
|
284
|
+
subject, not only by providers that declare an activity namespace.
|
|
271
285
|
|
|
272
286
|
Use the [optional-module migration](./optional-modules-upgrade.md) to select
|
|
273
287
|
modules, grant auth-management permissions, and migrate issued-token clients.
|
|
@@ -275,7 +289,9 @@ Preserve storage, encryption keys, and identity namespaces. 0.24.1 adds two
|
|
|
275
289
|
optional settings, `execute.maxHostCalls` and `execute.hostCallTimeoutMs`, for
|
|
276
290
|
deployments whose providers legitimately run past the 20-call and 15-second
|
|
277
291
|
`execute_code` defaults, and one bounded `warn` log line per failed connector
|
|
278
|
-
call; neither needs migration.
|
|
292
|
+
call; neither needs migration. 0.24.2 adds tool-level
|
|
293
|
+
`connectorAccess` grants and optional named pools at `/mcp/<pool>`; a
|
|
294
|
+
deployment that declares neither is unchanged. See [pools](./auth.md#pools).
|
|
279
295
|
|
|
280
296
|
### 0.22.3 → 0.23.0
|
|
281
297
|
|
package/ethos.md
CHANGED
|
@@ -60,7 +60,7 @@ subsystem guides and the CHANGELOG.
|
|
|
60
60
|
| `connecta.batch` | removed | JavaScript promises suffice |
|
|
61
61
|
| Automatic direct-call retries | removed | callers own retry timing |
|
|
62
62
|
| Connector HTTP routes | removed | deployments own custom routes |
|
|
63
|
-
| Caller-selected toolkits | removed |
|
|
63
|
+
| Caller-selected toolkits | removed | config derives every view; config-declared, grant-gated pools at `/mcp/<pool>` are not caller-selected ([#178](https://github.com/zackbart/connecta/issues/178), [#531](https://github.com/zackbart/connecta/issues/531)) |
|
|
64
64
|
| Proactive credential liveness | removed | fail-at-use is enough ([#179](https://github.com/zackbart/connecta/issues/179)) |
|
|
65
65
|
| Classic (executor-free) surface | removed | an executor is mandatory ([#273](https://github.com/zackbart/connecta/issues/273)) |
|
|
66
66
|
| Per-result lexical query coverage | removed | did not earn its response bytes in a precommitted gate ([#323](https://github.com/zackbart/connecta/issues/323)) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
|