ToolDescriptor tools.tool@1
Generated at from
openvibe-contracts v0.33.0 and
openvibe-sdk v0.5.0.
- Version
- 1.0.0
- Owner
- tools
- Visibility
- public
- Status
- active
- Compatibility
- backward
- Decision
- ADR-027
- Schema
https://openvibe.network/contracts/tools/tool.v1.json
One tool on openvibe.tools as its registry describes it (GET /api/v1/tools/:id, and each item of GET /api/v1/tools; capability tools.tool.read; ADR-027). There is one descriptor per catalogue tool (GET /api/catalog.json tools[].id), built from the tool's own code, so its page, the run API, openvibe-sdk/tools, the OpenAPI document and the docs all read the same facts. EXECUTION is where the tool's engine runs for its page: client (in the browser; nothing leaves it), sync (a server request answered inline) or job (an asynchronous job on a satellite, tools.job@1). API says whether POST /api/v1/tools/{id}/run exposes the tool. A client tool has api true only when it also has a server engine (a pure transform that runs in Node), and its page stays browser-only. A page-only tool (yt) has api false and run null. A job tool's run creates a job of run.job.type whose input is { ...input, ...run.job.preset, tool: run.job.operation } (the preset and the operation always win). INPUT is the JSON Schema (2020-12) that a run request's input must match, embedded or as { $ref: https://openvibe.tools/api/v1/tools/{id}/schema#/$defs/input }. GET /api/v1/tools/:id/schema answers { $schema, $id, $defs: { input, output } }, and the list uses the $ref form. RULES this schema enforces: api false has no run, and api true has a run and an input; an API job tool names its job, and only job tools name one; an API tool whose output is a file runs as a job (its results are served as job files); a tools.net.probe tool fetches (egress) and is never anonymous; an anonymous egress tool has a per-target throttle (limits.perTargetPerMinute); a client tool never fetches; an unavailable tool says why (statusReason); JSON output has a schema. contracts.tools.checkDescriptor(d) also checks what depends on the id (run.path, $ref targets) and files.min <= files.max.
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
id | string | yes | The tool's catalogue id, which is its subdomain label (png, jsminify, dns, pdf2jpg). It never changes. |
|
family | string | yes | The catalogue family: net, dev, img, audio, docs, text, media, places, pastes… |
|
name | string | yes |
| |
summary | string | yes | One plain sentence: what the tool does. |
|
status | enum | yes | stable: works, and its input and output only grow. beta: works; input or output may still change in a minor. preview: works with known gaps (limits or output not final). unavailable: listed, but runs are refused with 503 tools.tool.unavailable and the page says so (statusReason). |
|
statusReason | string | Why the status is what it is, for people (e.g. 'needs qpdf on the host'). Required when unavailable. |
| |
execution | enum | yes | Where the engine runs for the tool's page: client (the browser), sync (a server request answered inline), job (an asynchronous job). |
|
api | boolean | yes | POST /api/v1/tools/{id}/run exposes the tool. false for a client tool without a server engine and for page-only tools (yt). | |
run | object | null | yes | How to call it; null when api is false. | |
input | one of | yes | JSON Schema (2020-12) of the run request's input: embedded (an object schema), or { $ref } to $defs/input of GET /api/v1/tools/:id/schema. null only for a tool without an API. | |
files | object | null | yes | The files a run takes (multipart parts, or tools.run-request@1 files references); null when it takes none. | |
output | object | yes |
| |
output.kind | enum | yes | json: result.data; text: result.text; file or files: result.files (job result files). |
|
output.schema | one of | JSON Schema of result.data (kind json): embedded, or { $ref } to $defs/output of GET /api/v1/tools/:id/schema. | ||
output.mime | array of string | Media types the result files can have (kind file or files). |
| |
limits | object | yes |
| |
limits.timeoutMs | integer | yes | A run (or its job) longer than this fails with tools.job.timeout or 504. |
|
limits.maxDurationSec | integer | Longest audio or video input. |
| |
limits.maxPixels | integer | Largest image input (width × height). |
| |
limits.maxPages | integer | Most PDF pages. |
| |
limits.maxInputBytes | integer | Largest input as JSON (text to transform, lists of hosts…). |
| |
limits.perTargetPerMinute | integer | Egress tools: most runs per minute against one target host or address, across all callers. |
| |
auth | object | yes | Caller tiers: anonymous < session < user < app/service. |
|
auth.anonymous | boolean | yes | true: a caller with no token and no browser session may run it (keyed by IP, IPv6 by /64). false: a browser session (the ov_tools_jobs cookie), a signed-in person or a token is needed. | |
auth.capability | enum | yes | What an app or service token must hold. tools.tool.run is public. tools.net.probe (partner) covers network probes: only principals holding it run these through the API; people use their pages, which have a per-target throttle. |
|
quotaClass | string | yes | The quota bucket a run counts against, with allowances per caller tier. Names describe the work, never a tier or a price (tools-run, tools-job, tools-probe, tools-fetch…), so a paid tier later adds allowances, not names. |
|
cost | integer | yes | Relative weight of one run within its quota class (1 = a cheap lookup or transform). Quotas count weight, not requests. |
|
egress | boolean | yes | The server fetches a host or URL the caller chose (DNS, WHOIS, headers, Open Graph, ports…), always through the SSRF guard. | |
hosts | array of string | yes | The tool's public hostnames, canonical first (png.openvibe.tools, a custom domain…); empty for a tool that lives on another service. |
|
docs | string | yes | Where a person reads about the tool. |
|
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: dns-sync-egress
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Valid: jsonminify-client-engine
{
"id": "jsonminify",
"family": "dev",
"name": "JSON Minifier",
"summary": "Strip the whitespace out of JSON.",
"status": "stable",
"execution": "client",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/jsonminify/run",
"job": null
},
"input": {
"type": "object",
"required": [
"text"
],
"additionalProperties": false,
"properties": {
"text": {
"type": "string",
"maxLength": 1048576
}
}
},
"files": null,
"output": {
"kind": "text"
},
"limits": {
"timeoutMs": 5000,
"maxInputBytes": 1048576
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-run",
"cost": 1,
"egress": false,
"hosts": [
"json-minifier.openvibe.tools",
"jsonminify.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/jsonminify"
}Valid: logo-client-only
{
"id": "logo",
"family": "text",
"name": "Logo Maker",
"summary": "Make a text logo in the browser.",
"status": "stable",
"execution": "client",
"api": false,
"run": null,
"input": null,
"files": null,
"output": {
"kind": "file",
"mime": [
"image/png",
"image/svg+xml"
]
},
"limits": {
"timeoutMs": 1000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-run",
"cost": 1,
"egress": false,
"hosts": [
"logo.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/logo"
}Valid: png-job
{
"id": "png",
"family": "img",
"name": "PNG Converter",
"summary": "Convert JPG, WebP, AVIF, HEIC, GIF, BMP, TIFF and more to PNG.",
"status": "stable",
"execution": "job",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/png/run",
"job": {
"type": "img.process",
"operation": "convert",
"preset": {
"format": "png"
}
},
"legacy": [
"POST /api/process",
"POST /api/process/direct"
]
},
"input": {
"type": "object",
"additionalProperties": false,
"properties": {
"compressionLevel": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 16384
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"image/*"
],
"maxBytes": 52428800
},
"output": {
"kind": "file",
"mime": [
"image/png"
]
},
"limits": {
"timeoutMs": 120000,
"maxPixels": 100000000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 5,
"egress": false,
"hosts": [
"png.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/png"
}Valid: port-probe
{
"id": "port",
"family": "net",
"name": "Port Checker",
"summary": "Check whether TCP ports on a host are open.",
"status": "beta",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/port/run",
"job": null,
"legacy": [
"GET /api/net/port/:target"
]
},
"input": {
"type": "object",
"required": [
"host",
"ports"
],
"additionalProperties": false,
"properties": {
"host": {
"type": "string",
"maxLength": 253
},
"ports": {
"type": "array",
"minItems": 1,
"maxItems": 20,
"items": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
}
}
},
"files": null,
"output": {
"kind": "json",
"schema": {
"type": "object",
"properties": {
"results": {
"type": "array"
}
}
}
},
"limits": {
"timeoutMs": 15000,
"perTargetPerMinute": 6
},
"auth": {
"anonymous": false,
"capability": "tools.net.probe"
},
"quotaClass": "tools-probe",
"cost": 5,
"egress": true,
"hosts": [
"port.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/port"
}Valid: protectpdf-unavailable
{
"id": "protectpdf",
"family": "docs",
"name": "Protect PDF",
"summary": "Put a password on a PDF (AES-256).",
"status": "unavailable",
"statusReason": "Needs qpdf on the host; not deployed yet.",
"execution": "job",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/protectpdf/run",
"job": {
"type": "docs.process",
"operation": "protect"
}
},
"input": {
"type": "object",
"required": [
"password"
],
"properties": {
"password": {
"type": "string",
"minLength": 1,
"maxLength": 128
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"application/pdf"
],
"maxBytes": 104857600
},
"output": {
"kind": "file",
"mime": [
"application/pdf"
]
},
"limits": {
"timeoutMs": 300000,
"maxPages": 2000
},
"auth": {
"anonymous": false,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 10,
"egress": false,
"hosts": [
"protectpdf.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/protectpdf"
}Valid: yt-page-only
{
"id": "yt",
"family": "media",
"name": "YouTube Downloader",
"summary": "Save a YouTube video or its audio.",
"status": "stable",
"execution": "job",
"api": false,
"run": null,
"input": null,
"files": null,
"output": {
"kind": "file",
"mime": [
"video/mp4",
"audio/mpeg"
]
},
"limits": {
"timeoutMs": 900000,
"maxDurationSec": 3600,
"perTargetPerMinute": 20
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-download",
"cost": 50,
"egress": true,
"hosts": [
"youtube-downloader.openvibe.tools",
"yt.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/yt"
}Rejected: anonymous-egress-without-throttle
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: api-false-with-run
{
"id": "png",
"family": "img",
"name": "PNG Converter",
"summary": "Convert JPG, WebP, AVIF, HEIC, GIF, BMP, TIFF and more to PNG.",
"status": "stable",
"execution": "job",
"api": false,
"run": {
"method": "POST",
"path": "/api/v1/tools/png/run",
"job": {
"type": "img.process",
"operation": "convert",
"preset": {
"format": "png"
}
},
"legacy": [
"POST /api/process",
"POST /api/process/direct"
]
},
"input": {
"type": "object",
"additionalProperties": false,
"properties": {
"compressionLevel": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 16384
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"image/*"
],
"maxBytes": 52428800
},
"output": {
"kind": "file",
"mime": [
"image/png"
]
},
"limits": {
"timeoutMs": 120000,
"maxPixels": 100000000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 5,
"egress": false,
"hosts": [
"png.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/png"
}Rejected: api-job-tool-without-job
{
"id": "png",
"family": "img",
"name": "PNG Converter",
"summary": "Convert JPG, WebP, AVIF, HEIC, GIF, BMP, TIFF and more to PNG.",
"status": "stable",
"execution": "job",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/png/run",
"job": null,
"legacy": [
"POST /api/process",
"POST /api/process/direct"
]
},
"input": {
"type": "object",
"additionalProperties": false,
"properties": {
"compressionLevel": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 16384
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"image/*"
],
"maxBytes": 52428800
},
"output": {
"kind": "file",
"mime": [
"image/png"
]
},
"limits": {
"timeoutMs": 120000,
"maxPixels": 100000000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 5,
"egress": false,
"hosts": [
"png.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/png"
}Rejected: api-true-without-input
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": null,
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: api-true-without-run
{
"id": "png",
"family": "img",
"name": "PNG Converter",
"summary": "Convert JPG, WebP, AVIF, HEIC, GIF, BMP, TIFF and more to PNG.",
"status": "stable",
"execution": "job",
"api": true,
"run": null,
"input": {
"type": "object",
"additionalProperties": false,
"properties": {
"compressionLevel": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 16384
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"image/*"
],
"maxBytes": 52428800
},
"output": {
"kind": "file",
"mime": [
"image/png"
]
},
"limits": {
"timeoutMs": 120000,
"maxPixels": 100000000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 5,
"egress": false,
"hosts": [
"png.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/png"
}Rejected: client-tool-fetches
{
"id": "jsonminify",
"family": "dev",
"name": "JSON Minifier",
"summary": "Strip the whitespace out of JSON.",
"status": "stable",
"execution": "client",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/jsonminify/run",
"job": null
},
"input": {
"type": "object",
"required": [
"text"
],
"additionalProperties": false,
"properties": {
"text": {
"type": "string",
"maxLength": 1048576
}
}
},
"files": null,
"output": {
"kind": "text"
},
"limits": {
"timeoutMs": 5000,
"maxInputBytes": 1048576,
"perTargetPerMinute": 10
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-run",
"cost": 1,
"egress": true,
"hosts": [
"json-minifier.openvibe.tools",
"jsonminify.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/jsonminify"
}Rejected: file-output-answered-inline
{
"id": "png",
"family": "img",
"name": "PNG Converter",
"summary": "Convert JPG, WebP, AVIF, HEIC, GIF, BMP, TIFF and more to PNG.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/png/run",
"job": null,
"legacy": [
"POST /api/process",
"POST /api/process/direct"
]
},
"input": {
"type": "object",
"additionalProperties": false,
"properties": {
"compressionLevel": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 16384
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"image/*"
],
"maxBytes": 52428800
},
"output": {
"kind": "file",
"mime": [
"image/png"
]
},
"limits": {
"timeoutMs": 120000,
"maxPixels": 100000000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 5,
"egress": false,
"hosts": [
"png.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/png"
}Rejected: input-schema-not-an-object
{
"id": "jsonminify",
"family": "dev",
"name": "JSON Minifier",
"summary": "Strip the whitespace out of JSON.",
"status": "stable",
"execution": "client",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/jsonminify/run",
"job": null
},
"input": {
"type": "string"
},
"files": null,
"output": {
"kind": "text"
},
"limits": {
"timeoutMs": 5000,
"maxInputBytes": 1048576
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-run",
"cost": 1,
"egress": false,
"hosts": [
"json-minifier.openvibe.tools",
"jsonminify.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/jsonminify"
}Rejected: json-output-without-schema
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json"
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: mime-with-parameters
{
"id": "png",
"family": "img",
"name": "PNG Converter",
"summary": "Convert JPG, WebP, AVIF, HEIC, GIF, BMP, TIFF and more to PNG.",
"status": "stable",
"execution": "job",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/png/run",
"job": {
"type": "img.process",
"operation": "convert",
"preset": {
"format": "png"
}
},
"legacy": [
"POST /api/process",
"POST /api/process/direct"
]
},
"input": {
"type": "object",
"additionalProperties": false,
"properties": {
"compressionLevel": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 16384
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"image/png; charset=binary"
],
"maxBytes": 52428800
},
"output": {
"kind": "file",
"mime": [
"image/png"
]
},
"limits": {
"timeoutMs": 120000,
"maxPixels": 100000000
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 5,
"egress": false,
"hosts": [
"png.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/png"
}Rejected: probe-anonymous
{
"id": "port",
"family": "net",
"name": "Port Checker",
"summary": "Check whether TCP ports on a host are open.",
"status": "beta",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/port/run",
"job": null,
"legacy": [
"GET /api/net/port/:target"
]
},
"input": {
"type": "object",
"required": [
"host",
"ports"
],
"additionalProperties": false,
"properties": {
"host": {
"type": "string",
"maxLength": 253
},
"ports": {
"type": "array",
"minItems": 1,
"maxItems": 20,
"items": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
}
}
},
"files": null,
"output": {
"kind": "json",
"schema": {
"type": "object",
"properties": {
"results": {
"type": "array"
}
}
}
},
"limits": {
"timeoutMs": 15000,
"perTargetPerMinute": 6
},
"auth": {
"anonymous": true,
"capability": "tools.net.probe"
},
"quotaClass": "tools-probe",
"cost": 5,
"egress": true,
"hosts": [
"port.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/port"
}Rejected: probe-without-egress
{
"id": "port",
"family": "net",
"name": "Port Checker",
"summary": "Check whether TCP ports on a host are open.",
"status": "beta",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/port/run",
"job": null,
"legacy": [
"GET /api/net/port/:target"
]
},
"input": {
"type": "object",
"required": [
"host",
"ports"
],
"additionalProperties": false,
"properties": {
"host": {
"type": "string",
"maxLength": 253
},
"ports": {
"type": "array",
"minItems": 1,
"maxItems": 20,
"items": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
}
}
},
"files": null,
"output": {
"kind": "json",
"schema": {
"type": "object",
"properties": {
"results": {
"type": "array"
}
}
}
},
"limits": {
"timeoutMs": 15000,
"perTargetPerMinute": 6
},
"auth": {
"anonymous": false,
"capability": "tools.net.probe"
},
"quotaClass": "tools-probe",
"cost": 5,
"egress": false,
"hosts": [
"port.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/port"
}Rejected: quota-class-without-prefix
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: ref-not-a-string
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": 42
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: run-get-method
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "GET",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: sync-tool-with-job
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": {
"type": "net.lookup",
"operation": "dns"
},
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: unavailable-without-reason
{
"id": "protectpdf",
"family": "docs",
"name": "Protect PDF",
"summary": "Put a password on a PDF (AES-256).",
"status": "unavailable",
"execution": "job",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/protectpdf/run",
"job": {
"type": "docs.process",
"operation": "protect"
}
},
"input": {
"type": "object",
"required": [
"password"
],
"properties": {
"password": {
"type": "string",
"minLength": 1,
"maxLength": 128
}
}
},
"files": {
"min": 1,
"max": 1,
"accept": [
"application/pdf"
],
"maxBytes": 104857600
},
"output": {
"kind": "file",
"mime": [
"application/pdf"
]
},
"limits": {
"timeoutMs": 300000,
"maxPages": 2000
},
"auth": {
"anonymous": false,
"capability": "tools.tool.run"
},
"quotaClass": "tools-job",
"cost": 10,
"egress": false,
"hosts": [
"protectpdf.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/protectpdf"
}Rejected: unknown-capability
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.job.create"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: unknown-status
{
"id": "dns",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "deprecated",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Rejected: uppercase-id
{
"id": "DNS",
"family": "net",
"name": "DNS Lookup",
"summary": "Look up A, AAAA, MX, TXT, NS, CNAME and other records for a domain.",
"status": "stable",
"execution": "sync",
"api": true,
"run": {
"method": "POST",
"path": "/api/v1/tools/dns/run",
"job": null,
"legacy": [
"GET /api/net/dns/:target"
]
},
"input": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/input"
},
"files": null,
"output": {
"kind": "json",
"schema": {
"$ref": "https://openvibe.tools/api/v1/tools/dns/schema#/$defs/output"
}
},
"limits": {
"timeoutMs": 10000,
"maxInputBytes": 1024,
"perTargetPerMinute": 30
},
"auth": {
"anonymous": true,
"capability": "tools.tool.run"
},
"quotaClass": "tools-fetch",
"cost": 1,
"egress": true,
"hosts": [
"dns.openvibe.tools"
],
"docs": "https://openvibe.tools/tool/dns"
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('tools.tool@1', value); // { valid, errors: [{ path, message }] }