fix(anchor): parse Rekor v2's response shape, not v1's - #9855
Conversation
submitToRekor was v2 on the request side -- hashedRekordRequestV002, POST /api/v2/log/entries -- while parseRekorResponse expected v1: an object keyed by entry uuid, a numeric logIndex, and a uuid field. Rekor v2 returns the TransparencyLogEntry directly, encodes logIndex as a proto3 int64 (JSON "42", a string), and has no uuid at all. All three checks failed on every real response, so this backend could never record a successful anchor even when the log accepted the submission -- it wrote status: failed with "did not match the expected TransparencyLogEntry shape". Surfaced on a live self-host instance: once #9845 fixed the shard URL, the error moved from fetch failed (DNS) to this parse failure, i.e. the submission now reaches a real log and is rejected only at our end. The fixture was itself v1-shaped and its assertion's title read "reading the entry under its dynamic uuid key", so the test agreed with the bug and could not fail. Replaced with a real-shaped entry; the scheduler's inline mock had the same problem. backendRef carries the inclusion proof's checkpoint where uuid used to be -- v2's locator, since an entry is identified by log index plus the checkpoint the proof was issued against. An absent checkpoint parses to null rather than failing: the entry IS in the log, only the offline re-check is unavailable, and discarding a real submission over an optional field is the worse trade. An unparseable logIndex still fails, so NaN can never reach a published backendRef. Closes #9854
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-29 14:29:44 UTC
Review summary Nits — 6 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9855 +/- ##
==========================================
- Coverage 91.65% 90.77% -0.88%
==========================================
Files 916 916
Lines 112763 112772 +9
Branches 27087 27093 +6
==========================================
- Hits 103348 102366 -982
- Misses 8126 9315 +1189
+ Partials 1289 1091 -198
Flags with carried forward coverage won't be shown. Click here to find out more.
|
Closes #9854
The backend was half-migrated
submitToRekoris Rekor v2 on the way out —hashedRekordRequestV002,POST /api/v2/log/entries— and Rekor v1 on the way back in:v2 returns the
TransparencyLogEntrydirectly, encodeslogIndexas a proto3 int64 (JSON"42", a string), and has nouuid— an entry is located by log index plus the checkpoint its inclusion proof was issued against.All three checks fail on every real response, so this backend could never record a successful anchor, even when the log accepted the submission.
How it surfaced
On the live self-host instance from #9845. Once the shard URL was corrected, the published failure moved from
fetch failed(DNS) to"Rekor response did not match the expected TransparencyLogEntry shape"— the submission now reaches a real log and is rejected only at our end.Why review couldn't have caught it
The fixture was v1-shaped, and the assertion's title read "reading the entry under its dynamic uuid key". The test agreed with the bug. Both are corrected rather than deleted, so the contract change is visible in history — and the scheduler suite had the same v1 mock inline.
Judgement calls
nullrather than failing. The entry is in the log; only the offline re-check is unavailable. Throwing away a real successful submission over an optional field is the worse trade.logIndexstill fails. Coercing would putNaNin a publishedbackendRef, which is worse than no anchor.backendRefreshaped (uuid→checkpoint). It is opaque per-backend JSON — the git backend stores{owner, repo, branch, path, sha}— so nothing parses the rekor variant's fields.backendRefthat points nowhere.Validation
tsc --noEmitclean. 87 tests pass across the rekor, scheduler, persistence and public-route suites.ledger-anchor-rekor.tsat 100% lines / 100% branches.Merged current main (including #9845, which touched the same file) and verified both changes coexist: the corrected default shard, the endpoint-naming error wrap, and this parser are all present.