Storage verification
StableGenerated from capsule-server/openapi.json, the OpenAPI 3.2 document
capsule-server emits and mise run openapi-check-kynos keeps current. To change a
description on this page, change the annotation on the handler or model it comes from
and regenerate — this file is build output. The auth model, error contract, and
conventions common to every endpoint are on the REST API overview.
GET /v1/assets/{asset_id}/receipts
Section titled “GET /v1/assets/{asset_id}/receipts”Fetch every custody receipt covering one asset.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
asset_id | path | string | Required. The asset id. |
| Status | Body | Description |
|---|---|---|
200 | AssetReceiptsResponse application/json | OK. |
400 | CodedProblem application/problem+json | Bad Request. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate. |
403 | CodedProblem application/problem+json | Forbidden. |
404 | CodedProblem application/problem+json | Not found. |
413 | — | the request body exceeds the configured limit. |
500 | CodedProblem application/problem+json | Internal server error. |
POST /v1/storage/verify
Section titled “POST /v1/storage/verify”Confirm that the server holds the copies a client is about to stop holding.
A pure read: it writes no blob, no index row and no verdict. Soundness against a racing collection comes from the standing GC grace window rather than from a per-request lease, which is why nothing here takes one.
Authentication: required — bearer.
Request body (required, application/json): StorageVerifyRequest
| Status | Body | Description |
|---|---|---|
200 | StorageVerifyResponse application/json | OK. |
400 | CodedProblem application/problem+json | Bad Request. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate. |
403 | CodedProblem application/problem+json | Forbidden. |
413 | — | the request body exceeds the configured limit. |
415 | CodedProblem application/problem+json | Unsupported Media Type. |
422 | CodedProblem application/problem+json | Unprocessable Entity. |
500 | CodedProblem application/problem+json | Internal server error. |
Schemas
Section titled “Schemas”The models these endpoints carry. A field whose type names another model links to it when this page documents that model, which it does when some path from an operation reaches it within 4 references. A model only ever reached deeper than that is named without being expanded.
AssetReceipt
Section titled “AssetReceipt”One custody receipt, decoded, beside the bytes that were signed.
| Field | Type | Description |
|---|---|---|
receipt_seq | integer | Required. Strictly monotonic per server. The chain position this receipt cannot be moved from. |
server_id | string | Required. This server’s canonical origin — what binds the receipt to one server. |
server_key_id | string | Required. The attestation key fingerprint that signed, hex. Survives rotation, which is why the key is named rather than assumed. |
prior_receipt_hash | string | null | SHA-256 of the previous receipt in the server’s log, hex. Absent for the first receipt this server ever issued. |
upload_id | string | Required. The upload session that produced custody. |
blob_role | string | Required. original, derivative, metadata or provenance. |
ciphertext_hash | string | Required. The server-recomputed ciphertext content address, hex. |
size | integer | Required. Ciphertext size in bytes. |
envelope_hash | string | null | SHA-256 of the asset’s signed manifest, hex — present on the provenance receipt and absent on every other, because the manifest commits to the rest. |
received_at | string | Required. The server’s trusted clock at the finalization commit, RFC 3339. |
receipt_cbor | string | Required. The full signed receipt as canonical CBOR, base64. This is the receipt. Verify the hybrid signature over these bytes under the key server_key_id names, from /.well-known/capsule/attestation-keys; everything above is a reading of them. |
AssetReceiptsResponse
Section titled “AssetReceiptsResponse”The chain.
| Field | Type | Description |
|---|---|---|
asset_id | string | Required. The asset the chain belongs to, echoed so a client batching requests can tell the answers apart. |
receipts | AssetReceipt[] | Required. Every receipt covering the asset, in receipt_seq order. |
AssetVerifyRequest
Section titled “AssetVerifyRequest”One asset to verify, with the exact copies the client is relying on.
| Field | Type | Description |
|---|---|---|
asset_id | string | Required. The asset. |
blob_hashes | string[] | Required. Every content address the client would be trusting the server with. The verdict is a conjunction over exactly these, so a client asks about what it is about to delete. |
BlobVerdictResponse
Section titled “BlobVerdictResponse”One declared blob’s verdict.
| Field | Type | Description |
|---|---|---|
hash | string | Required. The address, as the client declared it. |
role | string | Required. The role the asset holds it under — unknown for a hash the asset does not hold. |
stored | boolean | Required. The bytes are present at that address. |
indexed | boolean | Required. A live asset of the caller’s references the address. |
retrievable | boolean | Required. Nothing is withholding it. |
deep | string | null | What a deep scan found: intact, corrupt, or rate_limited (S-C41). Absent when no deep scan ran, and the absence is load-bearing: it is the difference between “we did not look at the bytes” and “we looked and they were fine”, and a client deciding whether to release its only copy has to be able to tell those apart. |
CodedProblem
Section titled “CodedProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
StorageVerdictResponse
Section titled “StorageVerdictResponse”One asset’s verdict.
| Field | Type | Description |
|---|---|---|
asset_id | string | Required. The asset the client asked about. |
durable | boolean | Required. Every declared blob is stored ∧ indexed ∧ retrievable. This is the field that gates a deletion, so it is false whenever the server cannot say otherwise. |
blobs | BlobVerdictResponse[] | Required. One entry per declared hash, in declaration order and never shortened. |
checked_at | string | Required. The server’s own clock at verification, RFC 3339. Never the client’s. |
StorageVerifyRequest
Section titled “StorageVerifyRequest”The POST /v1/storage/verify body.
| Field | Type | Description |
|---|---|---|
assets | AssetVerifyRequest[] | Required. The assets to verify. |
deep | boolean | Also re-read and re-hash the bytes (S-C41). Absent or false is the structural check: ask the index and the store whether the bytes are there. true additionally re-hashes them, which is the only way to catch silent corruption — stored is a question about the filesystem, and a corrupt blob is still stored. Rate-limited per account, because a deep scan reads and hashes every declared blob and an unbounded one is an I/O-amplification attack costing the caller one small JSON body. Past the budget the structural verdict still comes back and each blob’s deep reads rate_limited: throwing away a good structural answer because the optional half was throttled would make the limiter cost more than it saves. |
StorageVerifyResponse
Section titled “StorageVerifyResponse”The POST /v1/storage/verify response.
| Field | Type | Description |
|---|---|---|
verdicts | StorageVerdictResponse[] | Required. One verdict per requested asset, in request order. |