Proofs And Certificates

Proofs are .der files produced by the wipe agent. The backend stores the raw proof object before processing and uses asynchronous workers to validate, decrypt, sign, certify, and optionally anchor the result.

Submission Routes

RouteAuthUse
POST /api/v1/proofsCLIENT_ADMIN, CLIENT_TECH, or generic proofs:write API keySubmit one multipart .der proof.
POST /api/v1/proofs/bulkCLIENT_ADMIN, CLIENT_TECH, or generic proofs:write API keySubmit up to 100 files or a ZIP archive, max 500 MB.
POST /ingest/v1/proofsEnrolled-agent API key with proofs:writeSubmit one raw .der body from an enrolled agent.
GET /ingest/v1/proofs/{id}Enrolled-agent API key with proofs:readPoll the status of an agent-owned proof.

Protected writes require Idempotency-Key. The unit proof size limit is 5 MB. The local rate limits are per authenticated principal or agent key: 100 unit submissions per hour and 500 batch submissions per hour. Each quota is a separate counter, shared across all API and ingest replicas through the database (rate_limit_windows, migration 0025); a 429 carries Retry-After.

The only value the backend accepts as a successful wipe, for disks[].wipe_status and wipe.result, is SUCCESS (case-insensitive). A disk without a wipe_status inherits wipe.result. Older synonyms such as true, wiped, ok, passed or completed are treated as failures, and a proof with no successful disk is REJECTED; check agent fleets still emitting them before upgrading.

Proof Statuses

StatusMeaningOperator action
RECEIVEDStored and queued.Watch queue depth if it persists.
VALIDATINGWorker is validating proof envelope, agent trust, schema, and version.Inspect worker logs if stalled.
GENERATING_PDFCertificate PDF is being rendered.Check object storage and signer if failures appear.
SIGNINGHMAC/PAdES/receipt signing is running.Check signer readiness and key IDs.
ANCHORINGAnchor worker is processing chain metadata.Check chain worker and blockchain configuration.
CERTIFIEDCertificate was produced with anchor data.No action.
CERTIFIED_NO_ANCHORCertificate was produced without active anchor data.Accept only when product policy allows.
AWAITING_LICENSEProof is valid but quota/licensing is unavailable.Import/allocate licenses, then retry.
FAILEDRecoverable dependency or processing failure.Fix root cause, then retry.
REJECTEDTerminal validation failure.Do not replay unless validation policy was wrong.
ABANDONEDOperator abandoned a failed proof.Keep audit context.

Lifecycle Actions

ActionRouteRole
List proofsGET /api/v1/proofsCLIENT_ADMIN, CLIENT_TECH, AUDITOR
Read proofGET /api/v1/proofs/{id}CLIENT_ADMIN, CLIENT_TECH, AUDITOR, or proofs:read where accepted
Read statusGET /api/v1/proofs/{id}/statusCLIENT_ADMIN, CLIENT_TECH, AUDITOR, or proofs:read where accepted
RetryPOST /api/v1/proofs/{id}/retryCLIENT_ADMIN
Full restartPOST /api/v1/proofs/{id}/full-restartCLIENT_ADMIN
AbandonPOST /api/v1/proofs/{id}/abandonCLIENT_ADMIN

retry, full-restart, and abandon require recent MFA when SENSITIVE_ACTION_MFA_MAX_AGE is enabled.

Rejection Codes

When a proof transitions to REJECTED, the API exposes two fields:

  • rejection_reason — free-text description of the failure, written by the pipeline step that detected it. Its wording may change between releases.
  • rejection_code — stable, machine-readable identifier that ISOs and integrations can act on without parsing text. The field is empty for proofs rejected before migration 0026 and for every non-REJECTED status.
CodeMeaning
no_successful_diskNo disk of the session reports SUCCESS; the portal certifies nothing (portal rule, outside the shared schema).
payload_not_jsonThe decrypted body is not a JSON document.
payload_invalidThe document does not satisfy the portal’s legacy (pre-v4) payload rules; rejection_reason says which field.
schema_invalidschema.Decode or schema.Validate of the shared module refused the v4 report (shape, enumeration, form, bound).
schema_version_unknownschema_version is not the one the shared module carries (schema.ErrVersion).
signature_missingThe CMS envelope carries no signature (envelope.ErrUnsigned).
signature_invalidThe signature does not verify, or the signer names no certificate (envelope.ErrSignature, ErrCertificate, ErrMessageDigest; legacy inline agent_signature failures).
untrusted_signerThe signer certificate does not chain to a trusted root (envelope.ErrUntrusted).
identity_refusedThe ISO identity is unknown, not ENROLLED, or revoked (envelope.ErrIdentity).
envelope_invalidAny other structural refusal of the CMS envelope (envelope.ErrSignedData, ErrAlgorithm, ErrAttributes, ErrSignerKey, ErrEnveloped, ErrNotCanonical, ErrIdentifier).
report_digest_mismatchThe decrypted report is not the one the signed report-sha256 names (envelope.ErrReportDigest).
session_binding_mismatchThe report’s wipe_session_id or iso_id differ from the signed attributes (envelope.ErrBinding).
organization_mismatchThe signer identity or the issuer member is bound to another Organisation than the submitter’s.
replayAnother proof of the same Organisation with the same wipe_session_id was already accepted (uniqueness rule).
stored_hash_mismatchThe stored .der no longer matches the SHA-256 recorded at submission.

Codes are added, never renamed. rejection_reason remains free text and may carry additional diagnostic detail beyond what the code conveys.

Certificate Routes

ActionRouteRole
List certificatesGET /api/v1/certificatesCLIENT_ADMIN, CLIENT_TECH, AUDITOR
Read metadataGET /api/v1/certificates/{id}CLIENT_ADMIN, CLIENT_TECH, AUDITOR
Download PDFGET /api/v1/certificates/{id}/pdfCLIENT_ADMIN, CLIENT_TECH, AUDITOR
Download canonical JSONGET /api/v1/certificates/{id}/canonicalCLIENT_ADMIN, CLIENT_TECH, AUDITOR
RevokePOST /api/v1/certificates/{id}/revokeCLIENT_ADMIN

Certificate statuses are CERTIFIED, CERTIFIED_NO_ANCHOR, and REVOKED. Revocation requires an audit reason and recent MFA when configured.

Canonical Object Schema

The canonical JSON carries a schema member naming its version:

VersionContent
wipe.certificate.v1Pre-anchor-identity documents.
wipe.certificate.v2Adds the anchor.chain_id logical chain identity.
wipe.certificate.v3evidence is the RAW agent proof document.

In wipe.certificate.v3 the evidence member is the decrypted proof document itself, minus its agent_signature member and canonicalized with RFC 8785 (JCS) — byte-for-byte the payload the agent signature covers. Fields the portal does not model, empty arrays, explicit nulls and numbers as the agent wrote them are all preserved, so an agent can replay its own signature check against the certificate.

Certificates issued under v1 and v2 keep verifying: verification recomputes the hash from the stored canonical JSON and never rebuilds the document.

Public Verification

Public verification is available through:

RouteInput
GET /verify or GET /api/v1/public/verifyQuery parameters.
POST /verify or POST /api/v1/public/verifyJSON body, query parameters, or both.

Supported identifiers are code, certificate_id, canonical_hash, and tx_hash. When more than one identifier is supplied, they must refer to the same certificate or the result is IDENTIFIER_MISMATCH.

Public responses never include tenant ID, organization ID, proof ID, internal storage keys, canonical JSON, HMAC value, or PDF object keys.

Operator Checks

SymptomFirst checks
Proofs remain RECEIVEDproofs.validated queue, proof worker health, DB connectivity.
Proofs become AWAITING_LICENSEActive grants, allocation scope, user/org quota, grant validity dates.
Proofs become FAILEDSigner, object storage, PAdES/TSA, malformed environment configuration.
Certificates are CERTIFIED_NO_ANCHORBLOCKCHAIN_ENABLED, chain registry, anchor worker, Hedera readiness.
Public verification returns invalid/tamperedPDF/canonical/HMAC mismatch, revoked certificate, chain lookup failure, wrong identifier.