Published in openvibe-contracts v0.33.0 (docs/adr/ADR-027-tools-platform-api.md), rendered as is.

ADR-027: Tools platform API

Status: Accepted 2026-09-23. Contracts in openvibe-contracts v0.33.0; the registry and run routes are planned until OpenVibe.Tools serves them.

Context and current evidence

The owner asked on 2026-09-23 for every tool to be open, modular, reachable through an API and the SDK, efficient, protected against abuse, and used across the other repositories. The survey of OpenVibe.Tools that day found:

Decision

One descriptor per tool, one run API

Refusals before the tool runs are problem+json. run-request.v1.json lists the codes.

Browser-only tools may get server engines

A pure transform whose engine also runs in Node gets an opt-in server engine for the API: JSON, minify and beautify, case, slug, hash, base64 and the like. Its descriptor then says execution: client and api: true. The page stays browser-only, so "nothing leaves your browser" stays true for people using the page. A tool without such an engine says api: false.

YouTube downloader is page-only

yt stays a page for people. It is not in the run API or the SDK, because of YouTube's terms and the legal exposure. Its descriptor says api: false and run: null.

Callers, tiers and quotas

Network probes need tools.net.probe

Port checks, ping, traceroute, mtr, latency and bulk header or TLS checks send traffic to a host the caller chose. Through the API and the SDK they need the capability tools.net.probe, whose visibility is partner. Network grants it to a developer project only when staff add it to that project's allowance by hand, never through a default or sandbox allowance. First-party services hold it through their own grants. People keep the probe pages, which have a per-target throttle.

A descriptor with egress: true either refuses anonymous callers or declares limits.perTargetPerMinute: runs per minute against one target, across all callers. A probe tool always has egress: true and auth.anonymous: false. A client tool never fetches.

Abuse log

Tools records refused and throttled runs, and runs that trip an abuse rule. Each row holds:

No raw IP is stored anywhere. The salt rotates daily and is never kept after its day, so an old hash cannot be tied back to an address, not even by trying every IPv4 address. Rows are kept 30 days. Under ADR-021 this is pseudonymous security data, not analytics. Its only use is acting on abuse: throttling, blocking a token or an app, reporting to the owner. It is never joined into analytics. Subject ids may appear because acting on a token or an app needs them, which ADR-021's analytics rule does not cover.

Legacy endpoints get deprecation headers

/api/process (and its /direct, /multi and /info variants), /api/net/* and /api/dev/* keep working. Each answer carries:

A descriptor lists these routes in run.legacy, which gives the mapping. Removing them after the sunset is a later decision, informed by how much they are still used.

Honest status

A tool whose engine is missing on the host has status unavailable: it is listed, its runs are refused with 503 tools.tool.unavailable, and its page says so. PDF protection becomes real (qpdf, AES-256) and PDF to image uses pdftoppm. They stay unavailable until qpdf and poppler-utils are deployed. Probe tools that only do a TCP ping describe themselves as that.

Alternatives considered

Migration consequences

In order:

  1. Contracts v0.33.0 (this ADR).
  2. The Tools registry and descriptors.
  3. The shared guard (tiers, quotas, semaphores, upload sniffing, ffmpeg hardening, egress throttles, the abuse log), first in report mode.
  4. Worker isolation, so pdf-lib and sharp stop blocking the event loop.
  5. The run API, the gateway jobs facade and the legacy headers.
  6. Network grants and the sandbox allowance.
  7. openvibe-sdk tools and the jobs client's retry and references.
  8. Callers move over: Live kiosk page titles, Chat MP3 conversion, Community "save as paste", Codes docs, the Search index, the Network launcher's recent tools.

tools.tool.read, tools.tool.run and tools.net.probe become active in the contracts release after Tools serves their routes.

Rollback

Every new route is additive. Turning the run API off leaves the pages and the legacy routes as they were. The guard starts in report mode, and enforcement is a switch. Deprecation headers are informational. Deleting the abuse log's table removes it completely, and it holds no raw data to leak.

Acceptance tests