Skip to main content

Documentation Index

Fetch the complete documentation index at: https://agentvolumes.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Trust attachments are append-only records associated with a published release subject. You upload them through the same two-phase lifecycle used for release archives: create an upload intent, PUT the attachment bytes to the returned URL, then finalize so the bibliotheca can verify the digest, validate subject binding, and make the attachment available through trust discovery. Authentication is required for all trust upload operations.

Endpoints

# Create upload intent — scopeless
POST /api/v1/volumes/{name}/{version}/trust/uploads

# Create upload intent — scoped
POST /api/v1/volumes/@{scope}/{name}/{version}/trust/uploads

# Finalize — scopeless
POST /api/v1/volumes/{name}/{version}/trust/uploads/{uploadId}/finalize

# Finalize — scoped
POST /api/v1/volumes/@{scope}/{name}/{version}/trust/uploads/{uploadId}/finalize

Upload lifecycle

1

Create an upload intent

Send a POST to the trust uploads endpoint with the release subject, attachment category, format metadata, and declared digest. The bibliotheca returns an uploadId and opaque upload instructions.
POST /api/v1/volumes/@acme/research-agent-pack/1.4.0/trust/uploads
Authorization: Bearer <your-token>
Content-Type: application/json
Idempotency-Key: provenance-1.4.0-build-42

{
  "subject": {
    "purl": "pkg:volume/%40acme/research-agent-pack@1.4.0",
    "integrity": "sha256:a3f2b8c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2"
  },
  "attachment": {
    "category": "provenance",
    "format": {
      "family": "slsa-provenance",
      "mediaType": "application/vnd.in-toto+json",
      "predicateType": "https://slsa.dev/provenance/v1"
    }
  },
  "declaredDigest": "sha256:c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
  "declaredSize": 2048
}
The 201 Created response mirrors the schema-backed intent record, including the bound subject, attachment metadata, declared digest, upload instructions, expiration time, and intent state:
{
  "uploadId": "tup_01HZ9QRTXK4J2M8SVWBN6P3Y5C",
  "subject": {
    "purl": "pkg:volume/%40acme/research-agent-pack@1.4.0",
    "integrity": "sha256:a3f2b8c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2"
  },
  "attachment": {
    "category": "provenance",
    "format": {
      "family": "slsa-provenance",
      "mediaType": "application/vnd.in-toto+json",
      "predicateType": "https://slsa.dev/provenance/v1"
    }
  },
  "declaredDigest": "sha256:c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
  "declaredSize": 2048,
  "upload": {
    "instructionType": "http-put",
    "url": "https://upload.example.com/trust-staging/tup_01HZ9QRTXK4J2M8SVWBN6P3Y5C",
    "method": "PUT"
  },
  "expiresAt": "2026-05-18T16:00:00Z",
  "state": "pending-upload"
}
2

Upload the attachment bytes

PUT the raw attachment bytes to the upload.url returned in step 1. Include any headers specified in upload.headers.
PUT https://upload.example.com/trust-staging/tup_01HZ9QRTXK4J2M8SVWBN6P3Y5C
Content-Type: application/vnd.in-toto+json
Content-Length: 2048

<raw attachment bytes>
3

Finalize the upload

Call the finalize endpoint with the uploadId. The bibliotheca verifies the digest, validates subject binding, and makes the attachment available through trust discovery.
POST /api/v1/volumes/@acme/research-agent-pack/1.4.0/trust/uploads/tup_01HZ9QRTXK4J2M8SVWBN6P3Y5C/finalize
Authorization: Bearer <your-token>
The 201 Created response includes the finalized attachment identity, bound subject, artifact digest, status, and detail URL:
{
  "uploadId": "tup_01HZ9QRTXK4J2M8SVWBN6P3Y5C",
  "attachmentId": "att_01HZ9QRTXK4J2M8SVWBN6P3Y5C",
  "subject": {
    "purl": "pkg:volume/%40acme/research-agent-pack@1.4.0",
    "integrity": "sha256:a3f2b8c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2"
  },
  "artifactDigest": "sha256:c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
  "artifactSize": 2048,
  "status": {
    "state": "active"
  },
  "detailUrl": "https://api.example.com/api/v1/volumes/@acme/research-agent-pack/1.4.0/trust/detail"
}

Upload intent request fields

subject
object
required
The release subject this attachment is bound to. Must match the release’s published identity exactly.
attachment
object
required
Metadata describing the trust attachment you are uploading.
declaredDigest
string
required
sha256:<hex> digest of the attachment bytes you will upload. The bibliotheca verifies the uploaded bytes match this value during finalize.
declaredSize
integer
Optional declared byte length of the attachment.

Idempotency

Pass an Idempotency-Key header or a idempotencyKey body field (not both, or they must match exactly) to make the intent creation idempotent.
POST /api/v1/volumes/@acme/research-agent-pack/1.4.0/trust/uploads
Authorization: Bearer <your-token>
Idempotency-Key: provenance-1.4.0-build-42
Content-Type: application/json

{ ... }
The header form is the preferred portable API surface. If you pass both the header and the body field, they must be byte-for-byte identical; otherwise the bibliotheca returns a 409 Conflict with the idempotency-conflict problem type.

Upload intent state lifecycle

StateMeaning
pending-uploadIntent created; bytes not yet received
uploadingBytes transfer in progress
uploadedBytes received; ready to finalize
expiredIntent expired before finalization
failedUpload failed

The http-put upload profile

Every write-capable v0.1 bibliotheca that supports trust attachment uploads must implement the http-put upload profile:
  • upload.instructionType = "http-put"
  • upload.url is the opaque byte-transfer target
  • upload.method is "PUT" when present; default to PUT when omitted
  • upload.headers contains headers you must include on the PUT request
If an upload intent advertises only unsupported profiles, fail locally with an unsupported-upload-profile diagnostic.

What the bibliotheca verifies at finalize

During finalize, the bibliotheca:
  1. Verifies the uploaded bytes match the declaredDigest (and declaredSize when provided)
  2. Validates the release-subject binding — the attachment must bind to the intended release
  3. Checks attachment metadata consistency
  4. Confirms the caller remains authorized
A failed, expired, or conflicting upload will never silently create an active trust attachment.

After finalization

After a successful finalize, the attachment appears in the trust detail view with status.state = "active". From that point on, the attachment follows the same append-only lifecycle as all trust attachments — it can transition to revoked, superseded, or invalid, but it is never deleted.
Trust attachments are append-only. Previously published attachments are never silently replaced or deleted — they remain in the append-only record and are represented through status metadata changes.