feat(adagents): add validate_adagents_structure helper#708
Merged
Conversation
Distinguishes a schema-invalid adagents.json from a valid file that doesn't list the caller's agent. get_properties_by_agent() collapses both cases into [], which makes "publisher hasn't authorized us yet" indistinguishable from "publisher's file is structurally broken" and forces callers to inspect entries themselves. The new validate_adagents_structure(data) -> AdagentsValidationReport checks every authorized_agents entry against the AdCP schema's oneOf discriminated union (six authorization_type variants, each with a required matching selector). Returns per-entry errors with index, url, kind, and message — so callers like aao_lookup_service can show "publisher's file is invalid" vs "you aren't listed" without re-implementing the schema. The companion helper validate_adagents_domain (network fetch + discovery) is unchanged. Naming pairs with that existing function; avoids collision with the legacy adcp.validation.validate_adagents. Closes #707 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add is_reference flag on AdagentsValidationReport so callers can distinguish a legitimate authoritative_location URL-reference file from an inline file with zero entries (which is itself invalid). - Enforce authorized_agents minItems: 1 on inline variant via new empty_authorized_agents error kind (file-level error, index=-1). - Tighten authorized_for check to require a non-empty string; previously truthy non-strings (e.g., numbers, lists) silently passed. - Normalize empty-string url to None so AdagentsEntryError.url is always either a usable identifier or None. - Export EntryErrorKind from top-level adcp so callers can pattern-match exhaustively. - Cross-link validate_adagents_structure from fetch_adagents docstring; document 3.0 schema target and selector-item validation as out-of-scope. - Tests: 3 new (authoritative_location is_reference, empty array invalid, non-string authorized_for/url) + tighten FrozenInstanceError assertion + non-empty fixture for the immutability test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds AdagentsEntryError, AdagentsValidationReport, EntryErrorKind, and validate_adagents_structure to the snapshot — all intentional additions in this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
validate_adagents_structure(data) -> AdagentsValidationReportinadcp.adagents. Lets callers distinguish a schema-invalid adagents.json from a valid file that doesn't list the caller's agent —get_properties_by_agent()collapses both into[]today, which made the wonderstruck.org-style bare-entry case from feat: helper to distinguish schema-invalid adagents.json from "agent not authorized" #707 indistinguishable from "publisher hasn't authorized us yet."AdagentsValidationReport(withschema_valid,errors,authorized_agents_count,properties_count) andAdagentsEntryError(withindex,url,kind,message). Error kinds:missing_url,missing_authorized_for,missing_authorization_type,unknown_authorization_type,missing_selector_for_type,not_an_object.authorized_agentsentry against the AdCP schema'soneOfdiscriminated union (sixauthorization_typevariants, each with its required selector array).Naming
The issue proposed
validate_adagents; I went withvalidate_adagents_structureto avoid colliding with the existingadcp.validation.validate_adagents(legacy raise-on-error helper, exported at top level and still used internally). The new name pairs cleanly with the existingvalidate_adagents_domain(network fetch + discovery) — domain validates a publisher domain end-to-end, structure validates pre-fetched data per-entry.Closes #707
Test plan
TestValidateAdagentsStructurecovering: all six authorization types valid, bare entries (the wonderstruck case from the issue), unknownauthorization_type, mismatched selector for type, empty selector array (minItems:1), missingurl/authorized_for, non-object entries,authoritative_locationURL-reference variant, non-dict/non-list raises, and the headline "distinguishes invalid file from unlisted agent" case.pytest tests/test_adagents.py— 119 passed.pytest tests/test_adagents.py tests/test_registry_new.py tests/test_registry_types_drift.py tests/test_schema_validation.py— 292 passed.ruff check src/ tests/test_adagents.py— clean.mypy src/— clean (801 source files).🤖 Generated with Claude Code