{"id":"pst_01M3PPVCYTGPEZE8Q8V13J58CN","url":"https://openvibe.blog/@openvibe/patch-notes-42-changes-across-14-sites","blog":{"id":"blg_01M362MF0EDJ7QHQTRD8A3Q981","handle":"openvibe","title":"The OpenVibe blog","url":"https://openvibe.blog/"},"title":"Patch notes: 42 changes across 14 sites","summary":"What shipped on OpenVibe on 2026-09-29: 42 changes to OpenVibe.Live, OpenVibe.Media, OpenVibe.Games, OpenVibe.Codes, OpenVibe.Network, OpenVibe.Chat and 8 more.","body_markdown":"What shipped on OpenVibe on 2026-09-29: 42 changes to OpenVibe.Live, OpenVibe.Media, OpenVibe.Games, OpenVibe.Codes, OpenVibe.Network, OpenVibe.Chat and 8 more. Every line below is a commit message from the OpenVibers repositories, linked to the change itself.\n\n## Highlights\n\n- **OpenVibe.Games:** M1 identity: the WebSocket authenticates at the upgrade, the editor key is gone, and the contracts pin is current (ADR-0007 decisions 8 and 12). ([`3ea36b3`](https://github.com/OpenVibers/OpenVibe.Games/commit/3ea36b36afeac29da30ac9d56a537d6e78581488))\n- **OpenVibe.Media:** scripts/retire-r2.js and its test are removed: R2 stays as Media's fast tier (owner, 2026-09-29), so a tool that empties it has no place here. It ran once (its report is on the host); promotion is back on and the sweep refills R2. The… ([`1535276`](https://github.com/OpenVibers/OpenVibe.Media/commit/1535276e3b4df3dfad432c165fd7cb23393229ac))\n- **OpenVibe.Games:** Physics conformance suite and an in-memory mock world (ADR-0007 M1 step 1): packages/physics/src/conformance.test.ts runs every seam case against MockPhysicsWorld and the Havok adapter (bodies, sweeps, joints, sleep and settle thresholds… ([`c24b7b1`](https://github.com/OpenVibers/OpenVibe.Games/commit/c24b7b1a288cbca745723e7d9c8918b6de0749e6))\n- **OpenVibe.Network:** Plan T2 deletions in Network (each proven uncalled across the estate first): the one-time scripts hash-refresh-tokens, follows-backfill and creator-analytics-backfill; the built-in fallback tool catalog (before Tools has answered, the… ([`f6fe857`](https://github.com/OpenVibers/OpenVibe.Network/commit/f6fe857099ef29b9eb4c9ddb1b5b2ee546b46bec))\n- **OpenVibe.Games:** Movement state hash and determinism harness (ADR-0007 M1 step 2): stateHash.ts hashes the quantised PlayerMoveState (FNV-1a 32-bit over a documented big-endian stream; 1e-4 m, 1e-3 m/s) and measures divergence against the 1 mm / 1 cm/s… ([`f328cfc`](https://github.com/OpenVibers/OpenVibe.Games/commit/f328cfc5e3787c3bd2af822d35eb52a98081aa9f))\n\n## OpenVibe.Live\n\n[openvibe.live](https://openvibe.live) · [repository](https://github.com/OpenVibers/OpenVibe.Live)\n\n- N-1 fixtures re-recorded from 1a28261, the release now in production (npm run n-1:record). ([`ee2ad94`](https://github.com/OpenVibers/OpenVibe.Live/commit/ee2ad948a4c25b9af9c27be16e731025afa6c2d3))\n- Internal routes take service tokens (plan T2, X-Internal-Key retirement, step 1 of the sweep): /internal/user-avatar (live.avatar.write), /internal/url-registry/refresh (live.url_registry.refresh), /internal/analytics-summary… ([`660833d`](https://github.com/OpenVibers/OpenVibe.Live/commit/660833de2aef557a4652d93aaea914c01d9496e0))\n- N-1 fixtures re-recorded from 660833d, the release now in production (npm run n-1:record). ([`f8880b1`](https://github.com/OpenVibers/OpenVibe.Live/commit/f8880b1f23f5756fdb214012fbda61eff9acb041))\n- Live never sends X-Internal-Key again (plan T2, step 2 of the sweep): every call to Network's internal API goes with Live's client-credentials service token, including the avatar report and mark-read-by-type now that Network guards them… ([`bea231e`](https://github.com/OpenVibers/OpenVibe.Live/commit/bea231e516fdcd470051eccf0d7ccdb230a734a3))\n- N-1 fixtures re-recorded from bea231e, the release now in production (npm run n-1:record). ([`71829e5`](https://github.com/OpenVibers/OpenVibe.Live/commit/71829e5e2103f5edbbdf5f0950d97c086fb13cc2))\n- X-Internal-Key is gone from Live (plan T2, step 3 of the sweep): every internal route takes only a Network service token with the capability it performs (live.avatar.write, live.url_registry.refresh, live.analytics.read… ([`66f590b`](https://github.com/OpenVibers/OpenVibe.Live/commit/66f590b7e5a80cfa13e153e57d3becea5f03dc67))\n- N-1 fixtures re-recorded from 66f590b, the release now in production (npm run n-1:record). ([`c56e9c4`](https://github.com/OpenVibers/OpenVibe.Live/commit/c56e9c498342baab621734d87b4bec353d47977d))\n- No floating promises left in Live (plan T0, the shared checker reports 0): the control socket awaits handleCommand so a rejection is caught and logged; the Kick and YouTube chat-relay connects stay fire-and-forget but log their rejections… ([`6e7ed60`](https://github.com/OpenVibers/OpenVibe.Live/commit/6e7ed605cbdcd7e39054e37bab11cbdc9c82e4f8))\n\n## OpenVibe.Media\n\n[openvibe.media](https://openvibe.media) · [repository](https://github.com/OpenVibers/OpenVibe.Media)\n\n- scripts/retire-r2.js and its test are removed: R2 stays as Media's fast tier (owner, 2026-09-29), so a tool that empties it has no place here. It ran once (its report is on the host); promotion is back on and the sweep refills R2. The… ([`1535276`](https://github.com/OpenVibers/OpenVibe.Media/commit/1535276e3b4df3dfad432c165fd7cb23393229ac))\n- docs/media-fabric.md: the accepted design for Media's storage and delivery (owner, 2026-09-29). Two fabrics (online: B2 canonical, R2 Standard hot, Bunny/CDN, the Media host's NVMe edge; archive/backup separately, deep archive never… ([`12c6811`](https://github.com/OpenVibers/OpenVibe.Media/commit/12c6811b72325ea42cd1dfb40f40ad9bd6b203dd))\n- Media Fabric F1a: every read goes through one placement router (docs/media-fabric.md). ([`b2bdc44`](https://github.com/OpenVibers/OpenVibe.Media/commit/b2bdc4487659616b21fa8da00a0ab5a6509686a3))\n- Media Fabric F1b, off until the edge host exists: the origin shield. For a public B2 copy Node answers with X-Accel-Redirect into nginx's /_media_shield/b2/ (a 10 MB slice cache with proxy_cache_lock, keyed by object path and slice, never… ([`8c19184`](https://github.com/OpenVibers/OpenVibe.Media/commit/8c191840c9a13ddd6338e7ec5988292dd8af0b1d))\n- Origin shield (F1b) review fixes, still inert until MEDIA_SHIELD is set. The edge is known from X-Media-Shield-Host, which only the edge server block sets and openvibe.media clears (req.hostname honoured a client's X-Forwarded-Host), and… ([`29e6ada`](https://github.com/OpenVibers/OpenVibe.Media/commit/29e6ada831778049452e3044f285b88098469253))\n- Origin shield: viewers keep the one public URL. A shield-eligible read (a public or unlisted B2 copy, never private, sandbox or a recording) that arrives on openvibe.media answers a 302 to the same path on the DNS-only edge host, where the… ([`2ab62eb`](https://github.com/OpenVibers/OpenVibe.Media/commit/2ab62eb0d856f4f1149e279f89c8efe1c8c4d6f9))\n- Origin shield on in production: edge.openvibe.media (DNS-only, DNS-01 certificate), the nginx shield, MEDIA_SHIELD=b2. The edge also hides B2's object headers (x-amz-version-id, x-bz-*). docs/media-fabric.md records the switch-on and the… ([`a174534`](https://github.com/OpenVibers/OpenVibe.Media/commit/a1745348c9cb74cc517c9b8c82937037186cc0b8))\n- X-Internal-Key retirement, Media's step (plan T2): POST /internal/avatar-ingest takes Network's service token with media.avatar.ingest (server/service-guard.js, loopback only; a Bearer is judged on the token alone, the key still passes… ([`8364eee`](https://github.com/OpenVibers/OpenVibe.Media/commit/8364eeec44d6d4c0442bebae66d4db0f5976df6f))\n\n## OpenVibe.Games\n\n[openvibe.games](https://openvibe.games) · [repository](https://github.com/OpenVibers/OpenVibe.Games)\n\n- M1 identity: the WebSocket authenticates at the upgrade, the editor key is gone, and the contracts pin is current (ADR-0007 decisions 8 and 12). ([`3ea36b3`](https://github.com/OpenVibers/OpenVibe.Games/commit/3ea36b36afeac29da30ac9d56a537d6e78581488))\n- Physics conformance suite and an in-memory mock world (ADR-0007 M1 step 1): packages/physics/src/conformance.test.ts runs every seam case against MockPhysicsWorld and the Havok adapter (bodies, sweeps, joints, sleep and settle thresholds… ([`c24b7b1`](https://github.com/OpenVibers/OpenVibe.Games/commit/c24b7b1a288cbca745723e7d9c8918b6de0749e6))\n- Staff auth on openvibe-sdk v0.23.1's JWKS client (the last good keys through a Network outage, a rotation honoured on an unknown kid) and openvibe-contracts v0.78.0. Service and app principals are now checked by openvibe-contracts'… ([`5d18446`](https://github.com/OpenVibers/OpenVibe.Games/commit/5d18446bae00362dcf16b60fd99115d3cdb08487))\n- Movement state hash and determinism harness (ADR-0007 M1 step 2): stateHash.ts hashes the quantised PlayerMoveState (FNV-1a 32-bit over a documented big-endian stream; 1e-4 m, 1e-3 m/s) and measures divergence against the 1 mm / 1 cm/s… ([`f328cfc`](https://github.com/OpenVibers/OpenVibe.Games/commit/f328cfc5e3787c3bd2af822d35eb52a98081aa9f))\n- The portal's JSON-LD comes from openvibe-shared/seo (plan T11): WebSite plus the game as the site's primary type, injected as the page is served instead of a hand-written block in index.html. The page is built once per file version… ([`203057f`](https://github.com/OpenVibers/OpenVibe.Games/commit/203057f1431c849d52390f844d996ce29f47ad07))\n\n## OpenVibe.Codes\n\n[openvibe.codes](https://openvibe.codes) · [repository](https://github.com/OpenVibers/OpenVibe.Codes)\n\n- Network tokens verify through openvibe-sdk/auth's JWKS client (v0.23.1) in place of Codes' own key fetcher: the last good keys through a Network outage, backoff, a rotation honoured at once. Sign-in sessions and playground app tokens use… ([`57340a9`](https://github.com/OpenVibers/OpenVibe.Codes/commit/57340a97fb80555595910a04676f0eb02eaa35b3))\n- Token rejections keep the reason about the token (wrong audience, expired, bad signature): the playground's developers need 'not for openvibe.media'. Only token.no_key, whose SDK text names the internal JWKS URL and the connect error… ([`09212f6`](https://github.com/OpenVibers/OpenVibe.Codes/commit/09212f6723fa3d3c8d57fe44f8deed414714a083))\n- robots.txt, sitemap.xml and a new llms.txt come from openvibe-shared/seo (plan T11, server/http/discovery.js). The sitemap adds each public app and published release with its real publish date (one light query, releases.publicIndex); fixed… ([`9c60e95`](https://github.com/OpenVibers/OpenVibe.Codes/commit/9c60e959943c4bf1bd79ff83192701f3f68b5515))\n- Codes' outbox is openvibe-sdk/events createServiceOutbox (plan T1): the same event_outbox table, event-type allowlist and relay rules in one call, the hand-rolled wrapper gone. Pins openvibe-sdk v0.25.0, openvibe-contracts v0.79.0… ([`3408517`](https://github.com/OpenVibers/OpenVibe.Codes/commit/3408517d5aca7d0ffd5a203094fc412747c7ced4))\n\n## OpenVibe.Network\n\n[openvibe.network](https://openvibe.network) · [repository](https://github.com/OpenVibers/OpenVibe.Network)\n\n- X-Internal-Key retirement, Network's step (plan T2, register C-50–C-58), on openvibe-contracts v0.79.0 (via v0.78.0: the realtime manifest is gone, so the registry tests assert its absence). The 13 key-only internal routes nothing in the… ([`79a4eea`](https://github.com/OpenVibers/OpenVibe.Network/commit/79a4eea28fd444cbf4c94dc3fa4e38e9d32da7c9))\n- X-Internal-Key is gone from Network (plan T2, the last step of the sweep): every /internal route takes only a service token with the capability it performs (the router gate answers 401 token.missing without a Bearer and keeps the… ([`3bff136`](https://github.com/OpenVibers/OpenVibe.Network/commit/3bff136078b4ebda6bc21cf48a5b5ecf774c657a))\n- Plan T2 deletions in Network (each proven uncalled across the estate first): the one-time scripts hash-refresh-tokens, follows-backfill and creator-analytics-backfill; the built-in fallback tool catalog (before Tools has answered, the… ([`f6fe857`](https://github.com/OpenVibers/OpenVibe.Network/commit/f6fe857099ef29b9eb4c9ddb1b5b2ee546b46bec))\n- Grants for plan T3 and T4, on Contracts 0.80.0: Live reads a channel's moderation settings, moderators and emote count from Chat (chat.moderation.read); Chat uploads and deletes emote images in Media's chat namespace and runs the chat-AI… ([`b5d8707`](https://github.com/OpenVibers/OpenVibe.Network/commit/b5d870737f33a28a1bfead992c176ff8234757be))\n\n## OpenVibe.Chat\n\n[openvibe.chat](https://openvibe.chat) · [repository](https://github.com/OpenVibers/OpenVibe.Chat)\n\n- Pins current (plan T3 step 0): openvibe-sdk v0.23.1 (openvibe-sdk/db, ambient transactions, openvibe-sdk/testing, the JWKS client), openvibe-contracts v0.79.0, openvibe-shared v2.0.0 (none of its removed exports were used here), and the… ([`50e4dc1`](https://github.com/OpenVibers/OpenVibe.Chat/commit/50e4dc1bf97424fab897b3199805b4cf0ad78b87))\n- robots.txt, llms.txt and sitemap.xml come from openvibe-shared/seo (plan T11, server/web/discovery.js): public data only, lastmod from the data itself (the newest public message, each room's last activity), never today; every previous… ([`2091ec6`](https://github.com/OpenVibers/OpenVibe.Chat/commit/2091ec67febc89585826ee6eac61350daf2b91f9))\n\n## OpenVibe.Search\n\n[search.openvibe.network](https://search.openvibe.network) · [repository](https://github.com/OpenVibers/OpenVibe.Search)\n\n- Network tokens verify with keys from openvibe-sdk/auth's JWKS client (v0.23.1) in place of the hand-written key store: fresh keys, the last good ones through a Network outage, backoff, and a rotation honoured on an unknown kid. Service… ([`a3235a5`](https://github.com/OpenVibers/OpenVibe.Search/commit/a3235a5110525480449c5c70a8bbe5f8445cc429))\n- Crawl files through openvibe-shared/seo (plan T11): /llms.txt (what Search is, its public pages and machine-readable endpoints), /robots.txt from the shared builder with every existing rule kept, /sitemap.xml whose lastmods come from the… ([`fb2eed3`](https://github.com/OpenVibers/OpenVibe.Search/commit/fb2eed31b230d501e120302fb5651d0331f8842a))\n\n## OpenVibe.Sources\n\n[sources.openvibe.network](https://sources.openvibe.network) · [repository](https://github.com/OpenVibers/OpenVibe.Sources)\n\n- A corrupt stored robots.txt row no longer throws: it reads as no rules and warns once per origin (plan T0). Test: test/robots-ssrf.test.js stores unparseable rules and checks the fetch goes on. Built on a free model, reviewed independently… ([`d3f5e00`](https://github.com/OpenVibers/OpenVibe.Sources/commit/d3f5e0060054b5f0bfdee678d23835e435eb2929))\n- Network tokens verify with keys from openvibe-sdk/auth's JWKS client (v0.23.1) in place of Sources' own key store: the last good keys through a Network outage, backoff, a rotation honoured on an unknown kid. Every service-token rule stays… ([`4bea21f`](https://github.com/OpenVibers/OpenVibe.Sources/commit/4bea21fb843688f9900bf0918ef03b7014908e32))\n\n## OpenVibe.Tools\n\n[openvibe.tools](https://openvibe.tools) · [repository](https://github.com/OpenVibers/OpenVibe.Tools)\n\n- Internal analytics take Network service tokens (plan T2, X-Internal-Key retirement): GET /api/internal/analytics (and /bots) on the gateway and all seven tool sites accept a token holding tools.analytics.read (audience openvibe.tools… ([`55e4b84`](https://github.com/OpenVibers/OpenVibe.Tools/commit/55e4b84fcf6d4a0d88df057c7c4593d0299cd75d))\n- X-Internal-Key is gone from Tools (plan T2): GET /api/internal/analytics[/bots] on the gateway and the seven tool sites take only a Network service token with tools.analytics.read (401 token.missing without one), loopback only; the gateway… ([`139ece3`](https://github.com/OpenVibers/OpenVibe.Tools/commit/139ece3044f2f9e5b07e05e8c6c32e32cc64ab8c))\n\n## OpenVibe.AI\n\n[ai.openvibe.network](https://ai.openvibe.network) · [repository](https://github.com/OpenVibers/OpenVibe.AI)\n\n- Network tokens verify with keys from openvibe-sdk/auth's JWKS client (v0.23.1): fresh keys, the last good ones through a Network outage, backoff, and a rotation honoured on an unknown kid, in place of the hand-written key store. Every… ([`dde5e8f`](https://github.com/OpenVibers/OpenVibe.AI/commit/dde5e8fd4253a2d7ad8394d42873482a192feace))\n\n## OpenVibe.Blog\n\n[openvibe.blog](https://openvibe.blog) · [repository](https://github.com/OpenVibers/OpenVibe.Blog)\n\n- Blog on the service kit (plan T1): sign-in is openvibe-sdk/sso createSsoClient (state + PKCE S256, server-side exchange, next limited to this site and the Network), service tokens are checked by openvibe-sdk/auth verifyServiceToken (the… ([`f3fac6a`](https://github.com/OpenVibers/OpenVibe.Blog/commit/f3fac6a512941c34ff7bd9ae94166f1c22223628))\n\n## OpenVibe.Coupons\n\n[openvibe.coupons](https://openvibe.coupons) · [repository](https://github.com/OpenVibers/OpenVibe.Coupons)\n\n- Coupons on the service kit (plan T1): sign-in is openvibe-sdk/sso createSsoClient (state + PKCE S256, server-side exchange, next limited to this site and the Network) and server/auth/sso.js with the openvibe-shared/auth-client import is… ([`d4d51e1`](https://github.com/OpenVibers/OpenVibe.Coupons/commit/d4d51e16d55cfdafc05171ce4b0c0073fa23a3a2))\n\n## OpenVibe.Deals\n\n[openvibe.deals](https://openvibe.deals) · [repository](https://github.com/OpenVibers/OpenVibe.Deals)\n\n- Deals on the service kit (plan T1): sign-in is openvibe-sdk/sso createSsoClient (state + PKCE S256, server-side exchange, next limited to this site and the Network), service tokens are checked by openvibe-sdk/auth verifyServiceToken (the… ([`8d78e7e`](https://github.com/OpenVibers/OpenVibe.Deals/commit/8d78e7ead13261e0078f62c7e119bcd47e1b21df))\n\n## OpenVibe.Tips\n\n[openvibe.tips](https://openvibe.tips) · [repository](https://github.com/OpenVibers/OpenVibe.Tips)\n\n- Tips' outbox is openvibe-sdk/events createServiceOutbox (plan T1): tips_event_outbox, the service as actor, internal visibility and important priority on every envelope as before; callers use emitIn(t, envelope) inside the change's… ([`592a420`](https://github.com/OpenVibers/OpenVibe.Tips/commit/592a42028654907bdffe9a72a546b047485ccde2))\n\n---\n\nPatch notes are put together automatically when enough changes have shipped, or when a large feature lands. See every site's own updates page for the live list.","revision":1,"state":"published","visibility":"public","published_at":"2026-09-29T13:49:44.817Z","revised_at":"2026-09-29T13:49:44.801Z","author":{"subject":"usr_01KKT9AC60KM7CRTB3WN1Z8P56","name":"goosely","username":"goosely"},"authorship":{"mode":"imported","workflow":null,"reviewed":false,"disclosure":{"mode":"imported","short":"Imported","long":"Imported from Commit messages from the OpenVibers repositories on GitHub; originally by OpenVibers."}},"tags":["patch-notes","live","media","games","codes","network","chat","search","sources","tools","ai"],"categories":[],"series":{"title":"Patch notes","url":"https://openvibe.blog/@openvibe/series/patch-notes","position":null},"media":[],"citations":[],"indexability":{"indexable":true,"robots":"index, follow","reasons":[]}}