From 53c59ed73b42be7ad18e43c020215dc407dd94a7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 06:17:40 +0000 Subject: [PATCH] Revert "fix(discovery): quote opaque tier probes safely (#102)" This reverts commit 83b74be330b8c9aafd624b3dc6cd1160b940d01d. --- docs/INTERFACE.md | 2 +- live/guild/app/__init__.py | 8 ++--- live/guild/app/main.py | 28 +++++----------- live/guild/contract/contract.json | 2 +- .../tests/test_discovery_probe_paid_routes.py | 32 ------------------- server.json | 2 +- 6 files changed, 13 insertions(+), 61 deletions(-) diff --git a/docs/INTERFACE.md b/docs/INTERFACE.md index 58eaa14..b938e57 100644 --- a/docs/INTERFACE.md +++ b/docs/INTERFACE.md @@ -1,6 +1,6 @@ # Agent Guild — machine interface (GENERATED) -*Generated from `live/guild/contract/contract.json` v2 (service 2.5.16). Do not edit by hand — run `make contract`.* +*Generated from `live/guild/contract/contract.json` v2 (service 2.5.15). Do not edit by hand — run `make contract`.* - Host: https://agent-guild-5d5r.onrender.com - MCP (streamable HTTP): https://agent-guild-5d5r.onrender.com/mcp/ diff --git a/live/guild/app/__init__.py b/live/guild/app/__init__.py index 127db99..211e39f 100644 --- a/live/guild/app/__init__.py +++ b/live/guild/app/__init__.py @@ -3,12 +3,8 @@ # Single source of truth for the service version. Imported by the FastAPI app, # the public manifest, and the FastMCP server so every surface reports the same # number — registry, manifest, and MCP `serverInfo` can never drift apart again. -__version__ = "2.5.16" # PATCH (machine-visible semver, 2026-08-14): - # lets generic registries safely probe a parameterized - # protected tier with an opaque placeholder while any - # executing retry still fails before settlement. - # History of 2.5.15: adds the singular OpenAPI path - # example still used by +__version__ = "2.5.15" # PATCH (machine-visible semver, 2026-08-14): + # adds the singular OpenAPI path example still used by # MPPScan so the last tier route is discoverable by # generic machine registries. History of 2.5.14: makes # every paid route quoteable by generic machine diff --git a/live/guild/app/main.py b/live/guild/app/main.py index 6067e9b..632e33c 100644 --- a/live/guild/app/main.py +++ b/live/guild/app/main.py @@ -2370,30 +2370,20 @@ async def wallet_protected_payment_tier( The ``tier_id`` path parameter advertises both OpenAPI's singular example and JSON Schema's examples array. This keeps standards-compliant clients - precise. Registry probes that substitute a non-product placeholder receive - a canonical, non-executable discovery quote for the smallest real tier; - an unknown tier still fails closed (404) before settlement whenever a body, - proof or payment credential is present. + precise while letting registry probes that implement only the older + singular field substitute a valid tier and reach the priced 402 quote; an + unknown tier still fails closed (404) for an executing caller. """ - proof_header = request.headers.get(callerproof.HTTP_HEADER.lower()) - discovery = ( - not body and not proof_header and not _payment_attempt_present() - and billing.billing_enforced() and x402.enabled()) - requested_tier_id = tier_id try: protectedmarket.tier_path(tier_id) service_quote = protectedmarket.tier_quote(tier_id) except protectedmarket.ProtectedMarketplaceRefused as exc: - if not discovery: - raise HTTPException(404, str(exc)) - # Some registries intentionally substitute opaque path placeholders - # rather than OpenAPI examples. Quote the smallest real tier at its - # canonical resource, never the unknown path. The response is marked - # non-executable below; any retry carries a payment/body/proof signal, - # re-enters the strict branch above and fails 404 before settlement. - tier_id = next(iter(protectedmarket.TIERS)) - service_quote = protectedmarket.tier_quote(tier_id) + raise HTTPException(404, str(exc)) + proof_header = request.headers.get(callerproof.HTTP_HEADER.lower()) + discovery = ( + not body and not proof_header and not _payment_attempt_present() + and billing.billing_enforced() and x402.enabled()) will_execute = bool( _executable_payment_present() or not billing.billing_enforced()) verified, caller_did, semantic = _verify_marketplace_body_caller_proof( @@ -2410,8 +2400,6 @@ async def wallet_protected_payment_tier( "strict JSON {request, caller_proof}; a Base-EVM EIP-191 " "proof must bind RFC 8785 JCS(request), this exact tier " "route and the canonical Payan buy URL."), - "requested_tier": requested_tier_id, - "quoted_tier": tier_id, "tier": protectedmarket.catalog()[ list(protectedmarket.TIERS).index(tier_id)], "schema": "/wallet-binding/protected-decision/tiers", diff --git a/live/guild/contract/contract.json b/live/guild/contract/contract.json index e374bd9..8559bbe 100644 --- a/live/guild/contract/contract.json +++ b/live/guild/contract/contract.json @@ -1050,6 +1050,6 @@ "mcp_url": "https://agent-guild-5d5r.onrender.com/mcp/", "name": "Agent Guild", "repository": "https://github.com/AgentTanuki/agent-guild", - "version": "2.5.16" + "version": "2.5.15" } } diff --git a/live/guild/tests/test_discovery_probe_paid_routes.py b/live/guild/tests/test_discovery_probe_paid_routes.py index b868682..1342cf5 100644 --- a/live/guild/tests/test_discovery_probe_paid_routes.py +++ b/live/guild/tests/test_discovery_probe_paid_routes.py @@ -8,8 +8,6 @@ """ from __future__ import annotations -import base64 -import json import os import sys @@ -111,36 +109,6 @@ def test_openapi_declares_a_real_tier_example(client): ), "registry compatibility requires the singular OpenAPI example field" -def test_unknown_tier_registry_placeholder_gets_canonical_safe_quote( - client, settle_spy): - response = client.post( - "/wallet-binding/protected-decision/tiers/not_found", - json={}, headers={"user-agent": "registry-probe/1.0"}) - assert response.status_code == 402 - payload = response.json()["detail"] - assert payload["discovery_only"] is True - assert payload["executable"] is False - assert payload["requested_tier"] == "not_found" - assert payload["quoted_tier"] == "1000-usdc" - challenge = json.loads(base64.b64decode( - response.headers["PAYMENT-REQUIRED"])) - assert challenge["resource"]["url"].split("?", 1)[0].endswith( - "/wallet-binding/protected-decision/tiers/1000-usdc") - assert "not_found" not in challenge["resource"]["url"] - assert settle_spy == [] - - -def test_unknown_tier_payment_retry_fails_before_settlement( - client, settle_spy): - response = client.post( - "/wallet-binding/protected-decision/tiers/not_found", - json={}, headers={"PAYMENT-SIGNATURE": "AAAA"}) - assert response.status_code == 404 - assert settle_spy == [] - assert "payment-response" not in { - key.lower() for key in response.headers} - - def test_x402_retry_for_unknown_agent_fails_before_settlement( client, settle_spy): response = client.get( diff --git a/server.json b/server.json index df6193b..573497e 100644 --- a/server.json +++ b/server.json @@ -2,7 +2,7 @@ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "name": "io.github.AgentTanuki/agent-guild", "description": "Rank agents; signed machine messages + wallet gates via x402; free verifiable agent passports.", - "version": "2.5.16", + "version": "2.5.15", "repository": { "url": "https://github.com/AgentTanuki/agent-guild", "source": "github"