a2aproject / a2aproject/a2a-js
[Bug]: canonicalizeAgentCard drops REQUIRED fields with default values, contradicting the §8.4.1 worked example
- Lingua principale
- TypeScript
- Stelle
- 613
- Fork
- 169
- Merge medio
- 1g 6h
- PR unite (30g)
- 21
Descrizione
**What happened?**
`canonicalizeAgentCard` in `src/signature.ts` runs `cleanEmpty` before `jcsStringify`, and `cleanEmpty` deletes empty strings, empty arrays and empty objects unconditionally. Spec §8.4.1 rule 1 says the opposite for one class of field: "Required fields: Fields marked with `REQUIRED` MUST always be present, even if the field value matches the default." The section then prints a worked example that turns on exactly this, deriving `description: ""` include and `skills: []` include, and shows the canonical result.
Running the section's own fragment through this SDK gives `{"capabilities":{"pushNotifications":false,"streaming":false},"name":"Example Agent"}` where the specification says `{"capabilities":{"pushNotifications":false,"streaming":false},"description":"","name":"Example Agent","skills":[]}`. `a2a-python` produces byte-identical output to this SDK here, so the two agree with each other and both differ from the text. That agreement is why the divergence is invisible: no cross-implementation test can see it, and it will surface the first time somebody writes a third canonicalizer from the specification rather than from one of these two. `a2aproject/a2a-go#141` is open to do precisely that.
I want to be clear that I do not think this is straightforwardly this SDK's fault, and I have filed the substance against the specification at a2aproject/A2A#2122. `description` is a proto3 singular string with no presence carrying only a `google.api.field_behavior = REQUIRED` annotation, and ADR-001 makes ProtoJSON normative. ProtoJSON does not read `field_behavior`, so `AgentCard.toJSON` cannot distinguish "REQUIRED and defaulted" from "unset" and no stock encoder can produce the bytes §8.4.1 prints. Whichever way the specification resolves that, this SDK will need a change: either `cleanEmpty` grows a list of REQUIRED field paths that it never strips, or the specification's rule 1 and worked example change to match what a ProtoJSON encoder emits and this code is already correct. I would rather not send a patch until that is decided, but I wanted the divergence recorded here so it is not rediscovered by whoever writes the third implementation.
Separately and unrelated to the above, I checked this SDK's canonicalization against two independent RFC 8785 implementations, `rfc8785.py` and `gowebpki/jcs` v1.0.1, across non-ASCII string content, non-BMP object keys and ECMAScript number serialization. This SDK is conformant on all three, and the divergence I found in the cross-SDK direction is on the Python side, which I have reported there. `jcsStringify` is doing the right thing.
One question rather than a bug: `verifyAgentCardSignature` rejects any signature whose protected header lacks `typ`, `kid` or `alg`. §8.4.2 lists `typ` under "The protected header MUST include:" but the bullet itself says `typ` "SHOULD be set to \"JOSE\" for JWS", so it is not obvious from the text whether absence of `typ` is a verification failure. In practice cards signed by `a2a-python` always carry a `typ` because PyJWT stamps one, but the value is `"JWT"` rather than `"JOSE"` unless the caller sets it explicitly, so this SDK currently accepts a header the specification arguably discourages while rejecting one it arguably permits. I have asked on a2aproject/A2A#2122 and will follow whatever the answer is.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.