openvibers/openvibe.contracts Commits

Contracts 0.103.0: schemas for Chat's site-daily, first-chat and sound-by-command reads; planned network.resource.read (#48)

OP OpenVibers committed 5 Oct 2026 · 0ceb61ce82 · 51 files, +698 −75

* Watch contracts, events, capabilities and placeholder service manifest (planned); document runtime:<class>; release 0.102.0

Release 0.102.0 is complete. Here is the change list and verification.

**Schemas (all new, planned, owner `watch`, first-party)**
- `contracts/watch/watch.v1.json:1` — `watch.watch@1` (source/extraction/comparison/condition/actions/budget/retention); source/cadence/extraction/comparison/condition/action/budget/retention live in `$defs` so the request reuses them.
- `contracts/watch/watch-request.v1.json:1` — `watch.watch-request@1` (create/patch body; every field optional, create rules in code).
- `contracts/watch/watch-result.v1.json:1` — `watch.watch-result@1` (`{watches}`/`{watch}`/`{id,status}`/`{id,deleted:true}`).
- `contracts/watch/observation.v1.json:1` — `watch.observation@1` (immutable observation).
- `contracts/watch/check-run.v1.json:1` — `watch.check-run@1` (immutable run; the migration's 12 terminal states).
- `contracts/events/payloads/watch.observation.recorded.v1.json:1` — subject `{watch}`, internal, low, `service:watch`.
- `contracts/events/payloads/watch.watch.triggered.v1.json:1` — subject `{watch}`, internal, important; Network → `WATCH_TRIGGERED` for `recipient`.
- `contracts/events/payloads/watch.check.failed.v1.json:1` — internal, normal, `consecutive_failures`.

**Fixtures** (valid + invalid each): `fixtures/watch.watch/{valid/price-threshold,invalid/missing-owner}.json:1`, `fixtures/watch.watch-request/{valid/create-event-watch,invalid/unknown-status}.json:1`, `fixtures/watch.watch-result/{valid/paused,invalid/not-deleted}.json:1`, `fixtures/watch.observation/{valid/price-changed,invalid/missing-check-run}.json:1`, `fixtures/watch.check-run/{valid/http-changed,invalid/unknown-state}.json:1`, `fixtures/watch.observation.recorded/{valid/price-changed,invalid/missing-owner}.json:1`, `fixtures/watch.watch.triggered/{valid/price-below,invalid/missing-observation}.json:1`, `fixtures/watch.check.failed/{valid/http-error,invalid/zero-failures}.json:1`.

**Catalog / manifests / docs / release**
- `contracts/catalog.json:4190` — the 8 entries, status `planned`, inserted at the end of the `trade.*` block.
- `manifests/capabilities/watch.watch.read.json:1`, `watch.watch.manage.json:1`, `watch.observation.read.json:1`, `watch.check.run.json:1` — planned; `inputSchema`/`outputSchema` (`common.no-body@1`, `watch.watch-request@1`, `watch.watch-result@1`, `watch.observation@1`, `watch.check-run@1`); `implementedBy` empty (no routes exist).
- `manifests/services/watch.json:1` — placeholder like `run.json` (no site/health/internalOrigin; lifecycle all `none`; `>=0.102.0 <1.0.0`).
- `manifests/products/openvibe.watch.json:30` — `relationships.service: "watch"` (needed so `product-catalog.test.js` sees one service serving the domain, exactly as `openvibe.run`→`run`).
- `contracts/platform/resource-offer.v1.json:69` — `capabilities` description now documents `runtime:<class>` for a kind harness beside the reserved `worker:<class>` names (docs-only).
- `CHANGELOG.md:7`, `STATUS.json:12,26`, `package.json:3`, `package-lock.json:3,9` — 0.102.0 release entry/line/feature/version, as the 0.101.0 commit did.
- `generated/` — `npm run generate`: 26 OpenAPI docs (version line), `json-schema/bundle.json`, `typescript/index.d.ts`; no `openapi/watch.json` (planned capabilities are excluded).
- `lib/ids.js:9` — **untouched**: `watch:'wch'`, `observation:'wco'`, `check:'ckr'` were already present.

**Repo-convention deviations from the dossier (stated as requested)**
- The dossier's `watch.triggered` became **`watch.watch.triggered`** (file an

* Contracts 0.103.0: schemas for Chat's site-daily, first-chat and sound-by-command reads; planned network.resource.read

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 23cf4b82..117678a3 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,27 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
++## 0.103.0 — 2026-10-05
++
++**Chat's three new internal reads and Network's resource index** (Chat PR #24; ADR-048). Additive: three new chat result
++contracts and one planned capability, two capability route lists extended, no existing schema broken.
++- `chat.site-daily-result@1` (new, owner `chat`, first-party): the answer of `POST /internal/chat/stats` with
++ `kind: "site-daily"` — `{ days: [{ day, messages, chatters }] }`, one UTC day per entry in `[since, until)`,
++ zero-filled, at most 400 — Live's home series. `chat.stats-request@1` gained `site-daily` in its kind `enum`, with
++ the per-kind `allOf` rule that both `since` and `until` are required, the way its `user` and `stream` kinds already
++ express their required field.
++- `chat.first-chat-result@1` (`{ first }`, Live's welcome check) and `chat.sound-result@1` (`{ sound }`, reusing
++ `chat.sounds-result@1`'s sound projection) are the answers of the other two reads. All three follow the other
++ `chat.*` internal-read schemas: an `anyOf` of the ok shape and `chat.ingress-ack@1`'s error, with valid and
++ invalid fixtures.
++- Capabilities: `GET /internal/chat/first-chat` joins `chat.analysis.read`'s routes and
++ `GET /internal/chat/sounds/by-command` joins `chat.sounds.read`'s.
++- `network.resource.read` (new, owner `network`, first-party, **planned**): OpenVibe.Network's resource index
++ (ADR-048 section 3) — `GET /api/v1/resources` answers `common.resource-list-result@1` and
++ `GET /api/v1/resources/:ovrn` answers `common.resource-summary@1`; listed in `manifests/services/network.json`.
++ The T2 Fabric offer registry's public routes, today sharing `/api/v1/resources`, move to `/api/v1/offers` in
++ Network's own release; no Contracts manifest listed those public routes, so no route list changed here.
++
## 0.102.0 — 2026-10-05
**The Watch contracts** (plan T18). Additive: eight new planned contracts, four planned capabilities and the Watch placeholder manifest, no existing schema changed.
ddiff --git a/STATUS.json b/STATUS.json
iindex e2fa395b..8283b710 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -9,7 +9,7 @@
"plan": "OpenVibe Development Roadmap (combined), Wave 1; implementation plan rev 3 section 3.1",
"deployed": false,
"deployment": "none of its own: a library and artifact repository published as release tags; services pin a tag and deploy it with their own releases",
-- "contracts": "openvibe-contracts v0.102.0 (this package; the newest tag)",
++ "contracts": "openvibe-contracts v0.103.0 (this package; the newest tag)",
"features": [
"589 JSON Schemas with valid and invalid fixtures",
"31 service manifests with lifecycle declarations",
@@@ -23,7 +23,9 @@
"generated estate: docs/ESTATE.md and manifests/repositories/ from the checkouts (scripts/estate.js; --check fails on drift)",
"chat.ticket-conversation@1 and the planned chat.ticket.write capability: a per-ticket conversation keyed by ticket id and calling service, with author_kind person|agent|staff",
"platform.task@1 (planned, owner network) and ADR-044: one task at OpenVibe.Actor's router with a mode, a per-task and per-day budget, result, cost and explanation, SSE progress, cancel and webhooks",
-- "watch.watch@1 and the other Watch contracts (plan T18, planned), three watch events, four capabilities and the placeholder service manifest: user-defined persistent observations over pages, feeds, APIs, events and devices"
++ "watch.watch@1 and the other Watch contracts (plan T18, planned), three watch events, four capabilities and the placeholder service manifest: user-defined persistent observations over pages, feeds, APIs, events and devices",
++ "chat.site-daily-result@1, chat.first-chat-result@1 and chat.sound-result@1: Chat's three new internal reads (kind site-daily for Live's home series, the welcome check, and the sound a !command plays), with chat.stats-request@1 now accepting kind site-daily and the two route lists extended",
++ "network.resource.read (planned, ADR-048): OpenVibe.Network's resource index, GET /api/v1/resources (common.resource-list-result@1) and GET /api/v1/resources/:ovrn (common.resource-summary@1)"
],
"updated": "2026-10-05"
}
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex 1acf461d..fb924efb 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -4728,6 +4728,15 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "chat.site-daily-result",
++ "version": "1.0.0",
++ "owner": "chat",
++ "schema": "chat/site-daily-result.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "chat.messages-page",
"version": "1.0.0",
@@@ -4746,6 +4755,15 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "chat.first-chat-result",
++ "version": "1.0.0",
++ "owner": "chat",
++ "schema": "chat/first-chat-result.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "chat.moderation-queue-result",
"version": "1.0.0",
@@@ -4764,6 +4782,15 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "chat.sound-result",
++ "version": "1.0.0",
++ "owner": "chat",
++ "schema": "chat/sound-result.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "chat.sound-asset-request",
"version": "1.0.0",
ddiff --git a/contracts/chat/first-chat-result.v1.json b/contracts/chat/first-chat-result.v1.json
nnew file mode 100644
iindex 00000000..29bae534
---- /dev/null
++++ b/contracts/chat/first-chat-result.v1.json
@@@ -0,0 +1,26 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/chat/first-chat-result.v1.json",
++ "title": "ChatFirstChatResult",
++ "description": "chat.first-chat-result@1: the answer of GET /internal/chat/first-chat?channel_id&identity on OpenVibe.Chat (capability chat.analysis.read), OpenVibe.Live's welcome check (isFirstChatInChannel): first is true when identity (user:<user_id>, anon:<anonId> or ext:<prefixed username>) has never chatted in the channel, from stream_first_chats, and false when it has. channel_id is the channel owner's Live user id (stream_first_chats.channel_user_id), not Chat's ctx_channels.id. A failure is chat.ingress-ack@1's error.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "first"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "first": {
++ "type": "boolean"
++ }
++ }
++ },
++ {
++ "$ref": "ingress-ack.v1.json#/$defs/error"
++ }
++ ]
++}
ddiff --git a/contracts/chat/site-daily-result.v1.json b/contracts/chat/site-daily-result.v1.json
nnew file mode 100644
iindex 00000000..8ac487bb
---- /dev/null
++++ b/contracts/chat/site-daily-result.v1.json
@@@ -0,0 +1,58 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/chat/site-daily-result.v1.json",
++ "title": "ChatSiteDailyResult",
++ "description": "chat.site-daily-result@1: the answer of POST /internal/chat/stats with kind site-daily on OpenVibe.Chat (capability chat.stats.read), for OpenVibe.Live's home series: every non-deleted message across all channels and the distinct chatters (COALESCE(user_id, anon_id, source_platform || username)) per UTC day in [since, until), one entry per day with zero-filled gaps, at most 400 days. A failure is chat.ingress-ack@1's error.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "days"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "days": {
++ "type": "array",
++ "maxItems": 400,
++ "items": {
++ "$ref": "#/$defs/day"
++ }
++ }
++ }
++ },
++ {
++ "$ref": "ingress-ack.v1.json#/$defs/error"
++ }
++ ],
++ "$defs": {
++ "day": {
++ "type": "object",
++ "required": [
++ "day",
++ "messages",
++ "chatters"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "day": {
++ "type": "string",
++ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
++ "description": "UTC calendar day, 'YYYY-MM-DD'."
++ },
++ "messages": {
++ "type": "integer",
++ "minimum": 0,
++ "description": "Non-deleted messages that day, any message_type."
++ },
++ "chatters": {
++ "type": "integer",
++ "minimum": 0,
++ "description": "Distinct chatters that day (registered, anonymous or relayed)."
++ }
++ }
++ }
++ }
++}
ddiff --git a/contracts/chat/sound-result.v1.json b/contracts/chat/sound-result.v1.json
nnew file mode 100644
iindex 00000000..b32e10ce
---- /dev/null
++++ b/contracts/chat/sound-result.v1.json
@@@ -0,0 +1,26 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/chat/sound-result.v1.json",
++ "title": "ChatSoundResult",
++ "description": "chat.sound-result@1: the answer of GET /internal/chat/sounds/by-command?channel_id&command on OpenVibe.Chat (capability chat.sounds.read): the approved channel sound a !command plays, one at random when several match (OpenVibe.Live's getChannelSoundByCommand), projected exactly as chat.sounds-result@1's sound. channel_id is the channel owner's Live user id (channel_sounds.channel_owner_id). An unknown command or channel is a 404, answered as chat.ingress-ack@1's error.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "sound"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "sound": {
++ "$ref": "sounds-result.v1.json#/$defs/sound"
++ }
++ }
++ },
++ {
++ "$ref": "ingress-ack.v1.json#/$defs/error"
++ }
++ ]
++}
ddiff --git a/contracts/chat/stats-request.v1.json b/contracts/chat/stats-request.v1.json
iindex 3d2adf87..8f3d49f6 100644
---- a/contracts/chat/stats-request.v1.json
++++ b/contracts/chat/stats-request.v1.json
@@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/chat/stats-request.v1.json",
"title": "ChatStatsRequest",
-- "description": "chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.",
++ "description": "chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given; site-daily one row per UTC day in [since, until), zero-filled, a kind that takes only since and until. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.",
"type": "object",
"required": [
"kind"
@@@ -15,7 +15,8 @@
"site",
"user",
"stream",
-- "channel-top"
++ "channel-top",
++ "site-daily"
]
},
"user_id": {
@@@ -84,6 +85,24 @@
"stream_id"
]
}
++ },
++ {
++ "if": {
++ "properties": {
++ "kind": {
++ "const": "site-daily"
++ }
++ },
++ "required": [
++ "kind"
++ ]
++ },
++ "then": {
++ "required": [
++ "since",
++ "until"
++ ]
++ }
}
]
}
ddiff --git a/contracts/chat/stats-result.v1.json b/contracts/chat/stats-result.v1.json
iindex f411492c..f98b5865 100644
---- a/contracts/chat/stats-result.v1.json
++++ b/contracts/chat/stats-result.v1.json
@@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/chat/stats-result.v1.json",
"title": "ChatStatsResult",
-- "description": "chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first. A failure is chat.ingress-ack@1's error ({ ok: false, error }).",
++ "description": "chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first; the kind site-daily is answered by chat.site-daily-result@1, not here. A failure is chat.ingress-ack@1's error ({ ok: false, error }).",
"anyOf": [
{
"type": "object",
ddiff --git a/fixtures/chat.first-chat-result/invalid/missing-first.json b/fixtures/chat.first-chat-result/invalid/missing-first.json
nnew file mode 100644
iindex 00000000..0287aedd
---- /dev/null
++++ b/fixtures/chat.first-chat-result/invalid/missing-first.json
@@@ -0,0 +1,3 @@
++{
++ "ok": true
++}
ddiff --git a/fixtures/chat.first-chat-result/valid/first.json b/fixtures/chat.first-chat-result/valid/first.json
nnew file mode 100644
iindex 00000000..de744754
---- /dev/null
++++ b/fixtures/chat.first-chat-result/valid/first.json
@@@ -0,0 +1,4 @@
++{
++ "ok": true,
++ "first": true
++}
ddiff --git a/fixtures/chat.site-daily-result/invalid/negative-messages.json b/fixtures/chat.site-daily-result/invalid/negative-messages.json
nnew file mode 100644
iindex 00000000..cb274b7a
---- /dev/null
++++ b/fixtures/chat.site-daily-result/invalid/negative-messages.json
@@@ -0,0 +1,9 @@
++{
++ "days": [
++ {
++ "day": "2026-10-03",
++ "messages": -1,
++ "chatters": 96
++ }
++ ]
++}
ddiff --git a/fixtures/chat.site-daily-result/valid/two-days.json b/fixtures/chat.site-daily-result/valid/two-days.json
nnew file mode 100644
iindex 00000000..b55649aa
---- /dev/null
++++ b/fixtures/chat.site-daily-result/valid/two-days.json
@@@ -0,0 +1,15 @@
++{
++ "ok": true,
++ "days": [
++ {
++ "day": "2026-10-03",
++ "messages": 1834,
++ "chatters": 96
++ },
++ {
++ "day": "2026-10-04",
++ "messages": 0,
++ "chatters": 0
++ }
++ ]
++}
ddiff --git a/fixtures/chat.sound-result/invalid/sound-without-url.json b/fixtures/chat.sound-result/invalid/sound-without-url.json
nnew file mode 100644
iindex 00000000..822e3d10
---- /dev/null
++++ b/fixtures/chat.sound-result/invalid/sound-without-url.json
@@@ -0,0 +1,13 @@
++{
++ "sound": {
++ "id": 904,
++ "channel_owner_id": 77,
++ "command": "airhorn",
++ "mime": "audio/mpeg",
++ "duration_seconds": 2.4,
++ "created_by": 512,
++ "created_by_name": "pixelfox",
++ "media_url": null,
++ "media_asset_id": null
++ }
++}
ddiff --git a/fixtures/chat.sound-result/valid/by-command.json b/fixtures/chat.sound-result/valid/by-command.json
nnew file mode 100644
iindex 00000000..1d904b5d
---- /dev/null
++++ b/fixtures/chat.sound-result/valid/by-command.json
@@@ -0,0 +1,15 @@
++{
++ "ok": true,
++ "sound": {
++ "id": 904,
++ "channel_owner_id": 77,
++ "command": "airhorn",
++ "url": "/sounds/77/airhorn.mp3",
++ "mime": "audio/mpeg",
++ "duration_seconds": 2.4,
++ "created_by": 512,
++ "created_by_name": "pixelfox",
++ "media_url": "https://media.openvibe.network/med_01K6R3A1B2C3D4E5F6G7H8J9KA",
++ "media_asset_id": 4402
++ }
++}
ddiff --git a/fixtures/chat.stats-request/invalid/site-daily-without-until.json b/fixtures/chat.stats-request/invalid/site-daily-without-until.json
nnew file mode 100644
iindex 00000000..82d3b128
---- /dev/null
++++ b/fixtures/chat.stats-request/invalid/site-daily-without-until.json
@@@ -0,0 +1,4 @@
++{
++ "kind": "site-daily",
++ "since": 1759449600000
++}
ddiff --git a/fixtures/chat.stats-request/valid/site-daily.json b/fixtures/chat.stats-request/valid/site-daily.json
nnew file mode 100644
iindex 00000000..8f2e8a2e
---- /dev/null
++++ b/fixtures/chat.stats-request/valid/site-daily.json
@@@ -0,0 +1,5 @@
++{
++ "kind": "site-daily",
++ "since": 1759449600000,
++ "until": 1759622400000
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex acc62372..011baa71 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -52906,7 +52906,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/chat/stats-request.v1.json",
"title": "ChatStatsRequest",
-- "description": "chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.",
++ "description": "chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given; site-daily one row per UTC day in [since, until), zero-filled, a kind that takes only since and until. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.",
"type": "object",
"required": [
"kind"
@@@ -52919,7 +52919,8 @@
"site",
"user",
"stream",
-- "channel-top"
++ "channel-top",
++ "site-daily"
]
},
"user_id": {
@@@ -52988,6 +52989,24 @@
"stream_id"
]
}
++ },
++ {
++ "if": {
++ "properties": {
++ "kind": {
++ "const": "site-daily"
++ }
++ },
++ "required": [
++ "kind"
++ ]
++ },
++ "then": {
++ "required": [
++ "since",
++ "until"
++ ]
++ }
}
]
}
@@@ -53000,7 +53019,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/chat/stats-result.v1.json",
"title": "ChatStatsResult",
-- "description": "chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first. A failure is chat.ingress-ack@1's error ({ ok: false, error }).",
++ "description": "chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first; the kind site-daily is answered by chat.site-daily-result@1, not here. A failure is chat.ingress-ack@1's error ({ ok: false, error }).",
"anyOf": [
{
"type": "object",
@@@ -53085,6 +53104,69 @@
}
}
},
++ "chat.site-daily-result": {
++ "version": "1.0.0",
++ "owner": "chat",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/chat/site-daily-result.v1.json",
++ "title": "ChatSiteDailyResult",
++ "description": "chat.site-daily-result@1: the answer of POST /internal/chat/stats with kind site-daily on OpenVibe.Chat (capability chat.stats.read), for OpenVibe.Live's home series: every non-deleted message across all channels and the distinct chatters (COALESCE(user_id, anon_id, source_platform || username)) per UTC day in [since, until), one entry per day with zero-filled gaps, at most 400 days. A failure is chat.ingress-ack@1's error.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "days"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "days": {
++ "type": "array",
++ "maxItems": 400,
++ "items": {
++ "$ref": "#/$defs/day"
++ }
++ }
++ }
++ },
++ {
++ "$ref": "ingress-ack.v1.json#/$defs/error"
++ }
++ ],
++ "$defs": {
++ "day": {
++ "type": "object",
++ "required": [
++ "day",
++ "messages",
++ "chatters"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "day": {
++ "type": "string",
++ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
++ "description": "UTC calendar day, 'YYYY-MM-DD'."
++ },
++ "messages": {
++ "type": "integer",
++ "minimum": 0,
++ "description": "Non-deleted messages that day, any message_type."
++ },
++ "chatters": {
++ "type": "integer",
++ "minimum": 0,
++ "description": "Distinct chatters that day (registered, anonymous or relayed)."
++ }
++ }
++ }
++ }
++ }
++ },
"chat.messages-page": {
"version": "1.0.0",
"owner": "chat",
@@@ -53289,6 +53371,37 @@
]
}
},
++ "chat.first-chat-result": {
++ "version": "1.0.0",
++ "owner": "chat",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/chat/first-chat-result.v1.json",
++ "title": "ChatFirstChatResult",
++ "description": "chat.first-chat-result@1: the answer of GET /internal/chat/first-chat?channel_id&identity on OpenVibe.Chat (capability chat.analysis.read), OpenVibe.Live's welcome check (isFirstChatInChannel): first is true when identity (user:<user_id>, anon:<anonId> or ext:<prefixed username>) has never chatted in the channel, from stream_first_chats, and false when it has. channel_id is the channel owner's Live user id (stream_first_chats.channel_user_id), not Chat's ctx_channels.id. A failure is chat.ingress-ack@1's error.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "first"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "first": {
++ "type": "boolean"
++ }
++ }
++ },
++ {
++ "$ref": "ingress-ack.v1.json#/$defs/error"
++ }
++ ]
++ }
++ },
"chat.moderation-queue-result": {
"version": "1.0.0",
"owner": "chat",
@@@ -53705,6 +53818,37 @@
}
}
},
++ "chat.sound-result": {
++ "version": "1.0.0",
++ "owner": "chat",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/chat/sound-result.v1.json",
++ "title": "ChatSoundResult",
++ "description": "chat.sound-result@1: the answer of GET /internal/chat/sounds/by-command?channel_id&command on OpenVibe.Chat (capability chat.sounds.read): the approved channel sound a !command plays, one at random when several match (OpenVibe.Live's getChannelSoundByCommand), projected exactly as chat.sounds-result@1's sound. channel_id is the channel owner's Live user id (channel_sounds.channel_owner_id). An unknown command or channel is a 404, answered as chat.ingress-ack@1's error.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "sound"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "sound": {
++ "$ref": "sounds-result.v1.json#/$defs/sound"
++ }
++ }
++ },
++ {
++ "$ref": "ingress-ack.v1.json#/$defs/error"
++ }
++ ]
++ }
++ },
"chat.sound-asset-request": {
"version": "1.0.0",
"owner": "chat",
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex c9228388..22bed120 100644
---- a/generated/openapi/ai.json
++++ b/generated/openapi/ai.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.AI API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/billing.json b/generated/openapi/billing.json
iindex 58867efb..57a624bb 100644
---- a/generated/openapi/billing.json
++++ b/generated/openapi/billing.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Billing API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/blog.json b/generated/openapi/blog.json
iindex 1353793f..da00f28f 100644
---- a/generated/openapi/blog.json
++++ b/generated/openapi/blog.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Blog API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/bot.json b/generated/openapi/bot.json
iindex e237c984..d6278e51 100644
---- a/generated/openapi/bot.json
++++ b/generated/openapi/bot.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bot API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/chat.json b/generated/openapi/chat.json
iindex 6165bfe4..89daada6 100644
---- a/generated/openapi/chat.json
++++ b/generated/openapi/chat.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Chat API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
@@@ -72,6 +72,52 @@
}
}
},
++ "/internal/chat/first-chat": {
++ "get": {
++ "operationId": "get_internal_chat_first_chat",
++ "summary": "Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b), and the c",
++ "description": "**chat.analysis.read** (internal): Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b), and the channel welcome check (GET /internal/chat/first-chat: whether an identity has chatted in the channel before). Loopback only, Chat service token (Live's principal today); never granted to an app or delegated to an agent.",
++ "tags": [
++ "chat.analysis"
++ ],
++ "x-openvibe-capabilities": [
++ "chat.analysis.read"
++ ],
++ "x-openvibe-visibility": [
++ "internal"
++ ],
++ "x-openvibe-quota-class": "internal-read",
++ "security": [
++ {
++ "openvibeToken": [
++ "chat.analysis.read"
++ ]
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/chat.timeline-result.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
"/internal/chat/invalidate": {
"post": {
"operationId": "post_internal_chat_invalidate",
@@@ -580,6 +626,52 @@
}
}
},
++ "/internal/chat/sounds/by-command": {
++ "get": {
++ "operationId": "get_internal_chat_sounds_by_command",
++ "summary": "Count a channel's custom sounds, or list the sounds not yet uploaded to OpenVibe.Media, from OpenVibe.Chat's channel_sounds: for OpenVibe.Live's channel readiness and its Media asset sync (plan T3, J4",
++ "description": "**chat.sounds.read** (internal): Count a channel's custom sounds, or list the sounds not yet uploaded to OpenVibe.Media, from OpenVibe.Chat's channel_sounds: for OpenVibe.Live's channel readiness and its Media asset sync (plan T3, J4b). Loopback only, Chat service token (Live's principal today); never granted to an app or delegated to an agent.",
++ "tags": [
++ "chat.sounds"
++ ],
++ "x-openvibe-capabilities": [
++ "chat.sounds.read"
++ ],
++ "x-openvibe-visibility": [
++ "internal"
++ ],
++ "x-openvibe-quota-class": "internal-read",
++ "security": [
++ {
++ "openvibeToken": [
++ "chat.sounds.read"
++ ]
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/chat.sounds-result.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
"/internal/chat/stats": {
"post": {
"operationId": "post_internal_chat_stats",
@@@ -639,8 +731,8 @@
"/internal/chat/timeline": {
"get": {
"operationId": "get_internal_chat_timeline",
-- "summary": "Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b).",
-- "description": "**chat.analysis.read** (internal): Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b). Loopback only, Chat service token (Live's principal today); never granted to an app or delegated to an agent.",
++ "summary": "Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b), and the c",
++ "description": "**chat.analysis.read** (internal): Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b), and the channel welcome check (GET /internal/chat/first-chat: whether an identity has chatted in the channel before). Loopback only, Chat service token (Live's principal today); never granted to an app or delegated to an agent.",
"tags": [
"chat.analysis"
],
@@@ -4108,7 +4200,7 @@
},
"chat.stats-request.v1": {
"title": "ChatStatsRequest",
-- "description": "chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.",
++ "description": "chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given; site-daily one row per UTC day in [since, until), zero-filled, a kind that takes only since and until. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.",
"type": "object",
"required": [
"kind"
@@@ -4121,7 +4213,8 @@
"site",
"user",
"stream",
-- "channel-top"
++ "channel-top",
++ "site-daily"
]
},
"user_id": {
@@@ -4190,12 +4283,30 @@
"stream_id"
]
}
++ },
++ {
++ "if": {
++ "properties": {
++ "kind": {
++ "const": "site-daily"
++ }
++ },
++ "required": [
++ "kind"
++ ]
++ },
++ "then": {
++ "required": [
++ "since",
++ "until"
++ ]
++ }
}
]
},
"chat.stats-result.v1": {
"title": "ChatStatsResult",
-- "description": "chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first. A failure is chat.ingress-ack@1's error ({ ok: false, error }).",
++ "description": "chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first; the kind site-daily is answered by chat.site-daily-result@1, not here. A failure is chat.ingress-ack@1's error ({ ok: false, error }).",
"anyOf": [
{
"type": "object",
ddiff --git a/generated/openapi/codes.json b/generated/openapi/codes.json
iindex 2fb5e46a..9b43d070 100644
---- a/generated/openapi/codes.json
++++ b/generated/openapi/codes.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Codes API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/community.json b/generated/openapi/community.json
iindex 7c587bc9..3de3d42c 100644
---- a/generated/openapi/community.json
++++ b/generated/openapi/community.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Community API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/coupons.json b/generated/openapi/coupons.json
iindex fc0f24ec..668cb8da 100644
---- a/generated/openapi/coupons.json
++++ b/generated/openapi/coupons.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Coupons API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/deals.json b/generated/openapi/deals.json
iindex b73977d2..1d6ac48c 100644
---- a/generated/openapi/deals.json
++++ b/generated/openapi/deals.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Deals API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/events.json b/generated/openapi/events.json
iindex 3ef82e4f..aee29e1e 100644
---- a/generated/openapi/events.json
++++ b/generated/openapi/events.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Events API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/games.json b/generated/openapi/games.json
iindex 48044a31..ca712e85 100644
---- a/generated/openapi/games.json
++++ b/generated/openapi/games.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Games API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/host.json b/generated/openapi/host.json
iindex 500e060e..85a8edf9 100644
---- a/generated/openapi/host.json
++++ b/generated/openapi/host.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Host API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/index.json b/generated/openapi/index.json
iindex 4dfc0eeb..21ebba16 100644
---- a/generated/openapi/index.json
++++ b/generated/openapi/index.json
@@@ -33,7 +33,7 @@
"service": "chat",
"name": "OpenVibe.Chat",
"origin": "https://openvibe.chat",
-- "operations": 17,
++ "operations": 19,
"capabilities": 11
},
{
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex e473868a..739faa20 100644
---- a/generated/openapi/live.json
++++ b/generated/openapi/live.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Live API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/media.json b/generated/openapi/media.json
iindex de280ed7..74864a5d 100644
---- a/generated/openapi/media.json
++++ b/generated/openapi/media.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Media API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/network.json b/generated/openapi/network.json
iindex 93f685a3..023cb128 100644
---- a/generated/openapi/network.json
++++ b/generated/openapi/network.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Network API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex f8bcdd03..a252d434 100644
---- a/generated/openapi/news.json
++++ b/generated/openapi/news.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.News API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/openre.json b/generated/openapi/openre.json
iindex c4c0d20b..ac29753b 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRe.Stream API",
-- "version": "0.102.0",
-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/reviews.json b/generated/openapi/reviews.json
iindex 6baace4c..fa3cfcb7 100644
---- a/generated/openapi/reviews.json
++++ b/generated/openapi/reviews.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Reviews API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/search.json b/generated/openapi/search.json
iindex e21ac475..0683b4fa 100644
---- a/generated/openapi/search.json
++++ b/generated/openapi/search.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Search API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/sources.json b/generated/openapi/sources.json
iindex d32d22d8..a0da8eac 100644
---- a/generated/openapi/sources.json
++++ b/generated/openapi/sources.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Sources API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/space.json b/generated/openapi/space.json
iindex 1d6a8fda..141dc5ea 100644
---- a/generated/openapi/space.json
++++ b/generated/openapi/space.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Space API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/tips.json b/generated/openapi/tips.json
iindex aa16c196..3a05cba2 100644
---- a/generated/openapi/tips.json
++++ b/generated/openapi/tips.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tips API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/tools.json b/generated/openapi/tools.json
iindex c7c5c67c..8f01fb13 100644
---- a/generated/openapi/tools.json
++++ b/generated/openapi/tools.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tools API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/trade.json b/generated/openapi/trade.json
iindex 2eaccc16..eada7aaa 100644
---- a/generated/openapi/trade.json
++++ b/generated/openapi/trade.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Trade API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/vip.json b/generated/openapi/vip.json
iindex 8d78c9a6..18341b1f 100644
---- a/generated/openapi/vip.json
++++ b/generated/openapi/vip.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.VIP API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/openapi/wiki.json b/generated/openapi/wiki.json
iindex a09e5a74..cd86fa95 100644
---- a/generated/openapi/wiki.json
++++ b/generated/openapi/wiki.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Wiki API",
-- "version": "0.102.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.102.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.103.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.103.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"
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex 5216b1ac..e2d8223f 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -51164,12 +51164,12 @@ export type ChatEmoteCountResult =
/** [email protected] (owner: chat) */
/**
-- * chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.
++ * chat.stats-request@1: the body of POST /internal/chat/stats on OpenVibe.Chat (capability chat.stats.read): one count over chat_messages, for the stats OpenVibe.Live shows without reading its own copy of Chat's tables (home and SEO stats, admin dashboard, star of the day, VOD and recap cards, stream analytics, top chatters, AI slogans). kind site counts all of chat; user one person's messages (user_id); stream one stream's messages, chatters and soundboard plays (stream_id); channel-top the top chatters, of one stream (stream_id) or one channel (channel_user_id), or of all chat when neither is given; site-daily one row per UTC day in [since, until), zero-filled, a kind that takes only since and until. since and until bound chat_messages.timestamp, epoch ms, until exclusive. Deleted messages are never counted. Loopback only, service token.
*/
export type ChatStatsRequest = {
[k: string]: unknown | undefined;
} & {
-- kind: "site" | "user" | "stream" | "channel-top";
++ kind: "site" | "user" | "stream" | "channel-top" | "site-daily";
/**
* Live user id; required for kind user.
*/
@@@ -51198,7 +51198,7 @@ export type ChatStatsRequest = {
/** [email protected] (owner: chat) */
/**
-- * chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first. A failure is chat.ingress-ack@1's error ({ ok: false, error }).
++ * chat.stats-result@1: the answer of POST /internal/chat/stats (chat.stats.read). site, user and stream answer messages (non-deleted chat_messages rows) and chatters (distinct COALESCE(user_id, anon_id, source_platform || username)); stream also answers sounds (soundboard plays); channel-top answers top_chatters, most messages first; the kind site-daily is answered by chat.site-daily-result@1, not here. A failure is chat.ingress-ack@1's error ({ ok: false, error }).
*/
export type ChatStatsResult =
| {
@@@ -51238,6 +51238,39 @@ export type ChatStatsResult =
error: string;
};
++/** [email protected] (owner: chat) */
++/**
++ * chat.site-daily-result@1: the answer of POST /internal/chat/stats with kind site-daily on OpenVibe.Chat (capability chat.stats.read), for OpenVibe.Live's home series: every non-deleted message across all channels and the distinct chatters (COALESCE(user_id, anon_id, source_platform || username)) per UTC day in [since, until), one entry per day with zero-filled gaps, at most 400 days. A failure is chat.ingress-ack@1's error.
++ */
++export type ChatSiteDailyResult =
++ | {
++ ok?: true;
++ /**
++ * @maxItems 400
++ */
++ days: {
++ /**
++ * UTC calendar day, 'YYYY-MM-DD'.
++ */
++ day: string;
++ /**
++ * Non-deleted messages that day, any message_type.
++ */
++ messages: number;
++ /**
++ * Distinct chatters that day (registered, anonymous or relayed).
++ */
++ chatters: number;
++ }[];
++ }
++ | {
++ ok: false;
++ /**
++ * A human-readable reason.
++ */
++ error: string;
++ };
++
/** [email protected] (owner: chat) */
/**
* chat.messages-page@1: the answer of GET /internal/chat/messages on OpenVibe.Chat (capability chat.messages.read), which pages non-deleted chat_messages for OpenVibe.Live's AI context, clip and viewer jobs and its moderator search and history. Query: one filter of channel_user_id, stream_id, user_id, anon_id, username or id (one message), a cursor on id (after_id ascending, before_id descending), limit, and tail=1 (no rows, only max_id). max_id is the highest id matching the filter, null when none, so a caller can resume after it. A failure is chat.ingress-ack@1's error.
@@@ -51311,6 +51344,23 @@ export type ChatTimelineResult =
error: string;
};
++/** [email protected] (owner: chat) */
++/**
++ * chat.first-chat-result@1: the answer of GET /internal/chat/first-chat?channel_id&identity on OpenVibe.Chat (capability chat.analysis.read), OpenVibe.Live's welcome check (isFirstChatInChannel): first is true when identity (user:<user_id>, anon:<anonId> or ext:<prefixed username>) has never chatted in the channel, from stream_first_chats, and false when it has. channel_id is the channel owner's Live user id (stream_first_chats.channel_user_id), not Chat's ctx_channels.id. A failure is chat.ingress-ack@1's error.
++ */
++export type ChatFirstChatResult =
++ | {
++ ok?: true;
++ first: boolean;
++ }
++ | {
++ ok: false;
++ /**
++ * A human-readable reason.
++ */
++ error: string;
++ };
++
/** [email protected] (owner: chat) */
/**
* chat.moderation-queue-result@1: what OpenVibe.Chat's moderation queue reads answer (capability chat.moderation.queue.read), one shape per route, for OpenVibe.Live's moderator pages: GET /internal/chat/moderation/pending-ip?channel_id → { pending_ip } (a channel's messages held for IP approval, status pending, oldest first); GET /internal/chat/moderation/relay-users?channel_id → { relay_users } (relay names hidden or banned on the channel or everywhere, newest first); GET /internal/chat/moderation/relay-users/:id → { relay_user } (one, null when unknown); GET /internal/chat/moderation/tts-override?identity_key → { tts_override } (null when none). Internal: rows carry IP addresses. A failure is chat.ingress-ack@1's error.
@@@ -51454,6 +51504,52 @@ export type ChatSoundsResult =
error: string;
};
++/** [email protected] (owner: chat) */
++/**
++ * chat.sound-result@1: the answer of GET /internal/chat/sounds/by-command?channel_id&command on OpenVibe.Chat (capability chat.sounds.read): the approved channel sound a !command plays, one at random when several match (OpenVibe.Live's getChannelSoundByCommand), projected exactly as chat.sounds-result@1's sound. channel_id is the channel owner's Live user id (channel_sounds.channel_owner_id). An unknown command or channel is a 404, answered as chat.ingress-ack@1's error.
++ */
++export type ChatSoundResult =
++ | {
++ ok?: true;
++ /**
++ * One channel_sounds row.
++ */
++ sound: {
++ id: number;
++ channel_owner_id: number;
++ /**
++ * The trigger word (no leading '!'), lowercased: the sound's name.
++ */
++ command: string;
++ /**
++ * Where Chat keeps the audio file (its on-disk path).
++ */
++ url: string;
++ mime?: string | null;
++ duration_seconds?: number | null;
++ /**
++ * The uploader's Live user id.
++ */
++ created_by?: number | null;
++ created_by_name?: string | null;
++ /**
++ * The file's OpenVibe.Media URL; null until Live's asset sync uploaded it.
++ */
++ media_url: string | null;
++ /**
++ * The OpenVibe.Media asset id; null until uploaded.
++ */
++ media_asset_id: number | null;
++ };
++ }
++ | {
++ ok: false;
++ /**
++ * A human-readable reason.
++ */
++ error: string;
++ };
++
/** [email protected] (owner: chat) */
/**
* chat.sound-asset-request@1: the body of POST /internal/chat/sounds/asset on OpenVibe.Chat (capability chat.sounds.write): after OpenVibe.Live's asset sync uploaded a channel sound to OpenVibe.Media, the asset is written back onto Chat's channel_sounds row id. Writing the same asset again is a no-op; an unknown id is 404. Answers chat.ingress-ack@1.
ddiff --git a/manifests/capabilities/chat.analysis.read.json b/manifests/capabilities/chat.analysis.read.json
iindex 42c2454e..28fc69e7 100644
---- a/manifests/capabilities/chat.analysis.read.json
++++ b/manifests/capabilities/chat.analysis.read.json
@@@ -4,7 +4,7 @@
"owner": "chat",
"status": "active",
"visibility": "internal",
-- "description": "Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b). Loopback only, Chat service token (Live's principal today); never granted to an app or delegated to an agent.",
++ "description": "Count a channel's or a stream's chat messages per time bucket, with the latest message id: the chat timeline behind OpenVibe.Live's AI moments, chat spikes and activity reads (plan T3, J4b), and the channel welcome check (GET /internal/chat/first-chat: whether an identity has chatted in the channel before). Loopback only, Chat service token (Live's principal today); never granted to an app or delegated to an agent.",
"permissions": [
"chat:read"
],
@@@ -14,7 +14,8 @@
"quotaClass": "internal-read",
"events": [],
"implementedBy": [
-- "GET /internal/chat/timeline"
++ "GET /internal/chat/timeline",
++ "GET /internal/chat/first-chat"
],
"inputSchema": "common.no-body@1",
"outputSchema": "chat.timeline-result@1"
ddiff --git a/manifests/capabilities/chat.sounds.read.json b/manifests/capabilities/chat.sounds.read.json
iindex 11b097f8..aa9d93cc 100644
---- a/manifests/capabilities/chat.sounds.read.json
++++ b/manifests/capabilities/chat.sounds.read.json
@@@ -14,7 +14,8 @@
"quotaClass": "internal-read",
"events": [],
"implementedBy": [
-- "GET /internal/chat/sounds"
++ "GET /internal/chat/sounds",
++ "GET /internal/chat/sounds/by-command"
],
"inputSchema": "common.no-body@1",
"outputSchema": "chat.sounds-result@1"
ddiff --git a/manifests/capabilities/network.resource.read.json b/manifests/capabilities/network.resource.read.json
nnew file mode 100644
iindex 00000000..44098db2
---- /dev/null
++++ b/manifests/capabilities/network.resource.read.json
@@@ -0,0 +1,22 @@
++{
++ "id": "network.resource.read",
++ "version": "1.0",
++ "owner": "network",
++ "status": "planned",
++ "visibility": "first-party",
++ "description": "Read OpenVibe.Network's resource index (ADR-048): GET /api/v1/resources lists the resources Network owns as a page of common.resource-summary@1 (common.resource-list-result@1), and GET /api/v1/resources/:ovrn reads one by its OVRN (common.resource-summary@1). Every authority serves these for OpenVibe.Services to fan out and merge; Network's own resources today are its projects, apps, keys and nodes. Planned until Network ships the index; the T2 Fabric offer registry's public routes, today sharing /api/v1/resources, move to /api/v1/offers in the same release.",
++ "permissions": [
++ "resources:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "standard",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/resources",
++ "GET /api/v1/resources/:ovrn"
++ ],
++ "inputSchema": "common.no-body@1",
++ "outputSchema": "common.resource-list-result@1"
++}
ddiff --git a/manifests/services/network.json b/manifests/services/network.json
iindex f5fa46a8..b13b3c9e 100644
---- a/manifests/services/network.json
++++ b/manifests/services/network.json
@@@ -57,6 +57,7 @@
"network.project.manage",
"network.project.read",
"network.registry.read",
++ "network.resource.read",
"network.resource.report",
"network.staff.read",
"network.status.incident"
ddiff --git a/package-lock.json b/package-lock.json
iindex 626c49eb..d45ab879 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-contracts",
-- "version": "0.102.0",
++ "version": "0.103.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-contracts",
-- "version": "0.102.0",
++ "version": "0.103.0",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex ed2e7bed..7557b864 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.102.0",
++ "version": "0.103.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",