Skip to content

anchors: POST /v1/decision-ledger/anchor-attempts publishes no request-body schema #9770

Description

@JSONbored

Sub-issue of #9719. Decision-independent.

Problem

POST /v1/decision-ledger/anchor-attempts is, by design, a contract for a submitter that lives outside this reposrc/review/ledger-anchor-bittensor.ts:3-8 says so explicitly ("a small process on the operator's own node infrastructure… never in this repo"). An off-repo implementer's only reference is the OpenAPI document.

That document registers responses only (src/openapi/spec.ts:1948-1961), so apps/loopover-ui/public/openapi.json carries no requestBody. The full shape exists and is strictly validated in parseBittensorAnchorReport (ledger-anchor-bittensor.ts:49-91), but an implementer has to read TypeScript source to discover it:

{
  signed: {
    payload: { v, ledger, seq: int>0, rowHash: /^[0-9a-f]{64}$/, totalCount: int>0, at: string(<=40) },
    keyId: string(<=64),
    signature: string(<=512, base64)
  },
  status: "ok" | "failed",
  backendRef: { netuid: int[0,65535], blockNumber: int>0, blockHash: /^0x[0-9a-f]{64}$/, hotkey: string(<=64) },  // when "ok"
  error: string(<=500)                                                                                            // when "failed"
}

An endpoint whose entire purpose is to be called by code we do not ship, documented only in the source of the thing calling it, is a contract with no published surface.

Scope

Register the request body on the OpenAPI path, derived from the same validator rather than hand-copied — a second hand-maintained description of these bounds would drift, which is the failure @loopover/contract exists to prevent (#9521).

Also document the four named 422 rejection reasons (unknown_key, bad_signature, row_not_found, row_hash_mismatch). They are deliberately specific so a submitter bug is diagnosable from the response alone, and that is only useful if they are written down.

row_not_found deserves an explicit note, because it is the one an off-repo implementer will hit first and misdiagnose: an ok report is verified against the receiving deployment's own decision_ledger (ledger-anchor-bittensor.ts:113-115), so reporting an anchor for a ledger the receiver does not hold is rejected by design, not by misconfiguration. On api.loopover.ai that ledger is empty — see #9719.

Validation

npm run ui:openapi regenerates the committed artifact; ui:openapi:check enforces it. The existing parser tests in test/unit/ledger-anchor-bittensor.test.ts already pin the bounds, so the schema should be checked against them rather than asserted independently.

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