Two coupled findings from the three-expert review of #3962. Both touch the new `upstream_traffic` adoption.
A. Meta-shape over-fit in `payload_must_contain`
`sales-social/sync_audiences` and `audience-sync/create_audience` declare:
```yaml
payload_must_contain:
- path: "users[*].hashed_email"
match: present
```
That path assumes the upstream POST body has a top-level `users[]` with `hashed_email` per user — Google Customer Match / Meta CAPI nesting. Won't match TikTok (`data.audience.members[].email_hash`), Snap (`payload.data.list[].hash`), Pinterest (`audience.users[].HASHED_EMAIL`), or any non-Google/Meta shape. Storyboard fails for adopters whose upstream isn't Meta-shaped.
Fix: drop the `payload_must_contain` block on these two storyboards entirely. `identifier_paths` already does the value-echo verification across upstream shapes (it asserts the storyboard-supplied identifier value appears in the recorded payload at any depth — shape-agnostic). The path-shape assertion adds nothing the value-echo doesn't already cover, and over-constrains adopters whose upstream isn't Meta.
Storyboards in `adcontextprotocol/adcp`:
- `static/compliance/source/specialisms/sales-social/index.yaml` (sync_audiences step)
- `static/compliance/source/specialisms/audience-sync/index.yaml` (create_audience step)
B. Extend identifier-echo across related steps to the other 4 storyboards
`sales-social` is the only storyboard that uses the cross-step pattern: `sync_audiences` adds `hashed_email` in `add[]`, then `log_event` references the same `hashed_email` in `user_match`. The runner verifies both steps echo the same identifier upstream — the strongest anti-façade signal because a façade can't satisfy it by emitting some POST; it has to round-trip the buyer's specific identifier across two related calls.
The other 4 storyboards adopting `upstream_traffic` only assert single-step `min_count` or single-step `identifier_paths`. The pattern generalizes:
- signal-marketplace: `search_by_spec` returns `signal_id` → `activate_on_platform` should reference the same `signal_id` upstream.
- sales-non-guaranteed: `create_media_buy` returns `media_buy_id` → delivery / pacing steps should reference it upstream.
- creative-ad-server: `build_creative` returns `creative_id` → delivery / impression steps should reference it upstream.
- audience-sync has `discover` then `create` steps where similar echo could apply.
Each adoption is a small storyboard edit:
- Identify the cross-step identifier (signal_id, media_buy_id, creative_id, etc.).
- Add `identifier_paths` to the downstream step's `upstream_traffic` validation referencing the captured identifier.
- Optionally add `since: <prior_step_id>` so the assertion window scopes to traffic caused after the prior capture.
Why bundle these
Both are about the same surface (the 5 storyboards that adopted `upstream_traffic` in #3962) and both improve the anti-façade signal — A removes false-positive shape constraints, B adds true-positive echo verification. Single PR.
References
Two coupled findings from the three-expert review of #3962. Both touch the new `upstream_traffic` adoption.
A. Meta-shape over-fit in `payload_must_contain`
`sales-social/sync_audiences` and `audience-sync/create_audience` declare:
```yaml
payload_must_contain:
match: present
```
That path assumes the upstream POST body has a top-level `users[]` with `hashed_email` per user — Google Customer Match / Meta CAPI nesting. Won't match TikTok (`data.audience.members[].email_hash`), Snap (`payload.data.list[].hash`), Pinterest (`audience.users[].HASHED_EMAIL`), or any non-Google/Meta shape. Storyboard fails for adopters whose upstream isn't Meta-shaped.
Fix: drop the `payload_must_contain` block on these two storyboards entirely. `identifier_paths` already does the value-echo verification across upstream shapes (it asserts the storyboard-supplied identifier value appears in the recorded payload at any depth — shape-agnostic). The path-shape assertion adds nothing the value-echo doesn't already cover, and over-constrains adopters whose upstream isn't Meta.
Storyboards in `adcontextprotocol/adcp`:
B. Extend identifier-echo across related steps to the other 4 storyboards
`sales-social` is the only storyboard that uses the cross-step pattern: `sync_audiences` adds `hashed_email` in `add[]`, then `log_event` references the same `hashed_email` in `user_match`. The runner verifies both steps echo the same identifier upstream — the strongest anti-façade signal because a façade can't satisfy it by emitting some POST; it has to round-trip the buyer's specific identifier across two related calls.
The other 4 storyboards adopting `upstream_traffic` only assert single-step `min_count` or single-step `identifier_paths`. The pattern generalizes:
Each adoption is a small storyboard edit:
Why bundle these
Both are about the same surface (the 5 storyboards that adopted `upstream_traffic` in #3962) and both improve the anti-façade signal — A removes false-positive shape constraints, B adds true-positive echo verification. Single PR.
References