fix(storyboard): refs_resolve follow-ups (#710, #711, #712, #714)#717
Merged
Conversation
Bundle four refs_resolve validator fixes surfaced during adcp#2601 verification: - #710 Canonicalize `$agent_url` by stripping transport suffixes (/mcp, /a2a, /sse, /.well-known/agent[-card].json) while preserving subpath so sibling agents on shared hosts stay distinguishable. Mirrors the SDK's computeBaseUrl. Previously the check was a silent no-op on MCP/A2A agents because the runner's target URL never matched a ref's bare agent URL. - #711 Emit `scope_excluded_all_refs` meta-observation when the scope filter partitions 100% of source refs out — catches silent no-ops without changing pass/fail semantics. Suppressed under `on_out_of_scope: 'ignore'`. - #712 Detect paginated current-step targets and demote unresolved refs to `unresolved_with_pagination` observations instead of failing the check. Stops false-positives against conformant paginating sellers until the spec-level "compliance mode returns all" rule lands. - #714 Harden grader-visible payloads against hostile agent responses: strip userinfo (URL parse + regex fallback for non-URL fields), reject non-http schemes, code-point-safe truncate at 512 chars, cap observations at 50 with truncation marker, use hasOwnProperty throughout. Tests cover each fix plus the security hardening cases flagged in review (surrogate-pair safety, prototype-key guarding, meta-observation ordering under the cap, context-vs-current-step pagination scoping, ignore-mode suppression). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI failures on PR #717: - Code Quality: prettier formatting on the two refs_resolve files edited in this branch. - Test & Build: generated tool types out of sync with upstream `latest` schema bundle, which added five new ListScenarios values (seed_product, seed_pricing_option, seed_creative, seed_plan, seed_media_buy) and refined the scenarios description. Drift is unrelated to this PR — first push to main since the upstream change. Re-ran `prettier --write`, `npm run sync-schemas`, `npm run generate-types`, and `npm run generate-wellknown-schemas`. Tests pass locally (4965/0/6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Downstream review came back as ship it with three follow-ups. Filed:
Two non-PR items the reviewer is taking themselves:
Plus one nit deemed not worth fixing here: `CREDENTIAL_SHAPE_RE` doesn't catch `scheme://@host` (bare `@` with empty user). Edge case; mentioned for completeness. |
CI ci:docs-check failed because docs/llms.txt and docs/TYPE-SUMMARY.md still carry the v5.7.0 generated stamp; the version.ts drift correction in the prior commit bumped the library version stamp to v5.8.0. Re-ran `npm run generate-agent-docs`. Diff is stamp-only (date + version line); no content drift. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Conflict: src/lib/types/schemas.generated.ts — header timestamp only; resolved by regenerating. Auto-merge combined overlapping fixes to src/lib/server/test-controller.ts (main added `| SeedScenario` to the exhaustiveness guard via #716; this branch narrowed `ControllerScenario` to exclude `SeedScenario`). Both survive; functionally equivalent with one redundant exclusion.
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
Bundle of four
refs_resolvevalidator fixes surfaced by security/protocol review on adcontextprotocol/adcp#2601. Each fix closes a dedicated issue and ships with its own changeset.refs_resolve $agent_url should canonicalize transport path before scope compare #710 — Canonicalize
\$agent_urlby stripping transport suffixes (/mcp,/a2a,/sse,/.well-known/agent[-card].json) while preserving subpath. MirrorsSingleAgentClient.computeBaseUrl. Previously, the scope compare degraded to a silent no-op on every MCP/A2A agent because the runner's target URL never equalled the bare agent URL on refs. Path-preserving matters: AdCPagent_urlcan legitimately live under a subpath (https://publisher.com/.well-known/adcp/sales) — origin-only would false-positive sibling agents on shared hosts.refs_resolve: warn when scope filter excludes 100% of source refs #711 — Emit
scope_excluded_all_refsmeta-observation when a scope filter partitions 100% of source refs out. Catches the silent-no-op smell even when the underlying comparison is broken. Suppressed underon_out_of_scope: 'ignore'(which explicitly opts out of scope warnings).refs_resolve: pagination of list_creative_formats target #712 — Detect paginated current-step targets (
pagination.has_more: true) and demote unresolved refs tounresolved_with_paginationobservations instead of failing the check. Stops false positives against conformant paginating sellers.target_paginatedmeta-observation surfaces the partition decision. The spec-level fix (compliance mode requires seller returns all product-referenced formats in a single response) should follow in the AdCP repo.refs_resolve: observations payload hygiene (userinfo strip, size caps, escaping) #714 — Harden grader-visible payloads: strip userinfo via WHATWG URL parsing plus a regex fallback for credential-shaped substrings in non-URL fields; replace non-
http(s)schemes (blocksjavascript:/data:/file:stored-XSS vectors) with a placeholder; code-point-safe truncate at 512 chars; cap observations at 50 withobservations_truncatedmarker; usehasOwnPropertythroughout to prevent storyboard authors from drawing match keys fromObject.prototype.Expert review notes
Routed through code-reviewer, security-reviewer, and ad-tech-protocol-expert before pushing. Key incorporated feedback:
agent_urlexamples (core/format-id.jsonshowshttps://publisher.com/.well-known/adcp/sales). Rewrote to path-preserving + transport-suffix-stripping.#712needs to demote failure → observation, not just annotate. Implemented.javascript:scheme survival,key in refprototype access, pre-truncate ordering. All addressed with dedicated tests.types.ts. All addressed.Observation vocabulary
This PR adds three observation kinds the runner emits on
refs_resolveresults:scope_excluded_all_refs,target_paginated,unresolved_with_pagination, plusobservations_truncatedmarker. The runner-output-contract atcompliance/cache/latest/universal/runner-output-contract.yamlis synced from upstream and doesn't yet enumerate an observation taxonomy — documenting these kinds in the source contract belongs in a follow-up PR against adcontextprotocol/adcp.Test plan
node --test test/lib/storyboard-validations-refs-resolve.test.js— 39 tests, all pass (18 pre-existing + 21 new covering canonicalization, scope warnings, pagination demotion, and each hardening case)npm test— full suite 4965 pass / 0 fail / 6 skippednpm run buildcleanChangesets
Four patch-level changesets, one per closed issue — lets each fix land with its own CHANGELOG entry in the next release PR.
Closes #710, closes #711, closes #712, closes #714.
🤖 Generated with Claude Code