Skip to content

orb(anchor): the Rekor backend parses a v1 response shape, so a v2 submission can never record success #9854

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR.

Problem

submitToRekor is Rekor v2 on the request side — it builds a hashedRekordRequestV002 body and POSTs to
/api/v2/log/entries — but parseRekorResponse expects the v1 response shape:

const entries = Object.values(raw as Record<string, unknown>);   // v1: { "<uuid>": entry }
const entry = entries[0];
typeof candidate["logIndex"] !== "number"                        // v1: number
typeof candidate["uuid"] !== "string"                            // v1: has a uuid

Rekor v2 returns the TransparencyLogEntry directly, encodes logIndex as a proto3 int64 (so JSON
"42", a string), and has no uuid field at all — an entry is identified by its log index plus the
checkpoint its inclusion proof was issued against.

So all three checks fail on every real response. This backend can never record a successful anchor, even
when the log accepts the submission — it writes status: failed, "Rekor response did not match the expected TransparencyLogEntry shape", and moves on.

How it surfaced

On a live self-host instance with a populated ledger. After #9845 corrected the shard URL, the recorded error
moved from fetch failed (DNS) to the parse failure above — i.e. the submission now reaches a live log and is
rejected only at our end.

Why review did not catch it

The test fixture was itself v1-shaped:

const REKOR_RESPONSE = { "24296fb24b8ad77a": { logIndex: 42, uuid: "24296fb24b8ad77a", logId: { keyId: "c2iga0d1" } } };

and the assertion's own title read "reading the entry under its dynamic uuid key". The test agreed with the
bug, so it could not fail.

Requirements

  • Parse the v2 TransparencyLogEntry: entry at the top level, logIndex accepted as string OR number,
    logId.keyId required.
  • Replace uuid in backendRef with the checkpoint from inclusionProof — the v2 locator. backendRef is
    opaque per-backend JSON (the git backend stores a completely different shape), so this is safe to reshape.
  • A missing/malformed checkpoint must NOT fail the parse: the entry is in the log, only the offline re-check
    is unavailable, and discarding a real successful submission over an optional field is worse.
  • A non-finite or unparseable logIndex MUST fail, rather than publishing NaN in a backendRef.
  • The old v1 wrapper must now be rejected rather than half-parsed.

Deliverables

  • parseRekorResponse handles the v2 shape; fixture replaced with a real-shaped one.
  • Tests for: string logIndex, numeric logIndex, unparseable logIndex, missing/bad logId, checkpoint from
    {envelope}, bare-string checkpoint, absent checkpoint (parses, null), v1 wrapper rejected.
  • The scheduler test's inline mock updated too — it is v1-shaped as well.

Test Coverage Requirements

99%+ Codecov patch coverage, branch-counted.

Links

src/review/ledger-anchor-rekor.ts. Response shape: https://github.com/sigstore/rekor-tiles/blob/main/CLIENTS.md
Related: #9845, #9271.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions