feat(aao): re-introduce ?include=properties on directory inverse-lookup (#4890)#4894
Conversation
…nt (#4890) Re-introduces the include=properties query parameter deferred from #4836's counts-only v1. Each PublisherEntry carries property_ids[] when requested, so SDK divergence detectors can compare resolved property sets — not just counts — against a federated fetch. Spec-only; server impl tracked separately, parallel to the #4823 → #4836 pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Spec-only re-introduction of a deferred field, correctly scoped. Closing a count-vs-set false-negative trap in the divergence detector is the right primitive at the right layer.
Things I checked
- Schema/docs/example/changeset coherence — the worked example (
docs/aao/directory-api.mdx:130-142), the field-reference row (:164), the schema description (static/schemas/source/aao/agent-publishers.json:78-82), and the changeset prose all agree on shape, gating, scope, and order-unspecified. No drift, no required-flip, no type change. property_idscorrectly omitted fromPublisherEntry.required[]— conditional on?include=properties, absent otherwise.additionalProperties: falsestays in place atPublisherEntry(line 115).- Field naming matches canonical AdCP usage —
property_idsis whatcore/publisher-property-selector.json,adagents.jsonselectors, andapplies_to_property_idsalready use. Noproperties[]/property_id_listdrift. - Empty-frontmatter changeset (
---\n---) matches the sibling AAO PR convention (#4823, #4836, #4855). Intentional, not a defect. - Query-parameter encoding inherits the repeated-key rule pinned in #4855 (
?include=propertiesrepeats the key, same as?status=). Unknown values return 400. Consistent. - "Out of scope" entry correctly narrowed from "Inline property detail" (which deferred
?include=propertiesentirely) to "Full property objects inline" — accurate now that IDs are in scope and only the full objects are deferred. - Wire-compatibility: adding an optional response field gated by an opt-in query parameter is non-breaking. No in-production client is exposed;
minorchange shape is correct.
Follow-ups (non-blocking — file as issues or fold into the server impl PR)
-
Add
uniqueItems: truetoproperty_ids.static/schemas/source/aao/agent-publishers.json:78-82. The description asserts "treat as a set; order is unspecified" four times across docs and schema, but the schema doesn't encode it. Sibling selector arrays do —core/publisher-property-selector.json:26-27,93-94andadagents.json:265-266,288-289both pinuniqueItems: true. Without it, two conforming directories can emit["p-001","p-001","p-002"]vs["p-001","p-002"]and SDKs running raw set-diff disagree. The whole PR is about removing this class of inconsistency at the count layer; leaving it open at the ID layer reproduces it one level down. (ad-tech-protocol-expertflagged.) -
Pin empty-array semantics. When
properties_authorized: 0and?include=propertiesis set, isproperty_ids[], absent, ornull? Docs imply[]. One sentence in the field-reference row. -
Server impl is the load-bearing follow-up —
getPublishersForAgentDetailinserver/src/db/federated-index-db.ts, route handler inserver/src/routes/registry-api.ts, ZodAgentPublishersEntrySchema, regeneratedstatic/openapi/registry.yaml. Integration test parallel to the existing detail-row tests. Mirror in adcp-client (TS/JS), adcp-client-python, adcp-go.
Minor nit (non-blocking)
Three checkboxes in the PR body's test plan, zero check marks. The claims behind them ("Schema JSON parses," "Docs render," "Changeset present") are all visible-in-diff or asserted in prose — not a substantive gap, but the boxes themselves are paper trail worth ticking.
LGTM. Follow-ups noted below.
Summary
Re-introduces the
?include=propertiesquery parameter deferred from #4836's counts-only v1. When set, eachPublisherEntryinGET /v1/agents/{agent_url}/publisherscarries aproperty_ids: list[string]field — the canonical IDs the agent's selectors resolve to under that publisher.Closes #4890.
Why
Count-equality is not set-equality. A publisher rotating N properties leaves
properties_authorizedunchanged while the underlying set is entirely different. The SDK divergence detector (adcp-client-python#752) currently short-circuits to "no divergence" on count match — missing routine rotations against managed-network parent files (the cafemedia ~6,800-publisher shape).property_ids[]lets divergence detectors run full set-diff against a federated fetch.Scope
Spec-only (schema + docs + changeset), parallel to the #4823 → #4836 pattern. Server implementation tracked as a follow-up.
static/schemas/source/aao/agent-publishers.json— addproperty_ids: array<string>toPublisherEntry, optional (present iffinclude=properties).docs/aao/directory-api.mdx— document theincludequery parameter, worked example, response shape, field reference, and recommended workflow for divergence detectors. Update "Out of scope" since?include=propertiesis no longer deferred.Follow-ups
include=propertiesthroughgetPublishersForAgentDetailinserver/src/db/federated-index-db.tsand the route handler inserver/src/routes/registry-api.ts. Update the Zod response schema (AgentPublishersEntrySchema) and regeneratestatic/openapi/registry.yaml. Integration test parallel to the existing detail-row tests.detect_publisher_properties_divergenceto populatePublisherDivergence.missing_in_inline/.missing_in_federatedfromproperty_ids. Mirror in adcp-client (TS/JS) and adcp-go.Test plan
includerow in the query-parameters table and the worked example.🤖 Generated with Claude Code