feat(golang): add Go implementation using x402 v2 protocol with testable architecture#64
feat(golang): add Go implementation using x402 v2 protocol with testable architecture#640xfakeSpike wants to merge 12 commits intogoogle-agentic-commerce:mainfrom
Conversation
…jection - Add ResourceServer and ExtensionChecker interfaces for testability - Add NewBusinessOrchestratorWithDeps constructor for dependency injection - Create resourceServerWrapper to adapt concrete type to interface - Maintain backward compatibility with existing code
…succeeds - Fix ensureExtension to return error even if transitionToFailed succeeds - Fix handlePaymentSubmitted to return error even if transitionToFailed succeeds - Ensures proper error propagation in payment flow
- Add TestExtractPaymentPayload with coverage for message and task extraction - Add TestExtractPaymentRequirements with error handling tests - Add TestExtractPaymentReceipts with multiple receipt scenarios
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Summary of ChangesHello @0xfakeSpike, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a complete Go implementation of the x402 A2A payment protocol, focusing on an improved, testable architecture. It includes both merchant and client components, along with example applications, and features extensive test coverage. The changes enhance the protocol's robustness by addressing error handling and introducing clear interface abstractions for better maintainability and testability. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive Go implementation for the x402 A2A payment protocol, featuring core client and merchant logic, example applications, and extensive tests with a well-designed, testable architecture. However, a critical security audit revealed a high-severity broken access control vulnerability, allowing clients to bypass payment verification by manipulating message metadata, and a medium-severity prompt injection vulnerability in the example image generation service. Additionally, areas for improvement include error handling consistency, context propagation, and minor documentation and code maintainability issues.
| result, err := s.client.Models.GenerateContent( | ||
| ctx, | ||
| "gemini-2.5-flash-image", | ||
| genai.Text(prompt), | ||
| nil, | ||
| ) |
There was a problem hiding this comment.
The Execute function in the ImageService example passes user-provided prompts directly to the Gemini LLM without any sanitization or validation. An attacker can use prompt injection techniques to manipulate the LLM's behavior, potentially generating inappropriate content or bypassing intended service constraints, all while using the merchant's API credentials and incurring costs for the merchant.
| *.pyc | ||
| *.pyo | ||
| *.pyd | ||
| .Python |
| client *a2aclient.Client | ||
| } | ||
|
|
||
| func NewClient(merchantURL string, networkKeyPairs []types.NetworkKeyPair) (*Client, error) { |
There was a problem hiding this comment.
The NewClient function uses context.Background() when creating the A2A client. In library code, it's better to accept a context.Context from the caller. This gives the user of the library control over deadlines, cancellation, and passing request-scoped values.
| func NewClient(merchantURL string, networkKeyPairs []types.NetworkKeyPair) (*Client, error) { | |
| func NewClient(ctx context.Context, merchantURL string, networkKeyPairs []types.NetworkKeyPair) (*Client, error) { |
| } else if part.InlineData != nil { | ||
| imageBytes := part.InlineData.Data | ||
| outputFilename := "./gemini_generated_image.png" | ||
| _ = os.WriteFile(outputFilename, imageBytes, 0644) |
There was a problem hiding this comment.
The error returned by os.WriteFile is being ignored. While this is an example, it's good practice to handle potential errors, such as disk full or permission issues. At a minimum, the error should be logged.
if err := os.WriteFile(outputFilename, imageBytes, 0644); err != nil {
// Log or handle the error. For this example, we can just log it.
fmt.Printf("Warning: failed to write image to file: %v\n", err)
}|
|
||
| require ( | ||
| github.com/a2aproject/a2a-go v0.3.5 | ||
| github.com/coinbase/x402/go v0.0.0-20260206180803-de9f9f53b20c |
There was a problem hiding this comment.
Update client configuration documentation to use 'networkName' instead of 'network' to match the actual configuration field name.
- ExtractPaymentStatus now only reads from task status, completely ignores message metadata - Merchant orchestrator only processes payment based on task state, not client-submitted status - Added PaymentRequired branch to handle client payment submission correctly - Updated tests to reflect security changes This fixes a critical security vulnerability where malicious clients could bypass payment verification by setting x402.payment.status in message metadata to 'payment-verified' or 'payment-completed'. Now merchant only uses task status which is merchant-controlled.
Previously, when payment failed, if marshalling the error message failed or if there was no message, the function would return nil, effectively swallowing the error. This could lead to payment failures being silently ignored. Now the function always returns an error in the PaymentFailed case: - First tries to marshal the full message object - Falls back to extracting text from message parts if marshalling fails - Returns a generic error if no message is available This ensures payment failures are never silently ignored.
… task Previously, when encountering an unknown payment state in a working task, if json.Marshal failed or if there was no message, the function would return nil, effectively swallowing the error. This could lead to silent failures. Now the function always returns an error when task is in working state with unknown payment state: - First tries to marshal the full message object - Falls back to extracting text from message parts if marshalling fails - Returns a generic error with payment state if no message is available This ensures unknown payment states in working tasks are never silently ignored and errors are properly propagated to the caller.
Previously, when payment verification failed, the task was transitioned to a failed state but then the verification error was returned. This caused the Execute method in the orchestrator to propagate an error, suggesting an orchestrator failure rather than a normal business flow failure. After successfully transitioning the task to a failed state, the function now returns nil, nil. This indicates that the request was handled successfully (by failing the task), allowing the orchestrator's Execute method to complete without an error, which is consistent with how other business logic failures are handled.
Summary
Add complete Go implementation of x402 A2A payment protocol with improved architecture for testability and comprehensive test coverage.
Changes
Features
Refactoring
Fixes
Testing
Files Changed