feat(typescript): introduce standalone sample#144
Conversation
|
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 @miguelvelasquezdev, 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 delivers a new, self-contained TypeScript sample that showcases a complete agent-to-agent payment flow. It integrates multiple AI agents, each responsible for a specific part of the commerce transaction, from a shopper's initial product search to the final payment processing, demonstrating how these agents collaborate to fulfill a user's request. 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. 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
|
9c00d68 to
54d77e5
Compare
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive standalone TypeScript sample demonstrating the capabilities of Genkit and the @a2a-js/sdk for an e-commerce payment workflow. However, it contains critical security vulnerabilities, primarily related to Broken Access Control (IDOR) and LLM Safety (Prompt Injection), which could allow an attacker to steal sensitive user information. It is highly recommended to address these by implementing proper authentication/authorization and following LLM safety best practices. Additionally, several issues were identified, particularly with dependency versions in package.json, and suggestions for code improvements related to type safety, robustness, and best practices have been provided.
dcd196c to
805e0a8
Compare
3230be4 to
6850d79
Compare
73c4c3e to
9ab9a12
Compare
Mirrors the structure of samples/python and samples/go: src/{roles,common}
laid out by role, scenarios/a2a/human-present/cards with README + run.sh,
agent.ts + tools.ts split per role, Apache 2.0 headers, .env.example,
ESLint flat config, and a vitest e2e smoke test.
Built on Google ADK 0.6 (@google/adk, @google/adk-devtools), the A2A
SDK (@a2a-js/sdk), gemini-2.5-flash, and W3C Verifiable Credentials via
@digitalbazaar/vc.
…HNP MVP
Renames:
- src/roles/{credentials-provider,merchant,payment-processor,shopping}/
-> src/roles/{credentials-provider-agent,merchant-agent,
merchant-payment-processor-agent,shopping-agent}/
New (Human-Not-Present MVP):
- src/roles/merchant-agent-mcp/{server,trigger-server}.ts
- src/roles/credentials-provider-mcp/{server,trigger-server}.ts
- src/roles/merchant-payment-processor-mcp/{server,trigger-server}.ts
- src/roles/shopping-agent-v2/{agent,server,mandate-tools}.ts
- scenarios/a2a/human-not-present/cards/{run.sh,README.md}
Adds @modelcontextprotocol/sdk dependency. SD-JWT chain verification
and ES256 signing are stubbed; tool contracts mirror the Python v0.2
*_mcp roles so the cryptographic primitives can be filled in later
without touching the orchestrator.
…ayout) Aligns the TypeScript samples with the v0.2 repository structure where all language samples live under code/samples/. Also fixes two pre-existing typecheck errors surfaced by the move: - shopping-agent/agent.ts imported the old subagent folder names (shipping-collector/payment-collector) instead of the renamed shipping-address-collector/payment-method-collector. - shopping-agent-v2 mcpTool helper used a ZodTypeAny generic that ADK's FunctionTool rejects; narrowed to z.ZodObject<z.ZodRawShape>. Path/CI updates: - HNP run.sh REPO_ROOT depth (../../ -> ../../../) - linter.yaml working-directory + FILTER_REGEX_EXCLUDE (keep linting TS, still skip python/go/android/certs under code/samples/) - .eslintrc.json project + files globs - README path references tsc --noEmit and npm run lint both pass.
…sh binding + constraints Replaces the W3C VC / stubbed crypto with a real SD-JWT (ES256) mandate chain mirroring the Python AP2 v0.2 model, and hardens the highest-impact verification gaps. SD-JWT core (src/common/sdjwt/): - crypto.ts: ES256 keypair/signer/verifier/hasher/salt (WebCrypto via @sd-jwt/crypto-nodejs) - mandate-sdjwt.ts: issueOpenMandate (cnf.jwk holder binding), presentClosedMandate (KB-SD-JWT), verifyMandate (issuer sig + KB against cnf + nonce) - jwt.ts: plain ES256 compact JWS for the checkout JWT and PSP receipt - key-store.ts: file-backed ES256 keypairs shared across agent + MCP subprocesses - constraints.ts: amount + currency + merchant-allowlist checker - removes the @digitalbazaar W3C VC stack (src/common/vc/ deleted) Roles: - credentials-provider-agent: payment token is now an SD-JWT (account-manager), same string-in/string-out interface (tools.ts untouched) - credentials-provider-mcp: issue_payment_credential verifies the presented payment mandate is holder-bound to the SPECIFIC checkout_jwt_hash (replay protection); verify_payment_receipt verifies the PSP receipt signature - merchant-agent-mcp: create_checkout signs a real ES256 checkout JWT and commits to open_checkout_hash; complete_checkout verifies it, settles with the PSP, returns the PSP-signed payment receipt; carts are file-backed in TEMP_DB - merchant-payment-processor-mcp: signs the payment receipt with the PSP key - shopping-agent-v2: consent->monitoring->purchase LlmAgent hierarchy via subAgents + MCPToolset (ADK-TS idiomatic) with afterToolCallback error escalation; mandate-tools now do real SD-JWT issue/present/verify, real checkConstraintsAgainstMandate, payment presentation bound to checkout_jwt_hash, and a resetTempDb tool Deps: + @sd-jwt/core, @sd-jwt/crypto-nodejs, @modelcontextprotocol/sdk@^1.29; @google/adk -> 1.1.0; zod -> 4.4.3; - @digitalbazaar/*. Tests (16, all passing): SD-JWT issue/verify/KB round-trip + forged-KB rejection, credentials-provider SD-JWT token round-trip, ES256 JWT sign/verify/tamper, constraint checker, and hash-binding replay protection. tsc + eslint clean. Verified end-to-end live: intent -> signed open mandates -> price-drop trigger -> autonomous purchase with merchant- and PSP-signed receipts sharing one checkout_jwt_hash. Known gaps vs Python v0.2 (intentional): x402 stack not ported; VI's full multi-hop/multi-pair chain verifier (chain.py) not replicated.
…nd-rolled craft
Replace the AP2 TypeScript sample's hand-rolled SD-JWT mandate code with the
@verifiable-intent/core library, replicating the official Python reference flow
(verifiable_intent/python/examples) layer by layer.
New src/common/vi/ integration module:
- fixtures, JWK key store, merchant checkout JWT, and a per-role flow facade
(issueIssuerCredential / createUserMandate{Autonomous,Immediate} /
createAgentFulfillment / verifyCheckoutChain / verifyPaymentChainAndConstraints)
- test/unit/vi-chain.test.ts ports autonomous_flow.py + immediate_flow.py end to
end (full chain, privacy-strict merchant view, over-budget rejection)
Autonomous (Human-Not-Present) flow now uses the real L1->L2->split-L3 chain:
- shopping-agent-v2/mandate-tools.ts: assembleAndSignMandates issues L1+L2;
createMandateFulfillment builds split L3a/L3b + per-recipient L2 presentations
- merchant-agent-mcp: complete_checkout verifies the checkout chain (L3b)
- credentials-provider-mcp: issue_payment_credential verifies the payment chain
(L3a) and enforces mandate constraints (STRICT)
- consent/monitoring/purchase prompts updated to the new tool contract
v1 (Human-Present): credentials-provider-agent/account-manager.ts moved off the
craft onto @verifiable-intent/core SD-JWT primitives (behavior unchanged).
Removed the now-dead mandate craft: common/sdjwt/{mandate-sdjwt,constraints}.ts
and their unit tests; common/sdjwt keeps only shared ES256 + plain-JWS + key-store
utilities. Linked @verifiable-intent/core via package.json.
Verified: tsc --noEmit, build, and eslint clean; unit suite 11/11.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Start tracking the `adk web src/web-agents` entry-point that the `dev` script launches: a dedicated agents directory that re-exports the shopping-agent so ADK lists the app under its folder name (pointing adk web at src/roles is not viable — the *-mcp stdio servers and shopping-agent-v2 collide in ADK's loader). The file was previously untracked; without it a fresh checkout's `npm run dev` fails to start the web UI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A headless, git-checkpointed loop that keeps hardening + testing the Verifiable Intent integration, one verified backlog item at a time. - improve-loop.prompt.md: stable per-iteration prompt (pick one BACKLOG item -> small change -> typecheck+lint+`vitest run test/unit` must pass -> commit; never weaken tests; revert if not green; e2e excluded). - BACKLOG.md: the work queue (coverage, negative-path tests, server-free MCP tests, aud/nonce pinning, README). - improve-loop.sh: the runner — `--bare`, `--permission-mode acceptEdits`, a scoped tool allowlist (npm/npx/git/node + file tools only), an iteration cap, and a stop-when-green-and-backlog-empty gate. - test/unit/vi-chain-negative.test.ts: seed rejection tests (expired L3, missing/wrong issuer key, out-of-mandate payee). Unit suite now 15/15. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sed mandates) Gap found by the improve loop: complete_checkout and issue_payment_credential called verifyChain without pinning the L3 audience, so the VI library recorded the aud check as "skipped" — a mandate addressed to a different party would pass. - Add shared MERCHANT_AUD / NETWORK_AUD constants in common/vi/fixtures.ts. - Agent stamps them as the L3a/L3b `aud` (flow.ts createAgentFulfillment). - merchant-agent-mcp complete_checkout pins expectedL3CheckoutAud = MERCHANT_AUD. - credentials-provider-mcp issue_payment_credential pins expectedL3PaymentAud = NETWORK_AUD. - Test proves a wrong-audience checkout presentation is rejected. tsc + lint clean; unit suite 16/16. Logged a follow-up replay-protection finding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Locks the wiring the MCP servers rely on, without spawning servers or Gemini: the agent writes l1/l2/chk_*/pay_* to a temp dir exactly as shopping-agent-v2 does, then merchant (verifyCheckoutChain) and network (verifyPaymentChainAnd- Constraints) read them back and verify with the iteration-1 aud pinning. Covers a valid end-to-end purchase and an over-budget rejection. Also logged two gaps the audit surfaced (BACKLOG.md): (1) merchant slug item-ids vs L2 acceptable_items skus can mismatch and break createAgentFulfillment; (2) the minted pay_token isn't bound to checkout_jwt_hash. tsc + lint clean; unit suite 18/18. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The human-present / immediate flow (createUserMandateImmediate, the TS analog of immediate_flow.py) had a happy-path test but no rejection coverage. Add two immediate-specific cases: L2 verified against a different L1 fails the sd_hash L2->L1 binding, and verification against the wrong issuer key fails. Brings the immediate path to parity with the autonomous rejection tests. tsc + lint clean; unit suite 20/20. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make gaps measurable: add @vitest/coverage-v8, a unit-only `test:coverage:unit` script, and a coverage block in vitest.config.ts scoped to src/common/vi (the role servers/mandate-tools need stdio servers, so they're e2e-covered). Baseline: 85.7% stmts / 82.5% branch / 73.9% funcs / 85.6% lines. Surfaced a real gap — keys.ts (the file-backed key store every role server uses) is 0% covered; logged a follow-up to test it. npm-link to @verifiable-intent/core verified intact after install. tsc + lint clean; unit suite 20/20. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
keys.ts (loadOrCreateViKey / loadViPublicJwk) is the shared key store every role server uses to persist + resolve ES256 keys across processes, and it had no coverage. Add round-trip persist/reload, per-role kid assignment + fallback, legacy (no-kid) file format, loadViPublicJwk missing->null with no private-scalar leak, and a persisted issuer key signing a verifiable credential. src/common/vi coverage 85.7% -> 96.2% stmts, 73.9% -> 91.3% funcs. tsc + lint clean; unit suite 25/25. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The over-budget case was tested but not the exact cap boundary. Add: amount exactly at the cap is allowed, one minor unit over is rejected, and a currency differing from the mandate is rejected — through the network verification path (verifyPaymentChainAndConstraints). Confirms the spend cap is enforced exactly. tsc + lint clean; unit suite 28/28. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…udit) Iteration 7 audited every v2 prompt against the current tool signatures: all consistent after the migration. It also confirmed the item-id binding gap is a prompt-ordering bug — consent signed L2 before search_inventory ran, so L2's acceptable_items got default skus while the merchant serves generated slug ids, breaking createAgentFulfillment's item match. Fix: consent now calls search_inventory FIRST and threads the resolved item_id into assembleAndSignMandates (required), so the signed mandate binds the exact item the monitoring/purchase agents will buy. (Prompt-behavior change — needs e2e validation; gates unaffected.) tsc + lint clean; unit suite 28/28. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lock two core VI guarantees: only the cnf-bound agent can fulfill (an L3 signed by a non-delegated agent key — even with a matching kid — fails verification against L2's cnf.jwk), and a mutated L2 signature is rejected. Both via the network verification path. tsc + lint clean; unit suite 30/30. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erties) Capstone documentation for the Verifiable Intent integration: the L1->L2->L3 layer model, AP2 role->layer mapping diagram, the TEMP_DB cross-role file contract, the public flow API, and the security properties now enforced + tested (issuer trust, delegation binding, layer/audience binding, spend cap, freshness). Also records the remaining e2e-only gaps. tsc + lint clean; unit suite 30/30. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… status Iteration 10 audit: verifyCheckoutChain (merchant) verifies chain structure + aud but never runs checkConstraints — only the network path enforces constraints. So the merchant doesn't independently verify the checked-out item is acceptable (it trusts the agent's self-check). Logged as an e2e-design follow-up. Marks the unit-testable security/coverage/docs backlog as essentially complete (src/common/vi ~96% stmts / 91% funcs, 30 tests); remaining items are e2e-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9ab9a12 to
ce33fd1
Compare
Implements a standalone TypeScript sample with Genkit and @a2a-js/sdk.
Includes ShoppingAgent, CredentialsProviderAgent, MerchantAgent, and MerchantPaymentProcessorAgent with full payment workflow support.
Description
Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
CONTRIBUTINGGuide.Closes #67 🦕