Skip to content

docs(brand-protocol): RFC — brand verification surface (verify_subsidiary_claim / verify_property / verify_trademark)#4540

Open
bokelley wants to merge 5 commits into
mainfrom
bokelley/verification-endpoint-rfc
Open

docs(brand-protocol): RFC — brand verification surface (verify_subsidiary_claim / verify_property / verify_trademark)#4540
bokelley wants to merge 5 commits into
mainfrom
bokelley/verification-endpoint-rfc

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Draft RFC. Tracks #4521.

Summary

Replaces the originally-proposed typed-notification-endpoint design (push, event-based) with a federated trust surface (pull, interrogative). Three new brand-protocol tasks on the brand-agent let partners ask the brand authoritatively whether something belongs to it:

  • `verify_subsidiary_claim` — "Is this brand a subsidiary of yours?"
  • `verify_property` — "Is this site / app / property actually one of yours?"
  • `verify_trademark` — "Is this trademark one of yours?"

The mental model is DRM for brand identity: the brand owns the answers to "what's mine," and authorized partners can ask before they act. The mutual-assertion crawl model stays as decentralized backstop. The brand-agent verification path is the federated alternative for brands that opt in.

Why this shape

Three real gaps in the crawl-only model:

  1. Two-state visibility. Crawl answers "mutual or not." Can't surface pending review, disputed, licensed in.
  2. TTL-bound freshness. Consumer view is only as fresh as last crawl.
  3. One-sided pessimism. A leaf with TLS-verified identity gets downgraded to "unverified" until the parent edits its portfolio file.

The interrogative surface fixes all three. Authoritative answers, real-time, with the rich state surface partners actually need (especially `pending_review` and `disputed`).

What's in this PR

  • One proposal doc at `docs/brand-protocol/proposals/brand-verification-rfc.mdx` — motivation, design, trust model, open questions
  • Three task docs at `docs/brand-protocol/tasks/verify_*.mdx`
  • Seven schemas:
    • Shared status enum: `brand/verification-status.json`
    • Three request/response pairs
  • brand.json Conformance update: one SHOULD that agent path is preferred when advertised
  • docs.json nav updated under brand-protocol Tasks
  • Changeset noting draft RFC status

Validation

  • `npm run build:schemas` clean
  • `npm run test:schemas` 7/7
  • `npm run test:examples` 36/36
  • `npm run test:json-schema` 260/260
  • `npm run test:composed` 40/40
  • `npm run typecheck` clean

Open questions (in the RFC doc, repeated here for visibility)

  1. `verify_property` use_case scoping — keep?
  2. `pending_review` queue position / resolution window — public vs authorized-only?
  3. Agent-says-not_ours vs leaf-says-house — UI guidance for "disputed" rendering
  4. Rate-limiting policy — agent's call but spec sets expectations
  5. Bulk variants — defer or include in v1?

Test plan

  • Spec-owner review of the surface (interrogative vs notification framing)
  • Trust-model review (agent-wins, crawl-backstop)
  • Decision on the five open questions
  • Land only after the design review

Related

🤖 Generated with Claude Code

bokelley and others added 2 commits May 14, 2026 09:34
Draft RFC for a federated trust capability on the brand-agent — three
interrogative tools that let partners ask the brand authoritatively
whether something belongs to it. Reframes the email-based self-healing
SHOULD from PR #4505 as a richer pull-based DRM-for-brand-identity
surface.

New tasks (all brand-protocol, advertised in get_adcp_capabilities):
- verify_subsidiary_claim — replaces crawl inference for is-this-a-leaf
- verify_property — authoritative ownership of websites/apps/etc
- verify_trademark — licensing + jurisdiction + Nice class

Shared VerificationStatus enum captures rich state crawl cannot express:
owned / pending_review / disputed / not_ours / licensed_in / licensed_out
/ unknown. Public/authorized tier split mirrors get_brand_identity.

Cross-protocol: brand.json Conformance gains a SHOULD that when a house
publishes a brand-agent advertising these tasks, consumers prefer the
agent's signed response over crawl-based mutual-assertion inference. The
email-notification SHOULD continues to apply as a fallback when no
brand-agent is advertised. The RFC supersedes the typed-notification-
endpoint design originally sketched in #4521 — the verification surface
is interrogative, not notification-based.

Additive — no changes to brand.json itself; no migration burden.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oduct/docs (#4540)

Address all blockers and strong-should-fix items from the three-expert
review on PR #4540. Open questions resolved with consensus positions
baked into the contract.

Schemas
- Fix oneOf discriminator: success arm now carries symmetric not.errors,
  matching the error arm. Mirrors search-brands-response.json convention.
- Per-tool status enum subsets — verify_property excludes pending_review
  and licensed_in/out; verify_trademark excludes pending_review;
  verify_subsidiary excludes licensed_in/out. Each tool's response
  constrains the shared VerificationStatus to its applicable set.
- Add `transferring` to VerificationStatus — M&A in flight is distinct
  from pending_review.
- Drop redundant `license_type` from verify-trademark-response (status
  already carries the licensing relationship).
- Field-name consistency: `context_note` everywhere (verify_subsidiary
  previously had `dispute_reason`).
- `regions` empty-array ambiguity resolved with `"global"` sentinel
  matching request schema.
- Use-case authorization gains a registered starter set (advertising,
  endorsement, retail_listing, editorial, commercial_advertising,
  merchandise_resale) with additionalProperties: boolean for extensions.
- pending_review now REQUIRES expected_resolution_window_days; agents
  MUST transition or flip to unknown past the window.

RFC doc
- Conflict resolution promoted from open question to normative trust
  model. Full table covering all status × crawl-observation combinations.
- Signing key corrected: adcp_use: "response-signing" (not request-signing).
  Per the keys-per-purpose convention.
- "DRM-shaped" stays as analogy; lead framing is "federated authoritative
  verification" — what the spec audience actually wants.
- Motivation honest about what the surface does NOT fix: the sub-brand
  self-publishing problem is relocated, not solved. Partner gets typed
  state instead of silence; brand-side workflow gap remains.
- verify_property reframed: not a bid-time tool (sub-100ms budgets);
  inventory onboarding / supply-path curation / fraud / clearance.
- verify_trademark differentiator foregrounded: registries can't tell
  you authorized use cases or licensee posture.
- Deployment model section added: AAO-hosted as managed service for
  most members; self-hosted for holdcos/agencies with bandwidth; no
  brand-agent as graceful-degradation path.
- End-to-end Nike worked example added — six steps from discovery
  through full portfolio verification with cache guidance.
- Caching as normative SHOULD per-status (was prose).
- Rate-limiting as normative expectation: Retry-After header,
  prefer-cached-prior over hard error.
- Prior art expanded: ads.txt for inventory authority (complementary),
  WHOIS/RDAP for domain registration (different layer), trademark
  registries (registration facts only). No direct equivalent today.
- check_competitive_relationship moved to "indefinitely deferred"
  (politically loaded; brands won't publicly enumerate enemies).
- Authorization-tier table promoted to single authoritative source;
  task pages refer back.
- Resolved-decisions section replaces Open Questions.

Task pages
- Parallelism fixed for RAG retrieval: each page inlines core content
  (trust model row-table, caching, error codes) rather than cross-
  referencing back to verify_subsidiary_claim. Cross-links remain for
  full normative detail.
- Each page adds Capability discovery snippet showing get_adcp_capabilities
  advertisement.
- Each page's CodeGroup includes a Response (error) example.
- verify_property "When to use" reframed away from bid-time.
- verify_trademark leads with the differentiator vs registries.

Nav and Conformance
- docs.json: new Proposals group under brand-protocol nav surfaces the
  RFC.
- brand-json Conformance bullet updated to cite the correct signing
  key (response-signing) and call out that signed disputed/not_ours
  overrides leaf-side house_domain claims.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley and others added 3 commits May 14, 2026 10:47
… baseline

CI check test:oneof-discriminators flagged the three new verification
response schemas as undiscriminated oneOfs. They follow the same shape
as the existing brand-protocol responses already in the baseline
(get-brand-identity-response, search-brands-response, etc.) — success
arm required:[status] vs error arm required:[errors] — and don't have
a natural cross-arm discriminator beyond the existing required-field
asymmetry.

Ratcheting the baseline via --update --accept-new is the documented path
for this pattern. The three entries:
- brand/verify-property-response.json
- brand/verify-subsidiary-claim-response.json
- brand/verify-trademark-response.json

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ify aging contract enforcement

Two pieces of feedback addressed.

Verification as a gate, not a signal
- verify_property and verify_subsidiary_claim now lead with "this is a
  prerequisite gate — check before you proceed, not after." The gating
  semantics are what justify the round-trip cost; consuming the answer
  post-decision means you're using the wrong tool.
- When-to-use sections reframed around gating points: inventory
  onboarding (gate the catalog entry), creative clearance (gate
  approval), fraud escalation (gate the action), brand-relationship
  establishment (gate governance trust extension).
- verify_trademark already framed correctly; minor lead tightening.

pending_review aging contract honesty
- MUST language stays — declared intent + defined fallback is better
  than today's silent pending limbo. But the enforcement story now
  reads as it actually is: agent-side, not spec-level. Most brand-side
  day-one deployments won't ship automated pending→unknown flipping.
- New dedicated subsection in the RFC: "pending_review aging and the
  crawl safety net." Spells out: enforcement is agent-side; day-one
  deployments will lag; consumer-side fallback to crawl on stale
  pending_review IS the safety net; MUST is fine because the fallback
  is graceful.
- Trust-model row updated to instruct consumers to treat stale
  pending_review as effectively unknown.
- Resolved-decision #2 points at the new section.
- verify_subsidiary_claim task page mirrors the same framing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_property request

Platform-agnosticism lint flagged the store enum in
brand/verify-property-request.json (apple/google/amazon/roku) because
the new file path doesn't match the existing brand.json allowlist
entries. Same canonical-identifier justification applies: these are
the names of the app stores, not vendor-promotional values.

Factoring the store enum into a shared enums/property-store.json
(referenced from both brand.json and the verify_property request) is
the right long-term cleanup — protocol-expert review flagged it on
PR #4540. Tracking separately; for now the allowlist mirrors the
existing brand.json pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant