Affected package or area
@agentcommercekit/ack-id
Affected version, release, or commit
@agentcommercekit/ack-id 0.11.0, ACK commit 0b8fdaa
Environment
- Node.js: v24.14.1
- Package manager and version: pnpm 11.8.0
- Operating system: WSL2 / Linux
Summary
createA2AHandshakeMessage() returns the wrong nonce when creating a response handshake with requestNonce.
When requestNonce is provided, createA2AHandshakePayload() correctly puts the initiator's nonce in payload.nonce and the newly generated nonce in payload.replyNonce. However, createA2AHandshakeMessage() always returns nonce: payload.nonce, so callers receive the peer's old request nonce instead of the fresh reply nonce they need to correlate the next handshake leg.
Minimal reproduction and steps
- In
packages/ack-id/src/a2a/sign-message.test.ts, add a regression test that calls createA2AHandshakeMessage() with requestNonce.
- Mock
generateRandomNonce() to return fresh-reply-nonce.
- Call
createA2AHandshakeMessage("agent", { recipient: userDid, vc: testCredential, requestNonce: "initiator-nonce" }, { did: agentDid, jwtSigner }).
- Assert that
result.nonce is fresh-reply-nonce.
- Run:
pnpm run build
pnpm --filter @agentcommercekit/ack-id test -- src/a2a/sign-message.test.ts
Expected behavior
When requestNonce is provided, createA2AHandshakeMessage() should return the freshly generated replyNonce so callers can store and correlate the next handshake leg.
Actual behavior
createA2AHandshakeMessage() returns payload.nonce, which is the peer's original requestNonce. The fresh nonce is only present in payload.replyNonce and is not returned to the caller.
Relevant code
packages/ack-id/src/a2a/sign-message.ts
const payload = createA2AHandshakePayload(params)
return {
sig: jwt,
jti,
nonce: payload.nonce,
message,
}
Observed failing assertion
Expected: fresh-reply-nonce
Received: initiator-nonce
Suggested fix
Return payload.replyNonce when it exists, otherwise keep the current initiator behavior.
nonce: payload.replyNonce ?? payload.nonce
AI usage
This issue was found and validated with assistance from Hermes Agent.
Acknowledgements
Affected package or area
@agentcommercekit/ack-id
Affected version, release, or commit
@agentcommercekit/ack-id 0.11.0, ACK commit 0b8fdaa
Environment
Summary
createA2AHandshakeMessage()returns the wrong nonce when creating a response handshake withrequestNonce.When
requestNonceis provided,createA2AHandshakePayload()correctly puts the initiator's nonce inpayload.nonceand the newly generated nonce inpayload.replyNonce. However,createA2AHandshakeMessage()always returnsnonce: payload.nonce, so callers receive the peer's old request nonce instead of the fresh reply nonce they need to correlate the next handshake leg.Minimal reproduction and steps
packages/ack-id/src/a2a/sign-message.test.ts, add a regression test that callscreateA2AHandshakeMessage()withrequestNonce.generateRandomNonce()to returnfresh-reply-nonce.createA2AHandshakeMessage("agent", { recipient: userDid, vc: testCredential, requestNonce: "initiator-nonce" }, { did: agentDid, jwtSigner }).result.nonceisfresh-reply-nonce.pnpm run build
pnpm --filter @agentcommercekit/ack-id test -- src/a2a/sign-message.test.ts
Expected behavior
When
requestNonceis provided,createA2AHandshakeMessage()should return the freshly generatedreplyNonceso callers can store and correlate the next handshake leg.Actual behavior
createA2AHandshakeMessage()returnspayload.nonce, which is the peer's originalrequestNonce. The fresh nonce is only present inpayload.replyNonceand is not returned to the caller.Relevant code
packages/ack-id/src/a2a/sign-message.tsObserved failing assertion
Expected: fresh-reply-nonce
Received: initiator-nonce
Suggested fix
Return
payload.replyNoncewhen it exists, otherwise keep the current initiator behavior.AI usage
This issue was found and validated with assistance from Hermes Agent.
Acknowledgements