feat(decisioning): property_list resolver + intersection helper for get_products#500
Merged
Merged
Conversation
9 tasks
8f57a41 to
9d9ccf0
Compare
…et_products Closes #494 Adds capability-gated framework support for buyer-side property_list filtering in get_products, mirroring the webhook_emit post-adapter pattern. When Features(property_list_filtering=True) is declared and a PropertyListFetcher is wired, the framework fetches the buyer's authorized property IDs and filters the platform's product list post-adapter, setting response.property_list_applied=True. https://claude.ai/code/session_01GqPV3vkvFdC6DesCzwKFNQ
- Remove {exc} interpolation from wire error message to prevent
auth_token / credential leakage through upstream exception reprs
- Extract property_list_capability_enabled() helper to eliminate
duplicate getattr chains in handler.py and serve.py
- Export validate_property_list_config and property_list_capability_enabled
from adcp.decisioning public __all__ so self-managed adopters can
call the boot guard themselves
- Add two tests for by_id with empty property_ids (strict + permissive)
confirming the vacuous-subset guard works
https://claude.ai/code/session_01GqPV3vkvFdC6DesCzwKFNQ
9d9ccf0 to
8edec6c
Compare
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.
Summary
Implements the capability-gated
property_listfilter forget_productsrequested in #494. Mirrors thewebhook_emitpost-adapter side-effect pattern already established in the framework.PropertyListFetcherProtocol — adopter-supplied, no hidden HTTP client; distinct fromResourceResolver(which resolves wire references, not list contents)resolve_property_list— fetches buyer's allowed property IDs fromref.agent_url; wraps fetch failures asAdcpError("SERVICE_UNAVAILABLE", recovery="transient");auth_tokennever appears in the wire error message (logged server-side only)filter_products_by_property_list— three-mode filter:'all'→ always include;'by_id'→ strict (all IDs must be ⊆ allowed) or permissive (any intersection);'by_tag'→ always exclude (can't match IDs)maybe_apply_property_list_filter— post-adapter gate called byget_productsshim; no-op when capability not declared orparams.property_listis absent; usesmodel_copynot in-place mutationvalidate_property_list_config— boot-time fail-fast whenproperty_list_filtering=Truedeclared but no fetcher wiredproperty_list_capability_enabled(platform)— shared helper eliminating the duplicategetattrchain inhandler.pyandserve.pyPublic API additions to
adcp.decisioning:PropertyListFetcher,filter_products_by_property_list,resolve_property_list(for self-managed adopters)validate_property_list_config,property_list_capability_enabled(for boot-time wiring)Wire
create_adcp_server_from_platform(platform, property_list_fetcher=MyFetcher(client)).Expert consultation
Protocol expert — confirmed
by_tagselection cannot be matched against property ID lists; confirmedproperty_targeting_allowedstrict/permissive semantics. Flagged usingmodel_copyto avoid aliasing the platform's return value.DX expert — confirmed
PropertyListFetcheris NOT redundant withResourceResolver(different abstraction levels). Flagged thatvalidate_property_list_configmust be exported publicly for self-managed adopters who push filtering into their ownget_productsimplementation.Code reviewer — flagged
{exc}interpolation into the wire error message as a credential-leak risk (upstream HTTP exception repr may carryauth_token). Fixed: exception logged server-side vialogger.warning, not included in theAdcpErrormessage ordetails. Also flagged duplicategetattrchain (fixed viaproperty_list_capability_enabledhelper).Test plan
tests/test_decisioning_property_list.py— all passingTestFilterProductsByPropertyList:'all'always-include,'by_id'strict/permissive,'by_tag'always-exclude, mixed entries, empty products/allowed,property_targeting_allowed=None, emptyproperty_idslist (strict + permissive)TestResolvePropertyList: returns set; auth_token threaded; failure →AdcpError(transient); auth_token absent from error detailsTestValidatePropertyListConfig: enabled/fetcher combinations; no fetcher + enabled → terminal errorTestMaybeApplyPropertyListFilter: no-op cases; filter applied + flag set; no fetcher warning; fetch failure propagation;model_copyused not in-place mutationruff check src/— cleanmypy src/adcp/decisioning/property_list.py handler.py serve.py __init__.py— no new errorsCloses #494
Generated by Claude Code