Skip to content

feat(ucp): identity capability is config-only static policy (1.6.0) - #17

Merged
vvillait88 merged 11 commits into
mainfrom
feat/ucp-identity-config-mode
May 11, 2026
Merged

feat(ucp): identity capability is config-only static policy (1.6.0)#17
vvillait88 merged 11 commits into
mainfrom
feat/ucp-identity-config-mode

Conversation

@vvillait88

Copy link
Copy Markdown
Contributor

Summary

  • The sh.agentscore.identity UCP capability now declares static merchant policy as config (an AgentScoreGatePolicy), not as runtime per-operator claims. Per-operator identity attestation lives at the AP2 risk-signal endpoint, never inside the public profile.
  • get_agentscore_data(request) (per-operator runtime helper, renamed from get_assess_data for cross-language brand alignment with node-commerce's getAgentScoreData) is unchanged in behavior.

Breaking changes

  • build_ucp_profile's data kwarg removed; pass agentscore_gate instead.
  • _AGENTSCORE_CAPABILITY_VERSION bumped to "2026-04-08" (date format).
  • get_assess_data adapter helpers renamed to get_agentscore_data across all 6 framework adapters (fastapi, flask, django, aiohttp, sanic, middleware).
  • Cross-lang fixtures data-driven-claims / typed-claims removed; replaced with agentscore-gate-full / agentscore-gate-blocked.

Why

Mixing static merchant policy with per-request operator claims in one capability binding made the UCP profile drift on every request and conflated two layers. UCP is the public, cacheable declaration; AP2 is the per-operator runtime attestation. Profile must stay deterministic across requests.

Test plan

  • uv run pytest — 872 passing, 95.10% coverage
  • uv run ruff check
  • uv run ty check agentscore_commerce/
  • Cross-lang parity tests passing (node + python emit byte-identical canonical UCP bodies)

🤖 Generated with Claude Code

vvillait88 and others added 11 commits May 10, 2026 15:34
The UCP `sh.agentscore.identity` capability declares the merchant's gate
policy as `config` (a static AgentScoreGatePolicy), not as runtime claims.
Per-operator identity attestation lives at the AP2 risk-signal endpoint, not
in the public profile.

Breaking changes:
- `build_ucp_profile`'s `data` kwarg removed; pass `agentscore_gate` instead
- `_AGENTSCORE_CAPABILITY_VERSION` bumped to "2026-04-08" (date format)
- `get_assess_data` adapter helpers renamed to `get_agentscore_data` for
  cross-language brand alignment with node-commerce
- Cross-lang fixtures `data-driven-claims` / `typed-claims` removed;
  replaced with `agentscore-gate-full` / `agentscore-gate-blocked`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A2AAgentCardCapabilities.endpoints was `list[dict[str, str]]` (arbitrary
key/value), now a `list[A2AAgentCardEndpoint]` TypedDict mirroring node's
`{ name: string; path?: string; method?: string }[]` contract. Dict literals
still satisfy the type so call sites are unchanged.

Also drops the stale "1.4.0" version pin from the README's stability note.

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

The `capability` cross-lang fixture's hand-crafted UCPCapabilityBinding for
sh.agentscore.identity carried `version: "1"` (the pre-refactor scheme).
Bumped to "2026-04-08" so vendor copies of our capability shape match what
the SDK auto-injects today. Regenerated all 10 cross-lang fixtures (fresh
keys + signatures) and mirrored both languages' fixture sets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three spec-compliance fixes after auditing against the canonical UCP profile schema
and A2A v1.0 proto definitions:

1. A2A AgentCard refactored to match the canonical proto at
   github.com/a2aproject/A2A/blob/main/specification/a2a.proto. Old shape used
   invented `protocol_version` / `card_version` / `endpoints[]` fields and put
   `extensions[]` at top level; spec puts extensions inside `capabilities`,
   uses `version` (agent semver), `supported_interfaces` (typed protocol
   bindings), top-level `skills` of `AgentSkill` objects, and required
   `default_input_modes` / `default_output_modes`. New dataclasses:
   `A2AAgentInterface`, `A2AAgentProvider`, `A2AAgentSkill`. The `data:
   AssessResult` parameter and `identity` block are removed; A2A spec uses a
   separate `AgentCardSignature` (RFC 7515 JWS) for identity.

2. `A2AAgentCardExtension` now carries `description` (required) and `required`
   (bool) per spec §4.4.4. `ucp_a2a_extension()` helper sets both.

3. `sh.agentscore.payment.stripe-spt` violated UCP reverse-DNS regex
   `^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9_]*)+$` — hyphens forbidden in segment
   chars. Renamed to `sh.agentscore.payment.stripe_spt`. Schema URL slug,
   spec page slug, and JSON file path migrated to snake_case for consistency.

Plus two runtime validators added:
- `UCPServiceBinding.to_dict()` raises when transport is rest/mcp/a2a and
  endpoint is None (spec service.json business_schema requires endpoint for
  these transports; embedded MAY omit it).
- `UCPPaymentHandlerBinding.to_dict()` drops `available_instruments` when
  the list is empty (spec payment_handler.json requires `minItems: 1`).

Cross-lang fixtures regenerated (the `extras-int` fixture's stripe-spt key
changed to stripe_spt; all 10 fixtures now carry fresh signatures).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The README's identity-publishing example for build_a2a_agent_card used the
pre-refactor shape (capabilities=A2AAgentCardCapabilities(...) + data=
assess_result + no version / description / skills). Update to the
spec-compliant inputs (top-level description, version, skills as
A2AAgentSkill objects, extensions inside capabilities via the helper).

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

Three more A2A spec items from re-reading the proto:

- `skills` is REQUIRED per spec §4.4.1 (proto field 12,
  [field_behavior=REQUIRED]). Old code accepted empty list. Now
  build_a2a_agent_card raises ValueError when skills is empty/None;
  callers must declare ≥1 AgentSkill (or construct A2AAgentCard
  directly to bypass).

- `icon_url` (proto field 14, optional) added to A2AAgentCard +
  build_a2a_agent_card.

- `signatures` (proto field 13, optional, list of AgentCardSignature
  per §4.4.7) added to A2AAgentCard + build_a2a_agent_card. New
  A2AAgentCardSignature dataclass: protected (REQUIRED), signature
  (REQUIRED), header (optional). Verifiers compute over the canonical
  card body MINUS this field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The UCP project publishes the MCP shopping openrpc at
\`https://ucp.dev/services/shopping/mcp.openrpc.json\` (per
github.com/Universal-Commerce-Protocol/ucp source/services/shopping/).
Our SDK was emitting \`openrpc.json\` without the \`mcp.\` prefix.
Cross-lang fixtures regenerated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Activity, Classification, Identity, Reputation, ScoreDetail, Grade, ScoreStatus
are reputation-API shapes that live in agentscore-py. python-commerce was
duplicating them locally as @DataClass copies; agentscore-py has them as
TypedDict. Vendors who need these should import from agentscore-py directly.

Removes the duplicates from agentscore_commerce/identity/types.py and from
the public __all__. Mirrors node-commerce's tighter module boundary
(@agent-score/commerce doesn't re-export reputation types either).

OperatorVerification, PolicyCheck, PolicyResult kept — those are gate-relevant
(consumed by AssessResult and the policy module) and not reputation types.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both within existing constraints. Lockfile-only change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vvillait88
vvillait88 merged commit be729ad into main May 11, 2026
7 checks passed
@vvillait88
vvillait88 deleted the feat/ucp-identity-config-mode branch May 11, 2026 01:03
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