openvibers/openvibe.chat Commits
README and STATUS.json are current (roadmap WS-U task 3): the README gains Security (SECURITY.md, auth, private data, network exposure, egress, secrets by name) and Deploy (sudo ovhost deploy chat, unit, port, env file, /ready, both nginx files, N-1 recording, rollback) sections. Capabilities and events now lists every event Chat produces and consumes and the grants it uses at Live, Events, Network, VIP and Tools. The status, domain and launch-rule lines say openvibe.chat launched on 2026-09-24 (it left OpenVibe.Sites that day), not that it is a placeholder, and drop a stale release sha. STATUS.json names openvibe-contracts v0.71.0, gains features, corrects the domain, events, capabilities used and the in-code-only notes, and is updated 2026-09-28.
Changes
@@@ -4,10 +4,12 @@**Status:** alpha — deployed. Since the cutover on 2026-09-23 at 02:03 UTC (`docs/cutover.md`),Chat is the authority for openvibe.live's chat: the service runs on `openvibe-ovh` (unit--`openvibe-chat`, 127.0.0.1:4400, release `45f2b1f`), Live runs with `CHAT_AUTHORITY=chat` and keeps--a read mirror, and chat events go to OpenVibe.Events. `openvibe.chat` still shows its placeholder.--**Domain:** `openvibe.chat` (placeholder); Chat is served on Live's origin:--`https://openvibe.live/ws/chat`, `/api/chat/`, `/api/dm/`, `/api/tts/`, `/api/sounds` via nginx.++`openvibe-chat`, 127.0.0.1:4400), Live runs with `CHAT_AUTHORITY=chat` and keeps a read mirror, and++chat events go to OpenVibe.Events. `openvibe.chat` is Chat's own site (global chat, messages, rooms,++settings; the service manifest records it live since 2026-09-24).++**Domain:** `openvibe.chat` ([deploy/nginx/openvibe.chat.conf](deploy/nginx/openvibe.chat.conf)); Chat++is also served on Live's origin: `https://openvibe.live/ws/chat`, `/api/chat/`, `/api/dm/`,++`/api/tts/`, `/api/sounds` via nginx.**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §9 and §9.5.**License:** AGPL-3.0 (same as every OpenVibe service).@@@ -430,10 +432,23 @@ v0.30.2 (so is the `chat.preferences` user module since v0.32.0); the check namethe contracts check enforces it. Planned families:`chat.room.*`, `chat.message.*`, `chat.dm.*`, `chat.moderation.*`, `chat.tts.*`, `chat.call.*`.--Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat.moderation.action`--(produced); planned `chat.room.updated`, `chat.call.*`, `chat.tts.queued|played|failed`. Consumed:--`live.release.deployed`, `network.module.updated` (Chat's own subscriptions: Network grant--`chat events.subscription.manage openvibe.events`).++Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat.moderation.action`,++`chat.room.message.created`, `chat.room.message.deleted` (produced); planned `chat.room.updated`,++`chat.call.*`, `chat.tts.queued|played|failed`. Consumed at `POST /internal/events` (signature v2,++`CHAT_EVENTS_SECRET`, openvibe-sdk inbox): `live.release.deployed`, `network.module.updated`,++`network.user.token_valid_after`, `vip.membership.changed`, `network.block.changed`,++`network.subject.merged`, `network.account.export_requested` and `network.account.deleted` (Chat's own++subscriptions, created at boot when missing).++++Called elsewhere, as the service principal `chat` ([server/net/service-auth.js](server/net/service-auth.js)):++++| Service | Grant | Why |++|---|---|---|++| OpenVibe.Live | `live.chat_context.read`, `live.chat_effects.write`, `live.chat_mirror.write` | the chat context Live still owns (bans, channel settings), effects, the read mirror |++| OpenVibe.Events | `events.event.publish`, `events.subscription.manage` | the outbox relay; the subscriptions above |++| OpenVibe.Network | `network.modules.read`, `network.modules.write` | chat preferences and the other chat user modules |++| OpenVibe.VIP | `vip.entitlement.check` | subscriber badges (fails closed) |++| OpenVibe.Tools | `tools.tool.run`, `tools.job.read` | sound uploads to MP3 (local ffmpeg is the fallback) |## Depends on@@@ -452,6 +467,41 @@ Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat- a paid TTS request is never duplicated by a retry — *forwarded writes are applied once per idempotency key; paid TTS does not exist yet*- after a reconnect, deleted and blocked state converge; browser parity (join, send, DM, `/tts`, moderation, popout) — *`scripts/parity.js` and `test/parity.test.js` (`docs/parity.md`): a reader that was away converges on what a connected reader saw (cursor reads carry `deleted_ids`); gaps: sub-only mode does not exist, public chat does not apply blocks*++## Security++++Reporting a vulnerability: [SECURITY.md](SECURITY.md). The rules the code keeps:++++- **Auth.** People sign in with a Network session JWT, verified here with the Network's key (tokens++ issued before a subject's `token_valid_after` are refused), or an `hbt_` API token resolved through++ Live; `?token=` on `/ws/chat` is deprecated. Services use client-credentials tokens for audience++ `openvibe.chat`, checked per capability (`chat.live_bridge.write`, `chat.message.send`,++ `chat.presence.read`). Staff gates ask the contracts staff map.++- **Private data.** DMs are delivered only to participants, and private rooms only to members++ (`test/security-crawl.js` walks every route); network blocks count like DM blocks; a staff member++ reading someone else's chat logs is recorded as a moderation action; account export and deletion++ follow Network's events.++- **Network exposure.** `/internal/*` and `/metrics` answer 404 through nginx, which sets the client++ address from the connection only; WS upgrades check the origin and IP bans.++- **Egress.** Chat calls its configured Network, Live, Events, VIP and Tools hosts; the soundboard++ import fetches only 101soundboards' own addresses, checked on every DNS answer.++- **Secrets.** `OV_OAUTH_CLIENT_SECRET` and `CHAT_EVENTS_SECRET` live in `/etc/openvibe/chat.env` (0600),++ by name only.++++## Deploy++++Production deploys with `sudo ovhost deploy chat` on the host (strategy `git-checkout`: fetch,++fast-forward `/opt/openvibe.chat`, install on a lockfile change, restart, wait for `/ready`).++The unit is `openvibe-chat.service` on `127.0.0.1:4400`, the env file `/etc/openvibe/chat.env`. Readiness is++`/ready` (not `/api/ready`). nginx: [deploy/nginx/openvibe.chat.conf](deploy/nginx/openvibe.chat.conf)++for openvibe.chat and [deploy/nginx/openvibe.live-chat.locations.conf](deploy/nginx/openvibe.live-chat.locations.conf),++included in openvibe.live's vhost, for Live's chat paths. After a deploy, record the N-1 fixtures++(`npm run n-1:record`). Switching chat back to Live is in `docs/cutover.md` (with++`scripts/mirror-flush.js`).++++Rollback: ovhost puts the previous sha back by itself when `/ready` does not answer 2xx after the++restart; afterwards `sudo ovhost rollback chat --to <sha>`. Nothing blocks a rollback: the schema++code only adds tables and columns.++## Launch ruleThis repository does not make the product real, and the domain keeps its placeholder page on@@@ -468,7 +518,8 @@ following exist here (plan §12.12):The launch release removes the domain from `OpenVibe.Sites/sites.json`, switches routing andregisters maturity in the ecosystem registry atomically. A placeholder is never counted as an--implemented service.++implemented service. `openvibe.chat` launched on 2026-09-24 (global chat, messages, settings): it++left OpenVibe.Sites, and this repository's vhost serves it.---@@@ -6,18 +6,44 @@"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)","runtime": "node 22, express, ws, better-sqlite3","port": 4400,-- "domain": "openvibe.live (/ws/chat, /api/chat/, /api/dm/, /api/tts/, /api/sounds via an nginx include in openvibe.live's vhost); openvibe.chat is still the OpenVibe.Sites placeholder",-- "contracts": "openvibe-contracts v0.33.0",++ "domain": "openvibe.chat (Chat's own site: global chat, messages, rooms, settings; the service manifest records it live since 2026-09-24) and openvibe.live (/ws/chat, /api/chat/, /api/dm/, /api/tts/, /api/sounds via an nginx include in openvibe.live's vhost)",++ "contracts": "openvibe-contracts v0.71.0","capabilities": ["chat.live_bridge.write", "chat.message.send", "chat.presence.read"],-- "capabilitiesUsed": ["live.chat_context.read", "live.chat_effects.write", "live.chat_mirror.write", "events.event.publish", "events.subscription.manage", "vip.entitlement.check", "network.modules.read", "network.modules.write"],++ "capabilitiesUsed": [++ "live.chat_context.read",++ "live.chat_effects.write",++ "live.chat_mirror.write",++ "events.event.publish",++ "events.subscription.manage",++ "vip.entitlement.check",++ "network.modules.read",++ "network.modules.write",++ "tools.tool.run",++ "tools.job.read"++ ],"capabilitiesRegistered": true,-- "events": ["chat.message.created", "chat.message.deleted", "chat.dm.created", "chat.moderation.action"],-- "eventsConsumed": "live.release.deployed (the deploy card, folded by subject.id with the bridge's deployNotice: one card per head whichever comes first; register C-84) and network.module.updated (drops a cached chat.preferences copy), POST /internal/events, signature v2, openvibe-sdk inbox; subscriptions created at boot. In code only, not deployed; needs CHAT_EVENTS_SECRET in chat.env and the Network grant chat events.subscription.manage openvibe.events",++ "events": ["chat.message.created", "chat.message.deleted", "chat.dm.created", "chat.moderation.action", "chat.room.message.created", "chat.room.message.deleted"],++ "eventsConsumed": "live.release.deployed, network.module.updated, network.user.token_valid_after, vip.membership.changed, network.block.changed, network.subject.merged, network.account.export_requested and network.account.deleted at POST /internal/events (signature v2, openvibe-sdk inbox); subscriptions created at boot when missing (CHAT_EVENTS_SECRET and the Network grant chat events.subscription.manage openvibe.events)","liveAuthorityFlag": "CHAT_AUTHORITY=chat is set in production live.env since the cutover (2026-09-23 02:03 UTC); Live's chat tables are a read mirror Chat keeps current",-- "vip": "Member badges from OpenVibe.VIP (server/vip/badges.js: entitlements/check with product chat, cached 60 s, never blocks sending, fails closed). In code only, not deployed; needs the Network grant chat vip.entitlement.check openvibe.vip and Live's chat UI to render vip_badge / chat_vip_badge",-- "preferences": "Chat preferences in the Network user module chat.preferences (server/prefs/: GET/PUT /api/chat/preferences with Chat's service token, cached 60 s, If-Match on every write; scripts/migrate-chat-preferences.js moves the choices in Live's user_preferences). In code only, not deployed; needs Network with the chat.preferences handoff and the grants chat network.modules.read/write on chat.preferences, then the migration, then Live's chat.js calling /api/chat/preferences",-- "calls": "Live's call server, call routes and stream hooks ported to server/calls/ with a calls lifecycle table (WS-I task 1). In code only, off (CHAT_CALLS unset); the switch is CHAT_CALLS=1, Live CALLS_AUTHORITY=chat and the nginx include deploy/nginx/calls/openvibe.live-calls.locations.conf (docs/calls-cutover.md)",++ "vip": "Member badges from OpenVibe.VIP (server/vip/badges.js: entitlements/check with product chat, cached 60 s, never blocks sending, fails closed; vip.membership.changed drops the cache). Needs the Network grant chat vip.entitlement.check openvibe.vip",++ "preferences": "Chat preferences in the Network user module chat.preferences, plus chat.tts_defaults, chat.dm_settings and chat.presence_prefs (server/prefs/: /api/chat/preferences and siblings with Chat's service token, cached 60 s, If-Match on every write; scripts/migrate-chat-preferences.js moves the choices in Live's user_preferences). Needs the grants chat network.modules.read/write",++ "calls": "Live's call server, call routes and stream hooks ported to server/calls/ with a calls lifecycle table (WS-I task 1). Off unless CHAT_CALLS=1; the switch is CHAT_CALLS=1, Live CALLS_AUTHORITY=chat and the nginx include deploy/nginx/calls/openvibe.live-calls.locations.conf (docs/calls-cutover.md)","deployed": true,-- "deployment": "openvibe-ovh /opt/openvibe.chat, unit openvibe-chat, 127.0.0.1:4400 (loopback); public only through openvibe.live's nginx include for the chat paths; release 45f2b1f; EVENTS_URL set (chat.message.created reaches OpenVibe.Events); restore drill passed 2026-09-23",-- "updated": "2026-09-23"++ "deployment": "Deployed with `sudo ovhost deploy chat`: /opt/openvibe.chat, unit openvibe-chat, 127.0.0.1:4400 (loopback); public through the openvibe.chat vhost and openvibe.live's nginx include for the chat paths; EVENTS_URL set (chat.message.created reaches OpenVibe.Events); restore drill passed 2026-09-23",++ "updated": "2026-09-28",++ "features": [++ "Live's global, stream and channel chat (authority since 2026-09-23, Live keeps a read mirror)",++ "DMs and group DMs, participants only",++ "rooms: public and private, roles, invitations, slow mode, unread counts",++ "moderation: bans, timeouts, purges, filters, slow, sub-only and member-only modes, audited log access",++ "TTS, sounds and soundboard with persisted queues",++ "calls ported from Live (off until the calls cutover)",++ "openvibe.chat site: global chat, messages, rooms, settings, history download",++ "chat preferences in Network user modules",++ "VIP subscriber badges",++ "network blocks, revocation, account merge, export and deletion from Network events",++ "outbox events and chat.room.message.* on the realtime plane",++ "N-1 compatibility tests",++ "per-actor limits (openvibe-sdk/limits)"++ ]}
@@ -4,10 +4,12 @@
@@ -4,10 +4,12 @@
**Status:** alpha — deployed. Since the cutover on 2026-09-23 at 02:03 UTC (`docs/cutover.md`),
**Status:** alpha — deployed. Since the cutover on 2026-09-23 at 02:03 UTC (`docs/cutover.md`),
Chat is the authority for openvibe.live's chat: the service runs on `openvibe-ovh` (unit
Chat is the authority for openvibe.live's chat: the service runs on `openvibe-ovh` (unit
-`openvibe-chat`, 127.0.0.1:4400, release `45f2b1f`), Live runs with `CHAT_AUTHORITY=chat` and keeps
-a read mirror, and chat events go to OpenVibe.Events. `openvibe.chat` still shows its placeholder.
-**Domain:** `openvibe.chat` (placeholder); Chat is served on Live's origin:
-`https://openvibe.live/ws/chat`, `/api/chat/`, `/api/dm/`, `/api/tts/`, `/api/sounds` via nginx.
+`openvibe-chat`, 127.0.0.1:4400), Live runs with `CHAT_AUTHORITY=chat` and keeps a read mirror, and
+chat events go to OpenVibe.Events. `openvibe.chat` is Chat's own site (global chat, messages, rooms,
+settings; the service manifest records it live since 2026-09-24).
+**Domain:** `openvibe.chat` ([deploy/nginx/openvibe.chat.conf](deploy/nginx/openvibe.chat.conf)); Chat
+is also served on Live's origin: `https://openvibe.live/ws/chat`, `/api/chat/`, `/api/dm/`,
+`/api/tts/`, `/api/sounds` via nginx.
**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §9 and §9.5.
**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §9 and §9.5.
**License:** AGPL-3.0 (same as every OpenVibe service).
**License:** AGPL-3.0 (same as every OpenVibe service).
@@ -430,10 +432,23 @@ v0.30.2 (so is the `chat.preferences` user module since v0.32.0); the check name
@@ -430,10 +432,23 @@ v0.30.2 (so is the `chat.preferences` user module since v0.32.0); the check name
the contracts check enforces it. Planned families:
the contracts check enforces it. Planned families:
`chat.room.*`, `chat.message.*`, `chat.dm.*`, `chat.moderation.*`, `chat.tts.*`, `chat.call.*`.
`chat.room.*`, `chat.message.*`, `chat.dm.*`, `chat.moderation.*`, `chat.tts.*`, `chat.call.*`.
-Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat.moderation.action`
-(produced); planned `chat.room.updated`, `chat.call.*`, `chat.tts.queued|played|failed`. Consumed:
-`live.release.deployed`, `network.module.updated` (Chat's own subscriptions: Network grant
-`chat events.subscription.manage openvibe.events`).
+Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat.moderation.action`,
+`chat.room.message.created`, `chat.room.message.deleted` (produced); planned `chat.room.updated`,
+`chat.call.*`, `chat.tts.queued|played|failed`. Consumed at `POST /internal/events` (signature v2,
+`CHAT_EVENTS_SECRET`, openvibe-sdk inbox): `live.release.deployed`, `network.module.updated`,
+`network.user.token_valid_after`, `vip.membership.changed`, `network.block.changed`,
+`network.subject.merged`, `network.account.export_requested` and `network.account.deleted` (Chat's own
+subscriptions, created at boot when missing).
+
+Called elsewhere, as the service principal `chat` ([server/net/service-auth.js](server/net/service-auth.js)):
+
+| Service | Grant | Why |
+|---|---|---|
+| OpenVibe.Live | `live.chat_context.read`, `live.chat_effects.write`, `live.chat_mirror.write` | the chat context Live still owns (bans, channel settings), effects, the read mirror |
+| OpenVibe.Events | `events.event.publish`, `events.subscription.manage` | the outbox relay; the subscriptions above |
+| OpenVibe.Network | `network.modules.read`, `network.modules.write` | chat preferences and the other chat user modules |
+| OpenVibe.VIP | `vip.entitlement.check` | subscriber badges (fails closed) |
+| OpenVibe.Tools | `tools.tool.run`, `tools.job.read` | sound uploads to MP3 (local ffmpeg is the fallback) |
## Depends on
## Depends on
@@ -452,6 +467,41 @@ Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat
@@ -452,6 +467,41 @@ Events: `chat.message.created`, `chat.message.deleted`, `chat.dm.created`, `chat
- a paid TTS request is never duplicated by a retry — *forwarded writes are applied once per idempotency key; paid TTS does not exist yet*
- a paid TTS request is never duplicated by a retry — *forwarded writes are applied once per idempotency key; paid TTS does not exist yet*
- after a reconnect, deleted and blocked state converge; browser parity (join, send, DM, `/tts`, moderation, popout) — *`scripts/parity.js` and `test/parity.test.js` (`docs/parity.md`): a reader that was away converges on what a connected reader saw (cursor reads carry `deleted_ids`); gaps: sub-only mode does not exist, public chat does not apply blocks*
- after a reconnect, deleted and blocked state converge; browser parity (join, send, DM, `/tts`, moderation, popout) — *`scripts/parity.js` and `test/parity.test.js` (`docs/parity.md`): a reader that was away converges on what a connected reader saw (cursor reads carry `deleted_ids`); gaps: sub-only mode does not exist, public chat does not apply blocks*
+## Security
+
+Reporting a vulnerability: [SECURITY.md](SECURITY.md). The rules the code keeps:
+
+- **Auth.** People sign in with a Network session JWT, verified here with the Network's key (tokens
+ issued before a subject's `token_valid_after` are refused), or an `hbt_` API token resolved through
+ Live; `?token=` on `/ws/chat` is deprecated. Services use client-credentials tokens for audience
+ `openvibe.chat`, checked per capability (`chat.live_bridge.write`, `chat.message.send`,
+ `chat.presence.read`). Staff gates ask the contracts staff map.
+- **Private data.** DMs are delivered only to participants, and private rooms only to members
+ (`test/security-crawl.js` walks every route); network blocks count like DM blocks; a staff member
+ reading someone else's chat logs is recorded as a moderation action; account export and deletion
+ follow Network's events.
+- **Network exposure.** `/internal/*` and `/metrics` answer 404 through nginx, which sets the client
+ address from the connection only; WS upgrades check the origin and IP bans.
+- **Egress.** Chat calls its configured Network, Live, Events, VIP and Tools hosts; the soundboard
+ import fetches only 101soundboards' own addresses, checked on every DNS answer.
+- **Secrets.** `OV_OAUTH_CLIENT_SECRET` and `CHAT_EVENTS_SECRET` live in `/etc/openvibe/chat.env` (0600),
+ by name only.
+
+## Deploy
+
+Production deploys with `sudo ovhost deploy chat` on the host (strategy `git-checkout`: fetch,
+fast-forward `/opt/openvibe.chat`, install on a lockfile change, restart, wait for `/ready`).
+The unit is `openvibe-chat.service` on `127.0.0.1:4400`, the env file `/etc/openvibe/chat.env`. Readiness is
+`/ready` (not `/api/ready`). nginx: [deploy/nginx/openvibe.chat.conf](deploy/nginx/openvibe.chat.conf)
+for openvibe.chat and [deploy/nginx/openvibe.live-chat.locations.conf](deploy/nginx/openvibe.live-chat.locations.conf),
+included in openvibe.live's vhost, for Live's chat paths. After a deploy, record the N-1 fixtures
+(`npm run n-1:record`). Switching chat back to Live is in `docs/cutover.md` (with
+`scripts/mirror-flush.js`).
+
+Rollback: ovhost puts the previous sha back by itself when `/ready` does not answer 2xx after the
+restart; afterwards `sudo ovhost rollback chat --to <sha>`. Nothing blocks a rollback: the schema
+code only adds tables and columns.
+
## Launch rule
## Launch rule
This repository does not make the product real, and the domain keeps its placeholder page on
This repository does not make the product real, and the domain keeps its placeholder page on
@@ -468,7 +518,8 @@ following exist here (plan §12.12):
@@ -468,7 +518,8 @@ following exist here (plan §12.12):
The launch release removes the domain from `OpenVibe.Sites/sites.json`, switches routing and
The launch release removes the domain from `OpenVibe.Sites/sites.json`, switches routing and
registers maturity in the ecosystem registry atomically. A placeholder is never counted as an
registers maturity in the ecosystem registry atomically. A placeholder is never counted as an
-implemented service.
+implemented service. `openvibe.chat` launched on 2026-09-24 (global chat, messages, settings): it
+left OpenVibe.Sites, and this repository's vhost serves it.
---
---
@@ -6,18 +6,44 @@
@@ -6,18 +6,44 @@
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"runtime": "node 22, express, ws, better-sqlite3",
"runtime": "node 22, express, ws, better-sqlite3",
"port": 4400,
"port": 4400,
- "domain": "openvibe.live (/ws/chat, /api/chat/, /api/dm/, /api/tts/, /api/sounds via an nginx include in openvibe.live's vhost); openvibe.chat is still the OpenVibe.Sites placeholder",
- "contracts": "openvibe-contracts v0.33.0",
+ "domain": "openvibe.chat (Chat's own site: global chat, messages, rooms, settings; the service manifest records it live since 2026-09-24) and openvibe.live (/ws/chat, /api/chat/, /api/dm/, /api/tts/, /api/sounds via an nginx include in openvibe.live's vhost)",
+ "contracts": "openvibe-contracts v0.71.0",
"capabilities": ["chat.live_bridge.write", "chat.message.send", "chat.presence.read"],
"capabilities": ["chat.live_bridge.write", "chat.message.send", "chat.presence.read"],
- "capabilitiesUsed": ["live.chat_context.read", "live.chat_effects.write", "live.chat_mirror.write", "events.event.publish", "events.subscription.manage", "vip.entitlement.check", "network.modules.read", "network.modules.write"],
+ "capabilitiesUsed": [
+ "live.chat_context.read",
+ "live.chat_effects.write",
+ "live.chat_mirror.write",
+ "events.event.publish",
+ "events.subscription.manage",
+ "vip.entitlement.check",
+ "network.modules.read",
+ "network.modules.write",
+ "tools.tool.run",
+ "tools.job.read"
+ ],
"capabilitiesRegistered": true,
"capabilitiesRegistered": true,
- "events": ["chat.message.created", "chat.message.deleted", "chat.dm.created", "chat.moderation.action"],
- "eventsConsumed": "live.release.deployed (the deploy card, folded by subject.id with the bridge's deployNotice: one card per head whichever comes first; register C-84) and network.module.updated (drops a cached chat.preferences copy), POST /internal/events, signature v2, openvibe-sdk inbox; subscriptions created at boot. In code only, not deployed; needs CHAT_EVENTS_SECRET in chat.env and the Network grant chat events.subscription.manage openvibe.events",
+ "events": ["chat.message.created", "chat.message.deleted", "chat.dm.created", "chat.moderation.action", "chat.room.message.created", "chat.room.message.deleted"],
+ "eventsConsumed": "live.release.deployed, network.module.updated, network.user.token_valid_after, vip.membership.changed, network.block.changed, network.subject.merged, network.account.export_requested and network.account.deleted at POST /internal/events (signature v2, openvibe-sdk inbox); subscriptions created at boot when missing (CHAT_EVENTS_SECRET and the Network grant chat events.subscription.manage openvibe.events)",
"liveAuthorityFlag": "CHAT_AUTHORITY=chat is set in production live.env since the cutover (2026-09-23 02:03 UTC); Live's chat tables are a read mirror Chat keeps current",
"liveAuthorityFlag": "CHAT_AUTHORITY=chat is set in production live.env since the cutover (2026-09-23 02:03 UTC); Live's chat tables are a read mirror Chat keeps current",
- "vip": "Member badges from OpenVibe.VIP (server/vip/badges.js: entitlements/check with product chat, cached 60 s, never blocks sending, fails closed). In code only, not deployed; needs the Network grant chat vip.entitlement.check openvibe.vip and Live's chat UI to render vip_badge / chat_vip_badge",
- "preferences": "Chat preferences in the Network user module chat.preferences (server/prefs/: GET/PUT /api/chat/preferences with Chat's service token, cached 60 s, If-Match on every write; scripts/migrate-chat-preferences.js moves the choices in Live's user_preferences). In code only, not deployed; needs Network with the chat.preferences handoff and the grants chat network.modules.read/write on chat.preferences, then the migration, then Live's chat.js calling /api/chat/preferences",
- "calls": "Live's call server, call routes and stream hooks ported to server/calls/ with a calls lifecycle table (WS-I task 1). In code only, off (CHAT_CALLS unset); the switch is CHAT_CALLS=1, Live CALLS_AUTHORITY=chat and the nginx include deploy/nginx/calls/openvibe.live-calls.locations.conf (docs/calls-cutover.md)",
+ "vip": "Member badges from OpenVibe.VIP (server/vip/badges.js: entitlements/check with product chat, cached 60 s, never blocks sending, fails closed; vip.membership.changed drops the cache). Needs the Network grant chat vip.entitlement.check openvibe.vip",
+ "preferences": "Chat preferences in the Network user module chat.preferences, plus chat.tts_defaults, chat.dm_settings and chat.presence_prefs (server/prefs/: /api/chat/preferences and siblings with Chat's service token, cached 60 s, If-Match on every write; scripts/migrate-chat-preferences.js moves the choices in Live's user_preferences). Needs the grants chat network.modules.read/write",
+ "calls": "Live's call server, call routes and stream hooks ported to server/calls/ with a calls lifecycle table (WS-I task 1). Off unless CHAT_CALLS=1; the switch is CHAT_CALLS=1, Live CALLS_AUTHORITY=chat and the nginx include deploy/nginx/calls/openvibe.live-calls.locations.conf (docs/calls-cutover.md)",
"deployed": true,
"deployed": true,
- "deployment": "openvibe-ovh /opt/openvibe.chat, unit openvibe-chat, 127.0.0.1:4400 (loopback); public only through openvibe.live's nginx include for the chat paths; release 45f2b1f; EVENTS_URL set (chat.message.created reaches OpenVibe.Events); restore drill passed 2026-09-23",
- "updated": "2026-09-23"
+ "deployment": "Deployed with `sudo ovhost deploy chat`: /opt/openvibe.chat, unit openvibe-chat, 127.0.0.1:4400 (loopback); public through the openvibe.chat vhost and openvibe.live's nginx include for the chat paths; EVENTS_URL set (chat.message.created reaches OpenVibe.Events); restore drill passed 2026-09-23",
+ "updated": "2026-09-28",
+ "features": [
+ "Live's global, stream and channel chat (authority since 2026-09-23, Live keeps a read mirror)",
+ "DMs and group DMs, participants only",
+ "rooms: public and private, roles, invitations, slow mode, unread counts",
+ "moderation: bans, timeouts, purges, filters, slow, sub-only and member-only modes, audited log access",
+ "TTS, sounds and soundboard with persisted queues",
+ "calls ported from Live (off until the calls cutover)",
+ "openvibe.chat site: global chat, messages, rooms, settings, history download",
+ "chat preferences in Network user modules",
+ "VIP subscriber badges",
+ "network blocks, revocation, account merge, export and deletion from Network events",
+ "outbox events and chat.room.message.* on the realtime plane",
+ "N-1 compatibility tests",
+ "per-actor limits (openvibe-sdk/limits)"
+ ]
}
}