@zackbart/connecta 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/README.md +126 -134
  3. package/bin/connecta.mjs +13 -2
  4. package/bin/version.mjs +1 -1
  5. package/dist/argument-redaction.js +230 -0
  6. package/dist/auth-elicitation.js +14 -9
  7. package/dist/authorization-handoff.js +111 -0
  8. package/dist/call-recovery.js +25 -0
  9. package/dist/catalog-cache.js +2 -2
  10. package/dist/catalog-service.js +103 -63
  11. package/dist/config-schema.d.ts +14 -7
  12. package/dist/config-schema.js +29 -10
  13. package/dist/config.d.ts +2 -0
  14. package/dist/config.js +12 -7
  15. package/dist/connectors/guarded-fetch.d.ts +9 -1
  16. package/dist/connectors/guarded-fetch.js +17 -5
  17. package/dist/connectors/negotiation-cache.js +1 -1
  18. package/dist/downstream-input-context.js +9 -0
  19. package/dist/downstream-input.js +13 -11
  20. package/dist/errors.d.ts +38 -12
  21. package/dist/errors.js +19 -9
  22. package/dist/execute.js +375 -43
  23. package/dist/executor-result.js +11 -9
  24. package/dist/executors/quickjs-child.js +12 -5
  25. package/dist/executors/quickjs-protocol.js +5 -6
  26. package/dist/executors/quickjs-runtime.js +6 -1
  27. package/dist/executors/quickjs.js +20 -4
  28. package/dist/guest-runtime.js +52 -2
  29. package/dist/guest-types.d.ts +47 -5
  30. package/dist/index.d.ts +1 -1
  31. package/dist/invocation.js +72 -14
  32. package/dist/meta-output.js +0 -15
  33. package/dist/meta-tools.js +166 -95
  34. package/dist/oauth-handoff.js +88 -11
  35. package/dist/operator-ui/generated.js +2 -2
  36. package/dist/operator-ui/view.d.ts +9 -0
  37. package/dist/operator-ui/view.js +11 -0
  38. package/dist/program-result.js +5 -0
  39. package/dist/program-writes.js +7 -48
  40. package/dist/provider.d.ts +8 -6
  41. package/dist/provider.js +3 -4
  42. package/dist/providers/_shared/google/workspace.d.ts +1 -1
  43. package/dist/providers/_shared/request-token.js +83 -0
  44. package/dist/providers/_shared/rest/dispatch.js +41 -0
  45. package/dist/providers/_shared/rest/operation-index.d.ts +133 -0
  46. package/dist/providers/_shared/rest/operation-index.js +527 -0
  47. package/dist/providers/_shared/rest/tools.d.ts +141 -0
  48. package/dist/providers/_shared/rest/tools.js +569 -0
  49. package/dist/providers/_shared/rest/value-safety.d.ts +151 -0
  50. package/dist/providers/_shared/rest/value-safety.js +580 -0
  51. package/dist/providers/cloudflare/graphql.js +385 -0
  52. package/dist/providers/cloudflare/index.d.ts +47 -51
  53. package/dist/providers/cloudflare/index.js +188 -1997
  54. package/dist/providers/cloudflare/openapi.generated.js +3347 -0
  55. package/dist/providers/cloudflare/rest.d.ts +37 -0
  56. package/dist/providers/cloudflare/rest.js +1056 -0
  57. package/dist/providers/cloudflare/skill.generated.js +7 -4
  58. package/dist/providers/cloudflare/value-safety.js +1247 -0
  59. package/dist/providers/infisical/index.d.ts +7 -0
  60. package/dist/providers/infisical/index.js +713 -0
  61. package/dist/providers/infisical/skill.generated.js +8 -0
  62. package/dist/providers/notion/index.d.ts +35 -31
  63. package/dist/providers/notion/index.js +60 -1499
  64. package/dist/providers/notion/openapi.generated.js +75 -0
  65. package/dist/providers/notion/rest.d.ts +24 -0
  66. package/dist/providers/notion/rest.js +1067 -0
  67. package/dist/providers/notion/skill.generated.js +5 -4
  68. package/dist/providers/notion/value-safety.js +31 -0
  69. package/dist/providers/stripe/index.d.ts +26 -20
  70. package/dist/providers/stripe/index.js +103 -130
  71. package/dist/providers/stripe/openapi.generated.js +649 -0
  72. package/dist/providers/stripe/rest.d.ts +14 -0
  73. package/dist/providers/stripe/rest.js +395 -0
  74. package/dist/providers/stripe/skill.generated.js +7 -5
  75. package/dist/providers/stripe/value-safety.js +705 -0
  76. package/dist/providers/vercel/index.d.ts +31 -22
  77. package/dist/providers/vercel/index.js +96 -853
  78. package/dist/providers/vercel/openapi.generated.js +456 -0
  79. package/dist/providers/vercel/rest.d.ts +20 -0
  80. package/dist/providers/vercel/rest.js +1002 -0
  81. package/dist/providers/vercel/skill.generated.js +4 -5
  82. package/dist/providers/vercel/value-safety.js +328 -0
  83. package/dist/registry.d.ts +8 -6
  84. package/dist/registry.js +134 -61
  85. package/dist/resource-read.js +4 -1
  86. package/dist/routes/mcp.js +11 -2
  87. package/dist/sent-secrets.d.ts +54 -13
  88. package/dist/sent-secrets.js +770 -231
  89. package/dist/skills.js +26 -16
  90. package/dist/sqlite.js +21 -6
  91. package/dist/storage/keys.js +20 -5
  92. package/dist/storage/memory.js +9 -4
  93. package/dist/storage/sql.js +18 -9
  94. package/dist/types.d.ts +17 -3
  95. package/dist/usage-guide.js +49 -40
  96. package/dist/version.d.ts +1 -1
  97. package/dist/version.js +1 -1
  98. package/dist/worker.js +2 -1
  99. package/dist/write-outcome.js +47 -0
  100. package/documentation/README.md +64 -0
  101. package/documentation/architecture.md +241 -97
  102. package/documentation/auth.md +138 -5
  103. package/documentation/code-mode.md +224 -107
  104. package/documentation/deploying.md +146 -0
  105. package/documentation/integrating.md +170 -0
  106. package/documentation/meta-tools.md +142 -30
  107. package/documentation/operating.md +135 -0
  108. package/documentation/operator-tests.md +4 -0
  109. package/documentation/operator-ui.md +132 -0
  110. package/documentation/provider-auth-migration.md +307 -0
  111. package/documentation/provider-migration-0.29.md +22 -5
  112. package/examples/worker/README.md +9 -2
  113. package/package.json +9 -2
  114. package/templates/node/README.md +9 -2
  115. package/templates/node/package.json +1 -1
  116. package/dist/providers/vercel/mcp-ownership.js +0 -212
package/CHANGELOG.md CHANGED
@@ -2,6 +2,105 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.31.0 — 2026-10-09
6
+
7
+ Connecta 0.31.0 lets the auth mode choose how Stripe, Notion, Cloudflare and Vercel connect (#801). `auth: { type: "oauth" }` connects the vendor's hosted MCP server, OAuth only. A key connects Connecta's own REST connector with an operator-managed credential: Stripe `apiKey`, Notion `token`, Cloudflare `apiToken` or `globalApiKey`, and Vercel `token`. Each implementation is now complete on its own. This replaces the 0.29 split, in which the hosted server owned writes and the REST surface refused them, so a Cloudflare API token could not change a DNS record. Decision record 0005 explains the choice. Deployments that use none of these four providers need no changes.
8
+
9
+ The timing comes from Stripe. Its hosted MCP server stops accepting `sk_` secret keys and untagged `rk_` restricted keys on 2026-10-31, so a deployment that sends one of those keys to `mcp.stripe.com` loses Stripe on that date. Upgrade before then. Stripe still documents agent-tagged restricted keys for its MCP server, but Connecta's hosted Stripe connection is now OAuth only, and every Stripe key, tagged or not, uses the REST connector. For these four providers, Connecta no longer sends a bearer key, literal header or operator credential to the hosted MCP server. Other hosted providers, such as RevenueCat, Mixpanel and GitHub, are unchanged.
10
+
11
+ Every key connector serves the same four tools. `<vendor>_api_search` and `<vendor>_api_details` read an operation index compiled from the vendor's pinned OpenAPI document. `<vendor>_api_read` and `<vendor>_api_write` check each call's path and parameters against that index before sending it, and return `{ status, data, page? }`. The read tool admits GET plus reviewed read-only POSTs such as Stripe's invoice preview, Cloudflare analytics and Vercel observability queries. Each vendor keeps a few named tools. Stripe POST writes send the caller's `idempotencyKey`, or a generated one, as `Idempotency-Key` and return it; DELETE writes send none. When a deadline interrupts one of those POST writes, or its outcome is otherwise unknown, `uncertainCall.recovery` carries the generated key, or a caller-supplied key of at most 128 characters. A longer caller key is still sent to Stripe but not echoed there, since the caller already has it. Every Stripe request, v1 and v2, sends `Stripe-Version: 2026-09-30.endive`, the pinned index's version, whatever the account's default API version. Response shapes and accepted parameters follow that version, so check the fields programs rely on with `stripe_api_details`. Stripe's `connectedAccount` now works with an operator-managed key. `npm run providers:check` reports when a pinned index falls behind the vendor's live document.
12
+
13
+ Most existing configurations of these providers need edits. `auth` is now required, with no default, and omitting it throws an error that lists the valid types. `surface` is removed from Notion, Vercel and Cloudflare, along with Cloudflare `authentication` and its `credential` override. Stripe loses literal `headers` auth and hosted `credential` auth. Cloudflare bearer-token auth to `mcp.cloudflare.com` is removed, so those deployments move to `apiToken` and its REST tools. A credential stored under the same connector id carries over; run its Test action after upgrading.
14
+
15
+ Tool names change on the key paths. Cloudflare's `cloudflare_api_get` and `cloudflare_api_mutate` become `cloudflare_api_read` and `cloudflare_api_write`. `verify_api_token` and `verify_global_api_key` become `verify_credential`. Cloudflare's 23 hand-written reads give way to `cloudflare_api_read`, which returns unprojected results. Vercel's `vercel_api_get` and `vercel_api_mutate` become `vercel_api_read` and `vercel_api_write`, and `verify_project_domain`, `remove_project_domain` and `delete_deployment` are removed. Notion's token connector drops eight `integration_*` tools in favor of the generic ones. Stripe keeps its tool names with Connecta's contracts, but natural-language Sigma, metrics, docs search, the planner, reports and feedback exist only on the OAuth connection.
16
+
17
+ Several exports are removed. Cloudflare loses `CloudflareApiOptions`, `CloudflareMcpOptions`, `CloudflareConnectionOptions` and `CloudflareAuthentication`, plus `CLOUDFLARE_DNS_RECORD_TYPES` and `CLOUDFLARE_CONTENT_DNS_RECORD_TYPES`. Notion and Vercel lose their `ApiOptions`, `McpOptions` and `ConnectionOptions` types, and Stripe loses `StripeHeaderOptions`. Each `<Vendor>Options` is now a union of per-auth types, such as `StripeApiKeyOptions`, `NotionTokenOptions`, `VercelTokenOptions` and `CloudflareGlobalApiKeyOptions`.
18
+
19
+ A Cloudflare Global API Key reaches every account and zone its user can reach. `auth: { type: "globalApiKey" }` therefore requires `pin: { accountIds, zoneIds }` unless the configuration states `unpinned: true`. It never writes `/user` or `/memberships`. Pins deny by default and also apply to GraphQL tags and list results. An operation that names no account or zone is refused unless it was reviewed as safe. Pins are optional for scoped API tokens. A Global API Key cannot reach R2.
20
+
21
+ Every key connector applies one reviewed value-safety table. No REST tool response, success or error, returns a credential that grants access to the vendor or a third party, or a stored secret value. Operations that mint or hand out credentials are refused before they are sent. Stored secrets read as `"[redacted]"`. URLs that act as capabilities keep only their scheme and host, or lose their signing parameters. Reviewed operations withhold the vendor's error text unless their review keeps it. Results therefore lose fields they used to return. Stripe withholds client secrets, webhook signing secrets, Issuing card numbers and CVCs, and Checkout Session URLs other than those of guest payment sessions. Notion strips the signatures from pre-signed file URLs, so a returned file URL no longer downloads. Vercel returns `"[redacted]"` for environment values and header rule values. Cloudflare redacts Hyperdrive passwords, dispatch binding values and transform-rule header values. The guarantee assumes an honest vendor server and covers only the REST key connectors. Secrets that people type into free text, names or identifiers are out of scope. Hosted OAuth connections fall outside it: they return what the vendor's server returns, under Connecta's existing credential and `writeOnly` redaction.
22
+
23
+ The four provider entries now carry both transports and a pinned index. Measured gzip, Stripe grows from 171 KB to 243 KB, Notion from 191 KB to 216 KB, Vercel from 190 KB to 231 KB and Cloudflare from 193 KB to 338 KB, all within their stated caps. Vercel admits only reviewed and approved MCP clients to its hosted server. If it refuses authorization for that reason, the deployment needs Vercel's approval or a token connector. Vercel's hosted connection now lists its four environment variable tools. The two that can return decrypted values are classified as writes. Cloudflare's hosted `execute` is always a write, so a read-only pool on a Cloudflare OAuth connector reaches only `search`. Use an API token for read-only API access. Agent evals against fake vendors for all four providers are planned. `documentation/provider-auth-migration.md` gives the step-by-step migration for each provider.
24
+
25
+ ### Changed
26
+
27
+ - **Breaking:** `cloudflare()` now requires `auth`, which selects the implementation. `auth: { type: "oauth" }` connects Cloudflare's hosted MCP server (`search` and `execute`), OAuth only; bearer-token and credential auth to `mcp.cloudflare.com` are removed. `auth: { type: "apiToken" }` and `auth: { type: "globalApiKey" }` connect Connecta's own REST connector to the v4 API with an operator-managed credential: `cloudflare_api_search` and `cloudflare_api_details` read a pinned Cloudflare API index (3,336 operations, deprecated ones dropped), `cloudflare_api_read` (GET plus 47 reviewed read-only POSTs such as analytics, Analytics Engine and Log Explorer SQL, and KV bulk get) and `cloudflare_api_write` check every call against that index before sending it and return `{ status, data, page? }` with the envelope unwrapped, and the named tools are `verify_credential`, `list_accounts`, `list_zones`, `graphql_query` (read-only, refuses mutations), and `cloudflare_api_upload`. `accountId` and `zoneId` fill path placeholders; `pin: { accountIds, zoneIds }` restricts every call by default deny (an operation naming no account or zone is refused unless reviewed safe), including GraphQL tags and list results, and is required for a Global API Key unless `unpinned: true`. A reviewed value-safety table derived from the pinned spec gives every credential-bearing operation a verdict: credential producers (API tokens, Access service tokens, R2 temporary credentials, signing keys, direct-upload URLs, and more) and payment secrets are refused, stored and embedded secrets and environment and plain-text binding values are redacted on every method and tool, and operations that take or return credentials withhold vendor error text; URL Scanner captures are refused; a pinned connector's GraphQL documents hold one query and only fragments it uses, and a key-name, typed-secret, and URL-credential heuristic backs it up; a Global API Key never writes `/user` or `/memberships`. `surface`, `authentication`, `credential` overrides, the API-token mutation refusals, `verify_api_token`, `verify_global_api_key` (now `verify_credential`), `cloudflare_api_get`, `cloudflare_api_mutate`, the 23 hand-written reads from `get_zone` and `list_dns_records` to `list_pages_domains` (use `cloudflare_api_read`), `CLOUDFLARE_DNS_RECORD_TYPES`, `CLOUDFLARE_CONTENT_DNS_RECORD_TYPES`, and the `CloudflareApiOptions`, `CloudflareMcpOptions`, `CloudflareConnectionOptions`, and `CloudflareAuthentication` types are removed. See the provider auth migration guide.
28
+ - Record that the auth mode selects the provider implementation: OAuth uses the vendor's hosted MCP and keys use a Connecta REST connector, superseding the hosted MCP ownership rule for Stripe, Vercel, Cloudflare and Notion (decision record 0005). Each provider's change is its own entry.
29
+ - **Breaking:** `notion()` now requires `auth`, which selects the implementation, and `surface` is removed. `auth: { type: "oauth" }` connects Notion's hosted MCP server as the signed-in user, OAuth only, with the same reviewed catalog. `auth: { type: "token" }` connects Connecta's REST connector to `api.notion.com` as an internal integration with an operator-managed token: `notion_api_search`, `notion_api_details`, `notion_api_read`, and `notion_api_write` reach every operation in a pinned Notion API index (with the sent `Notion-Version` pinned to it), check each call against it before sending, admit Notion's read-only POST queries on the read tool, and return `{ status, data, page? }`, where `page.in: "body"` marks a body-borne cursor, `page.path` names a view query's continuation, and `hasMore` without `next` marks a cursorless cut-off such as meeting notes' limit. The token connector keeps `integration_search`, `integration_get_page`, `integration_get_page_content`, `integration_get_data_source_schema`, `integration_query_data_source`, `integration_create_page`, and `integration_append_blocks` (which now also takes `checklist`); `integration_get_page_property`, `integration_get_database`, `integration_list_users`, `integration_get_self`, `integration_list_comments`, `integration_update_page_properties`, `integration_trash_page`, and `integration_add_comment` are removed in favor of the generic tools. Notion's OAuth token endpoints and multipart file sends are refused. Notion's reconciliation table is retired. `npm run providers:spec` accepts `options.versionHeader` for documents that carry their API version in a header parameter. See the provider auth migration guide.
30
+ - **Breaking:** `stripe()` now requires `auth`, which selects the implementation. `auth: { type: "oauth" }` connects Stripe's hosted MCP server exactly as before, OAuth only. `auth: { type: "apiKey" }` with `mode` (and optional `connectedAccount`) connects Connecta's own REST connector to `api.stripe.com` with an operator-managed secret or restricted key: `stripe_api_search` and `stripe_api_details` read a pinned Stripe API index, `stripe_api_read` and `stripe_api_write` check every call against that index before sending it, form-encode v1 bodies, send v2 bodies as JSON, send `Stripe-Version: 2026-09-30.endive` (the pinned index's version) on every v1 and v2 request whatever the account's default API version, so response shapes and accepted parameters follow it (check them with `stripe_api_details`), return `{ status, data, page? }` with optional `select`, and on every POST write send the caller's `idempotencyKey` or a generated one as `Idempotency-Key` and return it (DELETE sends none); `get_stripe_account_info` and `get_balance_summary` are named reads. A key whose prefix contradicts `mode` is refused before any request, and `connectedAccount` now works with an operator-managed key. Literal `headers` and hosted `credential` auth are removed; omitting `auth` is refused with the valid types. Providers gain the `"dual"` kind, `variants()` accepts a nested discriminant such as `["auth", "type"]`, the operator UI shows whether a provider connector uses hosted MCP or REST, and `npm run providers:spec` compiles pinned OpenAPI documents into operation indexes that `check:providers-generated` checks offline and `providers:check` compares with the live document. A POST write's key also reaches the caller when the response body is lost or the call deadline interrupts it: `write_outcome_unknown` now carries `uncertainCall.recovery` with the generated key, or a caller-supplied key of at most 128 characters (a longer caller key is still sent to Stripe but not echoed, since the caller already has it). See the provider auth migration guide.
31
+ - **Breaking:** `vercel()` now requires `auth`, which selects the implementation, and `surface` is removed. `auth: { type: "oauth" }` connects Vercel's hosted MCP server as before, OAuth only; it now also lists `filter_project_envs`, `get_project_env`, `create_project_env`, and `edit_project_env`, with the two value-returning reads reviewed as writes. `auth: { type: "token" }` with optional `teamId` and `baseUrl` connects Connecta's own REST connector to `api.vercel.com` with an operator-managed access token, complete on its own: `vercel_api_search` and `vercel_api_details` read Vercel's OpenAPI document pinned by content hash, `vercel_api_read` (GET plus reviewed read-only POSTs such as `POST /v2/observability/query`) and `vercel_api_write` check every call against that index before sending it, apply the default team to operations that accept one (`teamId: null` for the personal account), and return `{ status, data, page? }` with `until` or `cursor` pagination. Named tools are `list_teams`, the value-safe environment variable tools, `get_deployment_build_logs`, `get_runtime_logs` (bounded by `waitMs` and `maxRows`), and `vercel_api_upload` for octet-stream operations. Value safety follows a reviewed per-operation table derived from the pinned spec (`scripts/value-safety.mjs` flags every operation whose response may carry a credential or secret value; a test fails on any without a verdict): credential minting, Connect authorization, project transfer requests, decrypted environment values, Global Config items and tokens, a domain move-out, KMS signing, and domain transfer codes are refused; environment values, protection-bypass secrets, deploy hook URLs, drain and webhook headers, signing secrets, and destination URLs beyond their origin, external route and redirect destinations beyond their origin, the args and values of every header, cookie, and query rule (route transforms and conditions, firewall conditions), team invite codes, synced Global Config items, and URL credentials are redacted on every path; a key-name heuristic covers the rest; and secret-family failures carry fixed messages. The 0.29 ownership refusals, reconciliation tables, `vercel_api_get`, `vercel_api_mutate`, `verify_project_domain`, `remove_project_domain`, `delete_deployment`, and the no-op `defaultPageSize` option are removed. See the provider auth migration guide.
32
+
33
+ ### Security
34
+
35
+ - **Breaking:** Every key connector (Stripe, Notion, Cloudflare, Vercel) now applies one reviewed value-safety mechanism: one detector over each pinned spec (the union of the former Cloudflare and Vercel detectors), one per-vendor table of `refuse`, `redact`, and `safe` verdicts, one redaction engine on every result, and one error policy. Stripe refuses operations that hand out a credential (ephemeral keys, Terminal connection tokens and onboarding links, v1 and v2 account links, login links, account, customer, and billing portal sessions, file link creation, Financial Connections session creation, and the meter event session), refuses Issuing `number` and `cvc` expansions on every Issuing path, and redacts client secrets, webhook and event destination signing secrets, Apps secret payloads, app-install authorization codes, Terminal Wi-Fi passwords, forwarded header values, and Issuing card numbers and CVCs; webhook, file link, and pre-signed import URLs keep only their origin. Resource rules keyed on Stripe's `object` apply these wherever an object appears (expansions, lists, events and their `previous_attributes`). Identity verification URLs are unchanged; a Checkout Session's URL is returned whole only for a provably guest payment session (no `customer`, `customer_account`, customer creation, or saved payment method options) and otherwise keeps only its origin. Notion withholds the signature parameters of pre-signed file URLs and refuses its OAuth endpoints through the table. Cloudflare's review grows by 259 operations, newly redacting Hyperdrive passwords, RealtimeKit storage credentials, transform-rule header values, dispatch binding values, and webhook destinations beyond their origin. Vercel replaces environment values with `"[redacted]"` instead of dropping them, and redacts audit-event invite codes, integration drain headers, and route header values. Where the former engines differed the stricter rule holds: a credential-named field loses its whole value, and every reviewed operation (or one whose request takes a credential-named field) withholds the vendor's error text unless its review keeps it. `providers:spec` (now run under tsx) checks every reviewed path against the pinned response schema. `RestVendor.valueSafety` is required and the `redact` hook is removed; Cloudflare's generated index no longer carries `secrets`. See the provider auth migration guide.
36
+
37
+ ## 0.30.0 — 2026-10-09
38
+
39
+ Connecta 0.30.0 makes large results, sign-in and rich output dependable for agents, on both direct calls and programs. The six-tool surface from 0.29.0 stays. We measured the alternative, folding everything into `execute_code`, against it on Sonnet 5.5 and GPT-6-Luna (#765). The code-only surface scored lower and made a duplicate billable write, so it was not adopted.
40
+
41
+ Default `call_tool` and `call_destructive_tool` results now put their data in `content` and no longer send `structuredContent` or advertise `outputSchema`. Clients that prefer structured content, Claude Code among them, previously saw only a `{"format":"json"}` stub. Read the format from `_meta["dev.connecta/format"]`. For a truncated result, parse the first line of the text as a JSON notice. `resultMode: "value"` keeps the full structured envelope.
42
+
43
+ Programs no longer lose large data. A `connecta.call` result over the executor's inline cap is rebuilt from stash pages up to 1 MiB, and larger results come back as a handle for `connecta.result`. A program that returns more than 24,000 characters gets a pageable `resultId` in place of a truncated preview. If that run made a write, the notice says the write already ran. Paging checks the caller's connector grants on every page. Programs can forward images and other rich content with `connecta.emit(result)` or `result.content`, within the existing byte and block limits.
44
+
45
+ Downstream-OAuth handoff links use compact, opaque tokens that agents copy intact; links issued before the upgrade keep working until they expire. Auth failures on direct calls, program calls and catalog search now carry the sign-in link or operator instructions themselves, so agents no longer need a separate `authorize_connector` step. URL elicitation is unchanged.
46
+
47
+ Values submitted in JSON-Schema `writeOnly` argument fields are now treated like credentials. They are redacted from downstream result text, error text, program output and stored pages, with bounded work and memory. Values under 8 characters are replaced only where a structured field equals them, and prose containing them is withheld. Credential redaction of very large or deeply nested results no longer risks exhausting memory.
48
+
49
+ Custom `KVStorage` adapters must honor the new `expiresAtMs` option on `set` and `compareAndSet` and declare `capabilities: { absoluteExpiry: true }`. Construction rejects adapters without that declaration. The built-in memory, SQLite and D1 drivers already comply. Stash capacity charges now use storage time and hold until orphaned chunks expire, so a skewed or failing host can no longer over-admit stashes. The new maintained Infisical provider lets deployments manage projects, folders and secrets with machine-identity Universal Auth and no hand-written connector.
50
+
51
+ ### Added
52
+
53
+ - Add a maintained Infisical REST provider for machine-identity Universal Auth, projects, folders, and secret reads and writes. Tokens stay in memory and refresh before expiry, lists omit values by default, writes omit values and expose pending approvals, and credential-free OpenAPI checks cover every endpoint. Value-free results, including imports and approvals, return only validated identifiers and omit comments, descriptions, free-form names, reminder notes, and arbitrary nested objects. Project slugs are withheld because Infisical can derive them from free-text project names. Write recovery echoes omit secret values, secret comments, and folder descriptions without changing dispatched arguments. Comments are available only from explicit value reads. `metadataOmitted` reports withheld or unavailable metadata. This protects against careless human data entry on an honest server; adversarial encodings by a malicious server are out of scope. Known, accepted residual risk: environment slugs are returned as required routing identifiers. Infisical's UI derives them from environment names by default, so secrets entered in those names can appear in returned slugs. Operators must not put secrets in environment names or slugs. Secrets placed in identifiers or key names are out of scope. Submitted-value matching and request-secret registration are removed, preserving later program arguments and repeated writes with the same value. Rejected tokens never automatically resend writes; reconcile before an explicit retry. Existing `clientId`/`clientSecret` credentials work when the connector id is preserved. Core uncertainty and retry envelopes omit nested and composed `writeOnly` fields, withhold argument echoes when sensitivity cannot be resolved, and mark partial or withheld echoes with `argsRedacted: true`. Retry using the original arguments. Guarded base-URL validation refuses invalid configuration without quoting its value.
54
+ - Add an eval-only code arm, explicit route/outcome grading, offline baseline regrading and a paired A/B report with a pre-registered correctness and write-safety decision rule. Both agent runners assert the selected tool list; Claude also supports Haiku 5.5.
55
+ - Forward MCP rich content from programs with `connecta.emit(result)` or `result.content`, preserving native blocks and metadata within the existing paging and emission limits. Snapshot retained native blocks within byte, node, and depth limits before paging can yield so later connector mutations cannot change their content or bypass emission limits. Page oversized structured data before inspecting native presentation, and refuse cyclic or over-budget presentation without retaining it.
56
+
57
+ ### Changed
58
+
59
+ - Auth failures on direct calls, program calls, and catalog search/describe now include the authorization URL or operator credential instructions that `authorize_connector` returns. Each call or program run reuses one handoff per connector, without forcing reauthorization. Programs can read typed recovery through `error.data` as well as `error.details`; URL elicitation is unchanged.
60
+ - Separate the human product overview from agent task documentation. Route endpoint operation, deployment, integration, and repository maintenance through an agent index, preserve technical contracts and existing section links, and move the operator UI contract into its own guide.
61
+
62
+ ### Fixed
63
+
64
+ - Read Vercel's complete public MCP inventory from its linked category references, with bounded credential-free fetching and explicit unavailable findings for incomplete documentation.
65
+
66
+ Reconcile category URLs discovered across the entire index with published counts and category tool headings before comparing drift. Unrecognized formatting reports unavailable instead of silently omitting tools, and unused unrelated reference definitions do not block the inventory.
67
+
68
+ Resolve relative category destinations before requiring a count on each category link, exclude CommonMark code examples, and require the tool's known category to reconcile before reporting a removal. Disappearing categories require review, while unrelated count prose does not block the check.
69
+ - **Breaking:** Book each result stash reservation once with a finite deadline of booking time
70
+ plus a 30-second write budget plus the chunk TTL, normally 15 minutes. Stop the
71
+ write loop on timeout and return no paging ID. Absolute chunk and ledger expiry
72
+ prevents late or ambiguous writes from extending that bound. Custom KVStorage
73
+ adapters must honor the new `expiresAtMs` option on set and compareAndSet and
74
+ declare `capabilities: { absoluteExpiry: true }`; construction rejects legacy
75
+ adapters without that explicit opt-in. Rejected write responses retain the
76
+ original reservation because their dispatched operation may commit later.
77
+ Settlement and cleanup shorten or remove charges when possible; after failure
78
+ or exhausted retries, capacity may be over-held until the booked deadline.
79
+ Bound each cleanup/release or settlement path to 15 seconds, including storage
80
+ I/O, and abandon further work when its budget expires so stalled operations
81
+ cannot hang the caller after the write timeout.
82
+ Remove durable completion receipts and their recovery path.
83
+ State-file import and `migrate-state` report database failures with fixed
84
+ step descriptions, preventing SQLite trigger errors from printing imported
85
+ values (#726).
86
+ - Serve identical eval code-arm usage guidance through text, structured content, resource aliases and guest skills. Require clean matching runtime and task/harness provenance before evaluating the registered A/B decision; explicit mismatch diagnostics mark decisions NON-COMPARABLE.
87
+ - Require strict per-trial model, CLI, task and deadline provenance before the eval A/B decision. Count timeout, interruption and runner errors as failures regardless of cached status, report failure kinds per arm, and derive native code-arm skill manifests from the exact served guide bytes.
88
+ - Clarify the cross-connector join eval to select the highest-MRR customer with an open bug, and accept value-mode retained-result notices in the result-paging grader while preserving same-ID paging and single-fetch checks.
89
+ - **Breaking:** Keep default direct-call data and truncation previews visible in clients that prefer structured content. Successful `call_tool` and `call_destructive_tool` results with `resultMode` omitted or set to `"mcp"` now omit `structuredContent`, including its former `format` and paging fields. These tools also stop advertising `outputSchema`.
90
+
91
+ Migrate clients to read result data from `content` and format from `_meta["dev.connecta/format"]` instead of `structuredContent.format`. For truncated default-mode results, parse the first line of the content text as a JSON notice to read `resultId`, `nextOffset`, and `nextAction`, then page with `connecta.result`. Clients that need a structured envelope can request `resultMode: "value"` and keep reading `structuredContent.format` and the paging notice in `structuredContent.data`. Remove assumptions that either direct-call tool advertises an `outputSchema`; use content handling or the value-mode envelope instead. Value-mode and error envelopes retain their complete JSON mirrors.
92
+ - Require storage-side proof of expiry before pruning stash capacity charges, so an ahead caller clock cannot admit another stash while charged chunks remain readable.
93
+ - Make stash charge deadline tests deterministic under runner load across memory, SQLite, and D1.
94
+ - Page oversized call results inside programs through the existing result stash. Reconstruct bounded values across executors and return pageable handles for larger results, keeping completed writes successful and avoiding duplicate downstream calls. Preserve U+FEFF at result and page starts in program reconstruction and direct paging. Report unpageable oversized raw text containing unpaired UTF-16 surrogates without silently replacing its code units.
95
+ - Issue compact downstream-OAuth handoff URLs with opaque, unpadded base64url tokens so agents can copy them intact. Preserve exact signature verification, all identity and lifetime checks, and pre-upgrade links until their original expiry. Authorization guidance now tells agents to copy the URL unchanged and request a fresh link when it is invalid or expired.
96
+ - Stash oversized execute_code returns behind a pageable resultId, preserving the full redacted value without repeating completed writes. Share direct-call expiry, authority checks, page caps, and capacity limits; keep bounded truncation when paging is unavailable. Skill and catalog reads retain their grant dependencies through subsequent return stashes, including caught resolution failures and recovery metadata. Local guides follow connector visibility under exact-tool grants; downstream skills and resources retain whole-connector enforcement. Write warnings reflect only writes completed during the current run.
97
+ - Count Claude eval runner cleanup after successful conversation completion as a normal exit in paired comparisons.
98
+ Accept numeric 143 or signal SIGTERM only after successful completion and a harness SIGTERM sent before any observed child exit.
99
+
100
+ ### Security
101
+
102
+ - Redact submitted `writeOnly` argument values, including property names inside private objects and their encoded forms, from downstream results, errors, resource reads, connector usage guides, downstream skill files, program returns, logs, and emits before they reach agents, guest programs, or result paging storage. JSON results stay valid, with matching numbers and booleans replaced by a placeholder string, and nested JSON strings are decoded and checked. Short private values redact only equal structured fields and withhold prose that contains them, so identifiers and approval state remain; empty strings are exempt. Matching costs amortized constant work per scanned character regardless of how many values are registered, plus one budgeted confirmation per length where a long value's prefix appears; the matcher's memory, including at most 16 Ki runs of waiting confirmations per scanned text, is bounded across every credential and private value, and text that needs more work or runs is withheld. Redaction walks results iteratively and copies only what changes, so an oversized or deeply nested downstream result can no longer exhaust the heap or stack before paging, and one bounded work budget per redaction withholds only the affected field.
103
+
5
104
  ## 0.29.0 — 2026-10-08
6
105
 
7
106
  Connecta 0.29.0 adopts the MCP 2026-07-28 request envelope, binding client capabilities and client identity to each request. `server/discover` advertises the extensions served and private cache hints. Connecta-owned access, pool and deadline refusals return JSON-RPC errors; admission codes move to `-33001` and `-33002`. Modern clients must preserve the protocol-version and declared argument headers. `tools.listChanged` is false, and `subscriptions/listen` remains unsupported.
package/README.md CHANGED
@@ -2,149 +2,147 @@
2
2
 
3
3
  ![A monochrome clay Connecta hub joining many tools](https://raw.githubusercontent.com/zackbart/connecta/main/assets/connecta-clay-hero.png)
4
4
 
5
- One MCP endpoint. The integrations you chose. Your agent reaches them by
6
- writing code instead of loading a thousand tool definitions.
5
+ One connection between your agent and the services you choose.
6
+
7
+ Connecta brings your MCP servers and HTTP APIs together behind one endpoint.
8
+ Connect your agent once, then choose which integrations it can use. You run
9
+ Connecta yourself, on your own machine or infrastructure.
7
10
 
8
11
  ## The mental model
9
12
 
10
- You ask your agent a question that touches a service — Linear, Stripe, an
11
- internal API, anything you have connected. Here is what happens:
13
+ Ask your agent to find open issues, compare them with customer feedback, or
14
+ prepare a report. Connecta gives it a small set of tools for finding and using
15
+ the services you connected, without loading every service's tool definitions
16
+ into the conversation.
17
+
18
+ The agent writes a short program that runs in a sandbox beside those
19
+ integrations. It can gather results, combine them, and return the parts that
20
+ answer your question. Fifty issues can become a short list grouped by owner
21
+ before the result reaches the conversation. The agent writes the code; you
22
+ ask for the work.
23
+
24
+ ```mermaid
25
+ flowchart LR
26
+ Agent["Your agent"] <-->|"One connection"| Connecta["Your Connecta deployment"]
27
+ Connecta <--> Work["Work tools<br/>Linear, GitHub, Notion"]
28
+ Connecta <--> Business["Business services<br/>Stripe, RevenueCat, Mixpanel"]
29
+ Connecta <--> Yours["Your other services<br/>Remote MCP servers and HTTP APIs"]
30
+
31
+ style Connecta fill:#e0e7ff,stroke:#4338ca,color:#1e1b4b,stroke-width:2px
32
+ ```
33
+
34
+ You choose which services to connect and who can use them. Your agent keeps
35
+ the same connection as those services change.
12
36
 
13
- 1. The agent talks to one endpoint, yours, and sees six tools. Always six,
14
- no matter how many services sit behind it.
15
- 2. It writes a short JavaScript program. Connecta runs it in a sandbox next to
16
- your integrations. The program can search for tools, call them, chain the
17
- calls, and shape the result.
18
- 3. Only the answer comes back into the agent's context — not raw pages of
19
- API output.
20
- 4. If the agent wants to change something — create, update, delete — it
21
- can do that from a program in a `trusted` pool. A `read-only` pool
22
- routes each write through `call_destructive_tool`. The host controls approval; trusted endpoints annotate `execute_code` as a
23
- write. Pool trust defaults to `read-only`.
37
+ ## From a question to an answer
24
38
 
25
- Credentials never leave the server. The program never sees them, and neither
26
- does the agent.
39
+ Say you ask, "Which open issues affect our highest-value customers?" Your agent
40
+ can gather information from your issue tracker and customer records, combine
41
+ it inside Connecta, and bring back a focused answer.
27
42
 
28
43
  ```mermaid
29
44
  flowchart TB
30
- Client["Your MCP client<br/>Claude, Cursor, …"]
45
+ Question["You ask a question"] --> Plan["Your agent works out what to look up"]
46
+ Plan --> Gather["A program in Connecta gathers the relevant records"]
47
+ Gather --> Tracker["Open issues from your tracker"]
48
+ Gather --> Customers["Customer records from a connected service"]
49
+ Tracker --> Combine["The program matches, filters, and groups the results"]
50
+ Customers --> Combine
51
+ Combine --> Answer["Your agent explains the answer"]
52
+
53
+ style Combine fill:#e0e7ff,stroke:#4338ca,color:#1e1b4b,stroke-width:2px
54
+ style Answer fill:#dcfce7,stroke:#15803d,color:#14532d
55
+ ```
31
56
 
32
- subgraph Connecta["Connecta — one endpoint, six tools, your credentials"]
33
- Sandbox["execute_code<br/>the agent's program runs here<br/>reads, plus writes<br/>in trusted pools"]
34
- Explicit["call_destructive_tool<br/>one visible call per write<br/>your client can ask you first"]
35
- end
57
+ The records are an example; the available information depends on the services
58
+ and access you have configured. Processing results inside Connecta keeps the
59
+ conversation focused on the answer.
36
60
 
37
- Integrations["The integrations you chose<br/>Linear · Stripe · Notion · Vercel · your HTTP API · any MCP server"]
61
+ ## What you can do with it
38
62
 
39
- Client -->|"one connection"| Sandbox
40
- Client --> Explicit
41
- Sandbox -->|"reads"| Integrations
42
- Explicit -->|"writes"| Integrations
43
- ```
63
+ Connect hosted MCP services, add an internal HTTP API, and let the agent work
64
+ across them in one task. Changing your connected services does not require
65
+ changing the agent's connection. Your deployment decides which services and
66
+ operations each caller can reach.
67
+
68
+ Connecta includes maintained connections for <!-- providers:start -->Basecamp, Breeze ChMS, Church Community Builder, Cloudflare, GitHub, Gmail, Google Docs, Google Drive, Google Forms, Google Sheets, Google Slides, Infisical, Linear, Mixpanel, Notion, Overflow, Planning Center, RevenueCat, Stripe, Tithe.ly, and Vercel<!-- providers:end -->.
69
+ Each connection has its own setup guide.
70
+ Stripe, Notion, Cloudflare, and Vercel use their hosted MCP servers when you
71
+ sign in with OAuth, and Connecta's own API connections when you use an API key,
72
+ a Cloudflare API token or Global API Key, a Notion integration token, or a
73
+ Vercel access token. You can also
74
+ connect other remote MCP servers or define the operations you need from an
75
+ HTTP API.
76
+
77
+ Google Workspace connections use the account your deployment assigns to each
78
+ signed-in person. A Workspace administrator authorizes them for your domain.
79
+ Gmail reads mail and writes drafts, but does not send mail. Google Drive can
80
+ read, write, and share files, but does not permanently delete them. Available
81
+ operations and account access depend on the integration and your deployment.
82
+
83
+ Large results need not fill the conversation. The agent can filter and
84
+ summarize them in its program, or read a large result in smaller pieces.
85
+
86
+ ## Writes, credentials, and access
87
+
88
+ Connecta distinguishes reads from writes. By default, programs can read, and
89
+ each change uses a separate visible tool call. Your agent's host controls
90
+ whether it asks for approval. You can explicitly allow programs to make
91
+ changes too; the host then sees the program tool as a write. This choice does
92
+ not give a caller access to additional services.
44
93
 
45
- This is the kind of thing the agent writes, not you:
46
-
47
- ```js
48
- async () => {
49
- const { data: { nodes } } = await connecta.call("tracker.list_issues", { state: "started" });
50
- const byOwner = {};
51
- for (const issue of nodes) {
52
- (byOwner[issue.assignee?.name ?? "unassigned"] ??= []).push(issue.identifier);
53
- }
54
- return byOwner;
55
- }
94
+ ```mermaid
95
+ flowchart TB
96
+ Change["Your agent wants to change something"] --> Choice{"Are programs allowed<br/>to make changes?"}
97
+ Choice -->|"Default: no"| Separate["A separate visible call for each change"]
98
+ Choice -->|"Explicit choice: yes"| Program["A program that can make changes"]
99
+ Separate --> Host["Your agent's host handles approval"]
100
+ Program --> Host
101
+ Host --> Access["Connecta checks the caller's access"]
102
+ Access --> Services["The connected service receives the change"]
103
+
104
+ style Host fill:#fef3c7,stroke:#b45309,color:#78350f
105
+ style Access fill:#e0e7ff,stroke:#4338ca,color:#1e1b4b,stroke-width:2px
56
106
  ```
57
107
 
58
- Fifty issues in, one small object out. Your context window notices.
108
+ Connecta handles integration credentials on the server. Its sandbox does not
109
+ receive them. Optional encrypted storage protects saved credentials. Connections can use
110
+ shared credentials or a person's own account, with access rules set by the
111
+ deployment owner. Permission to use a connection is separate from permission
112
+ to manage its credentials.
59
113
 
60
- ## What you can do with it
114
+ People sign in through Clerk on Node or Cloudflare Access on Workers. Machine
115
+ clients use tokens issued by your Connecta deployment. A deployment can serve
116
+ several people within one tenant, each with the access you assign.
117
+
118
+ ## A place to see your connections
119
+
120
+ The optional operator UI shows connected services, available tools, access,
121
+ and configuration. Authorized people can connect accounts, manage credentials,
122
+ and issue client tokens. Optional activity history shows who called what,
123
+ when, and whether it worked, without recording arguments, results, or program
124
+ code. The UI's controls follow the signed-in person's permissions.
61
125
 
62
- - **Put every MCP server you use behind one connection.** Add or remove
63
- services in a config file; your client never changes.
64
- - **Wrap any HTTP API by hand.** A few lines per tool. No OpenAPI conversion —
65
- generated tool sprawl is the problem, not the fix.
66
- - **Use maintained connections** for <!-- providers:start -->Basecamp, Breeze ChMS, Church Community Builder, Cloudflare, GitHub, Gmail, Google Docs, Google Drive, Google Forms, Google Sheets, Google Slides, Linear, Mixpanel, Notion, Overflow, Planning Center, RevenueCat, Stripe, Tithe.ly, and Vercel<!-- providers:end -->: known endpoints, auth defaults, and
67
- vetted read/write classifications, imported one at a time.
68
- Cloudflare, Notion, and Vercel each let the deployment choose their
69
- hand-written API interface or official hosted MCP. Planning Center, Overflow,
70
- Tithe.ly, Breeze, and Church Community Builder are hand-written over their
71
- whole APIs, with every money-moving write behind approval. Gmail reads mail
72
- and writes drafts — never sends — and Google Drive reads, writes, and shares
73
- files — never deletes one for good — as each signed-in Workspace user through
74
- domain-wide delegation, with no per-user consent step; Google Docs reads and
75
- edits documents, and Google Sheets reads and writes spreadsheets, the same
76
- way. Google Slides reads, creates, edits, and comments on each user's decks the
77
- same way.
78
- Google Forms reads and edits forms and reads their responses the same way.
79
- - **Let the agent work in code.** Search, chain, filter, join, and reduce
80
- inside the sandbox instead of round-tripping every call through the model.
81
- - **Teach undeclared result shapes by using them.** Successful read-only calls
82
- retain field names and broad types in bounded runtime memory, never scalar
83
- values, so later programs can project a remote MCP result its provider never
84
- documented.
85
- - **Keep large results usable.** Oversized direct calls return a bounded
86
- preview with a handle for paging through the rest. For read-only work, the
87
- notice also points the agent to reduce or search the result inside a
88
- program. Discovery can show compact schemas, exact JSON Schema, or a
89
- TypeScript signature to read while writing JavaScript.
90
- - **Keep writes deliberate.** The registry classifies tools as reads or writes.
91
- Read-only pools route writes through `call_destructive_tool`; trusted pools
92
- let programs write and annotate `execute_code` as a write. The host controls
93
- approval. Exact deployment classification overrides beat provider review
94
- and downstream annotations.
95
- - **Run it on Node or Cloudflare Workers.** The core is shared; each deployment
96
- supplies its platform's executor and one store: a D1 database on Workers
97
- (`@zackbart/connecta/d1`), a SQLite file on Node (`@zackbart/connecta/sqlite`).
98
- The Node template also runs unchanged in Docker.
99
-
100
- Deployments explicitly compose optional features: `operatorUi()` from
101
- `@zackbart/connecta/ui`, `encryptedCredentialVault()` from `/credentials`,
102
- `activityHistory()` from `/activity`, and
103
- inbound authentication adapters from `/auth/*`. Omit a module and its implementation does no runtime work. Core
104
- keeps connector discovery, execution, invocation, and enforcement together.
105
- Both deployment shapes write configuration as `defineConfig((env) => …)`, with
106
- each optional module a type-checked expression the environment switches on.
107
- `createConnecta` validates it against one schema — an unknown option or an
108
- unusable value refuses to boot — and `connecta.describeConfig()` returns a
109
- secret-free snapshot of what the deployment runs with. With `operatorUi()` enabled,
110
- `GET /ui/api/config` returns that snapshot scoped to the caller, live connector
111
- facts, and the caller's grants and permissions. `CONNECTA_TOKEN=<bearer> connecta
112
- doctor --config --url https://connecta.example` prints only the scoped snapshot
113
- as JSON, using the same serializer. It does not run the diagnostic program.
114
-
115
- The optional UI has Overview, Connectors, Tools, Access, Activity and
116
- Config pages. Connector detail separates configuration, schemas, authentication,
117
- activity and diagnostics into tabs. Overview shows health, attention items and
118
- endpoint setup in a drawer; Config marks each snapshot value as default or
119
- configured. Catalog descriptions and schemas render as text. Activity filters
120
- stay in the URL and calls group by recorded request id. Authentication, history,
121
- and token controls use the signed-in person's existing permissions.
122
- Connector selection and access rules remain in deployment code.
123
-
124
- One deployment may serve several authenticated people inside the same tenant.
125
- Cloudflare Access supplies Worker identity; Node uses Clerk for human auth. Machine clients use connecta-issued `cta_`
126
- access tokens. Static bearer secrets are retired. Connecta owns no accounts or groups. Shared-credential administration and personal connection
127
- setup require separate explicit permissions, both denied by default. See
128
- [inbound auth](./documentation/auth.md#principals-visibility-and-operators).
129
- Clerk deployments enable `aud_claim_enabled` and use resource-bound JWT or
130
- opaque OAuth tokens by default. An explicit `allowedOAuthClientIds` list is a
131
- fallback for unbound tokens from dedicated clients. Clerk session
132
- tokens authenticate operator routes only; [Clerk auth](./documentation/auth.md#clerk-oauth-tokens-and-operator-sessions)
133
- describes endpoint audience validation and the configuration migration.
134
-
135
- Connecta is not a platform, a marketplace, a policy engine, or a multi-tenant
136
- service. The [principles](https://github.com/zackbart/connecta/blob/main/PRINCIPLES.md)
137
- state the goals and invariants; [decision records](https://github.com/zackbart/connecta/tree/main/decisions)
138
- explain past choices.
126
+ Your agent or developer changes the integrations and access rules in deployment
127
+ code. The UI helps you inspect them and manage authentication.
128
+
129
+ ## Where it runs
130
+
131
+ Run Connecta locally or on a server with Node, including in Docker, or host it
132
+ on Cloudflare Workers. Both offer the same agent tools. Running programs on
133
+ Workers requires Cloudflare's Workers Paid plan.
139
134
 
140
135
  ## Getting started
141
136
 
142
- Setup is written for an agent. Point yours at [`AGENTS.md`](https://github.com/zackbart/connecta/blob/main/AGENTS.md) and
143
- ask it to set up a Connecta deployment; the
144
- [documentation](./documentation/) covers the architecture, the six tools,
145
- code mode, and inbound auth if you want to go deeper. When upgrading an
146
- existing deployment, each [changelog](./CHANGELOG.md) release opens with what
147
- breaks and what a deployment can ignore.
137
+ Give your agent the [agent documentation](./documentation/README.md) and ask it
138
+ to set up Connecta with the integrations you want. Tell it where you want to
139
+ run it and who should have access. The setup guides cover Node, Docker, and
140
+ Cloudflare Workers, including connecting your agent client.
141
+
142
+ <a id="existing-client-tokens"></a>
143
+
144
+ For an existing deployment, ask your agent to follow the
145
+ [upgrade guidance](./documentation/deploying.md#upgrade-an-existing-deployment).
148
146
 
149
147
  ## Status
150
148
 
@@ -152,13 +150,7 @@ Built for its author's deployments first and published openly. Breaking
152
150
  changes are expected before 1.0. See the [changelog](./CHANGELOG.md) and
153
151
  [security policy](./SECURITY.md).
154
152
 
155
- ### Existing client tokens
156
-
157
- Upgrading from v0.23 does not require rotating managed `cta_…` tokens. Import
158
- `accessTokens` from `@zackbart/connecta/auth/access-tokens`, replace the old
159
- `accessTokens: true` with `accessTokens: accessTokens(storage)`, and keep the
160
- same persistent storage namespace and identity/tool/pool grant rules. Enable
161
- `identity.accessTokenManagement` only for the interactive operators who should
162
- manage tokens. Records written by v0.23 and later move with the store: a 0.28
163
- JSON state file migrates with `connecta migrate-state`, and a D1 table is
164
- read as is. See the package's `documentation/auth.md` for the migration.
153
+ The [principles](https://github.com/zackbart/connecta/blob/main/PRINCIPLES.md)
154
+ state the goals and tested rules. [Decision records](https://github.com/zackbart/connecta/tree/main/decisions)
155
+ explain past choices. [GitHub issues](https://github.com/zackbart/connecta/issues)
156
+ track planned work; a plan is not a shipped feature.
package/bin/connecta.mjs CHANGED
@@ -276,7 +276,13 @@ async function migrateState() {
276
276
  }
277
277
  const [statePath, databasePath] = args.map((arg) => resolve(process.cwd(), arg));
278
278
  const { importStateFile, openSqlite } = await import(pathToFileURL(join(packageRoot, "dist", "sqlite.js")).href);
279
- const database = openSqlite(databasePath);
279
+ let database;
280
+ try {
281
+ database = openSqlite(databasePath);
282
+ } catch {
283
+ throw new Error("State migration failed: could not open the SQLite database");
284
+ }
285
+ let closeFailed = false;
280
286
  try {
281
287
  const result = importStateFile(database, statePath);
282
288
  console.log(
@@ -284,8 +290,13 @@ async function migrateState() {
284
290
  ` (${result.kept} already present, ${result.expired} expired).`,
285
291
  );
286
292
  } finally {
287
- database.close();
293
+ try {
294
+ database.close();
295
+ } catch {
296
+ closeFailed = true;
297
+ }
288
298
  }
299
+ if (closeFailed) throw new Error("State migration failed: could not close the SQLite database");
289
300
  }
290
301
 
291
302
  try {
package/bin/version.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  // Generated from package.json by scripts/generate-version.mjs.
2
2
  // Workers-safe: no runtime filesystem read or deployment override.
3
- export const CONNECTA_VERSION = "0.29.0";
3
+ export const CONNECTA_VERSION = "0.31.0";