@zackbart/connecta 0.34.1 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +363 -0
- package/README.md +62 -106
- package/SECURITY.md +3 -2
- package/bin/connecta.mjs +41 -16
- package/bin/version.mjs +1 -1
- package/dist/access-tokens.d.ts +2 -1
- package/dist/access-tokens.js +66 -30
- package/dist/activity.d.ts +1 -1
- package/dist/activity.js +2 -0
- package/dist/agent-config.d.ts +23 -0
- package/dist/agent-config.js +59 -0
- package/dist/agent-description.js +16 -0
- package/dist/agent-identity.js +4 -4
- package/dist/agent-observation.js +39 -0
- package/dist/auth/clerk-sdk/client.d.ts +2 -0
- package/dist/auth/clerk-sdk/generated.js +554 -563
- package/dist/auth/clerk-transport.js +70 -3
- package/dist/auth/clerk.d.ts +13 -0
- package/dist/auth/clerk.js +653 -246
- package/dist/auth/cloudflare-access.js +46 -42
- package/dist/auth/downstream-client-metadata.js +2 -2
- package/dist/auth/downstream-oauth.js +2051 -1160
- package/dist/auth/downstream-revocation.js +88 -88
- package/dist/auth/native-call.js +20 -0
- package/dist/auth/native.js +184 -0
- package/dist/auth/oauth-start-reset.js +11 -5
- package/dist/auth/oauth-token-response.js +121 -102
- package/dist/auth/oauth-v2-migration.js +97 -78
- package/dist/auth/renewable-grant.js +10 -0
- package/dist/auth/static-oauth.js +663 -271
- package/dist/auth/vercel-agent.js +266 -0
- package/dist/auth-admission.js +204 -0
- package/dist/auth-elicitation.js +350 -241
- package/dist/authorization-handoff.js +164 -90
- package/dist/call-admission-context.js +3 -10
- package/dist/call-admission.js +2 -0
- package/dist/call-classification.js +9 -0
- package/dist/call-recovery.js +32 -13
- package/dist/canonical-json.js +8 -0
- package/dist/catalog-cache.js +369 -213
- package/dist/catalog-service.js +659 -530
- package/dist/catalog.js +5 -1
- package/dist/concurrency.js +0 -25
- package/dist/config-defaults.d.ts +1 -0
- package/dist/config-defaults.js +1 -0
- package/dist/config-schema.d.ts +3 -1
- package/dist/config-schema.js +13 -3
- package/dist/config.d.ts +40 -6
- package/dist/config.js +40 -26
- package/dist/connector-caller.d.ts +4 -0
- package/dist/connector-caller.js +17 -4
- package/dist/connectors/api-connector.d.ts +12 -7
- package/dist/connectors/api-connector.js +142 -56
- package/dist/connectors/guarded-fetch.d.ts +51 -17
- package/dist/connectors/guarded-fetch.js +215 -121
- package/dist/connectors/negotiation-cache.js +20 -10
- package/dist/connectors/remote-mcp.d.ts +10 -30
- package/dist/connectors/remote-mcp.js +955 -563
- package/dist/d1.js +10 -243
- package/dist/derived-context.js +5 -0
- package/dist/describe-config.d.ts +3 -1
- package/dist/describe-config.js +2 -0
- package/dist/downstream-input.js +347 -260
- package/dist/errors.d.ts +87 -6
- package/dist/errors.js +114 -4
- package/dist/execute.js +87 -50
- package/dist/executor-admission.js +3 -0
- package/dist/executors/quickjs.js +163 -112
- package/dist/guarded-transport.js +50 -0
- package/dist/guest-runtime.js +1 -1
- package/dist/http/client.js +439 -0
- package/dist/http/errors.js +558 -0
- package/dist/http/fields.js +49 -0
- package/dist/http/hatch-paging.js +318 -0
- package/dist/http/hatch.js +1279 -0
- package/dist/http/json-schema.js +267 -0
- package/dist/http/node-transport.js +241 -0
- package/dist/http/oauth.js +162 -0
- package/dist/http/paging.js +228 -0
- package/dist/http/provider.js +221 -0
- package/dist/http/safety.js +82 -0
- package/dist/http/services.js +79 -0
- package/dist/http/tools.js +383 -0
- package/dist/http/vendor-index.js +138 -0
- package/dist/http/vendor.js +448 -0
- package/dist/http/write-request.js +66 -0
- package/dist/http-policy.d.ts +11 -0
- package/dist/http-policy.js +45 -0
- package/dist/inbound-credential.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -0
- package/dist/invocation-auth.js +30 -19
- package/dist/invocation.js +218 -85
- package/dist/mcp-result.js +0 -4
- package/dist/membership.d.ts +4 -0
- package/dist/meta-output.js +1 -1
- package/dist/meta-tools.js +531 -406
- package/dist/native-recovery.js +52 -0
- package/dist/native-tools.js +382 -0
- package/dist/node.d.ts +4 -3
- package/dist/node.js +45 -8
- package/dist/oauth-handoff.js +177 -104
- package/dist/oauth-partition.js +6 -20
- package/dist/oauth-sealing.js +6 -7
- package/dist/operation-vocabulary.js +101 -0
- package/dist/operator-record.d.ts +2 -2
- package/dist/operator-record.js +17 -4
- package/dist/operator-ui/agents.d.ts +5 -4
- package/dist/operator-ui/agents.js +17 -7
- package/dist/operator-ui/config-summary.js +5 -4
- package/dist/operator-ui/connection-map.js +7 -5
- package/dist/operator-ui/contract.d.ts +7 -3
- package/dist/operator-ui/endpoints.js +4 -13
- package/dist/operator-ui/fix-prompts.d.ts +1 -1
- package/dist/operator-ui/fix-prompts.js +0 -8
- package/dist/operator-ui/generated.js +3 -3
- package/dist/operator-ui/model.d.ts +2 -3
- package/dist/operator-ui/overview.js +5 -2
- package/dist/operator-ui/setup-commands.js +0 -4
- package/dist/operator-ui/view.d.ts +2 -25
- package/dist/operator-ui/view.js +2 -76
- package/dist/program-writes.js +47 -26
- package/dist/provider-call-facts.d.ts +115 -0
- package/dist/provider-call-facts.js +182 -0
- package/dist/provider-call.d.ts +112 -0
- package/dist/provider-call.js +271 -0
- package/dist/provider.d.ts +65 -31
- package/dist/provider.js +116 -39
- package/dist/providers/_shared/google/hatch.js +91 -0
- package/dist/providers/_shared/google/kit.js +537 -0
- package/dist/providers/_shared/google/result-size.js +15 -2
- package/dist/providers/_shared/google/service-account.d.ts +2 -1
- package/dist/providers/_shared/google/service-account.js +8 -4
- package/dist/providers/_shared/google/workspace.d.ts +6 -210
- package/dist/providers/_shared/google/workspace.js +6 -425
- package/dist/providers/_shared/rest/compact-index.js +86 -0
- package/dist/providers/_shared/rest/dispatch.js +3 -23
- package/dist/providers/_shared/rest/kit.js +546 -0
- package/dist/providers/_shared/rest/operation-index.js +230 -14
- package/dist/providers/_shared/rest/response-media.js +11 -0
- package/dist/providers/_shared/rest/tools.js +101 -78
- package/dist/providers/_shared/rest/value-safety.js +353 -195
- package/dist/providers/_shared/sensitive-fields.js +27 -0
- package/dist/providers/breeze/api.js +584 -0
- package/dist/providers/breeze/index.d.ts +1 -3
- package/dist/providers/breeze/index.js +67 -1420
- package/dist/providers/breeze/openapi.generated.js +60 -0
- package/dist/providers/breeze/skill.generated.js +2 -6
- package/dist/providers/breeze/tools.js +696 -0
- package/dist/providers/ccb/api.js +496 -0
- package/dist/providers/ccb/index.d.ts +15 -37
- package/dist/providers/ccb/index.js +77 -1702
- package/dist/providers/ccb/lib/constants.d.ts +34 -0
- package/dist/providers/ccb/lib/constants.js +74 -0
- package/dist/providers/ccb/lib/guide.js +9 -0
- package/dist/providers/ccb/lib/verdicts.js +387 -0
- package/dist/providers/ccb/openapi.generated.js +397 -0
- package/dist/providers/ccb/safety.js +295 -0
- package/dist/providers/ccb/skill.generated.js +2 -6
- package/dist/providers/ccb/tools.js +853 -0
- package/dist/providers/cloudflare/api.js +1066 -0
- package/dist/providers/cloudflare/index.d.ts +5 -22
- package/dist/providers/cloudflare/index.js +79 -197
- package/dist/providers/cloudflare/lib/config.d.ts +16 -0
- package/dist/providers/cloudflare/lib/config.js +2 -0
- package/dist/providers/cloudflare/lib/discovery.js +29 -0
- package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
- package/dist/providers/cloudflare/lib/hatch.js +103 -0
- package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
- package/dist/providers/cloudflare/lib/response-media.js +75 -0
- package/dist/providers/cloudflare/openapi.generated.js +4 -3
- package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
- package/dist/providers/cloudflare/skill.generated.js +2 -10
- package/dist/providers/cloudflare/tools.js +360 -0
- package/dist/providers/docs/api.js +51 -0
- package/dist/providers/docs/index.d.ts +1 -12
- package/dist/providers/docs/index.js +53 -1165
- package/dist/providers/docs/lib/constants.d.ts +18 -0
- package/dist/providers/docs/lib/constants.js +18 -0
- package/dist/providers/docs/lib/discovery.js +26 -0
- package/dist/providers/docs/lib/requests.js +48 -0
- package/dist/providers/docs/lib/schemas.js +168 -0
- package/dist/providers/docs/openapi.generated.js +16 -0
- package/dist/providers/docs/safety.js +54 -0
- package/dist/providers/docs/skill.generated.js +2 -6
- package/dist/providers/docs/tools.js +802 -0
- package/dist/providers/drive/api.js +177 -0
- package/dist/providers/drive/index.d.ts +1 -12
- package/dist/providers/drive/index.js +38 -1448
- package/dist/providers/drive/lib/constants.d.ts +6 -0
- package/dist/providers/drive/lib/constants.js +6 -0
- package/dist/providers/drive/lib/contracts.js +532 -0
- package/dist/providers/drive/lib/hatch.js +197 -0
- package/dist/providers/drive/openapi.generated.js +77 -0
- package/dist/providers/drive/safety.js +90 -0
- package/dist/providers/drive/skill.generated.js +2 -6
- package/dist/providers/drive/tools.js +1290 -0
- package/dist/providers/forms/api.js +71 -0
- package/dist/providers/forms/index.d.ts +1 -12
- package/dist/providers/forms/index.js +49 -1145
- package/dist/providers/forms/lib/constants.d.ts +14 -0
- package/dist/providers/forms/lib/constants.js +19 -0
- package/dist/providers/forms/lib/hatch.js +72 -0
- package/dist/providers/forms/openapi.generated.js +23 -0
- package/dist/providers/forms/safety.js +34 -0
- package/dist/providers/forms/skill.generated.js +2 -8
- package/dist/providers/forms/tools.js +1024 -0
- package/dist/providers/github/api.js +150 -0
- package/dist/providers/github/index.d.ts +4 -5
- package/dist/providers/github/index.js +30 -87
- package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
- package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
- package/dist/providers/github/lib/discovery.js +132 -0
- package/dist/providers/github/lib/operations.js +58 -0
- package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
- package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
- package/dist/providers/github/openapi.generated.js +1216 -0
- package/dist/providers/github/safety.js +216 -0
- package/dist/providers/github/skill.generated.js +2 -5
- package/dist/providers/github/tools.js +506 -0
- package/dist/providers/gmail/api.js +114 -0
- package/dist/providers/gmail/index.d.ts +1 -12
- package/dist/providers/gmail/index.js +73 -1621
- package/dist/providers/gmail/lib/constants.d.ts +13 -0
- package/dist/providers/gmail/lib/constants.js +16 -0
- package/dist/providers/gmail/lib/index.js +173 -0
- package/dist/providers/gmail/lib/schemas.js +176 -0
- package/dist/providers/gmail/lib/threading.js +120 -0
- package/dist/providers/gmail/openapi.generated.js +92 -0
- package/dist/providers/gmail/safety.js +21 -0
- package/dist/providers/gmail/skill.generated.js +2 -6
- package/dist/providers/gmail/tools.js +1435 -0
- package/dist/providers/overflow/api.js +1008 -0
- package/dist/providers/overflow/index.d.ts +1 -17
- package/dist/providers/overflow/index.js +60 -1488
- package/dist/providers/overflow/skill.generated.js +2 -5
- package/dist/providers/overflow/tools.js +873 -0
- package/dist/providers/planning-center/api.js +467 -0
- package/dist/providers/planning-center/index.d.ts +4 -35
- package/dist/providers/planning-center/index.js +69 -2445
- package/dist/providers/planning-center/lib/constants.d.ts +58 -0
- package/dist/providers/planning-center/lib/constants.js +83 -0
- package/dist/providers/planning-center/lib/discovery.js +40 -0
- package/dist/providers/planning-center/lib/guide.js +39 -0
- package/dist/providers/planning-center/lib/json-api.js +83 -0
- package/dist/providers/planning-center/lib/verdicts.js +1758 -0
- package/dist/providers/planning-center/openapi.generated.js +1764 -0
- package/dist/providers/planning-center/safety.js +188 -0
- package/dist/providers/planning-center/skill.generated.js +2 -27
- package/dist/providers/planning-center/tools.js +1010 -0
- package/dist/providers/sheets/api.js +133 -0
- package/dist/providers/sheets/index.d.ts +4 -16
- package/dist/providers/sheets/index.js +61 -1172
- package/dist/providers/sheets/lib/constants.d.ts +14 -0
- package/dist/providers/sheets/lib/constants.js +14 -0
- package/dist/providers/sheets/lib/hatch.js +163 -0
- package/dist/providers/sheets/lib/requests.js +105 -0
- package/dist/providers/sheets/lib/schemas.js +138 -0
- package/dist/providers/sheets/openapi.generated.js +30 -0
- package/dist/providers/sheets/safety.js +27 -0
- package/dist/providers/sheets/skill.generated.js +2 -7
- package/dist/providers/sheets/tools.js +734 -0
- package/dist/providers/slides/api.js +147 -0
- package/dist/providers/slides/index.d.ts +2 -10
- package/dist/providers/slides/index.js +48 -2555
- package/dist/providers/slides/lib/constants.d.ts +11 -0
- package/dist/providers/slides/lib/constants.js +11 -0
- package/dist/providers/slides/lib/requests.js +60 -0
- package/dist/providers/slides/lib/schemas.js +565 -0
- package/dist/providers/slides/openapi.generated.js +18 -0
- package/dist/providers/slides/skill.generated.js +2 -6
- package/dist/providers/slides/tools.js +1968 -0
- package/dist/providers/stripe/api.js +401 -0
- package/dist/providers/stripe/index.d.ts +5 -27
- package/dist/providers/stripe/index.js +74 -210
- package/dist/providers/stripe/lib/config.d.ts +4 -0
- package/dist/providers/stripe/lib/config.js +2 -0
- package/dist/providers/stripe/openapi.generated.js +4 -3
- package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
- package/dist/providers/stripe/skill.generated.js +2 -11
- package/dist/providers/stripe/tools.js +77 -0
- package/dist/providers/tithely/api.js +531 -0
- package/dist/providers/tithely/index.d.ts +17 -0
- package/dist/providers/tithely/index.js +86 -965
- package/dist/providers/tithely/skill.generated.js +2 -5
- package/dist/providers/tithely/tools.js +426 -0
- package/dist/providers/vercel/api.js +551 -0
- package/dist/providers/vercel/index.d.ts +9 -25
- package/dist/providers/vercel/index.js +66 -260
- package/dist/providers/vercel/lib/config.d.ts +2 -0
- package/dist/providers/vercel/lib/config.js +2 -0
- package/dist/providers/vercel/lib/index.js +117 -0
- package/dist/providers/vercel/lib/logs.js +100 -0
- package/dist/providers/vercel/lib/pin.js +270 -0
- package/dist/providers/vercel/openapi.generated.js +10 -5
- package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
- package/dist/providers/vercel/skill.generated.js +2 -7
- package/dist/providers/vercel/tools.js +642 -0
- package/dist/redaction-identity.js +47 -0
- package/dist/redaction-marker.js +125 -0
- package/dist/registry.d.ts +21 -15
- package/dist/registry.js +409 -376
- package/dist/routes/access-tokens.js +1 -1
- package/dist/routes/actor-labels.js +1 -1
- package/dist/routes/connect.js +1 -1
- package/dist/routes/dispatch.js +103 -0
- package/dist/routes/mcp.js +170 -79
- package/dist/routes/oauth.js +3 -1
- package/dist/routes/operator.js +2 -2
- package/dist/routes/shared.d.ts +5 -4
- package/dist/routes/shared.js +244 -177
- package/dist/routes/skills.js +10 -8
- package/dist/routes/ui-config.js +27 -3
- package/dist/routes/ui-data.js +21 -20
- package/dist/routes/ui.js +1 -1
- package/dist/runtime/call-admission.js +0 -26
- package/dist/runtime/call-entry.js +30 -0
- package/dist/runtime/call.js +556 -0
- package/dist/runtime/connector-scope.js +7 -0
- package/dist/runtime/credential-probe.js +34 -0
- package/dist/runtime/executor.js +40 -0
- package/dist/runtime/native-storage.js +63 -0
- package/dist/runtime/registry.js +27 -0
- package/dist/runtime/request-scope.js +72 -0
- package/dist/runtime/run.js +15 -7
- package/dist/runtime/shared-read.js +34 -5
- package/dist/runtime/storage.js +34 -21
- package/dist/sent-secrets.d.ts +194 -37
- package/dist/sent-secrets.js +1743 -340
- package/dist/server.js +5 -56
- package/dist/skills.js +322 -222
- package/dist/sqlite.js +15 -14
- package/dist/storage/d1-copy.js +255 -0
- package/dist/storage/d1-driver.js +15 -0
- package/dist/storage/keys.js +28 -0
- package/dist/storage/sql-driver.js +88 -0
- package/dist/storage/sql-native.js +544 -0
- package/dist/storage/sql-schema.d.ts +6 -0
- package/dist/storage/sql-schema.js +15 -0
- package/dist/storage/sql.d.ts +14 -20
- package/dist/storage/sql.js +29 -535
- package/dist/timeout.js +0 -26
- package/dist/tool-safety.js +20 -10
- package/dist/types.d.ts +7 -109
- package/dist/upward.js +3 -0
- package/dist/usage-guide.js +3 -1
- package/dist/validate.d.ts +4 -2
- package/dist/validate.js +86 -9
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.js +312 -292
- package/dist/workspace-subject.js +5 -1
- package/dist/write-outcome.js +454 -34
- package/documentation/README.md +27 -7
- package/documentation/architecture.md +2547 -226
- package/documentation/auth.md +821 -98
- package/documentation/code-mode.md +49 -16
- package/documentation/deploying.md +164 -20
- package/documentation/hosted-mcp-migration.md +460 -0
- package/documentation/integrating.md +129 -144
- package/documentation/meta-tools.md +409 -32
- package/documentation/operating.md +27 -3
- package/documentation/operator-tests.md +3 -0
- package/documentation/operator-ui.md +68 -45
- package/documentation/provider-auth-migration.md +16 -63
- package/documentation/provider-migration-0.29.md +10 -5
- package/documentation/provider-migration-0.35.md +975 -0
- package/documentation/providers.md +965 -0
- package/examples/worker/AGENTS.md +23 -9
- package/examples/worker/README.md +254 -135
- package/examples/worker/alchemy.run.ts +116 -0
- package/examples/worker/gitignore +10 -0
- package/examples/worker/src/connecta.config.ts +23 -21
- package/examples/worker/wrangler.jsonc +14 -5
- package/guides/connecting-agents.md +157 -0
- package/guides/how-it-works.md +156 -0
- package/guides/safety-and-trust.md +153 -0
- package/package.json +27 -46
- package/templates/node/.env.example +3 -0
- package/templates/node/README.md +22 -2
- package/templates/node/docker-compose.yml +1 -0
- package/templates/node/package.json +3 -2
- package/templates/node/src/connecta.config.ts +8 -0
- package/dist/catalog-drift.d.ts +0 -138
- package/dist/catalog-drift.js +0 -578
- package/dist/providers/_shared/request-token.js +0 -83
- package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
- package/dist/providers/_shared/rest/tools.d.ts +0 -141
- package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
- package/dist/providers/basecamp/index.d.ts +0 -45
- package/dist/providers/basecamp/index.js +0 -997
- package/dist/providers/basecamp/skill.generated.js +0 -9
- package/dist/providers/cloudflare/rest.d.ts +0 -37
- package/dist/providers/cloudflare/rest.js +0 -1097
- package/dist/providers/github/hosted.js +0 -218
- package/dist/providers/github/rest.js +0 -321
- package/dist/providers/infisical/index.d.ts +0 -7
- package/dist/providers/infisical/index.js +0 -713
- package/dist/providers/infisical/skill.generated.js +0 -8
- package/dist/providers/intercom/index.d.ts +0 -24
- package/dist/providers/intercom/index.js +0 -121
- package/dist/providers/intercom/skill.generated.js +0 -8
- package/dist/providers/linear/index.d.ts +0 -55
- package/dist/providers/linear/index.js +0 -537
- package/dist/providers/linear/skill.generated.js +0 -8
- package/dist/providers/mixpanel/index.d.ts +0 -59
- package/dist/providers/mixpanel/index.js +0 -472
- package/dist/providers/mixpanel/operations.js +0 -20
- package/dist/providers/mixpanel/rest.js +0 -603
- package/dist/providers/mixpanel/skill.generated.js +0 -10
- package/dist/providers/mixpanel/value-safety.js +0 -16
- package/dist/providers/notion/index.d.ts +0 -67
- package/dist/providers/notion/index.js +0 -368
- package/dist/providers/notion/openapi.generated.js +0 -75
- package/dist/providers/notion/rest.d.ts +0 -24
- package/dist/providers/notion/rest.js +0 -1226
- package/dist/providers/notion/skill.generated.js +0 -11
- package/dist/providers/notion/value-safety.js +0 -56
- package/dist/providers/revenuecat/index.d.ts +0 -51
- package/dist/providers/revenuecat/index.js +0 -697
- package/dist/providers/revenuecat/skill.generated.js +0 -11
- package/dist/providers/stripe/rest.d.ts +0 -14
- package/dist/providers/stripe/rest.js +0 -402
- package/dist/providers/vercel/rest.d.ts +0 -20
- package/dist/providers/vercel/rest.js +0 -1020
- package/dist/providers/wispr-flow/index.d.ts +0 -14
- package/dist/providers/wispr-flow/index.js +0 -117
- package/dist/providers/wispr-flow/skill.generated.js +0 -8
- /package/dist/providers/github/{key.js → lib/key.js} +0 -0
|
@@ -17,9 +17,11 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
|
|
|
17
17
|
refused inside connecta. Do not add JWT parsing or another identity gate.
|
|
18
18
|
Signed-in maintainers alone manage shared credentials and agent tokens; pool
|
|
19
19
|
members connect only their own accounts on personal connectors in their pools.
|
|
20
|
-
- Attach Access to the Worker itself, not only its hostname
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
- Attach Access to the Worker itself, not only its hostname: keep the
|
|
21
|
+
Worker's `access` property pointing at the Worker-level application in
|
|
22
|
+
`alchemy.run.ts`. Enable Managed OAuth on that Access application. CIMD is
|
|
23
|
+
the spec's preferred client registration; enable DCR as the fallback Access
|
|
24
|
+
currently requires.
|
|
23
25
|
- Managed OAuth's **Allowed redirect URIs** must contain all three entries
|
|
24
26
|
below. This is application configuration under
|
|
25
27
|
`oauth_configuration.dynamic_client_registration.allowed_uris`, not an
|
|
@@ -48,8 +50,20 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
|
|
|
48
50
|
refuses every write call; `false` lets them run with MCP host approval. Named
|
|
49
51
|
pools inherit it unless they set their own `readOnly`. Do not configure the
|
|
50
52
|
removed `trust`.
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
+
- Deploy only with `npx alchemy deploy --stage production` from the folder
|
|
54
|
+
holding `alchemy.run.ts`, passing the same `--stage` to every `plan`,
|
|
55
|
+
`deploy`, and `destroy`. `wrangler.jsonc` is for `wrangler dev` only; never
|
|
56
|
+
deploy with Wrangler. Change Workers, D1, Access applications, vars, and
|
|
57
|
+
secrets in `alchemy.run.ts`, not in the dashboard or with other CLIs.
|
|
58
|
+
- Declare every secret in `alchemy.run.ts` `env` with `Config.Redacted`, its
|
|
59
|
+
value supplied through the environment or an uncommitted `.env`. Each deploy
|
|
60
|
+
deletes secrets set any other way. Never commit credential values, `.env`,
|
|
61
|
+
`.alchemy/` (local state holds secret values in plaintext), Access
|
|
62
|
+
service-token secrets, or `CREDENTIAL_ENCRYPTION_KEY`. Keep the
|
|
63
|
+
`.gitignore` renamed from the example's `gitignore`; if it is missing,
|
|
64
|
+
restore it before any `git add`.
|
|
65
|
+
- Keep `Alchemy.RemovalPolicy.retain()` on the D1 database and any R2 bucket,
|
|
66
|
+
so `alchemy destroy` never deletes connecta's state.
|
|
53
67
|
- All state lives in the one D1 database bound as `CONNECTA_DB`, through
|
|
54
68
|
`d1Storage` (and `d1ActivityStore`) from `@zackbart/connecta/d1`. Do not add
|
|
55
69
|
a KV namespace, a second database, or a copied storage adapter; connecta
|
|
@@ -64,10 +78,10 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
|
|
|
64
78
|
- Prefer `api()` when the agent must see an exact reviewed capability set;
|
|
65
79
|
`remoteMcp()` follows the downstream server's evolving tool catalog.
|
|
66
80
|
- Agents (unattended clients) use `<PUBLIC_URL>/agent/<pool>` with a stored
|
|
67
|
-
`cta_` bearer as their only credential. That needs
|
|
68
|
-
application
|
|
69
|
-
|
|
70
|
-
Access"). Never bypass any other path. `/mcp` and `/mcp/<pool>` refuse `cta_`.
|
|
81
|
+
`cta_` bearer as their only credential. That needs the self-hosted Access
|
|
82
|
+
application `ConnectaAgents` in `alchemy.run.ts`, one `<host>/agent/*`
|
|
83
|
+
destination per agent hostname with a single Bypass policy, beside the
|
|
84
|
+
Worker-level application (README.md § "Let agents through Access"). Never bypass any other path. `/mcp` and `/mcp/<pool>` refuse `cta_`.
|
|
71
85
|
`connecta doctor` also reads `/health` behind Access: set
|
|
72
86
|
`CF_ACCESS_CLIENT_ID`, `CF_ACCESS_CLIENT_SECRET`, and `CONNECTA_TOKEN`
|
|
73
87
|
together, and pass `--pool ci`, a pool that lists the agent.
|
|
@@ -21,14 +21,19 @@ migrations, and secrets.
|
|
|
21
21
|
|
|
22
22
|
## Files
|
|
23
23
|
|
|
24
|
-
| File | What it is
|
|
25
|
-
| ------------------------------------------------------ |
|
|
26
|
-
| `src/index.ts` | the Worker entrypoint — starts the configuration, under 30 lines
|
|
27
|
-
| `src/connecta.config.ts` | connectors, auth, storage, and optional modules, as `defineConfig((env) => …)`
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
| File | What it is |
|
|
25
|
+
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| `src/index.ts` | the Worker entrypoint — starts the configuration, under 30 lines |
|
|
27
|
+
| `src/connecta.config.ts` | connectors, auth, storage, and optional modules, as `defineConfig((env) => …)` |
|
|
28
|
+
| `alchemy.run.ts` | the deployment: Worker, vars, secrets, D1, Worker Loader, and both Access applications |
|
|
29
|
+
| `wrangler.jsonc` | local `wrangler dev` only, with a simulated Access identity; never used to deploy |
|
|
30
|
+
| `gitignore` | the copied deployment's `.gitignore`, shipped under this name because npm strips `.gitignore` ([Copied into its own repository](#copied-into-its-own-repository)) |
|
|
31
|
+
| `scripts/copy-kv-to-d1.mjs`, `kv-to-d1.wrangler.jsonc` | one-shot copy of a 0.28 Workers KV deployment's state into D1, run once and deleted ([Upgrading from 0.28](#upgrading-from-028)) |
|
|
32
|
+
|
|
33
|
+
Construct Connecta once per isolate and pass `ctx` through to `fetch`, as the
|
|
34
|
+
example entrypoint does.
|
|
35
|
+
|
|
36
|
+
Keep `enable_request_signal` in `alchemy.run.ts` and `wrangler.jsonc`. On Workers it lets a live
|
|
32
37
|
response's client disconnect abort its request, so connecta cancels the stream
|
|
33
38
|
and returns the admission permit promptly. The total admitted-request bound in
|
|
34
39
|
`admission.requests.maxDurationMs` (default 300,000 ms) also reclaims capacity
|
|
@@ -36,6 +41,19 @@ on a later request if workerd ends one without delivering a signal or stream
|
|
|
36
41
|
cancellation. Set it above the longest authorization, tool call, and response
|
|
37
42
|
delivery your deployment expects to serve.
|
|
38
43
|
|
|
44
|
+
Keep `enable_weak_ref` in `alchemy.run.ts` and `wrangler.jsonc`. Before the
|
|
45
|
+
2025-05-05 compatibility date it exposes `FinalizationRegistry`, which lets
|
|
46
|
+
connecta eventually release an authentication slot whose work workerd cancelled
|
|
47
|
+
and which therefore can never settle
|
|
48
|
+
([Authentication capacity](../../documentation/auth.md#authentication-capacity-and-ingress-limiting)).
|
|
49
|
+
|
|
50
|
+
Keep `unhandled_rejection_after_microtask_checkpoint` in both `alchemy.run.ts`
|
|
51
|
+
and `wrangler.jsonc`: it defers unhandled-rejection reporting until the microtask
|
|
52
|
+
checkpoint finishes, avoiding false reports when a handler attaches later in the
|
|
53
|
+
same checkpoint ([Cloudflare compatibility flag](https://developers.cloudflare.com/workers/configuration/compatibility-flags/#defer-unhandled-rejection-processing-to-after-microtask-checkpoint)).
|
|
54
|
+
Existing deployments receive this behavior on their next deploy after adding the
|
|
55
|
+
flag to their stack.
|
|
56
|
+
|
|
39
57
|
Storage is `d1Storage(env.CONNECTA_DB)` from `@zackbart/connecta/d1`, and
|
|
40
58
|
activity history, when `CONNECTA_ACTIVITY` is `"on"`, is `d1ActivityStore` over
|
|
41
59
|
the same database.
|
|
@@ -43,28 +61,153 @@ See [Storage](#storage).
|
|
|
43
61
|
|
|
44
62
|
## Deploy
|
|
45
63
|
|
|
46
|
-
|
|
47
|
-
|
|
64
|
+
[Alchemy](https://alchemy.run) deploys this Worker. `alchemy.run.ts` declares
|
|
65
|
+
the Worker script and every binding, the one D1 database, the Worker Loader,
|
|
66
|
+
the vars and secrets, the Worker-level Access application with Managed OAuth,
|
|
67
|
+
and [the agent bypass](#let-agents-through-access). Each deploy reconciles all
|
|
68
|
+
of them, so change the stack and redeploy instead of editing these resources in
|
|
69
|
+
the dashboard. Install `alchemy@2.0.0-beta.83`, `effect@4.0.5`, and
|
|
70
|
+
`@effect/platform-node@4.0.5` at exact versions. Effect must be connecta's own
|
|
71
|
+
exact pin; check `npm ls effect` for one resolved copy. Alchemy's CLI needs
|
|
72
|
+
Node 24.11.1 or later, although the deployed Worker does not. Inside the connecta
|
|
73
|
+
repository these are already development dependencies; a copied deployment
|
|
74
|
+
installs them as [below](#copied-into-its-own-repository).
|
|
75
|
+
|
|
76
|
+
Before the first deploy, edit `alchemy.run.ts`:
|
|
77
|
+
|
|
78
|
+
- Replace `signIn` with the deployment's Access rule, for example
|
|
79
|
+
`{ email: "alice@example.com" }` or `{ emailDomain: "example.com" }`.
|
|
80
|
+
- Set `CONNECTA_MAINTAINERS` to the maintainers' Access user ids (`user_uuid`,
|
|
81
|
+
else email), comma-separated.
|
|
82
|
+
- Keep `name: "connecta"` on the D1 database only if no other database in the
|
|
83
|
+
account has that name: the first deploy takes over a database with the same
|
|
84
|
+
name without asking.
|
|
85
|
+
|
|
86
|
+
Give Alchemy an account API token and the two secrets through the environment
|
|
87
|
+
or a `.env` file beside `alchemy.run.ts`, which Alchemy loads by default:
|
|
48
88
|
|
|
49
89
|
```sh
|
|
50
|
-
|
|
90
|
+
CLOUDFLARE_ACCOUNT_ID=<account id>
|
|
91
|
+
CLOUDFLARE_API_TOKEN=<account API token>
|
|
92
|
+
DOWNSTREAM_TOKEN=<the example remote MCP connector's token>
|
|
93
|
+
CREDENTIAL_ENCRYPTION_KEY=<base64 32-byte AES key>
|
|
94
|
+
```
|
|
51
95
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
96
|
+
The token needs Workers Scripts Write, D1 Write, Access: Apps and Policies
|
|
97
|
+
Write, and Access: Organizations, Identity Providers, and Groups Read on the
|
|
98
|
+
account. Generate the encryption key with the command in
|
|
99
|
+
[UI and encrypted credentials](#ui-and-encrypted-credentials). Then, from the
|
|
100
|
+
folder holding `alchemy.run.ts`:
|
|
55
101
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
wrangler secret put CREDENTIAL_ENCRYPTION_KEY # base64 32-byte AES key
|
|
59
|
-
wrangler deploy
|
|
102
|
+
```sh
|
|
103
|
+
npx alchemy deploy --stage production
|
|
60
104
|
```
|
|
61
105
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
106
|
+
Pass the same `--stage` to every `deploy`, `plan`, and `destroy`. Alchemy keys
|
|
107
|
+
its state by stage and otherwise picks a per-user stage that does not own the
|
|
108
|
+
deployment's resources. `npx alchemy plan --stage production`
|
|
109
|
+
shows the changes without applying them. Code and configuration updates use
|
|
110
|
+
the same deploy command. The Worker keeps its script tag across deploys, so the
|
|
111
|
+
Worker-level Access application keeps covering it and `ctx.access` keeps
|
|
112
|
+
arriving.
|
|
113
|
+
|
|
114
|
+
`PUBLIC_URL` is `Cloudflare.Worker.URL`: the Worker's first custom domain if it
|
|
115
|
+
has one, otherwise its `workers.dev` URL. The verified deployment uses the
|
|
116
|
+
`workers.dev` URL. A custom domain, set with the Worker's `domain` property,
|
|
117
|
+
for example `domain: "connecta.example.com"`, has not been verified with
|
|
118
|
+
connecta: the agent bypass is expected to follow `PUBLIC_URL` to that hostname
|
|
119
|
+
on the next deploy, leaving `/agent/*` on the `workers.dev` hostname behind
|
|
120
|
+
Access. Before agents use a custom domain, run every check in
|
|
121
|
+
[Verify after deploying](#verify-after-deploying) against the custom hostname,
|
|
122
|
+
and confirm that `/agent/ci` on the `workers.dev` hostname now gets Access's
|
|
123
|
+
refusal.
|
|
124
|
+
|
|
125
|
+
### Secrets and state
|
|
126
|
+
|
|
127
|
+
- **Declare every secret in `alchemy.run.ts`.** Each deploy replaces the
|
|
128
|
+
Worker's whole binding set, so a secret set any other way, for example with
|
|
129
|
+
`cf workers secrets put`, is deleted by the next deploy.
|
|
130
|
+
- **Never commit `.alchemy/` or `.env`.** A copied deployment gets both in
|
|
131
|
+
`.gitignore` from the example's `gitignore` file, renamed as in
|
|
132
|
+
[Copied into its own repository](#copied-into-its-own-repository). Alchemy's
|
|
133
|
+
local state under `.alchemy/state/` records the Worker's bindings, including
|
|
134
|
+
the plaintext value of every secret such as `CREDENTIAL_ENCRYPTION_KEY`.
|
|
135
|
+
Protect it like the secrets themselves and back it up securely. Alchemy also
|
|
136
|
+
writes per-run logs under `~/.alchemy/logs/`; keep them off shared machines.
|
|
137
|
+
- Local state belongs to one machine. To deploy from CI or from several
|
|
138
|
+
machines, replace `Alchemy.localState()` with `Cloudflare.state()`. It
|
|
139
|
+
bootstraps an account-level state-store Worker backed by a Durable Object
|
|
140
|
+
that encrypts resource state at rest with a key held in the account's
|
|
141
|
+
Secrets Store. Retain that store: deleting it loses Alchemy's record of what
|
|
142
|
+
it owns. This option has not been verified with connecta; deploy it to a
|
|
143
|
+
throwaway account first and confirm `ctx.access` and D1 as described in
|
|
144
|
+
[Verify after deploying](#verify-after-deploying).
|
|
145
|
+
|
|
146
|
+
### Destroying and recovering
|
|
147
|
+
|
|
148
|
+
The D1 database is declared with `Alchemy.RemovalPolicy.retain()`. `npx alchemy
|
|
149
|
+
destroy --stage production` deletes the Worker and both Access applications
|
|
150
|
+
but only forgets the database, so its grants, sealed credentials, tokens, and
|
|
151
|
+
activity remain. The next deploy adopts it again by name, with its data. Delete
|
|
152
|
+
a retained database deliberately, after a backup, with
|
|
153
|
+
`cf d1 delete <database-id>`. Keep the policy on any R2 bucket you add for the
|
|
154
|
+
same reason.
|
|
155
|
+
|
|
156
|
+
If local state is lost, the next deploy adopts the database by name and reuses
|
|
157
|
+
the Worker and its script tag through Alchemy's ownership tags, but cannot find
|
|
158
|
+
either Access application. Set `applicationId` on each
|
|
159
|
+
`Cloudflare.Access.Application` to its existing id (listed with
|
|
160
|
+
`cf zero-trust access applications list`) and deploy. That takes the
|
|
161
|
+
application over and keeps its AUD; a new application would change the AUD,
|
|
162
|
+
and Cloudflare refuses a second application for the Worker destination. Then
|
|
163
|
+
remove both `applicationId` values and deploy again; that updates the
|
|
164
|
+
applications in place.
|
|
165
|
+
|
|
166
|
+
### Verify after deploying
|
|
167
|
+
|
|
168
|
+
Access changes take time to settle at the edge. Repeat these checks until they
|
|
169
|
+
agree for several consecutive rounds:
|
|
170
|
+
|
|
171
|
+
- `/mcp` and `/` without credentials get Access's refusal. With Managed OAuth
|
|
172
|
+
that is a 401 whose `WWW-Authenticate` names `realm="OAuth"` and whose body
|
|
173
|
+
is `{"error":"invalid_token",…}`.
|
|
174
|
+
- `/agent/ci` without credentials reaches connecta: its 401 carries a bare
|
|
175
|
+
`WWW-Authenticate: Bearer` and the body `{"error":{"code":"host_auth_required",…}}`.
|
|
176
|
+
- With Access service-token headers, `/health` returns 200 and `/ui/api/config`
|
|
177
|
+
returns 403 `Cloudflare Access human identity required`. That 403 shows the
|
|
178
|
+
Worker received `ctx.access`; a 401 there means it did not.
|
|
179
|
+
|
|
180
|
+
Service-token checks and `connecta doctor` need a service token that the
|
|
181
|
+
Worker-level application admits. Create one with
|
|
182
|
+
`cf zero-trust access service-tokens create`, keep its client secret out of
|
|
183
|
+
the repository, and add its id to `ConnectaAccess` as a second policy, as the
|
|
184
|
+
comment in `alchemy.run.ts` shows. connecta still refuses that service
|
|
185
|
+
identity on every MCP and operator route.
|
|
186
|
+
|
|
187
|
+
Then sign in as a maintainer, issue the `ci` token, and run
|
|
188
|
+
[`connecta doctor`](#client-authentication-and-activity).
|
|
189
|
+
|
|
190
|
+
### Local development
|
|
191
|
+
|
|
192
|
+
`wrangler.jsonc` exists only for `wrangler dev`, which runs the Worker locally
|
|
193
|
+
with local D1 and needs no Cloudflare login. Its `access.dev` block gives every
|
|
194
|
+
local request a simulated operator identity; it requires Wrangler 4.123.0 or
|
|
195
|
+
later, and earlier versions ignore it with an unexpected-field warning. Remove
|
|
196
|
+
the block to test the missing-Access refusal. Keep its vars, compatibility
|
|
197
|
+
flags, and bindings in step with `alchemy.run.ts`, and never deploy with it:
|
|
198
|
+
a Wrangler deploy would leave Alchemy's state behind, and Alchemy would replace
|
|
199
|
+
it on the next deploy. `alchemy dev` does not supply `ctx.access` to this
|
|
200
|
+
Worker, so every request is refused there.
|
|
201
|
+
|
|
202
|
+
### Cloudflare Access
|
|
203
|
+
|
|
204
|
+
`ConnectaAccess` in `alchemy.run.ts` is attached to the Worker itself through
|
|
205
|
+
the Worker's `access` property: Alchemy adds the Worker's `worker` destination,
|
|
206
|
+
plus a `preview_worker` destination covering version preview URLs. Only that
|
|
207
|
+
attachment makes Access supply `ctx.access`; a hostname application does not.
|
|
208
|
+
Its policy, `signIn`, decides who may sign in. **Managed OAuth** is enabled for
|
|
209
|
+
interactive MCP clients, with Dynamic Client Registration and these three
|
|
210
|
+
**Allowed redirect URIs**:
|
|
68
211
|
|
|
69
212
|
```text
|
|
70
213
|
https://claude.ai/api/mcp/auth_callback
|
|
@@ -89,7 +232,8 @@ an agent: it uses `/agent/<pool>` with a stored `cta_` bearer as its only
|
|
|
89
232
|
credential, once [the agent bypass](#let-agents-through-access) exists. An
|
|
90
233
|
Access service identity alone is refused. See [Machine tokens](#machine-tokens).
|
|
91
234
|
|
|
92
|
-
|
|
235
|
+
In the stack these are `oauthConfiguration.dynamicClientRegistration.allowedUris`.
|
|
236
|
+
Through the Access API, the relevant part of the application is:
|
|
93
237
|
|
|
94
238
|
```json
|
|
95
239
|
{
|
|
@@ -108,7 +252,7 @@ Through the API, the relevant part of the application is:
|
|
|
108
252
|
```
|
|
109
253
|
|
|
110
254
|
Cloudflare's [Worker Access guide](https://developers.cloudflare.com/workers/configuration/cloudflare-access/)
|
|
111
|
-
|
|
255
|
+
explains the Worker destination; its [Managed OAuth guide](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/managed-oauth/)
|
|
112
256
|
owns client registration, redirect allowlists, and token lifetimes.
|
|
113
257
|
|
|
114
258
|
[`AGENTS.md`](./AGENTS.md) repeats the callback invariant for coding agents
|
|
@@ -117,11 +261,13 @@ the Access policy or application.
|
|
|
117
261
|
|
|
118
262
|
### Let agents through Access
|
|
119
263
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
other path.
|
|
264
|
+
`ConnectaAgents` in `alchemy.run.ts` is a second self-hosted Access
|
|
265
|
+
application whose destination is `<PUBLIC_URL host>/agent/*`, with a single
|
|
266
|
+
policy whose action is **Bypass** and whose include rule is **Everyone**. The
|
|
267
|
+
Worker-level application still protects every other path. Never bypass any
|
|
268
|
+
other path. To serve agents on another hostname too, add a destination for it,
|
|
269
|
+
for example `{ type: "public", uri: "agents.example.com/agent/*" }`. Through the
|
|
270
|
+
Access API, the application is:
|
|
125
271
|
|
|
126
272
|
```json
|
|
127
273
|
{
|
|
@@ -135,116 +281,86 @@ other path. Through the API:
|
|
|
135
281
|
It must be a hostname-and-path (`public`) destination: a second Worker
|
|
136
282
|
destination is refused because the Worker-level application owns it. Changes
|
|
137
283
|
took 15–19 seconds to settle when probed, occasionally longer, with transient
|
|
138
|
-
edge errors meanwhile. Do not rely on a fixed wait
|
|
139
|
-
|
|
140
|
-
`/mcp` still returns Access's refusal, several times in a row. Connecta ignores Access
|
|
284
|
+
edge errors meanwhile. Do not rely on a fixed wait; repeat
|
|
285
|
+
[Verify after deploying](#verify-after-deploying). Connecta ignores Access
|
|
141
286
|
context on `/agent/*` and refuses every other spelling of that namespace before
|
|
142
287
|
auth. [Deploying Connecta](https://github.com/zackbart/connecta/blob/main/documentation/deploying.md#agent-endpoints-behind-cloudflare-access)
|
|
143
288
|
records the untested cases and the propagation details.
|
|
144
289
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
290
|
+
### Moving a Wrangler-deployed Worker to Alchemy
|
|
291
|
+
|
|
292
|
+
A deployment first deployed with `wrangler deploy` already owns a Worker, a D1
|
|
293
|
+
database, and Access applications that Alchemy did not create. Take them over
|
|
294
|
+
once, in a quiet period, so the Worker keeps its script tag and the Access
|
|
295
|
+
applications keep their AUD and Managed OAuth client registrations:
|
|
296
|
+
|
|
297
|
+
1. Set `name` on the Worker and the D1 database to their existing names. The
|
|
298
|
+
database is adopted by name without further changes.
|
|
299
|
+
2. Wrap the Worker in `.pipe(Alchemy.AdoptPolicy.adopt(true))`, which permits
|
|
300
|
+
taking over a Worker without Alchemy's ownership tags.
|
|
301
|
+
3. Set `applicationId` on `ConnectaAccess` and `ConnectaAgents` to the existing
|
|
302
|
+
Worker-level and `/agent/*` application ids
|
|
303
|
+
(`cf zero-trust access applications list`).
|
|
304
|
+
4. Declare every existing secret and var in `env`, with the same values. The
|
|
305
|
+
first Alchemy deploy deletes any binding the stack does not declare.
|
|
306
|
+
5. Run `npx alchemy plan --stage production`, compare it with the live
|
|
307
|
+
resources, then deploy and repeat
|
|
308
|
+
[Verify after deploying](#verify-after-deploying).
|
|
309
|
+
6. Remove the `adopt(true)` pipe and both `applicationId` values afterwards;
|
|
310
|
+
the state now records them.
|
|
311
|
+
|
|
312
|
+
Adopting D1 by name and taking Access applications over by `applicationId`
|
|
313
|
+
were verified on throwaway deployments; taking over a Worker that lacks
|
|
314
|
+
Alchemy's ownership tags was checked against Alchemy's source only. Back up D1
|
|
315
|
+
first with a D1 export.
|
|
149
316
|
|
|
150
|
-
###
|
|
317
|
+
### Copied into its own repository
|
|
151
318
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
319
|
+
Inside the connecta repository, `pnpm install` at the root provides every
|
|
320
|
+
dependency this example imports, and `npx alchemy` run from `examples/worker`
|
|
321
|
+
resolves the root's Alchemy. A separate deployment starts from the example in
|
|
322
|
+
the published package. npm strips `.gitignore` files from packages, so the
|
|
323
|
+
example ships its ignore rules as `gitignore`; rename it before the first
|
|
324
|
+
`git add`, or `.alchemy/` local state with plaintext secret values, `.env`, and
|
|
325
|
+
`.dev.vars` are committed:
|
|
159
326
|
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
export default Alchemy.Stack(
|
|
170
|
-
"ConnectaResources",
|
|
171
|
-
{ providers: Cloudflare.providers(), state: Cloudflare.state() },
|
|
172
|
-
Effect.gen(function* () {
|
|
173
|
-
const database = yield* Cloudflare.D1.Database("ConnectaDB", {
|
|
174
|
-
name: "connecta",
|
|
175
|
-
}).pipe(adopt(true));
|
|
176
|
-
const access = yield* Cloudflare.Access.Application("ConnectaAccess", {
|
|
177
|
-
type: "self_hosted",
|
|
178
|
-
name: "Connecta",
|
|
179
|
-
destinations: [{ type: "worker", workerId }],
|
|
180
|
-
policies: [{ decision: "allow", include: [{ emailDomain: "example.com" }] }],
|
|
181
|
-
oauthConfiguration: {
|
|
182
|
-
enabled: true,
|
|
183
|
-
dynamicClientRegistration: {
|
|
184
|
-
enabled: true,
|
|
185
|
-
allowedUris: [
|
|
186
|
-
"https://claude.ai/api/mcp/auth_callback",
|
|
187
|
-
"https://chatgpt.com/connector_platform_oauth_redirect",
|
|
188
|
-
"https://chatgpt.com/connector/oauth/*",
|
|
189
|
-
],
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
}).pipe(adopt(true));
|
|
193
|
-
return { databaseId: database.databaseId,
|
|
194
|
-
accessId: access.applicationId };
|
|
195
|
-
}),
|
|
196
|
-
);
|
|
327
|
+
```sh
|
|
328
|
+
npm pack @zackbart/connecta@<version>
|
|
329
|
+
mkdir connecta-worker
|
|
330
|
+
tar -xzf zackbart-connecta-<version>.tgz -C connecta-worker --strip-components=3 package/examples/worker
|
|
331
|
+
rm zackbart-connecta-<version>.tgz
|
|
332
|
+
cd connecta-worker
|
|
333
|
+
mv gitignore .gitignore
|
|
334
|
+
git init
|
|
197
335
|
```
|
|
198
336
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
application, set secrets with `wrangler secret put`, and deploy with Wrangler.
|
|
204
|
-
After the initial `wrangler deploy`, use `wrangler versions upload` and
|
|
205
|
-
`wrangler versions deploy` for code updates.
|
|
206
|
-
|
|
207
|
-
The `adopt(true)` calls explicitly permit taking over matching existing
|
|
208
|
-
resources; compare their live names, IDs, Access policy, and data before the
|
|
209
|
-
first Alchemy deploy. Remove adoption where a resource is new. The stack
|
|
210
|
-
configures no `migrations`: connecta creates its tables on first use. Remote
|
|
211
|
-
`Cloudflare.state()` bootstraps an account-level state-store Worker backed by a
|
|
212
|
-
Durable Object and Secrets Store entries for its credentials. Retain them:
|
|
213
|
-
deleting the state store loses Alchemy's record of what it owns.
|
|
214
|
-
|
|
215
|
-
Verification for this optional path stops at the API and types. The 0.28
|
|
216
|
-
form of this snippet (a KV namespace and two D1 databases with `migrations`)
|
|
217
|
-
was copied to an isolated `alchemy.run.ts` and passed `tsc --noEmit` with
|
|
218
|
-
TypeScript 5.9.3, Alchemy 2.0.0-beta.79, and Effect 4.0.0, with `npm ls
|
|
219
|
-
effect` confirming one resolved copy; this form only removes resources and the
|
|
220
|
-
optional `migrations` field. No Alchemy deploy or adoption was run.
|
|
221
|
-
[Alchemy's Worker resource](https://alchemy.run/cloudflare/compute/workers/)
|
|
222
|
-
can declare `WorkerLoader`, domains, Browser Rendering, and cron wiring, but
|
|
223
|
-
those properties are coupled to its script deploy. Its current full deploy
|
|
224
|
-
still uses the script-upload endpoint; only a conditional gradual rollout uses
|
|
225
|
-
the versions API. A previous full deploy through that endpoint did not provide
|
|
226
|
-
`ctx.access`, so do not transfer Worker ownership until that path is verified
|
|
227
|
-
end to end. The [Access](https://alchemy.run/cloudflare/security/access/),
|
|
228
|
-
[D1](https://alchemy.run/cloudflare/data/d1/), and
|
|
229
|
-
[state-store](https://alchemy.run/state-store/) guides describe the resources
|
|
230
|
-
above; the typecheck does not prove Cloudflare will accept this particular
|
|
231
|
-
Access adoption or preserve production identity.
|
|
232
|
-
|
|
233
|
-
### Copied into its own repository
|
|
234
|
-
|
|
235
|
-
The `pnpm install` above is the connecta repository's, which already has every
|
|
236
|
-
dependency this file imports. A copy with its own `package.json` installs
|
|
237
|
-
Connecta and the separately installed `@cloudflare/codemode` peer:
|
|
337
|
+
The renamed `.gitignore` excludes `.alchemy/`, `.env` and `.env.*`, `.dev.vars`
|
|
338
|
+
and `.dev.vars.*`, `.wrangler/`, and `node_modules/`; add any other local
|
|
339
|
+
secret file to it. Then install Connecta, the separately installed
|
|
340
|
+
`@cloudflare/codemode` peer, and the deployment tooling:
|
|
238
341
|
|
|
239
342
|
```sh
|
|
240
343
|
npm install --save-exact @zackbart/connecta@<version>
|
|
241
344
|
npm install @cloudflare/codemode
|
|
345
|
+
npm install --save-dev --save-exact alchemy@2.0.0-beta.83 effect@4.0.5 @effect/platform-node@4.0.5
|
|
242
346
|
npm install --save-dev wrangler @cloudflare/workers-types typescript @types/node
|
|
347
|
+
npm ls effect # one resolved copy
|
|
243
348
|
```
|
|
244
349
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
`
|
|
350
|
+
The deployment tooling runs on the operator's machine with the account API
|
|
351
|
+
token; none of it is bundled into the Worker. Connecta's own dependency audit
|
|
352
|
+
checks only what the published package installs for a deployment (`--prod`),
|
|
353
|
+
so it says nothing about this tooling, and `alchemy@2.0.0-beta.83` pulls in
|
|
354
|
+
local tooling (dev servers, bundlers, a local database) with published
|
|
355
|
+
advisories, some rated high. Run `npm audit` in the deployment and review what
|
|
356
|
+
it reports, run Alchemy and Wrangler only on a trusted machine, keep
|
|
357
|
+
`alchemy dev` and `wrangler dev` bound to localhost, and give the API token
|
|
358
|
+
only the four permissions in [Deploy](#deploy) and a short expiry.
|
|
359
|
+
|
|
360
|
+
`wrangler` serves only `wrangler dev` and `scripts/copy-kv-to-d1.mjs`. A
|
|
361
|
+
`tsconfig.json` like the following lets `tsc --noEmit`
|
|
362
|
+
resolve `D1Database`, `WorkerLoader`, and `ExecutionContext`, and checks the
|
|
363
|
+
stack:
|
|
248
364
|
|
|
249
365
|
```json
|
|
250
366
|
{
|
|
@@ -258,7 +374,7 @@ A `tsconfig.json` like the following lets `tsc --noEmit` resolve `D1Database`,
|
|
|
258
374
|
"skipLibCheck": true,
|
|
259
375
|
"noEmit": true
|
|
260
376
|
},
|
|
261
|
-
"include": ["src/**/*.ts"]
|
|
377
|
+
"include": ["src/**/*.ts", "alchemy.run.ts"]
|
|
262
378
|
}
|
|
263
379
|
```
|
|
264
380
|
|
|
@@ -273,7 +389,7 @@ no Clerk import, secret, package, or fallback provider. Docker deployments keep
|
|
|
273
389
|
the Clerk path in the Node template.
|
|
274
390
|
|
|
275
391
|
Then list the maintainers' Access user ids (`user_uuid`, else email) in the
|
|
276
|
-
`CONNECTA_MAINTAINERS` var and point a maintainer's MCP client at
|
|
392
|
+
`CONNECTA_MAINTAINERS` var in `alchemy.run.ts`, deploy, and point a maintainer's MCP client at
|
|
277
393
|
`<PUBLIC_URL>/mcp`. Other people use `<PUBLIC_URL>/mcp/<pool>`, and agents
|
|
278
394
|
`<PUBLIC_URL>/agent/<pool>`, for a pool that lists them in `members`. The example explicitly enables
|
|
279
395
|
`ui: operatorUi()`; open `<PUBLIC_URL>/` for endpoints, and each connector's Connection tab
|
|
@@ -375,9 +491,9 @@ on the next call without redeploying; no liveness probe runs in the background.
|
|
|
375
491
|
With this vault, 0.25.0 seals existing downstream OAuth state on first read.
|
|
376
492
|
Rolling back to 0.24.x then requires reauthorizing those OAuth connectors.
|
|
377
493
|
|
|
378
|
-
The
|
|
494
|
+
The example's hosted Notion `remoteMcp()` entry uses a deployment-owned static header and echo
|
|
379
495
|
needs no secret. To exercise vault controls, declare a `credential` slot on an
|
|
380
|
-
`api()` connector or use a
|
|
496
|
+
`api()` connector or use a Stripe connector with `auth: { type: "apiKey" }`,
|
|
381
497
|
which declares its own slot.
|
|
382
498
|
Authorized users manage that slot inside the connection. Configuring a vault
|
|
383
499
|
does not create credentials or permissions by itself.
|
|
@@ -420,10 +536,11 @@ still require a deployment-code change.
|
|
|
420
536
|
|
|
421
537
|
The Dynamic Worker sandbox requires the
|
|
422
538
|
[Workers Paid plan](https://developers.cloudflare.com/dynamic-workers/pricing/).
|
|
423
|
-
The required Worker Loader binding is
|
|
539
|
+
The required Worker Loader binding is declared in `alchemy.run.ts`, and in
|
|
540
|
+
`wrangler.jsonc` for local development:
|
|
424
541
|
|
|
425
|
-
```
|
|
426
|
-
|
|
542
|
+
```ts
|
|
543
|
+
LOADER: Cloudflare.WorkerLoader(),
|
|
427
544
|
```
|
|
428
545
|
|
|
429
546
|
`src/connecta.config.ts` uses `workerExecutor({ loader: env.LOADER })` from
|
|
@@ -471,8 +588,10 @@ CREATE INDEX IF NOT EXISTS connecta_kv_expiry ON connecta_kv (expires_at_ms);
|
|
|
471
588
|
|
|
472
589
|
### Upgrading from 0.28
|
|
473
590
|
|
|
474
|
-
0.28 shipped three storage shapes in this example
|
|
475
|
-
|
|
591
|
+
0.28 shipped three storage shapes in this example, each deployed with
|
|
592
|
+
Wrangler. Finish the storage upgrade on the deployment's existing Wrangler
|
|
593
|
+
configuration, then [move it to Alchemy](#moving-a-wrangler-deployed-worker-to-alchemy).
|
|
594
|
+
Each shape moves to the one `CONNECTA_DB` binding:
|
|
476
595
|
|
|
477
596
|
- **Already on `d1-storage.ts`** (one D1 database, possibly also holding
|
|
478
597
|
activity). The table is unchanged, so no data moves. Rename the binding in
|
|
@@ -553,7 +672,7 @@ then `wrangler login` and check the prepared deployment with a dry run.
|
|
|
553
672
|
`verified` / `mismatches` counts by family only, and exits non-zero on any
|
|
554
673
|
invalid entry or mismatch. Keep traffic and writers stopped until these
|
|
555
674
|
counts are resolved. A verification pass does not rewrite copied entries.
|
|
556
|
-
5. Deploy the D1 configuration with `wrangler deploy` while maintenance remains.
|
|
675
|
+
5. Deploy the D1 configuration with the deployment's `wrangler deploy` while maintenance remains.
|
|
557
676
|
Run `connecta doctor --pool <pool>` using Access service credentials plus a
|
|
558
677
|
stored `cta_` bearer through `CONNECTA_TOKEN`. Verify an existing
|
|
559
678
|
OAuth connector without re-consent, an existing `cta_` token, a connector
|