Commits
-
Worker threads for sharp and pdf-lib (S5): apps/_shared/jobs/pool.js runs img's image operations and docs' pdf-lib tools in worker_threads, so a large merge or conversion never blocks the event loop (/api/health, the job routes and every other request keep answering). TOOLS_WORKERS (2, per app TOOLS_WORKERS_<APP>) run at once, shared by the jobs and the synchronous /api/process endpoints, which now submit to the pool and wait; TOOLS_WORKER_QUEUE (64) more wait, then 503 tools.busy with Retry-After. Each worker has a V8 heap limit (TOOLS_WORKER_MEMORY_MB, 512): a run that needs more fails with 413 tools.input.too_large and its worker is replaced. A run past its timeout (the job's own, or the descriptor's limits.timeoutMs on the sync endpoints: 504 tools.run.timeout), a cancelled job or a sync client that went away has its worker terminated at once, which pdf-lib and sharp never allowed before. Buffers move by transfer (never a pooled slab), tool errors keep status/code/extra/guardReason, idle workers stop after TOOLS_WORKER_IDLE_MS; qpdf and poppler tools stay on the main thread (their child processes have their own timeouts). /api/health shows workers. The older per-route limiters no longer count liveness and readiness probes (the guard's quota already skipped them). Tests: pool.test.js (off the event loop, size cap, queue and refusal, buffers, error fields, timeout and abort terminate, heap limit, crash, idle stop, env sizing) and docs pool.test.js on a real process (health stays under 250 ms during a 5000-page merge; a merge over a 32 MB heap fails 413 and the next job succeeds)OpenVibers · 24 Sept 2026
fcc2fe0 -
Guard deploy and docs: systemd resource bounds (MemoryMax 2G img/audio/docs, 1G yt, 768M gateway/text/maps/food; TasksMax 256; Nice 5 for img, audio, docs, yt) and ReadWritePaths for the gateway's data/ (its guard.db); deploy.sh creates every app's data/ and checks each app loads the guard with its better-sqlite3 before restarting; the repo's nginx copies set X-Forwarded-For and CF-Connecting-IP from $remote_addr like the host (one hop, never a client's chain). README: the guard (callers, one address source, quotas and the default table, heavy work, uploads, ffmpeg, egress, the abuse log as pseudonymous under ADR-021, the challenge hook, report vs enforce, environment) and the new job boundsOpenVibers · 24 Sept 2026
ef14d55 -
Tool registry API (capability tools.tool.read, ADR-027): GET /api/v1/tools answers tools.tool-list@1 with schemas as $refs (filters ?family= ?execution= ?api= ?status= ?q=, comma lists; a bad value is 400 tools.query.invalid), GET /api/v1/tools/:id tools.tool@1 with its schemas embedded, GET /api/v1/tools/:id/schema { $schema, $id, $defs: { input, output } } that the $refs point at. Public and cacheable: Access-Control-Allow-Origin * for any origin (each app's own CORS rules are skipped for these paths, and even a 429 is readable), OPTIONS preflight, an ETag with 304 on If-None-Match, Cache-Control public, max-age=300, HEAD; an unknown id is 404 problem+json tools.tool.not_found, and a planned placeholder or a mirror says so. Counted by each app's existing /api/ limiter (the gateway's 120 a minute). The gateway answers for all 169 tools and adds a tool_registry readiness row (degraded, never a crash, when a descriptor fails the contracts); img, audio, docs, text, yt, maps and food answer the same routes for their own tools with their own live status (apps/_shared/tools/local.js: catalogue copy, code-default hosts, a tool unavailable while a program it needs is missing, checked every 30 s), which the gateway reads every minute. /api/catalog.json is unchanged. tools-api.test.js runs the gateway and all seven satellites: contract-valid list, tool and schema documents (the $ref resolves with a JSON Schema validator), ETag/304, CORS, preflight, 404 problems, filters, the limiter, the catalogue untouched, each satellite's own list and status (qpdf, poppler, libheif, ffmpeg and yt-dlp pointed at nothing) and the gateway picking those statuses up. README documents the routes, where descriptors live, how status is decided and the server enginesOpenVibers · 23 Sept 2026
4cc923e -
README: the host packages some tools need (qpdf, poppler-utils, libheif-examples + libheif-plugin-libde265, ffmpeg), what happens while one is missing (503 tools.unavailable, the page says so, /api/ready degraded), the new limits and variables (PDF_MAX_PAGES, PDF2IMG_MAX_PAGES, YT_MAX_DURATION, YT_MAX_FILESIZE_MB, YT_INFO_CONCURRENCY, NET_IPINFO_TOKEN, the *_PATH overrides), the readiness rows for them, and the registry consistency testOpenVibers · 23 Sept 2026
96a7467 -
Analytics comes from openvibe-shared/analytics (v1.4.0; retires C-80): every app pins openvibe-shared v1.4.0 (package.json and lockfile), the seven satellites require openvibe-shared/analytics instead of the hand-copied apps/_shared/analytics/, which is deleted. scripts/analytics-prune.js is a wrapper over openvibe-shared/analytics/prune-cli (resolved from an installed app, like better-sqlite3 via loadSqlite()), keeping --app and the discovery of apps/<app>/data/analytics.db as its targets hook; backups are now owner-only. apps/_shared/test/analytics.test.js tests the package. New with v1.4.0: a request with Sec-GPC: 1 or DNT: 1 is not recorded at all (no raw row, visitor hash, session id or rate counter); README notes itOpenVibers · 23 Sept 2026
5d1b423 -
Jobs publish their lifecycle to OpenVibe.Events: tools.job.created (submit or retry; actor the owner), tools.job.started (claim), tools.job.succeeded and tools.job.failed (tool error, timeout, or failed on restart), each validated against openvibe-contracts tools.job.*@1 and written to an event_outbox table in the satellite's jobs.db (openvibe-sdk createOutbox) in the same SQLite transaction as the state change, including claim(); the relay posts to EVENTS_URL/api/v1/events with the tools client's token (events.event.publish on openvibe.events). Payloads carry ids, type, owner (null for a browser session), state, attempts, times, result locations (index, mime, size, sha256, local or media_id) and the error with server paths and the job's file names removed; never inputs, file names, output data or sessions. Cancelled jobs, progress, requeues and sandbox app jobs are not announced. Inert without EVENTS_URL (EVENTS_PUBLISH=off or no OV_OAUTH_CLIENT_SECRET also keep it off): no table, nothing written. A failed outbox write rolls the transition back; a finish that cannot commit leaves the job running with its inputs for boot recovery. apps/_shared/test/job-events.test.js covers one event per transition, rollbacks, sandbox, cancel, retry, restart, leaks, contract validation and the relayOpenVibers · 23 Sept 2026
5f3c304 -
Jobs retention: referenced results are never pruned (PUT/DELETE /api/v1/jobs/:id/references/:ref, e.g. community:paste:p_123, owner-scoped, idempotent; a referenced job shows expires_at null), and the pruner no longer drops a job whose Media object Media keeps (retention hold 409 media.object.held, Media unreachable or not configured): the job is kept and looked at again 24 h laterOpenVibers · 23 Sept 2026
8b317eb -
Jobs: POST /api/v1/jobs/:id/retry retries a failed job as a new job with the same type, input and files (retry_of / retried_by link them); owner-scoped (tools.job.create for principals), idempotent (a second call answers 200 Idempotent-Replayed with the same retry), 409 tools.job.not_failed for anything but a failed job, 410 tools.job.inputs_goneOpenVibers · 23 Sept 2026
2aff45d -
SSRF: the network tools refuse internal targets. apps/_shared/egress.js (from OpenVibe.Events) checks every resolved address after DNS (loopback, RFC 1918, link-local and 169.254.169.254, CGNAT, 0.0.0.0/8, multicast, documentation/benchmark, ULA/site-local v6, v4-mapped/NAT64/6to4/Teredo wrapping those) and dials only the checked address (IP literal + SNI for sockets, a pinned lookup for HTTP, so no rebinding)OpenVibers · 23 Sept 2026
f9a1441 -
Analytics within ADR-021 on every satellite: apps/_shared/analytics replaces the openvibe-shared tracker (no IP, user id or city in raw events; route templates, referer origins, user-agent classes, rotating session ids); raw events pruned after 30 days on a 24 h timer, rollups keptOpenVibers · 23 Sept 2026
533c9a3 -
Metrics and truthful readiness on the gateway and every satellite (Track O): openvibe-shared v1.3.0; GET /metrics for direct loopback callers only (route templates, proxy:<app> on the gateway, tools_jobs{app,state}); GET /api/ready with required vs optional checks (job store, job runtime, writable dirs; Network key, binaries, Media results, satellites and Community optional → degraded); nginx 404s /metricsOpenVibers · 23 Sept 2026
70e9a19 -
Docs: jobs API, durability, owner scoping, Media results and their grants, canonical hosts, registry catalog, tests; tools.job.* capability and service manifest proposalsOpenVibers · 23 Sept 2026
f5d27df -
openvibe-shared is the pinned OpenVibe.Shared v1.0.0 release in every app; the vendored copy and the deploy rsync are goneOpenVibers · 23 Sept 2026
4773f7b -
YT: periodic upstream self-check, status in /api/health and a banner while YouTube refuses the server; README explains the two ways outOpenVibers · 18 Sept 2026
073c6ff -
README: registry, host roles, server-rendered apex, deploy scriptOpenVibers · 18 Sept 2026
868e4f5 -
Gateway auth: silent SSO (prompt=none), ov_sso_hint cookie, Network URLs as next targetsOpenVibers · 18 Sept 2026
ae15ae4 -
Initial OpenVibe releaseOpenVibers · 17 Aug 2026
43d43c5