55 * policy compliance, limit checks, and authorized counterparty validation.
66 */
77
8+ const MandateService = require ( "./mandate" ) ;
89const logger = require ( "../utils/logger" ) ;
10+ const MandateService = require ( "./mandate" ) ;
911
1012class A2AService {
11- constructor ( walletService , db ) {
13+ constructor ( walletService , db , config = { } ) {
1214 this . walletService = walletService ;
1315 this . db = db ;
16+ this . mandateService = config . mandateService || new MandateService ( config . mandateConfig ) ;
17+ this . strictMandateMode =
18+ config . strictMandateMode !== undefined
19+ ? config . strictMandateMode
20+ : process . env . STRICT_MANDATE_MODE === "true" ;
1421 }
1522
1623 /**
@@ -19,25 +26,64 @@ class A2AService {
1926 * @param {string } params.fromAgentId - Sender Agent ID
2027 * @param {string } params.toAgentId - Recipient Agent ID
2128 * @param {number } params.amount - Amount to transfer
29+ * @param {string } params.mandate - Optional signed Mandate (AP2) for Zero Trust validation
2230 * @param {Object } params.ucpPayload - The original UCP intent/payload
31+ * @param {string } params.mandate - Optional signed Mandate (AP2) for Zero Trust validation
2332 */
24- async executeTransfer ( { fromAgentId, toAgentId, amount, ucpPayload = { } } ) {
33+ async executeTransfer ( {
34+ fromAgentId,
35+ toAgentId,
36+ amount,
37+ mandate,
38+ ucpPayload = { } ,
39+ } ) {
2540 try {
26- // 1. Validate Agents
41+ // 0. Zero Trust Mandate Validation
42+ if ( mandate ) {
43+ try {
44+ await this . mandateService . verifyMandate ( mandate ) ;
45+ } catch ( error ) {
46+ throw new Error (
47+ `Zero Trust Validation Failed: Mandate verification failed: ${ error . message } ` ,
48+ ) ;
49+ }
50+ } else if ( this . strictMandateMode ) {
51+ throw new Error (
52+ "Zero Trust Validation Failed: Mandate required for A2A transfer in strict mode" ,
53+ ) ;
54+ }
55+
56+ // 1. Validate Agents using Repository Pattern
2757 const fromAgent = await this . db . findAgentById ( fromAgentId ) ;
2858 if ( ! fromAgent || fromAgent . status !== "active" ) {
29- throw new Error ( `Sender agent ${ fromAgentId } not found or inactive` ) ;
59+ throw new Error (
60+ `Zero Trust Validation Failed: Sender agent ${ fromAgentId } not found or inactive` ,
61+ ) ;
3062 }
3163
3264 const toAgent = await this . db . findAgentById ( toAgentId ) ;
3365 if ( ! toAgent || toAgent . status !== "active" ) {
34- throw new Error ( `Recipient agent ${ toAgentId } not found or inactive` ) ;
66+ throw new Error (
67+ `Zero Trust Validation Failed: Recipient agent ${ toAgentId } not found or inactive` ,
68+ ) ;
69+ }
70+
71+ // 2. Zero Trust Mandate Validation
72+ if ( mandate ) {
73+ await this . mandateService . verifyMandate ( mandate , {
74+ amount,
75+ recipient : toAgentId ,
76+ } ) ;
77+ } else if ( this . strictMandateMode ) {
78+ throw new Error (
79+ "Zero Trust Validation Failed: Mandate required for A2A transfer in strict mode" ,
80+ ) ;
3581 }
3682
37- // 2 . Policy Checks (Sender)
83+ // 3 . Policy Checks (Sender)
3884 await this . _validateAgentPolicy ( fromAgent , toAgentId , amount ) ;
3985
40- // 3 . Execute Wallet Transfer
86+ // 4 . Execute Wallet Transfer
4187 const transferResult = await this . walletService . transfer ( {
4288 fromWalletId : fromAgent . walletId ,
4389 toWalletId : toAgent . walletId ,
@@ -49,13 +95,10 @@ class A2AService {
4995 counterpartyAgentId : toAgentId ,
5096 ucpPayload,
5197 type : "a2a_transfer" ,
98+ mandate,
5299 } ,
53100 } ) ;
54101
55- // 4. Update Agent Usage (if we were tracking daily usage in db, we'd do it here)
56- // For now, limits are stateless checks against config.
57- // In a real implementation, we would query daily volume or update a usage record.
58-
59102 return {
60103 success : true ,
61104 transferId : transferResult . transferId ,
@@ -106,6 +149,15 @@ class A2AService {
106149 */
107150 _handleError ( method , error ) {
108151 logger . error ( `A2AService.${ method } error:` , error ) ;
152+
153+ // Normalize Zero Trust errors
154+ if (
155+ error . message &&
156+ error . message . includes ( "Zero Trust Validation Failed:" )
157+ ) {
158+ return error ;
159+ }
160+
109161 return error instanceof Error ? error : new Error ( error ) ;
110162 }
111163}
0 commit comments