openvibers/openvibe.contracts Commits
v0.63.0: project usage rollups (roadmap WS-N task 4, ADR-014). New common.usage-recorded@1: one closed hour (or day) of one developer project's use of one capability in one environment, as the owning service counted it: project_id, env, capability, optional dimension (job type or tool), unit, window, window_start/window_end, quantity, errors, error_codes (up to 20) and samples (up to 10 recent failures: time, code, status, trace id, job/event/run/object id), plus revision; totals, not deltas, so a re-sent window replaces the earlier one; never a subject, app, address, session, input or message. New event types tools.usage.recorded (a Tools satellite's hour of a project's jobs, per tools.job.create or tools.tool.run) and events.usage.recorded (events.app.publish in events with refusals as errors; events.app.subscribe in deliveries with failed attempts as errors), both common.usage-recorded@1; the Tools and Events manifests produce them and Network consumes both. New network.project-usage-result@1 for GET /api/v1/projects/:project/usage on Network (daily rows, totals, recorded quotas with what their window used, errors by code and recent sampled failures). Fixtures; npm test checks each <service>.usage.recorded is the common payload, owned by its service and consumed by Network, and that a rollup carries no identity and at most ten samples. Additive (compat vs v0.62.0: no breaking changes).
Changes
@@@ -6,6 +6,16 @@ the notes were in the tag and commit messages (`git tag -n1`).## Unreleased++## 0.63.0 — 2026-09-26++++**Project usage rollups** (roadmap WS-N task 4, ADR-014): what feeds the per-project dashboards on OpenVibe.Codes.++- **New `common.usage-recorded@1`**: one closed window (an hour or a day) of one developer project's use of one capability in one environment, as the owning service counted it: `project_id`, `env`, `capability`, an optional `dimension` (a job type or tool id), `unit`, `window`, `window_start`, `window_end`, `quantity`, `errors`, `error_codes` (up to 20) and `samples` (up to 10 recent failures: time, code, status, trace id and a job, event, run or object id), plus `revision`. Totals, not deltas: a later rollup with the same key replaces the earlier one. It never names who did the work (no subject, app, address, session, input or message), and no producer emits one per request.++- **New event types `tools.usage.recorded`** (a Tools satellite's hour of a project's jobs, unit `jobs`, per `tools.job.create` or `tools.tool.run` and job type or tool) **and `events.usage.recorded`** (Events: `events.app.publish` in `events`, refusals as errors; `events.app.subscribe` in `deliveries`, failed webhook attempts as errors). Both payloads are `common.usage-recorded@1`; envelope subject `{ type: project, id: <project_id> }`, visibility `internal`, priority `low`. The Tools and Events manifests produce them; Network consumes both.++- **New `network.project-usage-result@1`**: what `GET /api/v1/projects/:project/usage?days=&env=` on Network answers a project's owner, admins and staff: daily rows and range totals per service, capability, unit and environment, the project's recorded quotas with what their current window used, and errors by code with the recent sampled failures.++- `npm test` checks that each `<service>.usage.recorded` is the common payload, owned by its service and consumed by Network, and that a rollup carries no identity and at most ten samples.++++Additive.++## 0.62.0 — 2026-09-26**Operator alerts** (roadmap WS-H task 11; the delivery path that Host's Prometheus alerts lacked).@@@ -95,6 +95,10 @@ const r = contracts.validate(`${env.event_type}@${env.version}`, env.payload);**Redaction (ADR-026).** Any event may carry `payload.redacts` (`events.redaction-directive@1`), shaped `{ event_ids?, subject_type?, subject_ids? }` with up to 1000 ids each, to take back the producer's own earlier events. OpenVibe.Events rewrites each target into a tombstone at its original seq: `{ redacted: true, redacted_at, redacted_by }`, with the producer itself as actor. Naming another source's event refuses the whole batch with 403 `events.redaction_not_allowed`. A malformed directive gets 422 `events.invalid_redaction`. `chat.message.deleted` always carries one. Browsers are replayed only the `public` events of the last `REALTIME_PUBLIC_REPLAY_SECONDS` (default 300); an older cursor gets `event: gap` with reason `public_window`.++## Project usage rollups (v0.63)++++The services that own a developer capability count each project's use of it and report one rollup per closed hour, never one event per request (roadmap WS-N task 4). Every `<service>.usage.recorded` event carries `common.usage-recorded@1`: project, environment, capability, optional dimension (job type, tool), unit, window, quantity, errors, errors by code and up to ten sampled failures with their trace ids. Emitted today: `tools.usage.recorded` (jobs) and `events.usage.recorded` (published events, webhook deliveries). OpenVibe.Network adds them up per project and day and answers `GET /api/v1/projects/:project/usage` (`network.project-usage-result@1`) to the project's owner and admins; OpenVibe.Codes shows it as the project's usage page. A rollup is totals, not a delta: the latest one for a key replaces the earlier, so a producer may re-send a window safely.++## Event delivery signaturesOpenVibe.Events POSTs each webhook delivery as `{ "event": <events.event-envelope@1>, "seq": n }`, keyed with the subscription secret:@@@ -210,6 +210,16 @@"status": "active","adr": "ADR-022"},++ {++ "id": "common.usage-recorded",++ "version": "1.0.0",++ "owner": "network",++ "schema": "common/usage-recorded.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-014"++ },{"id": "media.file-upload","version": "1.0.0",@@@ -2249,6 +2259,26 @@"status": "active","adr": "ADR-022"},++ {++ "id": "tools.usage.recorded",++ "version": "1.0.0",++ "owner": "tools",++ "schema": "events/payloads/tools.usage.recorded.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-014"++ },++ {++ "id": "events.usage.recorded",++ "version": "1.0.0",++ "owner": "events",++ "schema": "events/payloads/events.usage.recorded.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-014"++ },{"id": "live.stream.started","version": "1.0.0",@@@ -2513,6 +2543,16 @@"status": "active","adr": "ADR-005"},++ {++ "id": "network.project-usage-result",++ "version": "1.0.0",++ "owner": "network",++ "schema": "network/project-usage-result.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-014"++ },{"id": "network.staff-list-result","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,70 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/common/usage-recorded.v1.json",++ "title": "UsageRecorded",++ "description": "common.usage-recorded@1 (roadmap WS-N task 4, ADR-014): one rollup of a developer project's use of one capability in one environment over one closed window (an hour or a day), as the service that owns the capability counted it. The payload of every <service>.usage.recorded event; OpenVibe.Network adds them up per project and day for the project's dashboard on OpenVibe.Codes. The producer counts in the transaction that does its own accounting (a job's end, a stored event, a delivery attempt) and writes the rollup to its outbox after the window has closed: never one event per request. Totals, not deltas: a later event with the same key (source, project_id, env, capability, dimension, unit, window_start) replaces the earlier one, and a lower revision never replaces a higher one. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor the producing service. Never carries a subject id, an address, a session, a request's input or content, or a file name.",++ "type": "object",++ "required": ["project_id", "env", "capability", "unit", "window", "window_start", "window_end", "quantity", "errors"],++ "additionalProperties": false,++ "properties": {++ "project_id": { "type": "string", "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$", "description": "The developer project whose app token did the work." },++ "env": { "enum": ["sandbox", "production"], "description": "The environment of that app token." },++ "capability": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$",++ "maxLength": 80,++ "description": "The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe."++ },++ "dimension": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "pattern": "^[a-z0-9][a-z0-9_.:-]*$",++ "not": { "pattern": "^(usr|gst|app|mod|svc|job|evt|req)_" },++ "description": "Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job."++ },++ "unit": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$",++ "description": "What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit."++ },++ "window": { "enum": ["hour", "day"], "description": "The length of the window." },++ "window_start": { "type": "string", "format": "date-time", "description": "UTC, on the hour (midnight for a day)." },++ "window_end": { "type": "string", "format": "date-time", "description": "window_start plus the window, exclusive." },++ "quantity": { "type": "integer", "minimum": 0, "description": "Units used in the window, by work that succeeded and work that failed alike." },++ "errors": {++ "type": "integer",++ "minimum": 0,++ "description": "Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity."++ },++ "error_codes": {++ "type": "object",++ "maxProperties": 20,++ "propertyNames": { "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$", "maxLength": 80 },++ "additionalProperties": { "type": "integer", "minimum": 1 },++ "description": "The errors by problem code (at most 20 codes; the rest are only in errors)."++ },++ "samples": {++ "type": "array",++ "maxItems": 10,++ "description": "The last failures of the window, newest first, so a developer can find them in their own logs.",++ "items": {++ "type": "object",++ "required": ["at", "code"],++ "additionalProperties": false,++ "properties": {++ "at": { "type": "string", "format": "date-time" },++ "code": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$", "maxLength": 80 },++ "status": { "type": "integer", "minimum": 100, "maximum": 599, "description": "The HTTP status the failure was answered with, when there was one." },++ "trace_id": { "type": "string", "pattern": "^[0-9a-f]{32}$", "description": "The W3C trace id of the request (or event) that failed." },++ "ref": {++ "type": "string",++ "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject."++ }++ }++ }++ },++ "revision": { "type": "integer", "minimum": 1, "description": "1 when absent. A producer that re-emits a window with corrected totals raises it." }++ }++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/events.usage.recorded.v1.json",++ "title": "EventsUsageRecordedPayload",++ "description": "events.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Events server/usage.js). One hour of a developer project's use of OpenVibe.Events in one environment: events.app.publish in unit events (quantity counts the events stored; errors the publish requests refused with a problem, such as 429 events.quota_exceeded or 403 events.type_not_allowed) and events.app.subscribe in unit deliveries (quantity counts webhook delivery attempts to the project's subscriptions; errors the attempts without a 2xx, as events.delivery.http_<status>, events.delivery.timeout or events.delivery.failed). Counted in the transaction that stores the events or records the attempt (a refusal right after it is answered); Events stores the rollup as its own event after the hour closes, in the same transaction that marks it sent. The payload is common.usage-recorded@1. Envelope: source events, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:events.",++ "$ref": "../../common/usage-recorded.v1.json"++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/tools.usage.recorded.v1.json",++ "title": "ToolsUsageRecordedPayload",++ "description": "tools.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Tools apps/_shared/jobs/usage.js). One hour of a developer project's jobs on one Tools satellite, per capability (tools.job.create for POST /api/v1/jobs, tools.tool.run for a tool run) and job type or tool (dimension), in unit jobs: quantity counts the jobs that ended (succeeded or failed; a cancelled job is not counted), errors the failed ones, by code, with the last failures' job ids and trace ids. Counted in the transaction that records a job's end; written to the satellite's outbox after the hour closes. Only jobs of developer-app tokens (they carry a project) are counted; sandbox jobs are counted under env sandbox. The payload is common.usage-recorded@1. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:tools.",++ "$ref": "../../common/usage-recorded.v1.json"++}nnew file mode 100644@@@ -0,0 +1,118 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/network/project-usage-result.v1.json",++ "title": "ProjectUsageResult",++ "description": "network.project-usage-result@1 (roadmap WS-N task 4, ADR-014): what GET /api/v1/projects/:project/usage?days=&env= on OpenVibe.Network answers a project's owner or admin (or staff): the project's usage per day, service, capability and unit, added up from the <service>.usage.recorded rollups (common.usage-recorded@1) the owning services emit after each hour closes; the project's recorded quotas with what the current window has used; and its recent failures with their codes and trace ids. Counts only, never who did what: no subject id, address, input or content.",++ "type": "object",++ "required": ["project_id", "env", "range", "generated_at", "last_recorded_at", "freshness", "totals", "daily", "quotas", "errors"],++ "additionalProperties": false,++ "$defs": {++ "service": { "type": "string", "pattern": "^[a-z][a-z0-9-]{1,39}$" },++ "capability": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$", "maxLength": 80 },++ "unit": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,31}$" },++ "env": { "enum": ["sandbox", "production"] },++ "code": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$", "maxLength": 80 },++ "count": { "type": "integer", "minimum": 0 }++ },++ "properties": {++ "project_id": { "type": "string", "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$" },++ "env": { "enum": ["all", "sandbox", "production"], "description": "The environments counted (the env query parameter; all by default)." },++ "range": {++ "type": "object",++ "required": ["days", "from", "to"],++ "additionalProperties": false,++ "properties": {++ "days": { "type": "integer", "minimum": 1, "maximum": 90 },++ "from": { "type": "string", "format": "date", "description": "First UTC day counted." },++ "to": { "type": "string", "format": "date", "description": "Last UTC day counted (today)." }++ }++ },++ "generated_at": { "type": "string", "format": "date-time" },++ "last_recorded_at": { "type": ["string", "null"], "format": "date-time", "description": "When the newest rollup for this project arrived; null before the first." },++ "freshness": { "type": "string", "maxLength": 300, "description": "How current the numbers are, in words (rollups arrive after each hour closes)." },++ "totals": {++ "type": "array",++ "description": "The whole range per service, capability, unit and environment.",++ "items": {++ "type": "object",++ "required": ["service", "capability", "unit", "env", "quantity", "errors"],++ "additionalProperties": false,++ "properties": {++ "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" }, "unit": { "$ref": "#/$defs/unit" },++ "env": { "$ref": "#/$defs/env" }, "quantity": { "$ref": "#/$defs/count" }, "errors": { "$ref": "#/$defs/count" }++ }++ }++ },++ "daily": {++ "type": "array",++ "description": "One row per UTC day, service, capability, dimension, unit and environment that saw usage; days without any are absent. Newest day first.",++ "items": {++ "type": "object",++ "required": ["day", "service", "capability", "dimension", "unit", "env", "quantity", "errors"],++ "additionalProperties": false,++ "properties": {++ "day": { "type": "string", "format": "date" },++ "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" },++ "dimension": { "type": ["string", "null"], "maxLength": 80 },++ "unit": { "$ref": "#/$defs/unit" }, "env": { "$ref": "#/$defs/env" },++ "quantity": { "$ref": "#/$defs/count" }, "errors": { "$ref": "#/$defs/count" }++ }++ }++ },++ "quotas": {++ "type": "array",++ "description": "The project's recorded quotas (GET /api/v1/projects/:project/quotas), each with what its current window has used, in every environment together. used is null where the rollups cannot tell (a minute or hour window, or a unit no service reports for that capability).",++ "items": {++ "type": "object",++ "required": ["capability", "limit", "window", "unit", "enforced_by", "used", "remaining", "window_start", "note"],++ "additionalProperties": false,++ "properties": {++ "capability": { "$ref": "#/$defs/capability" },++ "limit": { "type": "integer", "minimum": 0 },++ "window": { "enum": ["minute", "hour", "day", "month", "total"] },++ "unit": { "$ref": "#/$defs/unit" },++ "enforced_by": { "type": ["string", "null"], "description": "The audience of the service that enforces it (openvibe.<owner>)." },++ "used": { "type": ["integer", "null"], "minimum": 0 },++ "remaining": { "type": ["integer", "null"], "minimum": 0 },++ "window_start": { "type": ["string", "null"], "format": "date-time", "description": "Start of the current window counted (today, this month); null for total and when used is null." },++ "note": { "type": ["string", "null"], "maxLength": 300 }++ }++ }++ },++ "errors": {++ "type": "object",++ "required": ["total", "by_code", "recent"],++ "additionalProperties": false,++ "properties": {++ "total": { "$ref": "#/$defs/count" },++ "by_code": {++ "type": "array",++ "items": {++ "type": "object",++ "required": ["service", "capability", "code", "count"],++ "additionalProperties": false,++ "properties": { "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" }, "code": { "$ref": "#/$defs/code" }, "count": { "$ref": "#/$defs/count" } }++ }++ },++ "recent": {++ "type": "array",++ "maxItems": 50,++ "description": "The newest failures the rollups sampled, newest first.",++ "items": {++ "type": "object",++ "required": ["at", "env", "service", "capability", "code", "status", "trace_id", "ref"],++ "additionalProperties": false,++ "properties": {++ "at": { "type": "string", "format": "date-time" },++ "env": { "$ref": "#/$defs/env" }, "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" },++ "code": { "$ref": "#/$defs/code" },++ "status": { "type": ["integer", "null"], "minimum": 100, "maximum": 599 },++ "trace_id": { "type": ["string", "null"], "pattern": "^[0-9a-f]{32}$" },++ "ref": { "type": ["string", "null"], "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$" }++ }++ }++ }++ }++ }++ }++}nnew file mode 100644@@@ -0,0 +1,32 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ],++ "ip": "203.0.113.7"++}nnew file mode 100644@@@ -0,0 +1,32 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ],++ "app_id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"++}nnew file mode 100644@@@ -0,0 +1,31 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "usr_01jab2c3d4e5f6g7h8j9k0mnpq",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,30 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "Timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "day",++ "window_start": "2026-09-25T00:00:00.000Z",++ "window_end": "2026-09-26T00:00:00.000Z",++ "quantity": -1,++ "errors": 0++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "day",++ "window_end": "2026-09-26T00:00:00.000Z",++ "quantity": 0,++ "errors": 0++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "minute",++ "window_start": "2026-09-25T00:00:00.000Z",++ "window_end": "2026-09-26T00:00:00.000Z",++ "quantity": 0,++ "errors": 0++}nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.failed",++ "detail": "Cannot read holiday.jpg"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.failed",++ "ref": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "staging",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "day",++ "window_start": "2026-09-25T00:00:00.000Z",++ "window_end": "2026-09-26T00:00:00.000Z",++ "quantity": 0,++ "errors": 0++}nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "sandbox",++ "capability": "events.app.publish",++ "unit": "events",++ "window": "hour",++ "window_start": "2026-09-26T09:00:00.000Z",++ "window_end": "2026-09-26T10:00:00.000Z",++ "quantity": 1800,++ "errors": 61,++ "error_codes": {++ "events.quota_exceeded": 60,++ "events.type_not_allowed": 1++ },++ "samples": [++ {++ "at": "2026-09-26T09:59:58.120Z",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "day",++ "window_start": "2026-09-25T00:00:00.000Z",++ "window_end": "2026-09-26T00:00:00.000Z",++ "quantity": 0,++ "errors": 0++}nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "day",++ "window_start": "2026-09-25T00:00:00.000Z",++ "window_end": "2026-09-26T00:00:00.000Z",++ "quantity": 7,++ "errors": 0,++ "revision": 2++}nnew file mode 100644@@@ -0,0 +1,31 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,26 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "sandbox",++ "capability": "events.app.publish",++ "unit": "events",++ "window": "hour",++ "window_start": "2026-09-26T09:00:00.000Z",++ "window_end": "2026-09-26T10:00:00.000Z",++ "quantity": 1800,++ "errors": 61,++ "error_codes": {++ "events.quota_exceeded": 60,++ "events.type_not_allowed": 1++ },++ "samples": [++ {++ "at": "2026-09-26T09:59:58.120Z",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c"++ }++ ],++ "payload": {++ "type": "app.p01jab.order.created"++ }++}nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "project_id": "live",++ "env": "sandbox",++ "capability": "events.app.publish",++ "unit": "events",++ "window": "hour",++ "window_start": "2026-09-26T09:00:00.000Z",++ "window_end": "2026-09-26T10:00:00.000Z",++ "quantity": 1800,++ "errors": 61,++ "error_codes": {++ "events.quota_exceeded": 60,++ "events.type_not_allowed": 1++ },++ "samples": [++ {++ "at": "2026-09-26T09:59:58.120Z",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,30 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "events.app.subscribe",++ "unit": "deliveries",++ "window": "hour",++ "window_start": "2026-09-26T10:00:00.000Z",++ "window_end": "2026-09-26T11:00:00.000Z",++ "quantity": 12,++ "errors": 2,++ "error_codes": {++ "events.delivery.http_500": 1,++ "events.delivery.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T10:31:00.000Z",++ "code": "events.delivery.timeout",++ "trace_id": "0af7651916cd43dd8448eb211c80319c",++ "ref": "evt_01JAB2C3D4E5F6G7H8J9K0MNPT"++ },++ {++ "at": "2026-09-26T10:30:00.000Z",++ "code": "events.delivery.http_500",++ "status": 500,++ "trace_id": "0af7651916cd43dd8448eb211c80319c",++ "ref": "evt_01JAB2C3D4E5F6G7H8J9K0MNPT"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "sandbox",++ "capability": "events.app.publish",++ "unit": "events",++ "window": "hour",++ "window_start": "2026-09-26T09:00:00.000Z",++ "window_end": "2026-09-26T10:00:00.000Z",++ "quantity": 1800,++ "errors": 61,++ "error_codes": {++ "events.quota_exceeded": 60,++ "events.type_not_allowed": 1++ },++ "samples": [++ {++ "at": "2026-09-26T09:59:58.120Z",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,115 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "all",++ "range": {++ "days": 365,++ "from": "2026-08-28",++ "to": "2026-09-26"++ },++ "generated_at": "2026-09-26T15:05:00.000Z",++ "last_recorded_at": "2026-09-26T15:02:11.000Z",++ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",++ "totals": [++ {++ "service": "tools",++ "capability": "tools.job.create",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "service": "events",++ "capability": "events.app.publish",++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "daily": [++ {++ "day": "2026-09-26",++ "service": "tools",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "day": "2026-09-26",++ "service": "events",++ "capability": "events.app.publish",++ "dimension": null,++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "quotas": [++ {++ "capability": "tools.job.create",++ "limit": 1000,++ "window": "day",++ "unit": "jobs",++ "enforced_by": "openvibe.tools",++ "used": 42,++ "remaining": 958,++ "window_start": "2026-09-26T00:00:00.000Z",++ "note": null++ },++ {++ "capability": "events.app.publish",++ "limit": 120,++ "window": "minute",++ "unit": "events",++ "enforced_by": "openvibe.events",++ "used": null,++ "remaining": null,++ "window_start": null,++ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"++ }++ ],++ "errors": {++ "total": 64,++ "by_code": [++ {++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "count": 60++ },++ {++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.failed",++ "count": 2++ }++ ],++ "recent": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "env": "production",++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T09:59:58.120Z",++ "env": "sandbox",++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c",++ "ref": null++ }++ ]++ }++}nnew file mode 100644@@@ -0,0 +1,115 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "all",++ "range": {++ "days": 30,++ "from": "2026-08-28",++ "to": "2026-09-26"++ },++ "generated_at": "2026-09-26T15:05:00.000Z",++ "last_recorded_at": "2026-09-26T15:02:11.000Z",++ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",++ "totals": [++ {++ "service": "tools",++ "capability": "tools.job.create",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "service": "events",++ "capability": "events.app.publish",++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "daily": [++ {++ "day": "2026-09-26",++ "service": "tools",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "day": "2026-09-26",++ "service": "events",++ "capability": "events.app.publish",++ "dimension": null,++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "quotas": [++ {++ "capability": "tools.job.create",++ "limit": 1000,++ "window": "day",++ "unit": "jobs",++ "enforced_by": "openvibe.tools",++ "used": -5,++ "remaining": 958,++ "window_start": "2026-09-26T00:00:00.000Z",++ "note": null++ },++ {++ "capability": "events.app.publish",++ "limit": 120,++ "window": "minute",++ "unit": "events",++ "enforced_by": "openvibe.events",++ "used": null,++ "remaining": null,++ "window_start": null,++ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"++ }++ ],++ "errors": {++ "total": 64,++ "by_code": [++ {++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "count": 60++ },++ {++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.failed",++ "count": 2++ }++ ],++ "recent": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "env": "production",++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T09:59:58.120Z",++ "env": "sandbox",++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c",++ "ref": null++ }++ ]++ }++}nnew file mode 100644@@@ -0,0 +1,119 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "all",++ "range": {++ "days": 30,++ "from": "2026-08-28",++ "to": "2026-09-26"++ },++ "generated_at": "2026-09-26T15:05:00.000Z",++ "last_recorded_at": "2026-09-26T15:02:11.000Z",++ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",++ "totals": [++ {++ "service": "tools",++ "capability": "tools.job.create",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "service": "events",++ "capability": "events.app.publish",++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "daily": [++ {++ "day": "2026-09-26",++ "service": "tools",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "day": "2026-09-26",++ "service": "events",++ "capability": "events.app.publish",++ "dimension": null,++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "quotas": [++ {++ "capability": "tools.job.create",++ "limit": 1000,++ "window": "day",++ "unit": "jobs",++ "enforced_by": "openvibe.tools",++ "used": 42,++ "remaining": 958,++ "window_start": "2026-09-26T00:00:00.000Z",++ "note": null++ },++ {++ "capability": "events.app.publish",++ "limit": 120,++ "window": "minute",++ "unit": "events",++ "enforced_by": "openvibe.events",++ "used": null,++ "remaining": null,++ "window_start": null,++ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"++ }++ ],++ "errors": {++ "total": 64,++ "by_code": [++ {++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "count": 60++ },++ {++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.failed",++ "count": 2++ }++ ],++ "recent": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "env": "production",++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR",++ "subject": {++ "type": "user",++ "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"++ }++ },++ {++ "at": "2026-09-26T09:59:58.120Z",++ "env": "sandbox",++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c",++ "ref": null++ }++ ]++ }++}nnew file mode 100644@@@ -0,0 +1,115 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "all",++ "range": {++ "days": 30,++ "from": "2026-08-28",++ "to": "2026-09-26"++ },++ "generated_at": "2026-09-26T15:05:00.000Z",++ "last_recorded_at": "2026-09-26T15:02:11.000Z",++ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",++ "totals": [++ {++ "service": "tools",++ "capability": "tools.job.create",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "service": "events",++ "capability": "events.app.publish",++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "daily": [++ {++ "day": "2026-09-26",++ "service": "tools",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "env": "production",++ "quantity": 42,++ "errors": 3++ },++ {++ "day": "2026-09-26",++ "service": "events",++ "capability": "events.app.publish",++ "dimension": null,++ "unit": "events",++ "env": "sandbox",++ "quantity": 1800,++ "errors": 61++ }++ ],++ "quotas": [++ {++ "capability": "tools.job.create",++ "limit": 1000,++ "window": "day",++ "unit": "jobs",++ "enforced_by": "openvibe.tools",++ "used": 42,++ "remaining": 958,++ "window_start": "2026-09-26T00:00:00.000Z",++ "note": null++ },++ {++ "capability": "events.app.publish",++ "limit": 120,++ "window": "minute",++ "unit": "events",++ "enforced_by": "openvibe.events",++ "used": null,++ "remaining": null,++ "window_start": null,++ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"++ }++ ],++ "errors": {++ "total": 64,++ "by_code": [++ {++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "count": 60++ },++ {++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.failed",++ "count": 2++ }++ ],++ "recent": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "env": "production",++ "service": "tools",++ "capability": "tools.job.create",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T09:59:58.120Z",++ "env": "sandbox",++ "service": "events",++ "capability": "events.app.publish",++ "code": "events.quota_exceeded",++ "status": 429,++ "trace_id": "0af7651916cd43dd8448eb211c80319c",++ "ref": null++ }++ ]++ }++}nnew file mode 100644@@@ -0,0 +1,20 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "range": {++ "days": 7,++ "from": "2026-09-20",++ "to": "2026-09-26"++ },++ "generated_at": "2026-09-26T15:05:00.000Z",++ "last_recorded_at": null,++ "freshness": "No usage has been recorded for this project yet.",++ "totals": [],++ "daily": [],++ "quotas": [],++ "errors": {++ "total": 0,++ "by_code": [],++ "recent": []++ }++}nnew file mode 100644@@@ -0,0 +1,35 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ],++ "owner": {++ "type": "app",++ "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"++ }++}nnew file mode 100644@@@ -0,0 +1,30 @@++{++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,31 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "production",++ "capability": "tools.job.create",++ "dimension": "img.process",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T14:00:00.000Z",++ "window_end": "2026-09-26T15:00:00.000Z",++ "quantity": 42,++ "errors": 3,++ "error_codes": {++ "tools.job.failed": 2,++ "tools.job.timeout": 1++ },++ "samples": [++ {++ "at": "2026-09-26T14:51:07.412Z",++ "code": "tools.job.timeout",++ "status": 504,++ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"++ },++ {++ "at": "2026-09-26T14:20:13.001Z",++ "code": "tools.job.failed",++ "status": 422,++ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "env": "sandbox",++ "capability": "tools.tool.run",++ "unit": "jobs",++ "window": "hour",++ "window_start": "2026-09-26T08:00:00.000Z",++ "window_end": "2026-09-26T09:00:00.000Z",++ "quantity": 5,++ "errors": 0,++ "dimension": "image-resize"++}@@@ -2580,6 +2580,150 @@}}},++ "common.usage-recorded": {++ "version": "1.0.0",++ "owner": "network",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/common/usage-recorded.v1.json",++ "title": "UsageRecorded",++ "description": "common.usage-recorded@1 (roadmap WS-N task 4, ADR-014): one rollup of a developer project's use of one capability in one environment over one closed window (an hour or a day), as the service that owns the capability counted it. The payload of every <service>.usage.recorded event; OpenVibe.Network adds them up per project and day for the project's dashboard on OpenVibe.Codes. The producer counts in the transaction that does its own accounting (a job's end, a stored event, a delivery attempt) and writes the rollup to its outbox after the window has closed: never one event per request. Totals, not deltas: a later event with the same key (source, project_id, env, capability, dimension, unit, window_start) replaces the earlier one, and a lower revision never replaces a higher one. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor the producing service. Never carries a subject id, an address, a session, a request's input or content, or a file name.",++ "type": "object",++ "required": [++ "project_id",++ "env",++ "capability",++ "unit",++ "window",++ "window_start",++ "window_end",++ "quantity",++ "errors"++ ],++ "additionalProperties": false,++ "properties": {++ "project_id": {++ "type": "string",++ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The developer project whose app token did the work."++ },++ "env": {++ "enum": [++ "sandbox",++ "production"++ ],++ "description": "The environment of that app token."++ },++ "capability": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$",++ "maxLength": 80,++ "description": "The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe."++ },++ "dimension": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "pattern": "^[a-z0-9][a-z0-9_.:-]*$",++ "not": {++ "pattern": "^(usr|gst|app|mod|svc|job|evt|req)_"++ },++ "description": "Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job."++ },++ "unit": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$",++ "description": "What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit."++ },++ "window": {++ "enum": [++ "hour",++ "day"++ ],++ "description": "The length of the window."++ },++ "window_start": {++ "type": "string",++ "format": "date-time",++ "description": "UTC, on the hour (midnight for a day)."++ },++ "window_end": {++ "type": "string",++ "format": "date-time",++ "description": "window_start plus the window, exclusive."++ },++ "quantity": {++ "type": "integer",++ "minimum": 0,++ "description": "Units used in the window, by work that succeeded and work that failed alike."++ },++ "errors": {++ "type": "integer",++ "minimum": 0,++ "description": "Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity."++ },++ "error_codes": {++ "type": "object",++ "maxProperties": 20,++ "propertyNames": {++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$",++ "maxLength": 80++ },++ "additionalProperties": {++ "type": "integer",++ "minimum": 1++ },++ "description": "The errors by problem code (at most 20 codes; the rest are only in errors)."++ },++ "samples": {++ "type": "array",++ "maxItems": 10,++ "description": "The last failures of the window, newest first, so a developer can find them in their own logs.",++ "items": {++ "type": "object",++ "required": [++ "at",++ "code"++ ],++ "additionalProperties": false,++ "properties": {++ "at": {++ "type": "string",++ "format": "date-time"++ },++ "code": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$",++ "maxLength": 80++ },++ "status": {++ "type": "integer",++ "minimum": 100,++ "maximum": 599,++ "description": "The HTTP status the failure was answered with, when there was one."++ },++ "trace_id": {++ "type": "string",++ "pattern": "^[0-9a-f]{32}$",++ "description": "The W3C trace id of the request (or event) that failed."++ },++ "ref": {++ "type": "string",++ "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject."++ }++ }++ }++ },++ "revision": {++ "type": "integer",++ "minimum": 1,++ "description": "1 when absent. A producer that re-emits a window with corrected totals raises it."++ }++ }++ }++ },"media.file-upload": {"version": "1.0.0","owner": "media",@@@ -23671,6 +23815,30 @@"$ref": "../../common/moderation-action.v1.json"}},++ "tools.usage.recorded": {++ "version": "1.0.0",++ "owner": "tools",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/tools.usage.recorded.v1.json",++ "title": "ToolsUsageRecordedPayload",++ "description": "tools.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Tools apps/_shared/jobs/usage.js). One hour of a developer project's jobs on one Tools satellite, per capability (tools.job.create for POST /api/v1/jobs, tools.tool.run for a tool run) and job type or tool (dimension), in unit jobs: quantity counts the jobs that ended (succeeded or failed; a cancelled job is not counted), errors the failed ones, by code, with the last failures' job ids and trace ids. Counted in the transaction that records a job's end; written to the satellite's outbox after the hour closes. Only jobs of developer-app tokens (they carry a project) are counted; sandbox jobs are counted under env sandbox. The payload is common.usage-recorded@1. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:tools.",++ "$ref": "../../common/usage-recorded.v1.json"++ }++ },++ "events.usage.recorded": {++ "version": "1.0.0",++ "owner": "events",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/events.usage.recorded.v1.json",++ "title": "EventsUsageRecordedPayload",++ "description": "events.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Events server/usage.js). One hour of a developer project's use of OpenVibe.Events in one environment: events.app.publish in unit events (quantity counts the events stored; errors the publish requests refused with a problem, such as 429 events.quota_exceeded or 403 events.type_not_allowed) and events.app.subscribe in unit deliveries (quantity counts webhook delivery attempts to the project's subscriptions; errors the attempts without a 2xx, as events.delivery.http_<status>, events.delivery.timeout or events.delivery.failed). Counted in the transaction that stores the events or records the attempt (a refusal right after it is answered); Events stores the rollup as its own event after the hour closes, in the same transaction that marks it sent. The payload is common.usage-recorded@1. Envelope: source events, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:events.",++ "$ref": "../../common/usage-recorded.v1.json"++ }++ },"live.stream.started": {"version": "1.0.0","owner": "live",@@@ -26194,6 +26362,379 @@}}},++ "network.project-usage-result": {++ "version": "1.0.0",++ "owner": "network",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/network/project-usage-result.v1.json",++ "title": "ProjectUsageResult",++ "description": "network.project-usage-result@1 (roadmap WS-N task 4, ADR-014): what GET /api/v1/projects/:project/usage?days=&env= on OpenVibe.Network answers a project's owner or admin (or staff): the project's usage per day, service, capability and unit, added up from the <service>.usage.recorded rollups (common.usage-recorded@1) the owning services emit after each hour closes; the project's recorded quotas with what the current window has used; and its recent failures with their codes and trace ids. Counts only, never who did what: no subject id, address, input or content.",++ "type": "object",++ "required": [++ "project_id",++ "env",++ "range",++ "generated_at",++ "last_recorded_at",++ "freshness",++ "totals",++ "daily",++ "quotas",++ "errors"++ ],++ "additionalProperties": false,++ "$defs": {++ "service": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{1,39}$"++ },++ "capability": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$",++ "maxLength": 80++ },++ "unit": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "env": {++ "enum": [++ "sandbox",++ "production"++ ]++ },++ "code": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$",++ "maxLength": 80++ },++ "count": {++ "type": "integer",++ "minimum": 0++ }++ },++ "properties": {++ "project_id": {++ "type": "string",++ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "env": {++ "enum": [++ "all",++ "sandbox",++ "production"++ ],++ "description": "The environments counted (the env query parameter; all by default)."++ },++ "range": {++ "type": "object",++ "required": [++ "days",++ "from",++ "to"++ ],++ "additionalProperties": false,++ "properties": {++ "days": {++ "type": "integer",++ "minimum": 1,++ "maximum": 90++ },++ "from": {++ "type": "string",++ "format": "date",++ "description": "First UTC day counted."++ },++ "to": {++ "type": "string",++ "format": "date",++ "description": "Last UTC day counted (today)."++ }++ }++ },++ "generated_at": {++ "type": "string",++ "format": "date-time"++ },++ "last_recorded_at": {++ "type": [++ "string",++ "null"++ ],++ "format": "date-time",++ "description": "When the newest rollup for this project arrived; null before the first."++ },++ "freshness": {++ "type": "string",++ "maxLength": 300,++ "description": "How current the numbers are, in words (rollups arrive after each hour closes)."++ },++ "totals": {++ "type": "array",++ "description": "The whole range per service, capability, unit and environment.",++ "items": {++ "type": "object",++ "required": [++ "service",++ "capability",++ "unit",++ "env",++ "quantity",++ "errors"++ ],++ "additionalProperties": false,++ "properties": {++ "service": {++ "$ref": "#/$defs/service"++ },++ "capability": {++ "$ref": "#/$defs/capability"++ },++ "unit": {++ "$ref": "#/$defs/unit"++ },++ "env": {++ "$ref": "#/$defs/env"++ },++ "quantity": {++ "$ref": "#/$defs/count"++ },++ "errors": {++ "$ref": "#/$defs/count"++ }++ }++ }++ },++ "daily": {++ "type": "array",++ "description": "One row per UTC day, service, capability, dimension, unit and environment that saw usage; days without any are absent. Newest day first.",++ "items": {++ "type": "object",++ "required": [++ "day",++ "service",++ "capability",++ "dimension",++ "unit",++ "env",++ "quantity",++ "errors"++ ],++ "additionalProperties": false,++ "properties": {++ "day": {++ "type": "string",++ "format": "date"++ },++ "service": {++ "$ref": "#/$defs/service"++ },++ "capability": {++ "$ref": "#/$defs/capability"++ },++ "dimension": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 80++ },++ "unit": {++ "$ref": "#/$defs/unit"++ },++ "env": {++ "$ref": "#/$defs/env"++ },++ "quantity": {++ "$ref": "#/$defs/count"++ },++ "errors": {++ "$ref": "#/$defs/count"++ }++ }++ }++ },++ "quotas": {++ "type": "array",++ "description": "The project's recorded quotas (GET /api/v1/projects/:project/quotas), each with what its current window has used, in every environment together. used is null where the rollups cannot tell (a minute or hour window, or a unit no service reports for that capability).",++ "items": {++ "type": "object",++ "required": [++ "capability",++ "limit",++ "window",++ "unit",++ "enforced_by",++ "used",++ "remaining",++ "window_start",++ "note"++ ],++ "additionalProperties": false,++ "properties": {++ "capability": {++ "$ref": "#/$defs/capability"++ },++ "limit": {++ "type": "integer",++ "minimum": 0++ },++ "window": {++ "enum": [++ "minute",++ "hour",++ "day",++ "month",++ "total"++ ]++ },++ "unit": {++ "$ref": "#/$defs/unit"++ },++ "enforced_by": {++ "type": [++ "string",++ "null"++ ],++ "description": "The audience of the service that enforces it (openvibe.<owner>)."++ },++ "used": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 0++ },++ "remaining": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 0++ },++ "window_start": {++ "type": [++ "string",++ "null"++ ],++ "format": "date-time",++ "description": "Start of the current window counted (today, this month); null for total and when used is null."++ },++ "note": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 300++ }++ }++ }++ },++ "errors": {++ "type": "object",++ "required": [++ "total",++ "by_code",++ "recent"++ ],++ "additionalProperties": false,++ "properties": {++ "total": {++ "$ref": "#/$defs/count"++ },++ "by_code": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "service",++ "capability",++ "code",++ "count"++ ],++ "additionalProperties": false,++ "properties": {++ "service": {++ "$ref": "#/$defs/service"++ },++ "capability": {++ "$ref": "#/$defs/capability"++ },++ "code": {++ "$ref": "#/$defs/code"++ },++ "count": {++ "$ref": "#/$defs/count"++ }++ }++ }++ },++ "recent": {++ "type": "array",++ "maxItems": 50,++ "description": "The newest failures the rollups sampled, newest first.",++ "items": {++ "type": "object",++ "required": [++ "at",++ "env",++ "service",++ "capability",++ "code",++ "status",++ "trace_id",++ "ref"++ ],++ "additionalProperties": false,++ "properties": {++ "at": {++ "type": "string",++ "format": "date-time"++ },++ "env": {++ "$ref": "#/$defs/env"++ },++ "service": {++ "$ref": "#/$defs/service"++ },++ "capability": {++ "$ref": "#/$defs/capability"++ },++ "code": {++ "$ref": "#/$defs/code"++ },++ "status": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 100,++ "maximum": 599++ },++ "trace_id": {++ "type": [++ "string",++ "null"++ ],++ "pattern": "^[0-9a-f]{32}$"++ },++ "ref": {++ "type": [++ "string",++ "null"++ ],++ "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++ }++ }++ }++ }++ }++ }++ },"network.staff-list-result": {"version": "1.0.0","owner": "network",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Chat API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Codes API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Community API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Coupons API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Deals API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Events API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Games API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Host API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Media API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Network API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.News API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenRe.Stream API",-- "version": "0.62.0",-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Reviews API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Search API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Sources API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tips API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tools API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Trade API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.VIP API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Wiki API",-- "version": "0.62.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.63.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -1176,1286 +1176,2250 @@ export interface ModerationAction {details?: {};}--/** [email protected] (owner: media) */--/**-- * media.file-upload@1: the multipart/form-data body of POST /api/v1/:app/files (media.object.upload, namespace :app): one part named `file` with the bytes and its filename and type. The tenant's quota is checked against the bytes; the answer is media.file@1 (201).-- */--export interface MediaFileUpload {-- /**-- * The multipart part named file (filename and Content-Type from the part).-- */-- file: string;-- [k: string]: unknown | undefined;--}----/** [email protected] (owner: search) */++/** [email protected] (owner: network) *//**-- * What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.++ * common.usage-recorded@1 (roadmap WS-N task 4, ADR-014): one rollup of a developer project's use of one capability in one environment over one closed window (an hour or a day), as the service that owns the capability counted it. The payload of every <service>.usage.recorded event; OpenVibe.Network adds them up per project and day for the project's dashboard on OpenVibe.Codes. The producer counts in the transaction that does its own accounting (a job's end, a stored event, a delivery attempt) and writes the rollup to its outbox after the window has closed: never one event per request. Totals, not deltas: a later event with the same key (source, project_id, env, capability, dimension, unit, window_start) replaces the earlier one, and a lower revision never replaces a higher one. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor the producing service. Never carries a subject id, an address, a session, a request's input or content, or a file name.*/--export interface IndexDocument {-- /**-- * Owning service id (wiki, blog, news, community, sources…). Only that service may write the document.-- */-- owner: string;-- /**-- * Resource type inside the owner (page, post, story, entity, offer, coupon, instrument, item…).-- */-- type: string;++export interface UsageRecorded {/**-- * Resource id inside owner+type. Stable across revisions.++ * The developer project whose app token did the work.*/-- id: string;++ project_id: string;/**-- * Owner's monotonic revision of the resource. An older revision never overwrites a newer one; at equal revision a deletion wins.++ * The environment of that app token.*/-- revision: number;++ env: "sandbox" | "production";/**-- * Deletion marker. true = tombstone; every other content field is ignored.++ * The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe.*/-- deleted?: boolean;++ capability: string;/**-- * public: anyone. unlisted: never listed except to ACL matches; fetchable by exact id by a signed-in subject. members: subjects, groups or entitlements in acl. private: subjects in acl.subjects only. draft: never served.++ * Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job.*/-- visibility?: "public" | "unlisted" | "members" | "private" | "draft";++ dimension?: string;/**-- * Who may see a non-public document. Ignored for public documents. Empty means nobody (for members/private) or direct-id only (for unlisted).++ * What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit.*/-- acl?: {-- /**-- * @maxItems 200-- */-- subjects?: string[];-- /**-- * Opaque group keys owned by some service, e.g. role:admin (Network role), wiki.space:spc_…:member.-- *-- * @maxItems 100-- */-- groups?: string[];-- /**-- * Entitlement keys (VIP/Billing), e.g. vip.plan:pln_…. Only a first-party service that just resolved them may present them for a viewer.-- *-- * @maxItems 100-- */-- entitlements?: string[];-- };-- canonical_url?: string;-- title?: string;-- summary?: string;++ unit: string;/**-- * Plain text for full-text search (no HTML). Keep it under the Events payload limit when publishing through Events.++ * The length of the window.*/-- body?: string;++ window: "hour" | "day";/**-- * Filterable values (category, tags, space, author subject, currency…). Filter with facet.<key>=<value>.++ * UTC, on the hour (midnight for a day).*/-- facets?: {-- [k: string]: (string | number | boolean | string[]) | undefined;-- };++ window_start: string;/**-- * BCP 47 tag.++ * window_start plus the window, exclusive.*/-- language?: string;-- authorship?: "human" | "ai_assisted" | "ai_generated" | "imported";++ window_end: string;/**-- * Where the content came from: typed references to source records (Sources items, citations, Media objects).-- *-- * @maxItems 50++ * Units used in the window, by work that succeeded and work that failed alike.*/-- provenance?: {-- service: string;-- type: string;-- id: string;-- revision?: number;-- label?: string;-- url?: string;-- retrieved_at?: string;-- /**-- * true when the reference came from a stub provider; the document is then never indexable.-- */-- stub?: boolean;-- }[];++ quantity: number;/**-- * Only published documents are ever served.++ * Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity.*/-- publication_state?: "draft" | "scheduled" | "published" | "unpublished" | "retracted" | "archived";-- published_at?: string | null;-- updated_at?: string | null;++ errors: number;/**-- * The owner's deterministic indexability decision (publishing packages, roadmap §32.3). Search can only make it stricter.++ * The errors by problem code (at most 20 codes; the rest are only in errors).*/-- indexability?: {-- decision: "index" | "noindex";-- /**-- * Known reasons: draft, private, members_only, unlisted, not_published, deleted, thin_content, duplicate_without_canonical, unsupported_claims, unsourced, stub_provider, sensitive_unreviewed, ai_unreviewed, missing_canonical_url, third_party_content, owner_decision.-- *-- * @maxItems 20-- */-- reasons?:-- | []-- | [string]-- | [string, string]-- | [string, string, string]-- | [string, string, string, string]-- | [string, string, string, string, string]-- | [string, string, string, string, string, string]-- | [string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ];++ error_codes?: {++ [k: string]: number | undefined;};--}----/** [email protected] (owner: search) */--/**-- * search.query@1: the query string of GET /api/v1/search (and, with q/owner/type/limit only, GET /api/v1/suggest), capabilities search.query.run and search.query.delegate. Who sees what is decided by Search per hit: anonymous callers get public, published, indexable documents; a person also restricted documents naming them; a delegating service passes X-OV-Subject. Filters narrow; they never widen visibility.-- */--export interface SearchQuery {-- /**-- * Words to match (FTS5; empty lists by recency).-- */-- q?: string;-- /**-- * One owner service (live, community, wiki, …).-- */-- owner?: string;-- /**-- * One document type within the owner (channel, vod, thread, …).-- */-- type?: string;-- /**-- * BCP 47 language.-- */-- lang?: string;/**-- * Comma-separated facet keys to count over what the caller can see.++ * The last failures of the window, newest first, so a developer can find them in their own logs.++ *++ * @maxItems 10*/-- facets?: string;-- limit?: number | string;-- /**-- * next_cursor of the previous page.-- */-- cursor?: string;-- /**-- * A facet filter (facet.<key>=<value>); repeat the parameter for several values.-- *-- * This interface was referenced by `SearchQuery`'s JSON-Schema definition-- * via the `patternProperty` "^facet\.[a-z][a-z0-9_]{0,39}$".-- */-- [k: string]:-- | string++ samples?:| []-- | [string]-- | [string, string]-- | [string, string, string]-- | [string, string, string, string]-- | [string, string, string, string, string]-- | [string, string, string, string, string, string]-- | [string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string, string, string]-- | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]| [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }]| [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }]| [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }]| [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }]| [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }]-- | [-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string,-- string-- ];--}----/** [email protected] (owner: search) */--/**-- * search.query-result@1: the answer of GET /api/v1/search — one page of hits the caller may see, a cursor for the next page, and facet counts when asked. Never a total count and never an ACL.-- */--export interface SearchQueryResult {-- /**-- * @maxItems 100-- */-- results: {-- owner: string;-- type: string;-- id: string;-- revision?: number;-- visibility?: string;-- title?: string | null;-- summary?: string | null;-- canonical_url?: string | null;-- facets?: {} | null;-- language?: string | null;-- authorship?: string | null;-- provenance?: unknown[] | {} | null;-- published_at?: string | null;-- updated_at?: string | null;-- /**-- * false for a noindex document the caller may still see.-- */-- indexable?: boolean;-- /**-- * Escaped text with <mark> around the matches; nothing else.-- */-- snippet_html?: string | null;-- }[];-- next_cursor: string | null;-- facets?: {-- [k: string]:-- | {-- value: string;-- count: number;-- }[]-- | undefined;-- };--}----/** [email protected] (owner: search) */--/**-- * search.write-result@1: the answer of PUT /api/v1/documents/:owner/:type/:id (search.document.write). applied: stored (or a tombstone recorded); unchanged: the same revision with the same content. A revision older than the stored one is a 409 problem search.stale_revision; the same revision with different content is 409 search.revision_conflict.-- */--export interface SearchWriteResult {-- outcome: "applied" | "unchanged";-- revision: number;-- /**-- * What Search held before this write (null: nothing).-- */-- stored_revision?: number | null;-- deleted?: boolean;--}----/** [email protected] (owner: sources) */--/**-- * A registered source (roadmap §4.2 B, Wave 14): where it is fetched from and on what terms. Credentials are referenced by environment-variable NAME only. A source's existence is never permission to fetch: robots and terms are verified before it is enabled, and the fetcher re-checks robots.txt on every run.-- */--export interface Source {-- key: string;-- name: string;-- type: "rss" | "atom" | "sitemap" | "jsonld" | "api" | "manual";-- category: "news" | "blog" | "reviews" | "deals" | "coupons" | "trade";-- homepage_url?: string | null;-- /**-- * @maxItems 20-- */-- endpoints:-- | []| [{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- }-- ]-- | [++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- }-- ]-- | [++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;}]| [{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- }-- ]-- | [-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;}]| [{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;}]| [{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- }-- ]-- | [-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- }-- ]-- | [-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;},{-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- }-- ]-- | [-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;}-- ]-- | [-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {-- [k: string]: string | undefined;-- };-- },-- {-- url: string;-- format?: "json" | "xml";-- items_path?: string;-- item_kind?: string;-- fields?: {-- [k: string]: string | undefined;-- };-- extra?: {++ ];++ /**++ * 1 when absent. A producer that re-emits a window with corrected totals raises it.++ */++ revision?: number;++}++++/** [email protected] (owner: media) */++/**++ * media.file-upload@1: the multipart/form-data body of POST /api/v1/:app/files (media.object.upload, namespace :app): one part named `file` with the bytes and its filename and type. The tenant's quota is checked against the bytes; the answer is media.file@1 (201).++ */++export interface MediaFileUpload {++ /**++ * The multipart part named file (filename and Content-Type from the part).++ */++ file: string;++ [k: string]: unknown | undefined;++}++++/** [email protected] (owner: search) */++/**++ * What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.++ */++export interface IndexDocument {++ /**++ * Owning service id (wiki, blog, news, community, sources…). Only that service may write the document.++ */++ owner: string;++ /**++ * Resource type inside the owner (page, post, story, entity, offer, coupon, instrument, item…).++ */++ type: string;++ /**++ * Resource id inside owner+type. Stable across revisions.++ */++ id: string;++ /**++ * Owner's monotonic revision of the resource. An older revision never overwrites a newer one; at equal revision a deletion wins.++ */++ revision: number;++ /**++ * Deletion marker. true = tombstone; every other content field is ignored.++ */++ deleted?: boolean;++ /**++ * public: anyone. unlisted: never listed except to ACL matches; fetchable by exact id by a signed-in subject. members: subjects, groups or entitlements in acl. private: subjects in acl.subjects only. draft: never served.++ */++ visibility?: "public" | "unlisted" | "members" | "private" | "draft";++ /**++ * Who may see a non-public document. Ignored for public documents. Empty means nobody (for members/private) or direct-id only (for unlisted).++ */++ acl?: {++ /**++ * @maxItems 200++ */++ subjects?: string[];++ /**++ * Opaque group keys owned by some service, e.g. role:admin (Network role), wiki.space:spc_…:member.++ *++ * @maxItems 100++ */++ groups?: string[];++ /**++ * Entitlement keys (VIP/Billing), e.g. vip.plan:pln_…. Only a first-party service that just resolved them may present them for a viewer.++ *++ * @maxItems 100++ */++ entitlements?: string[];++ };++ canonical_url?: string;++ title?: string;++ summary?: string;++ /**++ * Plain text for full-text search (no HTML). Keep it under the Events payload limit when publishing through Events.++ */++ body?: string;++ /**++ * Filterable values (category, tags, space, author subject, currency…). Filter with facet.<key>=<value>.++ */++ facets?: {++ [k: string]: (string | number | boolean | string[]) | undefined;++ };++ /**++ * BCP 47 tag.++ */++ language?: string;++ authorship?: "human" | "ai_assisted" | "ai_generated" | "imported";++ /**++ * Where the content came from: typed references to source records (Sources items, citations, Media objects).++ *++ * @maxItems 50++ */++ provenance?: {++ service: string;++ type: string;++ id: string;++ revision?: number;++ label?: string;++ url?: string;++ retrieved_at?: string;++ /**++ * true when the reference came from a stub provider; the document is then never indexable.++ */++ stub?: boolean;++ }[];++ /**++ * Only published documents are ever served.++ */++ publication_state?: "draft" | "scheduled" | "published" | "unpublished" | "retracted" | "archived";++ published_at?: string | null;++ updated_at?: string | null;++ /**++ * The owner's deterministic indexability decision (publishing packages, roadmap §32.3). Search can only make it stricter.++ */++ indexability?: {++ decision: "index" | "noindex";++ /**++ * Known reasons: draft, private, members_only, unlisted, not_published, deleted, thin_content, duplicate_without_canonical, unsupported_claims, unsourced, stub_provider, sensitive_unreviewed, ai_unreviewed, missing_canonical_url, third_party_content, owner_decision.++ *++ * @maxItems 20++ */++ reasons?:++ | []++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ];++ };++}++++/** [email protected] (owner: search) */++/**++ * search.query@1: the query string of GET /api/v1/search (and, with q/owner/type/limit only, GET /api/v1/suggest), capabilities search.query.run and search.query.delegate. Who sees what is decided by Search per hit: anonymous callers get public, published, indexable documents; a person also restricted documents naming them; a delegating service passes X-OV-Subject. Filters narrow; they never widen visibility.++ */++export interface SearchQuery {++ /**++ * Words to match (FTS5; empty lists by recency).++ */++ q?: string;++ /**++ * One owner service (live, community, wiki, …).++ */++ owner?: string;++ /**++ * One document type within the owner (channel, vod, thread, …).++ */++ type?: string;++ /**++ * BCP 47 language.++ */++ lang?: string;++ /**++ * Comma-separated facet keys to count over what the caller can see.++ */++ facets?: string;++ limit?: number | string;++ /**++ * next_cursor of the previous page.++ */++ cursor?: string;++ /**++ * A facet filter (facet.<key>=<value>); repeat the parameter for several values.++ *++ * This interface was referenced by `SearchQuery`'s JSON-Schema definition++ * via the `patternProperty` "^facet\.[a-z][a-z0-9_]{0,39}$".++ */++ [k: string]:++ | string++ | []++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ];++}++++/** [email protected] (owner: search) */++/**++ * search.query-result@1: the answer of GET /api/v1/search — one page of hits the caller may see, a cursor for the next page, and facet counts when asked. Never a total count and never an ACL.++ */++export interface SearchQueryResult {++ /**++ * @maxItems 100++ */++ results: {++ owner: string;++ type: string;++ id: string;++ revision?: number;++ visibility?: string;++ title?: string | null;++ summary?: string | null;++ canonical_url?: string | null;++ facets?: {} | null;++ language?: string | null;++ authorship?: string | null;++ provenance?: unknown[] | {} | null;++ published_at?: string | null;++ updated_at?: string | null;++ /**++ * false for a noindex document the caller may still see.++ */++ indexable?: boolean;++ /**++ * Escaped text with <mark> around the matches; nothing else.++ */++ snippet_html?: string | null;++ }[];++ next_cursor: string | null;++ facets?: {++ [k: string]:++ | {++ value: string;++ count: number;++ }[]++ | undefined;++ };++}++++/** [email protected] (owner: search) */++/**++ * search.write-result@1: the answer of PUT /api/v1/documents/:owner/:type/:id (search.document.write). applied: stored (or a tombstone recorded); unchanged: the same revision with the same content. A revision older than the stored one is a 409 problem search.stale_revision; the same revision with different content is 409 search.revision_conflict.++ */++export interface SearchWriteResult {++ outcome: "applied" | "unchanged";++ revision: number;++ /**++ * What Search held before this write (null: nothing).++ */++ stored_revision?: number | null;++ deleted?: boolean;++}++++/** [email protected] (owner: sources) */++/**++ * A registered source (roadmap §4.2 B, Wave 14): where it is fetched from and on what terms. Credentials are referenced by environment-variable NAME only. A source's existence is never permission to fetch: robots and terms are verified before it is enabled, and the fetcher re-checks robots.txt on every run.++ */++export interface Source {++ key: string;++ name: string;++ type: "rss" | "atom" | "sitemap" | "jsonld" | "api" | "manual";++ category: "news" | "blog" | "reviews" | "deals" | "coupons" | "trade";++ homepage_url?: string | null;++ /**++ * @maxItems 20++ */++ endpoints:++ | []++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ }++ ]++ | [++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {++ [k: string]: string | undefined;++ };++ },++ {++ url: string;++ format?: "json" | "xml";++ items_path?: string;++ item_kind?: string;++ fields?: {++ [k: string]: string | undefined;++ };++ extra?: {[k: string]: string | undefined;};},@@@ -24930,145 +25894,2073 @@ export interface ToolsJobSucceededPayload {*/expires_at: string | null;/**-- * Where the result files are, never their content, names or the tool's output data (GET /api/v1/jobs/:id has those, for the owner).++ * Where the result files are, never their content, names or the tool's output data (GET /api/v1/jobs/:id has those, for the owner).++ */++ result: {++ /**++ * @maxItems 100++ */++ files: {++ /**++ * n in /api/v1/jobs/:id/files/:n.++ */++ index: number;++ mime: string;++ size: number;++ sha256: string;++ /**++ * media: stored as an OpenVibe.Media object (TOOLS_JOB_RESULTS=media); local: kept on the satellite until the job expires.++ */++ storage: "local" | "media";++ /**++ * { media_id, role: output } when storage is media.++ */++ media: MediaRef | null;++ }[];++ };++}++++/** [email protected] (owner: tools) */++/**++ * tools.job.failed v1 (OpenVibe.Tools apps/_shared/jobs/events.js). The job failed: the tool refused the input, it timed out, or it was running when the satellite restarted and its type does not requeue. A cancelled job is not a failure and is not announced as one. Emitted in the transaction that records the transition, beside the job's own SSE event. Carries ids, type, owner, state, times and result locations; never the job's input, its files, its output data or a session. Jobs of sandbox app tokens are not announced. Envelope: subject { type: job, id: <job_id> }, visibility internal, priority important, actor service:tools.++ */++export interface ToolsJobFailedPayload {++ job_id: string;++ /**++ * The Tools satellite that runs the job (img, audio, docs…).++ */++ service: string;++ /**++ * Job type, e.g. img.process.++ */++ type: string;++ type_version: number;++ state: "failed";++ /**++ * Who submitted the job: a user (user:usr_…), a service, app or mod principal. null for an anonymous browser session; the session is never published.++ */++ owner: SubjectRef | null;++ attempts: number;++ max_attempts: number;++ created_at: string;++ /**++ * The failed job this one retries (POST /api/v1/jobs/:id/retry).++ */++ retry_of: string | null;++ /**++ * null when the job failed before it ever ran.++ */++ started_at: string | null;++ finished_at: string;++ /**++ * When the job and its result files are pruned; null while something references the result (PUT /api/v1/jobs/:id/references/:ref).++ */++ expires_at: string | null;++ /**++ * The job's problem (errors.problem@1) without request or trace ids.++ */++ error: {++ status: number;++ /**++ * tools.job.failed, tools.job.timeout, or a code the tool chose (tools.…: tools.pdf.too_many_pages, tools.pdf.wrong_password…).++ */++ code: string;++ /**++ * Human-readable reason; server paths are scrubbed.++ */++ detail: string;++ };++ retryable: boolean;++}++++/** [email protected] (owner: media) */++/**++ * media.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff action on someone else's media in OpenVibe.Media: a retention hold placed or released (moderation, dmca, admin, evidence), and a staff deletion or visibility change of someone else's VOD, clip or object. Not an owner acting on their own media, and not a creator's own pin. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member (or the service acting for an app's staff). Never carries the media itself.++ */++export interface MediaModerationActionPayload {++ /**++ * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).++ */++ action: string;++ target: {++ /**++ * What was acted on, in the service's own words (post, page, release, user, player, …).++ */++ type: string;++ id: string;++ /**++ * Whose content or account it was, when known.++ */++ owner_subject?: string | null;++ };++ /**++ * The staff member or moderator (null only for a service acting without a person).++ */++ actor_subject: string | null;++ reason?: string | null;++ /**++ * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.++ */++ details?: {};++}++++/** [email protected] (owner: tools) */++/**++ * tools.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff or moderator action on someone else's content or account in OpenVibe.Tools (apps/gateway and its guard), such as guard blocks and unblocks of an account, an app or an address, and staff actions on someone else's jobs or tool pages. Not a person acting on their own content. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member. Never carries the content itself.++ */++export interface ToolsModerationActionPayload {++ /**++ * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).++ */++ action: string;++ target: {++ /**++ * What was acted on, in the service's own words (post, page, release, user, player, …).++ */++ type: string;++ id: string;++ /**++ * Whose content or account it was, when known.++ */++ owner_subject?: string | null;++ };++ /**++ * The staff member or moderator (null only for a service acting without a person).++ */++ actor_subject: string | null;++ reason?: string | null;++ /**++ * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.++ */++ details?: {};++}++++/** [email protected] (owner: tools) */++/**++ * tools.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Tools apps/_shared/jobs/usage.js). One hour of a developer project's jobs on one Tools satellite, per capability (tools.job.create for POST /api/v1/jobs, tools.tool.run for a tool run) and job type or tool (dimension), in unit jobs: quantity counts the jobs that ended (succeeded or failed; a cancelled job is not counted), errors the failed ones, by code, with the last failures' job ids and trace ids. Counted in the transaction that records a job's end; written to the satellite's outbox after the hour closes. Only jobs of developer-app tokens (they carry a project) are counted; sandbox jobs are counted under env sandbox. The payload is common.usage-recorded@1. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:tools.++ */++export interface ToolsUsageRecordedPayload {++ /**++ * The developer project whose app token did the work.++ */++ project_id: string;++ /**++ * The environment of that app token.++ */++ env: "sandbox" | "production";++ /**++ * The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe.++ */++ capability: string;++ /**++ * Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job.++ */++ dimension?: string;++ /**++ * What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit.++ */++ unit: string;++ /**++ * The length of the window.++ */++ window: "hour" | "day";++ /**++ * UTC, on the hour (midnight for a day).++ */++ window_start: string;++ /**++ * window_start plus the window, exclusive.++ */++ window_end: string;++ /**++ * Units used in the window, by work that succeeded and work that failed alike.++ */++ quantity: number;++ /**++ * Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity.++ */++ errors: number;++ /**++ * The errors by problem code (at most 20 codes; the rest are only in errors).++ */++ error_codes?: {++ [k: string]: number | undefined;++ };++ /**++ * The last failures of the window, newest first, so a developer can find them in their own logs.++ *++ * @maxItems 10++ */++ samples?:++ | []++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ];++ /**++ * 1 when absent. A producer that re-emits a window with corrected totals raises it.*/-- result: {-- /**-- * @maxItems 100-- */-- files: {-- /**-- * n in /api/v1/jobs/:id/files/:n.-- */-- index: number;-- mime: string;-- size: number;-- sha256: string;-- /**-- * media: stored as an OpenVibe.Media object (TOOLS_JOB_RESULTS=media); local: kept on the satellite until the job expires.-- */-- storage: "local" | "media";-- /**-- * { media_id, role: output } when storage is media.-- */-- media: MediaRef | null;-- }[];-- };++ revision?: number;}--/** [email protected] (owner: tools) */++/** [email protected] (owner: events) *//**-- * tools.job.failed v1 (OpenVibe.Tools apps/_shared/jobs/events.js). The job failed: the tool refused the input, it timed out, or it was running when the satellite restarted and its type does not requeue. A cancelled job is not a failure and is not announced as one. Emitted in the transaction that records the transition, beside the job's own SSE event. Carries ids, type, owner, state, times and result locations; never the job's input, its files, its output data or a session. Jobs of sandbox app tokens are not announced. Envelope: subject { type: job, id: <job_id> }, visibility internal, priority important, actor service:tools.++ * events.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Events server/usage.js). One hour of a developer project's use of OpenVibe.Events in one environment: events.app.publish in unit events (quantity counts the events stored; errors the publish requests refused with a problem, such as 429 events.quota_exceeded or 403 events.type_not_allowed) and events.app.subscribe in unit deliveries (quantity counts webhook delivery attempts to the project's subscriptions; errors the attempts without a 2xx, as events.delivery.http_<status>, events.delivery.timeout or events.delivery.failed). Counted in the transaction that stores the events or records the attempt (a refusal right after it is answered); Events stores the rollup as its own event after the hour closes, in the same transaction that marks it sent. The payload is common.usage-recorded@1. Envelope: source events, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:events.*/--export interface ToolsJobFailedPayload {-- job_id: string;-- /**-- * The Tools satellite that runs the job (img, audio, docs…).-- */-- service: string;-- /**-- * Job type, e.g. img.process.-- */-- type: string;-- type_version: number;-- state: "failed";-- /**-- * Who submitted the job: a user (user:usr_…), a service, app or mod principal. null for an anonymous browser session; the session is never published.-- */-- owner: SubjectRef | null;-- attempts: number;-- max_attempts: number;-- created_at: string;-- /**-- * The failed job this one retries (POST /api/v1/jobs/:id/retry).-- */-- retry_of: string | null;++export interface EventsUsageRecordedPayload {/**-- * null when the job failed before it ever ran.++ * The developer project whose app token did the work.*/-- started_at: string | null;-- finished_at: string;++ project_id: string;/**-- * When the job and its result files are pruned; null while something references the result (PUT /api/v1/jobs/:id/references/:ref).++ * The environment of that app token.*/-- expires_at: string | null;++ env: "sandbox" | "production";/**-- * The job's problem (errors.problem@1) without request or trace ids.++ * The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe.*/-- error: {-- status: number;-- /**-- * tools.job.failed, tools.job.timeout, or a code the tool chose (tools.…: tools.pdf.too_many_pages, tools.pdf.wrong_password…).-- */-- code: string;-- /**-- * Human-readable reason; server paths are scrubbed.-- */-- detail: string;-- };-- retryable: boolean;--}----/** [email protected] (owner: media) */--/**-- * media.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff action on someone else's media in OpenVibe.Media: a retention hold placed or released (moderation, dmca, admin, evidence), and a staff deletion or visibility change of someone else's VOD, clip or object. Not an owner acting on their own media, and not a creator's own pin. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member (or the service acting for an app's staff). Never carries the media itself.-- */--export interface MediaModerationActionPayload {++ capability: string;/**-- * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).++ * Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job.*/-- action: string;-- target: {-- /**-- * What was acted on, in the service's own words (post, page, release, user, player, …).-- */-- type: string;-- id: string;-- /**-- * Whose content or account it was, when known.-- */-- owner_subject?: string | null;-- };++ dimension?: string;/**-- * The staff member or moderator (null only for a service acting without a person).++ * What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit.*/-- actor_subject: string | null;-- reason?: string | null;++ unit: string;/**-- * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.++ * The length of the window.*/-- details?: {};--}----/** [email protected] (owner: tools) */--/**-- * tools.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff or moderator action on someone else's content or account in OpenVibe.Tools (apps/gateway and its guard), such as guard blocks and unblocks of an account, an app or an address, and staff actions on someone else's jobs or tool pages. Not a person acting on their own content. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member. Never carries the content itself.-- */--export interface ToolsModerationActionPayload {++ window: "hour" | "day";/**-- * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).++ * UTC, on the hour (midnight for a day).*/-- action: string;-- target: {-- /**-- * What was acted on, in the service's own words (post, page, release, user, player, …).-- */-- type: string;-- id: string;-- /**-- * Whose content or account it was, when known.-- */-- owner_subject?: string | null;++ window_start: string;++ /**++ * window_start plus the window, exclusive.++ */++ window_end: string;++ /**++ * Units used in the window, by work that succeeded and work that failed alike.++ */++ quantity: number;++ /**++ * Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity.++ */++ errors: number;++ /**++ * The errors by problem code (at most 20 codes; the rest are only in errors).++ */++ error_codes?: {++ [k: string]: number | undefined;};/**-- * The staff member or moderator (null only for a service acting without a person).++ * The last failures of the window, newest first, so a developer can find them in their own logs.++ *++ * @maxItems 10*/-- actor_subject: string | null;-- reason?: string | null;++ samples?:++ | []++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ]++ | [++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ },++ {++ at: string;++ code: string;++ /**++ * The HTTP status the failure was answered with, when there was one.++ */++ status?: number;++ /**++ * The W3C trace id of the request (or event) that failed.++ */++ trace_id?: string;++ /**++ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.++ */++ ref?: string;++ }++ ];/**-- * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.++ * 1 when absent. A producer that re-emits a window with corrected totals raises it.*/-- details?: {};++ revision?: number;}/** [email protected] (owner: live) */@@@ -26310,6 +29202,106 @@ export interface NetworkRealtimeTicketResult {subject: string;}++/** [email protected] (owner: network) */++/**++ * network.project-usage-result@1 (roadmap WS-N task 4, ADR-014): what GET /api/v1/projects/:project/usage?days=&env= on OpenVibe.Network answers a project's owner or admin (or staff): the project's usage per day, service, capability and unit, added up from the <service>.usage.recorded rollups (common.usage-recorded@1) the owning services emit after each hour closes; the project's recorded quotas with what the current window has used; and its recent failures with their codes and trace ids. Counts only, never who did what: no subject id, address, input or content.++ */++export interface ProjectUsageResult {++ project_id: string;++ /**++ * The environments counted (the env query parameter; all by default).++ */++ env: "all" | "sandbox" | "production";++ range: {++ days: number;++ /**++ * First UTC day counted.++ */++ from: string;++ /**++ * Last UTC day counted (today).++ */++ to: string;++ };++ generated_at: string;++ /**++ * When the newest rollup for this project arrived; null before the first.++ */++ last_recorded_at: string | null;++ /**++ * How current the numbers are, in words (rollups arrive after each hour closes).++ */++ freshness: string;++ /**++ * The whole range per service, capability, unit and environment.++ */++ totals: {++ service: Service;++ capability: Capability;++ unit: Unit;++ env: Env;++ quantity: Count;++ errors: Count;++ }[];++ /**++ * One row per UTC day, service, capability, dimension, unit and environment that saw usage; days without any are absent. Newest day first.++ */++ daily: {++ day: string;++ service: Service;++ capability: Capability;++ dimension: string | null;++ unit: Unit;++ env: Env;++ quantity: Count;++ errors: Count;++ }[];++ /**++ * The project's recorded quotas (GET /api/v1/projects/:project/quotas), each with what its current window has used, in every environment together. used is null where the rollups cannot tell (a minute or hour window, or a unit no service reports for that capability).++ */++ quotas: {++ capability: Capability;++ limit: number;++ window: "minute" | "hour" | "day" | "month" | "total";++ unit: Unit;++ /**++ * The audience of the service that enforces it (openvibe.<owner>).++ */++ enforced_by: string | null;++ used: number | null;++ remaining: number | null;++ /**++ * Start of the current window counted (today, this month); null for total and when used is null.++ */++ window_start: string | null;++ note: string | null;++ }[];++ errors: {++ total: Count;++ by_code: {++ service: Service;++ capability: Capability;++ code: Code;++ count: Count;++ }[];++ /**++ * The newest failures the rollups sampled, newest first.++ *++ * @maxItems 50++ */++ recent: {++ at: string;++ env: Env;++ service: Service;++ capability: Capability;++ code: Code;++ status: number | null;++ trace_id: string | null;++ ref: string | null;++ }[];++ };++}++/** [email protected] (owner: network) *//*** network.staff-list-result@1: the answer of network.staff.read on OpenVibe.Network. GET /api/v1/staff/moderators[?service=chat|live|community|pastes|calls] (a service token holding network.staff.read, or a signed-in person holding staff.moderation.logs) → { service, staff }: the network's global moderators, admins and the owner who are not banned, with the staff capabilities their role holds in the contracts staff map; ?service keeps those holding the capability that moderates that service (another service name keeps those holding staff.content.moderate; an invalid value is ignored and answered as null). Answered with Cache-Control: private, no-store; a person without staff.moderation.logs gets 403 { error: forbidden }.@@@ -27,7 +27,9 @@"events.app.read","events.app.subscribe"],-- "eventsProduced": [],++ "eventsProduced": [++ "events.usage.recorded"++ ],"eventsConsumed": [],"namespacesOwned": [],"lifecycle": {@@@ -69,6 +69,7 @@"coupons.moderation.action","deals.moderation.action","deals.watch.matched",++ "events.usage.recorded","games.moderation.action","live.moderation.action","live.stream.started",@@@ -77,6 +78,7 @@"reviews.moderation.action","tips.interaction.moderated","tools.moderation.action",++ "tools.usage.recorded","trade.alert.triggered","trade.moderation.action","wiki.moderation.action"@@@ -39,7 +39,8 @@"tools.job.started","tools.job.succeeded","tools.job.failed",-- "tools.moderation.action"++ "tools.moderation.action",++ "tools.usage.recorded"],"eventsConsumed": ["network.user.token_valid_after"@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.62.0",++ "version": "0.63.0","description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.","main": "index.js","types": "generated/typescript/index.d.ts",@@@ -791,6 +791,35 @@ await assert.rejects(failing.getToken(), /401: invalid_client/);ok(R({ ...r, expires_in: 300 }) && !R({ ...r, expires_in: 301 }), 'a ticket lives at most 300 s');}++// ── Project usage (WS-N task 4, ADR-014): one shared rollup payload, one event per producer ──++// Every <service>.usage.recorded is common.usage-recorded@1, owned by its service and consumed by++// Network (the project dashboard). A rollup counts, it never says who: no subject, app, address,++// input or message, and at most ten sampled failures.++{++ const usage = contracts.catalog.filter(c => /\.usage\.recorded$/.test(c.id));++ ok(usage.length >= 2 && ['tools', 'events'].every(svc => usage.some(c => c.id === `${svc}.usage.recorded`)), 'tools and events publish usage rollups');++ for (const c of usage) {++ ok(c.owner === c.id.split('.')[0] && c.adr === 'ADR-014', `${c.id} is owned by ${c.id.split('.')[0]}`);++ ok(contracts.schema(c.id).$ref === '../../common/usage-recorded.v1.json', `${c.id} is a common.usage-recorded@1`);++ ok(services.get('network').eventsConsumed.includes(c.id), `network consumes ${c.id} into project usage`);++ }++ const U = (v) => contracts.validate('common.usage-recorded@1', v).valid;++ const base = JSON.parse(fs.readFileSync(path.join(ROOT, 'fixtures/common.usage-recorded/valid/tools-jobs-hour.json'), 'utf8'));++ ok(U(base), 'an hour of jobs');++ for (const k of ['project_id', 'env', 'capability', 'unit', 'window', 'window_start', 'window_end', 'quantity', 'errors']) ok(!U({ ...base, [k]: undefined }), `a rollup needs ${k}`);++ for (const k of ['subject', 'owner', 'actor', 'user_id', 'app_id', 'ip', 'session', 'input', 'request_id']) ok(!U({ ...base, [k]: 'x' }), `a rollup never carries ${k}`);++ const props = Object.keys(contracts.schema('common.usage-recorded').properties);++ ok(!props.some(p => /subject|owner|actor|user|ip|session|address/.test(p)), 'no field of the rollup names who did it');++ const sample = base.samples[0];++ ok(!U({ ...base, samples: Array.from({ length: 11 }, () => sample) }), 'at most ten sampled failures: a rollup, not a request log');++ for (const ref of ['usr_01JAB2C3D4E5F6G7H8J9K0MNPQ', 'app_01JAB2C3D4E5F6G7H8J9K0MNPQ', 'req_01JAB2C3D4E5F6G7H8J9K0MNPQ']) ok(!U({ ...base, samples: [{ ...sample, ref }] }), `a sample never refers to ${ref.slice(0, 3)}_`);++ ok(!U({ ...base, window: 'minute' }) && U({ ...base, window: 'day' }), 'windows are an hour or a day');++ const R = (v) => contracts.validate('network.project-usage-result@1', v).valid;++ const res = JSON.parse(fs.readFileSync(path.join(ROOT, 'fixtures/network.project-usage-result/valid/dashboard.json'), 'utf8'));++ ok(R(res) && !R({ ...res, range: { ...res.range, days: 91 } }), 'a dashboard covers at most 90 days');++ ok(res.errors.recent.every(e => contracts.validate('common.usage-recorded@1', { ...base, samples: [{ at: e.at, code: e.code, ...(e.status ? { status: e.status } : {}), ...(e.trace_id ? { trace_id: e.trace_id } : {}), ...(e.ref ? { ref: e.ref } : {}) }] }).valid), 'the dashboard\'s recent failures are the rollups\' samples');++}++// ── Capability schemas (WS-C task 4): a ratchet over compatibility/capability-schema-gaps.json ──execFileSync(process.execPath, [path.join(__dirname, 'capability-schemas.test.js')], { stdio: 'inherit' });
@@ -6,6 +6,16 @@ the notes were in the tag and commit messages (`git tag -n1`).
@@ -6,6 +6,16 @@ the notes were in the tag and commit messages (`git tag -n1`).
## Unreleased
## Unreleased
+## 0.63.0 — 2026-09-26
+
+**Project usage rollups** (roadmap WS-N task 4, ADR-014): what feeds the per-project dashboards on OpenVibe.Codes.
+- **New `common.usage-recorded@1`**: one closed window (an hour or a day) of one developer project's use of one capability in one environment, as the owning service counted it: `project_id`, `env`, `capability`, an optional `dimension` (a job type or tool id), `unit`, `window`, `window_start`, `window_end`, `quantity`, `errors`, `error_codes` (up to 20) and `samples` (up to 10 recent failures: time, code, status, trace id and a job, event, run or object id), plus `revision`. Totals, not deltas: a later rollup with the same key replaces the earlier one. It never names who did the work (no subject, app, address, session, input or message), and no producer emits one per request.
+- **New event types `tools.usage.recorded`** (a Tools satellite's hour of a project's jobs, unit `jobs`, per `tools.job.create` or `tools.tool.run` and job type or tool) **and `events.usage.recorded`** (Events: `events.app.publish` in `events`, refusals as errors; `events.app.subscribe` in `deliveries`, failed webhook attempts as errors). Both payloads are `common.usage-recorded@1`; envelope subject `{ type: project, id: <project_id> }`, visibility `internal`, priority `low`. The Tools and Events manifests produce them; Network consumes both.
+- **New `network.project-usage-result@1`**: what `GET /api/v1/projects/:project/usage?days=&env=` on Network answers a project's owner, admins and staff: daily rows and range totals per service, capability, unit and environment, the project's recorded quotas with what their current window used, and errors by code with the recent sampled failures.
+- `npm test` checks that each `<service>.usage.recorded` is the common payload, owned by its service and consumed by Network, and that a rollup carries no identity and at most ten samples.
+
+Additive.
+
## 0.62.0 — 2026-09-26
## 0.62.0 — 2026-09-26
**Operator alerts** (roadmap WS-H task 11; the delivery path that Host's Prometheus alerts lacked).
**Operator alerts** (roadmap WS-H task 11; the delivery path that Host's Prometheus alerts lacked).
@@ -95,6 +95,10 @@ const r = contracts.validate(`${env.event_type}@${env.version}`, env.payload);
@@ -95,6 +95,10 @@ const r = contracts.validate(`${env.event_type}@${env.version}`, env.payload);
**Redaction (ADR-026).** Any event may carry `payload.redacts` (`events.redaction-directive@1`), shaped `{ event_ids?, subject_type?, subject_ids? }` with up to 1000 ids each, to take back the producer's own earlier events. OpenVibe.Events rewrites each target into a tombstone at its original seq: `{ redacted: true, redacted_at, redacted_by }`, with the producer itself as actor. Naming another source's event refuses the whole batch with 403 `events.redaction_not_allowed`. A malformed directive gets 422 `events.invalid_redaction`. `chat.message.deleted` always carries one. Browsers are replayed only the `public` events of the last `REALTIME_PUBLIC_REPLAY_SECONDS` (default 300); an older cursor gets `event: gap` with reason `public_window`.
**Redaction (ADR-026).** Any event may carry `payload.redacts` (`events.redaction-directive@1`), shaped `{ event_ids?, subject_type?, subject_ids? }` with up to 1000 ids each, to take back the producer's own earlier events. OpenVibe.Events rewrites each target into a tombstone at its original seq: `{ redacted: true, redacted_at, redacted_by }`, with the producer itself as actor. Naming another source's event refuses the whole batch with 403 `events.redaction_not_allowed`. A malformed directive gets 422 `events.invalid_redaction`. `chat.message.deleted` always carries one. Browsers are replayed only the `public` events of the last `REALTIME_PUBLIC_REPLAY_SECONDS` (default 300); an older cursor gets `event: gap` with reason `public_window`.
+## Project usage rollups (v0.63)
+
+The services that own a developer capability count each project's use of it and report one rollup per closed hour, never one event per request (roadmap WS-N task 4). Every `<service>.usage.recorded` event carries `common.usage-recorded@1`: project, environment, capability, optional dimension (job type, tool), unit, window, quantity, errors, errors by code and up to ten sampled failures with their trace ids. Emitted today: `tools.usage.recorded` (jobs) and `events.usage.recorded` (published events, webhook deliveries). OpenVibe.Network adds them up per project and day and answers `GET /api/v1/projects/:project/usage` (`network.project-usage-result@1`) to the project's owner and admins; OpenVibe.Codes shows it as the project's usage page. A rollup is totals, not a delta: the latest one for a key replaces the earlier, so a producer may re-send a window safely.
+
## Event delivery signatures
## Event delivery signatures
OpenVibe.Events POSTs each webhook delivery as `{ "event": <events.event-envelope@1>, "seq": n }`, keyed with the subscription secret:
OpenVibe.Events POSTs each webhook delivery as `{ "event": <events.event-envelope@1>, "seq": n }`, keyed with the subscription secret:
@@ -210,6 +210,16 @@
@@ -210,6 +210,16 @@
"status": "active",
"status": "active",
"adr": "ADR-022"
"adr": "ADR-022"
},
},
+ {
+ "id": "common.usage-recorded",
+ "version": "1.0.0",
+ "owner": "network",
+ "schema": "common/usage-recorded.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-014"
+ },
{
{
"id": "media.file-upload",
"id": "media.file-upload",
"version": "1.0.0",
"version": "1.0.0",
@@ -2249,6 +2259,26 @@
@@ -2249,6 +2259,26 @@
"status": "active",
"status": "active",
"adr": "ADR-022"
"adr": "ADR-022"
},
},
+ {
+ "id": "tools.usage.recorded",
+ "version": "1.0.0",
+ "owner": "tools",
+ "schema": "events/payloads/tools.usage.recorded.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-014"
+ },
+ {
+ "id": "events.usage.recorded",
+ "version": "1.0.0",
+ "owner": "events",
+ "schema": "events/payloads/events.usage.recorded.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-014"
+ },
{
{
"id": "live.stream.started",
"id": "live.stream.started",
"version": "1.0.0",
"version": "1.0.0",
@@ -2513,6 +2543,16 @@
@@ -2513,6 +2543,16 @@
"status": "active",
"status": "active",
"adr": "ADR-005"
"adr": "ADR-005"
},
},
+ {
+ "id": "network.project-usage-result",
+ "version": "1.0.0",
+ "owner": "network",
+ "schema": "network/project-usage-result.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-014"
+ },
{
{
"id": "network.staff-list-result",
"id": "network.staff-list-result",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/common/usage-recorded.v1.json",
+ "title": "UsageRecorded",
+ "description": "common.usage-recorded@1 (roadmap WS-N task 4, ADR-014): one rollup of a developer project's use of one capability in one environment over one closed window (an hour or a day), as the service that owns the capability counted it. The payload of every <service>.usage.recorded event; OpenVibe.Network adds them up per project and day for the project's dashboard on OpenVibe.Codes. The producer counts in the transaction that does its own accounting (a job's end, a stored event, a delivery attempt) and writes the rollup to its outbox after the window has closed: never one event per request. Totals, not deltas: a later event with the same key (source, project_id, env, capability, dimension, unit, window_start) replaces the earlier one, and a lower revision never replaces a higher one. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor the producing service. Never carries a subject id, an address, a session, a request's input or content, or a file name.",
+ "type": "object",
+ "required": ["project_id", "env", "capability", "unit", "window", "window_start", "window_end", "quantity", "errors"],
+ "additionalProperties": false,
+ "properties": {
+ "project_id": { "type": "string", "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$", "description": "The developer project whose app token did the work." },
+ "env": { "enum": ["sandbox", "production"], "description": "The environment of that app token." },
+ "capability": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$",
+ "maxLength": 80,
+ "description": "The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe."
+ },
+ "dimension": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "pattern": "^[a-z0-9][a-z0-9_.:-]*$",
+ "not": { "pattern": "^(usr|gst|app|mod|svc|job|evt|req)_" },
+ "description": "Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job."
+ },
+ "unit": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$",
+ "description": "What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit."
+ },
+ "window": { "enum": ["hour", "day"], "description": "The length of the window." },
+ "window_start": { "type": "string", "format": "date-time", "description": "UTC, on the hour (midnight for a day)." },
+ "window_end": { "type": "string", "format": "date-time", "description": "window_start plus the window, exclusive." },
+ "quantity": { "type": "integer", "minimum": 0, "description": "Units used in the window, by work that succeeded and work that failed alike." },
+ "errors": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity."
+ },
+ "error_codes": {
+ "type": "object",
+ "maxProperties": 20,
+ "propertyNames": { "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$", "maxLength": 80 },
+ "additionalProperties": { "type": "integer", "minimum": 1 },
+ "description": "The errors by problem code (at most 20 codes; the rest are only in errors)."
+ },
+ "samples": {
+ "type": "array",
+ "maxItems": 10,
+ "description": "The last failures of the window, newest first, so a developer can find them in their own logs.",
+ "items": {
+ "type": "object",
+ "required": ["at", "code"],
+ "additionalProperties": false,
+ "properties": {
+ "at": { "type": "string", "format": "date-time" },
+ "code": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$", "maxLength": 80 },
+ "status": { "type": "integer", "minimum": 100, "maximum": 599, "description": "The HTTP status the failure was answered with, when there was one." },
+ "trace_id": { "type": "string", "pattern": "^[0-9a-f]{32}$", "description": "The W3C trace id of the request (or event) that failed." },
+ "ref": {
+ "type": "string",
+ "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject."
+ }
+ }
+ }
+ },
+ "revision": { "type": "integer", "minimum": 1, "description": "1 when absent. A producer that re-emits a window with corrected totals raises it." }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/events.usage.recorded.v1.json",
+ "title": "EventsUsageRecordedPayload",
+ "description": "events.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Events server/usage.js). One hour of a developer project's use of OpenVibe.Events in one environment: events.app.publish in unit events (quantity counts the events stored; errors the publish requests refused with a problem, such as 429 events.quota_exceeded or 403 events.type_not_allowed) and events.app.subscribe in unit deliveries (quantity counts webhook delivery attempts to the project's subscriptions; errors the attempts without a 2xx, as events.delivery.http_<status>, events.delivery.timeout or events.delivery.failed). Counted in the transaction that stores the events or records the attempt (a refusal right after it is answered); Events stores the rollup as its own event after the hour closes, in the same transaction that marks it sent. The payload is common.usage-recorded@1. Envelope: source events, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:events.",
+ "$ref": "../../common/usage-recorded.v1.json"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/tools.usage.recorded.v1.json",
+ "title": "ToolsUsageRecordedPayload",
+ "description": "tools.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Tools apps/_shared/jobs/usage.js). One hour of a developer project's jobs on one Tools satellite, per capability (tools.job.create for POST /api/v1/jobs, tools.tool.run for a tool run) and job type or tool (dimension), in unit jobs: quantity counts the jobs that ended (succeeded or failed; a cancelled job is not counted), errors the failed ones, by code, with the last failures' job ids and trace ids. Counted in the transaction that records a job's end; written to the satellite's outbox after the hour closes. Only jobs of developer-app tokens (they carry a project) are counted; sandbox jobs are counted under env sandbox. The payload is common.usage-recorded@1. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:tools.",
+ "$ref": "../../common/usage-recorded.v1.json"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/network/project-usage-result.v1.json",
+ "title": "ProjectUsageResult",
+ "description": "network.project-usage-result@1 (roadmap WS-N task 4, ADR-014): what GET /api/v1/projects/:project/usage?days=&env= on OpenVibe.Network answers a project's owner or admin (or staff): the project's usage per day, service, capability and unit, added up from the <service>.usage.recorded rollups (common.usage-recorded@1) the owning services emit after each hour closes; the project's recorded quotas with what the current window has used; and its recent failures with their codes and trace ids. Counts only, never who did what: no subject id, address, input or content.",
+ "type": "object",
+ "required": ["project_id", "env", "range", "generated_at", "last_recorded_at", "freshness", "totals", "daily", "quotas", "errors"],
+ "additionalProperties": false,
+ "$defs": {
+ "service": { "type": "string", "pattern": "^[a-z][a-z0-9-]{1,39}$" },
+ "capability": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$", "maxLength": 80 },
+ "unit": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,31}$" },
+ "env": { "enum": ["sandbox", "production"] },
+ "code": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$", "maxLength": 80 },
+ "count": { "type": "integer", "minimum": 0 }
+ },
+ "properties": {
+ "project_id": { "type": "string", "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$" },
+ "env": { "enum": ["all", "sandbox", "production"], "description": "The environments counted (the env query parameter; all by default)." },
+ "range": {
+ "type": "object",
+ "required": ["days", "from", "to"],
+ "additionalProperties": false,
+ "properties": {
+ "days": { "type": "integer", "minimum": 1, "maximum": 90 },
+ "from": { "type": "string", "format": "date", "description": "First UTC day counted." },
+ "to": { "type": "string", "format": "date", "description": "Last UTC day counted (today)." }
+ }
+ },
+ "generated_at": { "type": "string", "format": "date-time" },
+ "last_recorded_at": { "type": ["string", "null"], "format": "date-time", "description": "When the newest rollup for this project arrived; null before the first." },
+ "freshness": { "type": "string", "maxLength": 300, "description": "How current the numbers are, in words (rollups arrive after each hour closes)." },
+ "totals": {
+ "type": "array",
+ "description": "The whole range per service, capability, unit and environment.",
+ "items": {
+ "type": "object",
+ "required": ["service", "capability", "unit", "env", "quantity", "errors"],
+ "additionalProperties": false,
+ "properties": {
+ "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" }, "unit": { "$ref": "#/$defs/unit" },
+ "env": { "$ref": "#/$defs/env" }, "quantity": { "$ref": "#/$defs/count" }, "errors": { "$ref": "#/$defs/count" }
+ }
+ }
+ },
+ "daily": {
+ "type": "array",
+ "description": "One row per UTC day, service, capability, dimension, unit and environment that saw usage; days without any are absent. Newest day first.",
+ "items": {
+ "type": "object",
+ "required": ["day", "service", "capability", "dimension", "unit", "env", "quantity", "errors"],
+ "additionalProperties": false,
+ "properties": {
+ "day": { "type": "string", "format": "date" },
+ "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" },
+ "dimension": { "type": ["string", "null"], "maxLength": 80 },
+ "unit": { "$ref": "#/$defs/unit" }, "env": { "$ref": "#/$defs/env" },
+ "quantity": { "$ref": "#/$defs/count" }, "errors": { "$ref": "#/$defs/count" }
+ }
+ }
+ },
+ "quotas": {
+ "type": "array",
+ "description": "The project's recorded quotas (GET /api/v1/projects/:project/quotas), each with what its current window has used, in every environment together. used is null where the rollups cannot tell (a minute or hour window, or a unit no service reports for that capability).",
+ "items": {
+ "type": "object",
+ "required": ["capability", "limit", "window", "unit", "enforced_by", "used", "remaining", "window_start", "note"],
+ "additionalProperties": false,
+ "properties": {
+ "capability": { "$ref": "#/$defs/capability" },
+ "limit": { "type": "integer", "minimum": 0 },
+ "window": { "enum": ["minute", "hour", "day", "month", "total"] },
+ "unit": { "$ref": "#/$defs/unit" },
+ "enforced_by": { "type": ["string", "null"], "description": "The audience of the service that enforces it (openvibe.<owner>)." },
+ "used": { "type": ["integer", "null"], "minimum": 0 },
+ "remaining": { "type": ["integer", "null"], "minimum": 0 },
+ "window_start": { "type": ["string", "null"], "format": "date-time", "description": "Start of the current window counted (today, this month); null for total and when used is null." },
+ "note": { "type": ["string", "null"], "maxLength": 300 }
+ }
+ }
+ },
+ "errors": {
+ "type": "object",
+ "required": ["total", "by_code", "recent"],
+ "additionalProperties": false,
+ "properties": {
+ "total": { "$ref": "#/$defs/count" },
+ "by_code": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["service", "capability", "code", "count"],
+ "additionalProperties": false,
+ "properties": { "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" }, "code": { "$ref": "#/$defs/code" }, "count": { "$ref": "#/$defs/count" } }
+ }
+ },
+ "recent": {
+ "type": "array",
+ "maxItems": 50,
+ "description": "The newest failures the rollups sampled, newest first.",
+ "items": {
+ "type": "object",
+ "required": ["at", "env", "service", "capability", "code", "status", "trace_id", "ref"],
+ "additionalProperties": false,
+ "properties": {
+ "at": { "type": "string", "format": "date-time" },
+ "env": { "$ref": "#/$defs/env" }, "service": { "$ref": "#/$defs/service" }, "capability": { "$ref": "#/$defs/capability" },
+ "code": { "$ref": "#/$defs/code" },
+ "status": { "type": ["integer", "null"], "minimum": 100, "maximum": 599 },
+ "trace_id": { "type": ["string", "null"], "pattern": "^[0-9a-f]{32}$" },
+ "ref": { "type": ["string", "null"], "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$" }
+ }
+ }
+ }
+ }
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ],
+ "ip": "203.0.113.7"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ],
+ "app_id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "usr_01jab2c3d4e5f6g7h8j9k0mnpq",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "Timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "day",
+ "window_start": "2026-09-25T00:00:00.000Z",
+ "window_end": "2026-09-26T00:00:00.000Z",
+ "quantity": -1,
+ "errors": 0
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "day",
+ "window_end": "2026-09-26T00:00:00.000Z",
+ "quantity": 0,
+ "errors": 0
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "minute",
+ "window_start": "2026-09-25T00:00:00.000Z",
+ "window_end": "2026-09-26T00:00:00.000Z",
+ "quantity": 0,
+ "errors": 0
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.failed",
+ "detail": "Cannot read holiday.jpg"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.failed",
+ "ref": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "staging",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "day",
+ "window_start": "2026-09-25T00:00:00.000Z",
+ "window_end": "2026-09-26T00:00:00.000Z",
+ "quantity": 0,
+ "errors": 0
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "sandbox",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "window": "hour",
+ "window_start": "2026-09-26T09:00:00.000Z",
+ "window_end": "2026-09-26T10:00:00.000Z",
+ "quantity": 1800,
+ "errors": 61,
+ "error_codes": {
+ "events.quota_exceeded": 60,
+ "events.type_not_allowed": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "day",
+ "window_start": "2026-09-25T00:00:00.000Z",
+ "window_end": "2026-09-26T00:00:00.000Z",
+ "quantity": 0,
+ "errors": 0
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "day",
+ "window_start": "2026-09-25T00:00:00.000Z",
+ "window_end": "2026-09-26T00:00:00.000Z",
+ "quantity": 7,
+ "errors": 0,
+ "revision": 2
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "sandbox",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "window": "hour",
+ "window_start": "2026-09-26T09:00:00.000Z",
+ "window_end": "2026-09-26T10:00:00.000Z",
+ "quantity": 1800,
+ "errors": 61,
+ "error_codes": {
+ "events.quota_exceeded": 60,
+ "events.type_not_allowed": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c"
+ }
+ ],
+ "payload": {
+ "type": "app.p01jab.order.created"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "project_id": "live",
+ "env": "sandbox",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "window": "hour",
+ "window_start": "2026-09-26T09:00:00.000Z",
+ "window_end": "2026-09-26T10:00:00.000Z",
+ "quantity": 1800,
+ "errors": 61,
+ "error_codes": {
+ "events.quota_exceeded": 60,
+ "events.type_not_allowed": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "events.app.subscribe",
+ "unit": "deliveries",
+ "window": "hour",
+ "window_start": "2026-09-26T10:00:00.000Z",
+ "window_end": "2026-09-26T11:00:00.000Z",
+ "quantity": 12,
+ "errors": 2,
+ "error_codes": {
+ "events.delivery.http_500": 1,
+ "events.delivery.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T10:31:00.000Z",
+ "code": "events.delivery.timeout",
+ "trace_id": "0af7651916cd43dd8448eb211c80319c",
+ "ref": "evt_01JAB2C3D4E5F6G7H8J9K0MNPT"
+ },
+ {
+ "at": "2026-09-26T10:30:00.000Z",
+ "code": "events.delivery.http_500",
+ "status": 500,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c",
+ "ref": "evt_01JAB2C3D4E5F6G7H8J9K0MNPT"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "sandbox",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "window": "hour",
+ "window_start": "2026-09-26T09:00:00.000Z",
+ "window_end": "2026-09-26T10:00:00.000Z",
+ "quantity": 1800,
+ "errors": 61,
+ "error_codes": {
+ "events.quota_exceeded": 60,
+ "events.type_not_allowed": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "all",
+ "range": {
+ "days": 365,
+ "from": "2026-08-28",
+ "to": "2026-09-26"
+ },
+ "generated_at": "2026-09-26T15:05:00.000Z",
+ "last_recorded_at": "2026-09-26T15:02:11.000Z",
+ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",
+ "totals": [
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "daily": [
+ {
+ "day": "2026-09-26",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "day": "2026-09-26",
+ "service": "events",
+ "capability": "events.app.publish",
+ "dimension": null,
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "quotas": [
+ {
+ "capability": "tools.job.create",
+ "limit": 1000,
+ "window": "day",
+ "unit": "jobs",
+ "enforced_by": "openvibe.tools",
+ "used": 42,
+ "remaining": 958,
+ "window_start": "2026-09-26T00:00:00.000Z",
+ "note": null
+ },
+ {
+ "capability": "events.app.publish",
+ "limit": 120,
+ "window": "minute",
+ "unit": "events",
+ "enforced_by": "openvibe.events",
+ "used": null,
+ "remaining": null,
+ "window_start": null,
+ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"
+ }
+ ],
+ "errors": {
+ "total": 64,
+ "by_code": [
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "count": 60
+ },
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.failed",
+ "count": 2
+ }
+ ],
+ "recent": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "env": "production",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "env": "sandbox",
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c",
+ "ref": null
+ }
+ ]
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "all",
+ "range": {
+ "days": 30,
+ "from": "2026-08-28",
+ "to": "2026-09-26"
+ },
+ "generated_at": "2026-09-26T15:05:00.000Z",
+ "last_recorded_at": "2026-09-26T15:02:11.000Z",
+ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",
+ "totals": [
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "daily": [
+ {
+ "day": "2026-09-26",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "day": "2026-09-26",
+ "service": "events",
+ "capability": "events.app.publish",
+ "dimension": null,
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "quotas": [
+ {
+ "capability": "tools.job.create",
+ "limit": 1000,
+ "window": "day",
+ "unit": "jobs",
+ "enforced_by": "openvibe.tools",
+ "used": -5,
+ "remaining": 958,
+ "window_start": "2026-09-26T00:00:00.000Z",
+ "note": null
+ },
+ {
+ "capability": "events.app.publish",
+ "limit": 120,
+ "window": "minute",
+ "unit": "events",
+ "enforced_by": "openvibe.events",
+ "used": null,
+ "remaining": null,
+ "window_start": null,
+ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"
+ }
+ ],
+ "errors": {
+ "total": 64,
+ "by_code": [
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "count": 60
+ },
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.failed",
+ "count": 2
+ }
+ ],
+ "recent": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "env": "production",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "env": "sandbox",
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c",
+ "ref": null
+ }
+ ]
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,119 @@
@@ -0,0 +1,119 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "all",
+ "range": {
+ "days": 30,
+ "from": "2026-08-28",
+ "to": "2026-09-26"
+ },
+ "generated_at": "2026-09-26T15:05:00.000Z",
+ "last_recorded_at": "2026-09-26T15:02:11.000Z",
+ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",
+ "totals": [
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "daily": [
+ {
+ "day": "2026-09-26",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "day": "2026-09-26",
+ "service": "events",
+ "capability": "events.app.publish",
+ "dimension": null,
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "quotas": [
+ {
+ "capability": "tools.job.create",
+ "limit": 1000,
+ "window": "day",
+ "unit": "jobs",
+ "enforced_by": "openvibe.tools",
+ "used": 42,
+ "remaining": 958,
+ "window_start": "2026-09-26T00:00:00.000Z",
+ "note": null
+ },
+ {
+ "capability": "events.app.publish",
+ "limit": 120,
+ "window": "minute",
+ "unit": "events",
+ "enforced_by": "openvibe.events",
+ "used": null,
+ "remaining": null,
+ "window_start": null,
+ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"
+ }
+ ],
+ "errors": {
+ "total": 64,
+ "by_code": [
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "count": 60
+ },
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.failed",
+ "count": 2
+ }
+ ],
+ "recent": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "env": "production",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR",
+ "subject": {
+ "type": "user",
+ "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
+ }
+ },
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "env": "sandbox",
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c",
+ "ref": null
+ }
+ ]
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "all",
+ "range": {
+ "days": 30,
+ "from": "2026-08-28",
+ "to": "2026-09-26"
+ },
+ "generated_at": "2026-09-26T15:05:00.000Z",
+ "last_recorded_at": "2026-09-26T15:02:11.000Z",
+ "freshness": "Usage arrives as hourly rollups after each hour closes; the current hour is not counted yet.",
+ "totals": [
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "daily": [
+ {
+ "day": "2026-09-26",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "env": "production",
+ "quantity": 42,
+ "errors": 3
+ },
+ {
+ "day": "2026-09-26",
+ "service": "events",
+ "capability": "events.app.publish",
+ "dimension": null,
+ "unit": "events",
+ "env": "sandbox",
+ "quantity": 1800,
+ "errors": 61
+ }
+ ],
+ "quotas": [
+ {
+ "capability": "tools.job.create",
+ "limit": 1000,
+ "window": "day",
+ "unit": "jobs",
+ "enforced_by": "openvibe.tools",
+ "used": 42,
+ "remaining": 958,
+ "window_start": "2026-09-26T00:00:00.000Z",
+ "note": null
+ },
+ {
+ "capability": "events.app.publish",
+ "limit": 120,
+ "window": "minute",
+ "unit": "events",
+ "enforced_by": "openvibe.events",
+ "used": null,
+ "remaining": null,
+ "window_start": null,
+ "note": "a minute window is enforced by the service as it happens; hourly rollups cannot show it"
+ }
+ ],
+ "errors": {
+ "total": 64,
+ "by_code": [
+ {
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "count": 60
+ },
+ {
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.failed",
+ "count": 2
+ }
+ ],
+ "recent": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "env": "production",
+ "service": "tools",
+ "capability": "tools.job.create",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T09:59:58.120Z",
+ "env": "sandbox",
+ "service": "events",
+ "capability": "events.app.publish",
+ "code": "events.quota_exceeded",
+ "status": 429,
+ "trace_id": "0af7651916cd43dd8448eb211c80319c",
+ "ref": null
+ }
+ ]
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "range": {
+ "days": 7,
+ "from": "2026-09-20",
+ "to": "2026-09-26"
+ },
+ "generated_at": "2026-09-26T15:05:00.000Z",
+ "last_recorded_at": null,
+ "freshness": "No usage has been recorded for this project yet.",
+ "totals": [],
+ "daily": [],
+ "quotas": [],
+ "errors": {
+ "total": 0,
+ "by_code": [],
+ "recent": []
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ],
+ "owner": {
+ "type": "app",
+ "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
+{
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "production",
+ "capability": "tools.job.create",
+ "dimension": "img.process",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T14:00:00.000Z",
+ "window_end": "2026-09-26T15:00:00.000Z",
+ "quantity": 42,
+ "errors": 3,
+ "error_codes": {
+ "tools.job.failed": 2,
+ "tools.job.timeout": 1
+ },
+ "samples": [
+ {
+ "at": "2026-09-26T14:51:07.412Z",
+ "code": "tools.job.timeout",
+ "status": 504,
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPR"
+ },
+ {
+ "at": "2026-09-26T14:20:13.001Z",
+ "code": "tools.job.failed",
+ "status": 422,
+ "ref": "job_01JAB2C3D4E5F6G7H8J9K0MNPS"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "env": "sandbox",
+ "capability": "tools.tool.run",
+ "unit": "jobs",
+ "window": "hour",
+ "window_start": "2026-09-26T08:00:00.000Z",
+ "window_end": "2026-09-26T09:00:00.000Z",
+ "quantity": 5,
+ "errors": 0,
+ "dimension": "image-resize"
+}
@@ -2580,6 +2580,150 @@
@@ -2580,6 +2580,150 @@
}
}
}
}
},
},
+ "common.usage-recorded": {
+ "version": "1.0.0",
+ "owner": "network",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/common/usage-recorded.v1.json",
+ "title": "UsageRecorded",
+ "description": "common.usage-recorded@1 (roadmap WS-N task 4, ADR-014): one rollup of a developer project's use of one capability in one environment over one closed window (an hour or a day), as the service that owns the capability counted it. The payload of every <service>.usage.recorded event; OpenVibe.Network adds them up per project and day for the project's dashboard on OpenVibe.Codes. The producer counts in the transaction that does its own accounting (a job's end, a stored event, a delivery attempt) and writes the rollup to its outbox after the window has closed: never one event per request. Totals, not deltas: a later event with the same key (source, project_id, env, capability, dimension, unit, window_start) replaces the earlier one, and a lower revision never replaces a higher one. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor the producing service. Never carries a subject id, an address, a session, a request's input or content, or a file name.",
+ "type": "object",
+ "required": [
+ "project_id",
+ "env",
+ "capability",
+ "unit",
+ "window",
+ "window_start",
+ "window_end",
+ "quantity",
+ "errors"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "project_id": {
+ "type": "string",
+ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The developer project whose app token did the work."
+ },
+ "env": {
+ "enum": [
+ "sandbox",
+ "production"
+ ],
+ "description": "The environment of that app token."
+ },
+ "capability": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$",
+ "maxLength": 80,
+ "description": "The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe."
+ },
+ "dimension": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "pattern": "^[a-z0-9][a-z0-9_.:-]*$",
+ "not": {
+ "pattern": "^(usr|gst|app|mod|svc|job|evt|req)_"
+ },
+ "description": "Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job."
+ },
+ "unit": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$",
+ "description": "What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit."
+ },
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ],
+ "description": "The length of the window."
+ },
+ "window_start": {
+ "type": "string",
+ "format": "date-time",
+ "description": "UTC, on the hour (midnight for a day)."
+ },
+ "window_end": {
+ "type": "string",
+ "format": "date-time",
+ "description": "window_start plus the window, exclusive."
+ },
+ "quantity": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Units used in the window, by work that succeeded and work that failed alike."
+ },
+ "errors": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity."
+ },
+ "error_codes": {
+ "type": "object",
+ "maxProperties": 20,
+ "propertyNames": {
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$",
+ "maxLength": 80
+ },
+ "additionalProperties": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "description": "The errors by problem code (at most 20 codes; the rest are only in errors)."
+ },
+ "samples": {
+ "type": "array",
+ "maxItems": 10,
+ "description": "The last failures of the window, newest first, so a developer can find them in their own logs.",
+ "items": {
+ "type": "object",
+ "required": [
+ "at",
+ "code"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "code": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$",
+ "maxLength": 80
+ },
+ "status": {
+ "type": "integer",
+ "minimum": 100,
+ "maximum": 599,
+ "description": "The HTTP status the failure was answered with, when there was one."
+ },
+ "trace_id": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{32}$",
+ "description": "The W3C trace id of the request (or event) that failed."
+ },
+ "ref": {
+ "type": "string",
+ "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject."
+ }
+ }
+ }
+ },
+ "revision": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "1 when absent. A producer that re-emits a window with corrected totals raises it."
+ }
+ }
+ }
+ },
"media.file-upload": {
"media.file-upload": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "media",
"owner": "media",
@@ -23671,6 +23815,30 @@
@@ -23671,6 +23815,30 @@
"$ref": "../../common/moderation-action.v1.json"
"$ref": "../../common/moderation-action.v1.json"
}
}
},
},
+ "tools.usage.recorded": {
+ "version": "1.0.0",
+ "owner": "tools",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/tools.usage.recorded.v1.json",
+ "title": "ToolsUsageRecordedPayload",
+ "description": "tools.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Tools apps/_shared/jobs/usage.js). One hour of a developer project's jobs on one Tools satellite, per capability (tools.job.create for POST /api/v1/jobs, tools.tool.run for a tool run) and job type or tool (dimension), in unit jobs: quantity counts the jobs that ended (succeeded or failed; a cancelled job is not counted), errors the failed ones, by code, with the last failures' job ids and trace ids. Counted in the transaction that records a job's end; written to the satellite's outbox after the hour closes. Only jobs of developer-app tokens (they carry a project) are counted; sandbox jobs are counted under env sandbox. The payload is common.usage-recorded@1. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:tools.",
+ "$ref": "../../common/usage-recorded.v1.json"
+ }
+ },
+ "events.usage.recorded": {
+ "version": "1.0.0",
+ "owner": "events",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/events.usage.recorded.v1.json",
+ "title": "EventsUsageRecordedPayload",
+ "description": "events.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Events server/usage.js). One hour of a developer project's use of OpenVibe.Events in one environment: events.app.publish in unit events (quantity counts the events stored; errors the publish requests refused with a problem, such as 429 events.quota_exceeded or 403 events.type_not_allowed) and events.app.subscribe in unit deliveries (quantity counts webhook delivery attempts to the project's subscriptions; errors the attempts without a 2xx, as events.delivery.http_<status>, events.delivery.timeout or events.delivery.failed). Counted in the transaction that stores the events or records the attempt (a refusal right after it is answered); Events stores the rollup as its own event after the hour closes, in the same transaction that marks it sent. The payload is common.usage-recorded@1. Envelope: source events, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:events.",
+ "$ref": "../../common/usage-recorded.v1.json"
+ }
+ },
"live.stream.started": {
"live.stream.started": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "live",
"owner": "live",
@@ -26194,6 +26362,379 @@
@@ -26194,6 +26362,379 @@
}
}
}
}
},
},
+ "network.project-usage-result": {
+ "version": "1.0.0",
+ "owner": "network",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/network/project-usage-result.v1.json",
+ "title": "ProjectUsageResult",
+ "description": "network.project-usage-result@1 (roadmap WS-N task 4, ADR-014): what GET /api/v1/projects/:project/usage?days=&env= on OpenVibe.Network answers a project's owner or admin (or staff): the project's usage per day, service, capability and unit, added up from the <service>.usage.recorded rollups (common.usage-recorded@1) the owning services emit after each hour closes; the project's recorded quotas with what the current window has used; and its recent failures with their codes and trace ids. Counts only, never who did what: no subject id, address, input or content.",
+ "type": "object",
+ "required": [
+ "project_id",
+ "env",
+ "range",
+ "generated_at",
+ "last_recorded_at",
+ "freshness",
+ "totals",
+ "daily",
+ "quotas",
+ "errors"
+ ],
+ "additionalProperties": false,
+ "$defs": {
+ "service": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{1,39}$"
+ },
+ "capability": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$",
+ "maxLength": 80
+ },
+ "unit": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "env": {
+ "enum": [
+ "sandbox",
+ "production"
+ ]
+ },
+ "code": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$",
+ "maxLength": 80
+ },
+ "count": {
+ "type": "integer",
+ "minimum": 0
+ }
+ },
+ "properties": {
+ "project_id": {
+ "type": "string",
+ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "env": {
+ "enum": [
+ "all",
+ "sandbox",
+ "production"
+ ],
+ "description": "The environments counted (the env query parameter; all by default)."
+ },
+ "range": {
+ "type": "object",
+ "required": [
+ "days",
+ "from",
+ "to"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "days": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 90
+ },
+ "from": {
+ "type": "string",
+ "format": "date",
+ "description": "First UTC day counted."
+ },
+ "to": {
+ "type": "string",
+ "format": "date",
+ "description": "Last UTC day counted (today)."
+ }
+ }
+ },
+ "generated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "last_recorded_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "description": "When the newest rollup for this project arrived; null before the first."
+ },
+ "freshness": {
+ "type": "string",
+ "maxLength": 300,
+ "description": "How current the numbers are, in words (rollups arrive after each hour closes)."
+ },
+ "totals": {
+ "type": "array",
+ "description": "The whole range per service, capability, unit and environment.",
+ "items": {
+ "type": "object",
+ "required": [
+ "service",
+ "capability",
+ "unit",
+ "env",
+ "quantity",
+ "errors"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "service": {
+ "$ref": "#/$defs/service"
+ },
+ "capability": {
+ "$ref": "#/$defs/capability"
+ },
+ "unit": {
+ "$ref": "#/$defs/unit"
+ },
+ "env": {
+ "$ref": "#/$defs/env"
+ },
+ "quantity": {
+ "$ref": "#/$defs/count"
+ },
+ "errors": {
+ "$ref": "#/$defs/count"
+ }
+ }
+ }
+ },
+ "daily": {
+ "type": "array",
+ "description": "One row per UTC day, service, capability, dimension, unit and environment that saw usage; days without any are absent. Newest day first.",
+ "items": {
+ "type": "object",
+ "required": [
+ "day",
+ "service",
+ "capability",
+ "dimension",
+ "unit",
+ "env",
+ "quantity",
+ "errors"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "day": {
+ "type": "string",
+ "format": "date"
+ },
+ "service": {
+ "$ref": "#/$defs/service"
+ },
+ "capability": {
+ "$ref": "#/$defs/capability"
+ },
+ "dimension": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 80
+ },
+ "unit": {
+ "$ref": "#/$defs/unit"
+ },
+ "env": {
+ "$ref": "#/$defs/env"
+ },
+ "quantity": {
+ "$ref": "#/$defs/count"
+ },
+ "errors": {
+ "$ref": "#/$defs/count"
+ }
+ }
+ }
+ },
+ "quotas": {
+ "type": "array",
+ "description": "The project's recorded quotas (GET /api/v1/projects/:project/quotas), each with what its current window has used, in every environment together. used is null where the rollups cannot tell (a minute or hour window, or a unit no service reports for that capability).",
+ "items": {
+ "type": "object",
+ "required": [
+ "capability",
+ "limit",
+ "window",
+ "unit",
+ "enforced_by",
+ "used",
+ "remaining",
+ "window_start",
+ "note"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "capability": {
+ "$ref": "#/$defs/capability"
+ },
+ "limit": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "window": {
+ "enum": [
+ "minute",
+ "hour",
+ "day",
+ "month",
+ "total"
+ ]
+ },
+ "unit": {
+ "$ref": "#/$defs/unit"
+ },
+ "enforced_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The audience of the service that enforces it (openvibe.<owner>)."
+ },
+ "used": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "remaining": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "window_start": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "description": "Start of the current window counted (today, this month); null for total and when used is null."
+ },
+ "note": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ }
+ }
+ }
+ },
+ "errors": {
+ "type": "object",
+ "required": [
+ "total",
+ "by_code",
+ "recent"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "total": {
+ "$ref": "#/$defs/count"
+ },
+ "by_code": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "service",
+ "capability",
+ "code",
+ "count"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "service": {
+ "$ref": "#/$defs/service"
+ },
+ "capability": {
+ "$ref": "#/$defs/capability"
+ },
+ "code": {
+ "$ref": "#/$defs/code"
+ },
+ "count": {
+ "$ref": "#/$defs/count"
+ }
+ }
+ }
+ },
+ "recent": {
+ "type": "array",
+ "maxItems": 50,
+ "description": "The newest failures the rollups sampled, newest first.",
+ "items": {
+ "type": "object",
+ "required": [
+ "at",
+ "env",
+ "service",
+ "capability",
+ "code",
+ "status",
+ "trace_id",
+ "ref"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "env": {
+ "$ref": "#/$defs/env"
+ },
+ "service": {
+ "$ref": "#/$defs/service"
+ },
+ "capability": {
+ "$ref": "#/$defs/capability"
+ },
+ "code": {
+ "$ref": "#/$defs/code"
+ },
+ "status": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 100,
+ "maximum": 599
+ },
+ "trace_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[0-9a-f]{32}$"
+ },
+ "ref": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^(job|evt|run|med)_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"network.staff-list-result": {
"network.staff-list-result": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "network",
"owner": "network",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"title": "OpenVibe.Billing API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"title": "OpenVibe.Blog API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Chat API",
"title": "OpenVibe.Chat API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Codes API",
"title": "OpenVibe.Codes API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Community API",
"title": "OpenVibe.Community API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Coupons API",
"title": "OpenVibe.Coupons API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Deals API",
"title": "OpenVibe.Deals API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Events API",
"title": "OpenVibe.Events API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Games API",
"title": "OpenVibe.Games API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Host API",
"title": "OpenVibe.Host API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"title": "OpenVibe.Live API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Media API",
"title": "OpenVibe.Media API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Network API",
"title": "OpenVibe.Network API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.News API",
"title": "OpenVibe.News API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRe.Stream API",
"title": "OpenRe.Stream API",
- "version": "0.62.0",
- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Reviews API",
"title": "OpenVibe.Reviews API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Search API",
"title": "OpenVibe.Search API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Sources API",
"title": "OpenVibe.Sources API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tips API",
"title": "OpenVibe.Tips API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tools API",
"title": "OpenVibe.Tools API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Trade API",
"title": "OpenVibe.Trade API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.VIP API",
"title": "OpenVibe.VIP API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Wiki API",
"title": "OpenVibe.Wiki API",
- "version": "0.62.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.63.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.63.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -1176,1286 +1176,2250 @@ export interface ModerationAction {
@@ -1176,1286 +1176,2250 @@ export interface ModerationAction {
details?: {};
details?: {};
}
}
-/** [email protected] (owner: media) */
-/**
- * media.file-upload@1: the multipart/form-data body of POST /api/v1/:app/files (media.object.upload, namespace :app): one part named `file` with the bytes and its filename and type. The tenant's quota is checked against the bytes; the answer is media.file@1 (201).
- */
-export interface MediaFileUpload {
- /**
- * The multipart part named file (filename and Content-Type from the part).
- */
- file: string;
- [k: string]: unknown | undefined;
-}
-
-/** [email protected] (owner: search) */
+/** [email protected] (owner: network) */
/**
/**
- * What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.
+ * common.usage-recorded@1 (roadmap WS-N task 4, ADR-014): one rollup of a developer project's use of one capability in one environment over one closed window (an hour or a day), as the service that owns the capability counted it. The payload of every <service>.usage.recorded event; OpenVibe.Network adds them up per project and day for the project's dashboard on OpenVibe.Codes. The producer counts in the transaction that does its own accounting (a job's end, a stored event, a delivery attempt) and writes the rollup to its outbox after the window has closed: never one event per request. Totals, not deltas: a later event with the same key (source, project_id, env, capability, dimension, unit, window_start) replaces the earlier one, and a lower revision never replaces a higher one. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor the producing service. Never carries a subject id, an address, a session, a request's input or content, or a file name.
*/
*/
-export interface IndexDocument {
- /**
- * Owning service id (wiki, blog, news, community, sources…). Only that service may write the document.
- */
- owner: string;
- /**
- * Resource type inside the owner (page, post, story, entity, offer, coupon, instrument, item…).
- */
- type: string;
+export interface UsageRecorded {
/**
/**
- * Resource id inside owner+type. Stable across revisions.
+ * The developer project whose app token did the work.
*/
*/
- id: string;
+ project_id: string;
/**
/**
- * Owner's monotonic revision of the resource. An older revision never overwrites a newer one; at equal revision a deletion wins.
+ * The environment of that app token.
*/
*/
- revision: number;
+ env: "sandbox" | "production";
/**
/**
- * Deletion marker. true = tombstone; every other content field is ignored.
+ * The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe.
*/
*/
- deleted?: boolean;
+ capability: string;
/**
/**
- * public: anyone. unlisted: never listed except to ACL matches; fetchable by exact id by a signed-in subject. members: subjects, groups or entitlements in acl. private: subjects in acl.subjects only. draft: never served.
+ * Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job.
*/
*/
- visibility?: "public" | "unlisted" | "members" | "private" | "draft";
+ dimension?: string;
/**
/**
- * Who may see a non-public document. Ignored for public documents. Empty means nobody (for members/private) or direct-id only (for unlisted).
+ * What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit.
*/
*/
- acl?: {
- /**
- * @maxItems 200
- */
- subjects?: string[];
- /**
- * Opaque group keys owned by some service, e.g. role:admin (Network role), wiki.space:spc_…:member.
- *
- * @maxItems 100
- */
- groups?: string[];
- /**
- * Entitlement keys (VIP/Billing), e.g. vip.plan:pln_…. Only a first-party service that just resolved them may present them for a viewer.
- *
- * @maxItems 100
- */
- entitlements?: string[];
- };
- canonical_url?: string;
- title?: string;
- summary?: string;
+ unit: string;
/**
/**
- * Plain text for full-text search (no HTML). Keep it under the Events payload limit when publishing through Events.
+ * The length of the window.
*/
*/
- body?: string;
+ window: "hour" | "day";
/**
/**
- * Filterable values (category, tags, space, author subject, currency…). Filter with facet.<key>=<value>.
+ * UTC, on the hour (midnight for a day).
*/
*/
- facets?: {
- [k: string]: (string | number | boolean | string[]) | undefined;
- };
+ window_start: string;
/**
/**
- * BCP 47 tag.
+ * window_start plus the window, exclusive.
*/
*/
- language?: string;
- authorship?: "human" | "ai_assisted" | "ai_generated" | "imported";
+ window_end: string;
/**
/**
- * Where the content came from: typed references to source records (Sources items, citations, Media objects).
- *
- * @maxItems 50
+ * Units used in the window, by work that succeeded and work that failed alike.
*/
*/
- provenance?: {
- service: string;
- type: string;
- id: string;
- revision?: number;
- label?: string;
- url?: string;
- retrieved_at?: string;
- /**
- * true when the reference came from a stub provider; the document is then never indexable.
- */
- stub?: boolean;
- }[];
+ quantity: number;
/**
/**
- * Only published documents are ever served.
+ * Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity.
*/
*/
- publication_state?: "draft" | "scheduled" | "published" | "unpublished" | "retracted" | "archived";
- published_at?: string | null;
- updated_at?: string | null;
+ errors: number;
/**
/**
- * The owner's deterministic indexability decision (publishing packages, roadmap §32.3). Search can only make it stricter.
+ * The errors by problem code (at most 20 codes; the rest are only in errors).
*/
*/
- indexability?: {
- decision: "index" | "noindex";
- /**
- * Known reasons: draft, private, members_only, unlisted, not_published, deleted, thin_content, duplicate_without_canonical, unsupported_claims, unsourced, stub_provider, sensitive_unreviewed, ai_unreviewed, missing_canonical_url, third_party_content, owner_decision.
- *
- * @maxItems 20
- */
- reasons?:
- | []
- | [string]
- | [string, string]
- | [string, string, string]
- | [string, string, string, string]
- | [string, string, string, string, string]
- | [string, string, string, string, string, string]
- | [string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ];
+ error_codes?: {
+ [k: string]: number | undefined;
};
};
-}
-
-/** [email protected] (owner: search) */
-/**
- * search.query@1: the query string of GET /api/v1/search (and, with q/owner/type/limit only, GET /api/v1/suggest), capabilities search.query.run and search.query.delegate. Who sees what is decided by Search per hit: anonymous callers get public, published, indexable documents; a person also restricted documents naming them; a delegating service passes X-OV-Subject. Filters narrow; they never widen visibility.
- */
-export interface SearchQuery {
- /**
- * Words to match (FTS5; empty lists by recency).
- */
- q?: string;
- /**
- * One owner service (live, community, wiki, …).
- */
- owner?: string;
- /**
- * One document type within the owner (channel, vod, thread, …).
- */
- type?: string;
- /**
- * BCP 47 language.
- */
- lang?: string;
/**
/**
- * Comma-separated facet keys to count over what the caller can see.
+ * The last failures of the window, newest first, so a developer can find them in their own logs.
+ *
+ * @maxItems 10
*/
*/
- facets?: string;
- limit?: number | string;
- /**
- * next_cursor of the previous page.
- */
- cursor?: string;
- /**
- * A facet filter (facet.<key>=<value>); repeat the parameter for several values.
- *
- * This interface was referenced by `SearchQuery`'s JSON-Schema definition
- * via the `patternProperty` "^facet\.[a-z][a-z0-9_]{0,39}$".
- */
- [k: string]:
- | string
+ samples?:
| []
| []
- | [string]
- | [string, string]
- | [string, string, string]
- | [string, string, string, string]
- | [string, string, string, string, string]
- | [string, string, string, string, string, string]
- | [string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string, string, string]
- | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]
| [
| [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
]
]
| [
| [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
]
]
| [
| [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
]
]
| [
| [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
]
]
| [
| [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
]
]
- | [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
- ];
-}
-
-/** [email protected] (owner: search) */
-/**
- * search.query-result@1: the answer of GET /api/v1/search — one page of hits the caller may see, a cursor for the next page, and facet counts when asked. Never a total count and never an ACL.
- */
-export interface SearchQueryResult {
- /**
- * @maxItems 100
- */
- results: {
- owner: string;
- type: string;
- id: string;
- revision?: number;
- visibility?: string;
- title?: string | null;
- summary?: string | null;
- canonical_url?: string | null;
- facets?: {} | null;
- language?: string | null;
- authorship?: string | null;
- provenance?: unknown[] | {} | null;
- published_at?: string | null;
- updated_at?: string | null;
- /**
- * false for a noindex document the caller may still see.
- */
- indexable?: boolean;
- /**
- * Escaped text with <mark> around the matches; nothing else.
- */
- snippet_html?: string | null;
- }[];
- next_cursor: string | null;
- facets?: {
- [k: string]:
- | {
- value: string;
- count: number;
- }[]
- | undefined;
- };
-}
-
-/** [email protected] (owner: search) */
-/**
- * search.write-result@1: the answer of PUT /api/v1/documents/:owner/:type/:id (search.document.write). applied: stored (or a tombstone recorded); unchanged: the same revision with the same content. A revision older than the stored one is a 409 problem search.stale_revision; the same revision with different content is 409 search.revision_conflict.
- */
-export interface SearchWriteResult {
- outcome: "applied" | "unchanged";
- revision: number;
- /**
- * What Search held before this write (null: nothing).
- */
- stored_revision?: number | null;
- deleted?: boolean;
-}
-
-/** [email protected] (owner: sources) */
-/**
- * A registered source (roadmap §4.2 B, Wave 14): where it is fetched from and on what terms. Credentials are referenced by environment-variable NAME only. A source's existence is never permission to fetch: robots and terms are verified before it is enabled, and the fetcher re-checks robots.txt on every run.
- */
-export interface Source {
- key: string;
- name: string;
- type: "rss" | "atom" | "sitemap" | "jsonld" | "api" | "manual";
- category: "news" | "blog" | "reviews" | "deals" | "coupons" | "trade";
- homepage_url?: string | null;
- /**
- * @maxItems 20
- */
- endpoints:
- | []
| [
| [
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- }
- ]
- | [
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- }
- ]
- | [
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
}
}
]
]
| [
| [
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- }
- ]
- | [
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
}
}
]
]
| [
| [
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
}
}
]
]
| [
| [
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- }
- ]
- | [
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- }
- ]
- | [
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
},
},
{
{
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- }
- ]
- | [
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
}
}
- ]
- | [
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
- [k: string]: string | undefined;
- };
- },
- {
- url: string;
- format?: "json" | "xml";
- items_path?: string;
- item_kind?: string;
- fields?: {
- [k: string]: string | undefined;
- };
- extra?: {
+ ];
+ /**
+ * 1 when absent. A producer that re-emits a window with corrected totals raises it.
+ */
+ revision?: number;
+}
+
+/** [email protected] (owner: media) */
+/**
+ * media.file-upload@1: the multipart/form-data body of POST /api/v1/:app/files (media.object.upload, namespace :app): one part named `file` with the bytes and its filename and type. The tenant's quota is checked against the bytes; the answer is media.file@1 (201).
+ */
+export interface MediaFileUpload {
+ /**
+ * The multipart part named file (filename and Content-Type from the part).
+ */
+ file: string;
+ [k: string]: unknown | undefined;
+}
+
+/** [email protected] (owner: search) */
+/**
+ * What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.
+ */
+export interface IndexDocument {
+ /**
+ * Owning service id (wiki, blog, news, community, sources…). Only that service may write the document.
+ */
+ owner: string;
+ /**
+ * Resource type inside the owner (page, post, story, entity, offer, coupon, instrument, item…).
+ */
+ type: string;
+ /**
+ * Resource id inside owner+type. Stable across revisions.
+ */
+ id: string;
+ /**
+ * Owner's monotonic revision of the resource. An older revision never overwrites a newer one; at equal revision a deletion wins.
+ */
+ revision: number;
+ /**
+ * Deletion marker. true = tombstone; every other content field is ignored.
+ */
+ deleted?: boolean;
+ /**
+ * public: anyone. unlisted: never listed except to ACL matches; fetchable by exact id by a signed-in subject. members: subjects, groups or entitlements in acl. private: subjects in acl.subjects only. draft: never served.
+ */
+ visibility?: "public" | "unlisted" | "members" | "private" | "draft";
+ /**
+ * Who may see a non-public document. Ignored for public documents. Empty means nobody (for members/private) or direct-id only (for unlisted).
+ */
+ acl?: {
+ /**
+ * @maxItems 200
+ */
+ subjects?: string[];
+ /**
+ * Opaque group keys owned by some service, e.g. role:admin (Network role), wiki.space:spc_…:member.
+ *
+ * @maxItems 100
+ */
+ groups?: string[];
+ /**
+ * Entitlement keys (VIP/Billing), e.g. vip.plan:pln_…. Only a first-party service that just resolved them may present them for a viewer.
+ *
+ * @maxItems 100
+ */
+ entitlements?: string[];
+ };
+ canonical_url?: string;
+ title?: string;
+ summary?: string;
+ /**
+ * Plain text for full-text search (no HTML). Keep it under the Events payload limit when publishing through Events.
+ */
+ body?: string;
+ /**
+ * Filterable values (category, tags, space, author subject, currency…). Filter with facet.<key>=<value>.
+ */
+ facets?: {
+ [k: string]: (string | number | boolean | string[]) | undefined;
+ };
+ /**
+ * BCP 47 tag.
+ */
+ language?: string;
+ authorship?: "human" | "ai_assisted" | "ai_generated" | "imported";
+ /**
+ * Where the content came from: typed references to source records (Sources items, citations, Media objects).
+ *
+ * @maxItems 50
+ */
+ provenance?: {
+ service: string;
+ type: string;
+ id: string;
+ revision?: number;
+ label?: string;
+ url?: string;
+ retrieved_at?: string;
+ /**
+ * true when the reference came from a stub provider; the document is then never indexable.
+ */
+ stub?: boolean;
+ }[];
+ /**
+ * Only published documents are ever served.
+ */
+ publication_state?: "draft" | "scheduled" | "published" | "unpublished" | "retracted" | "archived";
+ published_at?: string | null;
+ updated_at?: string | null;
+ /**
+ * The owner's deterministic indexability decision (publishing packages, roadmap §32.3). Search can only make it stricter.
+ */
+ indexability?: {
+ decision: "index" | "noindex";
+ /**
+ * Known reasons: draft, private, members_only, unlisted, not_published, deleted, thin_content, duplicate_without_canonical, unsupported_claims, unsourced, stub_provider, sensitive_unreviewed, ai_unreviewed, missing_canonical_url, third_party_content, owner_decision.
+ *
+ * @maxItems 20
+ */
+ reasons?:
+ | []
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ];
+ };
+}
+
+/** [email protected] (owner: search) */
+/**
+ * search.query@1: the query string of GET /api/v1/search (and, with q/owner/type/limit only, GET /api/v1/suggest), capabilities search.query.run and search.query.delegate. Who sees what is decided by Search per hit: anonymous callers get public, published, indexable documents; a person also restricted documents naming them; a delegating service passes X-OV-Subject. Filters narrow; they never widen visibility.
+ */
+export interface SearchQuery {
+ /**
+ * Words to match (FTS5; empty lists by recency).
+ */
+ q?: string;
+ /**
+ * One owner service (live, community, wiki, …).
+ */
+ owner?: string;
+ /**
+ * One document type within the owner (channel, vod, thread, …).
+ */
+ type?: string;
+ /**
+ * BCP 47 language.
+ */
+ lang?: string;
+ /**
+ * Comma-separated facet keys to count over what the caller can see.
+ */
+ facets?: string;
+ limit?: number | string;
+ /**
+ * next_cursor of the previous page.
+ */
+ cursor?: string;
+ /**
+ * A facet filter (facet.<key>=<value>); repeat the parameter for several values.
+ *
+ * This interface was referenced by `SearchQuery`'s JSON-Schema definition
+ * via the `patternProperty` "^facet\.[a-z][a-z0-9_]{0,39}$".
+ */
+ [k: string]:
+ | string
+ | []
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ];
+}
+
+/** [email protected] (owner: search) */
+/**
+ * search.query-result@1: the answer of GET /api/v1/search — one page of hits the caller may see, a cursor for the next page, and facet counts when asked. Never a total count and never an ACL.
+ */
+export interface SearchQueryResult {
+ /**
+ * @maxItems 100
+ */
+ results: {
+ owner: string;
+ type: string;
+ id: string;
+ revision?: number;
+ visibility?: string;
+ title?: string | null;
+ summary?: string | null;
+ canonical_url?: string | null;
+ facets?: {} | null;
+ language?: string | null;
+ authorship?: string | null;
+ provenance?: unknown[] | {} | null;
+ published_at?: string | null;
+ updated_at?: string | null;
+ /**
+ * false for a noindex document the caller may still see.
+ */
+ indexable?: boolean;
+ /**
+ * Escaped text with <mark> around the matches; nothing else.
+ */
+ snippet_html?: string | null;
+ }[];
+ next_cursor: string | null;
+ facets?: {
+ [k: string]:
+ | {
+ value: string;
+ count: number;
+ }[]
+ | undefined;
+ };
+}
+
+/** [email protected] (owner: search) */
+/**
+ * search.write-result@1: the answer of PUT /api/v1/documents/:owner/:type/:id (search.document.write). applied: stored (or a tombstone recorded); unchanged: the same revision with the same content. A revision older than the stored one is a 409 problem search.stale_revision; the same revision with different content is 409 search.revision_conflict.
+ */
+export interface SearchWriteResult {
+ outcome: "applied" | "unchanged";
+ revision: number;
+ /**
+ * What Search held before this write (null: nothing).
+ */
+ stored_revision?: number | null;
+ deleted?: boolean;
+}
+
+/** [email protected] (owner: sources) */
+/**
+ * A registered source (roadmap §4.2 B, Wave 14): where it is fetched from and on what terms. Credentials are referenced by environment-variable NAME only. A source's existence is never permission to fetch: robots and terms are verified before it is enabled, and the fetcher re-checks robots.txt on every run.
+ */
+export interface Source {
+ key: string;
+ name: string;
+ type: "rss" | "atom" | "sitemap" | "jsonld" | "api" | "manual";
+ category: "news" | "blog" | "reviews" | "deals" | "coupons" | "trade";
+ homepage_url?: string | null;
+ /**
+ * @maxItems 20
+ */
+ endpoints:
+ | []
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ }
+ ]
+ | [
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
+ [k: string]: string | undefined;
+ };
+ },
+ {
+ url: string;
+ format?: "json" | "xml";
+ items_path?: string;
+ item_kind?: string;
+ fields?: {
+ [k: string]: string | undefined;
+ };
+ extra?: {
[k: string]: string | undefined;
[k: string]: string | undefined;
};
};
},
},
@@ -24930,145 +25894,2073 @@ export interface ToolsJobSucceededPayload {
@@ -24930,145 +25894,2073 @@ export interface ToolsJobSucceededPayload {
*/
*/
expires_at: string | null;
expires_at: string | null;
/**
/**
- * Where the result files are, never their content, names or the tool's output data (GET /api/v1/jobs/:id has those, for the owner).
+ * Where the result files are, never their content, names or the tool's output data (GET /api/v1/jobs/:id has those, for the owner).
+ */
+ result: {
+ /**
+ * @maxItems 100
+ */
+ files: {
+ /**
+ * n in /api/v1/jobs/:id/files/:n.
+ */
+ index: number;
+ mime: string;
+ size: number;
+ sha256: string;
+ /**
+ * media: stored as an OpenVibe.Media object (TOOLS_JOB_RESULTS=media); local: kept on the satellite until the job expires.
+ */
+ storage: "local" | "media";
+ /**
+ * { media_id, role: output } when storage is media.
+ */
+ media: MediaRef | null;
+ }[];
+ };
+}
+
+/** [email protected] (owner: tools) */
+/**
+ * tools.job.failed v1 (OpenVibe.Tools apps/_shared/jobs/events.js). The job failed: the tool refused the input, it timed out, or it was running when the satellite restarted and its type does not requeue. A cancelled job is not a failure and is not announced as one. Emitted in the transaction that records the transition, beside the job's own SSE event. Carries ids, type, owner, state, times and result locations; never the job's input, its files, its output data or a session. Jobs of sandbox app tokens are not announced. Envelope: subject { type: job, id: <job_id> }, visibility internal, priority important, actor service:tools.
+ */
+export interface ToolsJobFailedPayload {
+ job_id: string;
+ /**
+ * The Tools satellite that runs the job (img, audio, docs…).
+ */
+ service: string;
+ /**
+ * Job type, e.g. img.process.
+ */
+ type: string;
+ type_version: number;
+ state: "failed";
+ /**
+ * Who submitted the job: a user (user:usr_…), a service, app or mod principal. null for an anonymous browser session; the session is never published.
+ */
+ owner: SubjectRef | null;
+ attempts: number;
+ max_attempts: number;
+ created_at: string;
+ /**
+ * The failed job this one retries (POST /api/v1/jobs/:id/retry).
+ */
+ retry_of: string | null;
+ /**
+ * null when the job failed before it ever ran.
+ */
+ started_at: string | null;
+ finished_at: string;
+ /**
+ * When the job and its result files are pruned; null while something references the result (PUT /api/v1/jobs/:id/references/:ref).
+ */
+ expires_at: string | null;
+ /**
+ * The job's problem (errors.problem@1) without request or trace ids.
+ */
+ error: {
+ status: number;
+ /**
+ * tools.job.failed, tools.job.timeout, or a code the tool chose (tools.…: tools.pdf.too_many_pages, tools.pdf.wrong_password…).
+ */
+ code: string;
+ /**
+ * Human-readable reason; server paths are scrubbed.
+ */
+ detail: string;
+ };
+ retryable: boolean;
+}
+
+/** [email protected] (owner: media) */
+/**
+ * media.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff action on someone else's media in OpenVibe.Media: a retention hold placed or released (moderation, dmca, admin, evidence), and a staff deletion or visibility change of someone else's VOD, clip or object. Not an owner acting on their own media, and not a creator's own pin. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member (or the service acting for an app's staff). Never carries the media itself.
+ */
+export interface MediaModerationActionPayload {
+ /**
+ * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).
+ */
+ action: string;
+ target: {
+ /**
+ * What was acted on, in the service's own words (post, page, release, user, player, …).
+ */
+ type: string;
+ id: string;
+ /**
+ * Whose content or account it was, when known.
+ */
+ owner_subject?: string | null;
+ };
+ /**
+ * The staff member or moderator (null only for a service acting without a person).
+ */
+ actor_subject: string | null;
+ reason?: string | null;
+ /**
+ * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.
+ */
+ details?: {};
+}
+
+/** [email protected] (owner: tools) */
+/**
+ * tools.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff or moderator action on someone else's content or account in OpenVibe.Tools (apps/gateway and its guard), such as guard blocks and unblocks of an account, an app or an address, and staff actions on someone else's jobs or tool pages. Not a person acting on their own content. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member. Never carries the content itself.
+ */
+export interface ToolsModerationActionPayload {
+ /**
+ * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).
+ */
+ action: string;
+ target: {
+ /**
+ * What was acted on, in the service's own words (post, page, release, user, player, …).
+ */
+ type: string;
+ id: string;
+ /**
+ * Whose content or account it was, when known.
+ */
+ owner_subject?: string | null;
+ };
+ /**
+ * The staff member or moderator (null only for a service acting without a person).
+ */
+ actor_subject: string | null;
+ reason?: string | null;
+ /**
+ * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.
+ */
+ details?: {};
+}
+
+/** [email protected] (owner: tools) */
+/**
+ * tools.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Tools apps/_shared/jobs/usage.js). One hour of a developer project's jobs on one Tools satellite, per capability (tools.job.create for POST /api/v1/jobs, tools.tool.run for a tool run) and job type or tool (dimension), in unit jobs: quantity counts the jobs that ended (succeeded or failed; a cancelled job is not counted), errors the failed ones, by code, with the last failures' job ids and trace ids. Counted in the transaction that records a job's end; written to the satellite's outbox after the hour closes. Only jobs of developer-app tokens (they carry a project) are counted; sandbox jobs are counted under env sandbox. The payload is common.usage-recorded@1. Envelope: subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:tools.
+ */
+export interface ToolsUsageRecordedPayload {
+ /**
+ * The developer project whose app token did the work.
+ */
+ project_id: string;
+ /**
+ * The environment of that app token.
+ */
+ env: "sandbox" | "production";
+ /**
+ * The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe.
+ */
+ capability: string;
+ /**
+ * Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job.
+ */
+ dimension?: string;
+ /**
+ * What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit.
+ */
+ unit: string;
+ /**
+ * The length of the window.
+ */
+ window: "hour" | "day";
+ /**
+ * UTC, on the hour (midnight for a day).
+ */
+ window_start: string;
+ /**
+ * window_start plus the window, exclusive.
+ */
+ window_end: string;
+ /**
+ * Units used in the window, by work that succeeded and work that failed alike.
+ */
+ quantity: number;
+ /**
+ * Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity.
+ */
+ errors: number;
+ /**
+ * The errors by problem code (at most 20 codes; the rest are only in errors).
+ */
+ error_codes?: {
+ [k: string]: number | undefined;
+ };
+ /**
+ * The last failures of the window, newest first, so a developer can find them in their own logs.
+ *
+ * @maxItems 10
+ */
+ samples?:
+ | []
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ];
+ /**
+ * 1 when absent. A producer that re-emits a window with corrected totals raises it.
*/
*/
- result: {
- /**
- * @maxItems 100
- */
- files: {
- /**
- * n in /api/v1/jobs/:id/files/:n.
- */
- index: number;
- mime: string;
- size: number;
- sha256: string;
- /**
- * media: stored as an OpenVibe.Media object (TOOLS_JOB_RESULTS=media); local: kept on the satellite until the job expires.
- */
- storage: "local" | "media";
- /**
- * { media_id, role: output } when storage is media.
- */
- media: MediaRef | null;
- }[];
- };
+ revision?: number;
}
}
-/** [email protected] (owner: tools) */
+/** [email protected] (owner: events) */
/**
/**
- * tools.job.failed v1 (OpenVibe.Tools apps/_shared/jobs/events.js). The job failed: the tool refused the input, it timed out, or it was running when the satellite restarted and its type does not requeue. A cancelled job is not a failure and is not announced as one. Emitted in the transaction that records the transition, beside the job's own SSE event. Carries ids, type, owner, state, times and result locations; never the job's input, its files, its output data or a session. Jobs of sandbox app tokens are not announced. Envelope: subject { type: job, id: <job_id> }, visibility internal, priority important, actor service:tools.
+ * events.usage.recorded v1 (roadmap WS-N task 4, OpenVibe.Events server/usage.js). One hour of a developer project's use of OpenVibe.Events in one environment: events.app.publish in unit events (quantity counts the events stored; errors the publish requests refused with a problem, such as 429 events.quota_exceeded or 403 events.type_not_allowed) and events.app.subscribe in unit deliveries (quantity counts webhook delivery attempts to the project's subscriptions; errors the attempts without a 2xx, as events.delivery.http_<status>, events.delivery.timeout or events.delivery.failed). Counted in the transaction that stores the events or records the attempt (a refusal right after it is answered); Events stores the rollup as its own event after the hour closes, in the same transaction that marks it sent. The payload is common.usage-recorded@1. Envelope: source events, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:events.
*/
*/
-export interface ToolsJobFailedPayload {
- job_id: string;
- /**
- * The Tools satellite that runs the job (img, audio, docs…).
- */
- service: string;
- /**
- * Job type, e.g. img.process.
- */
- type: string;
- type_version: number;
- state: "failed";
- /**
- * Who submitted the job: a user (user:usr_…), a service, app or mod principal. null for an anonymous browser session; the session is never published.
- */
- owner: SubjectRef | null;
- attempts: number;
- max_attempts: number;
- created_at: string;
- /**
- * The failed job this one retries (POST /api/v1/jobs/:id/retry).
- */
- retry_of: string | null;
+export interface EventsUsageRecordedPayload {
/**
/**
- * null when the job failed before it ever ran.
+ * The developer project whose app token did the work.
*/
*/
- started_at: string | null;
- finished_at: string;
+ project_id: string;
/**
/**
- * When the job and its result files are pruned; null while something references the result (PUT /api/v1/jobs/:id/references/:ref).
+ * The environment of that app token.
*/
*/
- expires_at: string | null;
+ env: "sandbox" | "production";
/**
/**
- * The job's problem (errors.problem@1) without request or trace ids.
+ * The capability the usage counts against: tools.job.create, tools.tool.run, events.app.publish, events.app.subscribe.
*/
*/
- error: {
- status: number;
- /**
- * tools.job.failed, tools.job.timeout, or a code the tool chose (tools.…: tools.pdf.too_many_pages, tools.pdf.wrong_password…).
- */
- code: string;
- /**
- * Human-readable reason; server paths are scrubbed.
- */
- detail: string;
- };
- retryable: boolean;
-}
-
-/** [email protected] (owner: media) */
-/**
- * media.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff action on someone else's media in OpenVibe.Media: a retention hold placed or released (moderation, dmca, admin, evidence), and a staff deletion or visibility change of someone else's VOD, clip or object. Not an owner acting on their own media, and not a creator's own pin. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member (or the service acting for an app's staff). Never carries the media itself.
- */
-export interface MediaModerationActionPayload {
+ capability: string;
/**
/**
- * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).
+ * Optional finer key inside the capability, as the producer names it: a job type (img.process) or a tool id (image-resize). Never the id of a person, an app, a request or a job.
*/
*/
- action: string;
- target: {
- /**
- * What was acted on, in the service's own words (post, page, release, user, player, …).
- */
- type: string;
- id: string;
- /**
- * Whose content or account it was, when known.
- */
- owner_subject?: string | null;
- };
+ dimension?: string;
/**
/**
- * The staff member or moderator (null only for a service acting without a person).
+ * What quantity counts (jobs, events, deliveries, requests, bytes, tokens): the same word a Network project quota uses for its unit.
*/
*/
- actor_subject: string | null;
- reason?: string | null;
+ unit: string;
/**
/**
- * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.
+ * The length of the window.
*/
*/
- details?: {};
-}
-
-/** [email protected] (owner: tools) */
-/**
- * tools.moderation.action v1 (ADR-022, roadmap WS-D task 1). A staff or moderator action on someone else's content or account in OpenVibe.Tools (apps/gateway and its guard), such as guard blocks and unblocks of an account, an app or an address, and staff actions on someone else's jobs or tool pages. Not a person acting on their own content. Written to the service's outbox in the transaction that performs the action; OpenVibe.Network keeps it in the moderation audit log. The payload is common.moderation-action@1. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member. Never carries the content itself.
- */
-export interface ToolsModerationActionPayload {
+ window: "hour" | "day";
/**
/**
- * A short verb id, as the service names it: <thing>.<what happened> (post.hidden, user.banned, release.revoked, guard.blocked).
+ * UTC, on the hour (midnight for a day).
*/
*/
- action: string;
- target: {
- /**
- * What was acted on, in the service's own words (post, page, release, user, player, …).
- */
- type: string;
- id: string;
- /**
- * Whose content or account it was, when known.
- */
- owner_subject?: string | null;
+ window_start: string;
+ /**
+ * window_start plus the window, exclusive.
+ */
+ window_end: string;
+ /**
+ * Units used in the window, by work that succeeded and work that failed alike.
+ */
+ quantity: number;
+ /**
+ * Operations in the window that failed or were refused: a job that failed, a publish refused with a problem, a webhook attempt without a 2xx. A refused operation may use no unit, so errors can exceed quantity.
+ */
+ errors: number;
+ /**
+ * The errors by problem code (at most 20 codes; the rest are only in errors).
+ */
+ error_codes?: {
+ [k: string]: number | undefined;
};
};
/**
/**
- * The staff member or moderator (null only for a service acting without a person).
+ * The last failures of the window, newest first, so a developer can find them in their own logs.
+ *
+ * @maxItems 10
*/
*/
- actor_subject: string | null;
- reason?: string | null;
+ samples?:
+ | []
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ]
+ | [
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ },
+ {
+ at: string;
+ code: string;
+ /**
+ * The HTTP status the failure was answered with, when there was one.
+ */
+ status?: number;
+ /**
+ * The W3C trace id of the request (or event) that failed.
+ */
+ trace_id?: string;
+ /**
+ * What failed, when the project can look it up with its own token: a job, an event, an AI run, a Media object. Never a subject.
+ */
+ ref?: string;
+ }
+ ];
/**
/**
- * Per action: the fields changed, the previous and new state, a bulk action's count, … never the content.
+ * 1 when absent. A producer that re-emits a window with corrected totals raises it.
*/
*/
- details?: {};
+ revision?: number;
}
}
/** [email protected] (owner: live) */
/** [email protected] (owner: live) */
@@ -26310,6 +29202,106 @@ export interface NetworkRealtimeTicketResult {
@@ -26310,6 +29202,106 @@ export interface NetworkRealtimeTicketResult {
subject: string;
subject: string;
}
}
+/** [email protected] (owner: network) */
+/**
+ * network.project-usage-result@1 (roadmap WS-N task 4, ADR-014): what GET /api/v1/projects/:project/usage?days=&env= on OpenVibe.Network answers a project's owner or admin (or staff): the project's usage per day, service, capability and unit, added up from the <service>.usage.recorded rollups (common.usage-recorded@1) the owning services emit after each hour closes; the project's recorded quotas with what the current window has used; and its recent failures with their codes and trace ids. Counts only, never who did what: no subject id, address, input or content.
+ */
+export interface ProjectUsageResult {
+ project_id: string;
+ /**
+ * The environments counted (the env query parameter; all by default).
+ */
+ env: "all" | "sandbox" | "production";
+ range: {
+ days: number;
+ /**
+ * First UTC day counted.
+ */
+ from: string;
+ /**
+ * Last UTC day counted (today).
+ */
+ to: string;
+ };
+ generated_at: string;
+ /**
+ * When the newest rollup for this project arrived; null before the first.
+ */
+ last_recorded_at: string | null;
+ /**
+ * How current the numbers are, in words (rollups arrive after each hour closes).
+ */
+ freshness: string;
+ /**
+ * The whole range per service, capability, unit and environment.
+ */
+ totals: {
+ service: Service;
+ capability: Capability;
+ unit: Unit;
+ env: Env;
+ quantity: Count;
+ errors: Count;
+ }[];
+ /**
+ * One row per UTC day, service, capability, dimension, unit and environment that saw usage; days without any are absent. Newest day first.
+ */
+ daily: {
+ day: string;
+ service: Service;
+ capability: Capability;
+ dimension: string | null;
+ unit: Unit;
+ env: Env;
+ quantity: Count;
+ errors: Count;
+ }[];
+ /**
+ * The project's recorded quotas (GET /api/v1/projects/:project/quotas), each with what its current window has used, in every environment together. used is null where the rollups cannot tell (a minute or hour window, or a unit no service reports for that capability).
+ */
+ quotas: {
+ capability: Capability;
+ limit: number;
+ window: "minute" | "hour" | "day" | "month" | "total";
+ unit: Unit;
+ /**
+ * The audience of the service that enforces it (openvibe.<owner>).
+ */
+ enforced_by: string | null;
+ used: number | null;
+ remaining: number | null;
+ /**
+ * Start of the current window counted (today, this month); null for total and when used is null.
+ */
+ window_start: string | null;
+ note: string | null;
+ }[];
+ errors: {
+ total: Count;
+ by_code: {
+ service: Service;
+ capability: Capability;
+ code: Code;
+ count: Count;
+ }[];
+ /**
+ * The newest failures the rollups sampled, newest first.
+ *
+ * @maxItems 50
+ */
+ recent: {
+ at: string;
+ env: Env;
+ service: Service;
+ capability: Capability;
+ code: Code;
+ status: number | null;
+ trace_id: string | null;
+ ref: string | null;
+ }[];
+ };
+}
+
/** [email protected] (owner: network) */
/** [email protected] (owner: network) */
/**
/**
* network.staff-list-result@1: the answer of network.staff.read on OpenVibe.Network. GET /api/v1/staff/moderators[?service=chat|live|community|pastes|calls] (a service token holding network.staff.read, or a signed-in person holding staff.moderation.logs) → { service, staff }: the network's global moderators, admins and the owner who are not banned, with the staff capabilities their role holds in the contracts staff map; ?service keeps those holding the capability that moderates that service (another service name keeps those holding staff.content.moderate; an invalid value is ignored and answered as null). Answered with Cache-Control: private, no-store; a person without staff.moderation.logs gets 403 { error: forbidden }.
* network.staff-list-result@1: the answer of network.staff.read on OpenVibe.Network. GET /api/v1/staff/moderators[?service=chat|live|community|pastes|calls] (a service token holding network.staff.read, or a signed-in person holding staff.moderation.logs) → { service, staff }: the network's global moderators, admins and the owner who are not banned, with the staff capabilities their role holds in the contracts staff map; ?service keeps those holding the capability that moderates that service (another service name keeps those holding staff.content.moderate; an invalid value is ignored and answered as null). Answered with Cache-Control: private, no-store; a person without staff.moderation.logs gets 403 { error: forbidden }.
@@ -27,7 +27,9 @@
@@ -27,7 +27,9 @@
"events.app.read",
"events.app.read",
"events.app.subscribe"
"events.app.subscribe"
],
],
- "eventsProduced": [],
+ "eventsProduced": [
+ "events.usage.recorded"
+ ],
"eventsConsumed": [],
"eventsConsumed": [],
"namespacesOwned": [],
"namespacesOwned": [],
"lifecycle": {
"lifecycle": {
@@ -69,6 +69,7 @@
@@ -69,6 +69,7 @@
"coupons.moderation.action",
"coupons.moderation.action",
"deals.moderation.action",
"deals.moderation.action",
"deals.watch.matched",
"deals.watch.matched",
+ "events.usage.recorded",
"games.moderation.action",
"games.moderation.action",
"live.moderation.action",
"live.moderation.action",
"live.stream.started",
"live.stream.started",
@@ -77,6 +78,7 @@
@@ -77,6 +78,7 @@
"reviews.moderation.action",
"reviews.moderation.action",
"tips.interaction.moderated",
"tips.interaction.moderated",
"tools.moderation.action",
"tools.moderation.action",
+ "tools.usage.recorded",
"trade.alert.triggered",
"trade.alert.triggered",
"trade.moderation.action",
"trade.moderation.action",
"wiki.moderation.action"
"wiki.moderation.action"
@@ -39,7 +39,8 @@
@@ -39,7 +39,8 @@
"tools.job.started",
"tools.job.started",
"tools.job.succeeded",
"tools.job.succeeded",
"tools.job.failed",
"tools.job.failed",
- "tools.moderation.action"
+ "tools.moderation.action",
+ "tools.usage.recorded"
],
],
"eventsConsumed": [
"eventsConsumed": [
"network.user.token_valid_after"
"network.user.token_valid_after"
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.62.0",
+ "version": "0.63.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",
@@ -791,6 +791,35 @@ await assert.rejects(failing.getToken(), /401: invalid_client/);
@@ -791,6 +791,35 @@ await assert.rejects(failing.getToken(), /401: invalid_client/);
ok(R({ ...r, expires_in: 300 }) && !R({ ...r, expires_in: 301 }), 'a ticket lives at most 300 s');
ok(R({ ...r, expires_in: 300 }) && !R({ ...r, expires_in: 301 }), 'a ticket lives at most 300 s');
}
}
+// ── Project usage (WS-N task 4, ADR-014): one shared rollup payload, one event per producer ──
+// Every <service>.usage.recorded is common.usage-recorded@1, owned by its service and consumed by
+// Network (the project dashboard). A rollup counts, it never says who: no subject, app, address,
+// input or message, and at most ten sampled failures.
+{
+ const usage = contracts.catalog.filter(c => /\.usage\.recorded$/.test(c.id));
+ ok(usage.length >= 2 && ['tools', 'events'].every(svc => usage.some(c => c.id === `${svc}.usage.recorded`)), 'tools and events publish usage rollups');
+ for (const c of usage) {
+ ok(c.owner === c.id.split('.')[0] && c.adr === 'ADR-014', `${c.id} is owned by ${c.id.split('.')[0]}`);
+ ok(contracts.schema(c.id).$ref === '../../common/usage-recorded.v1.json', `${c.id} is a common.usage-recorded@1`);
+ ok(services.get('network').eventsConsumed.includes(c.id), `network consumes ${c.id} into project usage`);
+ }
+ const U = (v) => contracts.validate('common.usage-recorded@1', v).valid;
+ const base = JSON.parse(fs.readFileSync(path.join(ROOT, 'fixtures/common.usage-recorded/valid/tools-jobs-hour.json'), 'utf8'));
+ ok(U(base), 'an hour of jobs');
+ for (const k of ['project_id', 'env', 'capability', 'unit', 'window', 'window_start', 'window_end', 'quantity', 'errors']) ok(!U({ ...base, [k]: undefined }), `a rollup needs ${k}`);
+ for (const k of ['subject', 'owner', 'actor', 'user_id', 'app_id', 'ip', 'session', 'input', 'request_id']) ok(!U({ ...base, [k]: 'x' }), `a rollup never carries ${k}`);
+ const props = Object.keys(contracts.schema('common.usage-recorded').properties);
+ ok(!props.some(p => /subject|owner|actor|user|ip|session|address/.test(p)), 'no field of the rollup names who did it');
+ const sample = base.samples[0];
+ ok(!U({ ...base, samples: Array.from({ length: 11 }, () => sample) }), 'at most ten sampled failures: a rollup, not a request log');
+ for (const ref of ['usr_01JAB2C3D4E5F6G7H8J9K0MNPQ', 'app_01JAB2C3D4E5F6G7H8J9K0MNPQ', 'req_01JAB2C3D4E5F6G7H8J9K0MNPQ']) ok(!U({ ...base, samples: [{ ...sample, ref }] }), `a sample never refers to ${ref.slice(0, 3)}_`);
+ ok(!U({ ...base, window: 'minute' }) && U({ ...base, window: 'day' }), 'windows are an hour or a day');
+ const R = (v) => contracts.validate('network.project-usage-result@1', v).valid;
+ const res = JSON.parse(fs.readFileSync(path.join(ROOT, 'fixtures/network.project-usage-result/valid/dashboard.json'), 'utf8'));
+ ok(R(res) && !R({ ...res, range: { ...res.range, days: 91 } }), 'a dashboard covers at most 90 days');
+ ok(res.errors.recent.every(e => contracts.validate('common.usage-recorded@1', { ...base, samples: [{ at: e.at, code: e.code, ...(e.status ? { status: e.status } : {}), ...(e.trace_id ? { trace_id: e.trace_id } : {}), ...(e.ref ? { ref: e.ref } : {}) }] }).valid), 'the dashboard\'s recent failures are the rollups\' samples');
+}
+
// ── Capability schemas (WS-C task 4): a ratchet over compatibility/capability-schema-gaps.json ──
// ── Capability schemas (WS-C task 4): a ratchet over compatibility/capability-schema-gaps.json ──
execFileSync(process.execPath, [path.join(__dirname, 'capability-schemas.test.js')], { stdio: 'inherit' });
execFileSync(process.execPath, [path.join(__dirname, 'capability-schemas.test.js')], { stdio: 'inherit' });