@adcp/sdk 6.9.0 → 6.10.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/bin/adcp.js +285 -5
- package/compliance/cache/3.0.6.previous/domains/brand/index.yaml +163 -0
- package/compliance/cache/3.0.6.previous/domains/creative/index.yaml +412 -0
- package/compliance/cache/3.0.6.previous/domains/governance/index.yaml +683 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/creative-reception.yaml +247 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/index.yaml +769 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/create_media_buy_async.yaml +232 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +414 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/delivery_reporting.yaml +205 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_approved.yaml +211 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_conditions.yaml +196 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_denied.yaml +192 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_denied_recovery.yaml +244 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/invalid_transitions.yaml +284 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/inventory_list_no_match.yaml +143 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/inventory_list_targeting.yaml +271 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/measurement_terms_rejected.yaml +195 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/pending_creatives_to_start.yaml +250 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/proposal_finalize.yaml +243 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.0.6.previous/domains/signals/index.yaml +266 -0
- package/compliance/cache/3.0.6.previous/domains/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.0.6.previous/index.json +324 -0
- package/compliance/cache/3.0.6.previous/protocols/brand/index.yaml +163 -0
- package/compliance/cache/3.0.6.previous/protocols/creative/index.yaml +412 -0
- package/compliance/cache/3.0.6.previous/protocols/governance/index.yaml +683 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/creative-reception.yaml +247 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/index.yaml +769 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/create_media_buy_async.yaml +232 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +414 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/delivery_reporting.yaml +205 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_approved.yaml +211 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_conditions.yaml +196 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_denied.yaml +192 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_denied_recovery.yaml +244 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/invalid_transitions.yaml +284 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/inventory_list_no_match.yaml +143 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/inventory_list_targeting.yaml +271 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +195 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +250 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/proposal_finalize.yaml +243 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.0.6.previous/protocols/signals/index.yaml +266 -0
- package/compliance/cache/3.0.6.previous/protocols/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.0.6.previous/specialisms/audience-sync/index.yaml +280 -0
- package/compliance/cache/3.0.6.previous/specialisms/brand-rights/index.yaml +350 -0
- package/compliance/cache/3.0.6.previous/specialisms/brand-rights/scenarios/governance_denied.yaml +204 -0
- package/compliance/cache/3.0.6.previous/specialisms/collection-lists/index.yaml +359 -0
- package/compliance/cache/3.0.6.previous/specialisms/content-standards/index.yaml +572 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-ad-server/index.yaml +383 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-generative/generative-seller.yaml +758 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-generative/index.yaml +746 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-template/index.yaml +413 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-aware-seller/index.yaml +136 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-delivery-monitor/index.yaml +441 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-spend-authority/denied.yaml +221 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-spend-authority/index.yaml +330 -0
- package/compliance/cache/3.0.6.previous/specialisms/property-lists/index.yaml +482 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-broadcast-tv/index.yaml +689 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-catalog-driven/index.yaml +779 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-guaranteed/index.yaml +504 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-non-guaranteed/index.yaml +428 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-proposal-mode/index.yaml +520 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-social/index.yaml +584 -0
- package/compliance/cache/3.0.6.previous/specialisms/signal-marketplace/index.yaml +415 -0
- package/compliance/cache/3.0.6.previous/specialisms/signal-marketplace/scenarios/governance_denied.yaml +207 -0
- package/compliance/cache/3.0.6.previous/specialisms/signal-owned/index.yaml +316 -0
- package/compliance/cache/3.0.6.previous/test-kits/acme-outdoor.yaml +210 -0
- package/compliance/cache/3.0.6.previous/test-kits/bistro-oranje.yaml +126 -0
- package/compliance/cache/3.0.6.previous/test-kits/nova-motors.yaml +262 -0
- package/compliance/cache/3.0.6.previous/test-kits/osei-natural.yaml +126 -0
- package/compliance/cache/3.0.6.previous/test-kits/signed-requests-runner.yaml +155 -0
- package/compliance/cache/3.0.6.previous/test-kits/substitution-observer-runner.yaml +690 -0
- package/compliance/cache/3.0.6.previous/test-kits/summit-foods.yaml +125 -0
- package/compliance/cache/3.0.6.previous/test-kits/webhook-receiver-runner.yaml +265 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/001-minimal-plan.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/002-full-plan.json +217 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/003-bookkeeping-stripped.json +60 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/004a-human-review-omitted.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/004b-human-review-explicit-null.json +49 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/005a-policy-categories-order-1.json +53 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/005b-policy-categories-order-2.json +57 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/006a-ext-trace-v1.json +49 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/006b-ext-trace-v2.json +53 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/007-unicode-objectives.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/008-numeric-canonicalization.json +65 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/README.md +219 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/canonicalization.json +241 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/keys.json +60 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/001-no-signature-header.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/002-wrong-tag.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/003-expired-signature.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/004-window-too-long.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/005-alg-not-allowed.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/006-missing-covered-component.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/007-missing-content-digest.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/008-unknown-keyid.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/010-content-digest-mismatch.json +33 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/011-malformed-header.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/013-expires-le-created.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/014-missing-nonce-param.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/015-signature-invalid.json +28 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/016-replayed-nonce.json +35 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/017-key-revoked.json +38 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +28 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/019-signature-without-signature-input.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/020-rate-abuse.json +34 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/022-multi-valued-content-type.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +32 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/024-unquoted-string-param.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/026-non-ascii-host.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +25 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/001-basic-post.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/002-post-with-content-digest.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/003-es256-post.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/004-multiple-signature-labels.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/005-default-port-stripped.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/006-dot-segment-path.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/007-query-byte-preserved.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/008-percent-encoded-path.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/011-ipv6-authority.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/README.md +211 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/keys.json +61 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/001-wrong-tag.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/002-expired-signature.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/003-window-too-long.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/005-missing-authority-component.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/006-missing-content-digest.json +25 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/007-unknown-keyid.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/011-signature-without-input.json +25 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/013-expires-le-created.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/015-signature-invalid.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/016-replayed-nonce.json +37 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/017-key-revoked.json +32 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/018-rate-abuse.json +33 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/019-revocation-stale.json +32 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +41 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/001-basic-post.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/002-es256-post.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/004-default-port-stripped.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +25 -0
- package/compliance/cache/3.0.6.previous/universal/capability-discovery.yaml +125 -0
- package/compliance/cache/3.0.6.previous/universal/collection-lists-pagination-integrity.yaml +306 -0
- package/compliance/cache/3.0.6.previous/universal/content-standards-pagination-integrity.yaml +326 -0
- package/compliance/cache/3.0.6.previous/universal/deterministic-testing.yaml +1343 -0
- package/compliance/cache/3.0.6.previous/universal/error-compliance.yaml +474 -0
- package/compliance/cache/3.0.6.previous/universal/fictional-entities.yaml +307 -0
- package/compliance/cache/3.0.6.previous/universal/get-media-buys-pagination-integrity.yaml +160 -0
- package/compliance/cache/3.0.6.previous/universal/get-signals-pagination-integrity.yaml +211 -0
- package/compliance/cache/3.0.6.previous/universal/idempotency.yaml +593 -0
- package/compliance/cache/3.0.6.previous/universal/pagination-integrity-creative-formats.yaml +258 -0
- package/compliance/cache/3.0.6.previous/universal/pagination-integrity-list-accounts.yaml +262 -0
- package/compliance/cache/3.0.6.previous/universal/pagination-integrity.yaml +263 -0
- package/compliance/cache/3.0.6.previous/universal/property-lists-pagination-integrity.yaml +307 -0
- package/compliance/cache/3.0.6.previous/universal/runner-output-contract.yaml +358 -0
- package/compliance/cache/3.0.6.previous/universal/schema-validation.yaml +526 -0
- package/compliance/cache/3.0.6.previous/universal/security.yaml +431 -0
- package/compliance/cache/3.0.6.previous/universal/signed-requests.yaml +205 -0
- package/compliance/cache/3.0.6.previous/universal/storyboard-schema.yaml +1176 -0
- package/compliance/cache/3.0.6.previous/universal/v3-envelope-integrity.yaml +106 -0
- package/compliance/cache/3.0.6.previous/universal/webhook-emission.yaml +337 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.ts +33 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +127 -1
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/credential-policy.d.ts +221 -0
- package/dist/lib/server/credential-policy.d.ts.map +1 -0
- package/dist/lib/server/credential-policy.js +260 -0
- package/dist/lib/server/credential-policy.js.map +1 -0
- package/dist/lib/server/dynamic-registry.d.ts +219 -0
- package/dist/lib/server/dynamic-registry.d.ts.map +1 -0
- package/dist/lib/server/dynamic-registry.js +245 -0
- package/dist/lib/server/dynamic-registry.js.map +1 -0
- package/dist/lib/server/index.d.ts +8 -0
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +15 -4
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/operational-platform.d.ts +239 -0
- package/dist/lib/server/operational-platform.d.ts.map +1 -0
- package/dist/lib/server/operational-platform.js +94 -0
- package/dist/lib/server/operational-platform.js.map +1 -0
- package/dist/lib/server/wire-safe.d.ts +211 -0
- package/dist/lib/server/wire-safe.d.ts.map +1 -0
- package/dist/lib/server/wire-safe.js +231 -0
- package/dist/lib/server/wire-safe.js.map +1 -0
- package/dist/lib/server/wire-spec-fields.generated.d.ts +168 -0
- package/dist/lib/server/wire-spec-fields.generated.d.ts.map +1 -0
- package/dist/lib/server/wire-spec-fields.generated.js +172 -0
- package/dist/lib/server/wire-spec-fields.generated.js.map +1 -0
- package/dist/lib/testing/compliance/index.d.ts +2 -0
- package/dist/lib/testing/compliance/index.d.ts.map +1 -1
- package/dist/lib/testing/compliance/index.js +6 -1
- package/dist/lib/testing/compliance/index.js.map +1 -1
- package/dist/lib/testing/compliance/summary.d.ts +77 -0
- package/dist/lib/testing/compliance/summary.d.ts.map +1 -0
- package/dist/lib/testing/compliance/summary.js +176 -0
- package/dist/lib/testing/compliance/summary.js.map +1 -0
- package/dist/lib/testing/storyboard/compliance.d.ts +26 -0
- package/dist/lib/testing/storyboard/compliance.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/compliance.js +51 -0
- package/dist/lib/testing/storyboard/compliance.js.map +1 -1
- package/dist/lib/testing/storyboard/index.d.ts +2 -2
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js +4 -2
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +58 -5
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential discipline at the request boundary.
|
|
3
|
+
*
|
|
4
|
+
* Scans incoming buyer args for credential-shaped keys at any depth and
|
|
5
|
+
* rejects with `INVALID_REQUEST` when `credentialPolicy === 'authInfo-only'`.
|
|
6
|
+
* Closes the bug class observed in storefront fan-out paths where buyer-
|
|
7
|
+
* supplied keys like `<platform>_access_token` (top-level, in `context`,
|
|
8
|
+
* or in `ext`) flow through to upstream calls.
|
|
9
|
+
*
|
|
10
|
+
* Default mode is `'lax'` for back-compat. Opt into `'authInfo-only'` to
|
|
11
|
+
* enforce: credentials must arrive on `authInfo` (the framework-resolved
|
|
12
|
+
* bearer / signature / OAuth principal) and never on the args bag.
|
|
13
|
+
*
|
|
14
|
+
* Pattern set is extensible. Adopters whose platform vocabulary uses
|
|
15
|
+
* additional credential names extend via `credentialPolicy.patterns.extend`
|
|
16
|
+
* or replace the matcher entirely. Per-tool opt-out via
|
|
17
|
+
* `credentialPolicy.tools`.
|
|
18
|
+
*
|
|
19
|
+
* @see {@link AdcpServerConfig.credentialPolicy}
|
|
20
|
+
* @see docs/guides/CTX-METADATA-SAFETY.md
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Enforcement mode.
|
|
24
|
+
*
|
|
25
|
+
* - `'lax'` — no scan; current behavior.
|
|
26
|
+
* - `'authInfo-only'` — scan args for credential-shaped keys; reject any
|
|
27
|
+
* match with `INVALID_REQUEST` listing the offending paths (not values).
|
|
28
|
+
* Adopters who legitimately accept buyer-presented credentials opt out
|
|
29
|
+
* per-tool via {@link CredentialPolicyConfig.tools}.
|
|
30
|
+
*/
|
|
31
|
+
export type CredentialPolicyMode = 'lax' | 'authInfo-only';
|
|
32
|
+
/**
|
|
33
|
+
* Patterns that flag a key as credential-shaped. Values matching ANY
|
|
34
|
+
* regex (or returning `true` from the matcher) are treated as
|
|
35
|
+
* credential-bearing.
|
|
36
|
+
*/
|
|
37
|
+
export interface CredentialPatternsConfig {
|
|
38
|
+
/**
|
|
39
|
+
* Additional patterns appended to {@link DEFAULT_CREDENTIAL_PATTERNS}.
|
|
40
|
+
* Use for platform-specific names the defaults don't cover (e.g.
|
|
41
|
+
* `/^bearer$/i`, `/credentials/i`, `/^[a-z]+Pat$/`).
|
|
42
|
+
*/
|
|
43
|
+
extend?: RegExp[];
|
|
44
|
+
/**
|
|
45
|
+
* Replace the regex-based check entirely. Receives each property name
|
|
46
|
+
* encountered during recursion, plus the parent path. Return `true`
|
|
47
|
+
* to flag as credential-bearing. Mutually exclusive with `extend` —
|
|
48
|
+
* setting both throws at server construction.
|
|
49
|
+
*/
|
|
50
|
+
matcher?: (key: string, path: readonly string[]) => boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Per-tool override shape. Adopters specify either a mode string for
|
|
54
|
+
* coarse-grained override (`'lax'` lets every credential-shaped key
|
|
55
|
+
* through; `'authInfo-only'` rejects them all) or a granular
|
|
56
|
+
* `{ allow: [...] }` allowlist that permits specific credential paths
|
|
57
|
+
* while still rejecting unlisted ones.
|
|
58
|
+
*
|
|
59
|
+
* The `allow` shape is the recommended choice for storefronts that
|
|
60
|
+
* legitimately accept ONE specific buyer-presented credential per
|
|
61
|
+
* tool — `tools: { activate_signal: 'lax' }` opens the tool to every
|
|
62
|
+
* credential-shaped key (including `password=`, `client_secret=`),
|
|
63
|
+
* while `tools: { activate_signal: { allow: ['delivery.api_token'] } }`
|
|
64
|
+
* permits only the spec-blessed field and still rejects everything
|
|
65
|
+
* else.
|
|
66
|
+
*/
|
|
67
|
+
export type ToolCredentialPolicy = CredentialPolicyMode | {
|
|
68
|
+
readonly allow: readonly string[];
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Full credential-policy configuration. Pass a string for the simple
|
|
72
|
+
* case (`credentialPolicy: 'authInfo-only'`) or this shape for
|
|
73
|
+
* pattern customization or per-tool overrides.
|
|
74
|
+
*/
|
|
75
|
+
export interface CredentialPolicyConfig {
|
|
76
|
+
policy: CredentialPolicyMode;
|
|
77
|
+
patterns?: CredentialPatternsConfig;
|
|
78
|
+
/**
|
|
79
|
+
* Per-tool mode overrides. Storefronts that legitimately accept
|
|
80
|
+
* buyer-presented credentials on a specific tool opt that tool out
|
|
81
|
+
* of the server-wide `'authInfo-only'`:
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* credentialPolicy: {
|
|
85
|
+
* policy: 'authInfo-only',
|
|
86
|
+
* tools: {
|
|
87
|
+
* // Coarse: lets every credential-shaped key through
|
|
88
|
+
* legacy_tool: 'lax',
|
|
89
|
+
*
|
|
90
|
+
* // Granular: only the listed paths are allowlisted; other
|
|
91
|
+
* // credential-shaped keys still reject. Recommended for
|
|
92
|
+
* // tools where the legitimate buyer-presented credential is
|
|
93
|
+
* // a known, named field.
|
|
94
|
+
* activate_signal: { allow: ['delivery.api_token'] },
|
|
95
|
+
* },
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* Allowlist entries are exact path matches against the
|
|
100
|
+
* dot-notation path the scanner emits — e.g. `'snap_access_token'`
|
|
101
|
+
* (top-level), `'context.linkedin_access_token'` (nested),
|
|
102
|
+
* `'packages.0.extra.tiktok_access_token'` (array element).
|
|
103
|
+
*/
|
|
104
|
+
tools?: Record<string, ToolCredentialPolicy>;
|
|
105
|
+
/**
|
|
106
|
+
* Extend the credential-shaped-key scan to cover `ctx.authInfo.extra`
|
|
107
|
+
* in addition to the buyer args bag. Default `false`.
|
|
108
|
+
*
|
|
109
|
+
* Custom authenticators that stamp values into `authInfo.extra` (token
|
|
110
|
+
* introspection responses, JWT claim sets, OAuth scope blobs) are
|
|
111
|
+
* outside L1's args-bag scan. Adopter handler code that reads
|
|
112
|
+
* `ctx.authInfo.extra.<credential>` for upstream auth produces a
|
|
113
|
+
* silent leak surface: a buggy `BuyerAgentRegistry.resolve` factory
|
|
114
|
+
* that throws an error embedding `extra` lands the value in
|
|
115
|
+
* `logger.error` before `redactCredentialPatterns` (which only catches
|
|
116
|
+
* labeled `Bearer <token>` shapes and ≥32-char base64 blobs) could
|
|
117
|
+
* mask it.
|
|
118
|
+
*
|
|
119
|
+
* Orthogonal to {@link policy} — adopters can mix-and-match. Common
|
|
120
|
+
* shapes:
|
|
121
|
+
*
|
|
122
|
+
* - `policy: 'authInfo-only', scanAuthInfo: true` — strictest.
|
|
123
|
+
* - `policy: 'lax', scanAuthInfo: true` — trust args, defend log
|
|
124
|
+
* propagation of authInfo extras.
|
|
125
|
+
* - `policy: 'authInfo-only', scanAuthInfo: false` — current default
|
|
126
|
+
* if `scanAuthInfo` is omitted; args-only enforcement.
|
|
127
|
+
*
|
|
128
|
+
* **Default `false` is deliberate.** OAuth introspection blobs and
|
|
129
|
+
* JWT claims in `extra` will false-positive on default patterns
|
|
130
|
+
* like `/_token$/i` (e.g. `id_token`, `access_token` claims that
|
|
131
|
+
* the framework's authenticator legitimately stamps).
|
|
132
|
+
*
|
|
133
|
+
* **Wire-envelope discipline.** Args-bag hits are reported in
|
|
134
|
+
* `details.credential_paths` (the buyer already sent these — no
|
|
135
|
+
* info disclosure). `authInfo.extra` hits are NOT reported on
|
|
136
|
+
* the wire; they're logged server-side only. Returning paths
|
|
137
|
+
* to the buyer would create a probing oracle for the structure
|
|
138
|
+
* of `authInfo.extra` (an internal value the buyer has no read
|
|
139
|
+
* access to). The wire envelope reports a coarse signal —
|
|
140
|
+
* `details.scope: 'credentials'` plus a generic message —
|
|
141
|
+
* without enumerating which `extra` field tripped the scan.
|
|
142
|
+
*
|
|
143
|
+
* See adcontextprotocol/adcp-client#1539.
|
|
144
|
+
*/
|
|
145
|
+
scanAuthInfo?: boolean;
|
|
146
|
+
}
|
|
147
|
+
export type CredentialPolicy = CredentialPolicyMode | CredentialPolicyConfig;
|
|
148
|
+
/**
|
|
149
|
+
* Default credential-name patterns. Catches the three vectors observed
|
|
150
|
+
* in PR scope3data/agentic-adapters#248 plus the broader credential
|
|
151
|
+
* vocabulary common in TS ecosystems and HTTPSig / OAuth flows.
|
|
152
|
+
* Adopters whose platform names fall outside this set extend via
|
|
153
|
+
* {@link CredentialPatternsConfig.extend}.
|
|
154
|
+
*
|
|
155
|
+
* Coverage:
|
|
156
|
+
* - `_token$` (case-insensitive) — `*_access_token`, `bearer_token`,
|
|
157
|
+
* `id_token`, `session_token`, `auth_token`, `refresh_token`.
|
|
158
|
+
* - `_secret$` / `_password$` — `client_secret`, `db_password`.
|
|
159
|
+
* - `api[_-]?key` (case-insensitive) — `api_key`, `apiKey`, `api-key`,
|
|
160
|
+
* and prefixed variants like `criteo_api_key`.
|
|
161
|
+
* - `private[_-]?key` (case-insensitive) — `private_key`, `privateKey`,
|
|
162
|
+
* `private-key`. Common in JWT / RFC 9421 signing-key flows.
|
|
163
|
+
* - `^authorization$` / `^cookie$` (case-insensitive) — HTTP-header
|
|
164
|
+
* value smuggled as a field.
|
|
165
|
+
* - `^bearer$` — bare `bearer` field.
|
|
166
|
+
* - `^accessToken$` / `^refreshToken$` (case-insensitive) — camelCase
|
|
167
|
+
* and PascalCase exact matches.
|
|
168
|
+
*
|
|
169
|
+
* Intentionally excluded from defaults (too many false positives):
|
|
170
|
+
* - bare `key` / `principal` / `kid` / `pat` — too short to risk
|
|
171
|
+
* matching legitimate routing fields.
|
|
172
|
+
* - `*Token$` PascalCase suffix without a known prefix — e.g.
|
|
173
|
+
* `paymentToken` could be a legitimate wire field. Adopters who
|
|
174
|
+
* want broader coverage extend.
|
|
175
|
+
*/
|
|
176
|
+
export declare const DEFAULT_CREDENTIAL_PATTERNS: readonly RegExp[];
|
|
177
|
+
/**
|
|
178
|
+
* Recursively scan `value` for credential-shaped keys. Returns dotted
|
|
179
|
+
* paths to every match (e.g. `['snap_access_token',
|
|
180
|
+
* 'context.snap_access_token', 'ext.snap_access_token']`). Empty array
|
|
181
|
+
* means clean.
|
|
182
|
+
*
|
|
183
|
+
* Scope:
|
|
184
|
+
* - Walks own string-keyed data properties only. Symbol keys,
|
|
185
|
+
* prototype-chain inherited properties, and accessor (getter/setter)
|
|
186
|
+
* properties are skipped — JSON-derived inputs (the only source the
|
|
187
|
+
* framework dispatches) cannot carry any of those. Hand-built
|
|
188
|
+
* objects with credential-named getters are still flagged
|
|
189
|
+
* fail-closed (the property name is matched against the regex
|
|
190
|
+
* set), but the getter is never invoked, so a throwing or
|
|
191
|
+
* side-effecting getter cannot reach the dispatcher.
|
|
192
|
+
* - Walks both plain objects and arrays; array indices appear as
|
|
193
|
+
* numeric path segments.
|
|
194
|
+
* - Stops at primitives.
|
|
195
|
+
* - Cycle-safe via a `WeakSet` tracking visited objects.
|
|
196
|
+
*/
|
|
197
|
+
export declare function scanArgsForCredentials(value: unknown, patterns?: CredentialPatternsConfig): string[];
|
|
198
|
+
/**
|
|
199
|
+
* Normalize a `CredentialPolicy` (string or object) plus a tool name
|
|
200
|
+
* to the effective {@link ToolCredentialPolicy} for that tool —
|
|
201
|
+
* either a mode string or an `{ allow: [...] }` allowlist. Per-tool
|
|
202
|
+
* overrides win; otherwise the server-wide policy applies.
|
|
203
|
+
*
|
|
204
|
+
* Caller dispatch:
|
|
205
|
+
*
|
|
206
|
+
* ```ts
|
|
207
|
+
* const effective = resolveCredentialPolicyForTool(policy, toolName);
|
|
208
|
+
* if (effective === 'lax') return; // skip scan
|
|
209
|
+
* const hits = scanArgsForCredentials(args, patterns);
|
|
210
|
+
* if (typeof effective === 'object') {
|
|
211
|
+
* // Granular allow — filter hits by the allowlist
|
|
212
|
+
* const blocked = hits.filter(p => !effective.allow.includes(p));
|
|
213
|
+
* if (blocked.length > 0) reject(blocked);
|
|
214
|
+
* } else {
|
|
215
|
+
* // 'authInfo-only' — every hit blocks
|
|
216
|
+
* if (hits.length > 0) reject(hits);
|
|
217
|
+
* }
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
export declare function resolveCredentialPolicyForTool(policy: CredentialPolicy | undefined, toolName: string): ToolCredentialPolicy;
|
|
221
|
+
//# sourceMappingURL=credential-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-policy.d.ts","sourceRoot":"","sources":["../../../src/lib/server/credential-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,eAAe,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC;CAC7D;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAEhG;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,sBAAsB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAWvD,CAAC;AAmCH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,wBAAwB,GAAG,MAAM,EAAE,CAqDpG;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,QAAQ,EAAE,MAAM,GACf,oBAAoB,CAItB"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Credential discipline at the request boundary.
|
|
4
|
+
*
|
|
5
|
+
* Scans incoming buyer args for credential-shaped keys at any depth and
|
|
6
|
+
* rejects with `INVALID_REQUEST` when `credentialPolicy === 'authInfo-only'`.
|
|
7
|
+
* Closes the bug class observed in storefront fan-out paths where buyer-
|
|
8
|
+
* supplied keys like `<platform>_access_token` (top-level, in `context`,
|
|
9
|
+
* or in `ext`) flow through to upstream calls.
|
|
10
|
+
*
|
|
11
|
+
* Default mode is `'lax'` for back-compat. Opt into `'authInfo-only'` to
|
|
12
|
+
* enforce: credentials must arrive on `authInfo` (the framework-resolved
|
|
13
|
+
* bearer / signature / OAuth principal) and never on the args bag.
|
|
14
|
+
*
|
|
15
|
+
* Pattern set is extensible. Adopters whose platform vocabulary uses
|
|
16
|
+
* additional credential names extend via `credentialPolicy.patterns.extend`
|
|
17
|
+
* or replace the matcher entirely. Per-tool opt-out via
|
|
18
|
+
* `credentialPolicy.tools`.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link AdcpServerConfig.credentialPolicy}
|
|
21
|
+
* @see docs/guides/CTX-METADATA-SAFETY.md
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.DEFAULT_CREDENTIAL_PATTERNS = void 0;
|
|
25
|
+
exports.scanArgsForCredentials = scanArgsForCredentials;
|
|
26
|
+
exports.resolveCredentialPolicyForTool = resolveCredentialPolicyForTool;
|
|
27
|
+
exports.validateCredentialPolicy = validateCredentialPolicy;
|
|
28
|
+
/**
|
|
29
|
+
* Default credential-name patterns. Catches the three vectors observed
|
|
30
|
+
* in PR scope3data/agentic-adapters#248 plus the broader credential
|
|
31
|
+
* vocabulary common in TS ecosystems and HTTPSig / OAuth flows.
|
|
32
|
+
* Adopters whose platform names fall outside this set extend via
|
|
33
|
+
* {@link CredentialPatternsConfig.extend}.
|
|
34
|
+
*
|
|
35
|
+
* Coverage:
|
|
36
|
+
* - `_token$` (case-insensitive) — `*_access_token`, `bearer_token`,
|
|
37
|
+
* `id_token`, `session_token`, `auth_token`, `refresh_token`.
|
|
38
|
+
* - `_secret$` / `_password$` — `client_secret`, `db_password`.
|
|
39
|
+
* - `api[_-]?key` (case-insensitive) — `api_key`, `apiKey`, `api-key`,
|
|
40
|
+
* and prefixed variants like `criteo_api_key`.
|
|
41
|
+
* - `private[_-]?key` (case-insensitive) — `private_key`, `privateKey`,
|
|
42
|
+
* `private-key`. Common in JWT / RFC 9421 signing-key flows.
|
|
43
|
+
* - `^authorization$` / `^cookie$` (case-insensitive) — HTTP-header
|
|
44
|
+
* value smuggled as a field.
|
|
45
|
+
* - `^bearer$` — bare `bearer` field.
|
|
46
|
+
* - `^accessToken$` / `^refreshToken$` (case-insensitive) — camelCase
|
|
47
|
+
* and PascalCase exact matches.
|
|
48
|
+
*
|
|
49
|
+
* Intentionally excluded from defaults (too many false positives):
|
|
50
|
+
* - bare `key` / `principal` / `kid` / `pat` — too short to risk
|
|
51
|
+
* matching legitimate routing fields.
|
|
52
|
+
* - `*Token$` PascalCase suffix without a known prefix — e.g.
|
|
53
|
+
* `paymentToken` could be a legitimate wire field. Adopters who
|
|
54
|
+
* want broader coverage extend.
|
|
55
|
+
*/
|
|
56
|
+
exports.DEFAULT_CREDENTIAL_PATTERNS = Object.freeze([
|
|
57
|
+
/_token$/i,
|
|
58
|
+
/_secret$/i,
|
|
59
|
+
/_password$/i,
|
|
60
|
+
/api[_-]?key/i,
|
|
61
|
+
/private[_-]?key/i,
|
|
62
|
+
/^authorization$/i,
|
|
63
|
+
/^cookie$/i,
|
|
64
|
+
/^bearer$/i,
|
|
65
|
+
/^accessToken$/i,
|
|
66
|
+
/^refreshToken$/i,
|
|
67
|
+
]);
|
|
68
|
+
/**
|
|
69
|
+
* Strip `/g` and `/y` flags from a regex. With those flags set,
|
|
70
|
+
* `RegExp.prototype.test` advances `lastIndex`, causing alternating-skip
|
|
71
|
+
* behavior on repeated calls against the same pattern instance. The
|
|
72
|
+
* scanner calls `.test()` per key per request and reuses the regex
|
|
73
|
+
* instance across calls, so `/credentials/gi` (a natural footgun) would
|
|
74
|
+
* produce non-deterministic hits. Strip the offending flags rather than
|
|
75
|
+
* forcing adopters to read a footnote.
|
|
76
|
+
*/
|
|
77
|
+
function stripStatefulFlags(rx) {
|
|
78
|
+
if (!rx.global && !rx.sticky)
|
|
79
|
+
return rx;
|
|
80
|
+
return new RegExp(rx.source, rx.flags.replace(/[gy]/g, ''));
|
|
81
|
+
}
|
|
82
|
+
function buildMatcher(patterns) {
|
|
83
|
+
if (patterns?.matcher && patterns.extend) {
|
|
84
|
+
throw new Error('createAdcpServer: credentialPolicy.patterns cannot set both `matcher` and `extend`. ' +
|
|
85
|
+
'`matcher` fully replaces the regex-based check; `extend` adds to the default set. ' +
|
|
86
|
+
'Pick one — they answer different questions and combining them silently drops the regex set.');
|
|
87
|
+
}
|
|
88
|
+
if (patterns?.matcher) {
|
|
89
|
+
return patterns.matcher;
|
|
90
|
+
}
|
|
91
|
+
const regexes = patterns?.extend
|
|
92
|
+
? [...exports.DEFAULT_CREDENTIAL_PATTERNS, ...patterns.extend.map(stripStatefulFlags)]
|
|
93
|
+
: exports.DEFAULT_CREDENTIAL_PATTERNS;
|
|
94
|
+
return (key) => regexes.some(rx => rx.test(key));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Recursively scan `value` for credential-shaped keys. Returns dotted
|
|
98
|
+
* paths to every match (e.g. `['snap_access_token',
|
|
99
|
+
* 'context.snap_access_token', 'ext.snap_access_token']`). Empty array
|
|
100
|
+
* means clean.
|
|
101
|
+
*
|
|
102
|
+
* Scope:
|
|
103
|
+
* - Walks own string-keyed data properties only. Symbol keys,
|
|
104
|
+
* prototype-chain inherited properties, and accessor (getter/setter)
|
|
105
|
+
* properties are skipped — JSON-derived inputs (the only source the
|
|
106
|
+
* framework dispatches) cannot carry any of those. Hand-built
|
|
107
|
+
* objects with credential-named getters are still flagged
|
|
108
|
+
* fail-closed (the property name is matched against the regex
|
|
109
|
+
* set), but the getter is never invoked, so a throwing or
|
|
110
|
+
* side-effecting getter cannot reach the dispatcher.
|
|
111
|
+
* - Walks both plain objects and arrays; array indices appear as
|
|
112
|
+
* numeric path segments.
|
|
113
|
+
* - Stops at primitives.
|
|
114
|
+
* - Cycle-safe via a `WeakSet` tracking visited objects.
|
|
115
|
+
*/
|
|
116
|
+
function scanArgsForCredentials(value, patterns) {
|
|
117
|
+
const matcher = buildMatcher(patterns);
|
|
118
|
+
const hits = [];
|
|
119
|
+
const seen = new WeakSet();
|
|
120
|
+
const walk = (node, path) => {
|
|
121
|
+
if (node === null || typeof node !== 'object')
|
|
122
|
+
return;
|
|
123
|
+
if (seen.has(node))
|
|
124
|
+
return;
|
|
125
|
+
seen.add(node);
|
|
126
|
+
if (Array.isArray(node)) {
|
|
127
|
+
for (let i = 0; i < node.length; i++) {
|
|
128
|
+
walk(node[i], [...path, String(i)]);
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// Use property descriptors so accessor (getter/setter) properties
|
|
133
|
+
// are visible to the scanner without invoking the getter — a
|
|
134
|
+
// throwing getter on a credential-named property would otherwise
|
|
135
|
+
// either crash the dispatcher or land the surrounding `params`
|
|
136
|
+
// object in an outer error log. Data-only inputs (JSON.parse,
|
|
137
|
+
// structured clone) never have accessor descriptors, so this is
|
|
138
|
+
// a defensive measure for hand-built test inputs and any future
|
|
139
|
+
// transport that bypasses JSON parsing.
|
|
140
|
+
let descriptors;
|
|
141
|
+
try {
|
|
142
|
+
descriptors = Object.getOwnPropertyDescriptors(node);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Proxy-trapped property enumeration that throws — fail closed
|
|
146
|
+
// by recording the parent path as suspicious. Cannot enumerate
|
|
147
|
+
// to a finer-grained location.
|
|
148
|
+
hits.push([...path, '<unreadable>'].join('.'));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
for (const key of Object.keys(descriptors)) {
|
|
152
|
+
const desc = descriptors[key];
|
|
153
|
+
if (desc === undefined)
|
|
154
|
+
continue;
|
|
155
|
+
const childPath = [...path, key];
|
|
156
|
+
if (matcher(key, path)) {
|
|
157
|
+
hits.push(childPath.join('.'));
|
|
158
|
+
}
|
|
159
|
+
// Only recurse into data descriptors. Accessor descriptors
|
|
160
|
+
// (no `value` slot) are flagged-by-name above but never invoked.
|
|
161
|
+
if ('value' in desc) {
|
|
162
|
+
walk(desc.value, childPath);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
walk(value, []);
|
|
167
|
+
return hits;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Normalize a `CredentialPolicy` (string or object) plus a tool name
|
|
171
|
+
* to the effective {@link ToolCredentialPolicy} for that tool —
|
|
172
|
+
* either a mode string or an `{ allow: [...] }` allowlist. Per-tool
|
|
173
|
+
* overrides win; otherwise the server-wide policy applies.
|
|
174
|
+
*
|
|
175
|
+
* Caller dispatch:
|
|
176
|
+
*
|
|
177
|
+
* ```ts
|
|
178
|
+
* const effective = resolveCredentialPolicyForTool(policy, toolName);
|
|
179
|
+
* if (effective === 'lax') return; // skip scan
|
|
180
|
+
* const hits = scanArgsForCredentials(args, patterns);
|
|
181
|
+
* if (typeof effective === 'object') {
|
|
182
|
+
* // Granular allow — filter hits by the allowlist
|
|
183
|
+
* const blocked = hits.filter(p => !effective.allow.includes(p));
|
|
184
|
+
* if (blocked.length > 0) reject(blocked);
|
|
185
|
+
* } else {
|
|
186
|
+
* // 'authInfo-only' — every hit blocks
|
|
187
|
+
* if (hits.length > 0) reject(hits);
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
function resolveCredentialPolicyForTool(policy, toolName) {
|
|
192
|
+
if (policy === undefined)
|
|
193
|
+
return 'lax';
|
|
194
|
+
if (typeof policy === 'string')
|
|
195
|
+
return policy;
|
|
196
|
+
return policy.tools?.[toolName] ?? policy.policy;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Validate a `CredentialPolicy` at server construction. Catches typos
|
|
200
|
+
* in `tools` keys (`activte_signal` instead of `activate_signal`) and
|
|
201
|
+
* the both-`extend`-and-`matcher` config error before any traffic
|
|
202
|
+
* dispatches. Throws `Error` with a specific message; callers convert
|
|
203
|
+
* to their construction-time error envelope of choice.
|
|
204
|
+
*
|
|
205
|
+
* `knownToolNames` is the set of tool names the framework will
|
|
206
|
+
* register for this server (spec tools for the claimed specialisms +
|
|
207
|
+
* any adopter-supplied custom tools). Pass after the registration
|
|
208
|
+
* loop completes so the set is authoritative.
|
|
209
|
+
*
|
|
210
|
+
* @internal — adopters cannot construct `knownToolNames` outside the
|
|
211
|
+
* framework. The framework calls this once, late in `createAdcpServer`,
|
|
212
|
+
* after every tool (including `get_adcp_capabilities`) is registered.
|
|
213
|
+
*/
|
|
214
|
+
function validateCredentialPolicy(policy, knownToolNames) {
|
|
215
|
+
if (policy === undefined || typeof policy === 'string')
|
|
216
|
+
return;
|
|
217
|
+
// Surface the both-fields-set conflict at construction, not on the
|
|
218
|
+
// first credential-bearing request. Mirrors the runtime check in
|
|
219
|
+
// `buildMatcher` so adopters get the same diagnostic regardless of
|
|
220
|
+
// whether traffic is flowing yet.
|
|
221
|
+
if (policy.patterns?.matcher && policy.patterns?.extend) {
|
|
222
|
+
throw new Error('createAdcpServer: credentialPolicy.patterns cannot set both `matcher` and `extend`. ' +
|
|
223
|
+
'`matcher` fully replaces the regex-based check; `extend` adds to the default set. Pick one.');
|
|
224
|
+
}
|
|
225
|
+
if (!policy.tools)
|
|
226
|
+
return;
|
|
227
|
+
const unknownTools = Object.keys(policy.tools).filter(name => !knownToolNames.has(name));
|
|
228
|
+
if (unknownTools.length > 0) {
|
|
229
|
+
const known = [...knownToolNames].sort().join(', ');
|
|
230
|
+
throw new Error(`createAdcpServer: credentialPolicy.tools references unregistered tool name(s): ${unknownTools
|
|
231
|
+
.map(n => JSON.stringify(n))
|
|
232
|
+
.join(', ')}. ` +
|
|
233
|
+
`A typo in this map silently no-ops the per-tool override and the server-wide policy applies, ` +
|
|
234
|
+
`which fails-closed on tools that needed an opt-out. ` +
|
|
235
|
+
`Known tool names: ${known}.`);
|
|
236
|
+
}
|
|
237
|
+
// Validate granular allow-shape entries — each must be a non-empty
|
|
238
|
+
// array of strings. An empty `allow` is the same as 'authInfo-only'
|
|
239
|
+
// for that tool (no path is permitted) and is almost certainly a
|
|
240
|
+
// bug — surface it at construction. Non-string entries would
|
|
241
|
+
// silently never match the dotted-path strings the scanner emits.
|
|
242
|
+
for (const [toolName, toolPolicy] of Object.entries(policy.tools)) {
|
|
243
|
+
if (typeof toolPolicy === 'string')
|
|
244
|
+
continue;
|
|
245
|
+
if (!Array.isArray(toolPolicy.allow)) {
|
|
246
|
+
throw new Error(`createAdcpServer: credentialPolicy.tools[${JSON.stringify(toolName)}].allow must be an array of path strings.`);
|
|
247
|
+
}
|
|
248
|
+
if (toolPolicy.allow.length === 0) {
|
|
249
|
+
throw new Error(`createAdcpServer: credentialPolicy.tools[${JSON.stringify(toolName)}].allow is empty. ` +
|
|
250
|
+
`An empty allow list is equivalent to 'authInfo-only' for this tool — drop the entry or use the string shorthand.`);
|
|
251
|
+
}
|
|
252
|
+
const nonStrings = toolPolicy.allow.filter(p => typeof p !== 'string');
|
|
253
|
+
if (nonStrings.length > 0) {
|
|
254
|
+
throw new Error(`createAdcpServer: credentialPolicy.tools[${JSON.stringify(toolName)}].allow contains non-string entries: ` +
|
|
255
|
+
`${nonStrings.map(n => JSON.stringify(n)).join(', ')}. ` +
|
|
256
|
+
`Allowlist entries are exact-match path strings (e.g. 'context.snap_access_token').`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=credential-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-policy.js","sourceRoot":"","sources":["../../../src/lib/server/credential-policy.ts"],"names":[],"mappings":"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"}
|