Module adcp.types.domains.trusted_match.provider_registration
Classes
class Country (value: Any = <object object>, *, root: Any = <object object>)-
Expand source code
class Country(ScalarStr): __slots__ = () _constraints = {'pattern': '^[A-Z]{2}$'}A
strgenerated from a JSON Schema string root.Ancestors
- adcp.types._scalar.ScalarStr
- adcp.types._scalar._ScalarRoot
- builtins.str
class Status (*args, **kwds)-
Expand source code
class Status(StrEnum): active = 'active' inactive = 'inactive' draining = 'draining'Enum where members are also (and must be) strings
Ancestors
- enum.StrEnum
- builtins.str
- enum.ReprEnum
- enum.Enum
Class variables
var activevar drainingvar inactive
class TmpProviderRegistration1 (**data: Any)-
Expand source code
class TmpProviderRegistration1(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) provider_id: Annotated[ str, Field( description="Stable identifier for this provider registration. Used in logs, metrics, cache keys, as the key in `signals_by_provider` on Context Match responses and `targeting_kv_mapping` in publisher configuration, and as the key in `tmpx_providers` on Identity Match responses and `tmpx_macro_mapping` in publisher configuration. Publishers assign this — it is not the provider's agent_url. Charset is constrained to a safe alphanumeric/underscore set so the value can appear in operational surfaces (logs, metrics, dashboards) without quoting. See publisher-targeting-kv-config.json and publisher-tmpx-config.json.", max_length=64, min_length=1, pattern='^[A-Za-z0-9_]+$', ), ] endpoint: Annotated[ AnyUrl, Field( description='Base URL the router calls. The router appends /context for Context Match and /identity for Identity Match. MUST be HTTPS in production, validated against the canonical reserved IPv4 and IPv6 ranges, with the TCP connection pinned to the validated IP (DNS re-resolution alone is insufficient against rebinding). Publishers comparing two provider registrations for the same `endpoint` MUST canonicalize both per the AdCP URL canonicalization rules; two registrations differing only in case, default port, or path-slash collapsing are the same provider. See docs/trusted-match/specification#provider-registration-security, docs/building/implementation/security#webhook-url-validation-ssrf, and docs/reference/url-canonicalization.' ), ] context_match: Annotated[ Literal[True], Field(description='Provider handles Context Match requests (POST /context).') ] identity_match: Annotated[ StrictBool | None, Field(description='Provider handles Identity Match requests (POST /identity).'), ] = None countries: Annotated[ list[Country] | None, Field( description="ISO 3166-1 alpha-2 country codes this provider serves. The router filters Identity Match providers by the request's country field. MUST be present and non-empty when identity_match is true.", min_length=1, ), ] = None uid_types: Annotated[ list[uid_type.UidType] | None, Field( description="Identity types this provider can resolve. The router selects Identity Match providers whose uid_types overlaps with any uid_type in the request's identities array. MUST be present and non-empty when identity_match is true.", min_length=1, ), ] = None properties: Annotated[ list[UUID] | None, Field( description='Property RIDs (UUID v7) this provider serves. When present, the router only sends requests from these properties to this provider. When absent, the provider serves all properties.', min_length=1, ), ] = None timeout_ms: Annotated[ SchemaInt | None, Field( description="Per-provider timeout in milliseconds. The router skips this provider if it does not respond within this budget. Must be less than or equal to the router's overall latency_budget_ms. The router may further reduce this based on adaptive timeout allocation.", ge=5, le=5000, ), ] = 50 priority: Annotated[ SchemaInt | None, Field( description='Provider ordering for Context Match offer conflict resolution. Lower values have higher priority. When two providers return offers for the same package_id (a configuration error), the router keeps the offer from the higher-priority provider; equal priorities are broken by first response received. Identity Match eligibility remains a responder-scoped union because silent omission is not a negative vote. Also used for adaptive timeout allocation — higher-priority providers receive a larger share of the latency budget.', ge=0, ), ] = 0 tmpx_slots: Annotated[ list[TmpxSlot] | None, Field( description='Stable provider-local slot identifiers for the ordered TMPX chunks this provider mints. Slot IDs are opaque provider-namespaced tokens (e.g. `["primary","secondary"]`), NOT ad-server macro names — publishers map `(provider_id, slot_id)` → local destination via `tmpx_macro_mapping` in publisher-tmpx-config.json, so the destination namespace stays publisher-owned and the router never accepts a destination name from an untrusted provider. Distinct providers MAY reuse the same slot_id without collision because publisher lookup is keyed on `(provider_id, slot_id)`. Publishers use this list at startup to validate `tmpx_macro_mapping` covers every slot the provider mints and to detect config drift when the provider\'s slot contract changes. Ordering carries the ordered-prefix invariant: a provider that emits fewer chunks than it registered MUST emit an ordered prefix of this list — chunks map to slots in registration order and MUST NOT be shifted, sparse, or reordered. Cap of 2 slots in v1 aligned with the GAM macro-slot budget; the cap MAY rise without a shape change. A provider that emits TMPX (populates `tmpx_chunks` on its identity-match response) MUST register this list; a provider that does not emit TMPX omits it. Schema cannot enforce that predicate because "emits TMPX" is not schema-visible.', max_length=2, min_length=1, ), ] = None status: Annotated[ Status | None, Field( description='Provider lifecycle status. Active providers receive requests. Inactive providers are skipped entirely. Draining providers stop receiving new requests but in-flight requests complete normally.' ), ] = Status.active @field_validator('endpoint') @classmethod def _require_https_endpoint(cls, value: AnyUrl) -> AnyUrl: if value.scheme != 'https': raise ValueError('endpoint must use https') return value @model_validator(mode='after') def _require_identity_match_dimensions(self) -> TmpProviderRegistration1: if self.identity_match is True: if not self.countries: raise ValueError('countries is required when identity_match is true') if not self.uid_types: raise ValueError('uid_types is required when identity_match is true') return selfBase model for AdCP types with spec-compliant serialization.
Defaults to
extra='ignore'so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.Important
The env var is resolved once at module import time. Set it in your shell or CI environment before
import adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport has no effect on already-imported model classes (they captured the policy at class-body evaluation).Consumers who want per-model strict validation can override
model_configon their subclass.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context_match : Literal[True]var countries : list[Country] | Nonevar endpoint : pydantic.networks.AnyUrlvar identity_match : bool | Nonevar model_configvar priority : int | Nonevar properties : list[uuid.UUID] | Nonevar provider_id : strvar status : Status | Nonevar timeout_ms : int | Nonevar tmpx_slots : list[TmpxSlot] | Nonevar uid_types : list[UidType] | None
Inherited members
class TmpProviderRegistration2 (**data: Any)-
Expand source code
class TmpProviderRegistration2(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) provider_id: Annotated[ str, Field( description="Stable identifier for this provider registration. Used in logs, metrics, cache keys, as the key in `signals_by_provider` on Context Match responses and `targeting_kv_mapping` in publisher configuration, and as the key in `tmpx_providers` on Identity Match responses and `tmpx_macro_mapping` in publisher configuration. Publishers assign this — it is not the provider's agent_url. Charset is constrained to a safe alphanumeric/underscore set so the value can appear in operational surfaces (logs, metrics, dashboards) without quoting. See publisher-targeting-kv-config.json and publisher-tmpx-config.json.", max_length=64, min_length=1, pattern='^[A-Za-z0-9_]+$', ), ] endpoint: Annotated[ AnyUrl, Field( description='Base URL the router calls. The router appends /context for Context Match and /identity for Identity Match. MUST be HTTPS in production, validated against the canonical reserved IPv4 and IPv6 ranges, with the TCP connection pinned to the validated IP (DNS re-resolution alone is insufficient against rebinding). Publishers comparing two provider registrations for the same `endpoint` MUST canonicalize both per the AdCP URL canonicalization rules; two registrations differing only in case, default port, or path-slash collapsing are the same provider. See docs/trusted-match/specification#provider-registration-security, docs/building/implementation/security#webhook-url-validation-ssrf, and docs/reference/url-canonicalization.' ), ] context_match: Annotated[ StrictBool | None, Field(description='Provider handles Context Match requests (POST /context).'), ] = None identity_match: Annotated[ Literal[True], Field(description='Provider handles Identity Match requests (POST /identity).'), ] countries: Annotated[ list[Country] | None, Field( description="ISO 3166-1 alpha-2 country codes this provider serves. The router filters Identity Match providers by the request's country field. MUST be present and non-empty when identity_match is true.", min_length=1, ), ] = None uid_types: Annotated[ list[uid_type.UidType] | None, Field( description="Identity types this provider can resolve. The router selects Identity Match providers whose uid_types overlaps with any uid_type in the request's identities array. MUST be present and non-empty when identity_match is true.", min_length=1, ), ] = None properties: Annotated[ list[UUID] | None, Field( description='Property RIDs (UUID v7) this provider serves. When present, the router only sends requests from these properties to this provider. When absent, the provider serves all properties.', min_length=1, ), ] = None timeout_ms: Annotated[ SchemaInt | None, Field( description="Per-provider timeout in milliseconds. The router skips this provider if it does not respond within this budget. Must be less than or equal to the router's overall latency_budget_ms. The router may further reduce this based on adaptive timeout allocation.", ge=5, le=5000, ), ] = 50 priority: Annotated[ SchemaInt | None, Field( description='Provider ordering for Context Match offer conflict resolution. Lower values have higher priority. When two providers return offers for the same package_id (a configuration error), the router keeps the offer from the higher-priority provider; equal priorities are broken by first response received. Identity Match eligibility remains a responder-scoped union because silent omission is not a negative vote. Also used for adaptive timeout allocation — higher-priority providers receive a larger share of the latency budget.', ge=0, ), ] = 0 tmpx_slots: Annotated[ list[TmpxSlot] | None, Field( description='Stable provider-local slot identifiers for the ordered TMPX chunks this provider mints. Slot IDs are opaque provider-namespaced tokens (e.g. `["primary","secondary"]`), NOT ad-server macro names — publishers map `(provider_id, slot_id)` → local destination via `tmpx_macro_mapping` in publisher-tmpx-config.json, so the destination namespace stays publisher-owned and the router never accepts a destination name from an untrusted provider. Distinct providers MAY reuse the same slot_id without collision because publisher lookup is keyed on `(provider_id, slot_id)`. Publishers use this list at startup to validate `tmpx_macro_mapping` covers every slot the provider mints and to detect config drift when the provider\'s slot contract changes. Ordering carries the ordered-prefix invariant: a provider that emits fewer chunks than it registered MUST emit an ordered prefix of this list — chunks map to slots in registration order and MUST NOT be shifted, sparse, or reordered. Cap of 2 slots in v1 aligned with the GAM macro-slot budget; the cap MAY rise without a shape change. A provider that emits TMPX (populates `tmpx_chunks` on its identity-match response) MUST register this list; a provider that does not emit TMPX omits it. Schema cannot enforce that predicate because "emits TMPX" is not schema-visible.', max_length=2, min_length=1, ), ] = None status: Annotated[ Status | None, Field( description='Provider lifecycle status. Active providers receive requests. Inactive providers are skipped entirely. Draining providers stop receiving new requests but in-flight requests complete normally.' ), ] = Status.active @field_validator('endpoint') @classmethod def _require_https_endpoint(cls, value: AnyUrl) -> AnyUrl: if value.scheme != 'https': raise ValueError('endpoint must use https') return value @model_validator(mode='after') def _require_identity_match_dimensions(self) -> TmpProviderRegistration2: if self.identity_match is True: if not self.countries: raise ValueError('countries is required when identity_match is true') if not self.uid_types: raise ValueError('uid_types is required when identity_match is true') return selfBase model for AdCP types with spec-compliant serialization.
Defaults to
extra='ignore'so unknown fields from newer spec versions are silently dropped rather than causing validation errors. Generated types whose schemas setadditionalProperties: trueoverride this withextra='allow'in their ownmodel_config.Set
ADCP_STRICT_VALIDATION=1in the environment ("1","true","yes","on"are accepted) to flip the default toextra='forbid'. Use this during spec upgrades to catch silently-dropped renamed fields in tests. See :func:_resolve_extra_policy.Important
The env var is resolved once at module import time. Set it in your shell or CI environment before
import adcpruns — mutatingos.environ["ADCP_STRICT_VALIDATION"]after the firstadcpimport has no effect on already-imported model classes (they captured the policy at class-body evaluation).Consumers who want per-model strict validation can override
model_configon their subclass.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var context_match : bool | Nonevar countries : list[Country] | Nonevar endpoint : pydantic.networks.AnyUrlvar identity_match : Literal[True]var model_configvar priority : int | Nonevar properties : list[uuid.UUID] | Nonevar provider_id : strvar status : Status | Nonevar timeout_ms : int | Nonevar tmpx_slots : list[TmpxSlot] | Nonevar uid_types : list[UidType] | None
Inherited members
class TmpxMacro (value: Any = <object object>, *, root: Any = <object object>)-
Expand source code
class TmpxMacro(ScalarStr): """Deprecated 3.1.8 registered macro-name compatibility model.""" __slots__ = () _constraints = {'max_length': 64, 'min_length': 1, 'pattern': '^[A-Z][A-Z0-9_]*$'}Deprecated 3.1.8 registered macro-name compatibility model.
Ancestors
- adcp.types._scalar.ScalarStr
- adcp.types._scalar._ScalarRoot
- builtins.str
class TmpxSlot (value: Any = <object object>, *, root: Any = <object object>)-
Expand source code
class TmpxSlot(ScalarStr): __slots__ = () _constraints = {'max_length': 64, 'min_length': 1, 'pattern': '^[a-zA-Z][a-zA-Z0-9_]*$'}A
strgenerated from a JSON Schema string root.Ancestors
- adcp.types._scalar.ScalarStr
- adcp.types._scalar._ScalarRoot
- builtins.str