RunSession run.session@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
run
Visibility
public
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/run/session.v1.json

run.session@1 (the Desks plan's D6): one session on OpenVibe.Run, a browser desk held for one person, as GET /api/v1/sessions/{id} answers it (capability run.session.read) and run.session-list-result@1, POST /api/v1/sessions (run.session.create) and POST /api/v1/sessions/{id}/end (run.session.control) carry it. A session is a desk (bot.command@1 kind desk, kind browser) that Run places on a machine and OpenVibe.Bot leases to it (bot.desk-lease@1): on one of the person's own machines where they let agents use it (trust user-owned, never another person's), or on a desk host that serves other people (trust first-party or community: the host's OpenVibe Link runs every desk in its own sandbox, desk_isolation sandbox, and offers nothing else of the machine). STATES: placing (stored, looking for a machine) -> starting (the desk is leased and starting) -> running (the desk answered) -> ended. An ended session never changes; end.reason says why: ended (POST /api/v1/sessions/{id}/end), ttl (ttl_s ran out), idle (no command for idle_s), host_lost (its machine went away or stopped the desk), unplaceable (no machine had room before ttl_s, or none at all) or failed (the desk would not start). USAGE: desk_seconds counts from started_at to ended_at (or now while running), metered to OpenVibe.Billing as one platform.usage-sample@1 per minute (service run, operation browser.desk, unit s, idempotency_key run:<session id>:<minute>). Run mints the id (ses_<ULID>).

Fields

FieldTypeRequiredDescriptionConstraints
idhttps://openvibe.network/contracts/run/session.v1.json#/$defs/session_idyes
owneridentity.subject-refyesThe person the session is for: only they (or a first-party service acting for them) read, act on or end it.
viastring | nullyesThe first-party service that asked for the person (service:actor), or null when they asked themselves.
  • pattern ^service:[a-z][a-z0-9-]{0,40}$
kindconstyesA platform.runtime-class@1 name; browser (a headless browser driven over its pipe) is the only kind of session in v1.
  • = "browser"
stateenumyes
  • one of "placing", "starting", "running", "ended"
sizehttps://openvibe.network/contracts/run/session.v1.json#/$defs/sizeyes
ttl_sintegeryesThe most the session lives, from created_at.
  • minimum 60
  • maximum 14400
idle_sintegeryesA session no command used this long ends (end.reason idle).
  • minimum 60
  • maximum 3600
placementone ofyes
timingshttps://openvibe.network/contracts/run/session.v1.json#/$defs/timingsyes
endone ofyes
usagehttps://openvibe.network/contracts/run/session.v1.json#/$defs/usageyes
idempotency_keyone ofyes
task_idone ofThe OpenVibe.Actor task that asked for this session (plan 2026-11-07: one id across Surf, Computer and Actor). Null when a person opened it themselves. The session is the Computer the task's record carries.
curtainbooleanCurtain now (the privacy screen): while it is up the session's still answers the curtain picture, never the screen. The person raises and lifts it with POST /api/v1/sessions/{id}/curtain.
  • default false

Examples

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

Valid: ended-idle
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "ended",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqr",
    "trust": "community",
    "offer_id": "desk:dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "region": "eu",
    "reasons": [
      "a shared desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": "2026-10-28T10:20:00Z"
  },
  "end": {
    "reason": "idle",
    "detail": "no command for 900 s"
  },
  "usage": {
    "desk_seconds": 1196
  },
  "idempotency_key": null
}
Valid: ended-unplaceable
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": null,
  "kind": "browser",
  "state": "ended",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": null,
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": null,
    "last_used_at": null,
    "ended_at": "2026-10-28T10:01:00Z"
  },
  "end": {
    "reason": "unplaceable",
    "detail": "no desk host had room"
  },
  "usage": {
    "desk_seconds": 0
  },
  "idempotency_key": "actor:tsk_01JD2C3D4E5F6G7H8J9K0MNPQR"
}
Valid: placing
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": null,
  "kind": "browser",
  "state": "placing",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": null,
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": null,
    "last_used_at": null,
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 0
  },
  "idempotency_key": "actor:tsk_01JD2C3D4E5F6G7H8J9K0MNPQR"
}
Valid: running-own-machine
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqr",
    "trust": "user-owned",
    "offer_id": null,
    "region": null,
    "reasons": [
      "your own machine, as asked"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": null
}
Valid: running-shared
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqr",
    "trust": "community",
    "offer_id": "desk:dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "region": "eu",
    "reasons": [
      "a shared desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": null
}
Valid: running-task-session
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQS",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqs",
    "trust": "first-party",
    "offer_id": null,
    "region": null,
    "reasons": [
      "an OpenVibe desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-11-07T09:00:00Z",
    "started_at": "2026-11-07T09:00:04Z",
    "last_used_at": "2026-11-07T09:05:00Z",
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": "actor:tsk_01JAB2C3D4E5F6G7H8J9K0MNPT",
  "task_id": "tsk_01JAB2C3D4E5F6G7H8J9K0MNPT",
  "curtain": false
}
Rejected: desktop-kind
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "desktop",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqr",
    "trust": "community",
    "offer_id": "desk:dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "region": "eu",
    "reasons": [
      "a shared desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": null
}
Rejected: ended-without-reason
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "ended",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqr",
    "trust": "community",
    "offer_id": "desk:dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "region": "eu",
    "reasons": [
      "a shared desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": "2026-10-28T10:20:00Z"
  },
  "end": null,
  "usage": {
    "desk_seconds": 1196
  },
  "idempotency_key": null
}
Rejected: main-screen
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "main",
    "trust": "community",
    "offer_id": "desk:dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "region": "eu",
    "reasons": [
      "a shared desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": null
}
Rejected: running-unplaced
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": null,
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": null
  },
  "end": null,
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": null
}
Rejected: running-with-end
{
  "id": "ses_01JD2C3D4E5F6G7H8J9K0MNPQR",
  "owner": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "via": "service:actor",
  "kind": "browser",
  "state": "running",
  "size": {
    "width": 1280,
    "height": 800
  },
  "ttl_s": 3600,
  "idle_s": 900,
  "placement": {
    "machine": "dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "desk": "desk-s0mnpqr",
    "trust": "community",
    "offer_id": "desk:dev_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
    "region": "eu",
    "reasons": [
      "a shared desk host with room"
    ]
  },
  "timings": {
    "created_at": "2026-10-28T10:00:00Z",
    "started_at": "2026-10-28T10:00:04Z",
    "last_used_at": "2026-10-28T10:05:00Z",
    "ended_at": null
  },
  "end": {
    "reason": "idle",
    "detail": null
  },
  "usage": {
    "desk_seconds": 296
  },
  "idempotency_key": null
}

Validate

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