a2aproject / a2aproject/a2a-js
[Bug]: canonicalizeAgentCard drops REQUIRED fields with default values, contradicting the §8.4.1 worked example
- Lenguaje dominante
- TypeScript
- Estrellas
- 613
- Forks
- 169
- Merge medio
- 1 d 6 h
- PR fusionados (30 d)
- 21
Descripción
**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.
Guía de contribución
Línea de trabajo
The issue is in src/signature.ts, specifically the canonicalizeAgentCard function and its use of cleanEmpty before jcsStringify. First, understand the spec §8.4.1 and the open questions about REQUIRED fields with defaults. Check the linked spec issue a2aproject/A2A#2122 for resolution. The fix may involve modifying cleanEmpty to preserve certain fields or adjusting the canonicalization logic. Test changes against the worked example in the spec and cross-check with other SDKs.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- javascript, typescript
- Área
- backend-api-design, security
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Tranquilo
- Claridad
- Bien especificado
- Aptitud para principiantes
- 45/100