RunJobReadResult run.job-read-result@1

Generated at from openvibe-contracts v0.97.0 and openvibe-sdk v0.26.0.

Version
1.0.0
Owner
run
Visibility
public
Status
planned
Compatibility
backward
Decision
ADR-034
Schema
https://openvibe.network/contracts/run/job-read-result.v1.json

run.job-read-result@1 (PLANNED; plan T14 R1, ADR-034): one job on OpenVibe.Run, as GET /api/v1/jobs/{id} answers it (capability run.job.read), POST /api/v1/jobs/{id}/cancel answers it after the cancel (run.job.cancel), and run.job-create-result@1 and run.job-list-result@1 carry it. STATES: queued (stored, waiting for a node) -> placed (sent to a node as platform.job@1, not yet started) -> running (the node sent job_started) -> one end state: succeeded (job_exit reason exited with code 0), failed (exited with another code, or reason limit, stopped or failed), cancelled (POST /api/v1/jobs/{id}/cancel, or job_exit reason cancelled), expired (ttl_ms ran out: before placement, before start, or while running, job_exit reason ttl). An end state never changes. Run mints the id (job_<ULID>) and sends it unchanged as platform.job@1 `id`, so every metering reading of the job is `run:<id>:<n>` (platform.job-frame@1 job_usage). usage.seconds is wall_ms / 1000: the sum of the job's readings (service run, operation function.invoke, unit s). Never carries the job's stdout (GET /api/v1/jobs/{id}/stream) or a credential. More fields may be added.

Fields

FieldTypeRequiredDescriptionConstraints
idstringyesMinted by Run; the platform.job@1 id and the stem of every usage reading key (run:<id>:<n>).
  • pattern ^job_[0-9A-HJKMNP-TV-Z]{26}$
project_idstringyesThe project the caller's token names; usage is billed to it.
  • pattern ^prj_[0-9A-HJKMNP-TV-Z]{26}$
requesteridentity.subject-refyesThe token principal that submitted the job.
stateenumyes
  • one of "queued", "placed", "running", "succeeded", "failed", "cancelled", "expired"
classplatform.runtime-classyes
artifactone ofyes
inputshttps://openvibe.network/contracts/run/job-create-request.v1.json#/$defs/inputyes
  • maxItems 32
limitshttps://openvibe.network/contracts/run/job-create-request.v1.json#/$defs/limitsyes
ttl_msintegeryesThe job's lifetime from created_at, the default filled in.
  • minimum 1
egresshttps://openvibe.network/contracts/run/job-create-request.v1.json#/$defs/egressyes
requirementsplatform.workload-requirementsyesWhat the job was placed against, the default filled in.
idempotency_keyone ofyes
placementone ofyesWhere the job was sent; null while queued, and for a job cancelled or expired before placement.
timingsobjectyes
  • no other fields
timings.created_atstringyes
  • format date-time
timings.placed_atstring | nullyes
  • format date-time
timings.started_atstring | nullyesFrom job_started started_ms; null until the process started.
  • format date-time
timings.finished_atstring | nullyesWhen the job reached its end state; null before.
  • format date-time
exitone ofyesThe node's job_exit; null until it arrived, and for a job that ended before a node ran it.
resultanyyesThe artifact's declared output (job_exit result, any JSON); null unless state is succeeded.
usagehttps://openvibe.network/contracts/run/job-read-result.v1.json#/$defs/usageyes
errorone ofyesWhy the job failed or expired; null in every other state.

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: expired-unplaceable
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "expired",
  "placement": null,
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": null,
    "started_at": null,
    "finished_at": "2026-10-04T10:10:30.000Z"
  },
  "exit": null,
  "result": null,
  "usage": {
    "seconds": 0,
    "wall_ms": 0,
    "cpu_ms": null,
    "mem_peak_bytes": null
  },
  "error": {
    "code": "run.job.unplaceable",
    "detail": "no node offers worker:function with egress none"
  }
}
Valid: failed-limit
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "failed",
  "placement": {
    "node": "dev_01JAB2C3D4E5F6G7H8J9K0MNPT",
    "provider": null,
    "region": "us-west"
  },
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": "2026-10-04T10:00:00.400Z",
    "started_at": "2026-10-04T10:00:00.650Z",
    "finished_at": "2026-10-04T10:00:03.000Z"
  },
  "exit": {
    "reason": "limit",
    "code": null
  },
  "result": null,
  "usage": {
    "seconds": 2.35,
    "wall_ms": 2350,
    "cpu_ms": 1800,
    "mem_peak_bytes": 41943040
  },
  "error": {
    "code": "run.job.limit",
    "detail": "mem_bytes exceeded"
  }
}
Valid: queued
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "queued",
  "placement": null,
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": null,
    "started_at": null,
    "finished_at": null
  },
  "exit": null,
  "result": null,
  "usage": {
    "seconds": 0,
    "wall_ms": 0,
    "cpu_ms": null,
    "mem_peak_bytes": null
  },
  "error": null
}
Valid: running
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "running",
  "placement": {
    "node": "dev_01JAB2C3D4E5F6G7H8J9K0MNPT",
    "provider": null,
    "region": "us-west"
  },
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": "2026-10-04T10:00:00.400Z",
    "started_at": "2026-10-04T10:00:00.650Z",
    "finished_at": null
  },
  "exit": null,
  "result": null,
  "usage": {
    "seconds": 0,
    "wall_ms": 0,
    "cpu_ms": null,
    "mem_peak_bytes": null
  },
  "error": null
}
Valid: succeeded
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "succeeded",
  "placement": {
    "node": "dev_01JAB2C3D4E5F6G7H8J9K0MNPT",
    "provider": null,
    "region": "us-west"
  },
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": "2026-10-04T10:00:00.400Z",
    "started_at": "2026-10-04T10:00:00.650Z",
    "finished_at": "2026-10-04T10:00:03.000Z"
  },
  "exit": {
    "reason": "exited",
    "code": 0
  },
  "result": {
    "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPW"
  },
  "usage": {
    "seconds": 2.35,
    "wall_ms": 2350,
    "cpu_ms": 1800,
    "mem_peak_bytes": 41943040
  },
  "error": null
}
Rejected: failed-without-error
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "failed",
  "placement": {
    "node": "dev_01JAB2C3D4E5F6G7H8J9K0MNPT",
    "provider": null,
    "region": "us-west"
  },
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": "2026-10-04T10:00:00.400Z",
    "started_at": "2026-10-04T10:00:00.650Z",
    "finished_at": "2026-10-04T10:00:03.000Z"
  },
  "exit": {
    "reason": "limit",
    "code": null
  },
  "result": null,
  "usage": {
    "seconds": 2.35,
    "wall_ms": 2350,
    "cpu_ms": 1800,
    "mem_peak_bytes": 41943040
  },
  "error": null
}
Rejected: queued-with-result
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "queued",
  "placement": null,
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": null,
    "started_at": null,
    "finished_at": null
  },
  "exit": null,
  "result": {
    "ok": true
  },
  "usage": {
    "seconds": 0,
    "wall_ms": 0,
    "cpu_ms": null,
    "mem_peak_bytes": null
  },
  "error": null
}
Rejected: running-without-placement
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "running",
  "placement": null,
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": "2026-10-04T10:00:00.400Z",
    "started_at": "2026-10-04T10:00:00.650Z",
    "finished_at": null
  },
  "exit": null,
  "result": null,
  "usage": {
    "seconds": 0,
    "wall_ms": 0,
    "cpu_ms": null,
    "mem_peak_bytes": null
  },
  "error": null
}
Rejected: succeeded-nonzero-exit
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "succeeded",
  "placement": {
    "node": "dev_01JAB2C3D4E5F6G7H8J9K0MNPT",
    "provider": null,
    "region": "us-west"
  },
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": "2026-10-04T10:00:00.400Z",
    "started_at": "2026-10-04T10:00:00.650Z",
    "finished_at": "2026-10-04T10:00:03.000Z"
  },
  "exit": {
    "reason": "exited",
    "code": 1
  },
  "result": {
    "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPW"
  },
  "usage": {
    "seconds": 2.35,
    "wall_ms": 2350,
    "cpu_ms": 1800,
    "mem_peak_bytes": 41943040
  },
  "error": null
}
Rejected: unknown-state
{
  "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "requester": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPV"
  },
  "class": "function",
  "artifact": {
    "name": "thumbnail",
    "version": "1.2.0"
  },
  "inputs": [
    {
      "name": "photo.jpg",
      "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size_bytes": 482113
    }
  ],
  "limits": {
    "wall_ms": 30000,
    "cpu_ms": 30000,
    "mem_bytes": 268435456
  },
  "ttl_ms": 630000,
  "egress": "none",
  "requirements": {
    "kind": "run.function",
    "mobility": "job",
    "latency_class": "background",
    "objective": "balanced"
  },
  "idempotency_key": "thumb:photo-7",
  "state": "paused",
  "placement": null,
  "timings": {
    "created_at": "2026-10-04T10:00:00.000Z",
    "placed_at": null,
    "started_at": null,
    "finished_at": null
  },
  "exit": null,
  "result": null,
  "usage": {
    "seconds": 0,
    "wall_ms": 0,
    "cpu_ms": null,
    "mem_peak_bytes": null
  },
  "error": null
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('run.job-read-result@1', value);   // { valid, errors: [{ path, message }] }