openvibers/openvibe.contracts Commits

v0.13.0: OpenVibe.Chat is alpha — chat.live_bridge.write, chat.presence.read; Live gains live.chat_context.read, live.chat_effects.write, live.chat_mirror.write

OP OpenVibers committed 23 Sept 2026 · 4a51c9c638 · 8 files, +136 −8


Changes

ddiff --git a/manifests/capabilities/chat.live_bridge.write.json b/manifests/capabilities/chat.live_bridge.write.json
nnew file mode 100644
iindex 00000000..7929c305
---- /dev/null
++++ b/manifests/capabilities/chat.live_bridge.write.json
@@@ -0,0 +1,22 @@
++{
++ "id": "chat.live_bridge.write",
++ "version": "1.0",
++ "owner": "chat",
++ "status": "planned",
++ "visibility": "internal",
++ "description": "Live's remaining modules (AI viewers, chat relays, donations and alerts, /api/mod, recaps, news, calls, emotes, deploy notices) push to chat clients and write chat rows through OpenVibe.Chat: ChatServer calls in order (broadcasts, DMs with the participant check, TTS, channel sounds, disconnects, user updates, cache invalidations) and allow-listed chat-table writes, applied once per idempotency key, with placeholder ids mapped per Live boot. Transitional: shrinks as those modules move out of Live.",
++ "permissions": [
++ "chat:write"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "internal-write",
++ "events": [
++ "chat.message.created",
++ "chat.moderation.action"
++ ],
++ "implementedBy": [
++ "POST /internal/live/calls"
++ ]
++}
ddiff --git a/manifests/capabilities/chat.presence.read.json b/manifests/capabilities/chat.presence.read.json
nnew file mode 100644
iindex 00000000..7afab024
---- /dev/null
++++ b/manifests/capabilities/chat.presence.read.json
@@@ -0,0 +1,19 @@
++{
++ "id": "chat.presence.read",
++ "version": "1.0",
++ "owner": "chat",
++ "status": "planned",
++ "visibility": "internal",
++ "description": "Who is connected to chat where: connection and per-stream viewer counts, slow modes, and signed-in/anonymous sockets with their addresses — for Live's synchronous reads (health, AI viewer pacing, moderation by address). Internal: carries IP addresses.",
++ "permissions": [
++ "chat:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "internal-read",
++ "events": [],
++ "implementedBy": [
++ "GET /internal/live/presence"
++ ]
++}
ddiff --git a/manifests/capabilities/live.chat_context.read.json b/manifests/capabilities/live.chat_context.read.json
nnew file mode 100644
iindex 00000000..c3260699
---- /dev/null
++++ b/manifests/capabilities/live.chat_context.read.json
@@@ -0,0 +1,37 @@
++{
++ "id": "live.chat_context.read",
++ "version": "1.0",
++ "owner": "live",
++ "status": "planned",
++ "visibility": "internal",
++ "description": "OpenVibe.Chat reads the Live data chat decisions depend on and caches it (Wave 6): user projections and token resolution (Live's own rules, with the Network subject), streams, slots and channels, channel moderation settings and moderators, active bans, follows, IP approvals, cosmetics and tags, the chat site settings (tts_*, GIF and soundboard keys only), anon first-seen, arena-cached TTS clips and the chat profile card. Read-only; no secrets beyond the chat settings.",
++ "permissions": [
++ "live:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "internal-read",
++ "events": [],
++ "implementedBy": [
++ "POST /internal/chat-context/auth",
++ "GET /internal/chat-context/users",
++ "POST /internal/chat-context/users/lookup",
++ "GET /internal/chat-context/users/:id/follows",
++ "GET /internal/chat-context/users/profile",
++ "GET /internal/chat-context/streams",
++ "GET /internal/chat-context/streams/active",
++ "GET /internal/chat-context/streams/:id",
++ "GET /internal/chat-context/managed-streams",
++ "GET /internal/chat-context/channels",
++ "GET /internal/chat-context/channels/by-user/:userId",
++ "GET /internal/chat-context/channels/:id/policy",
++ "GET /internal/chat-context/channels/:id/approved-ip",
++ "GET /internal/chat-context/bans",
++ "POST /internal/chat-context/decor",
++ "GET /internal/chat-context/settings",
++ "GET /internal/chat-context/anon/:num",
++ "GET /internal/chat-context/anon-first-seen",
++ "GET /internal/chat-context/tts-audio/:file"
++ ]
++}
ddiff --git a/manifests/capabilities/live.chat_effects.write.json b/manifests/capabilities/live.chat_effects.write.json
nnew file mode 100644
iindex 00000000..9b445680
---- /dev/null
++++ b/manifests/capabilities/live.chat_effects.write.json
@@@ -0,0 +1,19 @@
++{
++ "id": "live.chat_effects.write",
++ "version": "1.0",
++ "owner": "live",
++ "status": "planned",
++ "visibility": "internal",
++ "description": "OpenVibe.Chat asks Live for the side effects chat triggers in data Live still owns (Wave 6): anon numbers, IP log, viewer counts and snapshots, /color, /ban /timeout /unban rows, IP approvals, /slow persistence, alert sounds, channel creation, TTS site settings, the per-message reactions (OpenCoins chat bonus, AI chat viewers, PowerChat relay), AI mod commands, arena commands, the media queue, hardware commands, /paste, translation, DM notifications and Media asset sync. Live re-checks the acting person (moderator, owner, admin) on every effect that acts for one, and refuses all of them unless CHAT_AUTHORITY=chat.",
++ "permissions": [
++ "live:write"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "internal-write",
++ "events": [],
++ "implementedBy": [
++ "POST /internal/chat-effects/{anon,ip-log,viewer-counts,viewer-snapshots,user-color,ban,approve-ip,channel-settings,alert-sound,ensure-channel,site-settings,chat-message,ai/mod-command,arena-command,media-queue,hardware,paste,translate,notify/dm,notify/dm-read,asset-sync}"
++ ]
++}
ddiff --git a/manifests/capabilities/live.chat_mirror.write.json b/manifests/capabilities/live.chat_mirror.write.json
nnew file mode 100644
iindex 00000000..d674f9f3
---- /dev/null
++++ b/manifests/capabilities/live.chat_mirror.write.json
@@@ -0,0 +1,19 @@
++{
++ "id": "live.chat_mirror.write",
++ "version": "1.0",
++ "owner": "live",
++ "status": "planned",
++ "visibility": "internal",
++ "description": "OpenVibe.Chat copies every change to the tables it owns into Live's tables of the same name and ids (a read mirror for Live's remaining readers and the rollback path). Only the twelve chat tables; only columns Live has; Live-only columns are kept; refused unless CHAT_AUTHORITY=chat. Retired when Live stops reading chat tables.",
++ "permissions": [
++ "live:write"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "internal-write",
++ "events": [],
++ "implementedBy": [
++ "POST /internal/chat-effects/mirror"
++ ]
++}
ddiff --git a/manifests/services/chat.json b/manifests/services/chat.json
iindex 995fec3f..89e064ac 100644
---- a/manifests/services/chat.json
++++ b/manifests/services/chat.json
@@@ -1,16 +1,25 @@
{
-- "version": "0.1.0",
++ "version": "0.2.0",
"contractRanges": {
-- "openvibe-contracts": "^0.1.0"
++ "openvibe-contracts": ">=0.13.0 <1.0.0"
},
"id": "chat",
"name": "OpenVibe.Chat",
-- "status": "placeholder",
++ "status": "alpha",
"repository": "OpenVibers/OpenVibe.Chat",
"domains": [],
-- "capabilities": [],
-- "eventsProduced": [],
++ "capabilities": [
++ "chat.live_bridge.write",
++ "chat.presence.read"
++ ],
++ "eventsProduced": [
++ "chat.message.created",
++ "chat.dm.created",
++ "chat.moderation.action"
++ ],
"eventsConsumed": [],
"namespacesOwned": [],
-- "notes": "Rooms, messages, DMs, calls, TTS and audio queues, moderation and presence \u2014 one identity, every conversation. Charter only; no runtime."
++ "notes": "Wave 6: Live's chat (WebSocket, DMs, history, TTS, sounds, moderation) behind a service boundary on 127.0.0.1:4400. Alpha: runs beside Live; authority moves only when Live runs with CHAT_AUTHORITY=chat and nginx routes the chat paths (see OpenVibe.Chat docs/cutover.md).",
++ "health": "/health",
++ "ready": "/ready"
}
ddiff --git a/manifests/services/live.json b/manifests/services/live.json
iindex 72795b40..e499a419 100644
---- a/manifests/services/live.json
++++ b/manifests/services/live.json
@@@ -15,7 +15,10 @@
"health": "/api/health",
"ready": "/api/ready",
"capabilities": [
-- "chat.message.send"
++ "chat.message.send",
++ "live.chat_context.read",
++ "live.chat_effects.write",
++ "live.chat_mirror.write"
],
"eventsProduced": [],
"eventsConsumed": [],
ddiff --git a/package.json b/package.json
iindex ea65dfa8..b82b707d 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.12.0",
++ "version": "0.13.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",