Skip to content

agentscore-commerce 1.8.0 — signer field + signer_sanctions surface - #19

Merged
vvillait88 merged 8 commits into
mainfrom
tec-295-signer-sanctions
May 11, 2026
Merged

agentscore-commerce 1.8.0 — signer field + signer_sanctions surface#19
vvillait88 merged 8 commits into
mainfrom
tec-295-signer-sanctions

Conversation

@vvillait88

Copy link
Copy Markdown
Contributor

Summary

Python-side mirror of agentscore/node-commerce#18. Switches the assess call inside verify_wallet_signer_match (sync + async) to use the renamed signer field.

  • identity/client.py: assess(..., resolve_signer=...)assess(..., signer=...)
  • agentscore-py peer-dep >=2.1.0>=2.2.0
  • Version 1.7.01.8.0
  • [tool.uv.sources] block routes uv to editable ../python-sdk for stacked-dev resolution (drops in a follow-up once python-sdk 2.2.0 publishes)

CI install will fail until python-sdk 2.2.0 publishes. Local tests pass via the editable source.

Out of scope

Renaming verify_wallet_signer_matchget_signer_verdict() synchronous getter is a deeper architectural refactor (6 framework adapters × cache evolution) and ships as its own minor bump once this wire contract settles.

Test plan

  • uv run pytest tests/ — 902/902 pass (with --all-extras)
  • uv run ruff check . clean
  • uv run ty check agentscore_commerce/ clean
  • CI green (after python-sdk 2.2.0 publishes)
  • Publish 1.8.0 once python-sdk 2.2.0 is live (unblocks store dep bump)

🤖 Generated with Claude Code

vvillait88 and others added 4 commits May 11, 2026 08:28
…e 2c)

Python-side mirror of agentscore/node-commerce#TBD. The minimum-viable
wire change: switch the assess() call inside verify_wallet_signer_match
(sync + async) to use the renamed `signer` field that the api change
in agentscore/core#TBD requires.

* identity/client.py: assess(..., resolve_signer=...) ->
  assess(..., signer=...) on both sync (verify_wallet_signer_match)
  and async (averify_wallet_signer_match) paths
* identity/client.py: import ResolveSigner -> Signer to match the
  rename in agentscore-py 2.2.0
* identity/types.py: comment refers to `signer` not `resolve_signer`
* tests/test_signer_match.py: same rename
* vulture_whitelist.py: ResolveSigner -> Signer

pyproject.toml:
  version 1.7.0 -> 1.8.0
  agentscore-py >= 2.1.0 -> >= 2.2.0 (blocked on python-sdk publish)
  added [tool.uv.sources] editable path to ../python-sdk for local dev

Tests: 51/51 in test_signer_match.py pass with the editable
local agentscore-py. The 5 pre-existing failures in test_lifted_helpers
and test_payment_servers come from optional peer deps `x402` and `mpp`
not being installed; they're orthogonal to TEC-295.

Out of scope: rename verify_wallet_signer_match -> get_signer_verdict
synchronous getter reading off cached assess response. The
architectural refactor across 6 framework adapters + cache evolution
ships as its own minor bump once the wire contract is settled.

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

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The prior commit broke local + CI dev resolution because agentscore-py 2.2.0
isn't published yet. The sources block routes uv to the editable local
python-sdk so the type imports resolve. CI will be red on this branch until
agentscore/python-sdk#TBD publishes 2.2.0; expected for a stacked PR.

Once 2.2.0 publishes we can land a follow-up that drops the sources block
since uv will then resolve from PyPI directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread vulture_whitelist.py
Comment thread agentscore_commerce/identity/client.py
@vvillait88

Copy link
Copy Markdown
Contributor Author

Both inline comments from @github-code-quality are false positives:

vulture_whitelist.py:19 — The bare Signer # noqa: F821 statement is the established vulture-whitelist pattern in this file; every entry on lines 1-21 has the same shape. It references the type so vulture doesn't flag it as dead code (the actual usage is in string-literal cast("Signer", {...}) calls that vulture's AST walk doesn't follow). Tuple/list form would change file conventions unnecessarily.

client.py:48 — Both DecisionPolicy and Signer ARE used, just via string-literal casts:

  • DecisionPolicycast("DecisionPolicy | None", ...) at lines 268 and 319
  • Signercast("Signer", {...}) at lines 559 and 630

String-cast type references are valid Python (PEP 484) and resolve correctly under ty / mypy. The bot's linter only walks runtime references, hence the false positive. ty check clean confirms both imports are properly used at the type layer.

Drops verify_wallet_signer_match / VerifyWalletSignerMatchOptions /
extract_payment_signer_address / signer_match_by_signer cache slot. Gate
adapters now extract the payment signer pre-evaluate (extract_payment_signer
on the x402 header) and pass {address, network} to /v1/assess. Merchants
read both signer_match (wallet-binding) and signer_sanctions (OFAC SDN
wallet-address) verdicts back via get_signer_verdict(request) — single
round trip, synchronous cache read, no extra HTTP.

All 6 adapters (fastapi, flask, django, aiohttp, sanic, middleware)
extract signer up front and expose get_signer_verdict. GateClient.check
/ acheck / check_identity / acheck_identity accept signer kwarg; raw
response cached parallel to projected AssessResult. SignerVerdict
dataclass returned from get_signer_verdict (was previously a dict cast
to dataclass — attribute access now actually works). Examples and
CLAUDE.md / README.md migrated. tests/test_get_signer_verdict.py
covers all 6 adapters + projection.
Comment thread agentscore_commerce/identity/types.py
Was dict[str, Any] | None — erased the discriminated union that node-commerce
preserves and that the python-sdk publishes. Re-imports SignerSanctions from
agentscore-py and re-exports it from identity/. Cross-language parity now
holds: both commerce flavors expose the same 3-arm union (clear / sanctioned /
unavailable).
agentscore-py 2.2.0 was renumbered to 2.3.0 to leapfrog the yanked 2.2.1
(ghost publish on PyPI). Bumping the dep range in lockstep.
…tscore-py 2.3.0

agentscore-py 2.3.0 is live on PyPI (yanked-2.2.1 leapfrog complete). Dropping
the local editable-path source so uv resolves the dep from the registry
and CI sync works without sibling-repo checkout.
@vvillait88

Copy link
Copy Markdown
Contributor Author

Followup on the third bot inline comment (types.py:6 "Network" is unused): also a false positive.

Network is re-exported via from agentscore import Network as Network so vendor code can do from agentscore_commerce.identity import Network. Internally it's used as a parameter type annotation in 7 adapter files (capture_wallet(..., network: Network, ...) etc.):

  • fastapi.py:43, 349
  • flask.py:36, 318
  • django.py:37, 297
  • aiohttp.py:36, 317
  • sanic.py (same pattern)
  • middleware.py:38, 349
  • client.py:41, 445, 467

The bot's linter only walks runtime references inside expressions; PEP 484 as Name re-exports + cross-file type-annotation usage are both invisible to it. Real linters all pass: ruff check, ty check, vulture ✅.

@vvillait88
vvillait88 merged commit c906b26 into main May 11, 2026
7 checks passed
@vvillait88
vvillait88 deleted the tec-295-signer-sanctions branch May 11, 2026 19:03
@vvillait88 vvillait88 changed the title agentscore-commerce 1.8.0 — signer field + signer_sanctions surface (TEC-295 Phase 2c) agentscore-commerce 1.8.0 — signer field + signer_sanctions surface May 12, 2026
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