Artifact Store API: schemas

The request and response bodies of the operations in this API.

AddArtifactVersionDto

PropertyTypeRequiredDescription
hashstringyes
pointerstringyes
schemaVersionstringyes
sizenumberyes

AppendArtifactEntryDto

PropertyTypeRequiredDescription
base64stringnoInline payload bytes (base64-encoded). Mutually exclusive with blobId. Capped at 16 MB; for larger payloads upload to /blobs first and pass blobId.
blobIdstringnoReference to an existing Blob row (content-addressed). Mutually exclusive with base64.
contentTypestringnoMIME type. Falls back to application/octet-stream when omitted.
filenamestringyesFile name as it should be remembered for this entry.
metadataobjectnoProducer-defined metadata stamped on the entry. IMAP entries typically carry { uid, messageId, partId } for correlation.

ArtifactDerivationInputDto

PropertyTypeRequiredDescription
inputHashstringnoContent hash at consumption time. Distinguishes "the input moved" from "the input was rewritten identically", which a version alone cannot.
inputRefstringyesKernel XemaObjectRef of the input. PARSED, not merely stored: a free (kind, id) pair lets two producers spell one input two ways and silently split the reverse index.
inputVersionstringnoThe input's version AT CONSUMPTION TIME. Omit only when the input's KIND has no version; the store substitutes a sentinel so the uniqueness constraint still holds.
roleone of "CONTEXT", "DEPENDENCY", "SOURCE"yesWhat the input was to this output. CONTEXT is the assembled-context receipt — what the producing invocation was TOLD.

ArtifactEntryResponseDto

PropertyTypeRequiredDescription
blobIdstringyesReference to the content-addressed Blob holding the bytes.
entryIdstringyes
sizenumberyesSize in bytes.

ArtifactEntryResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactEntryResponseDtoyes

ArtifactEntryScanState

not_scanned means no scanner is armed in this deployment — it is NOT a clean verdict.

Type: one of "not_scanned", "clean", "rejected"

ArtifactEntryUploadState

pending bytes are NOT readable. ready means size, digest and signature all checked out.

Type: one of "pending", "ready", "rejected", "expired"

ArtifactErasureOutcome

erased — the artifact existed in the caller's org + project scope and is gone. already_absent — nothing with this id is in that scope (already erased, or never there); the uploaded-object prefix was still swept, so a retry completes an interrupted erasure.

Type: one of "erased", "already_absent"

ArtifactErasureResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
blobsDeletednumberyesBlob rows physically removed — this artifact was their last owner.
blobsRetainedExternallyClaimednumberyesBlob rows KEPT because an external POST /blobs claimant (a workflow snapshot, a Temporal payload spill) holds byte-identical content.
blobsRetainedSharednumberyesBlob rows KEPT because another live artifact of the same org references byte-identical content. That content is still that other artifact's; no path from the erased artifact reaches it any more.
outcomeArtifactErasureOutcomeyeserased — the artifact existed in the caller's org + project scope and is gone. already_absent — nothing with this id is in that scope (already erased, or never there); the uploaded-object prefix was still swept, so a retry completes an interrupted erasure.
uploadedObjectsDeletednumberyesUploaded objects removed from object storage.
versionsDeletednumberyesVersions deleted with the artifact (inline payloads go with them).

ArtifactErasureResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactErasureResponseDtoyes

ArtifactFileDto

PropertyTypeRequiredDescription
contentKindDeliverableContentKindyesHow the file content is read.
pathstringyesWorkspace-relative path of the deliverable file this version is. Relative, no ./.. segment, [a-zA-Z0-9._-/] only.

ArtifactLinkResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
createdAtstringyes
idstringyes
refIdstringyes
refTypestringyes

ArtifactLinkResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactLinkResponseDtoyes

ArtifactResponseDto

PropertyTypeRequiredDescription
createdAtstringyes
createdBystringyes
currentVersionIdstring or nullnoTHE served version. Read this to answer "what does this artifact resolve to?" — never versions[0], and never the highest versions[].version. Those agree until somebody calls POST /artifacts/:id/rollback, after which the highest version is precisely the content that was taken OUT of service. Null means the artifact serves nothing yet: POST /artifacts creates the row and the first version arrives in a follow-up emit.
idstringyes
latestTitlestringyesDenormalized cache of the SERVED version's title — the title of the version named by currentVersionId. Resynced at every emit AND at every rollback. The authoritative per-version title lives on versions[].title. NOTE the field NAME is historical: it caches the served title, not max(version)'s, and after a rollback those are different versions. Renaming it to currentTitle is a coordinated wire change, not a schema edit.
linksarray of ArtifactLinkResponseDtono
orgIdstringyes
pipelineRunIdstringnoPipeline run ID this artifact belongs to
projectIdstringyes
typestringyes
versionsarray of ArtifactVersionResponseDtono

ArtifactResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactResponseDtoyes

ArtifactResponseDtoPaginatedEnvelope

PropertyTypeRequiredDescription
dataarray of ArtifactResponseDtoyes
paginationPaginationMetayes

ArtifactRollbackAuditResponseDto

PropertyTypeRequiredDescription
actorIdstringyesWho performed the rollback.
artifactIdstring or nullnoThe artifact this rollback was performed on. NULL once that artifact has been swept, cleaned up or erased — the audit row deliberately outlives its subject, so the denormalized fields below are what stay readable.
artifactNaturalKeystring or nullnoThe artifact's natural key at rollback time. Null when it carried none.
artifactTypestringyesThe artifact's type at rollback time.
correlationIdstringyes
createdAtstringyes
fromVersionnumberyes
fromVersionIdstringyes
idstringyes
orgIdstringyes
projectIdstringyes
reasonstring or nullnoOperator note supplied on the request. Never parsed.
toVersionnumberyes
toVersionIdstringyes

ArtifactRollbackAuditResponseDtoDataArrayEnvelope

PropertyTypeRequiredDescription
dataarray of ArtifactRollbackAuditResponseDtoyes

ArtifactRollbackResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
auditIdstringyesId of the durable audit row this rollback wrote, inside the same transaction as the pointer swap.
fromVersionnumberyesNumber of the version that was being served.
fromVersionIdstringyesId of the version that was being served.
latestTitlestringyesThe artifact's title after the flip — resynced to the restored version. When that version predates per-version titles, the previous title is kept (there is nothing to restore and the column is NOT NULL).
rolledBackAtstringyesWhen the swap committed (ISO-8601).
toVersionnumberyesNumber of the version now being served.
toVersionIdstringyesId of the version now being served.

ArtifactRollbackResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactRollbackResponseDtoyes

ArtifactTypeBiomeSourceDto

PropertyTypeRequiredDescription
biomeIdstringyes
installationIdstring or nullno
kindone of "biome"yes
originone of "distribution", "org_installation"yes
ownerOrgIdstring or nullno
releaseIdstringyes

ArtifactTypeOrgSourceDto

PropertyTypeRequiredDescription
kindone of "org"yes
orgIdstringyes

ArtifactTypePlatformSourceDto

PropertyTypeRequiredDescription
kindone of "platform"yes

ArtifactTypeResponseDto

PropertyTypeRequiredDescription
createdAtstring or nullnoISO timestamp for org rows; null for platform/biome entries.
descriptionstring or nullno
idstring or nullnoRow id for org rows; null for platform/biome entries.
schemaVersionsarray of stringyesAccepted schemaVersions, or ['*'] for wildcard.
sourceArtifactTypePlatformSourceDto or ArtifactTypeBiomeSourceDto or ArtifactTypeOrgSourceDtoyes
typestringyes

ArtifactTypeResponseDtoDataArrayEnvelope

PropertyTypeRequiredDescription
dataarray of ArtifactTypeResponseDtoyes

ArtifactTypeResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactTypeResponseDtoyes

ArtifactUploadDownloadUrlResponseDto

PropertyTypeRequiredDescription
contentTypestringyes
downloadUrlstringyesPresigned URL to GET the bytes from. Unsigned-bearer and short-lived — mint one per request rather than storing it.
expiresAtstringyes
filenamestringyes
methodstringyes

ArtifactUploadDownloadUrlResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactUploadDownloadUrlResponseDtoyes

ArtifactUploadEntryResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
confirmedAtstringnoWhen confirmation succeeded.
contentTypestringyesThe authoritative media type. Once confirmed this is the SNIFFED value, not what the client declared.
declaredContentTypestringnoWhat the client claimed, kept for provenance.
entryIdstringyes
filenamestringyes
scanStateArtifactEntryScanStateyesnot_scanned means no scanner is armed in this deployment — it is NOT a clean verdict.
scannerIdstringnoWhich scanner produced scanState. Absent while not scanned.
sha256stringnoServer-computed SHA-256 over the whole stored object. Never accepted from the client. Absent until confirmation succeeds.
sizenumberyesSize in bytes.
uploadStateArtifactEntryUploadStateyespending bytes are NOT readable. ready means size, digest and signature all checked out.
versionIdstringyes

ArtifactUploadEntryResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactUploadEntryResponseDtoyes

ArtifactUploadIntentResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
entryIdstringyesConfirm this entry with POST /artifacts/{artifactId}/entries/{entryId}/confirm once the PUT completes.
expiresAtstringyesWhen BOTH the URL and the intent behind it stop being usable. After this the entry can only be re-created, not confirmed.
methodstringyesHTTP method the presigned URL is signed for.
requiredHeadersmap of stringyesHeaders the client MUST send VERBATIM. The signature covers them — adding, dropping or "tidying" one produces a signature mismatch, not a helpful correction.
uploadUrlstringyesPresigned URL to PUT the bytes to. Short-lived and unsigned-bearer: anyone holding it can write until it expires, so do not log it.
versionIdstringyes

ArtifactUploadIntentResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactUploadIntentResponseDtoyes

ArtifactVersionResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
createdAtstringyes
fileArtifactFileDto or nullnoThe deliverable file this version is ({ path, contentKind }), as recorded by the producer at emit. Null when the version is not a recorded file.
hashstringyes
idstringyes
outputNamestring or nullnoDeclared output name on the producing activity (the name field of its OUTPUT_DECLARATIONS entry — e.g. response, structuredOutput, deliverables). Null for direct xema/emit-artifact calls that don’t carry a declaration name. Used by the Run Detail "Outputs" panel to group artifact versions by job + output.
pointerstringyes
pointsOfAttentionarray of PointOfAttentionDto or nullnoGeneric per-version "points of attention" the producer flagged at emit time ({ label, detail, severity }). Strictly per-version — read this from the specific version, never from the artifact head. Null when the producer supplied none.
producerJobRunIdstring or nullnoSynthetic ${runId}:${jobKey}:${matrixIndex} job-run id of the activity that emitted this version. Pairs with producerRunId for full lineage.
producerRunIdstring or nullnoWorkflow run that emitted this specific version. v1 mirrors Artifact.pipelineRunId; v2+ may differ when the revision was produced by a different run. Null on legacy rows.
schemaVersionstringyes
sizenumberyes
titlestring or nullnoTitle at the time this version was emitted. Lets the UI show the producer-supplied title for any prior version, even after a later revision renames the artifact. The parent Artifact.latestTitle is the denormalized cache of the latest version’s title.
versionnumberyes

ArtifactVersionResponseDtoDataArrayEnvelope

PropertyTypeRequiredDescription
dataarray of ArtifactVersionResponseDtoyes

ArtifactVersionResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataArtifactVersionResponseDtoyes

ArtifactVersioningMode

How the service should treat a re-emit on the same naturalKey. append (default for approval-gated deliverables) bumps the version; new always creates a fresh artifact row (per-attempt records); replace overwrites v1 in place (ephemeral side-effects). The store enforces the semantics — producers cannot pick the wrong one by forgetting a flag.

Type: one of "append", "new", "replace"

BlobResponseDto

PropertyTypeRequiredDescription
contentTypestringyesContent-Type recorded at upload time. Returned verbatim on GET; the server never sniffs the body.
createdAtstringyesWhen the blob row was created.
sha256stringyesServer-computed SHA-256 of the uploaded bytes (lowercase hex).
sizeBytesnumberyesLength of the uploaded body in bytes.

BlobResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataBlobResponseDtoyes

CreateArtifactDto

PropertyTypeRequiredDescription
pipelineRunIdstringnoPipeline run ID to scope this artifact to
titlestringyes
typestring (38 values)yes

CreateArtifactEntryUploadIntentDto

PropertyTypeRequiredDescription
declaredContentTypestringyesThe media type the client says these bytes are. Checked against the deployment's upload policy at mint time, and PROVEN against the stored bytes' signature at confirmation — a mismatch deletes the object and rejects the entry.
filenamestringyesFile name to remember for this entry. Recorded verbatim and used as the download filename; never used to build the storage key.
metadataobjectnoProducer-defined metadata stamped on the entry. Not interpreted by the platform.
sizenumberyesExact byte count the client will store. Judged against the per-kind cap now, and against the stored object at confirmation.

CreateArtifactTypeDto

PropertyTypeRequiredDescription
descriptionstring or nullnoOptional human-readable note about what payloads this type carries.
schemaVersionsarray of stringyesClosed set of accepted schemaVersion values. Use ['*'] for wildcard (any string).
typestringyesType id. Lowercase letters, digits, underscores, hyphens. Must start with a letter.

CreateArtifactUploadIntentDto

PropertyTypeRequiredDescription
classificationDataClassificationnoRetention classification. Drives the artifact-level expiresAt exactly as it does on POST /artifacts/emit.
declaredContentTypestringyesThe media type the client says these bytes are. Checked against the deployment's upload policy at mint time, and PROVEN against the stored bytes' signature at confirmation — a mismatch deletes the object and rejects the entry.
filenamestringyesFile name to remember for this entry. Recorded verbatim and used as the download filename; never used to build the storage key.
metadataobjectnoProducer-defined metadata stamped on the entry. Not interpreted by the platform.
pipelineRunIdstringnoWorkflow run that produced this upload, when there is one. Uploads made by a person normally have none.
sizenumberyesExact byte count the client will store. Judged against the per-kind cap now, and against the stored object at confirmation.
titlestringnoHuman title for the artifact. Defaults to filename when omitted.
typestringnoRegistered artifact type. Defaults to the platform uploaded_file type. An org or biome that has registered its own type may name it here; an unregistered type is refused by the artifact-type registry, not silently accepted.

CreateEphemeralArchiveDto

PropertyTypeRequiredDescription
metadataobjectnoFree-form producer metadata captured on the v1 inlinePayload. Use to record what kind of scan / fetch produced the archive — surfaces in audit but is not interpreted by the platform.
pipelineRunIdstringnoWorkflow run that owns the archive. Required when the request context does NOT already carry pipelineRunId (e.g. service-to-service mints). Cleanup is keyed on this value.
titlestringyesStable producer-defined slug for the archive. Mostly cosmetic — appears in audit + the latestTitle.
ttlSecondsnumbernoTTL in seconds. Defaults to 86400 (24h) when omitted. The sweeper deletes rows past expiresAt regardless of run state — fail-safe for lost terminal events.

DataClassification

Data-classification of this artifact (value-identical to the platform DataClassification set). Drives retention: when present and the deployment maps the class to a non-null TTL, the store derives expiresAt = createdAt + TTL UNLESS the caller supplied an explicit expiresAt (explicit wins). Omit for the unchanged no-auto-expiry behavior.

Type: one of "public", "internal", "confidential", "secret", "regulated"

DeliverableContentKind

How the file content is read.

Type: one of "json", "markdown", "text"

EmitArtifactDto

PropertyTypeRequiredDescription
classificationDataClassificationnoData-classification of this artifact (value-identical to the platform DataClassification set). Drives retention: when present and the deployment maps the class to a non-null TTL, the store derives expiresAt = createdAt + TTL UNLESS the caller supplied an explicit expiresAt (explicit wins). Omit for the unchanged no-auto-expiry behavior.
derivedFromarray of ArtifactDerivationInputDtonoWhat this version was produced FROM. Recorded in the derivation ledger in the SAME transaction-scoped call as the emit, so a version can never exist with a silently empty lineage. Absent means "this producer declared no inputs" — never "it had none", which is a different fact and is not one this contract can distinguish.
encryptAtRestbooleannoExplicit opt-in to ENCRYPTION-AT-REST for this version's payload. When omitted/false (default) the payload is stored exactly as before (inline JSON or plaintext blob) — existing behavior is 100% unchanged. When true, the payload is sealed into a per-org AES-256-GCM envelope (per-version content key wrapped by the org data-key) and stored as ciphertext; authorized same-org reads decrypt transparently. The request FAILS FAST (503) if the deployment has no encryption key configured — there is no plaintext fallback for an encryption request.
expiresAtstring (date-time)noExplicit fail-safe expiry instant (ISO-8601). When set it OVERRIDES any retention TTL derived from classification — explicit wins. When omitted, retention falls back to the classification→TTL map (or no expiry when neither is present).
fileArtifactFileDtonoThe deliverable file this version is: { path, contentKind }, both required inside it. Recorded on the version as a fact the producer holds, never derived from title or outputName. Omit when the version is not a file. Like title and outputName it is not part of the payload hash, so an idempotent re-emit keeps the first-written value.
labelsmap of stringnoFree-form labels attached to the artifact for downstream queries (e.g. {"source":"agent"}).
naturalKeystringnoStable producer identity for APPEND and REPLACE modes. REQUIRED when versioningMode is append or replace; ignored (stored as null) when new.
outputNamestringnoDeclared output name on the producing activity (the name field of its OUTPUT_DECLARATIONS entry — e.g. response, structuredOutput, deliverables). Set by finalizeOutputs during the unified-outputs promotion path so the Run Detail "Outputs" panel can group artifact versions by job + output name without a scan. Omit for direct xema/emit-artifact calls that don’t carry a declaration name.
payloadobjectyesJSON-serializable payload for version content. Artifact-store chooses inline vs blob-backed storage by size; callers always use the same endpoint.
pipelineRunIdstringnoPipeline run id this artifact belongs to. Inherited from X-Pipeline-Run-Id request context when omitted.
pointsOfAttentionarray of PointOfAttentionDtonoGeneric, domain-agnostic "points of attention" for THIS version — a closed-shape array of { label, detail, severity } (value-identical to the kernel PointOfAttention contract). A producer flags the salient things a reader should notice (an assumption, a gap, a risk) without the artifact schema growing a domain-specific field for each. Strictly per-version metadata (like title) — never denormalized onto the artifact head. Omit for none; the store persists NULL (absent), never a silent default. An explicit empty array is stored as-is.
producerJobRunIdstringnoSynthetic ${runId}:${jobKey}:${matrixIndex} job-run id of the activity that emitted this version. Recorded on the ArtifactVersion row (producer_job_run_id) for revision lineage. Inherits pipelineRunId separately for the run-level pointer.
schemaVersionstringnoSchema version of the payload. Defaults to 1.0.0 when omitted; producers SHOULD declare it explicitly so consumers can validate.
stageKeystringnoPhase key, when the artifact is scoped to a particular workflow phase.
titlestringyesHuman-readable title.
typestringyesArtifact type (a.k.a. kind). Must be registered in the schema-version registry.
versioningModeArtifactVersioningModeyesHow the service should treat a re-emit on the same naturalKey. append (default for approval-gated deliverables) bumps the version; new always creates a fresh artifact row (per-attempt records); replace overwrites v1 in place (ephemeral side-effects). The store enforces the semantics — producers cannot pick the wrong one by forgetting a flag.

EphemeralArchiveResponseDto

PropertyTypeRequiredDescription
artifactIdstringyes
expiresAtstringyesISO-8601 expiry timestamp (now + ttlSeconds).
versionIdstringyes

EphemeralArchiveResponseDtoDataEnvelope

PropertyTypeRequiredDescription
dataEphemeralArchiveResponseDtoyes

LinkArtifactDto

PropertyTypeRequiredDescription
refIdstringyes
refTypeone of "phase_gate", "pull_request", "thread", "backlog_item"yes

PaginationMeta

PropertyTypeRequiredDescription
hasMorebooleanno
limitnumberno
nextCursorstring or nullno
pagenumberno
previousCursorstring or nullno
totalnumberno
totalPagesnumberno

PointOfAttentionDto

PropertyTypeRequiredDescription
detailstringyesLonger human-readable explanation (≤ 2000 chars).
labelstringyesShort headline for the point (≤ 200 chars).
severityPointOfAttentionSeverityyesHow much scrutiny this point warrants. Closed set — a consumer renders each value with a fixed badge/colour.

PointOfAttentionSeverity

How much scrutiny this point warrants. Closed set — a consumer renders each value with a fixed badge/colour.

Type: one of "info", "warning", "critical"

ProblemActionableBy

Who can act on this refusal: user (correct the input, sign in), org-admin (an administrator of the organisation), platform (the operators of this installation), none (nobody — it cannot succeed). ABSENT when not known; never guessed.

Type: one of "user", "org-admin", "platform", "none"

ProblemDetailsDto

RFC 9457 problem document. The declared members are the reserved core; extension members are TOP-LEVEL and OPEN, owned by the refusing plane.

PropertyTypeRequiredDescription
actionableByProblemActionableBynoWho can act on this refusal: user (correct the input, sign in), org-admin (an administrator of the organisation), platform (the operators of this installation), none (nobody — it cannot succeed). ABSENT when not known; never guessed.
codestringyesSCREAMING_SNAKE_CASE. The machine-branchable refusal, and the value a policy rule, a retry predicate and a UI branch all name.
detailstringnoHuman-readable and specific to THIS occurrence.
errorsarray of ProblemFieldIssueDtonoField-level issues, when the refusal is about the request body.
instancestringnoURI reference identifying the occurrence — a request path, a run, a row.
paramsmap of string or number or booleannoSafe i18n interpolation values for the message keyed by code — typed and allowlisted per code by its declaration. Never server-authored copy, never internal diagnostics.
retryProblemRetrynoWhat a retry can achieve: transient (later, unchanged), after-change (only after someone changes something), never (a defect until a fixed version ships). ABSENT when not known.
statusnumberyesThe HTTP status code, repeated in the body so a logged document is self-contained.
titlestringyesShort, human-readable, and STABLE for a given type. Never per-occurrence — that is detail.
traceIdstringnoW3C trace-context trace-id, present when the caller sent a traceparent. Omitted rather than invented when it did not.
typestringyesAbsolute URI identifying the refusal TYPE. Derived one-to-one from code, so a caller may branch on either and can never be told two different things. Never about:blank.

ProblemFieldIssueDto

PropertyTypeRequiredDescription
codestringnoSCREAMING_SNAKE_CASE code of THIS issue, for a frontend i18n key. Present when the issue was minted by a declared problem.
detailstringyesProse for logs and developers. A frontend localises from code + params instead.
paramsmap of string or number or booleannoSafe i18n interpolation values for this issue's code.
pointerstringyesRFC 6901 JSON Pointer into the request body. Root is "/".

ProblemRetry

What a retry can achieve: transient (later, unchanged), after-change (only after someone changes something), never (a defect until a fixed version ships). ABSENT when not known.

Type: one of "transient", "after-change", "never"

RollbackArtifactDto

PropertyTypeRequiredDescription
reasonstringnoFree-form operator note recorded on the durable audit row. Never parsed, never interpreted — it exists so the audit trail can answer "why" as well as "who and when".
targetVersionnumberyesThe version number to serve again. Must be an existing version of this artifact, and must not already be the served one — rolling back to the version already in service is refused rather than treated as a no-op, because reporting success would report a change nobody made.