Skip to content
-
Network-token auth in Chat (WS-I task 3): a Network session JWT is verified here with the Network's key and resolved through the ctx_users projection by subject (new index), carrying the token's staff_caps and a role that only ever raises the projection's, so signed-in people keep chatting while Live is down. Live is asked only for hbt_ tokens, non-JWTs, a key we do not hold and subjects the projection cannot place (first visits create the account there). test/network-session.test.jsOpenVibers · 24 Sept 2026
3ebc5a1
-
One W3C trace across services (Track O): openvibe-shared v1.7.0 trace.install(app) keeps each request's traceparent and puts it on the calls made while serving it, to loopback and OpenVibe hosts only; Chat also takes the request context from openvibe-contracts http.middleware()OpenVibers · 24 Sept 2026
325f878
-
CI calls the shared test workflow (Track Q): OpenVibe.Shared test.yml@e8b0caf (install, node --check, npm test, openvibe-contracts-check; ffmpeg where the tests need it) instead of a copy of those stepsOpenVibers · 24 Sept 2026
6d86dd4
-
VIP client from openvibe-sdk/vip (v0.7.0): the copy of openvibe-vip/client is replaced by the SDK's published seam, same API and fail-closed behaviour; server/vip/vip-client.js re-exports it so callers are unchangedOpenVibers · 24 Sept 2026
4e95c11
-
VIP convergence (W10): Chat subscribes to vip.membership.changed; a delivery from VIP drops that member's cached subscriber-badge answers for the creator at once (vip/badges handleEvent) instead of converging by the cache TTL; any other source is ignoredOpenVibers · 24 Sept 2026
fba087a
-
Release manifest and metrics (Track R D43, Track O): openvibe-shared v1.6.0; GET /release.json (release, contracts and package versions) with POST /release-metrics, and GET /metrics (loopback only: request rates and latencies, process metrics, release_info) mounted before every routeOpenVibers · 24 Sept 2026
9ebde51
-
Staff gates ask the contracts staff map (D05, ADR-022): permissions.can(user, 'staff.<area>.<action>') over openvibe-contracts v0.35.0 (issued staff_caps claims win); per-IP and ban exemptions are staff.limits.exempt, chat-restriction bypass staff.moderation.bypass, purge/export/deleted-message views staff.moderation.purge, sound management staff.assets.manage, and the moderation/log helpers answer through the map. Same answers as before for every role; the one rank check left compares the target. test/staff-capabilities.test.jsOpenVibers · 24 Sept 2026
990fbd1
-
Sound uploads convert through OpenVibe.Tools (platform S9): the mp3 tool's run API via openvibe-sdk/tools (v0.6.0) with Chat's service token (tools.tool.run, tools.job.read), 128 kbps 44.1 kHz stereo, the result downloaded from the jobs facade; local ffmpeg whenever Tools is down, busy or refuses (CHAT_TOOLS_AUDIO=off skips it). test/tools-audio.test.jsOpenVibers · 24 Sept 2026
1d0e12a
-
SECURITY.md: how to report a vulnerability ([email protected], 7-day reply, scope, supported versions)OpenVibers · 24 Sept 2026
1ef6f99
-
A chat line that could not be saved is not broadcast: the sender gets an error and nobody sees a message that history, moderation and replays never have (the insert failure used to be swallowed as non-critical). ws-protocol testOpenVibers · 24 Sept 2026
d268cf8
-
openvibe-contracts v0.33.0OpenVibers · 23 Sept 2026
fcc824a
-
openvibe-contracts v0.32.0: chat.message.send is chat's own capability, checked with a literal idOpenVibers · 23 Sept 2026
4abf0fa
-
Events consumer (compatibility register C-84): Chat subscribes to live.release.deployed and network.module.updated and receives them at POST /internal/events (server/events/consumer.js). live.release.deployed makes the deploy card exactly as the bridge op deployNotice does (same fold: newest row in any room is a deploy card under 3 hours old; same broadcast passes and late-joiner replay), keyed by subject.id, the head commit. Both paths claim the head in the new deploy_releases table in the transaction that stores or folds the card, so while Live sends both the same head is one card whichever arrives first; the second only records bridge_at / event_at. The bridge's head is its first commit (Live sends them newest first). A retried bridge op, a redelivered event and Live re-announcing after a crash are the same card; a redeploy of an already announced head (a rollback) says nothing; a release event older than 6 hours (an operator replay) is ignored:stale. The bridge call keeps working. network.module.updated for chat.preferences goes to prefs.handleEvent(): a newer revision drops the cached copy at once instead of within CHAT_PREFS_TTL_MS, an older or equal one and other namespaces change nothing (and are not recorded). Exactly once: the openvibe-sdk inbox (chat_event_inbox, pruned after 35 days) claims (chat, event_id) in the same transaction as the change; broadcasts run after the commit; a failure is 500 and Events retries. Signature v2 only (parseDelivery requireV2, ±300 s) under CHAT_EVENTS_SECRET (comma list for rotation, 32+ characters each): bad, stale, v1-only or unsigned is 401, no secret 503, a forwarded request 403. Subscriptions are created at boot when missing (server/events/subscriptions.js: list, then create, 409 = exists; retried in the background at 10 s, 1, 5 and 15 min), an existing one is left as it is even when disabled; CHAT_EVENTS_SUBSCRIBE=0 turns it off, CHAT_EVENTS_ENDPOINT overrides http://127.0.0.1:<PORT>/internal/events. scripts/subscribe-events.js --dry-run | --disable | --enable. Needs the Network grant chat events.subscription.manage openvibe.events. /ready reports the consumer's counters under events.consumer. Adds openvibe-sdk v0.5.0. test/events-consumer.test.js: signature checks, the inbox, bridge-then-event and event-then-bridge for one head, folding and a stream message starting a new card across both paths, release validation and staleness, the preferences cache with older revisions ignored, idempotent boot subscriptions against a stub Events, inbox pruning. README (Events: Consumed), .env.example, STATUS.jsonOpenVibers · 23 Sept 2026
ed90461
-
Chat preferences move to the OpenVibe.Network user module chat.preferences (roadmap Wave 1 item 24; Chat owns the namespace since the Wave 6 cutover). GET /api/chat/preferences and PUT /api/chat/preferences { preferences } (a patch, null removes a field, optional If-Match) read and change the signed-in person's record through Network's /internal/modules/chat.preferences/:subject with Chat's service token (audience openvibe.network, network.modules.read + write; server/prefs/network-modules.js, one retry after a 401). server/prefs/chat-preferences.js: every write names the revision it read, a revision that moved is read again and the patch re-applied (3 tries), a browser If-Match is strict (412), a patch that changes nothing writes nothing, values are checked against the namespace schema (openvibe-contracts modules.validateData) before Network sees them. Cache per person for CHAT_PREFS_TTL_MS (60 s): Chat's own writes land in it, a change made through Network directly shows within the TTL, and handleEvent() drops an entry at once for a newer network.module.updated (for when Events deliveries reach Chat); Network down serves the cached copy (stale: true) or 503. API tokens read only; no Network subject is 409 prefs.subject_unknown. scripts/migrate-chat-preferences.js (server/prefs/from-live.js) moves what Live kept in user_preferences.chat_settings: only choices (showTimestamps -> timestamps, compactMode -> compact, fontSize small/large -> font_scale 0.88/1.18, showBadges false -> show_badges), the subject from Live's linked_accounts (the network link first), Live's database opened read-only, writes through Network only and create-only (If-Match 0) so an existing record is never overwritten and a re-run creates nothing. Dry run by default; --apply requires --backup <new file>, written 0600 and read back before any write, then given each creation's revision; --rollback <file> [--apply] deletes what that run created, keeping records changed since. test/helpers.js: the stub Network serves user modules with Network's revision and If-Match rules. Tests: test/preferences.test.js, test/migrate-preferences.test.js. README (Chat preferences), STATUS.json, .env.example.OpenVibers · 23 Sept 2026
c645a53
-
Deploy notices: a new deploy folds into the last card only if nobody has spoken in ANY room since (the global feed shows stream messages too, so cards kept folding past them and their time ranges ran past the messages below), and only within 3 hoursOpenVibers · 23 Sept 2026
7897688
-
VIP member badges: a member's messages in a creator's room carry the creator's VIP badge (a perk of their plan version bound to `chat badge`), resolved through OpenVibe.VIP's entitlement check (product chat) behind the shared product cacheOpenVibers · 23 Sept 2026
d02a73c
-
CI: run the shared security workflow (gitleaks secret scan + dependency audit, Track Q)OpenVibers · 23 Sept 2026
9e0563a
-
Persisted TTS and sound queue: every TTS utterance, channel !sound and 101soundboards clip is a row of audio_requests (server/chat/audio-queue.js) played one at a time per room, queued -> playing -> played, or skipped / failed. The audio is made when its turn comes and paced by the clip's length (WAV header, MP3 frame bitrate, or the sound's stored duration), so skip and clear take effect for everything not yet delivered. The broadcaster and moderators control it with /skiptts [id] and /cleartts (logged as tts_skip / tts_clear) and GET /api/tts/queue, POST /api/tts/queue/skip, /clear and /:id/report (the playing client's played / failed). Synthesis errors, missing clips and repeated crashes are recorded as failed and the queue moves on. A keyed request (the TTS of message m<id>) is queued once per room, replacing the 30 s in-memory dedupe, and the per-user limit (tts_max_queue_per_user) now holds. A restart keeps the queue: rows that were playing are finished, rows older than 5 minutes expire, and the rest play once the room has listeners again (a second after a socket rejoins, 8 s at most). Clients get the same tts-audio / soundboard-audio frames plus request_id, and two new frames they may ignore: audio-skip and audio-clear. test/audio-queue.test.js covers the state machine, pacing, permissions, failures, dedupe and a real SIGTERM restartOpenVibers · 23 Sept 2026
bf88760
-
Chat restart and cursor resume: test/restart-resume.test.js runs Chat as its own process, restarts it with SIGTERM on the same database, and proves that stream, global and channel readers that reconnect and read after_id=<last cursor> end up with exactly the room's rows: nothing written while they were away (by people or through Live's bridge, before or after the restart) is missing, nothing at or under the cursor comes back, and ids keep increasing. It exposed a duplicate: Live's placeholder-id map lived only in memory, so a broadcast whose insert the old process had acknowledged reached browsers with the negative placeholder instead of the row id, and a reader showed the row twice (frame and history). The map is now also kept in bridge_refs (a day; written in the insert's transaction when keyed), and a lookup falls back to it. Test helpers: h.detach, h.spawnChat, h.stopChatOpenVibers · 23 Sept 2026
49a5011
-
Enforce chat.message.send on the service API: an /internal/live/calls op that sends a chat message (a saveChatMessage write, the deploy notice, or a pushed chat/dm frame through any broadcast op or sendDm) needs chat.message.send in the caller's service or app token beside chat.live_bridge.write. Without it that op alone is refused (capability.denied, nothing persisted, no event, not marked applied) and the rest of the batch runs, so Live's queue is not blocked. Other frames (system notices, call invites), TTS, sounds, moderation writes and invalidations need only the bridge capability. Contracts still lists chat.message.send as owned by live, so the id is held in a constant the contracts check does not scan; it needs re-owning to chat. Network must grant live chat.message.send openvibe.chat before this deploys (docs/cutover.md). Denial test for a service and an app principal in test/bridge.test.jsOpenVibers · 23 Sept 2026
791cd3d
-
chat.message.deleted: every delete of public-room messages (one message by a moderator or through Live's bridge, a user's / anon's / relay user's history from self-delete or /api/mod, a time-range purge, the auto-delete sweep) adds a public chat.message.deleted to the outbox in the same transaction, one per 500 ids, carrying only message_ids (never the text, the author or who deleted it) and payload.redacts { subject_type: chat_message, subject_ids }, so OpenVibe.Events turns the stored chat.message.created into a tombstone on every read path. Return values of the delete functions are unchanged. test/message-deleted.test.js covers every path, chunking and rollback, and, with a sibling OpenVibe.Events checkout, the relay end to end: anonymous, signed-in and service SSE replay and pull return the tombstone at an unchanged seq, and only svc:chat can redact Chat's eventsOpenVibers · 23 Sept 2026
4cc1cbe
-
Docs: STATUS.json and README match production (2026-09-23)OpenVibers · 23 Sept 2026
4dc7b87
-
/ready tells the truth: a real chat.db read (required) and the last successful Live sync (optional)OpenVibers · 23 Sept 2026
45f2b1f
-
Credentialed CORS for exact origins only: the *.openvibe.tools suffix rule inherited from Live gave any tools subdomain credentialed access to a signed-in person's DMs and chat, and no tools satellite embeds chat. The list is Live's exact origins (BASE_URL + www, the Network, openvibe.games, openvibe.tools) plus ALLOWED_ORIGINS, the same list the WebSocket upgrade already usedOpenVibers · 23 Sept 2026
766ee35
-
nginx: client address headers only from $remote_addr (realip). X-Forwarded-For was appended to and CF-Connecting-IP passed through from the client, so a request reaching the origin without Cloudflare (DNS-only host or the bare IP) chose the address the service bans and rate-limits byOpenVibers · 23 Sept 2026
f16fe6c
-
Chat protocol security fixes: channel-room bans, room escape, rule bypasses, client address, regex budgetOpenVibers · 23 Sept 2026
9cdea20
-
emotes.media_url and media_asset_id (Live's Media asset sync), added to existing databases on bootOpenVibers · 23 Sept 2026
55010a5
-
openvibe-contracts v0.13.0 (chat capabilities and manifest released); contracts check is blockingOpenVibers · 23 Sept 2026
b87ea39
-
Cutover kit: Live patch (CHAT_AUTHORITY=chat), runbook, capability proposals, ops filesOpenVibers · 23 Sept 2026
547e2f9
-
Chat service: Live's chat behind a service boundary (roadmap Wave 6)OpenVibers · 23 Sept 2026
abf1e4b
More commits