You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(v2.8.1): wire canonicalization_profile across the 4 SDKs + close spec gaps
v2.8.0 declared the `canonicalization_profile` field in the bundle
manifest schema and described it normatively, but no SDK actually
wrote or read the field — the typed `BundleManifest` structures
shipped without it, and verifiers ignored it. v2.8.1 closes the gap
end to end.
SDK changes (TS / Python / Go / Rust)
-------------------------------------
- TypeScript (`@dcp-ai/sdk` 2.1.0 → 2.1.1): `BundleManifest`
interface in `types/v2.ts` gains
`canonicalization_profile?: 'dcp-jcs-v1'`. `BundleBuilderV2.build()`
in `bundle/builder-v2.ts` emits the field on every produced
manifest. `verifyV2Bundle` in `core/verify-v2.ts` accepts an absent
field (assumes `dcp-jcs-v1`), accepts `"dcp-jcs-v1"` explicitly,
and rejects any other value.
- Python (`dcp-ai` 2.8.0 → 2.8.1): `BundleManifest` in
`dcp_ai/v2/models.py` gains
`canonicalization_profile: Literal["dcp-jcs-v1"] | None = "dcp-jcs-v1"`.
Pydantic enforces unknown-value rejection at parse time; absence
triggers the default value.
- Go (`sdks/go/v2.8.0` → `v2.8.1`): `BundleManifest` struct in
`dcp/v2/types.go` gains `CanonicalizationProfile string` with
`json:"canonicalization_profile,omitempty"`. `BuildBundleV2` in
`dcp/v2/bundle_builder.go` sets `"dcp-jcs-v1"` on every produced
manifest. `VerifySignedBundleV2` in `dcp/v2/verify_bundle.go`
rejects manifests carrying any other value.
- Rust (`dcp-ai` crates.io 2.8.0 → 2.8.1): `BundleManifest` in
`src/v2/types.rs` gains `pub canonicalization_profile: Option<String>`
with `skip_serializing_if = "Option::is_none"`. `wasm_build_bundle`
in `src/lib.rs` emits the field on its manifest.
Spec & profile document
-----------------------
- `spec/DCP-AI-v2.0.md` § 9 (Bundle Manifest) now lists
`canonicalization_profile` alongside the other manifest fields,
with an inline note that an absent field MUST be assumed equivalent
to `"dcp-jcs-v1"`.
- `spec/CANONICALIZATION_PROFILE.md` § 2 — Rule 6 is rewritten as a
cross-language table that explicitly maps TypeScript, Python, Go,
and Rust host values onto the JSON wire format for both object
slots and array slots. The previous prose-only rule left
Python `None`, Go `nil`, and Rust `Option::None` underspecified
for verifiers cross-checking foreign producers.
- `spec/CANONICALIZATION_PROFILE.md` § 2 — new Rule 9 makes Unicode
normalization (NFC, NFD, NFKC, NFKD) explicitly out of scope: the
canonicalizer emits strings byte-for-byte as the host parser
delivers them, and a future profile (`dcp-jcs-v2` or later) MAY
pin a normalization form. RFC 8259 § 8.1 is referenced as the
conventional choice (NFC) for application-layer normalisation.
- Rule 9 also pins the rationale for not shipping `NaN` /
`±Infinity` interop fixtures: those values are not part of RFC
8259 wire format, so most parsers reject them before the
canonicalizer is reached. Rejection is verified by per-SDK unit
tests rather than shared fixtures.
Behavioural compatibility
-------------------------
The new field is additive and optional in serialization. A
`v2.8.1`-produced bundle carries `canonicalization_profile:
"dcp-jcs-v1"` on its manifest. Bundles produced by `v2.8.0` or
earlier have no such field, and `v2.8.1` verifiers accept them per
`spec/CANONICALIZATION_PROFILE.md` § 4 (absent ≡ `dcp-jcs-v1`). A
bundle that carries an unknown value (e.g. `"dcp-jcs-v2"`) is
rejected by every `v2.8.1` SDK — the forward-compatibility hook for
future profiles.
The bundle-level signature covers `canonical(manifest)`, so newly-
produced bundles have a different manifest hash than they would
under `v2.8.0`. Existing signed bundles and their stored signatures
remain valid under `v2.8.1` verifiers.
Tests
-----
- Conformance (root): DCP-AI CONFORMANCE PASS (V1 + V2)
- TypeScript: 461/461
- Python: 236/236
- Go: 4 packages OK
- Rust: 181 tests across 10 binaries
0 commit comments