Skip to content

Add AsterPay KYA Trust Score demo for ACK-ID integration#63

Open
timolein74 wants to merge 2 commits intoagentcommercekit:mainfrom
AsterPay:feat/asterpay-kya-demo
Open

Add AsterPay KYA Trust Score demo for ACK-ID integration#63
timolein74 wants to merge 2 commits intoagentcommercekit:mainfrom
AsterPay:feat/asterpay-kya-demo

Conversation

@timolein74
Copy link

@timolein74 timolein74 commented Mar 12, 2026

Summary

Adds an AsterPay KYA (Know Your Agent) Trust Score demo, similar to the existing Skyfire KYA demo, showing how AsterPay's trust scoring framework integrates with ACK-ID.

  • Trust Score (0-100) with 7 scoring components converted to W3C Verifiable Credentials
  • Bidirectional JWT <-> VC conversion with full cryptographic integrity (lossless round-trip)
  • Trust-score-aware ACK-ID verification with configurable minimum thresholds
  • ERC-8183 IACPHook simulation demonstrating 5-shield agent gate (VERIFY -> SCREEN -> SCORE -> ATTEST -> COMPLY)
  • InsumerAPI attestations (Coinbase KYC, country verification, Gitcoin Passport, USDC balance)

What is AsterPay?

AsterPay provides trust infrastructure for AI agent payments — trust scoring, sanctions screening, and EUR settlement via SEPA Instant. We're building the compliance and trust layer for agent commerce.

Files added

  • demos/asterpay-kya/ — Full demo with README, source, and config
  • package.json — Added demo:asterpay-kya script
  • demos/README.md — Added demo listing

Testing

The demo runs successfully with pnpm demo:asterpay-kya and all 5 steps complete without errors.

Summary by CodeRabbit

  • New Features

    • Added AsterPay KYA Trust Score demo showcasing integration with ACK-ID identity verification system, including trust score evaluation, sanctions screening, and commerce verification workflows.
  • Documentation

    • Added comprehensive demo documentation covering prerequisites, execution instructions, verification flow, trust component scoring details, and production configuration considerations.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 31171b40-aa49-4a1a-8c62-67e5dbd27196

📥 Commits

Reviewing files that changed from the base of the PR and between db25f9b and 491d90f.

📒 Files selected for processing (3)
  • demos/asterpay-kya/README.md
  • demos/asterpay-kya/src/asterpay-kya-ack-id.ts
  • demos/asterpay-kya/src/index.ts
✅ Files skipped from review due to trivial changes (2)
  • demos/asterpay-kya/README.md
  • demos/asterpay-kya/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • demos/asterpay-kya/src/asterpay-kya-ack-id.ts

Walkthrough

Adds a new AsterPay KYA demo under demos/asterpay-kya: docs, package/ts/vitest configs, and TypeScript modules implementing JWKS generation, mock KYA JWT creation, JWT↔W3C VC conversion, verification checks, and an interactive demo runner. Also adds a root npm script to launch the demo.

Changes

Cohort / File(s) Summary
Documentation
demos/README.md, demos/asterpay-kya/README.md
Added demo entry in root demos README and a comprehensive README for the AsterPay KYA → ACK‑ID demo describing flow, VC schema, verification checklist, and run instructions.
Package & Tooling
demos/asterpay-kya/package.json, demos/asterpay-kya/tsconfig.json, demos/asterpay-kya/vitest.config.ts, package.json
New workspace package manifest and npm script (demo:asterpay-kya), TypeScript project config with path alias, and Vitest config (passWithNoTests).
Core Demo Implementation
demos/asterpay-kya/src/jwk-keys.ts, demos/asterpay-kya/src/kya-token.ts, demos/asterpay-kya/src/asterpay-kya-ack-id.ts, demos/asterpay-kya/src/index.ts
Added JWKS/keypair generator, zod schemas and mock KYA JWT creation, conversion utilities between KYA JWT and W3C VC, verification logic (trusted issuers, expiry, sanctions, min trust score, insumer attestations), and an interactive demo script including ERC‑8183 IACPHook simulation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Suggested reviewers

  • pitluga
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding a new AsterPay KYA Trust Score demo for ACK-ID integration, which comprises the main deliverable of this PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demos/asterpay-kya/README.md`:
- Line 3: The README contains inconsistent terminology: the top summary uses
"VERIFY → SCREEN → SCORE → SETTLE → COMPLY" while later text and the demo use
"VERIFY → SCREEN → SCORE → ATTEST → COMPLY"; update the README to use a single
term across the file (choose either SETTLE or ATTEST) and replace all
occurrences of the alternate phrase so the phrases "VERIFY → SCREEN → SCORE →
SETTLE → COMPLY" and "VERIFY → SCREEN → SCORE → ATTEST → COMPLY" no longer
conflict; ensure the demo description and any headings match the selected term.

In `@demos/asterpay-kya/src/asterpay-kya-ack-id.ts`:
- Around line 51-84: The syntheticVC currently embeds the original JWT in
proof.originalPayload and jws but builds credentialSubject separately, so
credentialSubject can diverge from the signed payload; to fix, either (A) bind
the proof to the generated credentialSubject by producing a real signature over
the final VC (i.e., compute the proof.jws from the canonicalized
credentialSubject/VC and set proof.originalPayload to that canonicalized
payload) using the issuer key, or (B) derive credentialSubject directly from the
decoded jwtParts[1] payload (so credentialSubject exactly matches
proof.originalPayload) and add a runtime check in any consumer/read path to
verify credentialSubject === decoded proof.originalPayload before trusting the
VC; update the syntheticVC.proof (fields jws and originalPayload) accordingly
and ensure verification logic checks this equality.
- Around line 29-45: The code currently only enforces iat, exp, jti, and sub on
the verified JWT payload but does not reject tokens missing the trust-critical
claims, allowing undefined trustScore or sanctioned to slip through; update the
verification in asterpay-kya-ack-id.ts (where payload is extracted in
verifyAsterPayKyaAsAckId / the verification block referencing payload,
jwtSignature) to also require presence and valid types for trustScore (number)
and sanctioned (boolean) before creating the VC, and throw an explicit Error
(e.g., "Missing or invalid trust-critical claims: trustScore/sanctioned") if
they are absent or of the wrong type.

In `@demos/asterpay-kya/src/index.ts`:
- Around line 240-275: The demo currently always approves the IACPHook path
regardless of the converted credential; update the logic around
convertAsterPayKyaToVerifiableCredential/ vc (and att) to evaluate the actual
verification gates (check vc.credentialSubject.sanctioned flag, numeric
vc.credentialSubject.trustScore against the minimum threshold, and required
insumerAttestation fields like att.coinbaseKyc.met, att.gitcoinPassport.met,
att.tokenBalance.met) and branch: if any gate fails, log appropriate FAILED
messages (instead of the hardcoded success lines), emit a rejection outcome
(e.g., failure message instead of successMessage("IACPHook: APPROVED...")), and
avoid emitting ReputationPositive; otherwise proceed with the existing approved
logs and ReputationPositive emission. Ensure the printed
VERIFY/SCREEN/SCORE/ATTEST/COMPLY lines reflect the actual pass/fail of each
check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f46841a5-dc61-47b1-b5f8-6edff0e26177

📥 Commits

Reviewing files that changed from the base of the PR and between f0e8c6c and db25f9b.

📒 Files selected for processing (10)
  • demos/README.md
  • demos/asterpay-kya/README.md
  • demos/asterpay-kya/package.json
  • demos/asterpay-kya/src/asterpay-kya-ack-id.ts
  • demos/asterpay-kya/src/index.ts
  • demos/asterpay-kya/src/jwk-keys.ts
  • demos/asterpay-kya/src/kya-token.ts
  • demos/asterpay-kya/tsconfig.json
  • demos/asterpay-kya/vitest.config.ts
  • package.json

Comment on lines +51 to +84
const syntheticVC: Verifiable<W3CCredential<AsterPayKyaCredentialSubject>> = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://agentcommercekit.com/contexts/asterpay-kya/v1",
],
id: `urn:uuid:${payload.jti}`,
type: [
"VerifiableCredential",
"AsterPayKYACredential",
"AgentTrustScoreCredential",
],
issuer: { id: "did:web:api.asterpay.io" },
issuanceDate: new Date(payload.iat * 1000).toISOString(),
expirationDate: new Date(payload.exp * 1000).toISOString(),
credentialSubject: {
id: agentDid,
agentAddress: payload.agentAddress,
agentId: payload.agentId,
trustScore: payload.trustScore,
tier: payload.tier,
components: payload.components,
insumerAttestation: payload.insumerAttestation,
sanctioned: payload.sanctioned,
jti: payload.jti,
},
proof: {
type: "JsonWebSignature2020",
created: new Date(payload.iat * 1000).toISOString(),
verificationMethod: "did:web:api.asterpay.io#kya-key-1",
proofPurpose: "assertionMethod",
jws: `${jwtParts[0]}..${jwtSignature}`,
originalPayload: jwtParts[1],
},
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Bind the generated VC body to the proof.

The stored proof preserves the original JWT, but it never signs the generated credentialSubject. After conversion, credentialSubject.trustScore/sanctioned can be edited and the proof still reconstructs the old JWT, so this VC is not verifiable on its own.

Either issue a real signed VC here, or verify on read that the current credentialSubject exactly matches the signed payload before any consumer trusts the VC.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demos/asterpay-kya/src/asterpay-kya-ack-id.ts` around lines 51 - 84, The
syntheticVC currently embeds the original JWT in proof.originalPayload and jws
but builds credentialSubject separately, so credentialSubject can diverge from
the signed payload; to fix, either (A) bind the proof to the generated
credentialSubject by producing a real signature over the final VC (i.e., compute
the proof.jws from the canonicalized credentialSubject/VC and set
proof.originalPayload to that canonicalized payload) using the issuer key, or
(B) derive credentialSubject directly from the decoded jwtParts[1] payload (so
credentialSubject exactly matches proof.originalPayload) and add a runtime check
in any consumer/read path to verify credentialSubject === decoded
proof.originalPayload before trusting the VC; update the syntheticVC.proof
(fields jws and originalPayload) accordingly and ensure verification logic
checks this equality.

Copy link

@ak68a ak68a left a comment

Choose a reason for hiding this comment

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

Nice, JWT round-trip is clean. The @ts-expect-error on typ: 'kya+JWT' is the same issue as the Skyfire demo, left a note on #66 about widening the type in the JWT package.

Copy link
Author

@timolein74 timolein74 left a comment

Choose a reason for hiding this comment

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

Thanks for the thorough review! Addressed comments 1, 2, and 4 in the latest push:

1. README terminology — Fixed SETTLE to ATTEST (and the matching line in index.ts overview).

2. Trust-critical claims validation — Added explicit type-checked guards for trustScore (number), sanctioned (boolean), agentAddress, tier, components, and insumerAttestation before VC creation.

3. Synthetic VC proof binding — This is intentional by design. The synthetic VC is a wrapper around the original signed JWT, not a standalone VC. The proof binds to the JWT via proof.jws (header + signature) and proof.originalPayload (base64url-encoded payload). Any consumer can verify integrity by: (a) reconstructing the JWT from the proof fields, (b) verifying it against AsterPay's JWKS, and (c) confirming the decoded payload matches credentialSubject. This is the same pattern used in the existing Skyfire demo — the VC serves as a standardized envelope while the JWT signature remains the cryptographic root of trust. Issuing a new signature over the VC body would require AsterPay's production signing key, which a demo cannot access.

4. IACPHook verification gates — The simulation now runs actual verification via verifyAsterPayKyaAsAckId() first, and each shield check evaluates the real credential values. If any gate fails, the hook emits BLOCKED/REJECTED instead of always approving.

…tion, IACPHook verification gates

Made-with: Cursor
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.

2 participants