The traceability table, the READMEs, SECURITY.md and the header comment
of datekeys.cddl still described earlier versions: three drand schemes,
18 normative errors, a CDDL of v0.11 and signed releases that do not exist
yet. No normative text and no schema changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| 11 | Canonical profile encoding, `profile_hash`; `period` in 1..2^53−1, `genesis_time` in 0..2^53−1 | `Profile.CanonicalCBOR`, `Profile.Hash`, `profile.Decode` (hand-written `wire` encode and decode: keys 0 to 10, all required, in order; unsigned `genesis_time`, `codec.MaxSafeUint`; `period` limited to 1..86400 s, an implementation limit marked in `spec/datekeys.cddl`, `ERR_NON_CANONICAL_CBOR`) | `profile.TestQuicknetMatchesGoldenVector`, `TestQuicknetCBORLayout`, `TestDecodeRoundTrip`, `TestDecodeStructure`, `TestIntegerRanges`, `FuzzDecode`; `testdata/vectors/profile_quicknet.json`; the `provider_profile` block of `testdata/vectors/cbor.json` (*period of one day, the implementation limit*, *… above the implementation limit*) |
| 12.1 | Provider Profile validation: CDDL, field rules (`ERR_UNKNOWN_PROFILE`: the name alphabets, normative, and their lengths and the `public_key` size, implementation limits; `period` at most 2^32−1, implied by the 86400 s limit; `genesis_time` in 1..253402300798, provider `drand`, the three unchained tlock schemes, a public key that is the canonical encoding of a point of the key group (§12.2) other than the identity), then the chain-hash self-check (`ERR_PROFILE_MISMATCH`), then the pinned `profile_hash`; the same codes on the pin path and the decode path | `profile.Decode`, `Profile.Validate` (rules 1 to 3 for a value), `validateDrand` (drand `chain.Info.Hash`), `profile.NewRegistry` (encode, `Decode`, then the pinned hash) | `profile.TestDecodePrecedence` (with a G1 point outside the subgroup), `TestPinPathMatchesDecode`, `TestChainHashFormula` (the formula computed without drand), `TestPublicKeyEncodingIsCanonical`, `TestValidateRejectsTamperedProfiles`, `TestRegistry`; the `provider_profile` block of `testdata/vectors/cbor.json` |
| 12.1 | Provider Profile validation: CDDL, field rules (`ERR_UNKNOWN_PROFILE`: the name alphabets, normative, and their lengths and the `public_key` size, implementation limits; `period` at most 2^32−1, implied by the 86400 s limit; `genesis_time` in 1..253402300798, provider `drand`, the scheme `bls-unchained-g1-rfc9380` alone since v0.14, a public key that is the canonical encoding of a point of G2 (§12.2) other than the identity), then the chain-hash self-check (`ERR_PROFILE_MISMATCH`), then the pinned `profile_hash`; the same codes on the pin path and the decode path | `profile.Decode`, `Profile.Validate` (rules 1 to 3 for a value), `validateDrand` (drand `chain.Info.Hash`), `profile.NewRegistry` (encode, `Decode`, then the pinned hash) | `profile.TestDecodePrecedence` (with a G1 point outside the subgroup), `TestPinPathMatchesDecode`, `TestChainHashFormula` (the formula computed without drand), `TestPublicKeyEncodingIsCanonical`, `TestValidateRejectsTamperedProfiles`, `TestRegistry`; the `provider_profile` block of `testdata/vectors/cbor.json` |
| 12.2 | Canonical encoding of a BLS12-381 point: compressed, 48 bytes in G1 and 96 in G2 (c1 then c0); compression flag set, infinity flag only for the point at infinity with every other bit zero, sort flag for the lexicographically largest y; coordinates below p; the prime-order subgroup; every other string rejected (x + p, c0 + p, c1 + p, an identity with a payload or the sort flag, no compression flag, uncompressed forms, other lengths) | the decoder of `kilic/bls12-381` through drand's `kyber-bls12381` (`KyberG1` and `KyberG2``UnmarshalBinary`), which the reference runs for the public key (`profile.validateDrand`), the release signature (drand `Scheme.VerifyBeacon` in `provider.Verify`) and U (`tlock.BytesToCiphertext` in `agewrap.TimeIdentity.Unwrap`); the point at infinity refused explicitly for the public key and U, and for the signature by the BLS verification | `profile.TestDrandPointDecodersAreCanonical` (fails if a dependency update makes the decoders lenient), `TestPublicKeyEncodingIsCanonical`; `provider.TestVerifyRejects`; `agewrap.TestTimeIdentityStrictness`, `TestTimeIdentityRelease`; `internal/testkit.TestPointReencodings`; `capsule.TestPointMutationsChangeOnlyTheEncoding`; the ten point mutations of §64 |
| 13 | Root of trust | `profile.NewRegistry`, `profile.Pin`, `profile.Default`, `QuicknetProfileHash`; chain-hash self-check in `Profile.Validate` (the drand chain-info hash, formula in spec §12.1) | `profile.TestRegistry`, `TestPinPathMatchesDecode`; mutations *unknown profile*, *empty registry*; the `provider_profile` block of `testdata/vectors/cbor.json` |