remora/docs/api/openapi.yaml

1889 lines
58 KiB
YAML
Raw Normal View History

2026-07-13 14:59:50 +09:00
openapi: 3.2.0
$self: https://remora.invalid/api/openapi.yaml
2026-07-13 14:59:50 +09:00
jsonSchemaDialect: https://spec.openapis.org/oas/3.2/dialect/2025-09-17
info:
title: Remora API
version: 1.0.0
description: Mutable implementation contract for public job management and service-authenticated worker operations.
2026-07-13 14:59:50 +09:00
servers:
- url: /api
security:
- oidc: []
paths:
/v1/jobs:
post:
operationId: submitJob
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/JobSubmission'
responses:
'202':
description: Accepted, or the original accepted response for the same key and fingerprint.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
'409':
$ref: '#/components/responses/IdempotencyConflict'
default:
$ref: '#/components/responses/Error'
get:
operationId: listJobs
parameters:
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Limit'
- name: include_deleted
in: query
schema:
type: boolean
default: false
responses:
'200':
description: Authorized keyset page bound to one snapshot and filter.
content:
application/json:
schema:
$ref: '#/components/schemas/JobPage'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}:
parameters:
- $ref: '#/components/parameters/JobId'
get:
operationId: getJob
responses:
'200':
description: Current authorized full job or minimal hard-deletion tombstone projection.
2026-07-13 14:59:50 +09:00
content:
application/json:
schema:
$ref: '#/components/schemas/JobResource'
2026-07-13 14:59:50 +09:00
'404':
$ref: '#/components/responses/NotFound'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/result:
parameters:
- $ref: '#/components/parameters/JobId'
get:
operationId: getJobResult
responses:
'200':
description: Visible committed manifest-rooted result.
content:
application/json:
schema:
$ref: '#/components/schemas/ResultDescriptor'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/result/members:
parameters:
- $ref: '#/components/parameters/JobId'
get:
operationId: listJobResultMembers
description: Enumerates members only from the visible committed result.
parameters:
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Limit'
responses:
'200':
description: Authorized page of committed result members ordered by normalized path.
content:
application/json:
schema:
$ref: '#/components/schemas/ResultMemberPage'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/result/members/{member_id}/content:
parameters:
- $ref: '#/components/parameters/JobId'
- name: member_id
in: path
required: true
schema:
$ref: '#/components/schemas/OpaqueId'
get:
operationId: accessJobResultMember
description: Revalidates current authorization and redirects to a time-limited URL for the exact committed member identity.
responses:
'307':
description: Temporary redirect to the exact committed member. The URL is sensitive and must not be logged or cached.
headers:
Location:
description: Time-limited member URL.
required: true
schema:
type: string
format: uri
Cache-Control:
description: Prevents caching of the credential-bearing redirect response.
required: true
schema:
const: no-store
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
2026-07-13 14:59:50 +09:00
/v1/jobs/{job_id}/cancel:
parameters:
- $ref: '#/components/parameters/JobId'
post:
operationId: cancelJob
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
responses:
'202':
description: Cancellation intent accepted or prior response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
2026-07-13 14:59:50 +09:00
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/soft-delete:
parameters:
- $ref: '#/components/parameters/JobId'
post:
operationId: softDeleteJob
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
responses:
'200':
description: Job hidden, or prior response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
2026-07-13 14:59:50 +09:00
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/restore:
parameters:
- $ref: '#/components/parameters/JobId'
post:
operationId: restoreJob
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
responses:
'200':
description: Soft-deleted job restored, or prior response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
2026-07-13 14:59:50 +09:00
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/hard-delete:
parameters:
- $ref: '#/components/parameters/JobId'
post:
operationId: hardDeleteJob
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
responses:
'202':
description: Durable deletion operation created or replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
2026-07-13 14:59:50 +09:00
content:
application/json:
schema:
$ref: '#/components/schemas/DeletionOperation'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/revoke:
parameters:
- $ref: '#/components/parameters/JobId'
post:
operationId: revokeJobExecutionGrant
description: Administrator-only revocation of an accepted execution grant.
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
responses:
'202':
description: Durable cancellation intent recorded or prior response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
default:
$ref: '#/components/responses/Error'
/v1/jobs/{job_id}/attempts:
parameters:
- $ref: '#/components/parameters/JobId'
get:
operationId: listJobAttempts
parameters:
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Limit'
responses:
'200':
description: Durable attempt history ordered by fencing token.
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptPage'
'404':
$ref: '#/components/responses/NotFound'
default:
$ref: '#/components/responses/Error'
/v1/source-credentials:
post:
operationId: createSourceCredential
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredentialCreate'
responses:
'201':
description: Credential metadata and first immutable version created, or the original response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredential'
'409':
$ref: '#/components/responses/IdempotencyConflict'
default:
$ref: '#/components/responses/Error'
get:
operationId: listSourceCredentials
parameters:
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Limit'
responses:
'200':
description: Authorized credential metadata page without secret material.
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredentialPage'
default:
$ref: '#/components/responses/Error'
/v1/source-credentials/{credential_id}:
parameters:
- $ref: '#/components/parameters/CredentialId'
get:
operationId: getSourceCredential
responses:
'200':
description: Authorized credential metadata without secret material.
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredential'
'404':
$ref: '#/components/responses/NotFound'
default:
$ref: '#/components/responses/Error'
/v1/source-credentials/{credential_id}/versions:
parameters:
- $ref: '#/components/parameters/CredentialId'
post:
operationId: rotateSourceCredential
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredentialRotate'
responses:
'201':
description: New immutable version created and selected for future grants, or the original response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredential'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/IdempotencyConflict'
default:
$ref: '#/components/responses/Error'
/v1/source-credentials/{credential_id}/revoke:
parameters:
- $ref: '#/components/parameters/CredentialId'
post:
operationId: revokeSourceCredential
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
responses:
'200':
description: Credential revoked for future grants, or the original response replayed.
headers:
Idempotency-Expires-At:
$ref: '#/components/headers/IdempotencyExpiresAt'
content:
application/json:
schema:
$ref: '#/components/schemas/SourceCredential'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/IdempotencyConflict'
default:
$ref: '#/components/responses/Error'
2026-07-13 14:59:50 +09:00
/v1/deletions/{operation_id}:
parameters:
- name: operation_id
in: path
required: true
schema:
$ref: '#/components/schemas/OpaqueId'
get:
operationId: getDeletionOperation
responses:
'200':
description: Current deletion operation.
content:
application/json:
schema:
$ref: '#/components/schemas/DeletionOperation'
'404':
$ref: '#/components/responses/NotFound'
default:
$ref: '#/components/responses/Error'
/v1/events:
get:
operationId: connectEvents
parameters:
- name: cursor
in: query
description: Opaque authorization-bound replay cursor from an HTTP snapshot or prior frame.
schema:
type: string
minLength: 16
maxLength: 2048
responses:
'101':
description: WebSocket frames conform to events.schema.json. An absent, invalid, expired, or unauthorized cursor yields resync_required.
default:
$ref: '#/components/responses/Error'
/internal/v1/jobs/{job_id}/claim:
parameters:
- $ref: '#/components/parameters/JobId'
post:
operationId: claimJob
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ClaimRequest'
responses:
'200':
description: Reserved and durably authorized attempt, or replay of the same claim operation. The authority is non-executable until activateAttempt succeeds.
2026-07-13 14:59:50 +09:00
content:
application/json:
schema:
$ref: '#/components/schemas/ClaimResponse'
'409':
$ref: '#/components/responses/IdempotencyConflict'
2026-07-13 14:59:50 +09:00
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/renew:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: renewAttempt
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
2026-07-13 18:23:03 +09:00
$ref: '#/components/schemas/AttemptRenewRequest'
2026-07-13 14:59:50 +09:00
responses:
'200':
description: Existing exact live coordination lease renewed or prior response replayed; durable authority is unchanged.
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseProjection'
2026-07-13 14:59:50 +09:00
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/activate:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: activateAttempt
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptActivateRequest'
responses:
'200':
description: Exact authority activated, or a prior successful activation replayed while its lease and durable executing tuple still agree.
content:
application/json:
schema:
$ref: '#/components/schemas/ActivationResponse'
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/stop:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: stopAttempt
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptStopRequest'
responses:
'204':
description: The exact attempt has cooperatively stopped, or no further stop action is required.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/staging/write-intent:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: registerAttemptStagingWriteIntent
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptStagingWriteIntentRequest'
responses:
'204':
description: Exact staging key intent durably registered before target I/O.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/staging/object:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: registerAttemptStagingObject
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptStagingObjectRequest'
responses:
'204':
description: Exact completed staging object identity durably registered.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/staging/multipart:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: registerAttemptStagingMultipart
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptStagingMultipartRequest'
responses:
'204':
description: Exact staging multipart identity durably registered.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/resolved-source:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: pinAttemptResolvedSource
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptResolvedSourceRequest'
responses:
'204':
description: Resolved source pinned once, or the exact operation replayed.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/checkpoint:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: persistAttemptCheckpoint
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptCheckpointRequest'
responses:
'204':
description: Validated checkpoint persisted, or the exact operation replayed.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
2026-07-13 14:59:50 +09:00
/internal/v1/attempts/{attempt_id}/progress:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: reportAttemptProgress
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptProgressRequest'
responses:
'204':
description: Current progress accepted or duplicate ignored.
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
/internal/v1/attempts/{attempt_id}/outcome:
parameters:
- $ref: '#/components/parameters/AttemptId'
post:
operationId: reportAttemptOutcome
security:
- serviceAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttemptOutcomeRequest'
responses:
'200':
description: Durable outcome projection or replay of the same operation.
content:
application/json:
schema:
2026-07-17 09:16:46 +09:00
$ref: '#/components/schemas/JobPhaseProjection'
2026-07-13 14:59:50 +09:00
'409':
$ref: '#/components/responses/PreconditionFailed'
default:
$ref: '#/components/responses/Error'
components:
securitySchemes:
oidc:
type: openIdConnect
openIdConnectUrl: https://identity.invalid/.well-known/openid-configuration
serviceAuth:
type: mutualTLS
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
description: Subject- and operation-scoped key retained for at least 24 hours.
schema:
type: string
pattern: '^[A-Za-z0-9._~-]{16,128}$'
Cursor:
name: cursor
in: query
schema:
type: string
minLength: 16
maxLength: 2048
Limit:
name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 200
default: 50
JobId:
name: job_id
in: path
required: true
schema:
$ref: '#/components/schemas/OpaqueId'
AttemptId:
name: attempt_id
in: path
required: true
schema:
$ref: '#/components/schemas/OpaqueId'
CredentialId:
name: credential_id
in: path
required: true
schema:
$ref: '#/components/schemas/CredentialId'
2026-07-13 14:59:50 +09:00
headers:
IdempotencyExpiresAt:
description: Earliest time at which the server may forget this key.
schema:
type: string
format: date-time
responses:
Error:
description: Structured error with user-safe detail only.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ApiError'
NotFound:
description: Missing or unauthorized resource; the response does not distinguish them.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ApiError'
IdempotencyConflict:
description: The key exists with a different canonical request fingerprint.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ApiError'
PreconditionFailed:
description: Durable authority, fence, phase, or lifecycle precondition failed.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ApiError'
schemas:
OpaqueId:
type: string
pattern: '^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$'
PrincipalId:
description: Internal stable principal identifier mapped to one exact OIDC issuer and subject pair.
allOf:
- $ref: '#/components/schemas/OpaqueId'
CredentialId:
description: Owner-authorized source credential registry identifier.
allOf:
- $ref: '#/components/schemas/OpaqueId'
CredentialVersionId:
description: Immutable application credential-version identifier; backend secret-store coordinates are never exposed.
allOf:
- $ref: '#/components/schemas/OpaqueId'
2026-07-13 14:59:50 +09:00
Target:
type: object
additionalProperties: false
required: [store, bucket, prefix]
properties:
store:
type: string
minLength: 1
maxLength: 128
bucket:
type: string
pattern: '^(?!.*\.\.)[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$'
2026-07-13 14:59:50 +09:00
prefix:
type: string
maxLength: 1024
description: NFC-normalized target segments; semantic validation follows architecture.md.
TargetOverride:
type: object
additionalProperties: false
minProperties: 1
properties:
bucket:
type: string
pattern: '^(?!.*\.\.)[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$'
prefix:
type: string
maxLength: 1024
description: NFC-normalized target segments; semantic validation follows architecture.md.
StagingTarget:
type: object
additionalProperties: false
required: [store, bucket, prefix]
properties:
store:
type: string
minLength: 1
maxLength: 128
bucket:
type: string
pattern: '^(?!.*\.\.)[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$'
prefix:
type: string
minLength: 1
maxLength: 1024
description: Exact attempt-scoped internal prefix selected by the service.
ResultPath:
type: string
minLength: 1
maxLength: 4096
description: NFC-normalized relative POSIX path validated under architecture.md.
HttpSourceSubmission:
2026-07-13 14:59:50 +09:00
type: object
additionalProperties: false
required: [kind, url, result_path]
2026-07-13 14:59:50 +09:00
properties:
kind:
const: http
url:
type: string
format: uri
maxLength: 8192
writeOnly: true
description: Sensitive execution input. Public projections expose only display_url.
result_path:
$ref: '#/components/schemas/ResultPath'
credential_id:
$ref: '#/components/schemas/CredentialId'
ObjectStoreSourceSubmission:
2026-07-13 14:59:50 +09:00
type: object
additionalProperties: false
required: [kind, store, bucket, key, result_path]
2026-07-13 14:59:50 +09:00
properties:
kind:
const: object_store
store:
type: string
minLength: 1
maxLength: 128
bucket:
type: string
minLength: 3
maxLength: 63
key:
type: string
minLength: 1
maxLength: 4096
version_id:
type: string
maxLength: 1024
result_path:
$ref: '#/components/schemas/ResultPath'
credential_id:
$ref: '#/components/schemas/CredentialId'
HuggingFaceSelection:
type: object
additionalProperties: false
minProperties: 1
anyOf:
- required: [paths]
- required: [prefixes]
properties:
paths:
type: array
minItems: 1
maxItems: 1024
uniqueItems: true
items:
$ref: '#/components/schemas/ResultPath'
prefixes:
type: array
minItems: 1
maxItems: 1024
uniqueItems: true
items:
$ref: '#/components/schemas/ResultPath'
HuggingFaceSourceSubmission:
2026-07-13 14:59:50 +09:00
type: object
additionalProperties: false
required: [kind, repository_type, repository_id, revision]
properties:
kind:
const: hugging_face
repository_type:
type: string
enum: [model, dataset, space]
repository_id:
type: string
pattern: '^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$'
revision:
type: string
minLength: 1
maxLength: 256
selection:
$ref: '#/components/schemas/HuggingFaceSelection'
credential_id:
$ref: '#/components/schemas/CredentialId'
SourceSubmission:
2026-07-13 14:59:50 +09:00
oneOf:
- $ref: '#/components/schemas/HttpSourceSubmission'
- $ref: '#/components/schemas/ObjectStoreSourceSubmission'
- $ref: '#/components/schemas/HuggingFaceSourceSubmission'
2026-07-13 14:59:50 +09:00
discriminator:
propertyName: kind
mapping:
http: '#/components/schemas/HttpSourceSubmission'
object_store: '#/components/schemas/ObjectStoreSourceSubmission'
hugging_face: '#/components/schemas/HuggingFaceSourceSubmission'
HttpSourceProjection:
type: object
additionalProperties: false
required: [kind, display_url, result_path]
properties:
kind:
const: http
display_url:
type: string
format: uri
maxLength: 8192
description: Sanitized URL without userinfo, sensitive query values, or fragments.
result_path:
$ref: '#/components/schemas/ResultPath'
credential_id:
$ref: '#/components/schemas/CredentialId'
ObjectStoreSourceProjection:
type: object
additionalProperties: false
required: [kind, store, bucket, key, result_path]
properties:
kind:
const: object_store
store:
type: string
minLength: 1
maxLength: 128
bucket:
type: string
minLength: 3
maxLength: 63
key:
type: string
minLength: 1
maxLength: 4096
version_id:
type: string
maxLength: 1024
result_path:
$ref: '#/components/schemas/ResultPath'
credential_id:
$ref: '#/components/schemas/CredentialId'
HuggingFaceSourceProjection:
type: object
additionalProperties: false
required: [kind, repository_type, repository_id, revision]
properties:
kind:
const: hugging_face
repository_type:
type: string
enum: [model, dataset, space]
repository_id:
type: string
pattern: '^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$'
revision:
type: string
minLength: 1
maxLength: 256
selection:
$ref: '#/components/schemas/HuggingFaceSelection'
credential_id:
$ref: '#/components/schemas/CredentialId'
SourceProjection:
oneOf:
- $ref: '#/components/schemas/HttpSourceProjection'
- $ref: '#/components/schemas/ObjectStoreSourceProjection'
- $ref: '#/components/schemas/HuggingFaceSourceProjection'
discriminator:
propertyName: kind
mapping:
http: '#/components/schemas/HttpSourceProjection'
object_store: '#/components/schemas/ObjectStoreSourceProjection'
hugging_face: '#/components/schemas/HuggingFaceSourceProjection'
2026-07-13 14:59:50 +09:00
JobSubmission:
type: object
additionalProperties: false
required: [source]
2026-07-13 14:59:50 +09:00
properties:
source:
$ref: '#/components/schemas/SourceSubmission'
2026-07-13 14:59:50 +09:00
target:
description: Fields omitted here are taken from the configured default target before authorization.
$ref: '#/components/schemas/TargetOverride'
2026-07-13 14:59:50 +09:00
label:
type: string
minLength: 1
maxLength: 200
SourceCredentialKind:
type: string
enum: [basic_auth, bearer_token, http_headers, object_store, hugging_face]
BasicAuthMaterial:
type: object
additionalProperties: false
required: [username, password]
properties:
username:
type: string
minLength: 1
maxLength: 1024
password:
type: string
minLength: 1
maxLength: 16384
writeOnly: true
TokenMaterial:
type: object
additionalProperties: false
required: [token]
properties:
token:
type: string
minLength: 1
maxLength: 16384
writeOnly: true
HttpHeadersMaterial:
type: object
additionalProperties: false
required: [headers]
properties:
headers:
type: object
minProperties: 1
maxProperties: 64
propertyNames:
allOf:
- pattern: '^[a-z0-9!#$%&''*+.^_`|~-]+$'
- not:
enum: [authorization, connection, content-length, cookie, host, keep-alive, proxy-authenticate, proxy-authorization, te, trailer, transfer-encoding, upgrade]
additionalProperties:
type: string
minLength: 1
maxLength: 16384
description: Canonical lowercase end-to-end headers. Connection-nominated and routing, framing, cookie, proxy, and authentication headers are rejected.
writeOnly: true
ObjectStoreCredentialMaterial:
type: object
additionalProperties: false
required: [access_key_id, secret_access_key]
properties:
access_key_id:
type: string
minLength: 1
maxLength: 1024
secret_access_key:
type: string
minLength: 1
maxLength: 16384
session_token:
type: string
minLength: 1
maxLength: 16384
writeOnly: true
CredentialMaterial:
oneOf:
- $ref: '#/components/schemas/BasicAuthMaterial'
- $ref: '#/components/schemas/TokenMaterial'
- $ref: '#/components/schemas/HttpHeadersMaterial'
- $ref: '#/components/schemas/ObjectStoreCredentialMaterial'
writeOnly: true
description: Write-only material whose closed shape must match the credential kind. Values are never returned or logged.
SourceCredentialCreate:
oneOf:
- $ref: '#/components/schemas/BasicAuthCredentialCreate'
- $ref: '#/components/schemas/BearerTokenCredentialCreate'
- $ref: '#/components/schemas/HttpHeadersCredentialCreate'
- $ref: '#/components/schemas/ObjectStoreCredentialCreate'
- $ref: '#/components/schemas/HuggingFaceCredentialCreate'
discriminator:
propertyName: kind
mapping:
basic_auth: '#/components/schemas/BasicAuthCredentialCreate'
bearer_token: '#/components/schemas/BearerTokenCredentialCreate'
http_headers: '#/components/schemas/HttpHeadersCredentialCreate'
object_store: '#/components/schemas/ObjectStoreCredentialCreate'
hugging_face: '#/components/schemas/HuggingFaceCredentialCreate'
BasicAuthCredentialCreate:
type: object
additionalProperties: false
required: [label, kind, material]
properties:
label:
type: string
minLength: 1
maxLength: 200
kind:
const: basic_auth
material:
$ref: '#/components/schemas/BasicAuthMaterial'
BearerTokenCredentialCreate:
type: object
additionalProperties: false
required: [label, kind, material]
properties:
label:
type: string
minLength: 1
maxLength: 200
kind:
const: bearer_token
material:
$ref: '#/components/schemas/TokenMaterial'
HttpHeadersCredentialCreate:
type: object
additionalProperties: false
required: [label, kind, material]
properties:
label:
type: string
minLength: 1
maxLength: 200
kind:
const: http_headers
material:
$ref: '#/components/schemas/HttpHeadersMaterial'
ObjectStoreCredentialCreate:
type: object
additionalProperties: false
required: [label, kind, material]
properties:
label:
type: string
minLength: 1
maxLength: 200
kind:
const: object_store
material:
$ref: '#/components/schemas/ObjectStoreCredentialMaterial'
HuggingFaceCredentialCreate:
type: object
additionalProperties: false
required: [label, kind, material]
properties:
label:
type: string
minLength: 1
maxLength: 200
kind:
const: hugging_face
material:
$ref: '#/components/schemas/TokenMaterial'
SourceCredentialRotate:
type: object
additionalProperties: false
required: [material]
description: The material shape must match the stored credential kind; rotation never changes kind.
properties:
material:
$ref: '#/components/schemas/CredentialMaterial'
SourceCredentialVersion:
type: object
additionalProperties: false
required: [id, created_at]
properties:
id:
$ref: '#/components/schemas/CredentialVersionId'
created_at:
type: string
format: date-time
CredentialGrantVersion:
type: object
additionalProperties: false
required: [credential_id, version_id]
properties:
credential_id:
$ref: '#/components/schemas/CredentialId'
version_id:
$ref: '#/components/schemas/CredentialVersionId'
SourceCredential:
type: object
additionalProperties: false
required: [id, owner, label, kind, status, active_version, created_at, updated_at]
properties:
id:
$ref: '#/components/schemas/CredentialId'
owner:
$ref: '#/components/schemas/PrincipalId'
label:
type: string
minLength: 1
maxLength: 200
kind:
$ref: '#/components/schemas/SourceCredentialKind'
status:
type: string
enum: [active, revoked]
active_version:
oneOf:
- $ref: '#/components/schemas/SourceCredentialVersion'
- type: 'null'
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
SourceCredentialPage:
type: object
additionalProperties: false
required: [items, next_cursor]
properties:
items:
type: array
items:
$ref: '#/components/schemas/SourceCredential'
next_cursor:
type: [string, 'null']
2026-07-13 14:59:50 +09:00
JobPhase:
type: string
enum: [Queued, Running, RetryWait, Cancelling, Succeeded, Failed, Cancelled]
2026-07-17 09:16:46 +09:00
JobPhaseProjection:
type: object
additionalProperties: false
required: [phase]
properties:
phase:
$ref: '#/components/schemas/JobPhase'
TerminalJobPhase:
type: string
enum: [Succeeded, Failed, Cancelled]
2026-07-13 14:59:50 +09:00
JobLifecycle:
type: string
enum: [visible, soft_deleted, hard_deleting, hard_deleted]
AttemptAuthority:
type: object
additionalProperties: false
required: [attempt_id, fence, worker_incarnation]
properties:
attempt_id:
$ref: '#/components/schemas/OpaqueId'
fence:
type: integer
minimum: 1
worker_incarnation:
$ref: '#/components/schemas/OpaqueId'
LeaseProjection:
type: object
additionalProperties: false
required: [expires_at, renew_after]
properties:
expires_at:
type: string
format: date-time
description: Expiry of the exact coordination lease established for this authority.
renew_after:
type: string
format: date-time
description: Earliest recommended renewal time, strictly before expires_at.
2026-07-13 14:59:50 +09:00
Progress:
type: object
additionalProperties: false
required: [attempt_id, fence, completed_bytes, completed_members, observed_at]
properties:
attempt_id:
$ref: '#/components/schemas/OpaqueId'
fence:
type: integer
minimum: 1
completed_bytes:
type: integer
minimum: 0
total_bytes:
type: [integer, 'null']
minimum: 0
completed_members:
type: integer
minimum: 0
total_members:
type: [integer, 'null']
minimum: 0
observed_at:
type: string
format: date-time
ProgressValue:
type: object
additionalProperties: false
required: [completed_bytes, completed_members]
properties:
completed_bytes:
type: integer
minimum: 0
total_bytes:
type: [integer, 'null']
minimum: 0
completed_members:
type: integer
minimum: 0
total_members:
type: [integer, 'null']
minimum: 0
2026-07-13 14:59:50 +09:00
CheckpointProjection:
type: object
additionalProperties: false
required: [reusable, validated_bytes, validated_members]
properties:
reusable:
type: boolean
validated_bytes:
type: integer
minimum: 0
validated_members:
type: integer
minimum: 0
JobFailure:
2026-07-13 17:23:32 +09:00
oneOf:
- type: object
additionalProperties: false
required: [class, retryable, message]
properties:
class:
type: string
enum: [validation, authorization, source_not_found, source_changed, cancelled]
retryable:
const: false
message:
type: string
maxLength: 500
safe_details:
type: object
additionalProperties:
type: [string, integer, boolean, 'null']
- type: object
additionalProperties: false
required: [class, retryable, message]
properties:
class:
type: string
enum: [transient_source, transient_target, integrity, capacity, internal, lost_attempt]
retryable:
const: true
message:
type: string
maxLength: 500
safe_details:
type: object
additionalProperties:
type: [string, integer, boolean, 'null']
AttemptRuntimeFailure:
2026-07-13 14:59:50 +09:00
type: object
additionalProperties: false
2026-07-13 17:23:32 +09:00
required: [class, message]
2026-07-13 14:59:50 +09:00
properties:
class:
type: string
2026-07-13 17:23:32 +09:00
enum: [authorization, source_not_found, source_changed, transient_source, transient_target, integrity, capacity, internal]
2026-07-13 14:59:50 +09:00
message:
type: string
maxLength: 500
safe_details:
type: object
additionalProperties:
type: [string, integer, boolean, 'null']
ResultDescriptor:
type: object
additionalProperties: false
2026-07-17 09:16:46 +09:00
required: [kind, manifest_id, schema_version, manifest, member_count, total_bytes]
2026-07-13 14:59:50 +09:00
properties:
kind:
const: manifest
2026-07-17 09:16:46 +09:00
manifest_id:
$ref: '#/components/schemas/OpaqueId'
schema_version:
type: integer
minimum: 1
2026-07-13 14:59:50 +09:00
manifest:
$ref: '#/components/schemas/ObjectIdentity'
member_count:
type: integer
minimum: 1
total_bytes:
type: integer
minimum: 0
ObjectIdentity:
type: object
additionalProperties: false
2026-07-17 09:16:46 +09:00
required: [store, bucket, key, checksum, size]
2026-07-13 14:59:50 +09:00
properties:
store:
type: string
bucket:
type: string
key:
type: string
version_id:
type: string
checksum:
$ref: '#/components/schemas/Sha256Digest'
2026-07-17 09:16:46 +09:00
size:
type: integer
minimum: 0
Sha256Digest:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
DurableDescriptorRef:
type: object
additionalProperties: false
required: [id, kind, schema_version, byte_length, checksum]
properties:
id:
$ref: '#/components/schemas/OpaqueId'
kind:
type: string
enum: [resolved_source, checkpoint]
schema_version:
type: integer
minimum: 1
byte_length:
type: integer
minimum: 0
item_count:
type: integer
minimum: 0
checksum:
$ref: '#/components/schemas/Sha256Digest'
ResultMember:
type: object
additionalProperties: false
required: [id, path, size, object]
properties:
id:
$ref: '#/components/schemas/OpaqueId'
path:
2026-07-13 14:59:50 +09:00
type: string
minLength: 1
maxLength: 4096
description: NFC-normalized relative POSIX path validated under architecture.md.
size:
type: integer
minimum: 0
object:
$ref: '#/components/schemas/ObjectIdentity'
ResultMemberPage:
type: object
additionalProperties: false
required: [items, next_cursor]
properties:
items:
type: array
items:
$ref: '#/components/schemas/ResultMember'
next_cursor:
type: [string, 'null']
2026-07-13 14:59:50 +09:00
Job:
type: object
additionalProperties: false
required: [resource_kind, id, owner, label, revision, phase, lifecycle, source, target, authoritative_attempt, progress, checkpoint, result, failure, created_at, updated_at, event_cursor]
2026-07-13 14:59:50 +09:00
properties:
resource_kind:
const: job
2026-07-13 14:59:50 +09:00
id:
$ref: '#/components/schemas/OpaqueId'
owner:
$ref: '#/components/schemas/PrincipalId'
label:
type: [string, 'null']
minLength: 1
maxLength: 200
2026-07-13 14:59:50 +09:00
revision:
type: integer
minimum: 1
phase:
$ref: '#/components/schemas/JobPhase'
lifecycle:
$ref: '#/components/schemas/JobLifecycle'
source:
$ref: '#/components/schemas/SourceProjection'
2026-07-13 14:59:50 +09:00
target:
$ref: '#/components/schemas/Target'
authoritative_attempt:
oneOf:
- $ref: '#/components/schemas/AttemptAuthority'
- type: 'null'
progress:
oneOf:
- $ref: '#/components/schemas/Progress'
- type: 'null'
checkpoint:
oneOf:
- $ref: '#/components/schemas/CheckpointProjection'
- type: 'null'
result:
oneOf:
- $ref: '#/components/schemas/ResultDescriptor'
- type: 'null'
failure:
oneOf:
- $ref: '#/components/schemas/JobFailure'
- type: 'null'
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
event_cursor:
type: string
minLength: 16
JobTombstone:
type: object
additionalProperties: false
required: [resource_kind, id, owner, target, terminal_phase, deletion_operation_id, created_at, hard_delete_started_at, updated_at, event_cursor]
properties:
resource_kind:
const: tombstone
id:
$ref: '#/components/schemas/OpaqueId'
owner:
$ref: '#/components/schemas/PrincipalId'
target:
$ref: '#/components/schemas/Target'
terminal_phase:
$ref: '#/components/schemas/TerminalJobPhase'
deletion_operation_id:
$ref: '#/components/schemas/OpaqueId'
created_at:
type: string
format: date-time
hard_delete_started_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
event_cursor:
type: string
minLength: 16
JobResource:
oneOf:
- $ref: '#/components/schemas/Job'
- $ref: '#/components/schemas/JobTombstone'
discriminator:
propertyName: resource_kind
mapping:
job: '#/components/schemas/Job'
tombstone: '#/components/schemas/JobTombstone'
2026-07-13 14:59:50 +09:00
JobPage:
type: object
additionalProperties: false
required: [items, next_cursor, event_cursor]
properties:
items:
type: array
items:
$ref: '#/components/schemas/JobResource'
2026-07-13 14:59:50 +09:00
next_cursor:
type: [string, 'null']
event_cursor:
type: string
minLength: 16
AttemptRecord:
type: object
additionalProperties: false
required: [id, fence, worker_incarnation, state, progress, result, failure, created_at, updated_at]
allOf:
- if:
required: [state]
properties:
state:
const: AttemptCommitted
then:
properties:
result:
$ref: '#/components/schemas/ResultDescriptor'
else:
properties:
result:
type: 'null'
properties:
id:
$ref: '#/components/schemas/OpaqueId'
fence:
type: integer
minimum: 1
worker_incarnation:
$ref: '#/components/schemas/OpaqueId'
state:
type: string
enum: [AttemptAuthorized, AttemptExecuting, AttemptStopped, AttemptCommitted]
progress:
oneOf:
- $ref: '#/components/schemas/Progress'
- type: 'null'
result:
oneOf:
- $ref: '#/components/schemas/ResultDescriptor'
- type: 'null'
failure:
oneOf:
- $ref: '#/components/schemas/JobFailure'
- type: 'null'
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
AttemptPage:
type: object
additionalProperties: false
required: [items, next_cursor]
properties:
items:
type: array
items:
$ref: '#/components/schemas/AttemptRecord'
next_cursor:
type: [string, 'null']
DeletionProblem:
type: object
additionalProperties: false
required: [class, message]
properties:
class:
type: string
enum: [authorization, target_unavailable, configuration, internal]
message:
type: string
maxLength: 500
2026-07-13 14:59:50 +09:00
DeletionOperation:
type: object
additionalProperties: false
required: [id, job_id, state, problem, created_at, updated_at]
2026-07-13 14:59:50 +09:00
properties:
id:
$ref: '#/components/schemas/OpaqueId'
job_id:
$ref: '#/components/schemas/OpaqueId'
state:
type: string
enum: [queued, running, retry_wait, blocked, completed]
problem:
oneOf:
- $ref: '#/components/schemas/DeletionProblem'
- type: 'null'
2026-07-13 14:59:50 +09:00
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
ApiError:
type: object
additionalProperties: false
required: [code, message, request_id]
properties:
code:
type: string
enum: [invalid_request, unauthenticated, forbidden, not_found, idempotency_conflict, precondition_failed, cursor_invalid, cursor_expired, rate_limited, unavailable, internal]
message:
type: string
maxLength: 500
request_id:
$ref: '#/components/schemas/OpaqueId'
fields:
type: array
maxItems: 100
items:
type: object
additionalProperties: false
required: [pointer, code]
properties:
pointer:
type: string
maxLength: 500
code:
type: string
maxLength: 100
ClaimRequest:
type: object
additionalProperties: false
required: [operation_id, worker_incarnation]
properties:
operation_id:
$ref: '#/components/schemas/OpaqueId'
worker_incarnation:
$ref: '#/components/schemas/OpaqueId'
ExecutionEnvelope:
type: object
additionalProperties: false
required: [id, job_id, attempt_id, fence, worker_incarnation, source, sensitive_source_ref, credential_version, resolved_source_ref, target, staging_target, execution_grant_ref, checkpoint_ref]
properties:
id:
$ref: '#/components/schemas/OpaqueId'
job_id:
$ref: '#/components/schemas/OpaqueId'
attempt_id:
$ref: '#/components/schemas/OpaqueId'
fence:
type: integer
minimum: 1
worker_incarnation:
$ref: '#/components/schemas/OpaqueId'
source:
$ref: '#/components/schemas/SourceProjection'
sensitive_source_ref:
description: Opaque grant-bound reference to the complete accepted source input; credential_version identifies any pinned credential separately.
$ref: '#/components/schemas/OpaqueId'
credential_version:
oneOf:
- $ref: '#/components/schemas/CredentialGrantVersion'
- type: 'null'
resolved_source_ref:
oneOf:
- $ref: '#/components/schemas/DurableDescriptorRef'
- type: 'null'
target:
$ref: '#/components/schemas/Target'
staging_target:
$ref: '#/components/schemas/StagingTarget'
execution_grant_ref:
$ref: '#/components/schemas/OpaqueId'
checkpoint_ref:
oneOf:
- $ref: '#/components/schemas/DurableDescriptorRef'
- type: 'null'
ClaimResponse:
type: object
additionalProperties: false
required: [authority, execution]
properties:
authority:
$ref: '#/components/schemas/AttemptAuthority'
execution:
$ref: '#/components/schemas/ExecutionEnvelope'
ActivationResponse:
type: object
additionalProperties: false
required: [authority, execution, lease]
properties:
authority:
$ref: '#/components/schemas/AttemptAuthority'
execution:
$ref: '#/components/schemas/ExecutionEnvelope'
lease:
$ref: '#/components/schemas/LeaseProjection'
2026-07-13 14:59:50 +09:00
AttemptMutation:
type: object
required: [operation_id, fence, worker_incarnation]
properties:
operation_id:
$ref: '#/components/schemas/OpaqueId'
fence:
type: integer
minimum: 1
worker_incarnation:
$ref: '#/components/schemas/OpaqueId'
2026-07-13 18:23:03 +09:00
AttemptRenewRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
AttemptActivateRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
AttemptStopRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
StagingObjectIdentity:
type: object
additionalProperties: false
required: [store, bucket, key]
properties:
store:
type: string
minLength: 1
bucket:
type: string
minLength: 1
key:
type: string
minLength: 1
version_id:
type: string
minLength: 1
StagingWriteIntent:
type: object
additionalProperties: false
required: [store, bucket, key]
properties:
store:
type: string
minLength: 1
bucket:
type: string
minLength: 1
key:
type: string
minLength: 1
StagingMultipartIdentity:
type: object
additionalProperties: false
required: [store, bucket, key, upload_id]
properties:
store:
type: string
minLength: 1
bucket:
type: string
minLength: 1
key:
type: string
minLength: 1
upload_id:
type: string
minLength: 1
AttemptStagingObjectRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
required: [object]
properties:
object:
$ref: '#/components/schemas/StagingObjectIdentity'
completed_upload_id:
type: string
minLength: 1
AttemptStagingWriteIntentRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
required: [intent]
properties:
intent:
$ref: '#/components/schemas/StagingWriteIntent'
AttemptStagingMultipartRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
required: [multipart]
properties:
multipart:
$ref: '#/components/schemas/StagingMultipartIdentity'
AttemptResolvedSourceRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
required: [resolved_source_ref]
properties:
resolved_source_ref:
allOf:
- $ref: '#/components/schemas/DurableDescriptorRef'
- type: object
properties:
kind:
const: resolved_source
AttemptCheckpointRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
2026-07-17 09:16:46 +09:00
required: [checkpoint_ref, resolved_source_id, validated_bytes, validated_members]
properties:
checkpoint_ref:
allOf:
- $ref: '#/components/schemas/DurableDescriptorRef'
- type: object
properties:
kind:
const: checkpoint
2026-07-17 09:16:46 +09:00
resolved_source_id:
$ref: '#/components/schemas/OpaqueId'
validated_bytes:
type: integer
minimum: 0
validated_members:
type: integer
minimum: 0
staging_multipart:
$ref: '#/components/schemas/StagingMultipartIdentity'
2026-07-13 14:59:50 +09:00
AttemptProgressRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
required: [progress]
properties:
progress:
$ref: '#/components/schemas/ProgressValue'
2026-07-13 14:59:50 +09:00
AttemptOutcomeRequest:
unevaluatedProperties: false
allOf:
- $ref: '#/components/schemas/AttemptMutation'
- type: object
required: [outcome]
properties:
outcome:
oneOf:
- type: object
additionalProperties: false
required: [kind, result]
properties:
kind:
const: success
result:
$ref: '#/components/schemas/ResultDescriptor'
- type: object
additionalProperties: false
required: [kind, failure]
properties:
kind:
const: failure
failure:
2026-07-13 17:23:32 +09:00
$ref: '#/components/schemas/AttemptRuntimeFailure'