Compliance Publishing

Policies API v1 endpoints for publishing compliance snapshots and evidence packages.

Publish compliance snapshots and evidence packages to Nirmata Control Hub. nctl uses these endpoints when publishing compliance results. You can also call them directly from your own tooling.

All paths are relative to /policies/api/v1. See Policies API v1 for authentication and conventions.

Endpoints

OperationMethodPath
List evidence packagesGET/compliance/evidence-packages
Declare an evidence packagePOST/compliance/evidence-packages
Publish a compliance snapshotPOST/compliance/snapshots
Get an evidence packageGET/compliance/evidence-packages/{id}
Download an evidence packageGET/compliance/evidence-packages/{id}/download
Upload an evidence package partPUT/compliance/evidence-packages/{id}/parts/{index}

Reference

List evidence packages

GET /policies/api/v1/compliance/evidence-packages

Lists the tenant’s evidence packages, newest collection first, optionally filtered by target and standard.

Roles: admin, platform, security, devops

Query parameters

NameTypeRequiredDefaultDescription
targetIdstringNo—Filter by cluster ID (UUID)
standardstringNo—Filter by standard key
limitintegerNo50Page size (1-500)
offsetintegerNo0Items to skip (>=0)

Response 200 (application/json)

Array of EvidencePackageDto (no total count)

FieldTypeDescription
idstring (uuid)Package ID
publishIdstring (uuid)Idempotency key
targetIdstring (uuid)Cluster ID
targetNamestringCluster name
standardstring—
reportIdstring (uuid)Linked snapshot report, if any
publisherstring—
publisherVersionstring—
collectedAtstring (date-time)—
contentTypestringArchive media type
sha256stringHex SHA-256 of the archive
sizeBytesinteger—
partSizeBytesintegerRequired size of every part except the last
partCountinteger—
receivedPartsinteger[]Part indexes already stored (for resuming)
statusstringuploading | complete | failed | deleting
errorMessagestringSet when failed
metadataobjectProducer metadata
createdBystring—
createdAtstring (date-time)—
completedAtstring (date-time)—
duplicatebooleanOnly on the declare response

Errors

  • 400 — INVALID_PAGINATION or INVALID_ID (bad targetId)
  • 401 — Not authenticated
  • 403 — Caller’s role is not in the allowed roles

Declare an evidence package

POST /policies/api/v1/compliance/evidence-packages

Declares an evidence archive (size, SHA-256, metadata) before uploading its bytes in parts. The response gives partSizeBytes/partCount. Idempotent on publishId: re-declaring returns the existing package with its receivedParts (200, duplicate=true) so an interrupted upload can resume.

Roles: admin, security

Request body (application/json)

FieldTypeRequiredDescription
publishIdstring (uuid)YesIdempotency key
schemaVersionstringYesEnvelope version (“v1”)
publisherobjectYes{name, version}
clusterobjectYes{id, kubeSystemUid, name}; at least one of id/kubeSystemUid
standardstringYesStandard key
collectedAtstring (date-time)YesWhen evidence was collected
snapshotPublishIdstring (uuid)NopublishId of a snapshot already published for the same cluster/standard
contentTypestringYesapplication/gzip | application/x-gzip | application/x-tar | application/zip
sizeBytesintegerYesArchive size (>0, subject to a server max)
sha256stringYes64 hex chars
metadataobjectNoJSON object of producer metadata (size-capped)

Response 201 (application/json)

EvidencePackageDto (200 when duplicate)

FieldTypeDescription
idstring (uuid)Package ID
publishIdstring (uuid)Idempotency key
targetIdstring (uuid)Cluster ID
targetNamestringCluster name
standardstring—
reportIdstring (uuid)Linked snapshot report, if any
publisherstring—
publisherVersionstring—
collectedAtstring (date-time)—
contentTypestringArchive media type
sha256stringHex SHA-256 of the archive
sizeBytesinteger—
partSizeBytesintegerRequired size of every part except the last
partCountinteger—
receivedPartsinteger[]Part indexes already stored (for resuming)
statusstringuploading | complete | failed | deleting
errorMessagestringSet when failed
metadataobjectProducer metadata
createdBystring—
createdAtstring (date-time)—
completedAtstring (date-time)—
duplicatebooleanOnly on the declare response

Errors

  • 400 — Validation failure (e.g. INVALID_PUBLISH_ID, UNSUPPORTED_CONTENT_TYPE, INVALID_SHA256, INVALID_SIZE, INVALID_METADATA, INVALID_SNAPSHOT_PUBLISH_ID, cluster errors)
  • 409 — PUBLISH_ID_CONFLICT, PACKAGE_DELETED (expired), or AMBIGUOUS_CLUSTER
  • 413 — EVIDENCE_PACKAGE_TOO_LARGE
  • 422 — CLUSTER_NOT_FOUND / CLUSTER_MISMATCH, SNAPSHOT_NOT_FOUND, or SNAPSHOT_MISMATCH
  • 401 — Not authenticated
  • 403 — Caller’s role is not in the allowed roles

Publish a compliance snapshot

POST /policies/api/v1/compliance/snapshots

Stores a compliance snapshot computed outside Nirmata (for example by nctl scan compliance --publish) as a completed compliance report for the identified cluster. Idempotent on publishId: returns 201 when created and 200 with duplicate=true (describing the original report) when that publishId was already recorded. Controls unknown to the tenant’s catalog are dropped and listed in ignoredControls.

Roles: admin, security

Request body (application/json)

FieldTypeRequiredDescription
publishIdstring (uuid)YesProducer-generated idempotency key
schemaVersionstringYesEnvelope version; only “v1” accepted
publisherobjectYes{name: lowercase tool id e.g. “nctl” (required), version (<=128 chars)}
clusterobjectYes{id: Nirmata cluster UUID, kubeSystemUid: kube-system namespace UID, name (informational)}; at least one of id/kubeSystemUid required, must agree if both given
snapshotobjectYesnctl state.Snapshot: {id, standard (required, must be a known standard), cluster, context, timestamp (required, not in the future), controls: [{id, policy, policy_count, status: pass|fail|not-evaluated, pass_count, fail_count}], exceptions: [“ns/name”]}

Response 201 (application/json)

SnapshotPublishResponseDto (200 when duplicate)

FieldTypeDescription
reportIdstring (uuid)Created (or original) report ID
publishIdstring—
targetIdstring (uuid)Resolved cluster ID
targetNamestringNirmata cluster name
standardstring—
scanTimestampstring (date-time)—
scorenumber0-100
levelstringgreen | yellow | red | unknown
duplicatebooleanTrue if publishId was already recorded
ignoredControlsstring[]Control IDs dropped as unknown (empty on duplicate)

Errors

  • 400 — Validation failure, e.g. BODY_REQUIRED, PUBLISH_ID_REQUIRED, INVALID_PUBLISH_ID, UNSUPPORTED_SCHEMA_VERSION, INVALID_PUBLISHER, CLUSTER_REQUIRED, INVALID_CLUSTER_ID, SNAPSHOT_REQUIRED, STANDARD_REQUIRED, UNKNOWN_STANDARD, TIMESTAMP_REQUIRED, FUTURE_TIMESTAMP, unsupported control status
  • 409 — PUBLISH_ID_CONFLICT (publishId reused for different content) or AMBIGUOUS_CLUSTER (several clusters share the kube-system UID)
  • 422 — CLUSTER_NOT_FOUND or CLUSTER_MISMATCH (id and kubeSystemUid refer to different clusters)
  • 401 — Not authenticated
  • 403 — Caller’s role is not in the allowed roles

Get an evidence package

GET /policies/api/v1/compliance/evidence-packages/{id}

Returns one evidence package’s metadata and upload status.

Roles: admin, platform, security, devops

Path parameters

NameTypeDescription
idstringPackage ID (UUID)

Response 200 (application/json)

EvidencePackageDto

FieldTypeDescription
idstring (uuid)Package ID
publishIdstring (uuid)Idempotency key
targetIdstring (uuid)Cluster ID
targetNamestringCluster name
standardstring—
reportIdstring (uuid)Linked snapshot report, if any
publisherstring—
publisherVersionstring—
collectedAtstring (date-time)—
contentTypestringArchive media type
sha256stringHex SHA-256 of the archive
sizeBytesinteger—
partSizeBytesintegerRequired size of every part except the last
partCountinteger—
receivedPartsinteger[]Part indexes already stored (for resuming)
statusstringuploading | complete | failed | deleting
errorMessagestringSet when failed
metadataobjectProducer metadata
createdBystring—
createdAtstring (date-time)—
completedAtstring (date-time)—
duplicatebooleanOnly on the declare response

Errors

  • 400 — INVALID_ID
  • 404 — PACKAGE_NOT_FOUND
  • 401 — Not authenticated
  • 403 — Caller’s role is not in the allowed roles

Download an evidence package

GET /policies/api/v1/compliance/evidence-packages/{id}/download

Streams the complete evidence archive as an attachment (evidence--.tar.gz|tar|zip), with Content-Length and an X-Content-SHA256 header for integrity checking. Only complete packages can be downloaded.

Roles: admin, platform, security, devops

Path parameters

NameTypeDescription
idstringPackage ID (UUID)

Response 200 (archive media type of the package (e.g. application/gzip))

Binary archive; headers Content-Disposition, Content-Length, X-Content-SHA256

Errors

  • 400 — INVALID_ID
  • 404 — PACKAGE_NOT_FOUND
  • 409 — PACKAGE_NOT_COMPLETE, PACKAGE_FAILED or PACKAGE_DELETED
  • 401 — Not authenticated
  • 403 — Caller’s role is not in the allowed roles

Upload an evidence package part

PUT /policies/api/v1/compliance/evidence-packages/{id}/parts/{index}

Uploads one part of a declared package as raw bytes. Every part except the last must be exactly partSizeBytes. When the last missing part arrives the archive is verified against its SHA-256 and the package becomes complete (or failed). Re-uploading a part is safe.

Roles: admin, security

Path parameters

NameTypeDescription
idstringPackage ID (UUID)
indexintegerZero-based part index (0 to partCount-1)

Request body (application/octet-stream)

Response 200 (application/json)

EvidencePackageDto

FieldTypeDescription
idstring (uuid)Package ID
publishIdstring (uuid)Idempotency key
targetIdstring (uuid)Cluster ID
targetNamestringCluster name
standardstring—
reportIdstring (uuid)Linked snapshot report, if any
publisherstring—
publisherVersionstring—
collectedAtstring (date-time)—
contentTypestringArchive media type
sha256stringHex SHA-256 of the archive
sizeBytesinteger—
partSizeBytesintegerRequired size of every part except the last
partCountinteger—
receivedPartsinteger[]Part indexes already stored (for resuming)
statusstringuploading | complete | failed | deleting
errorMessagestringSet when failed
metadataobjectProducer metadata
createdBystring—
createdAtstring (date-time)—
completedAtstring (date-time)—
duplicatebooleanOnly on the declare response

Errors

  • 400 — INVALID_ID, INVALID_PART_INDEX, or INVALID_PART_SIZE
  • 404 — PACKAGE_NOT_FOUND
  • 409 — PACKAGE_FAILED or PACKAGE_DELETED
  • 401 — Not authenticated
  • 403 — Caller’s role is not in the allowed roles

Example

curl -X PUT -H 'Content-Type: application/octet-stream' --data-binary @part0.bin .../compliance/evidence-packages/{id}/parts/0