openvibers/openvibe.run STATUS.json

STATUS.json

main 7.9 KB · 65 lines · json

1{
2 "repository": "OpenVibers/OpenVibe.Run",
3 "stage": "alpha",
4 "code": true,
5 "wave": "W20",
6 "plan": "OpenVibe Updated Plan Based On Codebase (plan T14, ADR-034)",
7 "runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db) + Valkey 9",
8 "port": 4920,
9 "domain": "openvibe.run",
10 "contracts": "openvibe-contracts v0.422.0",
11 "sdk": "openvibe-sdk v0.161.0",
12 "shared": "openvibe-shared v4.237.0",
13 "packages": [
14 "openvibe-contracts v0.422.0",
15 "openvibe-sdk v0.161.0",
16 "openvibe-shared v4.237.0"
17 ],
18 "capabilities": [
19 "run.job.submit",
20 "run.job.read",
21 "run.job.list",
22 "run.job.cancel",
23 "run.job.stream",
24 "run.job.admin",
25 "run.session.create",
26 "run.session.read",
27 "run.session.control"
28 ],
29 "events": [
30 "run.job.queued",
31 "run.job.started",
32 "run.job.succeeded",
33 "run.job.failed",
34 "run.job.cancelled",
35 "run.job.expired",
36 "run.session.started",
37 "run.session.ended"
38 ],
39 "deployed": true,
40 "deployment": "openvibe-ovh: unit openvibe-run.service on 127.0.0.1:4920 since 2026-10-07 (release layout /opt/openvibe.run, env /etc/openvibe/run.env, database ov_run), deployed with `sudo ovhost deploy run`. The job API is reached by first-party callers on loopback; jobs are placed on people's own Bot nodes through Bot's internal jobs API (bot.job.dispatch). openvibe.run itself is parked (a 302 to openvibe.network) until Run has a product surface; the vhost in deploy/nginx/openvibe.run.conf is installed then. Its rules stay: /api/health, /api/ready, /release.json and the job API proxied, the client address from $remote_addr only, /internal/ and /metrics refused at the edge.",
41 "features": [
42 "the job API (/api/v1, one capability per route): POST /jobs (run.job.submit), GET /jobs/:id (run.job.read), GET /jobs/ (run.job.list), POST /jobs/:id/cancel (run.job.cancel), POST /jobs/:id/stream/ticket and GET /jobs/:id/stream (run.job.stream), GET /admin/jobs (run.job.admin)",
43 "the project and the requester come from the token (claims.project_id, claims.sub), never from the body; another project's job is 404 run.job_not_found, never 403",
44 "idempotent submit: the same Idempotency-Key (or body.idempotency_key) from the same project with the same body answers the first job (200, created false); with a different body it is 409 run.idempotency.conflict",
45 "every request body and query is validated against its released contract (run.job-create-request@1, run.job-list-query@1) and every answer against run.job-read-result@1, run.job-create-result@1, run.job-list-result@1, run.job-stream-ticket-result@1",
46 "limits bounded by the project's caps (RUN_LIMITS_*, 422 run.limits.exceeded) and args over 512 KiB refused 413 run.args_too_large, never silently lowered; requirements defaults to the contract's platform.workload-requirements@1 default (run.<class>, mobility job, latency_class background, objective balanced)",
47 "the run.job.queued|started|succeeded|failed|cancelled|expired events written in the same transaction as the state change, the outbox row keyed run:<job id>:<state> (a replay is one row) with a contract-valid evt_ document id on the published envelope, relayed from run_events_outbox by the openvibe-sdk outbox",
48 "the job stream: a two-minute single-use RS256 stream ticket (audience openvibe.run, typ run-stream, its own key — never Network's) opens text/event-stream of run.job-stream-event@1, replayed from the last 1 MiB with monotonic seq as the SSE id and Last-Event-ID resume",
49 "keyset paging on (created_at, id) with next_cursor null on the last page; run.job.admin lists any project's jobs (project_id in the query) and reads and cancels any job",
50 "the dispatcher bridge to OpenVibe.Bot (plan T14 step 6, server/dispatch/index.js + server/jobs/poller.js): a queued job is placed on a node from the Fabric offers (server/dispatch/placement.js, openvibe-sdk/placement plan(), the job's own platform.workload-requirements@1, no eligible offer → run.job.unplaceable) and handed to Bot once (server/dispatch/bot.js POST /api/v1/jobs, Network client-credentials token audience openvibe.bot holding bot.job.dispatch, cached until 60 s before expiry, never logged); every placed or running job is mirrored from Bot's own row (state, placement, timings, exit, result, metered wall clock) by a poller on RUN_POLL_MS (default 1000 ms, started by server/index.js, nothing at module load), each state change emitting its run.job.* event once in the same transaction and feeding the job's SSE stream with the node's stdout as output events; a job Bot answers 404 for after Run sent it fails run.job.worker_failed after RUN_DISPATCH_UNKNOWN_POLLS polls, and Bot can neither rename the node or the project of a job Run placed nor move its state backwards",
51 "cancel reaches the node: a queued job is cancelled at once, a placed or running one is marked cancel_requested and Bot is asked for job_cancel (once per job, retried by the poller) — the job settles cancelled when Bot reports it",
52 "ttl_ms expiry settles the job expired (run.job.ttl) and asks Bot to stop a job a node may hold",
53 "the job stream also opens with a Bearer service token holding run.job.stream for the job's project, besides the two-minute ticket",
54 "run_jobs (migrations/0001_jobs.sql) holds every job, its state, placement, timings, exit, result and the metered wall clock",
55 "Bot owns the node link and the per-second metering of the jobs it carries (plan T14 L1); Run holds a Billing token of its own (billing.usage.record, audience openvibe.billing) used only for the external managed-browser provider's jobs",
56 "plan T14 R4a built, not deployed: the managed-browser provider adapter (server/dispatch/browser-provider.js; RUN_BROWSER_PROVIDER_URL / _API_KEY / _TIMEOUT_MS, off while unset) places class browser jobs on kind=provider offers named browser-provider, validates every answer against browser-provider.job-create-result@1 / job-state@1 and never adopts a malformed one; Run meters those jobs itself, the provider's claimed wall time clamped to Run's observed duration + 5 s, and relays the readings from run_usage_outbox (migrations/0003_usage_outbox.sql) to Billing (RUN_BILLING_URL; unset, they wait and the jobs still run)",
57 "truthful readiness (GET /api/ready: db required; valkey, Network JWKS, Events, Bot reachability and the poller's own status reported, never claimed) and the loopback-only /metrics gauges (jobs queued, active, ended, outbox backlog, streams)",
58 "plan T11 step 4 built, not deployed: /llms.txt and /llms-full.txt (server/web/discovery.js, public pages and docs only, never the API, admin, a job or a stream) and IndexNow (INDEXNOW_KEY: serves GET /<key>.txt and pings the public pages once at boot; unset, the key route is 404 and nothing is sent)",
59 "a person's own machine (user-owned offer read from Network's internal list) runs only that person's jobs naming user-owned; a delegating service cancels and streams (by ticket) the jobs it started for a person",
60 "the Arena's race on the one engine (compare-arena-ecosystem.md §3, server/races/): POST /api/v1/races starts one child linux job per side under one parent race with the same share of the budget each, GET /api/v1/races/:id returns each side's output so far and its receipts, and POST /api/v1/races/:id/judgement records a bench.match@1 on Bench (source arena, shown order, blind true, human_pairwise with a keyed person hash) before the names are revealed; only the person who started it, through the same service, may read or judge",
61 "the race play as data (agents.play@1 1.1.0, server/plays/race.js): id race, one role per side, one parallel phase, an even budget split, blind true and stop when person, listed by GET /api/v1/plays; the matchmaker falls back to two entrants of different families from RUN_RACE_ENTRANTS while Bench has no matchmaker endpoint (Contracts 0.422.0 has no run.race@1 yet, so the race request/answer is validated in server/races/service.js)"
62 ],
63 "updated": "2026-11-13"
64}
65