@zackbart/connecta 0.15.1 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +40 -20
- package/CHANGELOG.md +653 -0
- package/README.md +25 -5
- package/bin/connecta.mjs +44 -3
- package/dist/access-tokens.d.ts +0 -1
- package/dist/access-tokens.js +0 -1
- package/dist/activity.d.ts +50 -2
- package/dist/activity.js +34 -1
- package/dist/apps-shell.d.ts +0 -1
- package/dist/apps-shell.js +0 -1
- package/dist/auth/bearer.d.ts +0 -1
- package/dist/auth/bearer.js +0 -1
- package/dist/auth/clerk.d.ts +0 -1
- package/dist/auth/clerk.js +45 -9
- package/dist/auth/downstream-oauth.d.ts +0 -1
- package/dist/auth/downstream-oauth.js +0 -1
- package/dist/call-admission.d.ts +0 -1
- package/dist/call-admission.js +0 -1
- package/dist/catalog-drift.d.ts +99 -0
- package/dist/catalog-drift.js +251 -0
- package/dist/catalog-fingerprint.d.ts +0 -1
- package/dist/catalog-fingerprint.js +0 -1
- package/dist/catalog-limits.d.ts +0 -1
- package/dist/catalog-limits.js +0 -1
- package/dist/catalog-service.d.ts +0 -1
- package/dist/catalog-service.js +41 -5
- package/dist/catalog.d.ts +11 -1
- package/dist/catalog.js +20 -1
- package/dist/concurrency.d.ts +0 -1
- package/dist/concurrency.js +0 -1
- package/dist/connector-scope.d.ts +0 -1
- package/dist/connector-scope.js +0 -1
- package/dist/connectors/api.d.ts +29 -21
- package/dist/connectors/api.js +45 -19
- package/dist/connectors/guarded-fetch.d.ts +106 -0
- package/dist/connectors/guarded-fetch.js +289 -0
- package/dist/connectors/remote-mcp.d.ts +0 -1
- package/dist/connectors/remote-mcp.js +0 -1
- package/dist/credentials.d.ts +0 -1
- package/dist/credentials.js +0 -1
- package/dist/errors.d.ts +30 -3
- package/dist/errors.js +1 -1
- package/dist/execute.d.ts +0 -1
- package/dist/execute.js +0 -1
- package/dist/executor-admission.d.ts +11 -1
- package/dist/executor-admission.js +28 -1
- package/dist/executor-result.d.ts +0 -1
- package/dist/executor-result.js +0 -1
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-child.js +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -1
- package/dist/executors/quickjs-protocol.js +0 -1
- package/dist/executors/quickjs-runtime.d.ts +0 -1
- package/dist/executors/quickjs-runtime.js +0 -1
- package/dist/executors/quickjs.d.ts +0 -1
- package/dist/executors/quickjs.js +2 -1
- package/dist/favicon.d.ts +0 -1
- package/dist/favicon.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -7
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +0 -1
- package/dist/json-schema.d.ts +0 -1
- package/dist/json-schema.js +0 -1
- package/dist/mcp-result.d.ts +0 -1
- package/dist/mcp-result.js +0 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +0 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/operator-ui/generated.d.ts +2 -3
- package/dist/operator-ui/generated.js +3 -4
- package/dist/operator-ui/model.d.ts +10 -1
- package/dist/operator-ui/model.js +0 -1
- package/dist/operator-ui/view.d.ts +167 -0
- package/dist/operator-ui/view.js +270 -0
- package/dist/providers/cloudflare.d.ts +0 -1
- package/dist/providers/cloudflare.js +261 -299
- package/dist/providers/linear.d.ts +26 -5
- package/dist/providers/linear.js +32 -61
- package/dist/providers/mixpanel.d.ts +35 -4
- package/dist/providers/mixpanel.js +53 -79
- package/dist/providers/notion.d.ts +0 -1
- package/dist/providers/notion.js +87 -42
- package/dist/providers/stripe.d.ts +13 -1
- package/dist/providers/stripe.js +31 -60
- package/dist/registry.d.ts +34 -2
- package/dist/registry.js +85 -5
- package/dist/retired-toolkits.d.ts +0 -1
- package/dist/retired-toolkits.js +0 -1
- package/dist/routes/access-tokens.d.ts +0 -1
- package/dist/routes/access-tokens.js +0 -1
- package/dist/routes/activity.d.ts +0 -1
- package/dist/routes/activity.js +0 -1
- package/dist/routes/credentials.d.ts +0 -1
- package/dist/routes/credentials.js +0 -1
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +0 -1
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +0 -1
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +0 -1
- package/dist/routes/ui.d.ts +0 -1
- package/dist/routes/ui.js +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +11 -1
- package/dist/skills.d.ts +0 -1
- package/dist/skills.js +0 -1
- package/dist/storage/file.d.ts +0 -1
- package/dist/storage/file.js +0 -1
- package/dist/storage/memory.d.ts +0 -1
- package/dist/storage/memory.js +0 -1
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -1
- package/dist/tool-safety.d.ts +0 -1
- package/dist/tool-safety.js +0 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +13 -137
- package/dist/validate.d.ts +13 -15
- package/dist/validate.js +24 -11
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/documentation/architecture.md +186 -5
- package/documentation/auth.md +11 -0
- package/documentation/call-admission.md +142 -6
- package/documentation/cloudflare.md +92 -10
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +14 -14
- package/documentation/connector-guides.md +172 -5
- package/documentation/connectors.md +89 -0
- package/documentation/linear.md +20 -2
- package/documentation/mcp-ui-design.md +2 -2
- package/documentation/meta-tools.md +7 -1
- package/documentation/mixpanel.md +42 -9
- package/documentation/notion.md +23 -2
- package/documentation/operations.md +325 -5
- package/documentation/operator-ui.md +120 -5
- package/documentation/provider-audit.md +160 -0
- package/documentation/provider-conventions.md +667 -0
- package/documentation/request-admission.md +167 -5
- package/documentation/rich-output-design.md +1 -2
- package/documentation/stripe.md +15 -0
- package/documentation/upgrading.md +454 -0
- package/ethos.md +14 -9
- package/examples/worker/README.md +102 -12
- package/examples/worker/src/index.ts +46 -1
- package/examples/worker/wrangler.jsonc +14 -1
- package/package.json +10 -6
- package/templates/node/.dockerignore +10 -0
- package/templates/node/.env.example +40 -3
- package/templates/node/AGENTS.md +16 -1
- package/templates/node/Dockerfile +49 -0
- package/templates/node/README.md +117 -2
- package/templates/node/docker-compose.yml +39 -0
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +182 -0
- package/templates/node/src/index.ts +80 -4
- package/assets/connecta-clay-hero.png +0 -0
- package/dist/access-tokens.d.ts.map +0 -1
- package/dist/access-tokens.js.map +0 -1
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js.map +0 -1
- package/dist/apps-shell.d.ts.map +0 -1
- package/dist/apps-shell.js.map +0 -1
- package/dist/auth/bearer.d.ts.map +0 -1
- package/dist/auth/bearer.js.map +0 -1
- package/dist/auth/clerk.d.ts.map +0 -1
- package/dist/auth/clerk.js.map +0 -1
- package/dist/auth/downstream-oauth.d.ts.map +0 -1
- package/dist/auth/downstream-oauth.js.map +0 -1
- package/dist/call-admission.d.ts.map +0 -1
- package/dist/call-admission.js.map +0 -1
- package/dist/catalog-fingerprint.d.ts.map +0 -1
- package/dist/catalog-fingerprint.js.map +0 -1
- package/dist/catalog-limits.d.ts.map +0 -1
- package/dist/catalog-limits.js.map +0 -1
- package/dist/catalog-service.d.ts.map +0 -1
- package/dist/catalog-service.js.map +0 -1
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js.map +0 -1
- package/dist/concurrency.d.ts.map +0 -1
- package/dist/concurrency.js.map +0 -1
- package/dist/connector-scope.d.ts.map +0 -1
- package/dist/connector-scope.js.map +0 -1
- package/dist/connectors/api.d.ts.map +0 -1
- package/dist/connectors/api.js.map +0 -1
- package/dist/connectors/remote-mcp.d.ts.map +0 -1
- package/dist/connectors/remote-mcp.js.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js.map +0 -1
- package/dist/executor-admission.d.ts.map +0 -1
- package/dist/executor-admission.js.map +0 -1
- package/dist/executor-result.d.ts.map +0 -1
- package/dist/executor-result.js.map +0 -1
- package/dist/executors/quickjs-child.d.ts.map +0 -1
- package/dist/executors/quickjs-child.js.map +0 -1
- package/dist/executors/quickjs-protocol.d.ts.map +0 -1
- package/dist/executors/quickjs-protocol.js.map +0 -1
- package/dist/executors/quickjs-runtime.d.ts.map +0 -1
- package/dist/executors/quickjs-runtime.js.map +0 -1
- package/dist/executors/quickjs.d.ts.map +0 -1
- package/dist/executors/quickjs.js.map +0 -1
- package/dist/favicon.d.ts.map +0 -1
- package/dist/favicon.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js.map +0 -1
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js.map +0 -1
- package/dist/mcp-result.d.ts.map +0 -1
- package/dist/mcp-result.js.map +0 -1
- package/dist/meta-tools.d.ts.map +0 -1
- package/dist/meta-tools.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/operator-ui/generated.d.ts.map +0 -1
- package/dist/operator-ui/generated.js.map +0 -1
- package/dist/operator-ui/model.d.ts.map +0 -1
- package/dist/operator-ui/model.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/linear.d.ts.map +0 -1
- package/dist/providers/linear.js.map +0 -1
- package/dist/providers/mixpanel.d.ts.map +0 -1
- package/dist/providers/mixpanel.js.map +0 -1
- package/dist/providers/notion.d.ts.map +0 -1
- package/dist/providers/notion.js.map +0 -1
- package/dist/providers/stripe.d.ts.map +0 -1
- package/dist/providers/stripe.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/retired-toolkits.d.ts.map +0 -1
- package/dist/retired-toolkits.js.map +0 -1
- package/dist/routes/access-tokens.d.ts.map +0 -1
- package/dist/routes/access-tokens.js.map +0 -1
- package/dist/routes/activity.d.ts.map +0 -1
- package/dist/routes/activity.js.map +0 -1
- package/dist/routes/credentials.d.ts.map +0 -1
- package/dist/routes/credentials.js.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/mcp.js.map +0 -1
- package/dist/routes/oauth.d.ts.map +0 -1
- package/dist/routes/oauth.js.map +0 -1
- package/dist/routes/shared.d.ts.map +0 -1
- package/dist/routes/shared.js.map +0 -1
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/storage/file.d.ts.map +0 -1
- package/dist/storage/file.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/timeout.d.ts.map +0 -1
- package/dist/timeout.js.map +0 -1
- package/dist/tool-safety.d.ts.map +0 -1
- package/dist/tool-safety.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/examples/node/README.md +0 -52
- package/examples/node/src/index.ts +0 -71
- package/src/access-tokens.ts +0 -289
- package/src/activity.ts +0 -234
- package/src/apps-shell.ts +0 -370
- package/src/auth/bearer.ts +0 -61
- package/src/auth/clerk.ts +0 -553
- package/src/auth/downstream-oauth.ts +0 -575
- package/src/call-admission.ts +0 -521
- package/src/catalog-fingerprint.ts +0 -52
- package/src/catalog-limits.ts +0 -11
- package/src/catalog-service.ts +0 -1153
- package/src/catalog.ts +0 -790
- package/src/concurrency.ts +0 -39
- package/src/connector-scope.ts +0 -66
- package/src/connectors/api.ts +0 -159
- package/src/connectors/remote-mcp.ts +0 -1090
- package/src/credentials.ts +0 -428
- package/src/errors.ts +0 -364
- package/src/execute.ts +0 -1406
- package/src/executor-admission.ts +0 -328
- package/src/executor-result.ts +0 -107
- package/src/executors/quickjs-child.ts +0 -172
- package/src/executors/quickjs-protocol.ts +0 -99
- package/src/executors/quickjs-runtime.ts +0 -470
- package/src/executors/quickjs.ts +0 -776
- package/src/favicon.ts +0 -53
- package/src/index.ts +0 -666
- package/src/invocation.ts +0 -655
- package/src/json-schema.ts +0 -11
- package/src/mcp-result.ts +0 -43
- package/src/meta-tools.ts +0 -1607
- package/src/node.ts +0 -206
- package/src/operator-ui/browser.css +0 -423
- package/src/operator-ui/browser.ts +0 -1281
- package/src/operator-ui/generated.ts +0 -4
- package/src/operator-ui/model.ts +0 -111
- package/src/providers/cloudflare.ts +0 -3999
- package/src/providers/linear.ts +0 -302
- package/src/providers/mixpanel.ts +0 -229
- package/src/providers/notion.ts +0 -1879
- package/src/providers/stripe.ts +0 -307
- package/src/registry.ts +0 -1085
- package/src/retired-toolkits.ts +0 -14
- package/src/routes/access-tokens.ts +0 -115
- package/src/routes/activity.ts +0 -215
- package/src/routes/credentials.ts +0 -254
- package/src/routes/mcp.ts +0 -429
- package/src/routes/oauth.ts +0 -322
- package/src/routes/shared.ts +0 -247
- package/src/routes/ui.ts +0 -152
- package/src/server.ts +0 -195
- package/src/skills.ts +0 -271
- package/src/storage/file.ts +0 -123
- package/src/storage/memory.ts +0 -44
- package/src/timeout.ts +0 -84
- package/src/tool-safety.ts +0 -15
- package/src/types.ts +0 -523
- package/src/ui.ts +0 -744
- package/src/validate.ts +0 -387
- package/src/version.ts +0 -7
package/ethos.md
CHANGED
|
@@ -38,22 +38,22 @@ order, and amending it is a design decision, not a drive-by edit.
|
|
|
38
38
|
- **One fetch-native core, two runtimes.** The same code runs unchanged on
|
|
39
39
|
Cloudflare Workers and in Node — a Worker or a Docker stack, your pick. Web
|
|
40
40
|
APIs only in the core; Node touches live behind explicit subpaths.
|
|
41
|
-
- **Observable,
|
|
42
|
-
masked credentials, and payload-free activity
|
|
43
|
-
they
|
|
41
|
+
- **Observable, actionable only over authentication material.** Operator pages
|
|
42
|
+
show connector status, masked credentials, and payload-free activity — and
|
|
43
|
+
they act: rotate a credential, issue or revoke an access token, run a
|
|
44
|
+
downstream OAuth flow. Declared capability is what they cannot touch.
|
|
44
45
|
|
|
45
46
|
## What this isn't
|
|
46
47
|
|
|
47
48
|
- **Not a platform.** No runtime connector registration, no admin UI that
|
|
48
|
-
changes
|
|
49
|
+
changes declared capability, no policy engine, no approvals, no pauses.
|
|
49
50
|
- **Not a schema ingester.** No OpenAPI or GraphQL → tools. Generated tool
|
|
50
51
|
sprawl is the disease the meta-tools treat, not a feature to add.
|
|
51
52
|
- **Not multi-tenant.** No accounts dimension, no per-user credential store,
|
|
52
53
|
no org hierarchy. Two accounts on one service are two connector instances.
|
|
53
54
|
- **Not stateful.** No protocol sessions, no server push. Scope resolves per
|
|
54
55
|
request — which is also where the MCP spec itself has now arrived.
|
|
55
|
-
- **Not a nanny.** Credentials
|
|
56
|
-
connecta doesn't probe them behind your back.
|
|
56
|
+
- **Not a nanny.** Credentials fail loudly at use; connecta never probes one.
|
|
57
57
|
- **Not a promise to strangers — yet.** Built for its author's deployments
|
|
58
58
|
first, published openly. Breaking changes are cheap and the version number
|
|
59
59
|
signals change, not stability.
|
|
@@ -71,6 +71,7 @@ proposing one without a new argument is not.
|
|
|
71
71
|
| Runtime connector registration | refused | config-as-code is the security model |
|
|
72
72
|
| Prebuilt connections as the preferred authoring path | accepted | an a-la-carte provider constructor, imported and constructed in the deployment file, encodes maintained defaults for providers connecta actually uses — preferred *when maintained*, with no promise of one per provider; it returns exactly one ordinary `Connector` with no extra privileges — never a bundle, a group, a preset, or a registry — its tools are hand-written or proxied from a downstream MCP catalog, never generated from a schema document; its vetted annotations classify what the downstream leaves unannotated and otherwise preserve explicit annotations, with one fail-closed exception: a release-reviewed destructive classification outranks a contradictory downstream `readOnlyHint: true`, because Connecta has independently established that the tool mutates existing state; `remoteMcp()` and `api()` stay first-class ([#297](https://github.com/zackbart/connecta/issues/297), [#315](https://github.com/zackbart/connecta/issues/315)) |
|
|
73
73
|
| Guarded raw REST escape hatches in a prebuilt connection | accepted | a large, fast-moving provider cannot be honestly represented by a small frozen list: a GET-only tool may expose provider-relative reads, while JSON mutations and explicit-content uploads stay separate and always cross the destructive boundary; the connector owns authentication, rate limits, error mapping, URL confinement, and safe method classification, while the provider token remains the capability boundary — this is not schema ingestion, runtime connector registration, or permission widening |
|
|
74
|
+
| Hosted-provider drift detection during catalog refreshes | accepted | a vetted classification is a claim about somebody else's catalog, and an allowlist nobody can tell is stale is an allowlist that is wrong — so each maintained hosted-MCP proxy ships the tool names, classifications, and (once a release records them) schemas it reviewed, and compares them against the live listing *inside* a catalog refresh the deployment already asked for; the boundary is the piggyback itself, which is what keeps this from being proactive credential liveness wearing a new hat ([#179](https://github.com/zackbart/connecta/issues/179)): no scheduled job, no background request, no credential probe, and not one byte of network traffic that would not have happened anyway; what it produces is four counts — unclassified additions, names no longer served, explicit annotation conflicts, schema changes — on connector status, `connecta doctor`, and one payload-free activity event with nowhere to put a tool name or a schema; the two read surfaces answer for the runtime that served the refresh, because the observation is isolate-local and only the activity event is durable, and unknown tools already fail closed, so drift costs approval round trips and stale guidance rather than capability ([#343](https://github.com/zackbart/connecta/issues/343)) |
|
|
74
75
|
| Provider registry / integration marketplace | refused | prebuilt connections are imports, not listings; discovery happens in documentation, never at runtime ([#297](https://github.com/zackbart/connecta/issues/297)) |
|
|
75
76
|
| Protocol sessions & server push | refused | stateless per request |
|
|
76
77
|
| Resources & prompts aggregation | refused | tools only; connecta's own Apps shell is the one `resources/read` carve-out ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
@@ -80,9 +81,10 @@ proposing one without a new argument is not.
|
|
|
80
81
|
| Proactive credential liveness | removed | fail-at-use is enough ([#179](https://github.com/zackbart/connecta/issues/179)) |
|
|
81
82
|
| Agent credential recovery | accepted | one `auth_required` route through `authorize_connector`; only an operator handles secrets ([#192](https://github.com/zackbart/connecta/issues/192)) |
|
|
82
83
|
| Operator-issued MCP access tokens | accepted | named, revocable authentication gives header-capable clients a small alternative to OAuth; tokens identify callers but never scope tools or become operator credentials |
|
|
84
|
+
| Operator boundary reworded: authentication material, never declared capability | accepted | supersedes "observable, never administrable", which had stopped describing the surface: operator routes already rotate credentials, issue and revoke access tokens, and drive downstream OAuth, each under its own accepted row, and the owner has decided the surface stays actionable — so the boundary now says what is actually true, that operator routes may manage authentication material for capabilities declared in deployment configuration and may not change the connector set, the declared tool catalog or annotations, requested OAuth scopes, admission policy, authorization rules, or caller tool scope; the claim is deliberately about *declared* capability, and twice so, because replacing an API token with a broader-scoped one widens downstream reach and no browser page can honestly promise otherwise, and because a remote MCP server's catalog is discovered rather than declared — connecta declares the connector, its credential slot, and its admission policy, while the tools that server serves are its own answer, so storing a credential or finishing an OAuth flow can legitimately take an `mcp()` connector from no tools to N, which is discovery arriving, not an operator editing the deployment ([#338](https://github.com/zackbart/connecta/issues/338)) |
|
|
83
85
|
| Structured result surface | accepted | canonical `structuredContent` plus complete compact `content`; summary-only text is gated on host-forwarding evidence ([#191](https://github.com/zackbart/connecta/issues/191)) |
|
|
84
86
|
| Code mode (`execute_code`) | accepted | the primary read, discovery, and composition surface: smaller serialized definitions, far smaller results once composition and projection happen before the model sees them, and a cold-start model that read the interface without help ([exploration](./documentation/code-first-exploration.md), [#224](https://github.com/zackbart/connecta/issues/224)) |
|
|
85
|
-
| Code-first as the default; the eval gate retired | accepted | owner decision, 2026-07-30: one operator, no deploy-time flip; [`eval/code-first-gate`](
|
|
87
|
+
| Code-first as the default; the eval gate retired | accepted | owner decision, 2026-07-30: one operator, no deploy-time flip; [`eval/code-first-gate`](https://github.com/zackbart/connecta/blob/main/eval/code-first-gate/README.md) survives as measurement, but nothing waits on its verdict ([#222](https://github.com/zackbart/connecta/issues/222), [#224](https://github.com/zackbart/connecta/issues/224)) |
|
|
86
88
|
| Surface consolidation to seven tools | accepted | `list_connectors`, `describe_tools`, and `batch_call` fold into the program surface, deleting the routing choice between direct calls, batches, discovery, and execution; `call_tool` stays because a simple call is not cheaper through code ([#224](https://github.com/zackbart/connecta/issues/224)) |
|
|
87
89
|
| Classic (executor-free) surface | removed | supersedes its provisional retention under [#224](https://github.com/zackbart/connecta/issues/224) — an executor is mandatory, and a deployment without one refuses to boot rather than serving a fallback shape ([#273](https://github.com/zackbart/connecta/issues/273)) |
|
|
88
90
|
| Connector shortcut namespaces in programs | accepted | sugar over canonical addressing, kept but frozen — every expansion invents a collision class `<connectorId>.<toolName>` already solved ([#223](https://github.com/zackbart/connecta/issues/223)) |
|
|
@@ -132,8 +134,11 @@ Breaking one is not a bug fix — it is a design change wearing a disguise.
|
|
|
132
134
|
`node:` builtin.
|
|
133
135
|
- **The published surface is a boundary.** Heavyweight or platform-bound code
|
|
134
136
|
goes behind an optional-peer subpath, never into core.
|
|
135
|
-
- **
|
|
136
|
-
|
|
137
|
+
- **Operator routes manage authentication material, never declared
|
|
138
|
+
capability.** Authenticating a declared capability is allowed; the connector
|
|
139
|
+
set, declared catalog and annotations, OAuth scopes, admission, authorization
|
|
140
|
+
rules, and caller tool scope take a config edit. A downstream catalog is
|
|
141
|
+
discovered, not declared — remote MCP tools appear when its credential does.
|
|
137
142
|
- **Structural mistakes throw at construction.** A deployment that boots into
|
|
138
143
|
the wrong shape is worse than one that refuses to boot.
|
|
139
144
|
|
|
@@ -8,7 +8,7 @@ and requires the Workers Paid plan.
|
|
|
8
8
|
This is also the **starting template for a deployment**: a real deployment
|
|
9
9
|
should be its own repository that pins an exact `@zackbart/connecta` version and
|
|
10
10
|
owns only its connector configuration, auth policy, domain, bindings,
|
|
11
|
-
migrations, and secrets. See [
|
|
11
|
+
migrations, and secrets. See [the Cloudflare guide](../../documentation/cloudflare.md).
|
|
12
12
|
|
|
13
13
|
## Files
|
|
14
14
|
|
|
@@ -41,6 +41,7 @@ wrangler secret put SUPPORT_TOKEN # one headless client
|
|
|
41
41
|
wrangler secret put EXEC_TOKEN # another headless client
|
|
42
42
|
wrangler secret put CLERK_SECRET_KEY
|
|
43
43
|
wrangler secret put DOWNSTREAM_TOKEN
|
|
44
|
+
wrangler secret put CREDENTIAL_ENCRYPTION_KEY # base64 32-byte AES key
|
|
44
45
|
wrangler deploy
|
|
45
46
|
```
|
|
46
47
|
|
|
@@ -49,9 +50,97 @@ Enable Dynamic Client Registration on the Clerk instance (OAuth Applications →
|
|
|
49
50
|
DCR) so Claude/Cursor can self-register — full walkthrough in
|
|
50
51
|
[setting up Clerk](../../documentation/auth.md).
|
|
51
52
|
|
|
53
|
+
### Copied into its own repository
|
|
54
|
+
|
|
55
|
+
The `npm install` above is the connecta repository's, which already has every
|
|
56
|
+
dependency this file imports. A copy with its own `package.json` installs three
|
|
57
|
+
things, because two of them are not part of connecta and never install with it:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
npm install @zackbart/connecta @cloudflare/codemode @clerk/backend
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Both are optional peers of `@zackbart/connecta` — declared in its manifest,
|
|
64
|
+
never installed with it, and each carrying the range this release supports.
|
|
65
|
+
`@cloudflare/codemode` is the executor behind `execute_code`, published as
|
|
66
|
+
`^0.4.4 || ^0.5.0`: install a version inside that and npm stays quiet, install
|
|
67
|
+
one outside and npm says so at install time instead of leaving a Worker to
|
|
68
|
+
discover the skew in production ([#376](https://github.com/zackbart/connecta/issues/376)).
|
|
69
|
+
|
|
70
|
+
`@clerk/backend` is the peer behind `@zackbart/connecta/auth/clerk`, which
|
|
71
|
+
`src/index.ts` imports at the top level, so wrangler must resolve it at
|
|
72
|
+
build time. Miss it and the build stops at
|
|
73
|
+
`Could not resolve "@clerk/backend"`, which is a missing peer rather than a
|
|
74
|
+
broken example. Drop `clerkAuth` from `auth` if this deployment has no operator
|
|
75
|
+
sign-in, and the peer goes with it — but read
|
|
76
|
+
[the operator surface](#the-operator-surface) first, because a deployment
|
|
77
|
+
without it can never write a credential or issue an access token.
|
|
78
|
+
|
|
52
79
|
Then point an MCP client at `<PUBLIC_URL>/mcp`, and open `<PUBLIC_URL>/` for
|
|
53
80
|
Connections. Credentials is at `/credentials`, named MCP access tokens are at
|
|
54
|
-
`/tokens`, Activity is at `/activity`, and legacy `/ui` redirects to `/`.
|
|
81
|
+
`/tokens`, Activity is at `/activity`, and legacy `/ui` redirects to `/`. Each
|
|
82
|
+
of those three appears in the nav only when this deployment can serve it — see
|
|
83
|
+
the next section for what turns each one on.
|
|
84
|
+
|
|
85
|
+
## The operator surface
|
|
86
|
+
|
|
87
|
+
This example ships the whole operator feature set. Three quarters of it is on
|
|
88
|
+
as deployed; the fourth needs a database, so it is commented in place.
|
|
89
|
+
|
|
90
|
+
**Operator sign-in** is the `clerkAuth` entry in `src/index.ts`, alongside two
|
|
91
|
+
static bearers. The split is deliberate: a bearer is a client key that may call
|
|
92
|
+
tools and read connector status, while writing a credential or issuing an
|
|
93
|
+
access token requires an interactive Clerk identity. Narrow who that can be
|
|
94
|
+
with `allowedDomains`, or with a `gate` for anything a domain cannot express.
|
|
95
|
+
|
|
96
|
+
**The credential vault** is `credentials: { encryptionKey: … }`, backed by the
|
|
97
|
+
same KV namespace as everything else and encrypted with the
|
|
98
|
+
`CREDENTIAL_ENCRYPTION_KEY` secret before a value reaches it. Generate one with:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
node -e "console.log(crypto.randomBytes(32).toString('base64'))"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Leave the secret unset and the deployment still runs — `/credentials` stays
|
|
105
|
+
read-only and connecta says so at startup. Keep the key in Worker secrets and
|
|
106
|
+
nowhere near KV: it is the only thing that makes a copied namespace useless.
|
|
107
|
+
Rotation takes effect on the next call, with no redeploy and no liveness probe,
|
|
108
|
+
because credentials fail at use.
|
|
109
|
+
|
|
110
|
+
The vault is ready here, and the Credentials page is still hidden, because that
|
|
111
|
+
page lists connector credential slots rather than deployments. Neither
|
|
112
|
+
connector in `src/index.ts` declares one — Notion carries a deployment-owned
|
|
113
|
+
static header and echo has no secret — so nothing would be on the page. Add
|
|
114
|
+
`credential: { label: "API token" }` to an `api()` connector (the commented
|
|
115
|
+
shape on `echo` is exactly it) or use a provider connector such as `notion()`,
|
|
116
|
+
which declares its own, and Credentials appears for a signed-in operator on the
|
|
117
|
+
next load.
|
|
118
|
+
|
|
119
|
+
**Access tokens** are `accessTokens: {}`. A signed-in operator mints named,
|
|
120
|
+
revocable Bearer tokens at `/tokens` for header-capable clients that will not do
|
|
121
|
+
OAuth. Secrets are shown once and only their hashes enter KV; a lost token is
|
|
122
|
+
reissued, never recovered. Note the KV caveat above — revocation is visible
|
|
123
|
+
everywhere only as fast as the namespace converges.
|
|
124
|
+
|
|
125
|
+
**Activity** is the commented block in `src/index.ts` and the commented
|
|
126
|
+
`d1_databases` binding in `wrangler.jsonc`; the section below creates the
|
|
127
|
+
database and applies the schema.
|
|
128
|
+
|
|
129
|
+
None of these change what agents can reach. Operator routes manage the
|
|
130
|
+
authentication material behind capabilities `src/index.ts` already declares —
|
|
131
|
+
never the connector set, the tool catalog, or its annotations.
|
|
132
|
+
|
|
133
|
+
`connecta doctor` reports the same line here as for a deployment with none of
|
|
134
|
+
this on: connector count, executor, seven tools. The executor it names is this
|
|
135
|
+
one — `DynamicWorkerExecutor executed`, not the Node template's QuickJS, which
|
|
136
|
+
is what doctor used to claim everywhere
|
|
137
|
+
([#368](https://github.com/zackbart/connecta/issues/368)). It carries a bearer, and a
|
|
138
|
+
bearer learns the model-facing surface rather than the deployment's
|
|
139
|
+
configuration topology. Confirm the operator surface the way an operator will:
|
|
140
|
+
sign in at `<PUBLIC_URL>/` and check that Tokens is live. Credentials joins it
|
|
141
|
+
once a connector declares a `credential` slot, and Activity once the D1 wiring
|
|
142
|
+
below is on — the nav shows a page when the deployment can actually serve it,
|
|
143
|
+
so a missing page is the honest report that its half is still off.
|
|
55
144
|
|
|
56
145
|
## Code mode
|
|
57
146
|
|
|
@@ -64,20 +153,19 @@ The required Worker Loader binding is checked into `wrangler.jsonc`:
|
|
|
64
153
|
```
|
|
65
154
|
|
|
66
155
|
`src/index.ts` constructs `DynamicWorkerExecutor` from `env.LOADER` and serves
|
|
67
|
-
the seven-tool surface.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```sh
|
|
71
|
-
npm install @cloudflare/codemode
|
|
72
|
-
```
|
|
156
|
+
the seven-tool surface. The executor package is one of the installs a copied
|
|
157
|
+
deployment owns — see
|
|
158
|
+
[copied into its own repository](#copied-into-its-own-repository).
|
|
73
159
|
|
|
74
160
|
## Activity history (optional)
|
|
75
161
|
|
|
76
162
|
`src/d1-activity.ts` is a complete `ActivityStore` over D1 — keyset paging on
|
|
77
|
-
`(occurred_at_ms, id)` plus a batched retention pass — but
|
|
78
|
-
|
|
163
|
+
`(occurred_at_ms, id)` plus a batched retention pass — but the wiring in
|
|
164
|
+
`src/index.ts` is **commented out**, so the example deploys without a database.
|
|
165
|
+
To enable it:
|
|
79
166
|
|
|
80
|
-
1. Create the database and
|
|
167
|
+
1. Create the database and uncomment the `d1_databases` binding in
|
|
168
|
+
`wrangler.jsonc`, pasting in the id it prints:
|
|
81
169
|
|
|
82
170
|
```sh
|
|
83
171
|
wrangler d1 create connecta-activity
|
|
@@ -137,7 +225,9 @@ into `src/index.ts`**, so the example deploys without a database. To enable it:
|
|
|
137
225
|
the failure and returns the tool result unharmed — so the symptom is not an
|
|
138
226
|
error your agent sees, it is an activity log that quietly stops recording.
|
|
139
227
|
|
|
140
|
-
3.
|
|
228
|
+
3. In `src/index.ts`, uncomment the `d1ActivityStore` import, the `ACTIVITY_DB`
|
|
229
|
+
field on `Env`, and the `activity` block — the three commented fragments
|
|
230
|
+
that together read:
|
|
141
231
|
|
|
142
232
|
```ts
|
|
143
233
|
import { d1ActivityStore } from "./d1-activity.js";
|
|
@@ -6,16 +6,25 @@
|
|
|
6
6
|
* namespace. The required Worker Loader binding in wrangler.jsonc backs the
|
|
7
7
|
* seven-tool surface.
|
|
8
8
|
*
|
|
9
|
+
* The operator surface is wired here except for activity history, which needs
|
|
10
|
+
* a database this example does not create for you: sign-in, the credential
|
|
11
|
+
* vault, and access-token issuance are on, and activity is three commented
|
|
12
|
+
* lines below. README.md § "The operator surface" walks through all four.
|
|
13
|
+
*
|
|
9
14
|
* Setup (this example has no package.json of its own — it self-references the
|
|
10
15
|
* installed `@zackbart/connecta` package):
|
|
11
16
|
* 1. `npm install` in the connecta package root (../../ from here) so the
|
|
12
|
-
* package import and wrangler resolve.
|
|
17
|
+
* package import and wrangler resolve. A copy in its own repository
|
|
18
|
+
* installs `@zackbart/connecta @cloudflare/codemode @clerk/backend`
|
|
19
|
+
* instead — the last two are not part of connecta, and the Clerk import
|
|
20
|
+
* below is an optional peer wrangler resolves at build time.
|
|
13
21
|
* 2. Create a KV namespace and put its id in wrangler.jsonc under `kv_namespaces`.
|
|
14
22
|
* 3. Set secrets:
|
|
15
23
|
* wrangler secret put SUPPORT_TOKEN
|
|
16
24
|
* wrangler secret put EXEC_TOKEN
|
|
17
25
|
* wrangler secret put CLERK_SECRET_KEY
|
|
18
26
|
* wrangler secret put DOWNSTREAM_TOKEN
|
|
27
|
+
* wrangler secret put CREDENTIAL_ENCRYPTION_KEY
|
|
19
28
|
* and CLERK_PUBLISHABLE_KEY + PUBLIC_URL as plain vars in wrangler.jsonc.
|
|
20
29
|
* 4. Enable Dynamic Client Registration in the Clerk dashboard
|
|
21
30
|
* (OAuth Applications -> DCR toggle) so Claude/Cursor can self-register.
|
|
@@ -32,6 +41,8 @@ import {
|
|
|
32
41
|
} from "@zackbart/connecta";
|
|
33
42
|
import { clerkAuth } from "@zackbart/connecta/auth/clerk";
|
|
34
43
|
import { cloudflareKvStorage } from "./cloudflare-kv.js";
|
|
44
|
+
// Activity history, off by default because it needs a D1 database.
|
|
45
|
+
// import { d1ActivityStore } from "./d1-activity.js";
|
|
35
46
|
|
|
36
47
|
interface Env {
|
|
37
48
|
CONNECTA_KV: KVNamespace;
|
|
@@ -41,8 +52,16 @@ interface Env {
|
|
|
41
52
|
EXEC_TOKEN: string;
|
|
42
53
|
CLERK_PUBLISHABLE_KEY: string;
|
|
43
54
|
CLERK_SECRET_KEY: string;
|
|
55
|
+
/**
|
|
56
|
+
* Base64 32-byte AES key encrypting operator-managed credentials in KV.
|
|
57
|
+
* Unset means no vault: /credentials stays read-only and connecta says so at
|
|
58
|
+
* startup. Never put it in KV — it is what protects KV.
|
|
59
|
+
*/
|
|
60
|
+
CREDENTIAL_ENCRYPTION_KEY: string;
|
|
44
61
|
DOWNSTREAM_TOKEN: string;
|
|
45
62
|
PUBLIC_URL: string;
|
|
63
|
+
/** Uncomment with the `d1_databases` binding to enable activity history. */
|
|
64
|
+
// ACTIVITY_DB: D1Database;
|
|
46
65
|
/**
|
|
47
66
|
* Worker Loader binding (wrangler.jsonc `worker_loaders`) powering
|
|
48
67
|
* execute_code. Dynamic Workers require the Workers Paid plan.
|
|
@@ -73,9 +92,30 @@ function build(env: Env) {
|
|
|
73
92
|
// allowedDomains: ["acme.com"],
|
|
74
93
|
}),
|
|
75
94
|
],
|
|
95
|
+
// Connectors that declare a `credential` slot become editable at
|
|
96
|
+
// /credentials, encrypted with this key before anything reaches KV. A
|
|
97
|
+
// saved replacement takes effect on the next call — no redeploy, and no
|
|
98
|
+
// liveness probe: credentials fail at use.
|
|
99
|
+
//
|
|
100
|
+
// The key is the vault, not the page: /credentials is a list of connector
|
|
101
|
+
// slots, so it stays hidden until a connector declares one. Neither
|
|
102
|
+
// connector below does — Notion here carries a deployment-owned static
|
|
103
|
+
// header and echo has no secret at all — so this example ships the vault
|
|
104
|
+
// ready and the page empty. Declare a slot (see the commented shape on
|
|
105
|
+
// `echo`, or use a provider connector like `notion()`, which declares its
|
|
106
|
+
// own) and the page appears on the next load.
|
|
107
|
+
credentials: { encryptionKey: env.CREDENTIAL_ENCRYPTION_KEY },
|
|
76
108
|
// Eligible Clerk operators can create named, revocable MCP Bearer tokens
|
|
77
109
|
// at /tokens. Secrets are shown once; only their hashes enter KV.
|
|
78
110
|
accessTokens: {},
|
|
111
|
+
// Payload-free activity at /activity, off until a database exists to hold
|
|
112
|
+
// it. Uncomment the `d1_databases` binding in wrangler.jsonc, apply the
|
|
113
|
+
// schema in README.md § "Activity history", then these three lines and the
|
|
114
|
+
// import above.
|
|
115
|
+
// activity: {
|
|
116
|
+
// store: d1ActivityStore(env.ACTIVITY_DB),
|
|
117
|
+
// deploymentId: "production",
|
|
118
|
+
// },
|
|
79
119
|
connectors: [
|
|
80
120
|
remoteMcp("notion", {
|
|
81
121
|
url: "https://mcp.notion.com/mcp",
|
|
@@ -87,6 +127,11 @@ function build(env: Env) {
|
|
|
87
127
|
}),
|
|
88
128
|
api("echo", {
|
|
89
129
|
description: "Echo — text transforms",
|
|
130
|
+
// What a vault-backed connector adds — an operator edits this slot at
|
|
131
|
+
// /credentials and the handler reads it with
|
|
132
|
+
// `await ctx.credential?.get()`, so the secret never lives in source
|
|
133
|
+
// or in a Worker variable:
|
|
134
|
+
// credential: { label: "API token" },
|
|
90
135
|
tools: [
|
|
91
136
|
{
|
|
92
137
|
name: "shout",
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
"observability": { "enabled": true },
|
|
8
8
|
|
|
9
9
|
// Plain vars. Secrets (SUPPORT_TOKEN, EXEC_TOKEN, CLERK_SECRET_KEY,
|
|
10
|
-
// DOWNSTREAM_TOKEN) are set with
|
|
10
|
+
// CREDENTIAL_ENCRYPTION_KEY, DOWNSTREAM_TOKEN) are set with
|
|
11
|
+
// `wrangler secret put <NAME>`, not here.
|
|
11
12
|
"vars": {
|
|
12
13
|
"PUBLIC_URL": "https://connecta.example.workers.dev",
|
|
13
14
|
"CLERK_PUBLISHABLE_KEY": "pk_test_replace-me"
|
|
@@ -18,6 +19,18 @@
|
|
|
18
19
|
{ "binding": "CONNECTA_KV", "id": "replace-with-kv-namespace-id" }
|
|
19
20
|
],
|
|
20
21
|
|
|
22
|
+
// Activity history. Create with `wrangler d1 create connecta-activity`,
|
|
23
|
+
// paste the id, apply the schema in README.md, then uncomment the matching
|
|
24
|
+
// lines in src/index.ts. Off by default so this example deploys without a
|
|
25
|
+
// database.
|
|
26
|
+
// "d1_databases": [
|
|
27
|
+
// {
|
|
28
|
+
// "binding": "ACTIVITY_DB",
|
|
29
|
+
// "database_name": "connecta-activity",
|
|
30
|
+
// "database_id": "replace-with-d1-database-id"
|
|
31
|
+
// }
|
|
32
|
+
// ],
|
|
33
|
+
|
|
21
34
|
// Required by execute_code; Dynamic Workers use the Workers Paid plan.
|
|
22
35
|
"worker_loaders": [{ "binding": "LOADER" }]
|
|
23
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
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.",
|
|
@@ -31,10 +31,7 @@
|
|
|
31
31
|
"files": [
|
|
32
32
|
"bin",
|
|
33
33
|
"dist",
|
|
34
|
-
"src",
|
|
35
|
-
"assets",
|
|
36
34
|
"documentation",
|
|
37
|
-
"examples/node",
|
|
38
35
|
"examples/worker",
|
|
39
36
|
"templates",
|
|
40
37
|
"AGENTS.md",
|
|
@@ -49,6 +46,7 @@
|
|
|
49
46
|
"types": "./dist/index.d.ts",
|
|
50
47
|
"import": "./dist/index.js"
|
|
51
48
|
},
|
|
49
|
+
"./package.json": "./package.json",
|
|
52
50
|
"./node": {
|
|
53
51
|
"types": "./dist/node.d.ts",
|
|
54
52
|
"import": "./dist/node.js"
|
|
@@ -100,10 +98,11 @@
|
|
|
100
98
|
"check:docs": "node scripts/check-doc-links.mjs",
|
|
101
99
|
"check:lint": "oxlint -D correctness --report-unused-disable-directives .",
|
|
102
100
|
"check:unused": "knip --include dependencies,unlisted,exports,nsExports,types,nsTypes",
|
|
103
|
-
"check:examples": "tsc -p tsconfig.
|
|
101
|
+
"check:examples": "tsc -p tsconfig.template.node.json && tsc -p tsconfig.examples.worker.json",
|
|
104
102
|
"check:security": "npm audit --omit=dev --audit-level=moderate",
|
|
105
103
|
"check:package": "node scripts/check-package.mjs",
|
|
106
104
|
"load:admission": "npm run build && node scripts/admission-load.mjs",
|
|
105
|
+
"drift:check": "tsx scripts/drift-check.mjs",
|
|
107
106
|
"check": "npm run check:docs && npm run check:operator-ui && npm run check:lint && npm run check:unused && npm run typecheck && npm run test && npm run build && npm run check:examples",
|
|
108
107
|
"release:check": "npm run check && npm run check:security && npm run check:package",
|
|
109
108
|
"prepack": "npm run check",
|
|
@@ -117,19 +116,23 @@
|
|
|
117
116
|
},
|
|
118
117
|
"peerDependencies": {
|
|
119
118
|
"@clerk/backend": "^3.12.0",
|
|
119
|
+
"@cloudflare/codemode": "^0.4.4 || ^0.5.0",
|
|
120
120
|
"quickjs-emscripten": "^0.32.0"
|
|
121
121
|
},
|
|
122
122
|
"peerDependenciesMeta": {
|
|
123
123
|
"@clerk/backend": {
|
|
124
124
|
"optional": true
|
|
125
125
|
},
|
|
126
|
+
"@cloudflare/codemode": {
|
|
127
|
+
"optional": true
|
|
128
|
+
},
|
|
126
129
|
"quickjs-emscripten": {
|
|
127
130
|
"optional": true
|
|
128
131
|
}
|
|
129
132
|
},
|
|
130
133
|
"devDependencies": {
|
|
131
134
|
"@clerk/backend": "^3.12.0",
|
|
132
|
-
"@cloudflare/codemode": "^0.
|
|
135
|
+
"@cloudflare/codemode": "^0.5.0",
|
|
133
136
|
"@cloudflare/vitest-pool-workers": "^0.18.8",
|
|
134
137
|
"@cloudflare/workers-types": "^4.20250101.0 || ^5.0.0",
|
|
135
138
|
"@playwright/test": "^1.62.0",
|
|
@@ -137,6 +140,7 @@
|
|
|
137
140
|
"esbuild": "^0.28.0",
|
|
138
141
|
"knip": "^6.29.0",
|
|
139
142
|
"oxlint": "^1.76.0",
|
|
143
|
+
"preact": "^10.29.8",
|
|
140
144
|
"quickjs-emscripten": "^0.32.0",
|
|
141
145
|
"tsx": "^4.23.1",
|
|
142
146
|
"typescript": "^5.6.0",
|
|
@@ -1,5 +1,42 @@
|
|
|
1
|
-
# Required
|
|
2
|
-
|
|
1
|
+
# Required, and deliberately empty. Both Compose and src/index.ts refuse to
|
|
2
|
+
# start while it is, so a copied .env cannot become a running deployment on a
|
|
3
|
+
# placeholder printed in this template. Use a long random value and keep it out
|
|
4
|
+
# of source control:
|
|
5
|
+
# node -e "console.log(crypto.randomBytes(32).toString('base64url'))"
|
|
6
|
+
CONNECTA_TOKEN=
|
|
3
7
|
|
|
4
|
-
# Optional. Defaults to 8787.
|
|
8
|
+
# Optional. Defaults to 8787. Compose publishes this port on the host too.
|
|
5
9
|
PORT=8787
|
|
10
|
+
|
|
11
|
+
# Optional. The origin this deployment answers on, once it answers on more
|
|
12
|
+
# than this machine: downstream OAuth calls back to
|
|
13
|
+
# <PUBLIC_URL>/oauth/callback/<connectorId>. Defaults to http://localhost:<PORT>.
|
|
14
|
+
PUBLIC_URL=
|
|
15
|
+
|
|
16
|
+
# Optional. Where fileStorage keeps downstream-OAuth tokens and catalogs.
|
|
17
|
+
# Defaults to ./.connecta-state.json locally and /data/connecta-state.json in
|
|
18
|
+
# the container — keep the container path under /data so state lands on the
|
|
19
|
+
# named volume and survives a rebuild.
|
|
20
|
+
CONNECTA_STATE_FILE=
|
|
21
|
+
|
|
22
|
+
# --- Operator surface ---------------------------------------------------
|
|
23
|
+
# Each of these is read only once the matching block in src/index.ts is
|
|
24
|
+
# uncommented. Setting one on its own changes nothing.
|
|
25
|
+
|
|
26
|
+
# Operator sign-in with Clerk. Only a signed-in operator may write a credential
|
|
27
|
+
# or issue an access token; the bearer above is a client key, not an admin key.
|
|
28
|
+
# Also run `npm install @clerk/backend` — it is an optional peer.
|
|
29
|
+
CLERK_PUBLISHABLE_KEY=
|
|
30
|
+
CLERK_SECRET_KEY=
|
|
31
|
+
|
|
32
|
+
# Credential vault. Base64-encoded 32-byte AES key encrypting the values an
|
|
33
|
+
# operator saves at /credentials. Generate one with:
|
|
34
|
+
# node -e "console.log(crypto.randomBytes(32).toString('base64'))"
|
|
35
|
+
# Keep it here or in a secret store — never in the state file it protects, and
|
|
36
|
+
# never in source control. Losing it makes stored credentials unreadable.
|
|
37
|
+
CONNECTA_CREDENTIAL_KEY=
|
|
38
|
+
|
|
39
|
+
# Payload-free activity history. Defaults to ./.connecta-activity.jsonl locally
|
|
40
|
+
# and /data/connecta-activity.jsonl in the container — same reasoning as the
|
|
41
|
+
# state file: keep it under /data so history survives a rebuild.
|
|
42
|
+
CONNECTA_ACTIVITY_FILE=
|
package/templates/node/AGENTS.md
CHANGED
|
@@ -6,13 +6,28 @@ This repository is deployment configuration, not a copy of Connecta itself.
|
|
|
6
6
|
- Keep `executor: quickJsExecutor()` for the prescribed seven-tool code-first
|
|
7
7
|
surface.
|
|
8
8
|
- Keep credentials in environment variables or an external secret store.
|
|
9
|
-
Never commit `.env`, `.connecta-state.json`,
|
|
9
|
+
Never commit `.env`, `.connecta-state.json`, `.connecta-activity.jsonl`,
|
|
10
|
+
tokens, or credential values.
|
|
10
11
|
- Add application logic only inside deliberate `api()` connector handlers.
|
|
11
12
|
Do not copy or modify Connecta package internals here.
|
|
12
13
|
- Prefer `api()` when the agent must see an exact reviewed capability surface;
|
|
13
14
|
`remoteMcp()` follows the downstream server's evolving tool catalog.
|
|
15
|
+
- The operator surface — Clerk sign-in, credential vault, access tokens,
|
|
16
|
+
activity — ships as commented blocks in `src/index.ts`. Enable one by
|
|
17
|
+
uncommenting it and setting the variables it names in `.env`, never by
|
|
18
|
+
inventing a parallel configuration path. `README.md` § "Turn on the operator
|
|
19
|
+
surface" is the walkthrough; `src/file-activity.ts` is the deployment-owned
|
|
20
|
+
activity store the activity block wires.
|
|
14
21
|
- Run `npm run typecheck` after configuration changes. With the server running,
|
|
15
22
|
run `CONNECTA_TOKEN=... npm run doctor` before calling setup complete.
|
|
23
|
+
- `Dockerfile` and `docker-compose.yml` containerize *this* source; they are
|
|
24
|
+
the same deployment, not a second one. Configuration belongs in `.env` and
|
|
25
|
+
`src/index.ts`, never in a divergent container entrypoint.
|
|
26
|
+
- Moving this deployment to a newer Connecta is its own procedure, and it is
|
|
27
|
+
not a re-`init` — `connecta init` refuses to merge into an existing path on
|
|
28
|
+
purpose. Follow
|
|
29
|
+
[the upgrade guide](https://github.com/zackbart/connecta/blob/main/documentation/upgrading.md),
|
|
30
|
+
which also ships at `node_modules/@zackbart/connecta/documentation/upgrading.md`.
|
|
16
31
|
|
|
17
32
|
Do not add alternate entrypoints, policy layers, generated connector catalogs,
|
|
18
33
|
or runtime connector registration. Keep the deployment small enough to review
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# This deployment, containerized. The build context is this directory: the
|
|
2
|
+
# image installs @zackbart/connecta from the registry exactly like any other
|
|
3
|
+
# consumer, so nothing here depends on the Connecta repository.
|
|
4
|
+
#
|
|
5
|
+
# docker compose up -d --build
|
|
6
|
+
FROM node:22-slim
|
|
7
|
+
|
|
8
|
+
WORKDIR /app
|
|
9
|
+
|
|
10
|
+
# `connecta init` deliberately leaves no lockfile — it rewrites the Connecta
|
|
11
|
+
# version pin, and a lockfile shipped in the template would already disagree
|
|
12
|
+
# with it. Without one the build resolves the pin itself, which is fine but not
|
|
13
|
+
# reproducible. Run `npm install` on the host and commit the `package-lock.json`
|
|
14
|
+
# it writes: the build context then carries it and every later build takes the
|
|
15
|
+
# `npm ci` path. A lockfile written inside this layer stays inside the image.
|
|
16
|
+
# Dev dependencies stay in: tsx runs src/index.ts directly, so the deployment
|
|
17
|
+
# you review is the deployment that runs.
|
|
18
|
+
COPY package.json package-lock.json* ./
|
|
19
|
+
RUN if [ -f package-lock.json ]; then \
|
|
20
|
+
npm ci --include=dev; \
|
|
21
|
+
else \
|
|
22
|
+
npm install --include=dev --no-audit --no-fund; \
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
COPY tsconfig.json ./
|
|
26
|
+
COPY src ./src
|
|
27
|
+
|
|
28
|
+
# State lives on a mounted volume. The image owns the mount point so a fresh
|
|
29
|
+
# named volume inherits an owner the non-root user can actually write to.
|
|
30
|
+
RUN mkdir -p /data && chown -R node:node /data /app
|
|
31
|
+
USER node
|
|
32
|
+
|
|
33
|
+
ENV NODE_ENV=production
|
|
34
|
+
ENV PORT=8787
|
|
35
|
+
ENV CONNECTA_STATE_FILE=/data/connecta-state.json
|
|
36
|
+
# Read only once the activity block in src/index.ts is uncommented; defaulted
|
|
37
|
+
# here so history lands on the volume rather than inside the container layer.
|
|
38
|
+
ENV CONNECTA_ACTIVITY_FILE=/data/connecta-activity.jsonl
|
|
39
|
+
EXPOSE 8787
|
|
40
|
+
|
|
41
|
+
# /health is always open, so the probe never carries the bearer token and
|
|
42
|
+
# never leaves the container.
|
|
43
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
|
44
|
+
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||8787)+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|
45
|
+
|
|
46
|
+
# `node --import tsx` keeps Node itself in the foreground: no wrapper process
|
|
47
|
+
# swallows SIGTERM, so `docker compose down` stops the server promptly and the
|
|
48
|
+
# QuickJS children go with it.
|
|
49
|
+
CMD ["node", "--import", "tsx", "src/index.ts"]
|