Skip to content

Commit 706ba57

Browse files
authored
Merge pull request #23 from dcplatforms/feature/a2a-zero-trust-modernization-1076727711116180867
A2A Zero Trust Modernization and Refactoring
2 parents 28ce628 + 0d11f38 commit 706ba57

2 files changed

Lines changed: 81 additions & 6 deletions

File tree

src/services/agent.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ const MandateService = require("./mandate");
1010
const logger = require("../utils/logger");
1111

1212
class AgentService {
13-
constructor(database, config = {}) {
13+
constructor(database, config = {}, a2aService = null) {
1414
this.db = database;
1515
this.config = {
1616
defaultSpendingLimit: config.defaultSpendingLimit || 1000,
1717
defaultAuthorizedCounterparties:
1818
config.defaultAuthorizedCounterparties || [],
1919
};
2020
this.mandateService = new MandateService(config.mandateConfig);
21+
this.a2aService = a2aService;
2122
}
2223

2324
/**
@@ -164,7 +165,7 @@ class AgentService {
164165
}
165166

166167
/**
167-
* Perform an Agent-to-Agent (A2A) transfer (conceptual)
168+
* Perform an Agent-to-Agent (A2A) transfer
168169
* @param {Object} params - Transfer parameters
169170
* @param {string} params.fromAgentId - Source agent ID
170171
* @param {string} params.toAgentId - Destination agent ID
@@ -173,9 +174,16 @@ class AgentService {
173174
* @returns {Promise<Object>} Transfer result
174175
*/
175176
async performA2ATransfer({ fromAgentId, toAgentId, amount, currency }) {
176-
// This is a conceptual implementation.
177-
// In a real system, this would involve interaction with the WalletService,
178-
// and policy checks for both agents.
177+
if (this.a2aService) {
178+
return await this.a2aService.executeTransfer({
179+
fromAgentId,
180+
toAgentId,
181+
amount,
182+
ucpPayload: { currency },
183+
});
184+
}
185+
186+
// Fallback for cases where a2aService is not provided
179187
const fromAgent = await this.getAgent(fromAgentId);
180188
await this.getAgent(toAgentId); // Verify toAgent exists
181189

tests/unit/agent.spec.js

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const AgentService = require('../../src/services/agent');
33
describe('AgentService', () => {
44
let agentService;
55
let mockDb;
6+
let mockA2AService;
67

78
beforeEach(() => {
89
mockDb = {
@@ -11,7 +12,10 @@ describe('AgentService', () => {
1112
findAllAgents: jest.fn(),
1213
updateAgent: jest.fn(),
1314
};
14-
agentService = new AgentService(mockDb);
15+
mockA2AService = {
16+
executeTransfer: jest.fn()
17+
};
18+
agentService = new AgentService(mockDb, {}, mockA2AService);
1519
});
1620

1721
describe('registerAgent', () => {
@@ -85,4 +89,67 @@ describe('AgentService', () => {
8589
expect(result.success).toBe(true);
8690
});
8791
});
92+
93+
describe('performA2ATransfer', () => {
94+
it('should delegate to a2aService if provided', async () => {
95+
const transferParams = {
96+
fromAgentId: 'agent1',
97+
toAgentId: 'agent2',
98+
amount: 100,
99+
currency: 'USD'
100+
};
101+
const expectedResult = { success: true, transferId: 'tx123' };
102+
mockA2AService.executeTransfer.mockResolvedValue(expectedResult);
103+
104+
const result = await agentService.performA2ATransfer(transferParams);
105+
106+
expect(mockA2AService.executeTransfer).toHaveBeenCalledWith({
107+
fromAgentId: 'agent1',
108+
toAgentId: 'agent2',
109+
amount: 100,
110+
ucpPayload: { currency: 'USD' }
111+
});
112+
expect(result).toEqual(expectedResult);
113+
});
114+
115+
it('should fallback to local logic if a2aService is not provided', async () => {
116+
const localAgentService = new AgentService(mockDb);
117+
const fromAgent = {
118+
id: 'agent1',
119+
config: { limits: { perTransaction: 500 }, authorizedCounterparties: ['agent2'] }
120+
};
121+
const toAgent = { id: 'agent2' };
122+
123+
mockDb.findAgentById.mockResolvedValueOnce(fromAgent);
124+
mockDb.findAgentById.mockResolvedValueOnce(toAgent);
125+
126+
const result = await localAgentService.performA2ATransfer({
127+
fromAgentId: 'agent1',
128+
toAgentId: 'agent2',
129+
amount: 100,
130+
currency: 'USD'
131+
});
132+
133+
expect(result.success).toBe(true);
134+
expect(result.amount).toBe(100);
135+
});
136+
137+
it('should throw error in fallback if amount exceeds limit', async () => {
138+
const localAgentService = new AgentService(mockDb);
139+
const fromAgent = {
140+
id: 'agent1',
141+
config: { limits: { perTransaction: 50 } }
142+
};
143+
144+
mockDb.findAgentById.mockResolvedValueOnce(fromAgent);
145+
mockDb.findAgentById.mockResolvedValueOnce({ id: 'agent2' });
146+
147+
await expect(localAgentService.performA2ATransfer({
148+
fromAgentId: 'agent1',
149+
toAgentId: 'agent2',
150+
amount: 100,
151+
currency: 'USD'
152+
})).rejects.toThrow('Zero Trust Validation Failed: Amount 100 exceeds agent per-transaction limit of 50');
153+
});
154+
});
88155
});

0 commit comments

Comments
 (0)