@zackbart/connecta 0.34.1 → 0.36.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 +418 -0
- package/README.md +65 -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 +2044 -1161
- 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 +751 -281
- 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 +29 -7
- package/dist/connectors/api-connector.js +145 -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/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 +227 -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 +379 -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/contract.d.ts +8 -3
- package/dist/operator-ui/generated.js +4 -4
- package/dist/operator-ui/model.d.ts +2 -3
- 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 +427 -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/kit.js +146 -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/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 +801 -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 +1023 -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/quickbooks/api.js +299 -0
- package/dist/providers/quickbooks/index.d.ts +13 -0
- package/dist/providers/quickbooks/index.js +93 -0
- package/dist/providers/quickbooks/lib/query.js +118 -0
- package/dist/providers/quickbooks/lib/writes.js +168 -0
- package/dist/providers/quickbooks/safety.js +222 -0
- package/dist/providers/quickbooks/skill.generated.js +5 -0
- package/dist/providers/quickbooks/tools.js +117 -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 +733 -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 +65 -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 +6 -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 +552 -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 -223
- 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 +9 -109
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +0 -1
- 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 +28 -7
- package/documentation/architecture.md +2409 -255
- package/documentation/auth.md +867 -114
- 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 +84 -48
- 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 +1347 -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 +30 -50
- 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/operator-ui/agents.d.ts +0 -74
- package/dist/operator-ui/agents.js +0 -104
- package/dist/operator-ui/config-summary.js +0 -565
- package/dist/operator-ui/connection-map.js +0 -376
- package/dist/operator-ui/endpoints.js +0 -221
- package/dist/operator-ui/fix-prompts.d.ts +0 -18
- package/dist/operator-ui/fix-prompts.js +0 -87
- package/dist/operator-ui/health.js +0 -52
- package/dist/operator-ui/member-page.js +0 -97
- package/dist/operator-ui/overview.js +0 -123
- package/dist/operator-ui/setup-commands.js +0 -51
- package/dist/operator-ui/view.d.ts +0 -401
- package/dist/operator-ui/view.js +0 -705
- package/dist/providers/_shared/request-token.js +0 -83
- package/dist/providers/_shared/rest/dispatch.js +0 -41
- 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/tools.js +0 -569
- 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
package/dist/routes/shared.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { AdmissionController } from "../executor-admission.js";
|
|
|
4
4
|
import type { Registry } from "../registry.js";
|
|
5
5
|
import { type ResolvedPool } from "../membership.js";
|
|
6
6
|
import type { AuthenticatedIdentity, Executor, IdentityReference, InboundAuth, InboundAuthRuntimeContext } from "../types.js";
|
|
7
|
+
import type { Logger } from "../types.js";
|
|
7
8
|
import type { ResolvedConfig } from "../config.js";
|
|
8
9
|
export { msg } from "../errors.js";
|
|
9
10
|
export interface ServerOptions {
|
|
@@ -65,7 +66,7 @@ export declare function authMetadata(request: Request, baseUrl: string, auth: re
|
|
|
65
66
|
provider: InboundAuth;
|
|
66
67
|
response: Response;
|
|
67
68
|
} | null>;
|
|
68
|
-
export declare function authorize(request: Request, baseUrl: string, auth: readonly InboundAuth[], runtimeContext?: RuntimeExecutionContext, partitionIdentity?: boolean, interactiveOnly?: boolean): Promise<{
|
|
69
|
+
export declare function authorize(request: Request, baseUrl: string, auth: readonly InboundAuth[], runtimeContext?: RuntimeExecutionContext, partitionIdentity?: boolean, interactiveOnly?: boolean, logger?: Logger): Promise<{
|
|
69
70
|
ok: true;
|
|
70
71
|
actor: ActivityActor;
|
|
71
72
|
identity: AuthenticatedIdentity;
|
|
@@ -78,14 +79,14 @@ export declare function authorize(request: Request, baseUrl: string, auth: reado
|
|
|
78
79
|
}>;
|
|
79
80
|
/**
|
|
80
81
|
* Admission at an agent endpoint, `/agent/<pool>` (#837). Only the built-in
|
|
81
|
-
*
|
|
82
|
+
* agent credential adapters are consulted: Clerk and Access never run, cookies and Clerk
|
|
82
83
|
* handshake parameters are stripped, and the runtime context, which carries
|
|
83
84
|
* Access's `ctx.access` even on a bypassed path, is never passed. Anything but
|
|
84
85
|
* an admitted declared agent gets the machine-only challenge.
|
|
85
86
|
*/
|
|
86
|
-
export declare function authorizeAgent(request: Request, baseUrl: string, auth: readonly InboundAuth[]): Promise<Awaited<ReturnType<typeof authorize>>>;
|
|
87
|
+
export declare function authorizeAgent(request: Request, baseUrl: string, auth: readonly InboundAuth[], logger?: Logger, settle?: (pending: Promise<unknown>) => void): Promise<Awaited<ReturnType<typeof authorize>>>;
|
|
87
88
|
/** Human routes reject machine credentials before any verification or storage I/O. */
|
|
88
|
-
export declare function authorizeUiIdentity(request: Request, baseUrl: string, auth: readonly InboundAuth[], purpose: string, runtimeContext?: RuntimeExecutionContext): Promise<Awaited<ReturnType<typeof authorize>>>;
|
|
89
|
+
export declare function authorizeUiIdentity(request: Request, baseUrl: string, auth: readonly InboundAuth[], purpose: string, runtimeContext?: RuntimeExecutionContext, logger?: Logger): Promise<Awaited<ReturnType<typeof authorize>>>;
|
|
89
90
|
export declare function isSameOrigin(request: Request, baseUrl: string): boolean;
|
|
90
91
|
export declare function withSecurityHeaders(response: Response, requestUrl: URL, _path: string): Response;
|
|
91
92
|
type AuthorizedIdentity = Extract<Awaited<ReturnType<typeof authorize>>, {
|
package/dist/routes/shared.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { authorizationCredential, authorizationRequest, isMachineCredential } from "../inbound-credential.js";
|
|
2
|
+
import { isVercelAgentCredential } from "../auth/vercel-agent.js";
|
|
2
3
|
import { htmlSecurityHeaders } from "../html-security.js";
|
|
3
4
|
import { isMaintainer, isMember } from "../membership.js";
|
|
4
5
|
import { identityStorageKey, validIdentityReference } from "../identity.js";
|
|
5
6
|
import { assertsAgents, isAgentName } from "../agent-identity.js";
|
|
7
|
+
import { authenticate } from "../auth-admission.js";
|
|
6
8
|
export { msg } from "../errors.js";
|
|
9
|
+
import { authCall, authFlow, authInvoke, authProgram, registerAuth } from "../auth/native.js";
|
|
10
|
+
import { runEdge } from "../runtime/run.js";
|
|
7
11
|
export function privateJson(body, init = {}) {
|
|
8
12
|
const headers = new Headers(init.headers);
|
|
9
13
|
headers.set("Content-Type", "application/json");
|
|
@@ -76,36 +80,42 @@ export async function authMetadata(request, baseUrl, auth) {
|
|
|
76
80
|
}
|
|
77
81
|
return null;
|
|
78
82
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
privateHeaders.set("Cache-Control", "no-store");
|
|
82
|
-
response = new Response(response.body, {
|
|
83
|
-
status: response.status,
|
|
84
|
-
statusText: response.statusText,
|
|
85
|
-
headers: privateHeaders,
|
|
86
|
-
});
|
|
87
|
-
if (response.status !== 401)
|
|
88
|
-
return response;
|
|
89
|
-
if (!response.headers.has("WWW-Authenticate")) {
|
|
90
|
-
const headers = new Headers(response.headers);
|
|
91
|
-
headers.set("WWW-Authenticate", refusingProvider?.challenge?.(request, baseUrl) ?? "Bearer");
|
|
92
|
-
response = new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
93
|
-
}
|
|
94
|
-
const path = new URL(request.url).pathname;
|
|
95
|
-
const pool = /^\/mcp\/([a-z0-9_-]+)$/.exec(path)?.[1];
|
|
96
|
-
const metadataRequest = new Request(new URL(`/.well-known/oauth-protected-resource${pool ? `/mcp/${pool}` : ""}`, baseUrl), { signal: request.signal });
|
|
97
|
-
const owner = await authMetadata(metadataRequest, baseUrl, auth);
|
|
98
|
-
if (!owner)
|
|
99
|
-
return response;
|
|
100
|
-
// Metadata is an ordinary bounded response, never retained across requests.
|
|
101
|
-
await owner.response.body?.cancel();
|
|
102
|
-
const challenge = owner.provider.challenge?.(request, baseUrl);
|
|
103
|
-
if (!challenge)
|
|
104
|
-
return response;
|
|
105
|
-
const headers = new Headers(response.headers);
|
|
106
|
-
headers.set("WWW-Authenticate", challenge);
|
|
107
|
-
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
83
|
+
function providerChallenge(response, request, baseUrl, auth, refusingProvider) {
|
|
84
|
+
return runEdge(authProgram(providerChallengeNative, [response, request, baseUrl, auth, refusingProvider]));
|
|
108
85
|
}
|
|
86
|
+
const providerChallengeNative = /* @__PURE__ */ registerAuth(providerChallenge, function (response, request, baseUrl, auth, refusingProvider) {
|
|
87
|
+
return authFlow(function* () {
|
|
88
|
+
const privateHeaders = new Headers(response.headers);
|
|
89
|
+
privateHeaders.set("Cache-Control", "no-store");
|
|
90
|
+
response = new Response(response.body, {
|
|
91
|
+
status: response.status,
|
|
92
|
+
statusText: response.statusText,
|
|
93
|
+
headers: privateHeaders,
|
|
94
|
+
});
|
|
95
|
+
if (response.status !== 401)
|
|
96
|
+
return response;
|
|
97
|
+
if (!response.headers.has("WWW-Authenticate")) {
|
|
98
|
+
const headers = new Headers(response.headers);
|
|
99
|
+
headers.set("WWW-Authenticate", refusingProvider?.challenge?.(request, baseUrl) ?? "Bearer");
|
|
100
|
+
response = new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
101
|
+
}
|
|
102
|
+
const path = new URL(request.url).pathname;
|
|
103
|
+
const pool = /^\/mcp\/([a-z0-9_-]+)$/.exec(path)?.[1];
|
|
104
|
+
const metadataRequest = new Request(new URL(`/.well-known/oauth-protected-resource${pool ? `/mcp/${pool}` : ""}`, baseUrl), { signal: request.signal });
|
|
105
|
+
const owner = (yield authCall(authMetadata, [metadataRequest, baseUrl, auth]));
|
|
106
|
+
if (!owner)
|
|
107
|
+
return response;
|
|
108
|
+
// Metadata is an ordinary bounded response, never retained across requests.
|
|
109
|
+
if (owner.response.body)
|
|
110
|
+
yield authInvoke(owner.response.body, "cancel", []);
|
|
111
|
+
const challenge = owner.provider.challenge?.(request, baseUrl);
|
|
112
|
+
if (!challenge)
|
|
113
|
+
return response;
|
|
114
|
+
const headers = new Headers(response.headers);
|
|
115
|
+
headers.set("WWW-Authenticate", challenge);
|
|
116
|
+
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
117
|
+
});
|
|
118
|
+
});
|
|
109
119
|
function recognizedProvider(request, auth, runtimeContext) {
|
|
110
120
|
for (const provider of auth) {
|
|
111
121
|
if (!provider.recognizesCredential)
|
|
@@ -122,123 +132,158 @@ function recognizedProvider(request, auth, runtimeContext) {
|
|
|
122
132
|
}
|
|
123
133
|
return undefined;
|
|
124
134
|
}
|
|
125
|
-
export
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// Every caller of this function is a human route. Agents reach pools only at
|
|
146
|
-
// `/agent/<pool>` (#837), so a `cta_` token refuses here without consulting
|
|
147
|
-
// token storage, and never falls back to a cookie, session, or Access context.
|
|
148
|
-
if (machineCredential) {
|
|
149
|
-
return {
|
|
150
|
-
ok: false,
|
|
151
|
-
response: await providerChallenge(privateJson({ error: "unauthorized" }, {
|
|
152
|
-
status: 401,
|
|
153
|
-
headers: { "WWW-Authenticate": "Bearer" },
|
|
154
|
-
}), request, baseUrl, auth),
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
if (auth.length === 0 && !interactiveOnly && !explicit) {
|
|
158
|
-
const actor = { kind: "anonymous" };
|
|
159
|
-
const identity = { actor, interactive: false };
|
|
160
|
-
return { ok: true, actor, identity };
|
|
161
|
-
}
|
|
162
|
-
// The built-in agent adapter answers only agent endpoints. A deployment
|
|
163
|
-
// whose only provider is that adapter still refuses here, never opens.
|
|
164
|
-
const humanAuth = auth.filter((provider) => !assertsAgents(provider));
|
|
165
|
-
let recognized;
|
|
166
|
-
try {
|
|
167
|
-
recognized = recognizedProvider(request, humanAuth, runtimeContext);
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
return { ok: false, response: privateJson({ error: "credential recognition failed" }, { status: 403 }) };
|
|
171
|
-
}
|
|
172
|
-
if (interactiveOnly && recognized && !recognized.interactiveOperator) {
|
|
173
|
-
return { ok: false, response: privateJson({ error: "authenticated user required" }, { status: 403 }) };
|
|
174
|
-
}
|
|
175
|
-
let lastResponse = null;
|
|
176
|
-
const eligible = humanAuth.filter((provider) => (!interactiveOnly || provider.interactiveOperator) &&
|
|
177
|
-
(!explicit || provider.kind !== "access_token" || !provider.recognizesCredential));
|
|
178
|
-
// A header owns one verdict even for adapters without a recognition hook.
|
|
179
|
-
const candidates = recognized ? [recognized] : explicit ? eligible.slice(0, 1) : eligible;
|
|
180
|
-
for (const provider of candidates) {
|
|
181
|
-
const result = await provider.authorize(request, baseUrl, runtimeContext);
|
|
182
|
-
// Only the built-in access-token adapter asserts an agent, and it never
|
|
183
|
-
// answers here. Any `agent` claim refuses like an unknown token.
|
|
184
|
-
const agent = result.ok ? result.agent : undefined;
|
|
185
|
-
if (result.ok && agent !== undefined) {
|
|
186
|
-
lastResponse = privateJson({ error: "unauthorized" }, {
|
|
187
|
-
status: 401,
|
|
188
|
-
headers: { "WWW-Authenticate": "Bearer" },
|
|
189
|
-
});
|
|
190
|
-
break;
|
|
191
|
-
}
|
|
192
|
-
if (result.ok) {
|
|
193
|
-
if (interactiveOnly && !result.userId) {
|
|
194
|
-
return { ok: false, response: privateJson({ error: "authenticated user required" }, { status: 403 }) };
|
|
195
|
-
}
|
|
196
|
-
const subjectId = result.subjectId ?? result.userId;
|
|
197
|
-
const actorNamespace = activityActorNamespace(provider);
|
|
198
|
-
const derivedPrincipal = result.userId && actorNamespace ? { namespace: actorNamespace, id: result.userId } : undefined;
|
|
199
|
-
const principal = validIdentityReference(result.principal) ? result.principal : derivedPrincipal;
|
|
200
|
-
const subject = subjectId
|
|
201
|
-
? { namespace: actorNamespace ?? `connecta:auth:${provider.kind}`, id: subjectId }
|
|
202
|
-
: principal;
|
|
203
|
-
const interactive = Boolean(result.userId && provider.interactiveOperator);
|
|
204
|
-
// Principal-only API callers still need a stable typed actor for history
|
|
205
|
-
// ownership. Never collapse distinct personal partitions into { kind }.
|
|
206
|
-
const actorId = agent ?? subjectId ?? principal?.id;
|
|
207
|
-
const recordNamespace = actorNamespace ?? (subjectId === undefined ? principal?.namespace : undefined);
|
|
208
|
-
const actor = {
|
|
209
|
-
kind: provider.kind,
|
|
210
|
-
...(actorId ? { id: actorId } : {}),
|
|
211
|
-
...(actorId && recordNamespace ? { namespace: recordNamespace } : {}),
|
|
212
|
-
};
|
|
213
|
-
const identity = {
|
|
214
|
-
actor,
|
|
215
|
-
...(subject ? { subject } : {}),
|
|
216
|
-
...(principal ? { principal } : {}),
|
|
217
|
-
...(agent !== undefined ? { agent } : {}),
|
|
218
|
-
interactive,
|
|
135
|
+
export function authorize(request, baseUrl, auth, runtimeContext, partitionIdentity = true, interactiveOnly = false, logger = console) {
|
|
136
|
+
return runEdge(authProgram(authorizeNative, [request, baseUrl, auth, runtimeContext, partitionIdentity, interactiveOnly, logger]));
|
|
137
|
+
}
|
|
138
|
+
const authorizeNative = /* @__PURE__ */ registerAuth(authorize, function (request, baseUrl, auth, runtimeContext, partitionIdentity = true, interactiveOnly = false, logger = console) {
|
|
139
|
+
return authFlow(function* () {
|
|
140
|
+
const credential = authorizationCredential(request);
|
|
141
|
+
const explicit = credential.kind !== "absent";
|
|
142
|
+
if (credential.kind === "invalid") {
|
|
143
|
+
const challenge = auth.find((provider) => !assertsAgents(provider))?.challenge?.(request, baseUrl) ?? "Bearer";
|
|
144
|
+
return {
|
|
145
|
+
ok: false,
|
|
146
|
+
response: (yield authCall(providerChallenge, [
|
|
147
|
+
privateJson({ error: "unauthorized" }, {
|
|
148
|
+
status: 401,
|
|
149
|
+
headers: { "WWW-Authenticate": challenge },
|
|
150
|
+
}),
|
|
151
|
+
request,
|
|
152
|
+
baseUrl,
|
|
153
|
+
auth,
|
|
154
|
+
])),
|
|
219
155
|
};
|
|
156
|
+
}
|
|
157
|
+
request = authorizationRequest(request);
|
|
158
|
+
if (explicit && runtimeContext)
|
|
159
|
+
runtimeContext = { waitUntil: runtimeContext.waitUntil.bind(runtimeContext) };
|
|
160
|
+
const machineCredential = isMachineCredential(request) || isVercelAgentCredential(request);
|
|
161
|
+
if (interactiveOnly && machineCredential) {
|
|
162
|
+
return { ok: false, response: privateJson({ error: "authenticated user required" }, { status: 403 }) };
|
|
163
|
+
}
|
|
164
|
+
// Every caller of this function is a human route. Agents reach pools only at
|
|
165
|
+
// `/agent/<pool>` (#837), so a workload or `cta_` credential refuses here
|
|
166
|
+
// without verification, and never falls back to a cookie, session or Access context.
|
|
167
|
+
if (machineCredential) {
|
|
220
168
|
return {
|
|
221
|
-
ok:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
169
|
+
ok: false,
|
|
170
|
+
response: (yield authCall(providerChallenge, [
|
|
171
|
+
privateJson({ error: "unauthorized" }, {
|
|
172
|
+
status: 401,
|
|
173
|
+
headers: { "WWW-Authenticate": "Bearer" },
|
|
174
|
+
}),
|
|
175
|
+
request,
|
|
176
|
+
baseUrl,
|
|
177
|
+
auth,
|
|
178
|
+
])),
|
|
227
179
|
};
|
|
228
180
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
181
|
+
if (auth.length === 0 && !interactiveOnly && !explicit) {
|
|
182
|
+
const actor = { kind: "anonymous" };
|
|
183
|
+
const identity = { actor, interactive: false };
|
|
184
|
+
return { ok: true, actor, identity };
|
|
185
|
+
}
|
|
186
|
+
// The built-in agent adapter answers only agent endpoints. A deployment
|
|
187
|
+
// whose only provider is that adapter still refuses here, never opens.
|
|
188
|
+
const humanAuth = auth.filter((provider) => !assertsAgents(provider));
|
|
189
|
+
let recognized;
|
|
190
|
+
try {
|
|
191
|
+
recognized = recognizedProvider(request, humanAuth, runtimeContext);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return { ok: false, response: privateJson({ error: "credential recognition failed" }, { status: 403 }) };
|
|
195
|
+
}
|
|
196
|
+
if (interactiveOnly && recognized && !recognized.interactiveOperator) {
|
|
197
|
+
return { ok: false, response: privateJson({ error: "authenticated user required" }, { status: 403 }) };
|
|
198
|
+
}
|
|
199
|
+
let lastResponse = null;
|
|
200
|
+
const eligible = humanAuth.filter((provider) => (!interactiveOnly || provider.interactiveOperator) &&
|
|
201
|
+
(!explicit || provider.kind !== "access_token" || !provider.recognizesCredential));
|
|
202
|
+
// A header owns one verdict even for adapters without a recognition hook.
|
|
203
|
+
const candidates = recognized ? [recognized] : explicit ? eligible.slice(0, 1) : eligible;
|
|
204
|
+
for (const provider of candidates) {
|
|
205
|
+
const admission = (yield authCall(authenticate, [
|
|
206
|
+
provider,
|
|
207
|
+
request,
|
|
208
|
+
baseUrl,
|
|
209
|
+
runtimeContext,
|
|
210
|
+
logger,
|
|
211
|
+
runtimeContext?.waitUntil.bind(runtimeContext),
|
|
212
|
+
]));
|
|
213
|
+
if (!admission.admitted)
|
|
214
|
+
return { ok: false, response: admission.response };
|
|
215
|
+
const result = admission.result;
|
|
216
|
+
// Only built-in agent credential adapters assert an agent, and they never
|
|
217
|
+
// answer here. Any `agent` claim refuses like an unknown token.
|
|
218
|
+
const agent = result.ok ? result.agent : undefined;
|
|
219
|
+
if (result.ok && agent !== undefined) {
|
|
220
|
+
lastResponse = privateJson({ error: "unauthorized" }, {
|
|
221
|
+
status: 401,
|
|
222
|
+
headers: { "WWW-Authenticate": "Bearer" },
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
if (result.ok) {
|
|
227
|
+
if (interactiveOnly && !result.userId) {
|
|
228
|
+
return { ok: false, response: privateJson({ error: "authenticated user required" }, { status: 403 }) };
|
|
229
|
+
}
|
|
230
|
+
const subjectId = result.subjectId ?? result.userId;
|
|
231
|
+
const actorNamespace = activityActorNamespace(provider);
|
|
232
|
+
const derivedPrincipal = result.userId && actorNamespace ? { namespace: actorNamespace, id: result.userId } : undefined;
|
|
233
|
+
const principal = validIdentityReference(result.principal) ? result.principal : derivedPrincipal;
|
|
234
|
+
const subject = subjectId
|
|
235
|
+
? { namespace: actorNamespace ?? `connecta:auth:${provider.kind}`, id: subjectId }
|
|
236
|
+
: principal;
|
|
237
|
+
const interactive = Boolean(result.userId && provider.interactiveOperator);
|
|
238
|
+
// Principal-only API callers still need a stable typed actor for history
|
|
239
|
+
// ownership. Never collapse distinct personal partitions into { kind }.
|
|
240
|
+
const actorId = agent ?? subjectId ?? principal?.id;
|
|
241
|
+
const recordNamespace = actorNamespace ?? (subjectId === undefined ? principal?.namespace : undefined);
|
|
242
|
+
const actor = {
|
|
243
|
+
kind: provider.kind,
|
|
244
|
+
...(actorId ? { id: actorId } : {}),
|
|
245
|
+
...(actorId && recordNamespace ? { namespace: recordNamespace } : {}),
|
|
246
|
+
};
|
|
247
|
+
const identity = {
|
|
248
|
+
actor,
|
|
249
|
+
...(subject ? { subject } : {}),
|
|
250
|
+
...(principal ? { principal } : {}),
|
|
251
|
+
...(agent !== undefined ? { agent } : {}),
|
|
252
|
+
interactive,
|
|
253
|
+
};
|
|
254
|
+
return {
|
|
255
|
+
ok: true,
|
|
256
|
+
actor,
|
|
257
|
+
identity,
|
|
258
|
+
...(result.sessionCookies?.length ? { sessionCookies: result.sessionCookies } : {}),
|
|
259
|
+
...(subject && partitionIdentity
|
|
260
|
+
? { subjectKey: (yield authCall(identityStorageKey, [subject])) }
|
|
261
|
+
: {}),
|
|
262
|
+
...(principal && partitionIdentity
|
|
263
|
+
? { principalKey: (yield authCall(identityStorageKey, [principal])) }
|
|
264
|
+
: {}),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
lastResponse = result.response;
|
|
268
|
+
if (recognized || result.response.status !== 401)
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
ok: false,
|
|
273
|
+
response: (yield authCall(providerChallenge, [
|
|
274
|
+
lastResponse ??
|
|
275
|
+
privateJson({ error: "unauthorized" }, {
|
|
276
|
+
status: 401,
|
|
277
|
+
headers: { "WWW-Authenticate": "Bearer" },
|
|
278
|
+
}),
|
|
279
|
+
request,
|
|
280
|
+
baseUrl,
|
|
281
|
+
auth,
|
|
282
|
+
explicit ? candidates[0] : undefined,
|
|
283
|
+
])),
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
});
|
|
242
287
|
/** The machine-only challenge: Bearer, with no authorization server to discover. */
|
|
243
288
|
function agentChallenge() {
|
|
244
289
|
return {
|
|
@@ -248,49 +293,71 @@ function agentChallenge() {
|
|
|
248
293
|
}
|
|
249
294
|
/**
|
|
250
295
|
* Admission at an agent endpoint, `/agent/<pool>` (#837). Only the built-in
|
|
251
|
-
*
|
|
296
|
+
* agent credential adapters are consulted: Clerk and Access never run, cookies and Clerk
|
|
252
297
|
* handshake parameters are stripped, and the runtime context, which carries
|
|
253
298
|
* Access's `ctx.access` even on a bypassed path, is never passed. Anything but
|
|
254
299
|
* an admitted declared agent gets the machine-only challenge.
|
|
255
300
|
*/
|
|
256
|
-
export
|
|
257
|
-
|
|
258
|
-
if (!provider || !isMachineCredential(request))
|
|
259
|
-
return agentChallenge();
|
|
260
|
-
let result;
|
|
261
|
-
try {
|
|
262
|
-
result = await provider.authorize(authorizationRequest(request), baseUrl, undefined);
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
return agentChallenge();
|
|
266
|
-
}
|
|
267
|
-
if (!result.ok) {
|
|
268
|
-
void result.response.body?.cancel().catch(() => { });
|
|
269
|
-
return agentChallenge();
|
|
270
|
-
}
|
|
271
|
-
const { agent } = result;
|
|
272
|
-
if (!isAgentName(agent) || result.userId !== undefined || result.principal !== undefined)
|
|
273
|
-
return agentChallenge();
|
|
274
|
-
const namespace = activityActorNamespace(provider);
|
|
275
|
-
const subject = { namespace: namespace ?? `connecta:auth:${provider.kind}`, id: result.subjectId ?? agent };
|
|
276
|
-
const actor = { kind: provider.kind, id: agent, ...(namespace ? { namespace } : {}) };
|
|
277
|
-
return {
|
|
278
|
-
ok: true,
|
|
279
|
-
actor,
|
|
280
|
-
identity: { actor, subject, agent, interactive: false },
|
|
281
|
-
subjectKey: await identityStorageKey(subject),
|
|
282
|
-
};
|
|
301
|
+
export function authorizeAgent(request, baseUrl, auth, logger = console, settle) {
|
|
302
|
+
return runEdge(authProgram(authorizeAgentNative, [request, baseUrl, auth, logger, settle]));
|
|
283
303
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
304
|
+
const authorizeAgentNative = /* @__PURE__ */ registerAuth(authorizeAgent, function (request, baseUrl, auth, logger = console, settle) {
|
|
305
|
+
return authFlow(function* () {
|
|
306
|
+
const provider = auth.find((candidate) => assertsAgents(candidate) && candidate.recognizesCredential?.(request) === true);
|
|
307
|
+
if (!provider)
|
|
308
|
+
return agentChallenge();
|
|
309
|
+
let result;
|
|
310
|
+
try {
|
|
311
|
+
const admission = (yield authCall(authenticate, [
|
|
312
|
+
provider,
|
|
313
|
+
authorizationRequest(request),
|
|
314
|
+
baseUrl,
|
|
315
|
+
undefined,
|
|
316
|
+
logger,
|
|
317
|
+
settle,
|
|
318
|
+
]));
|
|
319
|
+
if (!admission.admitted)
|
|
320
|
+
return { ok: false, response: admission.response };
|
|
321
|
+
result = admission.result;
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
return agentChallenge();
|
|
325
|
+
}
|
|
326
|
+
if (!result.ok) {
|
|
327
|
+
if (result.response.status === 503)
|
|
328
|
+
return result;
|
|
329
|
+
void result.response.body?.cancel().catch(() => { });
|
|
330
|
+
return agentChallenge();
|
|
331
|
+
}
|
|
332
|
+
const { agent } = result;
|
|
333
|
+
if (!isAgentName(agent) || result.userId !== undefined || result.principal !== undefined)
|
|
334
|
+
return agentChallenge();
|
|
335
|
+
const namespace = activityActorNamespace(provider);
|
|
336
|
+
const subject = { namespace: namespace ?? `connecta:auth:${provider.kind}`, id: result.subjectId ?? agent };
|
|
337
|
+
const actor = { kind: provider.kind, id: agent, ...(namespace ? { namespace } : {}) };
|
|
287
338
|
return {
|
|
288
|
-
ok:
|
|
289
|
-
|
|
339
|
+
ok: true,
|
|
340
|
+
actor,
|
|
341
|
+
identity: { actor, subject, agent, interactive: false },
|
|
342
|
+
subjectKey: (yield authCall(identityStorageKey, [subject])),
|
|
290
343
|
};
|
|
291
|
-
}
|
|
292
|
-
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
/** Human routes reject machine credentials before any verification or storage I/O. */
|
|
347
|
+
export function authorizeUiIdentity(request, baseUrl, auth, purpose, runtimeContext, logger = console) {
|
|
348
|
+
return runEdge(authProgram(authorizeUiIdentityNative, [request, baseUrl, auth, purpose, runtimeContext, logger]));
|
|
293
349
|
}
|
|
350
|
+
const authorizeUiIdentityNative = /* @__PURE__ */ registerAuth(authorizeUiIdentity, function (request, baseUrl, auth, purpose, runtimeContext, logger = console) {
|
|
351
|
+
return authFlow(function* () {
|
|
352
|
+
if (!auth.some((provider) => provider.interactiveOperator)) {
|
|
353
|
+
return {
|
|
354
|
+
ok: false,
|
|
355
|
+
response: privateJson({ error: `${purpose} requires interactive user authentication` }, { status: 403 }),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
return (yield authCall(authorize, [request, baseUrl, auth, runtimeContext, true, true, logger]));
|
|
359
|
+
});
|
|
360
|
+
});
|
|
294
361
|
export function isSameOrigin(request, baseUrl) {
|
|
295
362
|
const origin = request.headers.get("origin");
|
|
296
363
|
if (!origin)
|
package/dist/routes/skills.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { upwardStep } from "../upward.js";
|
|
2
|
+
import { authCall, authInvoke, authFlow, authMethod } from "../auth/native.js";
|
|
1
3
|
import { ProtocolError } from "@modelcontextprotocol/server";
|
|
2
|
-
import
|
|
4
|
+
import * as z from "zod";
|
|
3
5
|
import { ConnectorCallError } from "../errors.js";
|
|
4
6
|
import { SkillsRegistry } from "../skills.js";
|
|
5
7
|
/** Native Skills methods use the same request-view registry as both text readers. */
|
|
@@ -11,9 +13,9 @@ export function registerSkills(server, view, baseUrl, options) {
|
|
|
11
13
|
const listParams = z.object({ cursor: z.string().max(128).optional() });
|
|
12
14
|
const getParams = z.object({ uri: z.string().min(1).max(32_768).startsWith("skill://") });
|
|
13
15
|
const result = z.record(z.string(), z.unknown());
|
|
14
|
-
const safely =
|
|
16
|
+
const safely = authMethod((read) => authFlow(function* () {
|
|
15
17
|
try {
|
|
16
|
-
return
|
|
18
|
+
return yield* upwardStep(authCall(read, []));
|
|
17
19
|
}
|
|
18
20
|
catch (error) {
|
|
19
21
|
if (error instanceof ConnectorCallError && (error.code === "not_found" || error.code === "invalid_args")) {
|
|
@@ -22,9 +24,9 @@ export function registerSkills(server, view, baseUrl, options) {
|
|
|
22
24
|
// No raw downstream cause can become an SDK/operator diagnostic.
|
|
23
25
|
throw new ProtocolError(-32603, "Skills are unavailable.");
|
|
24
26
|
}
|
|
25
|
-
};
|
|
26
|
-
server.server.setRequestHandler("skills/list", { params: listParams, result }, (params) => safely(() => registry
|
|
27
|
-
server.server.setRequestHandler("skills/get", { params: getParams, result }, (params) => safely(() => registry
|
|
28
|
-
server.server.setRequestHandler("resources/list", { params: listParams, result }, (params) => safely(() => registry
|
|
29
|
-
server.server.setRequestHandler("resources/read", { params: getParams, result }, (params) => safely(() => registry
|
|
27
|
+
}));
|
|
28
|
+
server.server.setRequestHandler("skills/list", { params: listParams, result }, (params) => safely(authMethod(() => authInvoke(registry, "list", [params.cursor]))));
|
|
29
|
+
server.server.setRequestHandler("skills/get", { params: getParams, result }, (params) => safely(authMethod(() => authInvoke(registry, "get", [params.uri]))));
|
|
30
|
+
server.server.setRequestHandler("resources/list", { params: listParams, result }, (params) => safely(authMethod(() => authInvoke(registry, "resources", [params.cursor]))));
|
|
31
|
+
server.server.setRequestHandler("resources/read", { params: getParams, result }, (params) => safely(authMethod(() => authInvoke(registry, "read", [params.uri]))));
|
|
30
32
|
}
|
package/dist/routes/ui-config.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { agentDescriptions } from "../agent-description.js";
|
|
2
|
+
import { readAgentAdmission } from "../agent-observation.js";
|
|
1
3
|
// `GET /ui/api/config`: operator contract v2 (#837, decisions/0006), the
|
|
2
4
|
// operator page's only gate. A maintainer gets the unfiltered view; a human
|
|
3
5
|
// pool member gets exactly their own projection; anyone else gets the private
|
|
@@ -167,7 +169,9 @@ function scanActivity(context, authz, registry, rows, agents) {
|
|
|
167
169
|
// A last call is a call; any row recorded for an agent, a catalog
|
|
168
170
|
// refresh included, is a sign it was seen.
|
|
169
171
|
const row = event.kind !== "catalog_drift" && OUTCOMES.has(event.outcome) ? byId.get(event.connectorId) : undefined;
|
|
170
|
-
const agent = event.actor.kind === "access_token"
|
|
172
|
+
const agent = (event.actor.kind === "access_token" || event.actor.kind === "vercel_oidc") &&
|
|
173
|
+
event.actor.namespace === AGENT_NAMESPACE &&
|
|
174
|
+
event.actor.id
|
|
171
175
|
? byAgent.get(event.actor.id)
|
|
172
176
|
: undefined;
|
|
173
177
|
if ((!row && !agent) || !activityEventVisible(context, authz, registry, event))
|
|
@@ -376,19 +380,37 @@ function maintainerRead(context, authz) {
|
|
|
376
380
|
humanPath: `/mcp/${name}`,
|
|
377
381
|
agentPath: `/agent/${name}`,
|
|
378
382
|
readOnly: pool.readOnly,
|
|
383
|
+
surface: pool.native ? "native" : "meta",
|
|
384
|
+
executeCode: pool.native?.executeCode !== false,
|
|
379
385
|
owner: ownersVisible ? (pool.owner ?? null) : null,
|
|
380
386
|
tools: grants(pool.access, allIds),
|
|
381
387
|
members: pool.members.map((member) => member.kind === "agent" ? { kind: "agent", name: member.name } : human(member)),
|
|
382
388
|
}));
|
|
383
|
-
const
|
|
389
|
+
const tokenSlots = new Map(slots.map(({ name, ...token }) => [name, token]));
|
|
390
|
+
if (opts.config.accessTokens && opts.config.agents.some((name) => !tokenSlots.has(name))) {
|
|
391
|
+
return yield* refuse("agent token slots could not be read", 503);
|
|
392
|
+
}
|
|
393
|
+
const agents = agentDescriptions(opts.config).map(({ name, credentialTypes }) => ({
|
|
384
394
|
name,
|
|
395
|
+
credentialTypes: [...credentialTypes],
|
|
385
396
|
pools: [...opts.pools]
|
|
386
397
|
.filter(([, pool]) => pool.members.some((member) => member.kind === "agent" && member.name === name))
|
|
387
398
|
.map(([pool]) => pool),
|
|
388
|
-
token,
|
|
399
|
+
token: tokenSlots.get(name) ?? null,
|
|
389
400
|
lastSeenAt: null,
|
|
390
401
|
}));
|
|
391
402
|
const activity = yield* scanActivity(context, authz, registry, rows, agents);
|
|
403
|
+
let admissionsVisible = readsActivity(opts, authz) && activity !== "forbidden";
|
|
404
|
+
// A configured read gate still applies when the history store has no list.
|
|
405
|
+
if (admissionsVisible && activity === "unconfigured" && opts.config.activity?.readGate) {
|
|
406
|
+
admissionsVisible = yield* bounded(context, () => attempt(async () => (await opts.config.activity.readGate(authz.actor)) === true), () => Effect.succeed(false));
|
|
407
|
+
}
|
|
408
|
+
if (admissionsVisible) {
|
|
409
|
+
yield* bounded(context, () => Effect.forEach(agents, (agent) => readAgentAdmission(opts.config.storage, agent.name).pipe(Effect.catch(() => Effect.succeed(null)), Effect.map((at) => {
|
|
410
|
+
if (at && (!agent.lastSeenAt || at > agent.lastSeenAt))
|
|
411
|
+
agent.lastSeenAt = at;
|
|
412
|
+
})), { concurrency: resolveDiscoveryConcurrency(opts.config.discovery.concurrency) }), () => Effect.succeed(undefined));
|
|
413
|
+
}
|
|
392
414
|
const matrix = yield* matrixFor(context, visible, rows, ownersVisible);
|
|
393
415
|
const contract = {
|
|
394
416
|
schemaVersion: 2,
|
|
@@ -533,6 +555,8 @@ function memberRead(context, authz, pools) {
|
|
|
533
555
|
humanPath: `/mcp/${name}`,
|
|
534
556
|
agentPath: `/agent/${name}`,
|
|
535
557
|
readOnly: pool.readOnly,
|
|
558
|
+
surface: pool.native ? "native" : "meta",
|
|
559
|
+
executeCode: pool.native?.executeCode !== false,
|
|
536
560
|
owner: null,
|
|
537
561
|
tools: grants(pool.access, allIds),
|
|
538
562
|
members: [],
|