Skip to content
-
Broadcast workspace: End stream calls DELETE /api/streams/:id, the route that ends a stream (owner or staff). It posted to /api/streams/:id/end, which no route serves, so the button answered 'Failed to end stream' with a 404. Found by the N-1 recorder (WS-P task 11).OpenVibers · 26 Sept 2026
5caa46d5
-
N-1 harness, the version Chat, Media and Community share (roadmap WS-P task 11): test/n-1/harness.js, scripts/n-1-record.js and test/n-1.test.js are now the same file in all four repositories; only test/n-1/service.js (clients, boot, seed, samples) differs. Added for the other services and used here: pages an open tab holds are crawled at record time (Live: the shell and /@n1star, 63 more requests: every hashed script and stylesheet, links and forms, which the next release must still answer); paths built by concatenation or from a variable ('/api/x/' + id, base + '/y'); SDK-style call({ method, path }) sites; <form> actions; seeded ids that differ per run ({@name} slots); a JSON catch-all 404 counts as "the route is gone"; /ws/* sessions (sent message types from the client code, the replies' types and read fields), used by Chat; redirects compared without their query. Fixtures re-recorded from 8caa540, the release in production: 478 requests, 964 statements. docs/deploy.mdOpenVibers · 26 Sept 2026
2ec0dc2a
-
N-1 tests (roadmap WS-P task 11): the previous release's client against this server, and its SQL against this schema. test/n-1.test.js boots this checkout in the drill sandbox (writes let through by test/n-1/preload.js) on a database created from the previous release's schema, migration ledger and first-use tables, so this release's migrations run over it; then it replays test/fixtures/n-1/client.json inside openvibe-shared's mixed-version matrix (release-compat assertMixedVersion): 411 requests the previous client makes (its api/fetch call sites, found statically, with seeded values; every call anonymously, reads signed in), each answered compatibly (any 2xx for a 2xx, the same status otherwise, JSON where there was JSON, every response field the old client names still there with a type it had). Then every statement in test/fixtures/n-1/worker.json (961: what that release ran, plus its SQL literals that prepare on its own schema) must still prepare on the migrated schema, and no old INSERT may miss a new NOT NULL column without a default. Fixtures recorded from 8caa540, the release in production; refresh after each deploy with `npm run n-1:record [ref]` (scripts/n-1-record.js: a temporary worktree of the release, seeded, booted and replayed). Runs in npm test, so in CI, in about 6 s, with no git history or network. Checked by breaking it: a dropped serializer field, a dropped column and a table rebuilt with a new required column each fail it. docs/deploy.mdOpenVibers · 26 Sept 2026
dad5cad2
-
Pins: openvibe-shared 1.20.0 -> 1.22.0 (realtime notification badge, off until a site turns it on; the unreachable-host browser check)OpenVibers · 26 Sept 2026
8caa5404
-
GOLIVE_NOTIFY=events (compatibility register C-85): leave go-live notifications to Network's live.stream.started consumer. While Live's events outbox publishes, a go-live then makes neither the direct POST /internal/events/stream-live nor the fallback push, and logs that it left it to the consumer; unset (the default), any other value, or with the outbox off, the direct call stays. Why: while both paths run, the direct call claims Network's per-streamer window first at every real go-live (production 2026-09-24: 'Unified event sent' for streams 2478, 2479 and 2481, the consumer's delivery a second later), so the consumer can never show the notified outcome C-85 waits for. Rollback: unset it. test/golive-notify-mode.test.jsOpenVibers · 26 Sept 2026
e96383be
-
Performance audit: the 2026-09-26 measurement after the release-client work (WS-T task 2): the home page on production against the recorded baseline; release-watch adds one request and no measurable paint or blocking costOpenVibers · 26 Sept 2026
a13c2bdd
-
Open redirect fixed (roadmap WS-R task 5): Live's sign-in next let "/<TAB>/evil.com" and "/\evil.com" through (browsers read both as "//evil.com") and trusted openvibe.<any tld>, which anyone can register. safeNext moves to server/auth/safe-next.js: control characters and backslashes go home, only the zones OpenVibe owns (Network's sso-owned list; never a Host tenant subdomain), no credentials in the URL. test/open-redirect.test.jsOpenVibers · 26 Sept 2026
c4e17617
-
Pins: openvibe-shared 1.19.0 -> 1.20.0 (the update matrix and release manifest 1.2.0: client generations, the shell)OpenVibers · 26 Sept 2026
d1fcb692
-
Socket activation that stays in effect, on loopback: the release layout's socket unit still listened on 0.0.0.0:3000 with NonBlocking= in [Socket] (ignored by systemd); installing it on 2026-09-25 dropped the socket's descriptor, so the service bound 0.0.0.0:3000 itself: Live answered on the public IP past Cloudflare and nginx, and each restart refused connections (four 502s in the WS-P task 3 drain probe). Both unit copies are now the loopback one, NonBlocking= moved to the service drop-in; deploy.sh checks that systemd really holds the listener (not just is-active) and rebinds a changed or dropped socket (stop, restart socket, start); without LISTEN_FDS the process binds 127.0.0.1 in production (LISTEN_HOST overrides; HOST still builds URLs). test/systemd-units.test.js. Production was repaired by hand first (systemd holds 127.0.0.1:3000, the public port is closed)OpenVibers · 26 Sept 2026
ab8abff6
-
Pins: openvibe-shared 1.18.0 -> 1.19.0 (the update matrix: ov:content-dispose before a region is replaced)OpenVibers · 26 Sept 2026
53c9abd7
-
Live users -> subject projection, the rest (roadmap WS-B task 2 steps 2, 4 prep and 5): Live no longer reads users.email or users.password_hash, POST /internal/user-role is retired, and the contract step is an operator scriptOpenVibers · 26 Sept 2026
3a99cdc3
-
Pins: openvibe-shared 1.17.1 -> 1.18.0 (update telemetry: prompted count, sessions by generation)OpenVibers · 26 Sept 2026
af826304
-
Pins: openvibe-shared 1.16.1 -> 1.17.1 (release notifications)OpenVibers · 26 Sept 2026
f2b8508b
-
Release notification: the event ovhost announce publishes is host.release.published (its own type in openvibe-contracts 0.58.0; host.deploy.activated stays tenant hosting's), in the deploy script's comment and the docs. Comments only (WS-P task 9)OpenVibers · 26 Sept 2026
cd67c661
-
Release notification after a deploy (roadmap WS-P task 9): deploy.sh runs `ovhost announce live` once the release went liveOpenVibers · 26 Sept 2026
5162b094
-
Chat parity gaps, Live's side (roadmap WS-I task 6): the subscriber read for sub-only chat, sub_only as a channel setting, the dashboard's slow mode actually saved, a dashboard delete reaching the whole channel roomOpenVibers · 26 Sept 2026
d4e849f2
-
Chat parity follow-ups on Live (WS-I task 6): bans end at expires_at read as a UTC instant (datetime()), not text, so a timeout given as ISO no longer lasts until midnight UTC on Live's other surfaces; the floating chat widget applies the deleted_ids Chat returns with cursor reads, so what was deleted while it was away disappearsOpenVibers · 26 Sept 2026
0df56625
-
Home shell: no own <script> for /shared/ov-mark.js; the shared navbar loads it (the browser check counted it twice on every route); kiosk, tos, privacy and dmca have no navbar and keep theirsOpenVibers · 26 Sept 2026
00c9457a
-
The OV mark comes from openvibe-shared (/shared/ov-mark.js, 1.16.1: it stops animating when idle, hidden or off-screen) on the home, kiosk, tos, privacy and dmca pages; Live's older copy (public/js/ov-mark.js), which kept the shared one from loading, is goneOpenVibers · 26 Sept 2026
953e4b9e
-
Pins: openvibe-shared 1.16.0 -> 1.16.1 (the OV mark stops animating when idle, hidden or off-screen)OpenVibers · 26 Sept 2026
2514d149
-
CSP: connect-src allows https://cloudflareinsights.com, where Cloudflare Web Analytics' beacon reports (its script, static.cloudflareinsights.com, was already allowed in script-src and, by mistake, in connect-src). The beacon sends on page hide, so the browser check never saw the block; the other sites get the same two hosts (WS-Q task 3)OpenVibers · 26 Sept 2026
22d388a4
-
Clip page: a missing source VOD is absent, not a 404 (browser check on /clip/369, WS-Q task 3). GET /api/clips/:id says vod_visible: false when the clip's VOD is gone (Media 404) or hidden from this viewer, which is exactly when GET /api/vods/:id/context answers 404; the "From this stream" card (public/js/context-cards.js) then makes no request and keeps the plain text fallback. Unknown (Media unreachable) leaves it unset and the card asks as before. Tests: media-privacy (vod_visible for public, hidden and deleted source VODs), clip-source-cardOpenVibers · 26 Sept 2026
448f2125
-
A guest's session check answers 200, not 401 (browser check, WS-Q task 3): POST /api/auth/refresh without an ov_refresh cookie answers { access_token: null, user: null }. Every guest page view asks it (public/js/app.js tryRefreshToken, which reads a session only from access_token), and the 401 logged a console error on each. A refresh cookie that is present but rejected by the Network still answers 401 and is cleared. test/auth-refresh-guest.test.jsOpenVibers · 26 Sept 2026
73588d93
-
Pins: openvibe-shared 1.14.0 -> 1.16.0OpenVibers · 26 Sept 2026
834d9d4b
-
Found by the browser check on /vod/… and /clip/… (Host scripts/browser-check.js, WS-Q task 3): the VOD, clip and channel players' volume sliders are named ("Volume"; axe label, critical), and a guest's page no longer asks /api/coins/channel-balance, which answers 401 to a guest (a console error on every channel, VOD and clip page): the navbar points chip and the rewards panel ask only when signed in. test/player-a11y.test.jsOpenVibers · 26 Sept 2026
fcfc0d5c
-
What the browser check found on Live (Host scripts/browser-check.js, WS-Q task 3): /chat and /search are server-rendered with their own title and canonical (/search?q=… names /search and stays noindex; its meta existed but the route was missing from SEO_ROUTE_RE, so the shell answered with no canonical); the home page's JSON-LD is one ItemList per snapshot section, named by its visible heading (Live now, Recent VODs, Recent clips) instead of "Live & recent on OpenVibe.Live", which no page showed; the docs pages get a canonical URL, an icon that exists (/assets/logo.svg; /assets/favicon.ico 404ed on every docs visit) and keyboard access to code blocks that scroll (tabindex, focus ring; axe scrollable-region-focusable). Tests: seo-ssr, docs-renderOpenVibers · 26 Sept 2026
934156bb
-
Loyalty summary (WS-K task 9): Live writes its private live.loyalty user module on Network: channel points across channels and the top ten by points, the Arena Trash Level and XP (loyalty, never money; contracts 0.56.0). Viewers with points get it without streaming; points change while people watch, so at most one write per half hour except the daily refresh; the scan picks up changed points and Arena XP; a record whose points are gone is zeroed, not left stale. Pins: openvibe-contracts 0.52.0 -> 0.56.0OpenVibers · 26 Sept 2026
bf068778
-
Staged chat tables move to OpenVibe.Chat one table at a time (WS-I task 2, register C-04): server/chat/chat-tables.js reads who writes channel_moderators, channel_moderation_settings, emotes, user_tags, chat_ai_summaries and chat_timeline_events from app_state chat_table_authority (every table 'live' by default, always 'live' without CHAT_AUTHORITY=chat), and every Live writer goes through its write(): the dashboard's moderators and settings, /slow and alert sounds, emote upload/edit/delete and the Media asset-sync, chat-AI summaries and timeline (test/chat-tables-writers.test.js keeps it so; user_tags has no writer). At 'live' Live writes its own table and TEMP-trigger capture relays every change to Chat's copy (chat_staged_outbox, bridge op stagedApply; POST /internal/chat-tables/relay pauses it for an import); a per-table dual read compares Live's reads with Chat's copy in the background and counts matched/mismatched/inconclusive in chat_dual_read_stats, never changing an answer. POST /internal/chat-tables/:table (X-Internal-Key) hands a table over, its writers waiting: Live's queue drained, Chat takes it, Live stops writing; back: Chat's mirror drained first, then Live writes again (force for Chat down); GET /internal/chat-tables shows both sides. At 'chat' Live's writers call Chat over the bridge (awaited, idempotency key) and apply Chat's rows to Live's copy, which is then the read mirror (applyMirror takes staged rows only for a table Chat writes). Nothing starts under LIVE_DRILL or without CHAT_AUTHORITY=chat; no schema change beyond two new tables. The emote upload's 409 path no longer throws inside its catch. Runbook: OpenVibe.Chat docs/staged-tables-cutover.mdOpenVibers · 26 Sept 2026
d6480da6
-
Search suggestions: one per type and title (many VODs share a title), the best-rankedOpenVibers · 26 Sept 2026
fbc78464
-
Search facets and autocomplete (WS-O task 10): /search shows the first page's category and channel facets with counts and narrows to one (?category=&channel=, a new query starts without them); the box suggests titles as you type (GET /api/search/suggest → OpenVibe.Search /api/v1/suggest, Live's types only, never an error; an ARIA combobox: arrows, Enter opens, Escape closes)OpenVibers · 26 Sept 2026
fe1fdf91
More commits