Skip to content

feat(typescript): introduce standalone sample#144

Open
miguelvelasquezdev wants to merge 17 commits into
google-agentic-commerce:mainfrom
miguelvelasquezdev:feature/typescript-integration
Open

feat(typescript): introduce standalone sample#144
miguelvelasquezdev wants to merge 17 commits into
google-agentic-commerce:mainfrom
miguelvelasquezdev:feature/typescript-integration

Conversation

@miguelvelasquezdev

Copy link
Copy Markdown

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:

Closes #67 🦕

@miguelvelasquezdev miguelvelasquezdev requested a review from a team as a code owner January 22, 2026 03:16
@google-cla

google-cla Bot commented Jan 22, 2026

Copy link
Copy Markdown

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.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @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 TypeScript Sample: Introduces a comprehensive standalone TypeScript sample demonstrating an end-to-end payment workflow using Genkit and the @a2a-js/sdk.
  • Agent Implementation: Includes implementations for a ShoppingAgent, CredentialsProviderAgent, MerchantAgent, and MerchantPaymentProcessorAgent, all working together to simulate a full payment process.
  • Payment Workflow Support: The sample provides full support for a payment workflow, covering aspects from product search and cart management to shipping address collection, payment method selection, and payment processing, including handling OTP challenges.
  • CLI for Interaction: A command-line interface (CLI) is included to easily interact with the various agents and observe the workflow.

🧠 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 Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@miguelvelasquezdev miguelvelasquezdev force-pushed the feature/typescript-integration branch from 9c00d68 to 54d77e5 Compare January 22, 2026 03:20

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread samples/typescript/package.json Outdated
Comment thread samples/typescript/src/agents/credentials-provider-agent/tools.ts Outdated
Comment thread samples/typescript/package.json Outdated
Comment thread samples/typescript/package.json Outdated
Comment thread samples/typescript/src/agents/credentials-provider-agent/genkit.ts Outdated
Comment thread code/samples/typescript/package.json
Comment thread samples/typescript/package.json Outdated
Comment thread samples/typescript/src/utils/artifact.ts Outdated
@miguelvelasquezdev miguelvelasquezdev force-pushed the feature/typescript-integration branch 21 times, most recently from dcd196c to 805e0a8 Compare January 25, 2026 14:44
@miguelvelasquezdev

Copy link
Copy Markdown
Author

@mdoeseckle @pnewman1

@miguelvelasquezdev miguelvelasquezdev force-pushed the feature/typescript-integration branch from 3230be4 to 6850d79 Compare February 17, 2026 03:28
@miguelvelasquezdev miguelvelasquezdev force-pushed the feature/typescript-integration branch 2 times, most recently from 73c4c3e to 9ab9a12 Compare April 16, 2026 15:12
miguelvelasquezdev and others added 17 commits May 23, 2026 17:29
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>
@miguelvelasquezdev miguelvelasquezdev force-pushed the feature/typescript-integration branch from 9ab9a12 to ce33fd1 Compare June 14, 2026 01:40
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.

[Feat]: Add TypeScript SDK & Samples for AP2 Mandates

1 participant