test(delegation): add supplementary-plane parent-key vector (closes gap named in §3.1.3) - #292
Conversation
Signed-off-by: rajnisht7 <rajnishtiwari9787@gmail.com>
lywinged
left a comment
There was a problem hiding this comment.
The vector does what section 3.1.3 asks for, and I would like it in. Two text items are why this is request changes rather than approve. Both are text only, and one of them is in a file this PR does not touch yet. I will approve as soon as they land.
1. Section 3.1.3 still says the gap is open. Two sentences of the near-miss paragraph at spec/trace-v0.2.md line 220 stop being true on merge. It opens "A near-miss here passes every existing vector." and closes "Every vector in examples/delegation-link/ is currently ASCII, so the corpus does not discriminate the two; a vector whose parent record carries a supplementary-plane key is what closes that." No file under spec/ is in this diff, so the specification would assert a gap the merged corpus has closed, while this PR's own CHANGELOG and profile text already say "was entirely ASCII" in the past tense. The description says the section needs no text change, and that is right about its three numbered requirements. The sentence the description quotes is one of the two, and both sit in the informative note below that list, so repairing them changes no normative text. Please carry the repair in this PR rather than leave it to a follow-up. Opening and closing sentences, something like:
A near-miss here passes every vector but one. ...
examples/delegation-link/24-parent-key-supplementary-plane.jsonis the vector that catches it: its parent record carries a key outside the Basic Multilingual Plane, where the two orderings disagree. Every other record in that corpus has ASCII keys.
One caution on the wording. Six vectors already hold a non-ASCII character in their description metadata, so the closing sentence is not true byte for byte today either. What was true, and what the paragraph is about, is that no record in the corpus carried a key outside the Basic Multilingual Plane. A repaired sentence that names record keys stays true.
2. The new paragraph in section 5 of the profile counts twenty-three where the corpus supports twenty. "Twenty-three of the twenty-four score the ten rules above, two per rule with a declared implementation defect that one vector catches and the other misses." Measured the way tests/test_delegation_completeness.py states, rebuilding the rule registry without one entry and counting the vectors whose outcome moves, exactly twenty vectors are load-bearing, two per rule, which is what tests/delegation_margins.json records. Vectors 01, 02 and 03 expect verified with no codes, and no rule fires on them. The set is twenty rule vectors, three clean chains, and this one.
Not requests, for a later reader:
- The two orderings do not diverge on a supplementary-plane key alone. A second key in U+E000 to U+FFFF is what makes them disagree, and an emoji against an ASCII key sorts the same under both. Vector 24 carries that pair, and
03-utf16-key-order.jsonpairs a supplementary-plane key with one in that range as well, but the sentences in the CHANGELOG and the profile name only the supplementary-plane member.test_the_root_record_has_the_key_pair_this_vector_needsaccepts any BMP key, so a companion below U+D800 passes it while the vector stops discriminating. I regenerated the corpus with an ASCII companion to check: the vector still verifies and the whole vector loop still passes, and three of the four other assertions in that file are what catch it. - The vector catches a verifier that canonicalizes by code point. One that indexes parents under both canonicalizations resolves the link and passes, which rule 2 of section 3.1.3 forbids. Nothing for this PR to do about that.
Run against 008d0d9 from a fresh clone before writing the above:
- Full suite 1175 passed and 1 skipped;
ruff check src tests scripts,tools/check_dashes.pyandmypy src/agentrust_tracewith the dev extras all clean. - Four wrong canonicalizers over all 24 vectors,
json.dumps(sort_keys=True)with and without escaping and two hand written serializers ordering by UTF-8 bytes and by code point: vector 24 is the only one whose outcome moves, fromverifiedtoprovenance-invalidwithparent_not_found. - A JCS serializer written from RFC 8785 section 3.2.3 rather than from the library reproduces
rfc87850.1.4's bytes for the root record and the declaredparent_record_hash. - Both records validate against the schema and both signatures verify; the reference model round-trips the root with its two extra key members and the digest survives.
- The generator regenerates all 24 vectors byte for byte, and vector 24 differs from vector 01 only in the context leaf, the parent hash, those two members and the two signatures.
Tool-assisted: the runs and this write-up.
Signed-off-by: rajnisht7 <rajnishtiwari9787@gmail.com>
Signed-off-by: rajnisht7 <rajnishtiwari9787@gmail.com>
lywinged
left a comment
There was a problem hiding this comment.
Both items are in, and the wording is right. Checked on adc851a: the near-miss paragraph now opens with a claim the corpus supports and closes by naming the vector, and the profile paragraph reads twenty of the twenty-four with the three clean chains called out. I re-measured both against the corpus. Twenty vectors are load-bearing, two per rule, and 01, 02 and 03 are the three that no rule fires on. No record other than vector 24's carries a non-ASCII key, so the closing sentence holds. Full suite 1175 passed and 1 skipped, and ruff, tools/check_dashes.py and mypy are clean.
One thing arrived with the dash fix, which took the spaces with it:
Three more (`01`to`03`) are clean chains
That renders as 01to03. Just push the two spaces.
Not a request: the CHANGELOG bullet still says "That section states the corpus was entirely ASCII", in the present tense, about a section this PR has now changed. Fine to leave if that bullet reads as history.
Tool-assisted: the runs and this write-up.
lywinged
left a comment
There was a problem hiding this comment.
Approving at e446329. The spaces are in, and both items from the earlier review are correct.
Re-measured on this head rather than carried over: twenty-four vectors, twenty load-bearing with two per rule, and vector 24 still the only one whose outcome moves when the walk canonicalizes by code point, from verified to provenance-invalid with parent_not_found. The generator regenerates the corpus byte for byte. Full suite 1175 passed and 1 skipped, with ruff, tools/check_dashes.py and mypy clean.
Thanks for taking the specification sentence rather than leaving it for a follow-up. The corpus now says what section 3.1.3 says it says.
Tool-assisted: the runs and this write-up.
imran-siddique
left a comment
There was a problem hiding this comment.
Reviewed the added vector, generator, tests, and accompanying text at e446329. Locally, the delegation suites pass all 85 tests, including the positive reference walk and the divergent UTF-16/code-point parent digest. Regenerating the corpus produces no content diff after Git's line-ending normalization. The specification edit updates the description of the corpus without changing a requirement. Commits are signed off, Python 3.11/3.12 and CodeQL checks have passed, and the prior review's requested changes are addressed on this head.
What this changes
Adds a conformance vector to
examples/delegation-link/that spec section 3.1.3 names as missing. That section (landed in #245/#276) says the corpus is entirely ASCII, so it can't tell an implementation that canonicalizes the delegation chaindigest correctly (RFC 8785, UTF-16 key order) apart from one that takes a common shortcut (
sort_keys=True, code-point order) the two agree everywhere except when a key holds a supplementary-plane character:Vector 24's root carries an extra
cnf.jwkmember keyed outside the Basic Multilingual Plane. Verified the divergence is real, not theoretical: a naive canonicalizer computes a different root digest and reportsparent_not_foundon a chain that's otherwise identical to vector 01. Confirmed by mutation-testing all 24 vectors against both canonicalizers only vector 24's outcome changes.Type of change
Spec section
§3.1.3 (
delegation.parent_record_hash) : no text changed, this closes a test-coverage gap that section names.Checklist
git commit -s)CHANGELOG.mdupdated (for any normative change)<!-- CHANGED: #NNN: description -->in spec text