@zackbart/connecta 0.34.0 → 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 +393 -0
- package/README.md +62 -105
- 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 +15 -7
- package/dist/connectors/api-connector.js +147 -57
- 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/option-shapes.js +1 -1
- package/dist/connectors/remote-mcp.d.ts +12 -30
- package/dist/connectors/remote-mcp.js +960 -564
- package/dist/d1.js +10 -243
- package/dist/derived-context.js +5 -0
- package/dist/describe-config.d.ts +5 -1
- package/dist/describe-config.js +3 -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 +221 -87
- 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 +534 -408
- 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 +8 -4
- package/dist/operator-ui/connection-map.js +9 -6
- package/dist/operator-ui/contract.d.ts +7 -3
- package/dist/operator-ui/endpoints.js +5 -14
- 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/health.js +52 -0
- package/dist/operator-ui/model.d.ts +2 -3
- package/dist/operator-ui/overview.js +11 -19
- package/dist/operator-ui/setup-commands.js +0 -4
- package/dist/operator-ui/view.d.ts +5 -29
- package/dist/operator-ui/view.js +3 -59
- 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 +71 -32
- package/dist/provider.js +134 -40
- 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 +8 -209
- package/dist/providers/_shared/google/workspace.js +7 -426
- 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 +3 -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 +17 -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 +7 -22
- package/dist/providers/cloudflare/index.js +80 -194
- 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 +3299 -3208
- package/dist/providers/cloudflare/{value-safety.js → safety.js} +538 -18
- 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 +3 -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 +6 -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 +7 -27
- package/dist/providers/stripe/index.js +75 -191
- 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 -10
- package/dist/providers/stripe/tools.js +77 -0
- package/dist/providers/tithely/api.js +531 -0
- package/dist/providers/tithely/index.d.ts +19 -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 +11 -25
- package/dist/providers/vercel/index.js +67 -261
- 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 +398 -376
- package/dist/providers/vercel/{value-safety.js → safety.js} +261 -42
- 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 +30 -28
- package/dist/registry.js +446 -413
- 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 +29 -22
- 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 +330 -224
- 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 +11 -99
- 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 +2550 -186
- package/documentation/auth.md +821 -98
- package/documentation/code-mode.md +56 -21
- package/documentation/deploying.md +164 -20
- package/documentation/hosted-mcp-migration.md +460 -0
- package/documentation/integrating.md +144 -105
- package/documentation/meta-tools.md +411 -34
- package/documentation/operating.md +28 -4
- package/documentation/operator-tests.md +11 -2
- package/documentation/operator-ui.md +103 -33
- package/documentation/provider-auth-migration.md +38 -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 -42
- 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 -134
- package/dist/catalog-drift.js +0 -493
- 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 -43
- 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 -1078
- 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/linear/index.d.ts +0 -55
- package/dist/providers/linear/index.js +0 -352
- package/dist/providers/linear/skill.generated.js +0 -8
- package/dist/providers/mixpanel/index.d.ts +0 -57
- package/dist/providers/mixpanel/index.js +0 -468
- 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 -65
- 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 -49
- package/dist/providers/revenuecat/index.js +0 -557
- 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
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
export type { CloudflarePin } from "./rest.js";
|
|
5
|
-
/** Cloudflare's official whole-API hosted MCP endpoint. */
|
|
6
|
-
export declare const CLOUDFLARE_MCP_ENDPOINT = "https://mcp.cloudflare.com/mcp";
|
|
1
|
+
import type { CloudflarePin } from "./lib/config.js";
|
|
2
|
+
export { CLOUDFLARE_API_BASE } from "./lib/config.js";
|
|
3
|
+
export type { CloudflarePin } from "./lib/config.js";
|
|
7
4
|
interface CloudflareCommonOptions {
|
|
8
5
|
/** Human-readable display name; defaults identify the implementation. */
|
|
9
6
|
title?: string;
|
|
@@ -15,14 +12,8 @@ interface CloudflareCommonOptions {
|
|
|
15
12
|
instructions?: string;
|
|
16
13
|
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
17
14
|
maxResultBytes?: number;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export interface CloudflareOAuthOptions extends CloudflareCommonOptions {
|
|
21
|
-
auth: {
|
|
22
|
-
type: "oauth";
|
|
23
|
-
};
|
|
24
|
-
/** Optional per-runtime downstream call-admission policy. */
|
|
25
|
-
callAdmission?: ConnectorCallAdmissionPolicy;
|
|
15
|
+
/** Serve only read-classified tools on every endpoint. Defaults to false. */
|
|
16
|
+
readOnly?: boolean;
|
|
26
17
|
}
|
|
27
18
|
interface CloudflareKeyOptions extends CloudflareCommonOptions {
|
|
28
19
|
/**
|
|
@@ -62,12 +53,6 @@ export interface CloudflareGlobalApiKeyOptions extends CloudflareKeyOptions {
|
|
|
62
53
|
/** Accept every account and zone the key's user can reach. */
|
|
63
54
|
unpinned?: true;
|
|
64
55
|
}
|
|
65
|
-
export type CloudflareOptions =
|
|
66
|
-
/**
|
|
67
|
-
* A maintained Cloudflare connection. `auth` selects the implementation:
|
|
68
|
-
* OAuth reaches Cloudflare's hosted MCP server; an API token or a Global API
|
|
69
|
-
* Key reaches Connecta's REST connector to the v4 API.
|
|
70
|
-
*/
|
|
56
|
+
export type CloudflareOptions = CloudflareApiTokenOptions | CloudflareGlobalApiKeyOptions;
|
|
57
|
+
/** Maintained API connection. Hosted MCP uses a separate generic remoteMcp entry. */
|
|
71
58
|
export declare const cloudflare: import("../../provider.js").ProviderFactory<CloudflareOptions>;
|
|
72
|
-
/** @deprecated Read `cloudflare.definition.classify` instead. Kept for existing imports. */
|
|
73
|
-
export declare const CLOUDFLARE_MCP_VETTED_CATALOG: import("../../catalog-drift.js").VettedCatalog;
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { skill } from "./skill.generated.js";
|
|
2
|
-
/**
|
|
3
|
-
* No official `cloudflare` SDK on purpose. Cloudflare's v4 API is
|
|
4
|
-
* authenticated `fetch` over a uniform `{ success, errors, result,
|
|
5
|
-
* result_info }` envelope, and the key connector validates every call against
|
|
6
|
-
* a pinned operation index instead of typed wrappers, so Web APIs alone keep
|
|
7
|
-
* this provider Workers-clean. `test/package-surface.node.test.ts` pins it: no
|
|
8
|
-
* `cloudflare` package in any dependency field, every import relative.
|
|
9
|
-
*/
|
|
10
|
-
import { apiConnector } from "../../connectors/api-connector.js";
|
|
11
|
-
import { reviewedCatalog } from "../../catalog-drift.js";
|
|
12
2
|
import { keys, optionsOf, variants } from "../../config-schema.js";
|
|
13
|
-
import { CALL_ADMISSION
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export const CLOUDFLARE_MCP_ENDPOINT = "https://mcp.cloudflare.com/mcp";
|
|
3
|
+
import { CALL_ADMISSION } from "../../provider.js";
|
|
4
|
+
import { defineApiProvider } from "../../http/provider.js";
|
|
5
|
+
import { CloudflareApi, authenticate, cloudflareErrors, cloudflareRuntime, MAX_RESPONSE_BYTES, READ_CAP_MS, safety, result, describeProbe, settings, cloudflareIndex, WRITE_STEPS, UPLOADS, } from "./api.js";
|
|
6
|
+
import { cloudflareTools } from "./tools.js";
|
|
7
|
+
import { CLOUDFLARE_VERDICTS, CLOUDFLARE_PAGES, CLOUDFLARE_HEADERS, cloudflareBinding } from "./lib/hatch.js";
|
|
8
|
+
export { CLOUDFLARE_API_BASE } from "./lib/config.js";
|
|
20
9
|
/**
|
|
21
10
|
* Cloudflare documents a global limit of 1,200 requests per five minutes per
|
|
22
11
|
* user, counted cumulatively across the dashboard, API keys, and API tokens
|
|
@@ -61,71 +50,12 @@ const GLOBAL_API_KEY_CREDENTIAL = {
|
|
|
61
50
|
},
|
|
62
51
|
],
|
|
63
52
|
};
|
|
64
|
-
|
|
65
|
-
* Reviewed in #705's provider audit against https://developers.cloudflare.com/agents/model-context-protocol/cloudflare/servers-for-cloudflare/.
|
|
66
|
-
* Classifies the hosted OAuth catalog only; the REST connector annotates
|
|
67
|
-
* each tool it authors.
|
|
68
|
-
*/
|
|
69
|
-
const CLOUDFLARE_MCP_CLASSIFICATION = {
|
|
70
|
-
tools: {
|
|
71
|
-
search: {
|
|
72
|
-
verdict: "read",
|
|
73
|
-
reason: "Searches the Cloudflare OpenAPI contract without executing API methods.",
|
|
74
|
-
},
|
|
75
|
-
execute: {
|
|
76
|
-
verdict: "destructive",
|
|
77
|
-
reason: "Can mix HTTP methods across the Cloudflare API; no input schema proves a program only reads.",
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
function instructionsSection(instructions) {
|
|
82
|
-
const text = instructions?.trim();
|
|
83
|
-
return text ? `\n## ${skill.instructionsHeading}\n\n${text}\n` : "";
|
|
84
|
-
}
|
|
85
|
-
function oauthUsageGuide(purpose, instructions) {
|
|
86
|
-
const { oauth, shared, oauth_tail } = skill.fragments;
|
|
87
|
-
return `# Cloudflare usage
|
|
88
|
-
|
|
89
|
-
Hosted MCP over OAuth: \`search\` and \`execute\`. Connector purpose: ${purpose}${oauth}${shared}${oauth_tail}${instructionsSection(instructions)}`;
|
|
90
|
-
}
|
|
91
|
-
function idList(ids) {
|
|
92
|
-
return ids?.length ? ids.map((id) => `\`${id}\``).join(", ") : "none";
|
|
93
|
-
}
|
|
94
|
-
function keyUsageGuide(auth, options) {
|
|
95
|
-
const { key, global_warning, shared, key_tail } = skill.fragments;
|
|
96
|
-
const scheme = auth === "apiToken" ? "a scoped API token" : "a Global API Key";
|
|
97
|
-
const pinned = options.pin
|
|
98
|
-
? [
|
|
99
|
-
options.pin.accountIds?.length ? `accounts ${idList(options.pin.accountIds)} and every zone in them` : "",
|
|
100
|
-
options.pin.zoneIds?.length ? `zones ${idList(options.pin.zoneIds)}` : "",
|
|
101
|
-
].filter(Boolean)
|
|
102
|
-
: [];
|
|
103
|
-
const pin = options.pin
|
|
104
|
-
? `\n\nPinned to ${pinned.join(", plus ")}. Calls naming any other account or zone are refused before they are sent, and so is every operation that names neither, except the credential's own user, the filtered account, zone, and membership lists, zone creation in a pinned account, and public data.`
|
|
105
|
-
: auth === "globalApiKey"
|
|
106
|
-
? "\n\nUnpinned: this connector reaches every account and zone the key's user can."
|
|
107
|
-
: "";
|
|
108
|
-
const defaults = [
|
|
109
|
-
options.accountId ? `\`{account_id}\` in a path fills with \`${options.accountId}\`` : "",
|
|
110
|
-
options.zoneId ? `\`{zone_id}\` fills with \`${options.zoneId}\`` : "",
|
|
111
|
-
].filter(Boolean);
|
|
112
|
-
const defaultLine = defaults.length
|
|
113
|
-
? `\n\nDefaults: ${defaults.join("; ")}. Pass another id in the path when the request names a different one.`
|
|
114
|
-
: "";
|
|
115
|
-
return `# Cloudflare usage
|
|
116
|
-
|
|
117
|
-
REST with ${scheme}. Connector purpose: ${options.purpose}${auth === "globalApiKey" ? global_warning.trimEnd() : ""}${pin}${defaultLine}${key}${shared}${key_tail}${instructionsSection(options.instructions)}`;
|
|
118
|
-
}
|
|
119
|
-
const COMMON = keys("title", "authScope", "purpose", "instructions", "maxResultBytes");
|
|
53
|
+
const COMMON = keys("title", "authScope", "purpose", "instructions", "maxResultBytes", "readOnly");
|
|
120
54
|
const KEY_COMMON = keys("accountId", "zoneId", "baseUrl", "maxConcurrency");
|
|
121
55
|
const PIN = optionsOf()(keys("accountIds", "zoneIds"));
|
|
122
56
|
/** The closed options cloudflare() accepts, selected by `auth.type`; see `assertKnownOptions`. */
|
|
123
57
|
const CLOUDFLARE_OPTIONS = variants(["auth", "type"], {
|
|
124
|
-
oauth: optionsOf()(
|
|
125
|
-
...COMMON,
|
|
126
|
-
callAdmission: CALL_ADMISSION,
|
|
127
|
-
auth: optionsOf()(keys("type")),
|
|
128
|
-
}).shape,
|
|
58
|
+
oauth: { ...COMMON, callAdmission: CALL_ADMISSION, auth: optionsOf()(keys("type")) },
|
|
129
59
|
apiToken: optionsOf()({
|
|
130
60
|
...COMMON,
|
|
131
61
|
...KEY_COMMON,
|
|
@@ -139,130 +69,86 @@ const CLOUDFLARE_OPTIONS = variants(["auth", "type"], {
|
|
|
139
69
|
pin: PIN,
|
|
140
70
|
auth: optionsOf()(keys("type")),
|
|
141
71
|
}).shape,
|
|
142
|
-
});
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
summary: "Hosted MCP over OAuth. Search the OpenAPI document; execute programs always classify as writes.",
|
|
152
|
-
required: true,
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
function idsOf(id, value, path) {
|
|
157
|
-
if (value === undefined)
|
|
158
|
-
return undefined;
|
|
159
|
-
if (!Array.isArray(value) ||
|
|
160
|
-
value.length === 0 ||
|
|
161
|
-
!value.every((item) => typeof item === "string" && item.trim() !== "")) {
|
|
162
|
-
throw new Error(`cloudflare("${id}") ${path} must be a non-empty list of ids.`);
|
|
163
|
-
}
|
|
164
|
-
return value.map((item) => item.trim());
|
|
165
|
-
}
|
|
166
|
-
function optionalId(id, value, path) {
|
|
167
|
-
if (value === undefined)
|
|
168
|
-
return undefined;
|
|
169
|
-
if (typeof value !== "string" || value.trim() === "" || /[/?#\s]/.test(value.trim())) {
|
|
170
|
-
throw new Error(`cloudflare("${id}") ${path} must be a Cloudflare id.`);
|
|
171
|
-
}
|
|
172
|
-
return value.trim();
|
|
173
|
-
}
|
|
174
|
-
function cloudflareKey(auth) {
|
|
175
|
-
return (id, options, provider) => {
|
|
176
|
-
const maxConcurrency = options.maxConcurrency ?? 6;
|
|
177
|
-
if (!Number.isInteger(maxConcurrency) || maxConcurrency < 1) {
|
|
178
|
-
throw new Error(`cloudflare("${id}") maxConcurrency must be a positive integer.`);
|
|
179
|
-
}
|
|
180
|
-
let pin;
|
|
181
|
-
if (options.pin !== undefined) {
|
|
182
|
-
const accountIds = idsOf(id, options.pin.accountIds, "pin.accountIds");
|
|
183
|
-
const zoneIds = idsOf(id, options.pin.zoneIds, "pin.zoneIds");
|
|
184
|
-
if (!accountIds && !zoneIds)
|
|
185
|
-
throw new Error(`cloudflare("${id}") pin names accountIds, zoneIds, or both.`);
|
|
186
|
-
pin = {
|
|
187
|
-
...(accountIds ? { accountIds } : {}),
|
|
188
|
-
...(zoneIds ? { zoneIds } : {}),
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
if (auth === "globalApiKey") {
|
|
192
|
-
const unpinned = options.unpinned;
|
|
193
|
-
if (unpinned !== undefined && unpinned !== true) {
|
|
194
|
-
throw new Error(`cloudflare("${id}") unpinned must be true when set.`);
|
|
195
|
-
}
|
|
196
|
-
if (pin && unpinned)
|
|
197
|
-
throw new Error(`cloudflare("${id}") takes pin or unpinned: true, not both.`);
|
|
198
|
-
if (!pin && !unpinned) {
|
|
199
|
-
throw new Error(`cloudflare("${id}") requires pin: { accountIds, zoneIds } with globalApiKey auth, or unpinned: true: a Global API Key reaches every account and zone its user can.`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
const accountId = optionalId(id, options.accountId, "accountId");
|
|
203
|
-
const zoneId = optionalId(id, options.zoneId, "zoneId");
|
|
204
|
-
if (pin && accountId && pin.accountIds && !pin.accountIds.includes(accountId)) {
|
|
205
|
-
throw new Error(`cloudflare("${id}") accountId ${accountId} is outside its pin.`);
|
|
206
|
-
}
|
|
207
|
-
if (pin && zoneId && pin.zoneIds && !pin.accountIds && !pin.zoneIds.includes(zoneId)) {
|
|
208
|
-
throw new Error(`cloudflare("${id}") zoneId ${zoneId} is outside its pin.`);
|
|
209
|
-
}
|
|
210
|
-
const purpose = options.purpose.trim();
|
|
211
|
-
const rest = cloudflareRest({
|
|
212
|
-
auth,
|
|
213
|
-
baseUrl: options.baseUrl?.trim() || CLOUDFLARE_API_BASE,
|
|
214
|
-
accountId,
|
|
215
|
-
zoneId,
|
|
216
|
-
pin,
|
|
217
|
-
});
|
|
218
|
-
return apiConnector(id, {
|
|
219
|
-
...provider.connectorOptions,
|
|
220
|
-
title: options.title ?? (auth === "globalApiKey" ? "Cloudflare (Global API Key)" : "Cloudflare"),
|
|
221
|
-
description: `Cloudflare v4 API over REST (${auth === "globalApiKey" ? "Global API Key" : "API token"}${pin ? ", pinned" : ""}) — ${purpose}`,
|
|
222
|
-
credential: auth === "globalApiKey" ? GLOBAL_API_KEY_CREDENTIAL : API_TOKEN_CREDENTIAL,
|
|
72
|
+
}, undefined, ["oauth"]);
|
|
73
|
+
function usageGuide(options) {
|
|
74
|
+
const { auth, accountId, zoneId, pin } = settings(options);
|
|
75
|
+
return {
|
|
76
|
+
heading: "Cloudflare usage",
|
|
77
|
+
summary: "Configured Cloudflare REST credential: resolve domain/account ids, then inspect DNS, Workers, R2, KV or analytics.",
|
|
78
|
+
context: [
|
|
79
|
+
`Connector purpose: ${options.purpose}`,
|
|
80
|
+
`This connection already has an operator-configured ${auth === "apiToken" ? "scoped API token" : "Global API Key"}; there is no sign-in step.`,
|
|
223
81
|
...(auth === "globalApiKey"
|
|
224
|
-
?
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
},
|
|
239
|
-
tools: [...restTools(rest.vendor), ...rest.tools],
|
|
240
|
-
});
|
|
82
|
+
? [
|
|
83
|
+
"A Global API Key acts as its user across the user's estate. R2 requires an API token; user-setting and membership writes are refused.",
|
|
84
|
+
]
|
|
85
|
+
: []),
|
|
86
|
+
...(pin
|
|
87
|
+
? [
|
|
88
|
+
`Pin: account ids ${pin.accountIds?.join(", ") || "none"}; zone ids ${pin.zoneIds?.join(", ") || "none"}. A pinned account includes its zones. Calls outside this boundary are refused.`,
|
|
89
|
+
]
|
|
90
|
+
: ["No additional deployment pin: the credential's vendor permissions define its reachable estate."]),
|
|
91
|
+
...(accountId ? [`Default account id: ${accountId}.`] : []),
|
|
92
|
+
...(zoneId ? [`Default zone id: ${zoneId}.`] : []),
|
|
93
|
+
...(options.readOnly ? ["This connection is read-only: every write is refused."] : []),
|
|
94
|
+
],
|
|
95
|
+
required: true,
|
|
241
96
|
};
|
|
242
97
|
}
|
|
243
|
-
/**
|
|
244
|
-
|
|
245
|
-
* OAuth reaches Cloudflare's hosted MCP server; an API token or a Global API
|
|
246
|
-
* Key reaches Connecta's REST connector to the v4 API.
|
|
247
|
-
*/
|
|
248
|
-
export const cloudflare = defineProvider({
|
|
98
|
+
/** Maintained API connection. Hosted MCP uses a separate generic remoteMcp entry. */
|
|
99
|
+
export const cloudflare = defineApiProvider({
|
|
249
100
|
name: "cloudflare",
|
|
250
101
|
title: "Cloudflare",
|
|
251
|
-
kind: "dual",
|
|
252
102
|
readme: "Cloudflare",
|
|
253
103
|
bundle: {
|
|
254
|
-
baselineGzip:
|
|
255
|
-
|
|
256
|
-
note: "./providers/cloudflare remeasures at 334,055 B gzip (#801), from 151,186 B on main: auth now selects the implementation, so the entry carries the hosted MCP client and Connecta's REST connector (api(), the schema validator, the shared REST module, about 22 KB gzip as in ./providers/stripe) plus the pinned Cloudflare operation index: 3,336 non-deprecated operations from a 27 MB document. The index was shrunk before the cap moved, from 157 KB to 125 KB gzip as source: request details to depth 2 without descriptions or enums over 50 values, no operation ids (they restate summaries), no plain-string path parameters (the template names them), and a 6,000-character per-operation budget that lowers one sprawling operation's depth. Depth 1 would save about 18 KB more at the cost of nested validation such as DNS record alternatives. Removing 23 hand-written reads offsets part of the growth; the reviewed value-safety table adds about 12 KB. The value-safety consolidation (#801) moved the spec-derived candidate record out of the index and grew the table by 259 verdicts, a net +3,646 B (337,701 B), inside the cap. The cap uses the existing baseline + 60,000 B policy.",
|
|
104
|
+
baselineGzip: 597127,
|
|
105
|
+
note: "./providers/cloudflare merged GitHub/Cloudflare/CCB step-2 snapshot measures 597,127 B gzip standalone before recording these bundle facts, versus 528,947 B on main ce0c7492 (Node 26.12.0, zlib-ng 1.3.1, gzip level 9). The standard hatch, response-field metadata, retained 120-character parameter descriptions and numeric bounds account for this reviewed growth. The shared Effect kit is paid once per deployment; provider entries are report-only, not capped (#899).",
|
|
257
106
|
},
|
|
258
107
|
skill,
|
|
259
108
|
options: CLOUDFLARE_OPTIONS,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
109
|
+
vendor: CloudflareApi,
|
|
110
|
+
baseUrl: (options) => settings(options).baseUrl,
|
|
111
|
+
displayTitle: (options) => (options.auth.type === "globalApiKey" ? "Cloudflare (Global API Key)" : "Cloudflare"),
|
|
112
|
+
description: (options) => `Cloudflare v4 API over REST (${options.auth.type === "globalApiKey" ? "Global API Key" : "API token"}${settings(options).pin ? ", pinned" : ""}) — ${options.purpose}`,
|
|
113
|
+
maxResponseBytes: MAX_RESPONSE_BYTES,
|
|
114
|
+
timeoutMs: READ_CAP_MS,
|
|
115
|
+
defaultCallAdmission: (options) => admissionPolicy(options.maxConcurrency ?? 6),
|
|
116
|
+
credential: (options) => (options.auth.type === "globalApiKey" ? GLOBAL_API_KEY_CREDENTIAL : API_TOKEN_CREDENTIAL),
|
|
117
|
+
authenticate,
|
|
118
|
+
errors: cloudflareErrors,
|
|
119
|
+
inBandRefusals: true,
|
|
120
|
+
idempotencyKey: false,
|
|
121
|
+
pageSize: { default: 20, max: 50 },
|
|
122
|
+
safety,
|
|
123
|
+
result,
|
|
124
|
+
probe: {
|
|
125
|
+
run: (connection, options) => cloudflareRuntime(connection, settings(options)).verify(),
|
|
126
|
+
describe: describeProbe,
|
|
127
|
+
},
|
|
128
|
+
guide: usageGuide,
|
|
129
|
+
hatch: {
|
|
130
|
+
name: "cloudflare",
|
|
131
|
+
title: "Cloudflare",
|
|
132
|
+
index: cloudflareIndex,
|
|
133
|
+
verdicts: CLOUDFLARE_VERDICTS,
|
|
134
|
+
named: {
|
|
135
|
+
...Object.fromEntries(UPLOADS.map(([method, path]) => [`${method} ${path}`, "cloudflare_api_upload"])),
|
|
136
|
+
"GET /accounts": "list_accounts",
|
|
137
|
+
"GET /zones": "list_zones",
|
|
138
|
+
"GET /user/tokens/verify": "verify_credential",
|
|
139
|
+
},
|
|
140
|
+
fieldsRoot: "result",
|
|
141
|
+
pageCursor: "parameter",
|
|
142
|
+
headers: CLOUDFLARE_HEADERS,
|
|
143
|
+
textBodies: true,
|
|
144
|
+
writeSteps: WRITE_STEPS,
|
|
145
|
+
pages: CLOUDFLARE_PAGES,
|
|
146
|
+
binding: cloudflareBinding,
|
|
147
|
+
pathExample: "/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records",
|
|
148
|
+
notes: () => ({
|
|
149
|
+
read: 'DNS records, zones, Workers scripts, R2 buckets and objects, KV namespaces and keys are covered. Data retains the Cloudflare envelope; use fields:["result.id","result.name"]. Pass page.nextCursor in page.param within page.in, preserving the other arguments. Text/SQL reads take a string body.',
|
|
150
|
+
write: "Create, update or delete DNS records, purge cache URLs, deploy Workers and change KV/R2 state here. Reviewed uploads use cloudflare_api_upload; JSON, text/SQL and NDJSON writes retain their documented wire formats.",
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
tools: cloudflareTools,
|
|
266
154
|
});
|
|
267
|
-
/** @deprecated Read `cloudflare.definition.classify` instead. Kept for existing imports. */
|
|
268
|
-
export const CLOUDFLARE_MCP_VETTED_CATALOG = reviewedCatalog(cloudflare.definition.classify, 'defineProvider("cloudflare")');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Cloudflare's v4 REST base. Override only for a proxy or a test double. */
|
|
2
|
+
export declare const CLOUDFLARE_API_BASE = "https://api.cloudflare.com/client/v4";
|
|
3
|
+
/** The two key schemes Cloudflare's v4 API accepts. */
|
|
4
|
+
export type CloudflareKeyAuth = "apiToken" | "globalApiKey";
|
|
5
|
+
/** Accounts and zones a connector may touch; everything else is refused. */
|
|
6
|
+
export interface CloudflarePin {
|
|
7
|
+
accountIds?: readonly string[];
|
|
8
|
+
zoneIds?: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
export interface CloudflareRestOptions {
|
|
11
|
+
auth: CloudflareKeyAuth;
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
accountId: string | undefined;
|
|
14
|
+
zoneId: string | undefined;
|
|
15
|
+
pin: CloudflarePin | undefined;
|
|
16
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Reviewed workflow synonyms supplement, rather than replace, every pinned action/resource word.
|
|
2
|
+
const summaries = {
|
|
3
|
+
"GET /zones": "Find domains and zones by name or account",
|
|
4
|
+
"GET /zones/{zone_id}": "Get zone details and domain configuration",
|
|
5
|
+
"GET /accounts/{account_id}/r2/buckets": "List R2 buckets for an account",
|
|
6
|
+
"PATCH /zones/{zone_id}/dns_records/{dns_record_id}": "Update DNS record: set DNS TTL, content, name or proxy status",
|
|
7
|
+
"POST /zones/{zone_id}/purge_cache": "Clear cache for a file or URL: purge cache files, tags, hosts or prefixes",
|
|
8
|
+
"PUT /accounts/{account_id}/workers/scripts/{script_name}": "Deploy a Worker script: upload source and bindings",
|
|
9
|
+
"GET /accounts/{account_id}/storage/kv/namespaces/{namespace_id}/keys": "List KV keys and expiration metadata by prefix",
|
|
10
|
+
};
|
|
11
|
+
export function cloudflareDiscovery(data) {
|
|
12
|
+
const tags = [...data.tags];
|
|
13
|
+
return {
|
|
14
|
+
...data,
|
|
15
|
+
tags,
|
|
16
|
+
ops: data.ops.map(([method, path, id, summary, tag, server]) => {
|
|
17
|
+
const reviewed = summaries[`${method} ${path}`];
|
|
18
|
+
const combined = reviewed ? `${reviewed} (${summary})` : summary;
|
|
19
|
+
// The vendor calls deployment "upload"; keep that action and add the
|
|
20
|
+
// reviewed deployment category beside the original resource category.
|
|
21
|
+
const category = method === "PUT" && path === "/accounts/{account_id}/workers/scripts/{script_name}"
|
|
22
|
+
? tags.push(`${data.tags[tag]} (Worker deploy)`) - 1
|
|
23
|
+
: tag;
|
|
24
|
+
return server === undefined
|
|
25
|
+
? [method, path, id, combined, category]
|
|
26
|
+
: [method, path, id, combined, category, server];
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// definitions are walked, so a `mutation` hidden in a string, a comment, or
|
|
5
5
|
// after an anonymous query is still found, and anything that is not a query
|
|
6
6
|
// or a fragment is refused. Nothing here does I/O.
|
|
7
|
-
import { ConnectorCallError } from "
|
|
7
|
+
import { ConnectorCallError } from "../../../errors.js";
|
|
8
8
|
const SCOPED_FIELDS = new Set(["accounts", "zones"]);
|
|
9
9
|
function refuse(message) {
|
|
10
10
|
throw new ConnectorCallError("invalid_args", message);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Cloudflare's reviewed standard hatch binding; the kit owns discovery and admission.
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { ConnectorCallError } from "../../../errors.js";
|
|
4
|
+
import { cloudflarePage } from "../../../http/hatch-paging.js";
|
|
5
|
+
import { cloudflareIndex, SAFETY, READ_POSTS, HEADERS, cloudflareRuntime, settings, record, invalid } from "../api.js";
|
|
6
|
+
import { withholdEmbeddedUrlsIn } from "../../_shared/rest/value-safety.js";
|
|
7
|
+
export const CLOUDFLARE_VERDICTS = Object.fromEntries(cloudflareIndex.ops.map((op) => [
|
|
8
|
+
`${op.method} ${op.path}`,
|
|
9
|
+
SAFETY.refusal(op.method, op.path) || op.server
|
|
10
|
+
? "refuse"
|
|
11
|
+
: op.method === "GET" || READ_POSTS.some(([method, path]) => method === op.method && path === op.path)
|
|
12
|
+
? "read"
|
|
13
|
+
: "destructive",
|
|
14
|
+
]));
|
|
15
|
+
const badPage = (message) => {
|
|
16
|
+
throw new ConnectorCallError("connector_call_failed", message, { retryable: false });
|
|
17
|
+
};
|
|
18
|
+
const tokenPage = (param) => ({
|
|
19
|
+
param,
|
|
20
|
+
in: "query",
|
|
21
|
+
cursorInputMessage: `Pass page.nextCursor as cursor in query.${param}; do not send the vendor raw cursor.`,
|
|
22
|
+
decode: (value) => typeof value === "string" && value ? value : invalid("This paging cursor contains no valid Cloudflare token."),
|
|
23
|
+
next(data) {
|
|
24
|
+
const info = record(record(data)["result_info"]);
|
|
25
|
+
const value = info["cursor"] ?? record(info["cursors"])["after"];
|
|
26
|
+
if (value === undefined && !("cursor" in info) && !("cursors" in info))
|
|
27
|
+
return undefined;
|
|
28
|
+
if (info["is_truncated"] === false || info["is_truncated"] === "false")
|
|
29
|
+
return null;
|
|
30
|
+
if (value === null || value === undefined || value === "") {
|
|
31
|
+
if (info["is_truncated"] === true || info["is_truncated"] === "true")
|
|
32
|
+
badPage("Cloudflare reported another page without a cursor.");
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (typeof value !== "string")
|
|
36
|
+
return badPage("Cloudflare returned invalid cursor metadata.");
|
|
37
|
+
if (withholdEmbeddedUrlsIn(value) !== value || /\[redacted\]/i.test(value))
|
|
38
|
+
return { hasMore: true };
|
|
39
|
+
return value;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
export const CLOUDFLARE_PAGES = Object.fromEntries(cloudflareIndex.ops.flatMap((op) => {
|
|
43
|
+
if (CLOUDFLARE_VERDICTS[`${op.method} ${op.path}`] !== "read")
|
|
44
|
+
return [];
|
|
45
|
+
const params = cloudflareIndex.contract(op).parameters.filter((p) => p.in === "query");
|
|
46
|
+
const token = params.find((p) => p.name === "cursor" || p.name === "after");
|
|
47
|
+
// Only bind a continuation whose response envelope and query location are
|
|
48
|
+
// established by the pin. Mixed page/cursor APIs can use nonstandard
|
|
49
|
+
// pagination envelopes; retain their vendor query protocol until reviewed.
|
|
50
|
+
if (!cloudflareIndex.responseRoots(op)?.has("result_info") || (token && params.some((p) => p.name === "page")))
|
|
51
|
+
return [];
|
|
52
|
+
const adapter = token
|
|
53
|
+
? tokenPage(token.name)
|
|
54
|
+
: params.some((p) => p.name === "page")
|
|
55
|
+
? {
|
|
56
|
+
...cloudflarePage,
|
|
57
|
+
cursorInputMessage: "Omit page on the first call; to continue, pass page.nextCursor unchanged as the cursor in query.page.",
|
|
58
|
+
}
|
|
59
|
+
: undefined;
|
|
60
|
+
return adapter ? [[`${op.method} ${op.path}`, adapter]] : [];
|
|
61
|
+
}));
|
|
62
|
+
export const CLOUDFLARE_HEADERS = Object.fromEntries(Object.entries(HEADERS).map(([key, description]) => [
|
|
63
|
+
key,
|
|
64
|
+
{
|
|
65
|
+
description,
|
|
66
|
+
values: key === "cf-r2-jurisdiction"
|
|
67
|
+
? ["default", "eu", "us", "fedramp", "fedramp-high"]
|
|
68
|
+
: ["Standard", "InfrequentAccess"],
|
|
69
|
+
},
|
|
70
|
+
]));
|
|
71
|
+
export function cloudflareBinding({ connection, options, }) {
|
|
72
|
+
const runtime = cloudflareRuntime(connection, settings(options));
|
|
73
|
+
return {
|
|
74
|
+
review: "Cloudflare's indexed text, SQL, NDJSON and SCIM framing, closed R2 headers and configured defaults retain the same confined Connection, scoped admission and value safety.",
|
|
75
|
+
allowOtherBodyTypes: true,
|
|
76
|
+
path: runtime.fillDefaults,
|
|
77
|
+
prepareBody: (body, op) => runtime.scope({ method: op.method, path: op.path, op, params: {}, query: {}, body }).body,
|
|
78
|
+
refusal: (op) => SAFETY.refusal(op.method, op.path) ?? runtime.checkServer(op.server),
|
|
79
|
+
refuse: (call) => {
|
|
80
|
+
runtime.scope(call);
|
|
81
|
+
for (const parameter of cloudflareIndex.contract(call.op).parameters) {
|
|
82
|
+
if (parameter.in !== "query" ||
|
|
83
|
+
!["page", "per_page", "limit"].includes(parameter.name) ||
|
|
84
|
+
!["integer", "number"].includes(String(parameter.schema.type)))
|
|
85
|
+
continue;
|
|
86
|
+
const value = call.query[parameter.name];
|
|
87
|
+
if (value === undefined)
|
|
88
|
+
continue;
|
|
89
|
+
if (!(typeof value === "number" && Number.isSafeInteger(value) && value >= 0) &&
|
|
90
|
+
!(typeof value === "string" && /^\d+$/.test(value) && Number.isSafeInteger(Number(value))))
|
|
91
|
+
invalid(`${parameter.name} must be a whole number within the operation's declared bounds.`);
|
|
92
|
+
}
|
|
93
|
+
const policy = SAFETY.refusal(call.method, call.op.path);
|
|
94
|
+
if (policy)
|
|
95
|
+
return policy;
|
|
96
|
+
const type = cloudflareIndex.bodyType(call.op)?.toLowerCase() ?? "";
|
|
97
|
+
if (/multipart|octet-stream|image\//.test(type))
|
|
98
|
+
return "Use cloudflare_api_upload for this reviewed binary or multipart operation.";
|
|
99
|
+
return SAFETY.refusal(call.method, call.op.path) ?? runtime.checkServer(call.op.server) ?? runtime.refuse(call);
|
|
100
|
+
},
|
|
101
|
+
send: (call) => runtime.sendEnvelope(runtime.scope(call)).pipe(Effect.map(({ status, data }) => ({ status, data }))),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Exact pin 843eae2f: these 16 integer path parameters declare minimum: 0
|
|
2
|
+
// with exclusiveMinimum: true. Enforce the strict bound locally; the pin and
|
|
3
|
+
// compiled index remain unchanged.
|
|
4
|
+
export const EXCLUSIVE_PATH_IDS = {
|
|
5
|
+
"POST /accounts/{account_id}/cloudforce-one/v2/brand-protection/queries/{query_id}/matches/{domain_id}/dismiss": [
|
|
6
|
+
"query_id",
|
|
7
|
+
"domain_id",
|
|
8
|
+
],
|
|
9
|
+
"POST /accounts/{account_id}/cloudforce-one/v2/brand-protection/queries/{query_id}/matches/{domain_id}/undismiss": [
|
|
10
|
+
"query_id",
|
|
11
|
+
"domain_id",
|
|
12
|
+
],
|
|
13
|
+
"DELETE /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}": ["notice_id"],
|
|
14
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}": ["notice_id"],
|
|
15
|
+
"PUT /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}": ["notice_id"],
|
|
16
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}/letters": ["notice_id"],
|
|
17
|
+
"POST /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}/letters": ["notice_id"],
|
|
18
|
+
"DELETE /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}/letters/{letter_id}": [
|
|
19
|
+
"notice_id",
|
|
20
|
+
"letter_id",
|
|
21
|
+
],
|
|
22
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}/letters/{letter_id}": [
|
|
23
|
+
"notice_id",
|
|
24
|
+
"letter_id",
|
|
25
|
+
],
|
|
26
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}/letters/{letter_id}/pdf": ["notice_id", "letter_id"],
|
|
27
|
+
"DELETE /accounts/{account_id}/cloudforce-one/v2/credential-monitor/domains/{id}": ["id"],
|
|
28
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Reviewed non-JSON success media from evidence/openapi.json.
|
|
2
|
+
// Reproduce against the exact pin with scripts/audit-provider-media.mjs.
|
|
3
|
+
export const RESPONSE_MEDIA = {
|
|
4
|
+
"GET /accounts/{account_id}/access/saml_certificates/{saml_cert_set_id}/pem": ["application/x-pem-file"],
|
|
5
|
+
"GET /accounts/{account_id}/addressing/loa_documents/{loa_document_id}/download": ["application/pdf"],
|
|
6
|
+
"GET /accounts/{account_id}/ai-search/namespaces/{namespace}/instances/{id}/items/{item_id}/download": [
|
|
7
|
+
"application/octet-stream",
|
|
8
|
+
],
|
|
9
|
+
"GET /accounts/{account_id}/alerting/v3/policies/{policy_id}/email/unsubscribe": ["text/html"],
|
|
10
|
+
"POST /accounts/{account_id}/alerting/v3/policies/{policy_id}/email/unsubscribe": ["text/html"],
|
|
11
|
+
"GET /accounts/{account_id}/analytics_engine/sql": ["application/x-ndjson"],
|
|
12
|
+
"POST /accounts/{account_id}/analytics_engine/sql": ["application/x-ndjson"],
|
|
13
|
+
"GET /accounts/{account_id}/artifacts/namespaces/{namespace}/repos/{name}/blob/{hash}": ["application/octet-stream"],
|
|
14
|
+
"GET /accounts/{account_id}/artifacts/namespaces/{namespace}/repos/{name}/file": ["application/octet-stream"],
|
|
15
|
+
"GET /accounts/{account_id}/artifacts/namespaces/{namespace}/repos/{name}/raw/{ref}/{path}": [
|
|
16
|
+
"application/octet-stream",
|
|
17
|
+
"text/html",
|
|
18
|
+
"text/plain",
|
|
19
|
+
],
|
|
20
|
+
"POST /accounts/{account_id}/browser-rendering/pdf": ["application/pdf"],
|
|
21
|
+
"POST /accounts/{account_id}/browser-rendering/screenshot": ["image/jpg", "image/png", "image/webp", "text/plain"],
|
|
22
|
+
"POST /accounts/{account_id}/cloudforce-one/v2/brand-protection/letter/generate": ["application/pdf"],
|
|
23
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/brand-protection/takedown-notices/{notice_id}/letters/{letter_id}/pdf": ["application/pdf"],
|
|
24
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/collections/{collection_id}/export": [
|
|
25
|
+
"application/x-ndjson",
|
|
26
|
+
"text/csv",
|
|
27
|
+
"text/markdown",
|
|
28
|
+
],
|
|
29
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/requests/{project_type}/{request_id}/assets/{asset_id}/download": [
|
|
30
|
+
"application/octet-stream",
|
|
31
|
+
],
|
|
32
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/threat-signals/articles/{article_id}/content": [
|
|
33
|
+
"text/html",
|
|
34
|
+
"text/plain",
|
|
35
|
+
],
|
|
36
|
+
"GET /accounts/{account_id}/cloudforce-one/v2/threat-signals/feeds/{feed_id}/raw": ["application/xml", "text/plain"],
|
|
37
|
+
"GET /accounts/{account_id}/dex/commands/{command_id}/downloads/{filename}": ["application/zip"],
|
|
38
|
+
"GET /accounts/{account_id}/email/sending/messages/{message_id}": ["message/rfc822"],
|
|
39
|
+
"GET /accounts/{account_id}/images/v1/{image_id}/blob": ["image/*"],
|
|
40
|
+
"GET /accounts/{account_id}/intel/indicator-feeds/{feed_id}/data": ["text/csv"],
|
|
41
|
+
"POST /accounts/{account_id}/magic/cloud/onramps/{onramp_id}/export": ["application/zip"],
|
|
42
|
+
"GET /accounts/{account_id}/magic/cloud/resources/export": ["application/octet-stream"],
|
|
43
|
+
"GET /accounts/{account_id}/pcaps/{pcap_id}/download": ["application/vnd.tcpdump.pcap"],
|
|
44
|
+
"GET /accounts/{account_id}/queues/{queue_id}/metrics": ["text/event-stream"],
|
|
45
|
+
"GET /accounts/{account_id}/r2/buckets/{bucket_name}/objects/{object_key}": ["application/octet-stream"],
|
|
46
|
+
"GET /accounts/{account_id}/receipts/{receipt_id}/pdf": ["application/pdf"],
|
|
47
|
+
"GET /accounts/{account_id}/security-center/partners/{partner}/shadow-zones": ["text/csv"],
|
|
48
|
+
"GET /accounts/{account_id}/security-center/partners/{partner}/shadow-zones/{domain}/hosts": ["text/csv"],
|
|
49
|
+
"GET /accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{key_name}": ["application/octet-stream"],
|
|
50
|
+
"GET /accounts/{account_id}/stream/{identifier}/captions/{language}/vtt": ["text/vtt"],
|
|
51
|
+
"GET /accounts/{account_id}/stream/{identifier}/embed": ["text/html"],
|
|
52
|
+
"GET /accounts/{account_id}/urlscanner/response/{response_id}": ["text/plain"],
|
|
53
|
+
"GET /accounts/{account_id}/urlscanner/scan/{scan_id}/screenshot": ["image/png"],
|
|
54
|
+
"GET /accounts/{account_id}/urlscanner/v2/dom/{scan_id}": ["text/plain"],
|
|
55
|
+
"GET /accounts/{account_id}/urlscanner/v2/responses/{response_id}": ["text/plain"],
|
|
56
|
+
"GET /accounts/{account_id}/urlscanner/v2/screenshots/{scan_id}.png": ["image/png"],
|
|
57
|
+
"GET /accounts/{account_id}/workers/dispatch/namespaces/{dispatch_namespace}/scripts/{script_name}/content": [
|
|
58
|
+
"string",
|
|
59
|
+
],
|
|
60
|
+
"GET /accounts/{account_id}/workers/scripts/{script_name}": ["application/javascript", "multipart/form-data"],
|
|
61
|
+
"GET /accounts/{account_id}/workers/scripts/{script_name}/content/v2": ["string"],
|
|
62
|
+
"GET /accounts/{account_id}/workers/services/{service_name}/environments/{environment_name}/content": ["string"],
|
|
63
|
+
"POST /accounts/{account_id}/workers/workers/{worker_id}/versions/{version_id}/profile": [
|
|
64
|
+
"application/vnd.google.protobuf",
|
|
65
|
+
],
|
|
66
|
+
"GET /accounts/{account_id}/workflows/{workflow_name}/instances/{instance_id}/step": ["application/octet-stream"],
|
|
67
|
+
"GET /accounts/{account_tag}/analytics/sql": ["application/x-ndjson", "text/tab-separated-values"],
|
|
68
|
+
"POST /accounts/{account_tag}/analytics/sql": ["application/x-ndjson", "text/tab-separated-values"],
|
|
69
|
+
"GET /analytics/sql": ["application/x-ndjson", "text/tab-separated-values"],
|
|
70
|
+
"POST /analytics/sql": ["application/x-ndjson", "text/tab-separated-values"],
|
|
71
|
+
"GET /radar/datasets/{alias}": ["text/csv"],
|
|
72
|
+
"GET /zones/{zone_id}/dns_records/export": ["text/plain"],
|
|
73
|
+
"GET /zones/{zone_id}/security-center/partners/{partner}/shadow-hosts": ["text/csv"],
|
|
74
|
+
"GET /zones/{zone_id}/snippets/{snippet_name}/content": ["multipart/form-data"],
|
|
75
|
+
};
|