feat(testing): governance/property-lists/content-standards/collection-lists seeded bridges (#1755 phase 2)#1761
Merged
Merged
Conversation
…-lists seeded bridges (#1755 phase 2) Extends `TestControllerBridge<TAccount>` with three opt-in callbacks so platform-proxy sellers can seed governance-domain fixtures into conformance storyboards without driving real upstream calls. Each callback's seeded array feeds both the list AND the get path for that entity (dedup key in parens): - getSeededPropertyLists (list_id) → list_property_lists / get_property_list - getSeededCollectionLists (list_id) → list_collection_lists / get_collection_list - getSeededContentStandards (standards_id) → list_content_standards / get_content_standards List path: append-merge with seeded wins on collision; pagination.total_count increments by the non-colliding seeded count. Singleton path for property / collection: pick by request id, replace the response's `list` field, preserve handler's identifiers / pagination / resolved_at / cache_valid_until / coverage_gaps / context / ext. Singleton path for content-standards: success arm IS ContentStandards directly (no envelope wrapper per AdCP 3.0.11) — replace the entire response and preserve only handler ext. Same triply-gated sandbox contract (controller present + sandbox marker + resolved account is sandbox: true when resolveAccount produced one). BridgeFromSessionStoreOptions gains matching selectSeededPropertyLists / selectSeededCollectionLists / selectSeededContentStandards selectors. Unblocks the property-lists, governance-aware-seller, collection-lists, and content-standards storyboards on platform-proxy sellers. list_authorized_properties was deliberately skipped — that tool was removed from AdCP and replaced by get_adcp_capabilities discovery; no schema exists in schemas/cache/3.0.11/.
…ntext Both reviewers flagged that the get_content_standards response success arm carries context alongside ext (top-level optional properties on the response, even though allOf: [ContentStandards] is the body shape per schemas/cache/3.0.11/content-standards/get-content-standards-response.json). The initial commit dropped context on replace. replaceContentStandardsIfSeeded now mirrors replaceAccountFinancialsIfSeeded preservation: seeded fixture is authoritative on the ContentStandards body, framework-managed envelope fields (context, ext) round-trip from the handler. JSDoc on the bridge field, dispatcher comment, changeset, and VALIDATE-YOUR-AGENT.md callout corrected. New test asserts handler context + ext survive replace when seeded fixture lacks them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
Fix: ContentStandards singleton replace now preserves handler
|
This was referenced May 16, 2026
Merged
bokelley
added a commit
that referenced
this pull request
May 16, 2026
…1779) * docs(bridge): name resolveAccount trust boundary + multi-tenant keying as adopter responsibility Adds two paragraphs to the top-of-file JSDoc on TestControllerBridge: 1. Scope of verification — a storyboard pass through this bridge proves wire conformance against fixture data, not adapter health against the real upstream. Sellers must still exercise adapters against a live-OAuth sandbox runner separately. Cross-references the runner-visible-bridge-marker ask at #1775. 2. Adopter responsibilities — names two patterns the SDK can't enforce: (a) resolveAccount is the trust boundary; production bindings MUST configure it or the request-signal check is the only line of defense, because the dispatcher gate falls through to permissive when ctx.account === undefined. (b) Multi-tenant keying is the adopter's job; the SDK does no defensive cross-check between fixture-entry account IDs and the resolved ctx.account. No code change. Security-review-driven during the post-merge review of #1754 — main shipped the bridge surface (#1753 + phases #1759/#1761/ #1772) but no public-surface warning about either trust pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(bridge): docs-expert tightenings on JSDoc PR review - "bypassed by the post-handler merge" → "shadowed by the post-handler merge" (more accurate: the upstream is called, then its response is overridden). - "request-signal check is the only line of defense" → "buyer-supplied sandbox marker is the only gate" (flatter, more accurate). - Drop the "Snap, Meta, TikTok, Google Ads" brand list → "social / search / programmatic inventory APIs" (illustrative without pulling toward a specific adopter or violating fictional-names-only convention). - Echo a one-paragraph trust-boundary note on createAdcpServer's testController config field — that's where a wiring author lands when they hit autocomplete, and the last chance to warn before resolveAccount gets omitted. Cross-references the top-of-file JSDoc on TestControllerBridge. All four changes from the docs-expert review of PR #1779. No code behavior change; pure JSDoc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 of #1755 — extends
TestControllerBridge<TAccount>with seeded bridges for the governance-domain read tools so platform-proxy sellers can run the storyboards that gate property-lists / collection-lists / content-standards / governance-aware-seller specialisms without rewriting upstream adapters.Summary
Three new opt-in callbacks. Each seeded array feeds both the list and the get path for its entity, matching the user's instinct ("all or nothing, DX is odd otherwise"):
getSeededPropertyListslist_id(verifiedPropertyList.list_id: stringrequired)list_property_lists— mergelists: PropertyList[], incrementpagination.total_countby non-colliding countget_property_list— pick byrequest.list_id, replaceresponse.list, preserve handleridentifiers/pagination/resolved_at/cache_valid_until/coverage_gaps/context/extproperty-lists,governance-aware-seller(property catalog seeding)getSeededCollectionListslist_id(verifiedCollectionList.list_id: stringrequired)list_collection_lists— symmetric with property listsget_collection_list— symmetric; preserves handlercollections/pagination/resolved_at/cache_valid_until/coverage_gaps/context/extcollection-lists(program-level brand safety via IMDb/Gracenote/EIDR IDs)getSeededContentStandardsstandards_id(verifiedContentStandards.standards_id: stringrequired)list_content_standards— success armstandards: ContentStandards[]; merge + updatepagination.total_countget_content_standards— success arm ISContentStandardsdirectly (NO envelope wrapper per AdCP 3.0.11) — replace entire response, preserve only handlerext(nocontextin the success arm shape)content-standards(brand-safety / suitability policies)All three bridges follow the established seeded-wins-on-collision precedent set by the six existing bridges (
mergeSeededProducts/mergeSeededCreatives/mergeSeededMediaBuys/mergeSeededAccounts/mergeSeededMediaBuyDelivery/mergeSeededCreativeFormats) and the same triply-gated sandbox contract (controller present + sandbox marker on request + resolved account issandbox: truewhenresolveAccountproduced one).BridgeFromSessionStoreOptionsgains matchingselectSeededPropertyLists/selectSeededCollectionLists/selectSeededContentStandardsselectors.Tool skipped
list_authorized_properties— DELIBERATELY NOT ADDED. That tool was removed from AdCP and replaced by theget_adcp_capabilitiesdiscovery surface; no schema exists inschemas/cache/3.0.11/bundled/(verified). TheAuthorizedPropertytype only survives insrc/lib/types/v2-5/tools.generated.tsfor legacy 2.5 compat. Old references insrc/lib/discovery/property-crawler.ts(line 175) andsrc/lib/testing/scenarios/confirm the migration ("Use capabilities API which replaced list_authorized_properties").Schema-driven decisions
Verified each schema before designing the bridge:
schemas/cache/3.0.11/bundled/property/list-property-lists-response.json— plain interface,required: [lists],pagination?optional. ✅ list-shape only.schemas/cache/3.0.11/bundled/property/get-property-list-response.json— requiredlist, optionalidentifiers/pagination/resolved_at/cache_valid_until/coverage_gaps/context/ext. ✅ singleton replace oflistfield, preserve auxiliary data.schemas/cache/3.0.11/collection/list-collection-lists-response.json+get-collection-list-response.json— symmetric with property lists. ✅ same shape decision.schemas/cache/3.0.11/bundled/content-standards/list-content-standards-response.json—oneOf(success armstandards: ContentStandards[]/ error armerrors: []). ✅ append-merge into success arm; error arm gated out by dispatcher's pre-existing!isErrorResponse(formatted)check.get-content-standards-response.json—oneOfwhere the success arm ISContentStandardsdirectly (no envelope). ✅ replace entire response, preserve handlerextonly.Test plan
NODE_ENV=test npm test— 8769 pass / 0 fail / 3 skipped (pre-existing). Previous baseline 8748; +35 new test cases intest/lib/seed-per-tool-wiring.test.js(51 → 86it()blocks).npm run typecheck— clean.npm run format:check— clean.npm run build— clean.[A,B]+[B,C]→[A, B-seeded, C]with correct counts, sandbox-gating refusal, validation drop for missing/emptylist_id/standards_id, singleton-replace passthrough on no-match, context+ext preservation on singleton replace (PropertyList / CollectionList preserve full envelope; ContentStandards preserves onlyext).Test mix per bridge (caveat: list+get share the seeded callback so I split the suite by tool):
getSeededPropertyLists— 7 list-path tests + 4 get-path testsgetSeededCollectionLists— 6 list-path tests + 4 get-path testsgetSeededContentStandards— 6 list-path tests + 4 get-path testsbridgeFromSessionStore— 4 governance-selector wiring testsDoc updates
docs/guides/VALIDATE-YOUR-AGENT.md§ Platform-proxy sellers — extended the selector table with 3 new entries (each tied to the specialism it unblocks), updated the "Singleton exception" callout to mention the new singleton-replace paths and ContentStandards' bare-entity success arm, updated the "Validation drops" bullet with the new dedup keys.Files
src/lib/server/test-controller-bridge.ts— interface additions;filterValidSeededPropertyLists/filterValidSeededCollectionLists/filterValidSeededContentStandards(reusefilterValidById);mergeSeededPropertyListsIntoResponse/mergeSeededCollectionListsIntoResponse/mergeSeededContentStandardsIntoResponse;pickSeededPropertyListForRequest/replacePropertyListIfSeeded; matching pairs for collection-list and content-standards; selector wiring inbridgeFromSessionStore.src/lib/server/create-adcp-server.ts— 3 new dispatch branches (each handles bothlist_*andget_*for its entity) added after thelist_creative_formatsbranch, behind the same triply-gated sandbox check.test/lib/seed-per-tool-wiring.test.js— 35 new test cases, 7 new describe blocks..changeset/seeded-governance-bridges.md— minor.🤖 Generated with Claude Code