Skip to content

Attribute adagents.json properties to a publisher domain, gate permissive resolution, and verify cross-domain claims #1697

Closed

Description

@bokelley

Problem

get_properties_by_agent / resolve_properties_for_agent tell a sales agent which properties it is authorized for in one adagents.json. A sales agent syncing that file for a given publisher domain has to make three more decisions that the SDK leaves to it. Each implementation makes them differently, so the same file gives different answers from different agents.

We hit this in a sales agent built on this SDK. It kept a property only when its domain identifier equaled the publisher domain after stripping www./m./mobile.. So a publisher that authorized shop.example.org and ctv.example.org by property_ids in example.org's file lost both: the agent believed it sold only example.org. That rule was our own; the SDK's domain_matches would have handled it with *.example.org. We've moved the agent onto domain_matches, but the remaining decisions belong in the SDK so every agent gets them right.

Requests

1. Attribute a file's properties to a publisher domain

One file is often served at several publisher domains (a media group's shared file), or names a network's publishers. When syncing it for publisher domain D, an agent needs "which of these authorized properties are D's". Suggested helper:

def properties_for_publisher_domain(properties: list[dict], publisher_domain: str) -> list[dict]

Proposed rules, using domain_matches:

  • A property that declares publisher_domain belongs to D when that value names D.
  • Otherwise it belongs to D when a type=domain identifier names D, its www./m. forms, or any subdomain (*.D). A publisher entered as www.D is treated as D.
  • A property with no domain at all (an app identified only by bundle id) is kept, or reported separately for the caller to decide.

2. A domain gate for permissive (bare-entry) resolution

resolve_properties_for_agent(mode="permissive") returns every top-level property when the agent's entry is bare. Without a typed binding, nothing stops a file on attacker.example from bare-listing an agent and claiming another publisher's site, an app bundle or a DOOH venue. Every agent has to add its own gate. Suggestion: an optional publisher_domain= on the permissive mode. It keeps only properties with a type=domain identifier naming that domain or a subdomain, and ignores a property's own publisher_domain claim, since the file isn't attested.

3. Verify cross-domain claims at resolution time

When a file served at A authorizes an agent for a property on another domain B, nothing during resolution confirms that B vouches for it. Vouching would mean B's own adagents.json authorizes the agent, or points to A through authoritative_location or ads.txt MANAGERDOMAIN. fetch_agent_authorizations_from_directory and detect_publisher_properties_divergence cover this from the directory side. A resolver-side option would let sync paths enforce it without depending on a directory. That could be a verify_cross_domain=True flag or a helper that takes a fetcher and returns the verified subset.

Why in the SDK

These are spec-level rules: domain matching, delegation and revocation. The SDK already owns them in domain_matches, identifiers_match, authoritative_location following and revoked_publisher_domains. Keeping attribution, the permissive gate and cross-domain verification next to them means every sales agent applies the same rules.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions