openvibers/openvibe.network Commits

Roadmap baseline: D20 canonical resolver is partial, no longer not met (lineage contract in openvibe-contracts v0.32.0, resolver deployed in Live 2026-09-23 21:36 UTC, display-name test, production 401 check); remaining: consumers' grants, OpenRe session lineage, Media owner_subject backfill. Ledger: 3 met, 36 partial, 0 not met, 7 blocked on owner; all 46 verified (EC6 passes; EC7 waits on the owner's hazard review). Regenerated from origin/main

OP OpenVibers committed 23 Sept 2026 · e99a80fa38 · 15 files, +2017 −997


Changes

ddiff --git a/docs/roadmap-baseline/01-services.md b/docs/roadmap-baseline/01-services.md
iindex e0ecd792..88e6586d 100644
---- a/docs/roadmap-baseline/01-services.md
++++ b/docs/roadmap-baseline/01-services.md
@@@ -39,20 +39,20 @@ Deliverable 1: runtimes, ports, units, env files and repository state.
| Repo | HEAD | origin/main | Source files | LOC | Test files | CI | Routes | Tables | WS servers | Timers/jobs | TODO(contract) |
|---|---|---|---|---|---|---|---|---|---|---|---|
--| OpenVibe.Live | c893c6c | c893c6c | 189 | 74113 | 78 | yes | 629 | 125 | 8 | 51 | 15 |
--| OpenVibe.Network | 9bbd90f | 9bbd90f | 67 | 14871 | 28 | yes | 247 | 43 | 0 | 6 | 0 |
--| OpenVibe.Shared | c6405d4 | c6405d4 | 45 | 10921 | 17 | yes | 3 | 0 | 0 | 6 | 0 |
--| OpenVibe.Media | 9de4b25 | 9de4b25 | 38 | 11376 | 16 | yes | 92 | 20 | 0 | 11 | 0 |
++| OpenVibe.Live | ca7cc87 | ca7cc87 | 194 | 74460 | 81 | yes | 631 | 125 | 8 | 51 | 14 |
++| OpenVibe.Network | 09bf748 | 09bf748 | 68 | 15275 | 29 | yes | 248 | 45 | 0 | 7 | 0 |
++| OpenVibe.Shared | c272680 | c272680 | 47 | 11774 | 19 | yes | 2 | 0 | 0 | 6 | 0 |
++| OpenVibe.Media | ad2217b | ad2217b | 47 | 13469 | 20 | yes | 109 | 22 | 0 | 13 | 0 |
| OpenVibe.Tools | 5d1b423 | 5d1b423 | 130 | 22829 | 16 | yes | 118 | 3 | 0 | 16 | 0 |
--| OpenVibe.Community | 57d1dd4 | 57d1dd4 | 47 | 7885 | 25 | yes | 107 | 20 | 0 | 3 | 0 |
++| OpenVibe.Community | 63b90a8 | 63b90a8 | 47 | 7886 | 25 | yes | 107 | 20 | 0 | 3 | 0 |
| OpenVibe.Games | 7863fc6 | 7863fc6 | 117 | 22529 | 68 | yes | 21 | 12 | 2 | 3 | 0 |
| OpenVibe.Sites | d6e4cbd | d6e4cbd | 1 | 308 | 1 | yes | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Events | efc09a7 | efc09a7 | 17 | 2914 | 12 | yes | 17 | 7 | 0 | 3 | 0 |
--| OpenVibe.Chat | 7897688 | 7897688 | 28 | 11140 | 16 | yes | 60 | 32 | 1 | 9 | 0 |
++| OpenVibe.Chat | ed90461 | ed90461 | 34 | 11947 | 19 | yes | 63 | 34 | 1 | 10 | 0 |
| OpenRe.Stream | c091a09 | c091a09 | 34 | 4641 | 18 | yes | 37 | 12 | 0 | 2 | 0 |
| OpenVibe.Billing | aa445d0 | aa445d0 | 36 | 5124 | 16 | yes | 54 | 19 | 0 | 3 | 0 |
--| OpenVibe.Tips | 9a3a186 | 9a3a186 | 26 | 4065 | 11 | yes | 45 | 14 | 0 | 3 | 0 |
--| OpenVibe.VIP | 9668a49 | 9668a49 | 27 | 3881 | 10 | yes | 40 | 13 | 0 | 2 | 0 |
++| OpenVibe.Tips | f211c03 | f211c03 | 29 | 5250 | 15 | yes | 62 | 17 | 0 | 3 | 0 |
++| OpenVibe.VIP | fe7eaad | fe7eaad | 29 | 4194 | 11 | yes | 44 | 13 | 0 | 2 | 0 |
| OpenVibe.AI | 3a480ac | 3a480ac | 30 | 4576 | 17 | yes | 33 | 16 | 0 | 2 | 0 |
| OpenVibe.Search | a707e38 | a707e38 | 17 | 2733 | 13 | yes | 20 | 11 | 0 | 4 | 0 |
| OpenVibe.Sources | 2e986af | 2e986af | 23 | 2974 | 10 | yes | 17 | 8 | 0 | 4 | 0 |
@@@ -64,7 +64,7 @@ Deliverable 1: runtimes, ports, units, env files and repository state.
| OpenVibe.Coupons | 1c57c47 | 1c57c47 | 28 | 4081 | 12 | yes | 46 | 12 | 0 | 2 | 0 |
| OpenVibe.Trade | ddbc60c | ddbc60c | 36 | 4405 | 13 | yes | 7 | 10 | 0 | 2 | 0 |
| OpenVibe.Codes | 51d2386 | 51d2386 | 27 | 3966 | 19 | yes | 95 | 7 | 0 | 0 | 0 |
--| OpenVibe.Host | ea99b50 | ea99b50 | 55 | 8099 | 27 | yes | 56 | 11 | 0 | 1 | 0 |
++| OpenVibe.Host | 03dfcb3 | 03dfcb3 | 55 | 8099 | 27 | yes | 56 | 11 | 0 | 1 | 0 |
| OpenVibe.Examples | d5f4efc | d5f4efc | 11 | 1604 | 14 | yes | 0 | 1 | 0 | 0 | 0 |
LOC counts non-test source files in the scanned directories only (`server/`, `apps/`, `packages/`), not frontend assets.
ddiff --git a/docs/roadmap-baseline/02-schema.md b/docs/roadmap-baseline/02-schema.md
iindex 922fc13a..9ee321c5 100644
---- a/docs/roadmap-baseline/02-schema.md
++++ b/docs/roadmap-baseline/02-schema.md
@@@ -69,13 +69,13 @@ Deliverable 2: every table declared in code or present in production, with curre
| Table | Declared at | In prod | Target owner | Disposition | Wave |
|---|---|---|---|---|---|
| active_effects | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--| ai_chatbot_configs | server/db/database.js:1810 | live.db | OpenVibe.AI | extract | W13 |
++| ai_chatbot_configs | server/db/database.js:1782 | live.db | OpenVibe.AI | extract | W13 |
| ai_conversations | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| ai_memory | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| ai_timeline_cache | server/db/database.js:1303 | live.db | OpenVibe.AI | extract | W13 |
| ai_usage | server/db/database.js:1261 | live.db | OpenVibe.AI | extract | W13 |
--| ai_viewer_log | server/db/database.js:1894 | live.db | OpenVibe.AI | extract | W13 |
--| ai_viewer_threads | server/db/database.js:1880 | live.db | OpenVibe.AI | extract | W13 |
++| ai_viewer_log | server/db/database.js:1866 | live.db | OpenVibe.AI | extract | W13 |
++| ai_viewer_threads | server/db/database.js:1852 | live.db | OpenVibe.AI | extract | W13 |
| analytics_daily | (prod only) | analytics.db | OpenVibe.Live | keep | Track O / ADR-021 |
| analytics_day_salts | (prod only) | analytics.db | OpenVibe.Live | keep | Track O / ADR-021 |
| analytics_events | (prod only) | analytics.db | OpenVibe.Live | keep | Track O / ADR-021 |
@@@ -87,7 +87,7 @@ Deliverable 2: every table declared in code or present in production, with curre
| api_keys | server/db/schema.sql:391 | live.db | OpenVibe.Network (principals) / OpenVibe.Codes | extract | W1/W20 |
| api_tokens | server/db/schema.sql:404 | live.db | OpenVibe.Network (principals) / OpenVibe.Codes | extract | W1/W20 |
| app_state | server/db/database.js:1174 | live.db | OpenVibe.Live | keep | - |
--| approved_ips | server/db/database.js:2082 | live.db | OpenVibe.Network (policy) | extract | W1 |
++| approved_ips | server/db/database.js:2054 | live.db | OpenVibe.Network (policy) | extract | W1 |
| arena_achievements | (prod only) | live.db | archive then drop | investigate | W0 |
| arena_battles | (prod only) | live.db | archive then drop | investigate | W0 |
| arena_beef_hype | server/arena/beef.js:58 | live.db | OpenVibe.Live | keep | - |
@@@ -129,13 +129,13 @@ Deliverable 2: every table declared in code or present in production, with curre
| canvas_tiles | (prod only) | live.db | OpenVibe.Games | frozen-legacy | W12 |
| canvas_user_overrides | (prod only) | live.db | OpenVibe.Games | frozen-legacy | W12 |
| changelog_entries | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--| channel_ai_bots | server/db/database.js:1835 | live.db | OpenVibe.AI | extract | W13 |
--| channel_ai_config | server/db/database.js:1859 | live.db | OpenVibe.AI | extract | W13 |
--| channel_moderation_settings | server/db/database.js:1645, server/db/schema.sql:514 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
--| channel_moderators | server/db/database.js:1628, server/db/schema.sql:499 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
++| channel_ai_bots | server/db/database.js:1807 | live.db | OpenVibe.AI | extract | W13 |
++| channel_ai_config | server/db/database.js:1831 | live.db | OpenVibe.AI | extract | W13 |
++| channel_moderation_settings | server/db/database.js:1617, server/db/schema.sql:514 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
++| channel_moderators | server/db/database.js:1600, server/db/schema.sql:499 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
| channel_points | server/db/database.js:766 | live.db | OpenVibe.Billing (loyalty ledger) | extract | W8 (after ADR-012) |
--| channel_sounds | server/db/database.js:1748, server/db/schema.sql:625 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
--| channel_sounds_new | server/db/database.js:1772 | no | OpenVibe.Chat | extract | W6 (remainder) |
++| channel_sounds | server/db/database.js:1720, server/db/schema.sql:625 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
++| channel_sounds_new | server/db/database.js:1744 | no | OpenVibe.Chat | extract | W6 (remainder) |
| channels | server/db/schema.sql:26 | live.db | OpenVibe.Live | keep | - |
| chat_ai_summaries | server/db/database.js:1315 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
| chat_bridge_outbox | server/chat/chat-remote.js:94 | live.db | OpenVibe.Live | keep | W6 (compat) |
@@@ -154,9 +154,9 @@ Deliverable 2: every table declared in code or present in production, with curre
| comment_thread_refs | server/comments-client.js:47 | live.db | OpenVibe.Live | keep | W5 |
| comments | server/db/database.js:855, server/db/schema.sql:585 | live.db | OpenVibe.Community | frozen-legacy | W5 (done 2026-09-23) |
| content_views | server/db/schema.sql:328 | live.db | OpenVibe.Live | keep | - |
--| control_config_buttons | server/db/database.js:2313 | live.db | OpenRe.Stream | extract | W7 |
--| control_configs | server/db/database.js:2299 | live.db | OpenRe.Stream | extract | W7 |
--| control_whitelist | server/db/database.js:2284 | live.db | OpenRe.Stream | extract | W7 |
++| control_config_buttons | server/db/database.js:2278 | live.db | OpenRe.Stream | extract | W7 |
++| control_configs | server/db/database.js:2264 | live.db | OpenRe.Stream | extract | W7 |
++| control_whitelist | server/db/database.js:2249 | live.db | OpenRe.Stream | extract | W7 |
| custom_rewards | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| daily_claims | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| divorce_history | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
@@@ -168,7 +168,7 @@ Deliverable 2: every table declared in code or present in production, with curre
| dungeon_stats | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| easter_egg_solves | server/db/database.js:1347 | live.db | OpenVibe.AI | extract | W13 |
| emotes | server/db/schema.sql:603 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
--| emotes_new | server/db/database.js:1716 | no | OpenVibe.Chat | extract | W6 (remainder) |
++| emotes_new | server/db/database.js:1688 | no | OpenVibe.Chat | extract | W6 (remainder) |
| event_log | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| event_outbox | (prod only) | live.db | OpenVibe.Live | keep | W3 |
| farm_plots | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
@@@ -191,34 +191,34 @@ Deliverable 2: every table declared in code or present in production, with curre
| game_structures | server/game/schema.sql:87 | live.db | OpenVibe.Games | migrate-then-drop | W12 |
| game_world_state | server/game/schema.sql:7 | live.db | OpenVibe.Games | migrate-then-drop | W12 |
| gusher_profile | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--| hidden_relay_users | server/db/database.js:2119 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
++| hidden_relay_users | server/db/database.js:2091 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
| inventory | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--| ip_log | server/db/database.js:2058 | live.db | OpenVibe.Network (policy) | extract | W1 |
++| ip_log | server/db/database.js:2030 | live.db | OpenVibe.Network (policy) | extract | W1 |
| jo_profile | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| kick_channel_cache | server/db/database.js:780 | live.db | OpenRe.Stream | extract | W7 |
| linked_accounts | server/db/database.js:386 | live.db | OpenVibe.Network | extract | W1 |
| love_affinity | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| love_profile | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| love_proposals | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--| managed_streams | server/db/database.js:2427, server/db/schema.sql:78 | live.db | OpenRe.Stream | extract | W7 |
++| managed_streams | server/db/database.js:2392, server/db/schema.sql:78 | live.db | OpenRe.Stream | extract | W7 |
| media_request_settings | server/db/database.js:875, server/db/schema.sql:722 | live.db | OpenVibe.Chat | extract | W6 (remainder) |
| media_requests | server/db/database.js:889, server/db/schema.sql:739 | live.db, rs-companion.db | OpenVibe.Chat | extract | W6 (remainder) |
| mine_profile | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| mod_persuasion | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--| moderation_actions | server/db/database.js:1927 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
++| moderation_actions | server/db/database.js:1899 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
| music_profile | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| news_settings | server/news/news-service.js:47 | live.db | OpenVibe.Live | keep | - |
| openre_sessions | server/openre/schema.js:21 | live.db | OpenVibe.Live | keep | W7 |
--| paste_comments | server/db/database.js:2015 | live.db | OpenVibe.Community | frozen-legacy | W5 |
--| paste_likes | server/db/database.js:1983 | live.db | OpenVibe.Community | frozen-legacy | W5 |
--| pastes | server/db/database.js:1946 | live.db | OpenVibe.Community | frozen-legacy | W5 |
--| payment_orders | server/db/database.js:1595 | live.db | OpenVibe.Billing | extract | W8 (after ADR-012) |
--| pending_ip_messages | server/db/database.js:2099 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
++| paste_comments | server/db/database.js:1987 | live.db | OpenVibe.Community | frozen-legacy | W5 |
++| paste_likes | server/db/database.js:1955 | live.db | OpenVibe.Community | frozen-legacy | W5 |
++| pastes | server/db/database.js:1918 | live.db | OpenVibe.Community | frozen-legacy | W5 |
++| payment_orders | server/db/database.js:1567 | live.db | OpenVibe.Billing | extract | W8 (after ADR-012) |
++| pending_ip_messages | server/db/database.js:2071 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
| platform_connections | server/db/database.js:715 | live.db | OpenRe.Stream | extract | W7 |
| powerchat_connections | server/db/database.js:737 | live.db | OpenVibe.Live | keep | W3 (deliveries -> Events) |
| powerchat_webhook_deliveries | server/db/database.js:754 | live.db | OpenVibe.Live | keep | W3 (deliveries -> Events) |
| promo_claims | (prod only) | live.db | archive then drop | investigate | W0 |
--| relay_users | server/db/database.js:1473 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
++| relay_users | server/db/database.js:1472 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
| restream_destinations | server/db/database.js:697 | live.db | OpenRe.Stream | extract | W7 |
| roast_dossier | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| roast_log | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
@@@ -228,8 +228,8 @@ Deliverable 2: every table declared in code or present in production, with curre
| site_settings | server/db/database.js:355, server/db/schema.sql:556 | live.db | OpenVibe.Live | keep | - |
| stream_analytics | server/db/schema.sql:810 | live.db | OpenVibe.Live | keep | - |
| stream_controls | server/db/schema.sql:372 | live.db | OpenRe.Stream | extract | W7 |
--| stream_controls_new | server/db/database.js:2392 | no | OpenRe.Stream | extract | W7 |
--| stream_first_chats | server/db/database.js:2047 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
++| stream_controls_new | server/db/database.js:2357 | no | OpenRe.Stream | extract | W7 |
++| stream_first_chats | server/db/database.js:2019 | live.db | OpenVibe.Chat | mirror | W6 (done 2026-09-23) |
| stream_memories | server/db/database.js:1188 | live.db | OpenVibe.AI | extract | W13 |
| stream_recaps | server/recap/recap.js:27 | live.db | OpenVibe.AI | extract | W13 |
| stream_timeline_events | server/db/database.js:1236 | live.db | OpenVibe.Live | keep | - |
@@@ -252,9 +252,9 @@ Deliverable 2: every table declared in code or present in production, with curre
| user_voices | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
| users | server/db/schema.sql:5 | live.db, rs-companion.db | OpenVibe.Network | extract | W1 |
| verification_keys | server/db/database.js:366, server/db/schema.sql:567 | live.db | OpenVibe.Network | extract | W1 |
--| vibe_coding_events | server/db/database.js:2684, server/db/schema.sql:198 | live.db | OpenVibe.Codes | extract | W20 |
--| vibe_coding_sessions | server/db/database.js:2649, server/db/schema.sql:170 | live.db | OpenVibe.Codes | extract | W20 |
--| viewer_samples | server/db/database.js:3983 | live.db | OpenVibe.Live | keep | - |
++| vibe_coding_events | server/db/database.js:2649, server/db/schema.sql:198 | live.db | OpenVibe.Codes | extract | W20 |
++| vibe_coding_sessions | server/db/database.js:2614, server/db/schema.sql:170 | live.db | OpenVibe.Codes | extract | W20 |
++| viewer_samples | server/db/database.js:3832 | live.db | OpenVibe.Live | keep | - |
| viewer_snapshots | server/db/schema.sql:799 | live.db | OpenVibe.Live | keep | - |
| vod_ai_state | server/db/database.js:265 | live.db | OpenVibe.AI | extract | W13 |
| vods | server/db/schema.sql:280 | live.db | OpenVibe.Media | frozen-legacy | W4 |
@@@ -262,7 +262,7 @@ Deliverable 2: every table declared in code or present in production, with curre
| watch_time | server/db/schema.sql:706 | live.db | OpenVibe.Live | keep | - |
| woodcut_profile | (prod only) | rs-companion.db | OpenVibe.Games (import source) | frozen-legacy | W12 |
--## OpenVibe.Network (51)
++## OpenVibe.Network (53)
| Table | Declared at | In prod | Target owner | Disposition | Wave |
|---|---|---|---|---|---|
@@@ -301,17 +301,19 @@ Deliverable 2: every table declared in code or present in production, with curre
| oauth_codes | server/db/database.js:64 | network.db | OpenVibe.Network | keep | W1 (module split) |
| oauth_tokens | server/db/database.js:78 | network.db | OpenVibe.Network | keep | W1 (module split) |
| password_reset_tokens | server/db/database.js:241 | network.db | OpenVibe.Network | keep | W1 (module split) |
--| principal_grants | server/identity/principals.js:151 | network.db | OpenVibe.Network | keep | W1 (module split) |
--| principal_usage | server/identity/principals.js:161 | network.db | OpenVibe.Network | keep | W1 (module split) |
++| principal_grants | server/identity/principals.js:164 | network.db | OpenVibe.Network | keep | W1 (module split) |
++| principal_usage | server/identity/principals.js:174 | network.db | OpenVibe.Network | keep | W1 (module split) |
| push_subscriptions | server/db/database.js:380 | network.db | OpenVibe.Network | keep | W3 (delivery -> Events outbox) |
| site_settings | server/db/database.js:158 | network.db | OpenVibe.Network | keep | - |
--| stream_live_announcements | server/notifications/stream-live.js:17 | network.db | OpenVibe.Events | extract | W3 |
++| stream_live_announcements | server/notifications/stream-live.js:31 | network.db | OpenVibe.Events | extract | W3 |
| themes | server/db/database.js:103 | network.db | OpenVibe.Network | keep | W1 (module split) |
| tool_domains | server/domains/routes.js:44 | network.db | OpenVibe.Network | keep | W1 (module split) |
| url_registry | server/db/database.js:165, server/url-registry.js:7 | network.db | OpenVibe.Network | keep | W1 (module split) |
| user_effects | server/db/database.js:295 | network.db | OpenVibe.Network | keep | W1 (module split) |
| user_history | server/history/routes.js:26 | network.db | OpenVibe.Network | keep | W1 (module split) |
--| user_modules | server/identity/modules.js:24 | network.db | OpenVibe.Network | keep | W1 (module split) |
++| user_module_retirements | server/identity/modules.js:93 | no | OpenVibe.Network | keep | W1 (module split) |
++| user_module_revisions | server/identity/modules.js:86 | no | OpenVibe.Network | keep | W1 (module split) |
++| user_modules | server/identity/modules.js:75 | network.db | OpenVibe.Network | keep | W1 (module split) |
| user_preferences | server/db/database.js:92 | network.db | OpenVibe.Network | keep | W1 (module split) |
| user_sessions | server/db/database.js:274 | network.db | OpenVibe.Network | keep | W1 (module split) |
| users | server/db/database.js:33 | network.db | OpenVibe.Network | keep | W1 (module split) |
@@@ -322,7 +324,7 @@ Deliverable 2: every table declared in code or present in production, with curre
No tables.
--## OpenVibe.Media (21)
++## OpenVibe.Media (23)
| Table | Declared at | In prod | Target owner | Disposition | Wave |
|---|---|---|---|---|---|
@@@ -333,16 +335,18 @@ No tables.
| content_visits | server/views/service.js:43 | media.db | OpenVibe.Media | keep | W4 (object model) |
| event_outbox | (prod only) | media.db | OpenVibe.Media | keep | W3 |
| files | server/db/schema.sql:167 | media.db | OpenVibe.Media | keep | W4 (object model) |
--| media_holds | server/db/schema.sql:293 | media.db | OpenVibe.Media | keep | W4 (object model) |
--| media_invariant_violations | server/db/schema.sql:306 | media.db | OpenVibe.Media | keep | W4 (object model) |
--| media_jobs | server/db/schema.sql:279 | media.db | OpenVibe.Media | keep | W4 (object model) |
++| media_holds | server/db/schema.sql:338 | media.db | OpenVibe.Media | keep | W4 (object model) |
++| media_invariant_violations | server/db/schema.sql:351 | media.db | OpenVibe.Media | keep | W4 (object model) |
++| media_jobs | server/db/schema.sql:281 | media.db | OpenVibe.Media | keep | W4 (object model) |
| media_locations | server/db/schema.sql:241 | media.db | OpenVibe.Media | keep | W4 (object model) |
| media_objects | server/db/schema.sql:214 | media.db | OpenVibe.Media | keep | W4 (object model) |
| media_relationships | server/db/schema.sql:257 | media.db | OpenVibe.Media | keep | W4 (object model) |
| media_settings | server/db/schema.sql:182 | media.db | OpenVibe.Media | keep | W4 (object model) |
++| media_upload_parts | server/db/schema.sql:328 | no | OpenVibe.Media | keep | W4 (object model) |
++| media_uploads | server/db/schema.sql:312 | no | OpenVibe.Media | keep | W4 (object model) |
| media_variants | server/db/schema.sql:268 | media.db | OpenVibe.Media | keep | W4 (object model) |
--| media_verifications | server/db/schema.sql:320 | media.db | OpenVibe.Media | keep | W4 (object model) |
--| media_verify_runs | server/db/schema.sql:332 | media.db | OpenVibe.Media | keep | W4 (object model) |
++| media_verifications | server/db/schema.sql:365 | media.db | OpenVibe.Media | keep | W4 (object model) |
++| media_verify_runs | server/db/schema.sql:377 | media.db | OpenVibe.Media | keep | W4 (object model) |
| paste_comments | server/db/schema.sql:149 | media.db | OpenVibe.Community | frozen-legacy | W5 (done 2026-09-22) |
| paste_likes | server/db/schema.sql:141 | media.db | OpenVibe.Community | frozen-legacy | W5 (done 2026-09-22) |
| pastes | server/db/schema.sql:107 | media.db | OpenVibe.Community | frozen-legacy | W5 (done 2026-09-22) |
@@@ -422,7 +426,7 @@ No tables.
| sequences | server/store.js:20 | events.db | OpenVibe.Events | keep | W3 |
| subscriptions | server/store.js:48 | events.db | OpenVibe.Events | keep | W3 |
--## OpenVibe.Chat (32)
++## OpenVibe.Chat (34)
| Table | Declared at | In prod | Target owner | Disposition | Wave |
|---|---|---|---|---|---|
@@@ -433,6 +437,7 @@ No tables.
| channel_moderators | server/db/schema.sql:190 | chat.db | OpenVibe.Chat | staged | W6 (remainder) |
| channel_sounds | server/db/schema.sql:109 | chat.db | OpenVibe.Chat | keep | W6 |
| chat_ai_summaries | server/db/schema.sql:277 | chat.db | OpenVibe.Chat | staged | W6 (remainder) |
++| chat_event_inbox | server/db/schema.sql:487 | no | OpenVibe.Chat | keep | W6 |
| chat_messages | server/db/schema.sql:24 | chat.db | OpenVibe.Chat | keep | W6 |
| chat_meta | server/db/schema.sql:463 | chat.db | OpenVibe.Chat | keep | W6 |
| chat_timeline_events | server/db/schema.sql:295 | chat.db | OpenVibe.Chat | staged | W6 (remainder) |
@@@ -441,6 +446,7 @@ No tables.
| ctx_streams | server/db/schema.sql:333 | chat.db | OpenVibe.Chat | keep | W6 |
| ctx_sync | server/db/schema.sql:367 | chat.db | OpenVibe.Chat | keep | W6 |
| ctx_users | server/db/schema.sql:316 | chat.db | OpenVibe.Chat | keep | W6 |
++| deploy_releases | server/db/schema.sql:473 | no | OpenVibe.Chat | keep | W6 |
| dm_blocks | server/db/schema.sql:88 | chat.db | OpenVibe.Chat | keep | W6 |
| dm_conversations | server/db/schema.sql:54 | chat.db | OpenVibe.Chat | keep | W6 |
| dm_messages | server/db/schema.sql:76 | chat.db | OpenVibe.Chat | keep | W6 |
@@@ -501,26 +507,29 @@ No tables.
| subscriptions | server/db.js:184 | billing.db | OpenVibe.Billing | keep | W8 |
| transactions | server/db.js:40 | billing.db | OpenVibe.Billing | keep | W8 |
--## OpenVibe.Tips (16)
++## OpenVibe.Tips (19)
| Table | Declared at | In prod | Target owner | Disposition | Wave |
|---|---|---|---|---|---|
--| api_idempotency | server/db.js:249 | tips.db | OpenVibe.Tips | keep | W9 |
--| creator_tip_profiles | server/db.js:36 | tips.db | OpenVibe.Tips | keep | W9 |
++| api_idempotency | server/db.js:287 | tips.db | OpenVibe.Tips | keep | W9 |
++| creator_tip_profiles | server/db.js:37 | tips.db | OpenVibe.Tips | keep | W9 |
| event_outbox | (prod only) | tips.db | OpenVibe.Tips | keep | W3 |
| idempotency_receipts | (prod only) | tips.db | OpenVibe.Tips | keep | W3 |
--| import_runs | server/db.js:240 | tips.db | OpenVibe.Tips | keep | W9 |
--| interaction_effects | server/db.js:208 | tips.db | OpenVibe.Tips | keep | W9 |
--| migration_maps | server/db.js:224 | tips.db | OpenVibe.Tips | keep | W9 |
--| overlay_configs | server/db.js:162 | tips.db | OpenVibe.Tips | keep | W9 |
--| overlay_deliveries | server/db.js:189 | tips.db | OpenVibe.Tips | keep | W9 |
--| overlay_tokens | server/db.js:175 | tips.db | OpenVibe.Tips | keep | W9 |
--| paid_media_requests | server/db.js:149 | tips.db | OpenVibe.Tips | keep | W9 |
--| paid_messages | server/db.js:134 | tips.db | OpenVibe.Tips | keep | W9 |
--| settings | server/db.js:30 | tips.db | OpenVibe.Tips | keep | W9 |
--| tip_goal_contributions | server/db.js:123 | tips.db | OpenVibe.Tips | keep | W9 |
--| tip_goals | server/db.js:103 | tips.db | OpenVibe.Tips | keep | W9 |
--| tip_interactions | server/db.js:58 | tips.db | OpenVibe.Tips | keep | W9 |
++| import_runs | server/db.js:241 | tips.db | OpenVibe.Tips | keep | W9 |
++| interaction_effects | server/db.js:209 | tips.db | OpenVibe.Tips | keep | W9 |
++| migration_maps | server/db.js:225 | tips.db | OpenVibe.Tips | keep | W9 |
++| overlay_configs | server/db.js:163 | tips.db | OpenVibe.Tips | keep | W9 |
++| overlay_deliveries | server/db.js:190 | tips.db | OpenVibe.Tips | keep | W9 |
++| overlay_tokens | server/db.js:176 | tips.db | OpenVibe.Tips | keep | W9 |
++| paid_media_requests | server/db.js:150 | tips.db | OpenVibe.Tips | keep | W9 |
++| paid_messages | server/db.js:135 | tips.db | OpenVibe.Tips | keep | W9 |
++| settings | server/db.js:31 | tips.db | OpenVibe.Tips | keep | W9 |
++| tip_goal_contributions | server/db.js:124 | tips.db | OpenVibe.Tips | keep | W9 |
++| tip_goals | server/db.js:104 | tips.db | OpenVibe.Tips | keep | W9 |
++| tip_interactions | server/db.js:59 | tips.db | OpenVibe.Tips | keep | W9 |
++| tip_moderation_log | server/db.js:275 | no | OpenVibe.Tips | keep | W9 |
++| tip_moderator_invites | server/db.js:263 | no | OpenVibe.Tips | keep | W9 |
++| tip_moderators | server/db.js:252 | no | OpenVibe.Tips | keep | W9 |
## OpenVibe.VIP (15)
ddiff --git a/docs/roadmap-baseline/03-routes.md b/docs/roadmap-baseline/03-routes.md
iindex 08e9bd94..0dd38168 100644
---- a/docs/roadmap-baseline/03-routes.md
++++ b/docs/roadmap-baseline/03-routes.md
@@@ -8,19 +8,19 @@ Deliverable 3 (routes half). Paths include the prefix of the `app.use()` mount t
| Repo | Routes | GET | POST | PUT/PATCH | DELETE | Other | /internal/* | Stay | Elsewhere or moving |
|---|---|---|---|---|---|---|---|---|---|
--| OpenVibe.Live | 629 | 311 | 219 | 50 | 48 | 1 | 93 | 343 | 286 |
--| OpenVibe.Network | 247 | 116 | 82 | 30 | 19 | 0 | 30 | 246 | 1 |
--| OpenVibe.Shared | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 3 | 0 |
--| OpenVibe.Media | 92 | 40 | 35 | 5 | 12 | 0 | 1 | 74 | 18 |
++| OpenVibe.Live | 631 | 312 | 220 | 50 | 48 | 1 | 95 | 345 | 286 |
++| OpenVibe.Network | 248 | 116 | 82 | 30 | 20 | 0 | 30 | 247 | 1 |
++| OpenVibe.Shared | 2 | 2 | 0 | 0 | 0 | 0 | 0 | 2 | 0 |
++| OpenVibe.Media | 109 | 44 | 44 | 6 | 15 | 0 | 1 | 91 | 18 |
| OpenVibe.Tools | 118 | 98 | 14 | 1 | 4 | 1 | 0 | 118 | 0 |
| OpenVibe.Community | 107 | 54 | 32 | 12 | 9 | 0 | 0 | 107 | 0 |
| OpenVibe.Games | 21 | 0 | 3 | 0 | 0 | 18 | 0 | 21 | 0 |
| OpenVibe.Events | 17 | 11 | 5 | 1 | 0 | 0 | 1 | 17 | 0 |
--| OpenVibe.Chat | 60 | 37 | 14 | 3 | 6 | 0 | 0 | 60 | 0 |
++| OpenVibe.Chat | 63 | 38 | 15 | 4 | 6 | 0 | 0 | 63 | 0 |
| OpenRe.Stream | 37 | 25 | 8 | 2 | 2 | 0 | 0 | 37 | 0 |
| OpenVibe.Billing | 54 | 31 | 22 | 0 | 0 | 1 | 0 | 54 | 0 |
--| OpenVibe.Tips | 45 | 27 | 15 | 3 | 0 | 0 | 0 | 45 | 0 |
--| OpenVibe.VIP | 40 | 24 | 12 | 3 | 1 | 0 | 0 | 40 | 0 |
++| OpenVibe.Tips | 62 | 37 | 22 | 3 | 0 | 0 | 0 | 62 | 0 |
++| OpenVibe.VIP | 44 | 28 | 12 | 3 | 1 | 0 | 0 | 44 | 0 |
| OpenVibe.AI | 33 | 18 | 12 | 2 | 1 | 0 | 0 | 33 | 0 |
| OpenVibe.Search | 20 | 15 | 2 | 1 | 2 | 0 | 1 | 20 | 0 |
| OpenVibe.Sources | 17 | 11 | 3 | 1 | 2 | 0 | 0 | 17 | 0 |
@@@ -62,60 +62,60 @@ Owner = the repository whose code answers the route; target = the authority it b
| Method | Path | Source | Target | Disposition |
|---|---|---|---|---|
--| GET | /api/admin/admins | server/admin/routes.js:788 | | keep |
--| POST | /api/admin/admins | server/admin/routes.js:798 | | keep |
--| DELETE | /api/admin/admins/:id | server/admin/routes.js:817 | | keep |
--| GET | /api/admin/ai/explorer/:userId | server/admin/routes.js:577 | | keep |
--| GET | /api/admin/ai/overviews | server/admin/routes.js:609 | | keep |
--| GET | /api/admin/ai/status | server/admin/routes.js:567 | | keep |
--| POST | /api/admin/ai/streamer/:userId/overview | server/admin/routes.js:618 | | keep |
--| GET | /api/admin/ai/usage | server/admin/routes.js:520 | | keep |
--| POST | /api/admin/ai/viewers/:userId/:action | server/admin/routes.js:548 | | keep |
--| GET | /api/admin/ai/viewers/:userId/log | server/admin/routes.js:558 | | keep |
--| GET | /api/admin/ai/viewers/status | server/admin/routes.js:530 | | keep |
--| GET | /api/admin/analytics | server/index.js:707 | | keep |
--| GET | /api/admin/analytics/bots | server/index.js:716 | | keep |
--| GET | /api/admin/bans | server/admin/routes.js:427 | | keep |
--| POST | /api/admin/broadcast | server/index.js:824 | | keep |
--| PUT | /api/admin/channels/:id/force-nsfw | server/admin/routes.js:368 | | keep |
++| GET | /api/admin/admins | server/admin/routes.js:796 | | keep |
++| POST | /api/admin/admins | server/admin/routes.js:806 | | keep |
++| DELETE | /api/admin/admins/:id | server/admin/routes.js:825 | | keep |
++| GET | /api/admin/ai/explorer/:userId | server/admin/routes.js:580 | | keep |
++| GET | /api/admin/ai/overviews | server/admin/routes.js:617 | | keep |
++| GET | /api/admin/ai/status | server/admin/routes.js:569 | | keep |
++| POST | /api/admin/ai/streamer/:userId/overview | server/admin/routes.js:626 | | keep |
++| GET | /api/admin/ai/usage | server/admin/routes.js:522 | | keep |
++| POST | /api/admin/ai/viewers/:userId/:action | server/admin/routes.js:550 | | keep |
++| GET | /api/admin/ai/viewers/:userId/log | server/admin/routes.js:560 | | keep |
++| GET | /api/admin/ai/viewers/status | server/admin/routes.js:532 | | keep |
++| GET | /api/admin/analytics | server/index.js:709 | | keep |
++| GET | /api/admin/analytics/bots | server/index.js:718 | | keep |
++| GET | /api/admin/bans | server/admin/routes.js:429 | | keep |
++| POST | /api/admin/broadcast | server/index.js:826 | | keep |
++| PUT | /api/admin/channels/:id/force-nsfw | server/admin/routes.js:370 | | keep |
| GET | /api/admin/diagnostics | server/admin/routes.js:55 | | keep |
--| DELETE | /api/admin/media-tools/cookies | server/admin/routes.js:1242 | | keep |
--| PUT | /api/admin/media-tools/cookies | server/admin/routes.js:1161 | | keep |
--| POST | /api/admin/media-tools/cookies/check | server/admin/routes.js:1220 | | keep |
--| DELETE | /api/admin/media-tools/extra-args | server/admin/routes.js:1275 | | keep |
--| PUT | /api/admin/media-tools/extra-args | server/admin/routes.js:1256 | | keep |
--| GET | /api/admin/media-tools/status | server/admin/routes.js:1116 | | keep |
--| POST | /api/admin/media-tools/test | server/admin/routes.js:1286 | | keep |
--| GET | /api/admin/moderators | server/admin/routes.js:723 | | keep |
--| POST | /api/admin/moderators | server/admin/routes.js:735 | | keep |
--| DELETE | /api/admin/moderators/:id | server/admin/routes.js:762 | | keep |
--| GET | /api/admin/money | server/admin/routes.js:481 | | keep |
--| POST | /api/admin/money/actions/:id/resolve | server/admin/routes.js:495 | | keep |
--| POST | /api/admin/money/freeze | server/admin/routes.js:489 | | keep |
++| DELETE | /api/admin/media-tools/cookies | server/admin/routes.js:1250 | | keep |
++| PUT | /api/admin/media-tools/cookies | server/admin/routes.js:1169 | | keep |
++| POST | /api/admin/media-tools/cookies/check | server/admin/routes.js:1228 | | keep |
++| DELETE | /api/admin/media-tools/extra-args | server/admin/routes.js:1283 | | keep |
++| PUT | /api/admin/media-tools/extra-args | server/admin/routes.js:1264 | | keep |
++| GET | /api/admin/media-tools/status | server/admin/routes.js:1124 | | keep |
++| POST | /api/admin/media-tools/test | server/admin/routes.js:1294 | | keep |
++| GET | /api/admin/moderators | server/admin/routes.js:731 | | keep |
++| POST | /api/admin/moderators | server/admin/routes.js:743 | | keep |
++| DELETE | /api/admin/moderators/:id | server/admin/routes.js:770 | | keep |
++| GET | /api/admin/money | server/admin/routes.js:483 | | keep |
++| POST | /api/admin/money/actions/:id/resolve | server/admin/routes.js:497 | | keep |
++| POST | /api/admin/money/freeze | server/admin/routes.js:491 | | keep |
| PUT | /api/admin/openre/managed/:id/ingest-authority | server/openre/routes.js:35 | | keep |
| GET | /api/admin/openre/status | server/openre/routes.js:18 | | keep |
--| GET | /api/admin/settings | server/admin/routes.js:508 | | keep |
--| PUT | /api/admin/settings | server/admin/routes.js:633 | | keep |
--| DELETE | /api/admin/settings/:key | server/admin/routes.js:706 | | keep |
--| PUT | /api/admin/settings/:key | server/admin/routes.js:689 | | keep |
++| GET | /api/admin/settings | server/admin/routes.js:510 | | keep |
++| PUT | /api/admin/settings | server/admin/routes.js:641 | | keep |
++| DELETE | /api/admin/settings/:key | server/admin/routes.js:714 | | keep |
++| PUT | /api/admin/settings/:key | server/admin/routes.js:697 | | keep |
| GET | /api/admin/stats | server/admin/routes.js:67 | | keep |
--| GET | /api/admin/storage | server/admin/routes.js:961 | | keep |
--| DELETE | /api/admin/storage/clips/bulk | server/admin/routes.js:1066 | | keep |
--| GET | /api/admin/storage/vods | server/admin/routes.js:1016 | | keep |
--| DELETE | /api/admin/storage/vods/bulk | server/admin/routes.js:1035 | | keep |
--| GET | /api/admin/streams | server/admin/routes.js:303 | | keep |
--| DELETE | /api/admin/streams/:id | server/admin/routes.js:322 | | keep |
--| PUT | /api/admin/streams/:id/nsfw | server/admin/routes.js:416 | | keep |
--| GET | /api/admin/users | server/admin/routes.js:119 | | keep |
--| PUT | /api/admin/users/:id | server/admin/routes.js:156 | | keep |
--| DELETE | /api/admin/users/:id/ban | server/admin/routes.js:284 | | keep |
--| POST | /api/admin/users/:id/ban | server/admin/routes.js:246 | | keep |
--| PUT | /api/admin/users/:id/force-vod-recording | server/admin/routes.js:385 | | keep |
--| GET | /api/admin/verification-keys | server/admin/routes.js:839 | | keep |
--| POST | /api/admin/verification-keys | server/admin/routes.js:849 | | keep |
--| DELETE | /api/admin/verification-keys/:id | server/admin/routes.js:892 | | keep |
--| GET | /api/admin/vpn-queue | server/admin/routes.js:443 | | keep |
--| PUT | /api/admin/vpn-queue/:id | server/admin/routes.js:459 | | keep |
++| GET | /api/admin/storage | server/admin/routes.js:969 | | keep |
++| DELETE | /api/admin/storage/clips/bulk | server/admin/routes.js:1074 | | keep |
++| GET | /api/admin/storage/vods | server/admin/routes.js:1024 | | keep |
++| DELETE | /api/admin/storage/vods/bulk | server/admin/routes.js:1043 | | keep |
++| GET | /api/admin/streams | server/admin/routes.js:305 | | keep |
++| DELETE | /api/admin/streams/:id | server/admin/routes.js:324 | | keep |
++| PUT | /api/admin/streams/:id/nsfw | server/admin/routes.js:418 | | keep |
++| GET | /api/admin/users | server/admin/routes.js:121 | | keep |
++| PUT | /api/admin/users/:id | server/admin/routes.js:158 | | keep |
++| DELETE | /api/admin/users/:id/ban | server/admin/routes.js:286 | | keep |
++| POST | /api/admin/users/:id/ban | server/admin/routes.js:248 | | keep |
++| PUT | /api/admin/users/:id/force-vod-recording | server/admin/routes.js:387 | | keep |
++| GET | /api/admin/verification-keys | server/admin/routes.js:847 | | keep |
++| POST | /api/admin/verification-keys | server/admin/routes.js:857 | | keep |
++| DELETE | /api/admin/verification-keys/:id | server/admin/routes.js:900 | | keep |
++| GET | /api/admin/vpn-queue | server/admin/routes.js:445 | | keep |
++| PUT | /api/admin/vpn-queue/:id | server/admin/routes.js:461 | | keep |
| POST | /api/ai-viewers/${cmd} | server/ai/viewers/routes.js:117 | | keep |
| DELETE | /api/ai-viewers/bots/:id | server/ai/viewers/routes.js:220 | | keep |
| PATCH | /api/ai-viewers/bots/:id | server/ai/viewers/routes.js:185 | | keep |
@@@ -151,27 +151,27 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/arena/status | server/arena/routes.js:30 | | keep |
| GET | /api/arena/voice/:user | server/arena/routes.js:122 | | keep |
| POST | /api/auth/avatar | server/auth/routes.js:192 | | keep |
--| GET | /api/auth/avatar/history | server/auth/routes.js:246 | | keep |
--| GET | /api/auth/callback | server/auth/routes.js:488 | | keep |
++| GET | /api/auth/avatar/history | server/auth/routes.js:248 | | keep |
++| GET | /api/auth/callback | server/auth/routes.js:491 | | keep |
| POST | /api/auth/change-password | server/auth/routes.js:166 | | keep |
--| POST | /api/auth/fedcm | server/auth/routes.js:465 | | keep |
--| GET | /api/auth/ice-servers | server/auth/routes.js:900 | | keep |
++| POST | /api/auth/fedcm | server/auth/routes.js:468 | | keep |
++| GET | /api/auth/ice-servers | server/auth/routes.js:903 | | keep |
| POST | /api/auth/login | server/auth/routes.js:97 | | keep |
--| GET | /api/auth/logout | server/auth/routes.js:627 | | keep |
--| POST | /api/auth/logout | server/auth/routes.js:620 | | keep |
++| GET | /api/auth/logout | server/auth/routes.js:630 | | keep |
++| POST | /api/auth/logout | server/auth/routes.js:623 | | keep |
| GET | /api/auth/me | server/auth/routes.js:102 | | keep |
--| GET | /api/auth/preferences | server/auth/routes.js:679 | | keep |
--| PUT | /api/auth/preferences | server/auth/routes.js:689 | | keep |
++| GET | /api/auth/preferences | server/auth/routes.js:682 | | keep |
++| PUT | /api/auth/preferences | server/auth/routes.js:692 | | keep |
| PUT | /api/auth/profile | server/auth/routes.js:110 | | keep |
--| POST | /api/auth/refresh | server/auth/routes.js:558 | | keep |
++| POST | /api/auth/refresh | server/auth/routes.js:561 | | keep |
| POST | /api/auth/register | server/auth/routes.js:92 | | keep |
--| GET | /api/auth/sso/login | server/auth/routes.js:312 | | keep |
--| GET | /api/auth/sso/status | server/auth/routes.js:638 | | keep |
++| GET | /api/auth/sso/login | server/auth/routes.js:315 | | keep |
++| GET | /api/auth/sso/status | server/auth/routes.js:641 | | keep |
| GET | /api/auth/stream-key | server/auth/routes.js:171 | | keep |
| POST | /api/auth/stream-key/regenerate | server/auth/routes.js:176 | | keep |
--| GET | /api/auth/tokens | server/auth/routes.js:859 | | keep |
--| POST | /api/auth/tokens | server/auth/routes.js:821 | | keep |
--| DELETE | /api/auth/tokens/:id | server/auth/routes.js:879 | | keep |
++| GET | /api/auth/tokens | server/auth/routes.js:862 | | keep |
++| POST | /api/auth/tokens | server/auth/routes.js:824 | | keep |
++| DELETE | /api/auth/tokens/:id | server/auth/routes.js:882 | | keep |
| GET | /api/auth/user/:username | server/auth/routes.js:183 | | keep |
| GET | /api/channels/:channelId/moderation | server/admin/channel-mod-routes.js:157 | OpenVibe.Chat | extract |
| PUT | /api/channels/:channelId/moderation | server/admin/channel-mod-routes.js:170 | OpenVibe.Chat | extract |
@@@ -184,13 +184,13 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/channels/moderation/mine | server/admin/channel-mod-routes.js:49 | OpenVibe.Chat | extract |
| GET | /api/chat-ai/anon/:anonId | server/ai/chat-ai-routes.js:83 | | keep |
| GET | /api/chat-ai/global | server/ai/chat-ai-routes.js:14 | | keep |
--| GET | /api/chat-ai/live-captions/:username | server/ai/chat-ai-routes.js:230 | | keep |
++| GET | /api/chat-ai/live-captions/:username | server/ai/chat-ai-routes.js:236 | | keep |
| GET | /api/chat-ai/relay/:platform/:username | server/ai/chat-ai-routes.js:95 | | keep |
| GET | /api/chat-ai/timeline | server/ai/chat-ai-routes.js:24 | | keep |
| GET | /api/chat-ai/timeline/:username | server/ai/chat-ai-routes.js:174 | | keep |
--| GET | /api/chat-ai/transcript/:streamId | server/ai/chat-ai-routes.js:329 | | keep |
++| GET | /api/chat-ai/transcript/:streamId | server/ai/chat-ai-routes.js:335 | | keep |
| GET | /api/chat-ai/user/:id | server/ai/chat-ai-routes.js:39 | | keep |
--| GET | /api/chat-ai/vod-transcripts | server/ai/chat-ai-routes.js:267 | | keep |
++| GET | /api/chat-ai/vod-transcripts | server/ai/chat-ai-routes.js:273 | | keep |
| GET | /api/chat/:streamId/history | server/chat/routes.js:509 | OpenVibe.Chat | shadowed |
| GET | /api/chat/:streamId/replay | server/chat/routes.js:487 | OpenVibe.Chat | shadowed |
| GET | /api/chat/:streamId/users | server/chat/routes.js:633 | OpenVibe.Chat | shadowed |
@@@ -212,17 +212,17 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/chat/send | server/chat/routes.js:209 | OpenVibe.Chat | shadowed |
| GET | /api/chat/user/:userId/history | server/chat/routes.js:341 | OpenVibe.Chat | shadowed |
| GET | /api/chat/user/:username/profile | server/chat/routes.js:360 | OpenVibe.Chat | shadowed |
--| GET | /api/clips | server/media-proxy/clips.js:166 | OpenVibe.Media | adapter |
--| DELETE | /api/clips/:id | server/media-proxy/clips.js:335 | OpenVibe.Media | adapter |
--| GET | /api/clips/:id | server/media-proxy/clips.js:195 | OpenVibe.Media | adapter |
--| POST | /api/clips/:id/recut | server/media-proxy/clips.js:354 | OpenVibe.Media | adapter |
--| PUT | /api/clips/:id/title | server/media-proxy/clips.js:269 | OpenVibe.Media | adapter |
--| PUT | /api/clips/:id/visibility | server/media-proxy/clips.js:286 | OpenVibe.Media | adapter |
--| POST | /api/clips/bulk | server/media-proxy/clips.js:310 | OpenVibe.Media | adapter |
--| GET | /api/clips/mine | server/media-proxy/clips.js:118 | OpenVibe.Media | adapter |
--| GET | /api/clips/my-stream | server/media-proxy/clips.js:132 | OpenVibe.Media | adapter |
--| GET | /api/clips/settings/channel | server/media-proxy/clips.js:144 | OpenVibe.Media | adapter |
--| PUT | /api/clips/settings/channel | server/media-proxy/clips.js:153 | OpenVibe.Media | adapter |
++| GET | /api/clips | server/media-proxy/clips.js:168 | OpenVibe.Media | adapter |
++| DELETE | /api/clips/:id | server/media-proxy/clips.js:337 | OpenVibe.Media | adapter |
++| GET | /api/clips/:id | server/media-proxy/clips.js:197 | OpenVibe.Media | adapter |
++| POST | /api/clips/:id/recut | server/media-proxy/clips.js:356 | OpenVibe.Media | adapter |
++| PUT | /api/clips/:id/title | server/media-proxy/clips.js:271 | OpenVibe.Media | adapter |
++| PUT | /api/clips/:id/visibility | server/media-proxy/clips.js:288 | OpenVibe.Media | adapter |
++| POST | /api/clips/bulk | server/media-proxy/clips.js:312 | OpenVibe.Media | adapter |
++| GET | /api/clips/mine | server/media-proxy/clips.js:120 | OpenVibe.Media | adapter |
++| GET | /api/clips/my-stream | server/media-proxy/clips.js:134 | OpenVibe.Media | adapter |
++| GET | /api/clips/settings/channel | server/media-proxy/clips.js:146 | OpenVibe.Media | adapter |
++| PUT | /api/clips/settings/channel | server/media-proxy/clips.js:155 | OpenVibe.Media | adapter |
| POST | /api/coins/admin/grant | server/monetization/coins-routes.js:310 | | keep |
| GET | /api/coins/balance | server/monetization/coins-routes.js:26 | | keep |
| POST | /api/coins/bonus | server/monetization/coins-routes.js:70 | | keep |
@@@ -277,7 +277,7 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/cosmetics/internal-unlock | server/monetization/cosmetics-routes.js:91 | | keep |
| GET | /api/cosmetics/inventory | server/monetization/cosmetics-routes.js:32 | | keep |
| POST | /api/cosmetics/unequip | server/monetization/cosmetics-routes.js:55 | | keep |
--| POST | /api/csp-report | server/index.js:845 | | keep |
++| POST | /api/csp-report | server/index.js:847 | | keep |
| GET | /api/dm/blocks | server/chat/dm-routes.js:401 | OpenVibe.Chat | shadowed |
| DELETE | /api/dm/blocks/:userId | server/chat/dm-routes.js:389 | OpenVibe.Chat | shadowed |
| POST | /api/dm/blocks/:userId | server/chat/dm-routes.js:374 | OpenVibe.Chat | shadowed |
@@@ -327,22 +327,22 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/funds/leaderboard/:streamId | server/monetization/routes.js:233 | OpenVibe.Tips | extract |
| POST | /api/funds/purchase | server/monetization/routes.js:42 | OpenVibe.Tips | extract |
| POST | /api/funds/recycle | server/monetization/routes.js:206 | OpenVibe.Tips | extract |
--| GET | /api/health | server/index.js:726 | | keep |
--| GET | /api/home/digest | server/home/routes.js:457 | | keep |
--| GET | /api/home/discover | server/home/routes.js:507 | | keep |
--| GET | /api/home/featured | server/home/routes.js:247 | | keep |
--| GET | /api/home/hero | server/home/routes.js:333 | | keep |
--| GET | /api/home/pulse | server/home/routes.js:406 | | keep |
--| GET | /api/home/star | server/home/routes.js:352 | | keep |
--| POST | /api/home/star/rotate | server/home/routes.js:569 | | keep |
--| GET | /api/home/stats-live | server/home/routes.js:287 | | keep |
--| GET | /api/home/stats/series/:metric | server/home/routes.js:177 | | keep |
++| GET | /api/health | server/index.js:728 | | keep |
++| GET | /api/home/digest | server/home/routes.js:437 | | keep |
++| GET | /api/home/discover | server/home/routes.js:487 | | keep |
++| GET | /api/home/featured | server/home/routes.js:227 | | keep |
++| GET | /api/home/hero | server/home/routes.js:313 | | keep |
++| GET | /api/home/pulse | server/home/routes.js:386 | | keep |
++| GET | /api/home/star | server/home/routes.js:332 | | keep |
++| POST | /api/home/star/rotate | server/home/routes.js:549 | | keep |
++| GET | /api/home/stats-live | server/home/routes.js:267 | | keep |
++| GET | /api/home/stats/series/:metric | server/home/routes.js:166 | | keep |
| GET | /api/i18n/languages | server/i18n/routes.js:31 | | keep |
| POST | /api/i18n/translate | server/i18n/routes.js:36 | | keep |
| GET | /api/img-proxy | server/media/external-image-proxy.js:31 | | keep |
| GET | /api/kiosk/favicon | server/kiosk/routes.js:122 | | keep |
| GET | /api/kiosk/site | server/kiosk/routes.js:77 | | keep |
--| GET | /api/live-events | server/index.js:649 | | keep |
++| GET | /api/live-events | server/index.js:651 | | keep |
| POST | /api/media/advance | server/media/routes.js:267 | | keep |
| GET | /api/media/channel/:username | server/media/routes.js:52 | | keep |
| GET | /api/media/downloader/status | server/media/routes.js:418 | | keep |
@@@ -446,7 +446,7 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/powerchat/test-tip | server/integrations/powerchat-routes.js:350 | OpenVibe.Billing | extract |
| GET | /api/powerchat/tip-link | server/integrations/powerchat-routes.js:291 | OpenVibe.Billing | extract |
| POST | /api/powerchat/webhook | server/integrations/powerchat-routes.js:442 | OpenVibe.Billing | extract |
--| GET | /api/ready | server/index.js:764 | | keep |
++| GET | /api/ready | server/index.js:766 | | keep |
| GET | /api/recap/:streamId | server/recap/routes.js:21 | | keep |
| POST | /api/recap/:streamId/regenerate | server/recap/routes.js:43 | | keep |
| GET | /api/recap/channel/:username | server/recap/routes.js:14 | | keep |
@@@ -481,53 +481,53 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/sounds/channel/:userId | server/chat/sounds-routes.js:125 | OpenVibe.Chat | shadowed |
| PATCH | /api/sounds/command | server/chat/sounds-routes.js:313 | OpenVibe.Chat | shadowed |
| GET | /api/sounds/file/:filename | server/chat/sounds-routes.js:371 | OpenVibe.Chat | shadowed |
--| GET | /api/streams | server/streaming/routes.js:1086 | | keep |
--| POST | /api/streams | server/streaming/routes.js:1908 | | keep |
--| DELETE | /api/streams/:id | server/streaming/routes.js:2103 | | keep |
--| GET | /api/streams/:id | server/streaming/routes.js:1860 | | keep |
--| PUT | /api/streams/:id | server/streaming/routes.js:2052 | | keep |
--| GET | /api/streams/:id/call | server/streaming/routes.js:2422 | | keep |
--| PUT | /api/streams/:id/call | server/streaming/routes.js:2383 | | keep |
--| GET | /api/streams/:id/endpoint | server/streaming/routes.js:2150 | | keep |
--| POST | /api/streams/:id/follow | server/streaming/routes.js:2291 | | keep |
--| POST | /api/streams/:id/heartbeat | server/streaming/routes.js:2248 | | keep |
--| GET | /api/streams/:id/rtmp-status | server/streaming/routes.js:2266 | | keep |
--| GET | /api/streams/broadcast-settings | server/streaming/routes.js:1385 | | keep |
--| PUT | /api/streams/broadcast-settings | server/streaming/routes.js:1402 | | keep |
--| GET | /api/streams/channel | server/streaming/routes.js:638 | | keep |
--| PUT | /api/streams/channel | server/streaming/routes.js:650 | | keep |
++| GET | /api/streams | server/streaming/routes.js:1093 | | keep |
++| POST | /api/streams | server/streaming/routes.js:1924 | | keep |
++| DELETE | /api/streams/:id | server/streaming/routes.js:2119 | | keep |
++| GET | /api/streams/:id | server/streaming/routes.js:1876 | | keep |
++| PUT | /api/streams/:id | server/streaming/routes.js:2068 | | keep |
++| GET | /api/streams/:id/call | server/streaming/routes.js:2438 | | keep |
++| PUT | /api/streams/:id/call | server/streaming/routes.js:2399 | | keep |
++| GET | /api/streams/:id/endpoint | server/streaming/routes.js:2166 | | keep |
++| POST | /api/streams/:id/follow | server/streaming/routes.js:2307 | | keep |
++| POST | /api/streams/:id/heartbeat | server/streaming/routes.js:2264 | | keep |
++| GET | /api/streams/:id/rtmp-status | server/streaming/routes.js:2282 | | keep |
++| GET | /api/streams/broadcast-settings | server/streaming/routes.js:1393 | | keep |
++| PUT | /api/streams/broadcast-settings | server/streaming/routes.js:1410 | | keep |
++| GET | /api/streams/channel | server/streaming/routes.js:645 | | keep |
++| PUT | /api/streams/channel | server/streaming/routes.js:657 | | keep |
| GET | /api/streams/channel/:username | server/streaming/routes.js:207 | | keep |
--| PUT | /api/streams/channel/:username/about | server/streaming/routes.js:765 | | keep |
--| GET | /api/streams/channel/:username/bio-en | server/streaming/routes.js:746 | | keep |
--| GET | /api/streams/channel/:username/clips-taken | server/streaming/routes.js:557 | | keep |
--| POST | /api/streams/channel/:username/follow | server/streaming/routes.js:2336 | | keep |
--| GET | /api/streams/channel/:username/live | server/streaming/routes.js:600 | | keep |
--| GET | /api/streams/channel/:username/popular | server/streaming/routes.js:531 | | keep |
--| GET | /api/streams/channel/:username/resolve/:ref | server/streaming/routes.js:1424 | | keep |
--| GET | /api/streams/channel/:username/weather | server/streaming/routes.js:975 | | keep |
--| POST | /api/streams/channel/offline-screen | server/streaming/routes.js:871 | | keep |
--| POST | /api/streams/diag-log | server/streaming/routes.js:2241 | | keep |
--| POST | /api/streams/goal-media | server/streaming/routes.js:836 | | keep |
--| GET | /api/streams/managed | server/streaming/routes.js:1578 | | keep |
--| POST | /api/streams/managed | server/streaming/routes.js:1590 | | keep |
--| DELETE | /api/streams/managed/:id | server/streaming/routes.js:1804 | | keep |
--| PUT | /api/streams/managed/:id | server/streaming/routes.js:1644 | | keep |
--| POST | /api/streams/managed/:id/regenerate-key | server/streaming/routes.js:1829 | | keep |
--| GET | /api/streams/managed/:managedStreamId/history | server/streaming/routes.js:1458 | | keep |
--| GET | /api/streams/managed/:managedStreamId/profile | server/streaming/routes.js:1472 | | keep |
--| GET | /api/streams/mine | server/streaming/routes.js:1122 | | keep |
--| POST | /api/streams/panel-image | server/streaming/routes.js:814 | | keep |
--| GET | /api/streams/recent | server/streaming/routes.js:1134 | | keep |
--| GET | /api/streams/recent-vods | server/streaming/routes.js:1204 | | keep |
--| GET | /api/streams/recently-online | server/streaming/routes.js:1150 | | keep |
--| GET | /api/streams/rtmp-proxy/:streamId.flv | server/streaming/routes.js:2443 | | keep |
--| GET | /api/streams/setup-progress | server/streaming/routes.js:1524 | | keep |
--| GET | /api/streams/voice-channels | server/streaming/routes.js:1234 | | keep |
--| POST | /api/streams/voice-channels | server/streaming/routes.js:1255 | | keep |
--| DELETE | /api/streams/voice-channels/:channelId | server/streaming/routes.js:1267 | | keep |
--| GET | /api/streams/voice-channels/:channelId | server/streaming/routes.js:1244 | | keep |
--| POST | /api/streams/voice-channels/call-user | server/streaming/routes.js:1279 | | keep |
--| POST | /api/streams/voice-channels/call-user/respond | server/streaming/routes.js:1348 | | keep |
++| PUT | /api/streams/channel/:username/about | server/streaming/routes.js:772 | | keep |
++| GET | /api/streams/channel/:username/bio-en | server/streaming/routes.js:753 | | keep |
++| GET | /api/streams/channel/:username/clips-taken | server/streaming/routes.js:564 | | keep |
++| POST | /api/streams/channel/:username/follow | server/streaming/routes.js:2352 | | keep |
++| GET | /api/streams/channel/:username/live | server/streaming/routes.js:607 | | keep |
++| GET | /api/streams/channel/:username/popular | server/streaming/routes.js:538 | | keep |
++| GET | /api/streams/channel/:username/resolve/:ref | server/streaming/routes.js:1432 | | keep |
++| GET | /api/streams/channel/:username/weather | server/streaming/routes.js:982 | | keep |
++| POST | /api/streams/channel/offline-screen | server/streaming/routes.js:878 | | keep |
++| POST | /api/streams/diag-log | server/streaming/routes.js:2257 | | keep |
++| POST | /api/streams/goal-media | server/streaming/routes.js:843 | | keep |
++| GET | /api/streams/managed | server/streaming/routes.js:1594 | | keep |
++| POST | /api/streams/managed | server/streaming/routes.js:1606 | | keep |
++| DELETE | /api/streams/managed/:id | server/streaming/routes.js:1820 | | keep |
++| PUT | /api/streams/managed/:id | server/streaming/routes.js:1660 | | keep |
++| POST | /api/streams/managed/:id/regenerate-key | server/streaming/routes.js:1845 | | keep |
++| GET | /api/streams/managed/:managedStreamId/history | server/streaming/routes.js:1466 | | keep |
++| GET | /api/streams/managed/:managedStreamId/profile | server/streaming/routes.js:1487 | | keep |
++| GET | /api/streams/mine | server/streaming/routes.js:1129 | | keep |
++| POST | /api/streams/panel-image | server/streaming/routes.js:821 | | keep |
++| GET | /api/streams/recent | server/streaming/routes.js:1141 | | keep |
++| GET | /api/streams/recent-vods | server/streaming/routes.js:1212 | | keep |
++| GET | /api/streams/recently-online | server/streaming/routes.js:1158 | | keep |
++| GET | /api/streams/rtmp-proxy/:streamId.flv | server/streaming/routes.js:2459 | | keep |
++| GET | /api/streams/setup-progress | server/streaming/routes.js:1539 | | keep |
++| GET | /api/streams/voice-channels | server/streaming/routes.js:1242 | | keep |
++| POST | /api/streams/voice-channels | server/streaming/routes.js:1263 | | keep |
++| DELETE | /api/streams/voice-channels/:channelId | server/streaming/routes.js:1275 | | keep |
++| GET | /api/streams/voice-channels/:channelId | server/streaming/routes.js:1252 | | keep |
++| POST | /api/streams/voice-channels/call-user | server/streaming/routes.js:1287 | | keep |
++| POST | /api/streams/voice-channels/call-user/respond | server/streaming/routes.js:1356 | | keep |
| GET | /api/themes | server/themes/routes.js:20 | OpenVibe.Network | extract |
| POST | /api/themes | server/themes/routes.js:108 | OpenVibe.Network | extract |
| DELETE | /api/themes/:id | server/themes/routes.js:147 | OpenVibe.Network | extract |
@@@ -548,7 +548,7 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/tts/audio/:file | server/chat/tts-routes.js:125 | OpenVibe.Chat | shadowed |
| GET | /api/tts/settings | server/chat/tts-routes.js:43 | OpenVibe.Chat | shadowed |
| GET | /api/tts/voices | server/chat/tts-routes.js:33 | OpenVibe.Chat | shadowed |
--| GET | /api/updates | server/index.js:811 | | keep |
++| GET | /api/updates | server/index.js:813 | | keep |
| GET | /api/vibe-coding/channel/:username/:slotIdOrSlug/events | server/vibe-coding/routes.js:17 | OpenVibe.Codes | extract |
| GET | /api/vibe-coding/managed/:managedStreamId/events | server/vibe-coding/routes.js:47 | OpenVibe.Codes | extract |
| GET | /api/vibe-coding/managed/:managedStreamId/settings | server/vibe-coding/routes.js:74 | OpenVibe.Codes | extract |
@@@ -572,15 +572,15 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/vods/stream/:streamId/finalize | server/media-proxy/vods.js:237 | OpenVibe.Media | adapter |
| GET | /api/vods/stream/:streamId/live | server/media-proxy/vods.js:257 | OpenVibe.Media | adapter |
| POST | /api/vods/upload | server/media-proxy/vods.js:599 | OpenVibe.Media | adapter |
--| GET | /banned | server/index.js:979 | | keep |
--| POST | /banned/continue | server/index.js:949 | | keep |
--| GET | /canvas | server/index.js:682 | OpenVibe.Games | compat |
--| GET | /data/pastes/screenshots/:filename | server/index.js:600 | | keep |
--| GET | /dmca | server/index.js:888 | | keep |
++| GET | /banned | server/index.js:985 | | keep |
++| POST | /banned/continue | server/index.js:955 | | keep |
++| GET | /canvas | server/index.js:684 | OpenVibe.Games | compat |
++| GET | /data/pastes/screenshots/:filename | server/index.js:602 | | keep |
++| GET | /dmca | server/index.js:894 | | keep |
| GET | /docs | server/docs/routes.js:304 | | keep |
| GET | /docs/:name | server/docs/routes.js:306 | | keep |
| GET | /docs/:name.md | server/docs/routes.js:305 | | keep |
--| GET | /game | server/index.js:681 | OpenVibe.Games | compat |
++| GET | /game | server/index.js:683 | OpenVibe.Games | compat |
| GET | /internal/analytics-summary | server/index.js:562 | | keep |
| POST | /internal/chat-context/ai/mod-command | server/chat/live-context-routes.js:459 | | keep |
| POST | /internal/chat-context/alert-sound | server/chat/live-context-routes.js:375 | | keep |
@@@ -667,6 +667,8 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /internal/chat-effects/viewer-counts | server/chat/live-context-routes.js:293 | | keep |
| POST | /internal/chat-effects/viewer-snapshots | server/chat/live-context-routes.js:300 | | keep |
| GET | /internal/followers | server/streaming/followers-internal.js:12 | | keep |
++| GET | /internal/lineage/resolve | server/lineage/routes.js:33 | | keep |
++| POST | /internal/lineage/resolve | server/lineage/routes.js:34 | | keep |
| POST | /internal/media-events | server/index.js:554 | | keep |
| POST | /internal/media-webhook | server/index.js:552 | OpenVibe.Events | compat |
| POST | /internal/openre-events | server/index.js:557 | | keep |
@@@ -674,23 +676,23 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /internal/url-registry/refresh | server/internal/routes.js:28 | OpenVibe.Network | compat |
| POST | /internal/user-avatar | server/internal/routes.js:46 | OpenVibe.Network | compat |
| POST | /internal/user-role | server/internal/routes.js:71 | OpenVibe.Network | compat |
--| GET | /media/:username | server/index.js:883 | | keep |
--| GET | /obs/chat/:username | server/index.js:871 | | keep |
++| GET | /media/:username | server/index.js:885 | | keep |
++| GET | /obs/chat/:username | server/index.js:873 | | keep |
| GET | /openvibe-sw.js | server/index.js:455 | | keep |
--| GET | /overlay/chat/:username | server/index.js:879 | | keep |
--| GET | /overlay/chat/:username/:slotIdOrSlug | server/index.js:876 | | keep |
--| GET | /p/:slug | server/index.js:618 | OpenVibe.Community | adapter |
--| GET | /p/:slug/raw | server/index.js:629 | OpenVibe.Community | adapter |
--| GET | /p/:slug/screenshot | server/index.js:625 | OpenVibe.Community | adapter |
--| GET | /pastes | server/index.js:619 | OpenVibe.Community | adapter |
--| GET | /privacy | server/index.js:897 | | keep |
--| GET | /release.json | server/index.js:751 | | keep |
--| GET | /sitemap.xml | server/seo/seo.js:597 | | keep |
--| GET | /terms | server/index.js:894 | | keep |
--| GET | /tos | server/index.js:891 | | keep |
--| POST | /whip/:streamId | server/index.js:906 | OpenRe.Stream | extract |
--| DELETE | /whip/:streamId/:resourceId | server/index.js:908 | OpenRe.Stream | extract |
--| PATCH | /whip/:streamId/:resourceId | server/index.js:907 | OpenRe.Stream | extract |
++| GET | /overlay/chat/:username | server/index.js:881 | | keep |
++| GET | /overlay/chat/:username/:slotIdOrSlug | server/index.js:878 | | keep |
++| GET | /p/:slug | server/index.js:620 | OpenVibe.Community | adapter |
++| GET | /p/:slug/raw | server/index.js:631 | OpenVibe.Community | adapter |
++| GET | /p/:slug/screenshot | server/index.js:627 | OpenVibe.Community | adapter |
++| GET | /pastes | server/index.js:621 | OpenVibe.Community | adapter |
++| GET | /privacy | server/index.js:903 | | keep |
++| GET | /release.json | server/index.js:753 | | keep |
++| GET | /sitemap.xml | server/seo/seo.js:602 | | keep |
++| GET | /terms | server/index.js:900 | | keep |
++| GET | /tos | server/index.js:897 | | keep |
++| POST | /whip/:streamId | server/index.js:912 | OpenRe.Stream | extract |
++| DELETE | /whip/:streamId/:resourceId | server/index.js:914 | OpenRe.Stream | extract |
++| PATCH | /whip/:streamId/:resourceId | server/index.js:913 | OpenRe.Stream | extract |
## OpenVibe.Network
@@@ -715,7 +717,7 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/admin/domains/catalog | server/domains/routes.js:206 | | keep |
| POST | /api/admin/domains/check | server/domains/routes.js:217 | | keep |
| GET | /api/admin/ssh-info | server/index.js:510 | | keep |
--| GET | /api/auth/anon-identities | server/auth/routes.js:641 | | keep |
++| GET | /api/auth/anon-identities | server/auth/routes.js:647 | | keep |
| POST | /api/auth/anon-session | server/auth/routes.js:518 | | keep |
| GET | /api/auth/anon/:token | server/auth/routes.js:588 | | keep |
| POST | /api/auth/anon/:token/link | server/auth/routes.js:625 | | keep |
@@@ -737,13 +739,13 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/auth/register | server/auth/routes.js:90 | | keep |
| POST | /api/auth/reset-password | server/auth/routes.js:256 | | keep |
| GET | /api/auth/reset-password/validate | server/auth/routes.js:240 | | keep |
--| DELETE | /api/auth/sessions | server/auth/routes.js:723 | | keep |
--| GET | /api/auth/sessions | server/auth/routes.js:679 | | keep |
--| POST | /api/auth/sessions | server/auth/routes.js:692 | | keep |
--| DELETE | /api/auth/sessions/:id | server/auth/routes.js:714 | | keep |
--| GET | /api/auth/users/:id/card | server/auth/routes.js:734 | | keep |
--| DELETE | /api/auth/users/:id/follow | server/auth/routes.js:817 | | keep |
--| POST | /api/auth/users/:id/follow | server/auth/routes.js:786 | | keep |
++| DELETE | /api/auth/sessions | server/auth/routes.js:729 | | keep |
++| GET | /api/auth/sessions | server/auth/routes.js:685 | | keep |
++| POST | /api/auth/sessions | server/auth/routes.js:698 | | keep |
++| DELETE | /api/auth/sessions/:id | server/auth/routes.js:720 | | keep |
++| GET | /api/auth/users/:id/card | server/auth/routes.js:740 | | keep |
++| DELETE | /api/auth/users/:id/follow | server/auth/routes.js:823 | | keep |
++| POST | /api/auth/users/:id/follow | server/auth/routes.js:792 | | keep |
| GET | /api/brand | server/index.js:421 | | keep |
| GET | /api/catalog.json | server/index.js:481 | | keep |
| GET | /api/chrome | server/chrome/service.js:171 | | keep |
@@@ -761,13 +763,14 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/history | server/history/routes.js:108 | | keep |
| DELETE | /api/history/:id | server/history/routes.js:148 | | keep |
| PUT | /api/history/settings | server/history/routes.js:137 | | keep |
--| GET | /api/modules | server/identity/modules.js:101 | | keep |
--| DELETE | /api/modules/:ns | server/identity/modules.js:126 | | keep |
--| GET | /api/modules/:ns | server/identity/modules.js:109 | | keep |
--| PUT | /api/modules/:ns | server/identity/modules.js:117 | | keep |
--| GET | /api/modules/:ns/public/:subject | server/identity/modules.js:93 | | keep |
--| GET | /api/modules/modules/:ns/:subject | server/identity/modules.js:140 | | keep |
--| PUT | /api/modules/modules/:ns/:subject | server/identity/modules.js:149 | | keep |
++| GET | /api/modules | server/identity/modules.js:322 | | keep |
++| DELETE | /api/modules/:ns | server/identity/modules.js:347 | | keep |
++| GET | /api/modules/:ns | server/identity/modules.js:330 | | keep |
++| PUT | /api/modules/:ns | server/identity/modules.js:338 | | keep |
++| GET | /api/modules/:ns/public/:subject | server/identity/modules.js:314 | | keep |
++| DELETE | /api/modules/modules/:ns/:subject | server/identity/modules.js:382 | | keep |
++| GET | /api/modules/modules/:ns/:subject | server/identity/modules.js:362 | | keep |
++| PUT | /api/modules/modules/:ns/:subject | server/identity/modules.js:371 | | keep |
| DELETE | /api/profile/avatar | server/profile/avatar.js:107 | | keep |
| PUT | /api/profile/avatar | server/profile/avatar.js:96 | | keep |
| GET | /api/profile/avatar/:username | server/profile/avatar.js:110 | | keep |
@@@ -949,14 +952,13 @@ Owner = the repository whose code answers the route; target = the authority it b
| Method | Path | Source | Target | Disposition |
|---|---|---|---|---|
| GET | /api/ready | ready.js:15 | | keep |
--| GET | /release.json | release.js:8 | | keep |
| GET | /shared/:file | files.js:9 | | keep |
## OpenVibe.Media
| Method | Path | Source | Target | Disposition |
|---|---|---|---|---|
--| GET | /api/ready | server/observability.js:132 | | keep |
++| GET | /api/ready | server/observability.js:140 | | keep |
| GET | /api/v1/:app/admin/storage | server/admin/routes.js:72 | | keep |
| GET | /api/v1/:app/admin/storage/buckets | server/admin/routes.js:404 | | keep |
| GET | /api/v1/:app/admin/storage/tiers | server/admin/routes.js:258 | | keep |
@@@ -997,9 +999,9 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/v1/:app/pastes/admin/stats | server/pastes/routes.js:341 | OpenVibe.Community | frozen-legacy |
| POST | /api/v1/:app/pastes/bulk | server/pastes/routes.js:384 | OpenVibe.Community | frozen-legacy |
| GET | /api/v1/:app/pastes/config | server/pastes/routes.js:319 | OpenVibe.Community | frozen-legacy |
--| GET | /api/v1/:app/stats | server/index.js:114 | | keep |
--| GET | /api/v1/:app/stats/series/:metric | server/index.js:124 | | keep |
--| POST | /api/v1/:app/thumbnails/:kind/:id | server/thumbnails/routes.js:38 | | keep |
++| GET | /api/v1/:app/stats | server/index.js:115 | | keep |
++| GET | /api/v1/:app/stats/series/:metric | server/index.js:125 | | keep |
++| POST | /api/v1/:app/thumbnails/:kind/:id | server/thumbnails/routes.js:42 | | keep |
| GET | /api/v1/:app/views | server/views/routes.js:39 | | keep |
| POST | /api/v1/:app/views | server/views/routes.js:24 | | keep |
| GET | /api/v1/:app/vods | server/vod/routes.js:273 | | keep |
@@@ -1014,40 +1016,57 @@ Owner = the repository whose code answers the route; target = the authority it b
| POST | /api/v1/:app/vods/:id/ingest/rtp/start | server/vod/routes.js:133 | | keep |
| POST | /api/v1/:app/vods/:id/ingest/rtp/stop | server/vod/routes.js:147 | | keep |
| GET | /api/v1/:app/vods/latest-thumbs | server/vod/routes.js:301 | | keep |
--| GET | /api/v2/:app/objects | server/objects/routes.js:278 | | keep |
--| POST | /api/v2/:app/objects | server/objects/routes.js:188 | | keep |
--| DELETE | /api/v2/:app/objects/:id | server/objects/routes.js:308 | | keep |
--| GET | /api/v2/:app/objects/:id | server/objects/routes.js:303 | | keep |
--| GET | /api/v2/:app/objects/:id | server/objects/routes.js:382 | | keep |
--| POST | /api/v2/:app/objects/:id/complete | server/objects/routes.js:244 | | keep |
++| GET | /api/v2/:app/jobs | server/jobs/routes.js:63 | | keep |
++| POST | /api/v2/:app/jobs | server/jobs/routes.js:76 | | keep |
++| DELETE | /api/v2/:app/jobs/:jobId | server/jobs/routes.js:135 | | keep |
++| GET | /api/v2/:app/jobs/:jobId | server/jobs/routes.js:108 | | keep |
++| POST | /api/v2/:app/jobs/:jobId/approve | server/jobs/routes.js:113 | | keep |
++| POST | /api/v2/:app/jobs/:jobId/cancel | server/jobs/routes.js:134 | | keep |
++| GET | /api/v2/:app/objects | server/objects/routes.js:497 | | keep |
++| POST | /api/v2/:app/objects | server/objects/routes.js:261 | | keep |
++| DELETE | /api/v2/:app/objects/:id | server/objects/routes.js:527 | | keep |
++| GET | /api/v2/:app/objects/:id | server/objects/routes.js:522 | | keep |
++| GET | /api/v2/:app/objects/:id | server/objects/routes.js:601 | | keep |
++| POST | /api/v2/:app/objects/:id/complete | server/objects/routes.js:371 | | keep |
| PUT | /api/v2/:app/objects/:id/content | server/index.js:35 | | keep |
--| GET | /api/v2/:app/objects/:id/download | server/objects/routes.js:334 | | keep |
--| GET | /api/v2/:app/objects/:id/holds | server/objects/routes.js:353 | | keep |
--| POST | /api/v2/:app/objects/:id/holds | server/objects/routes.js:359 | | keep |
--| DELETE | /api/v2/:app/objects/:id/holds/:holdId | server/objects/routes.js:368 | | keep |
--| POST | /api/v2/:app/objects/:id/restore | server/objects/routes.js:324 | | keep |
++| GET | /api/v2/:app/objects/:id/download | server/objects/routes.js:553 | | keep |
++| GET | /api/v2/:app/objects/:id/holds | server/objects/routes.js:572 | | keep |
++| POST | /api/v2/:app/objects/:id/holds | server/objects/routes.js:578 | | keep |
++| DELETE | /api/v2/:app/objects/:id/holds/:holdId | server/objects/routes.js:587 | | keep |
++| POST | /api/v2/:app/objects/:id/multipart | server/objects/routes.js:411 | | keep |
++| DELETE | /api/v2/:app/objects/:id/multipart/:uploadId | server/objects/routes.js:486 | | keep |
++| GET | /api/v2/:app/objects/:id/multipart/:uploadId | server/objects/routes.js:440 | | keep |
++| POST | /api/v2/:app/objects/:id/multipart/:uploadId/complete | server/objects/routes.js:449 | | keep |
++| PUT | /api/v2/:app/objects/:id/multipart/:uploadId/parts/:n | server/index.js:36 | | keep |
++| POST | /api/v2/:app/objects/:id/restore | server/objects/routes.js:543 | | keep |
++| POST | /api/v2/:app/objects/:id/upload-url | server/objects/routes.js:387 | | keep |
| GET | /auth/callback | server/user-auth.js:281 | | keep |
| POST | /auth/fedcm | server/user-auth.js:327 | | keep |
| GET | /auth/login | server/user-auth.js:259 | | keep |
| GET | /auth/logout | server/user-auth.js:355 | | keep |
| GET | /auth/me | server/user-auth.js:379 | | keep |
| POST | /auth/refresh | server/user-auth.js:389 | | keep |
--| GET | /healthz | server/index.js:92 | | keep |
--| POST | /internal/avatar-ingest | server/index.js:63 | | keep |
--| GET | /manifest.webmanifest | server/index.js:51 | | keep |
--| GET | /o | server/objects/routes.js:278 | | keep |
--| POST | /o | server/objects/routes.js:188 | | keep |
--| DELETE | /o/:id | server/objects/routes.js:308 | | keep |
--| GET | /o/:id | server/objects/routes.js:303 | | keep |
--| GET | /o/:id | server/objects/routes.js:382 | | keep |
--| POST | /o/:id/complete | server/objects/routes.js:244 | | keep |
--| GET | /o/:id/download | server/objects/routes.js:334 | | keep |
--| GET | /o/:id/holds | server/objects/routes.js:353 | | keep |
--| POST | /o/:id/holds | server/objects/routes.js:359 | | keep |
--| DELETE | /o/:id/holds/:holdId | server/objects/routes.js:368 | | keep |
--| POST | /o/:id/restore | server/objects/routes.js:324 | | keep |
--| GET | /release.json | server/index.js:90 | | keep |
--| GET | /tos | server/index.js:48 | | keep |
++| GET | /healthz | server/index.js:93 | | keep |
++| POST | /internal/avatar-ingest | server/index.js:64 | | keep |
++| GET | /manifest.webmanifest | server/index.js:52 | | keep |
++| GET | /o | server/objects/routes.js:497 | | keep |
++| POST | /o | server/objects/routes.js:261 | | keep |
++| DELETE | /o/:id | server/objects/routes.js:527 | | keep |
++| GET | /o/:id | server/objects/routes.js:522 | | keep |
++| GET | /o/:id | server/objects/routes.js:601 | | keep |
++| POST | /o/:id/complete | server/objects/routes.js:371 | | keep |
++| GET | /o/:id/download | server/objects/routes.js:553 | | keep |
++| GET | /o/:id/holds | server/objects/routes.js:572 | | keep |
++| POST | /o/:id/holds | server/objects/routes.js:578 | | keep |
++| DELETE | /o/:id/holds/:holdId | server/objects/routes.js:587 | | keep |
++| POST | /o/:id/multipart | server/objects/routes.js:411 | | keep |
++| DELETE | /o/:id/multipart/:uploadId | server/objects/routes.js:486 | | keep |
++| GET | /o/:id/multipart/:uploadId | server/objects/routes.js:440 | | keep |
++| POST | /o/:id/multipart/:uploadId/complete | server/objects/routes.js:449 | | keep |
++| POST | /o/:id/restore | server/objects/routes.js:543 | | keep |
++| POST | /o/:id/upload-url | server/objects/routes.js:387 | | keep |
++| GET | /release.json | server/index.js:91 | | keep |
++| GET | /tos | server/index.js:49 | | keep |
## OpenVibe.Tools
@@@ -1336,6 +1355,7 @@ Owner = the repository whose code answers the route; target = the authority it b
| Method | Path | Source | Target | Disposition |
|---|---|---|---|---|
++| POST | / | server/events/consumer.js:91 | | keep |
| GET | /api/chat/:streamId/history | server/chat/routes.js:491 | | keep |
| GET | /api/chat/:streamId/replay | server/chat/routes.js:469 | | keep |
| GET | /api/chat/:streamId/users | server/chat/routes.js:617 | | keep |
@@@ -1351,6 +1371,8 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/chat/gif/search | server/chat/routes.js:163 | | keep |
| GET | /api/chat/gif/trending | server/chat/routes.js:136 | | keep |
| GET | /api/chat/global/history | server/chat/routes.js:449 | | keep |
++| GET | /api/chat/preferences | server/prefs/routes.js:30 | | keep |
++| PUT | /api/chat/preferences | server/prefs/routes.js:34 | | keep |
| GET | /api/chat/relay-user/:platform/:username | server/chat/routes.js:387 | | keep |
| GET | /api/chat/relay-user/:platform/:username/logs | server/chat/routes.js:427 | | keep |
| GET | /api/chat/search | server/chat/routes.js:331 | | keep |
@@@ -1393,9 +1415,9 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /api/tts/settings | server/chat/tts-routes.js:90 | | keep |
| GET | /api/tts/voices | server/chat/tts-routes.js:80 | | keep |
| POST | /calls | server/bridge/live-bridge.js:220 | | keep |
--| GET | /health | server/app.js:77 | | keep |
++| GET | /health | server/app.js:80 | | keep |
| GET | /presence | server/bridge/live-bridge.js:242 | | keep |
--| GET | /ready | server/app.js:94 | | keep |
++| GET | /ready | server/app.js:97 | | keep |
## OpenRe.Stream
@@@ -1502,84 +1524,102 @@ Owner = the repository whose code answers the route; target = the authority it b
| Method | Path | Source | Target | Disposition |
|---|---|---|---|---|
--| GET | / | server/web/routes.js:54 | | keep |
--| GET | /:handle | server/web/routes.js:233 | | keep |
--| GET | /:handle/goals | server/web/routes.js:234 | | keep |
--| POST | /:handle/tip | server/web/routes.js:245 | | keep |
++| GET | / | server/web/routes.js:65 | | keep |
++| GET | /:handle | server/web/routes.js:361 | | keep |
++| GET | /:handle/goals | server/web/routes.js:362 | | keep |
++| GET | /:handle/supporters | server/web/routes.js:372 | | keep |
++| POST | /:handle/tip | server/web/routes.js:387 | | keep |
| GET | /api/health | server/app.js:78 | | keep |
| GET | /api/ready | server/app.js:84 | | keep |
--| POST | /api/v1/checkout | server/api/v1.js:160 | | keep |
--| GET | /api/v1/goals | server/api/v1.js:213 | | keep |
--| POST | /api/v1/goals | server/api/v1.js:226 | | keep |
--| GET | /api/v1/goals/:id | server/api/v1.js:220 | | keep |
--| PATCH | /api/v1/goals/:id | server/api/v1.js:238 | | keep |
--| POST | /api/v1/goals/:id/close | server/api/v1.js:239 | | keep |
--| GET | /api/v1/interactions | server/api/v1.js:166 | | keep |
--| GET | /api/v1/interactions/:id | server/api/v1.js:185 | | keep |
--| POST | /api/v1/interactions/external | server/api/v1.js:198 | | keep |
--| POST | /api/v1/media-requests | server/api/v1.js:163 | | keep |
--| GET | /api/v1/overlay-configs | server/api/v1.js:264 | | keep |
--| POST | /api/v1/overlay-configs | server/api/v1.js:275 | | keep |
--| GET | /api/v1/overlay-configs/:id | server/api/v1.js:269 | | keep |
--| PATCH | /api/v1/overlay-configs/:id | server/api/v1.js:281 | | keep |
--| GET | /api/v1/overlay-tokens | server/api/v1.js:242 | | keep |
--| POST | /api/v1/overlay-tokens | server/api/v1.js:247 | | keep |
--| POST | /api/v1/overlay-tokens/:id/revoke | server/api/v1.js:257 | | keep |
--| POST | /api/v1/paid-messages | server/api/v1.js:161 | | keep |
--| GET | /api/v1/profiles/:creator | server/api/v1.js:82 | | keep |
--| PATCH | /api/v1/profiles/:creator | server/api/v1.js:93 | | keep |
--| GET | /api/v1/profiles/:creator/totals | server/api/v1.js:112 | | keep |
--| POST | /api/v1/simulate | server/api/v1.js:289 | | keep |
--| POST | /api/v1/tts-requests | server/api/v1.js:162 | | keep |
++| POST | /api/v1/checkout | server/api/v1.js:194 | | keep |
++| GET | /api/v1/goals | server/api/v1.js:248 | | keep |
++| POST | /api/v1/goals | server/api/v1.js:262 | | keep |
++| GET | /api/v1/goals/:id | server/api/v1.js:256 | | keep |
++| PATCH | /api/v1/goals/:id | server/api/v1.js:274 | | keep |
++| POST | /api/v1/goals/:id/close | server/api/v1.js:275 | | keep |
++| GET | /api/v1/interactions | server/api/v1.js:200 | | keep |
++| GET | /api/v1/interactions/:id | server/api/v1.js:219 | | keep |
++| POST | /api/v1/interactions/:id/${action} | server/api/v1.js:350 | | keep |
++| POST | /api/v1/interactions/external | server/api/v1.js:232 | | keep |
++| POST | /api/v1/me/erase | server/api/v1.js:125 | | keep |
++| GET | /api/v1/me/export | server/api/v1.js:124 | | keep |
++| POST | /api/v1/media-requests | server/api/v1.js:197 | | keep |
++| GET | /api/v1/moderation | server/api/v1.js:338 | | keep |
++| GET | /api/v1/moderation/log | server/api/v1.js:344 | | keep |
++| GET | /api/v1/moderators | server/api/v1.js:358 | | keep |
++| POST | /api/v1/moderators | server/api/v1.js:363 | | keep |
++| POST | /api/v1/moderators/:subject/remove | server/api/v1.js:370 | | keep |
++| GET | /api/v1/overlay-configs | server/api/v1.js:301 | | keep |
++| POST | /api/v1/overlay-configs | server/api/v1.js:312 | | keep |
++| GET | /api/v1/overlay-configs/:id | server/api/v1.js:306 | | keep |
++| PATCH | /api/v1/overlay-configs/:id | server/api/v1.js:318 | | keep |
++| GET | /api/v1/overlay-tokens | server/api/v1.js:278 | | keep |
++| POST | /api/v1/overlay-tokens | server/api/v1.js:283 | | keep |
++| POST | /api/v1/overlay-tokens/:id/revoke | server/api/v1.js:294 | | keep |
++| POST | /api/v1/paid-messages | server/api/v1.js:195 | | keep |
++| GET | /api/v1/profiles/:creator | server/api/v1.js:93 | | keep |
++| PATCH | /api/v1/profiles/:creator | server/api/v1.js:127 | | keep |
++| GET | /api/v1/profiles/:creator/supporters | server/api/v1.js:106 | | keep |
++| GET | /api/v1/profiles/:creator/totals | server/api/v1.js:146 | | keep |
++| POST | /api/v1/simulate | server/api/v1.js:377 | | keep |
++| POST | /api/v1/tts-requests | server/api/v1.js:196 | | keep |
| GET | /auth/callback | server/web/session.js:129 | | keep |
| POST | /auth/fedcm | server/web/session.js:155 | | keep |
| GET | /auth/login | server/web/session.js:116 | | keep |
| GET | /auth/logout | server/web/session.js:174 | | keep |
| GET | /auth/me | server/web/session.js:190 | | keep |
| POST | /auth/refresh | server/web/session.js:197 | | keep |
--| GET | /dashboard | server/web/routes.js:108 | | keep |
++| GET | /dashboard | server/web/routes.js:149 | | keep |
| POST | /events | server/events/consumer.js:51 | | keep |
--| GET | /overlay/:token | server/web/routes.js:183 | | keep |
--| GET | /overlay/:token/events | server/web/routes.js:194 | | keep |
--| GET | /overlay/:token/state | server/web/routes.js:204 | | keep |
--| GET | /receipts | server/web/routes.js:71 | | keep |
--| GET | /receipts/:id | server/web/routes.js:76 | | keep |
++| GET | /moderate/:handle | server/web/routes.js:321 | | keep |
++| POST | /moderate/:handle/:id/:act(hide\|restore) | server/web/routes.js:327 | | keep |
++| GET | /moderate/invite/:token | server/web/routes.js:283 | | keep |
++| POST | /moderate/invite/:token | server/web/routes.js:292 | | keep |
++| GET | /overlay/:token | server/web/routes.js:234 | | keep |
++| GET | /overlay/:token/events | server/web/routes.js:245 | | keep |
++| GET | /overlay/:token/state | server/web/routes.js:259 | | keep |
++| GET | /receipts | server/web/routes.js:82 | | keep |
++| GET | /receipts/:id | server/web/routes.js:112 | | keep |
++| GET | /receipts/erase | server/web/routes.js:102 | | keep |
++| POST | /receipts/erase | server/web/routes.js:106 | | keep |
++| GET | /receipts/export | server/web/routes.js:89 | | keep |
| GET | /release.json | server/app.js:85 | | keep |
--| GET | /robots.txt | server/web/routes.js:58 | | keep |
--| GET | /sitemap.xml | server/web/routes.js:60 | | keep |
++| GET | /robots.txt | server/web/routes.js:69 | | keep |
++| GET | /sitemap.xml | server/web/routes.js:71 | | keep |
## OpenVibe.VIP
| Method | Path | Source | Target | Disposition |
|---|---|---|---|---|
| GET | / | server/web/routes.js:80 | | keep |
--| GET | /:username | server/web/routes.js:219 | | keep |
--| GET | /:username/plans/:slug | server/web/routes.js:237 | | keep |
--| GET | /api/health | server/app.js:82 | | keep |
--| GET | /api/ready | server/app.js:84 | | keep |
--| POST | /api/v1/checkout | server/api/v1.js:203 | | keep |
++| GET | /:username | server/web/routes.js:220 | | keep |
++| GET | /:username/plans/:slug | server/web/routes.js:238 | | keep |
++| GET | /api/health | server/app.js:86 | | keep |
++| GET | /api/ready | server/app.js:88 | | keep |
++| POST | /api/v1/checkout | server/api/v1.js:210 | | keep |
| GET | /api/v1/creators/:ref | server/api/v1.js:99 | | keep |
--| GET | /api/v1/creators/:ref/members | server/api/v1.js:331 | | keep |
--| GET | /api/v1/entitlements/check | server/api/v1.js:269 | | keep |
--| POST | /api/v1/entitlements/check | server/api/v1.js:270 | | keep |
--| POST | /api/v1/memberships/:creator/cancel | server/api/v1.js:231 | | keep |
--| PUT | /api/v1/memberships/:creator/preferences | server/api/v1.js:236 | | keep |
--| GET | /api/v1/memberships/:subject | server/api/v1.js:215 | | keep |
--| GET | /api/v1/perks | server/api/v1.js:166 | | keep |
--| POST | /api/v1/perks | server/api/v1.js:173 | | keep |
--| PATCH | /api/v1/perks/:id | server/api/v1.js:180 | | keep |
--| GET | /api/v1/plans | server/api/v1.js:111 | | keep |
--| POST | /api/v1/plans | server/api/v1.js:132 | | keep |
--| GET | /api/v1/plans/:id | server/api/v1.js:125 | | keep |
--| PATCH | /api/v1/plans/:id | server/api/v1.js:148 | | keep |
--| POST | /api/v1/plans/:id/archive | server/api/v1.js:160 | | keep |
--| POST | /api/v1/plans/:id/publish | server/api/v1.js:155 | | keep |
--| GET | /api/v1/plans/:id/versions | server/api/v1.js:126 | | keep |
--| GET | /api/v1/policies | server/api/v1.js:273 | | keep |
--| POST | /api/v1/policies | server/api/v1.js:298 | | keep |
--| DELETE | /api/v1/policies/:id | server/api/v1.js:306 | | keep |
--| GET | /api/v1/policies/:id | server/api/v1.js:292 | | keep |
--| POST | /api/v1/policies/evaluate | server/api/v1.js:312 | | keep |
++| GET | /api/v1/creators/:ref/card | server/api/v1.js:111 | | keep |
++| GET | /api/v1/creators/:ref/members | server/api/v1.js:338 | | keep |
++| GET | /api/v1/entitlements/check | server/api/v1.js:276 | | keep |
++| POST | /api/v1/entitlements/check | server/api/v1.js:277 | | keep |
++| POST | /api/v1/memberships/:creator/cancel | server/api/v1.js:238 | | keep |
++| PUT | /api/v1/memberships/:creator/preferences | server/api/v1.js:243 | | keep |
++| GET | /api/v1/memberships/:subject | server/api/v1.js:222 | | keep |
++| GET | /api/v1/perks | server/api/v1.js:173 | | keep |
++| POST | /api/v1/perks | server/api/v1.js:180 | | keep |
++| PATCH | /api/v1/perks/:id | server/api/v1.js:187 | | keep |
++| GET | /api/v1/plans | server/api/v1.js:118 | | keep |
++| POST | /api/v1/plans | server/api/v1.js:139 | | keep |
++| GET | /api/v1/plans/:id | server/api/v1.js:132 | | keep |
++| PATCH | /api/v1/plans/:id | server/api/v1.js:155 | | keep |
++| POST | /api/v1/plans/:id/archive | server/api/v1.js:167 | | keep |
++| POST | /api/v1/plans/:id/publish | server/api/v1.js:162 | | keep |
++| GET | /api/v1/plans/:id/versions | server/api/v1.js:133 | | keep |
++| GET | /api/v1/policies | server/api/v1.js:280 | | keep |
++| POST | /api/v1/policies | server/api/v1.js:305 | | keep |
++| DELETE | /api/v1/policies/:id | server/api/v1.js:313 | | keep |
++| GET | /api/v1/policies/:id | server/api/v1.js:299 | | keep |
++| POST | /api/v1/policies/evaluate | server/api/v1.js:319 | | keep |
| GET | /auth/callback | server/web/session.js:129 | | keep |
| POST | /auth/fedcm | server/web/session.js:155 | | keep |
| GET | /auth/login | server/web/session.js:116 | | keep |
@@@ -1587,9 +1627,12 @@ Owner = the repository whose code answers the route; target = the authority it b
| GET | /auth/me | server/web/session.js:190 | | keep |
| POST | /auth/refresh | server/web/session.js:197 | | keep |
| GET | /dashboard | server/web/routes.js:121 | | keep |
++| GET | /embed/:username/badge.svg | server/web/embeds.js:103 | | keep |
++| GET | /embed/:username/card.json | server/web/embeds.js:94 | | keep |
++| GET | /embed/:username/widget | server/web/embeds.js:113 | | keep |
| POST | /events | server/events/consumer.js:75 | | keep |
| GET | /me | server/web/routes.js:86 | | keep |
--| GET | /release.json | server/app.js:85 | | keep |
++| GET | /release.json | server/app.js:89 | | keep |
| GET | /robots.txt | server/web/routes.js:74 | | keep |
| GET | /sitemap.xml | server/web/routes.js:75 | | keep |
ddiff --git a/docs/roadmap-baseline/04-cross-service.md b/docs/roadmap-baseline/04-cross-service.md
iindex 455fabb1..ac6da70e 100644
---- a/docs/roadmap-baseline/04-cross-service.md
++++ b/docs/roadmap-baseline/04-cross-service.md
@@@ -11,7 +11,7 @@ Deliverable 3 (dependency half). A call site is a source file that makes HTTP re
| OpenRe.Stream | OpenVibe.Network | 2 | bearer, internal-key, oauth-client |
| OpenVibe.Blog | OpenVibe.Network | 2 | internal-key, oauth-client |
| OpenVibe.Chat | OpenVibe.Live | 2 | service-token |
--| OpenVibe.Chat | OpenVibe.Network | 1 | oauth-client, service-token |
++| OpenVibe.Chat | OpenVibe.Network | 2 | oauth-client, service-token |
| OpenVibe.Chat | OpenVibe.Search | 1 | none-detected |
| OpenVibe.Community | OpenVibe.Live | 2 | bearer |
| OpenVibe.Community | OpenVibe.Media | 1 | bearer |
@@@ -62,6 +62,7 @@ Deliverable 3 (dependency half). A call site is a source file that makes HTTP re
| Chat/server/bridge/live-mirror.js:77 | OpenVibe.Live | live.internalUrl | service-token | yes | no |
| Chat/server/live-context.js:130 | OpenVibe.Live | live.internalUrl | service-token | yes | yes |
| Chat/server/net/service-auth.js:5 | OpenVibe.Network | /oauth/token, networkInternalUrl, /api/.well-known/jwks, networkUrl | oauth-client, service-token | yes | no |
++| Chat/server/prefs/network-modules.js:21 | OpenVibe.Network | networkInternalUrl | service-token | yes | yes |
| Chat/server/chat/routes.js:72 | OpenVibe.Search | searchUrl | none-detected | **no** | no |
| Community/server/live-client.js:6 | OpenVibe.Live | liveInternalUrl | bearer | yes | no |
| Community/server/pastes/proxy.js:26 | OpenVibe.Live | liveUrl, liveInternalUrl | bearer | yes | yes |
@@@ -84,7 +85,7 @@ Deliverable 3 (dependency half). A call site is a source file that makes HTTP re
| Live/server/comments-client.js:29 | OpenVibe.Community | OV_COMMUNITY_INTERNAL_URL, :4200, OV_COMMUNITY_URL | none-detected | yes | yes |
| Live/server/media-proxy/pastes.js:311 | OpenVibe.Community | OV_COMMUNITY_URL | none-detected | yes | yes |
| Live/server/pastes-client.js:16 | OpenVibe.Community | OV_COMMUNITY_INTERNAL_URL, :4200 | none-detected | yes | yes |
--| Live/server/seo/seo.js:427 | OpenVibe.Community | OV_COMMUNITY_URL | none-detected | **no** | no |
++| Live/server/seo/seo.js:432 | OpenVibe.Community | OV_COMMUNITY_URL | none-detected | **no** | no |
| Live/server/config.js:175 | OpenVibe.Media | MEDIA_URL, :4100 | internal-key | yes | no |
| Live/server/media-client.js:14 | OpenVibe.Media | :4100, MEDIA_URL, /api/v1/${ | api-key, bearer | yes | no |
| Live/server/chat/chat-server.js:84 | OpenVibe.Network | OV_NETWORK_INTERNAL_URL | internal-key | **no** | no |
ddiff --git a/docs/roadmap-baseline/05-realtime-and-jobs.md b/docs/roadmap-baseline/05-realtime-and-jobs.md
iindex 6412b8ef..a6238d30 100644
---- a/docs/roadmap-baseline/05-realtime-and-jobs.md
++++ b/docs/roadmap-baseline/05-realtime-and-jobs.md
@@@ -24,18 +24,18 @@ Deliverable 4, plus the background-job half of the exit criteria.
| Repo | Path | Referenced at |
|---|---|---|
--| OpenVibe.Live | /ws/ | server/index.js:427, server/index.js:437, server/index.js:1000 |
--| OpenVibe.Live | /ws/broadcast | server/index.js:1042, server/streaming/broadcast-server.js:187 |
--| OpenVibe.Live | /ws/call | server/index.js:1046, server/streaming/call-server.js:98 |
--| OpenVibe.Live | /ws/canvas | server/index.js:1048 |
--| OpenVibe.Live | /ws/chat | server/chat/chat-server.js:294, server/index.js:1038 |
--| OpenVibe.Live | /ws/control | server/controls/control-server.js:46, server/index.js:1044 |
--| OpenVibe.Live | /ws/game | server/index.js:1048 |
--| OpenVibe.Live | /ws/robotstreamer-publish | server/index.js:1050, server/integrations/robotstreamer-service.js:807 |
--| OpenVibe.Live | /ws/vibe-coding/publish | server/index.js:1040, server/vibe-coding/publish-server.js:31 |
++| OpenVibe.Live | /ws/ | server/index.js:427, server/index.js:437, server/web/page-status.js:180 |
++| OpenVibe.Live | /ws/broadcast | server/index.js:1046, server/streaming/broadcast-server.js:187 |
++| OpenVibe.Live | /ws/call | server/index.js:1050, server/streaming/call-server.js:98 |
++| OpenVibe.Live | /ws/canvas | server/index.js:1052 |
++| OpenVibe.Live | /ws/chat | server/chat/chat-server.js:294, server/index.js:1042 |
++| OpenVibe.Live | /ws/control | server/controls/control-server.js:46, server/index.js:1048 |
++| OpenVibe.Live | /ws/game | server/index.js:1052 |
++| OpenVibe.Live | /ws/robotstreamer-publish | server/index.js:1054, server/integrations/robotstreamer-service.js:807 |
++| OpenVibe.Live | /ws/vibe-coding/publish | server/index.js:1044, server/vibe-coding/publish-server.js:31 |
| OpenVibe.Network | /ws/ | server/deploy/nginx-generator.js:153 |
| OpenVibe.Games | /ws | apps/server/src/main.ts:254 |
--| OpenVibe.Chat | /ws/chat | server/app.js:202, server/chat/chat-server.js:234 |
++| OpenVibe.Chat | /ws/chat | server/app.js:210, server/chat/chat-server.js:234 |
| OpenVibe.Host | /ws/ | lib/nginx.js:60 |
## Non-HTTP protocols
@@@ -56,8 +56,8 @@ Owner = the repository whose process runs the job; target = the authority the wo
| Repo | Kind | Name | Interval | At | Target | Disposition |
|---|---|---|---|---|---|---|
--| OpenVibe.Live | setInterval | | 5 min | server/ai/ai-moments-job.js:500 | | keep |
--| OpenVibe.Live | setInterval | | ? | server/ai/auto-clip-job.js:312 | | keep |
++| OpenVibe.Live | setInterval | | 5 min | server/ai/ai-moments-job.js:495 | | keep |
++| OpenVibe.Live | setInterval | | ? | server/ai/auto-clip-job.js:308 | | keep |
| OpenVibe.Live | setInterval | | 1 min | server/ai/backfill-job.js:160 | | keep |
| OpenVibe.Live | setInterval | | ? | server/ai/chat-ai.js:473 | | keep |
| OpenVibe.Live | setInterval | | 5 min | server/ai/easter-egg-job.js:215 | | keep |
@@@ -76,12 +76,12 @@ Owner = the repository whose process runs the job; target = the authority the wo
| OpenVibe.Live | setInterval | | ? | server/chat/dm-routes.js:39 | OpenVibe.Chat | compat |
| OpenVibe.Live | setInterval | | ? | server/diagnostics.js:18 | | keep |
| OpenVibe.Live | setInterval | | ? | server/events/stream-events.js:100 | | keep |
--| OpenVibe.Live | setInterval | | 5 min | server/home/routes.js:583 | | keep |
++| OpenVibe.Live | setInterval | | 5 min | server/home/routes.js:563 | | keep |
| OpenVibe.Live | setInterval | | ? | server/home/star-job.js:130 | | keep |
--| OpenVibe.Live | setInterval | | 360 min | server/index.js:1310 | | keep |
--| OpenVibe.Live | setInterval | | 45 s | server/index.js:1327 | | keep |
--| OpenVibe.Live | setInterval | | ? | server/index.js:1351 | | keep |
--| OpenVibe.Live | setInterval | | ? | server/index.js:1362 | | keep |
++| OpenVibe.Live | setInterval | | 360 min | server/index.js:1314 | | keep |
++| OpenVibe.Live | setInterval | | 45 s | server/index.js:1331 | | keep |
++| OpenVibe.Live | setInterval | | ? | server/index.js:1355 | | keep |
++| OpenVibe.Live | setInterval | | ? | server/index.js:1366 | | keep |
| OpenVibe.Live | setInterval | | ? | server/integrations/chat-relay-service.js:615 | OpenVibe.Chat | extract |
| OpenVibe.Live | setInterval | | 1 s | server/integrations/powerchat-platform.js:296 | OpenVibe.Billing | extract |
| OpenVibe.Live | setInterval | | ? | server/integrations/powerchat-platform.js:430 | OpenVibe.Billing | extract |
@@@ -112,24 +112,27 @@ Owner = the repository whose process runs the job; target = the authority the wo
| OpenVibe.Network | setInterval | | ? | server/chrome/service.js:203 | | keep |
| OpenVibe.Network | setInterval | | 60 min | server/index.js:722 | | keep |
| OpenVibe.Network | setInterval | | 2 min | server/index.js:725 | | keep |
--| OpenVibe.Network | setInterval | | ? | server/index.js:732 | | keep |
++| OpenVibe.Network | setInterval | | ? | server/index.js:740 | | keep |
++| OpenVibe.Network | setInterval | | ? | server/index.js:743 | | keep |
| OpenVibe.Shared | setInterval | | 15 min | account-switcher.js:624 | | keep |
| OpenVibe.Shared | setInterval | | ? | analytics/retention.js:230 | | keep |
| OpenVibe.Shared | setInterval | | ? | analytics/tracker.js:115 | | keep |
| OpenVibe.Shared | setInterval | | ? | notification-ui.js:548 | | keep |
--| OpenVibe.Shared | setInterval | | 30 s | release-watch.js:88 | | keep |
--| OpenVibe.Shared | setInterval | | 10 min | release-watch.js:89 | | keep |
++| OpenVibe.Shared | setInterval | | ? | release-watch.js:170 | | keep |
++| OpenVibe.Shared | setInterval | | 10 min | release-watch.js:175 | | keep |
| OpenVibe.Media | setInterval | | ? | server/auth.js:59 | | keep |
--| OpenVibe.Media | setInterval | | ? | server/events.js:64 | | keep |
--| OpenVibe.Media | setInterval | | 720 min | server/index.js:136 | | keep |
--| OpenVibe.Media | setInterval | | ? | server/index.js:164 | | keep |
++| OpenVibe.Media | setInterval | | ? | server/events.js:73 | | keep |
++| OpenVibe.Media | setInterval | | 720 min | server/index.js:137 | | keep |
++| OpenVibe.Media | setInterval | | ? | server/index.js:166 | | keep |
++| OpenVibe.Media | setInterval | | ? | server/jobs/worker.js:64 | | keep |
++| OpenVibe.Media | setInterval | | ? | server/jobs/worker.js:183 | | keep |
| OpenVibe.Media | setInterval | | ? | server/objects/verify-job.js:226 | | keep |
| OpenVibe.Media | setInterval | | ? | server/pastes/routes.js:709 | OpenVibe.Community | frozen-legacy |
| OpenVibe.Media | setInterval | | ? | server/vod/clip-cutter.js:111 | | keep |
| OpenVibe.Media | setInterval | | ? | server/vod/clip-jobs.js:125 | | keep |
| OpenVibe.Media | setInterval | | ? | server/vod/health-job.js:266 | | keep |
| OpenVibe.Media | setInterval | | 1 min | server/vod/recorder.js:213 | | keep |
--| OpenVibe.Media | setInterval | | ? | server/vod/vod-storage.js:480 | | keep |
++| OpenVibe.Media | setInterval | | ? | server/vod/vod-storage.js:484 | | keep |
| OpenVibe.Tools | setInterval | | 15 s | apps/_shared/jobs/http.js:270 | | keep |
| OpenVibe.Tools | setInterval | | ? | apps/_shared/jobs/index.js:102 | | keep |
| OpenVibe.Tools | setInterval | | ? | apps/_shared/jobs/system.js:582 | | keep |
@@@ -161,6 +164,7 @@ Owner = the repository whose process runs the job; target = the authority the wo
| OpenVibe.Chat | setInterval | | ? | server/chat/chat-server.js:200 | | keep |
| OpenVibe.Chat | setInterval | | ? | server/chat/chat-server.js:205 | | keep |
| OpenVibe.Chat | setInterval | | ? | server/chat/dm-routes.js:46 | | keep |
++| OpenVibe.Chat | setInterval | | 360 min | server/events/consumer.js:136 | | keep |
| OpenVibe.Chat | setInterval | | ? | server/events/outbox.js:112 | | keep |
| OpenVibe.Chat | setInterval | | ? | server/live-context.js:726 | | keep |
| OpenVibe.Chat | setInterval | | 2 s | server/live-context.js:728 | | keep |
@@@ -169,8 +173,8 @@ Owner = the repository whose process runs the job; target = the authority the wo
| OpenVibe.Billing | setInterval | | ? | server/index.js:30 | | keep |
| OpenVibe.Billing | setInterval | | ? | server/network.js:40 | | keep |
| OpenVibe.Billing | setInterval | | ? | server/outbox.js:96 | | keep |
--| OpenVibe.Tips | setInterval | | ? | server/domain/overlays.js:268 | | keep |
--| OpenVibe.Tips | setInterval | | ? | server/index.js:21 | | keep |
++| OpenVibe.Tips | setInterval | | ? | server/domain/overlays.js:307 | | keep |
++| OpenVibe.Tips | setInterval | | ? | server/index.js:22 | | keep |
| OpenVibe.Tips | setInterval | | ? | server/network.js:42 | | keep |
| OpenVibe.VIP | setInterval | | ? | server/index.js:25 | | keep |
| OpenVibe.VIP | setInterval | | ? | server/network.js:42 | | keep |
ddiff --git a/docs/roadmap-baseline/06-secrets.md b/docs/roadmap-baseline/06-secrets.md
iindex c333fd57..fcb6b916 100644
---- a/docs/roadmap-baseline/06-secrets.md
++++ b/docs/roadmap-baseline/06-secrets.md
@@@ -37,6 +37,7 @@ Deliverable 5. Names and locations only; no value was read. "In prod" names the
| OpenVibe.Billing | STRIPE_WEBHOOK_SECRET | **not set** | server/config.js |
| OpenVibe.Blog | BLOG_FORM_SECRET | blog.env | server/config.js |
| OpenVibe.Blog | OV_OAUTH_CLIENT_SECRET | blog.env | server/config.js |
++| OpenVibe.Chat | CHAT_EVENTS_SECRET | **not set** | server/config.js |
| OpenVibe.Chat | OV_OAUTH_CLIENT_SECRET | chat.env | server/config.js |
| OpenVibe.Codes | CODES_FORM_SECRET | codes.env | server/config.js |
| OpenVibe.Codes | OV_CLIENT_SECRET | **not set** | server/http/portal.js |
@@@ -66,7 +67,7 @@ Deliverable 5. Names and locations only; no value was read. "In prod" names the
| OpenVibe.Live | GITHUB_TOKEN | **not set** | server/meta/routes.js |
| OpenVibe.Live | INTERNAL_API_KEY | live.env | server/chat/chat-server.js, server/config.js, server/monetization/wallet-client.js +3 |
| OpenVibe.Live | JWT_SECRET | live.env | server/arena/arena-service.js, server/config.js, server/integrations/platform-oauth.js +1 |
--| OpenVibe.Live | MEDIA_API_KEY | live.env | server/media-client.js |
++| OpenVibe.Live | MEDIA_API_KEY | live.env | server/lineage/media-source.js, server/media-client.js |
| OpenVibe.Live | MEDIA_EVENTS_SECRET | live.env | server/media-proxy/media-events.js |
| OpenVibe.Live | MEDIA_WEBHOOK_SECRET | live.env | server/media-proxy/webhook.js |
| OpenVibe.Live | OPENRE_EVENTS_SECRET | live.env | server/openre/mirror.js, server/openre/routes.js |
@@@ -362,6 +363,12 @@ Deliverable 5. Names and locations only; no value was read. "In prod" names the
| OpenVibe.Chat | BASE_URL | chat.env | server/config.js |
| OpenVibe.Chat | CHAT_CACHE_DIR | | server/config.js |
| OpenVibe.Chat | CHAT_DB_PATH | | server/config.js |
++| OpenVibe.Chat | CHAT_EVENTS_ENDPOINT | | server/config.js |
++| OpenVibe.Chat | CHAT_EVENTS_SUBSCRIBE | | server/config.js |
++| OpenVibe.Chat | CHAT_PREFS_CACHE_MAX | | server/config.js |
++| OpenVibe.Chat | CHAT_PREFS_ENABLED | | server/config.js |
++| OpenVibe.Chat | CHAT_PREFS_TIMEOUT_MS | | server/config.js |
++| OpenVibe.Chat | CHAT_PREFS_TTL_MS | | server/config.js |
| OpenVibe.Chat | CHAT_VIP_BADGE_DENY_TTL_MS | | server/config.js |
| OpenVibe.Chat | CHAT_VIP_BADGE_TTL_MS | | server/config.js |
| OpenVibe.Chat | CHAT_VIP_BADGE_UNAVAILABLE_TTL_MS | | server/config.js |
@@@ -786,6 +793,8 @@ Deliverable 5. Names and locations only; no value was read. "In prod" names the
| OpenVibe.Media | MEDIA_B2_ENDPOINT | media.env | server/vod/vod-storage.js |
| OpenVibe.Media | MEDIA_B2_KEY_ID | media.env | server/vod/vod-storage.js |
| OpenVibe.Media | MEDIA_B2_REGION | media.env | server/vod/vod-storage.js |
++| OpenVibe.Media | MEDIA_JOBS_ENABLED | | server/config.js |
++| OpenVibe.Media | MEDIA_JOBS_HEAVY_WHILE_RECORDING | | server/config.js |
| OpenVibe.Media | MEDIA_PUBLIC_URL | | server/config.js |
| OpenVibe.Media | MEDIA_R2_ACCESS_KEY_ID | media.env | server/vod/vod-storage.js |
| OpenVibe.Media | MEDIA_R2_BUCKET | media.env | server/vod/vod-storage.js |
@@@ -1040,10 +1049,12 @@ Deliverable 5. Names and locations only; no value was read. "In prod" names the
| OpenVibe.Tips | TIPS_JOBS | | server/config.js |
| OpenVibe.Tips | TIPS_JOBS_INTERVAL_MS | | server/config.js |
| OpenVibe.Tips | TIPS_MAX_BITS | | server/config.js |
++| OpenVibe.Tips | TIPS_MAX_PENDING_CHECKOUTS | | server/config.js |
| OpenVibe.Tips | TIPS_MEDIA_HOSTS | | server/config.js |
| OpenVibe.Tips | TIPS_MESSAGE_CHARS | | server/config.js |
| OpenVibe.Tips | TIPS_MIN_CHECKOUT_BITS | | server/config.js |
| OpenVibe.Tips | TIPS_OVERLAY_HEARTBEAT_MS | | server/config.js |
++| OpenVibe.Tips | TIPS_OVERLAY_MAX_STREAMS | | server/config.js |
| OpenVibe.Tips | TIPS_OVERLAY_REPLAY_LIMIT | | server/config.js |
| OpenVibe.Tips | TIPS_OVERLAY_TTL_MS | | server/config.js |
| OpenVibe.Tips | TIPS_POWERCHAT_LINK_TEMPLATE | | server/config.js |
@@@ -1159,11 +1170,13 @@ Deliverable 5. Names and locations only; no value was read. "In prod" names the
| OpenVibe.VIP | VIP_CHECKOUT_PROVIDERS | vip.env | server/config.js |
| OpenVibe.VIP | VIP_DB_PATH | | server/config.js |
| OpenVibe.VIP | VIP_JOBS | | server/config.js |
++| OpenVibe.VIP | VIP_MEMBER_COUNT_TTL_MS | | server/config.js |
| OpenVibe.VIP | VIP_POWERCHAT_LINK_TEMPLATE | | server/config.js |
| OpenVibe.VIP | VIP_PROJECTION_GRACE_MS | | server/config.js |
| OpenVibe.VIP | VIP_PROJECTION_MAX_AGE_MS | | server/config.js |
| OpenVibe.VIP | VIP_REFRESH_INTERVAL_MS | | server/config.js |
| OpenVibe.VIP | VIP_STAFF_ROLES | | server/config.js |
++| OpenVibe.VIP | VIP_WIDGET_FRAME_ANCESTORS | | server/config.js |
| OpenVibe.Wiki | BASE_URL | wiki.env | server/config.js |
| OpenVibe.Wiki | COOKIE_SECURE | | server/config.js |
| OpenVibe.Wiki | EVENTS_RELAY_INTERVAL_MS | | server/config.js |
ddiff --git a/docs/roadmap-baseline/07-ownership.md b/docs/roadmap-baseline/07-ownership.md
iindex 50eb3a53..579af223 100644
---- a/docs/roadmap-baseline/07-ownership.md
++++ b/docs/roadmap-baseline/07-ownership.md
@@@ -9,18 +9,18 @@ Deliverable 6. Current owner = the repo that creates the table; target owner = r
| Current owner | Tables | Stay | Staged copy | Moved (mirror left) | To move | Frozen legacy | Investigate |
|---|---|---|---|---|---|---|---|
| OpenVibe.Live | 193 | 33 | 0 | 12 | 81 | 44 | 23 |
--| OpenVibe.Network | 51 | 48 | 0 | 0 | 3 | 0 | 0 |
++| OpenVibe.Network | 53 | 50 | 0 | 0 | 3 | 0 | 0 |
| OpenVibe.Shared | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
--| OpenVibe.Media | 21 | 18 | 0 | 0 | 0 | 3 | 0 |
++| OpenVibe.Media | 23 | 20 | 0 | 0 | 0 | 3 | 0 |
| OpenVibe.Tools | 10 | 10 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Community | 20 | 20 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Games | 13 | 13 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Sites | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Events | 7 | 7 | 0 | 0 | 0 | 0 | 0 |
--| OpenVibe.Chat | 32 | 26 | 6 | 0 | 0 | 0 | 0 |
++| OpenVibe.Chat | 34 | 28 | 6 | 0 | 0 | 0 | 0 |
| OpenRe.Stream | 13 | 13 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Billing | 19 | 19 | 0 | 0 | 0 | 0 | 0 |
--| OpenVibe.Tips | 16 | 16 | 0 | 0 | 0 | 0 | 0 |
++| OpenVibe.Tips | 19 | 19 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.VIP | 15 | 15 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.AI | 16 | 16 | 0 | 0 | 0 | 0 | 0 |
| OpenVibe.Search | 21 | 21 | 0 | 0 | 0 | 0 | 0 |
ddiff --git a/docs/roadmap-baseline/08-discrepancies.md b/docs/roadmap-baseline/08-discrepancies.md
iindex fabcc4b0..5e0f1f6c 100644
---- a/docs/roadmap-baseline/08-discrepancies.md
++++ b/docs/roadmap-baseline/08-discrepancies.md
@@@ -8,18 +8,24 @@ Deliverable 7. Snapshot of openvibe-oregon taken 2026-09-23 20:32 UTC compared w
|---|---|---|---|
| medium | deploy | ai | deployed 96dc8a3 is 1 commit(s) behind origin/main 3a480ac |
| medium | deploy | billing | deployed c646279 is 1 commit(s) behind origin/main aa445d0 |
++| medium | deploy | chat | deployed 7897688 is 2 commit(s) behind origin/main ed90461 |
| medium | deploy | codes | deployed d60f279 is 1 commit(s) behind origin/main 51d2386 |
++| medium | deploy | community | deployed 57d1dd4 is 1 commit(s) behind origin/main 63b90a8 |
| medium | deploy | coupons | deployed 54df411 is 3 commit(s) behind origin/main 1c57c47 |
| medium | deploy | deals | deployed e72aeec is 2 commit(s) behind origin/main 91ca223 |
| medium | deploy | events | deployed 3366132 is 1 commit(s) behind origin/main efc09a7 |
| medium | deploy | games | deployed 474df50 is 1 commit(s) behind origin/main 7863fc6 |
--| medium | deploy | host | deployed 30f08d6 is 14 commit(s) behind origin/main ea99b50 |
++| medium | deploy | host | deployed 30f08d6 is 15 commit(s) behind origin/main 03dfcb3 |
++| medium | deploy | live | deployed c893c6c is 12 commit(s) behind origin/main ca7cc87 |
++| medium | deploy | media | deployed 9de4b25 is 4 commit(s) behind origin/main ad2217b |
++| medium | deploy | network | deployed 9bbd90f is 4 commit(s) behind origin/main 09bf748 |
| medium | deploy | news | deployed 5a17e7f is 1 commit(s) behind origin/main 5b393d2 |
| medium | deploy | openre | deployed e0dc1b4 is 2 commit(s) behind origin/main c091a09 |
| medium | deploy | reviews | deployed 1d462a2 is 1 commit(s) behind origin/main a7b50a6 |
| medium | deploy | sites | deployed d3b71af is 2 commit(s) behind origin/main d6e4cbd |
--| medium | deploy | tips | deployed 15bfc12 is 1 commit(s) behind origin/main 9a3a186 |
++| medium | deploy | tips | deployed 15bfc12 is 6 commit(s) behind origin/main f211c03 |
| medium | deploy | trade | deployed 9a55644 is 2 commit(s) behind origin/main ddbc60c |
++| medium | deploy | vip | deployed 9668a49 is 1 commit(s) behind origin/main fe7eaad |
| medium | deploy | wiki | deployed 011a68f is 1 commit(s) behind origin/main b4e70ac |
| low | database | /opt/openvibe.community/data/community.db | 115 KB, 9 tables, not a database the service opens (services.json): stale file or undeclared copy |
| low | database | /opt/openvibe.games/data/legacy-import/world-before-20260923T184930Z.db | 193 KB, 13 tables, not a database the service opens (services.json): stale file or undeclared copy |
@@@ -49,6 +55,7 @@ Deliverable 7. Snapshot of openvibe-oregon taken 2026-09-23 20:32 UTC compared w
| low | env | OpenVibe.Billing:POWERCHAT_WEBHOOK_SECRET | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
| low | env | OpenVibe.Billing:STRIPE_SECRET_KEY | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
| low | env | OpenVibe.Billing:STRIPE_WEBHOOK_SECRET | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
++| low | env | OpenVibe.Chat:CHAT_EVENTS_SECRET | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
| low | env | OpenVibe.Codes:OV_CLIENT_SECRET | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
| low | env | OpenVibe.Community:DISCORD_RELAY_WEBHOOK_VARS | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
| low | env | OpenVibe.Community:VIEW_HASH_SECRET | secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback |
@@@ -171,6 +178,8 @@ Deliverable 7. Snapshot of openvibe-oregon taken 2026-09-23 20:32 UTC compared w
| info | schema | OpenVibe.Blog:blog_term_links | in production (blog.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Blog (Prefixed stores created at runtime by openvibe-publishing (revisions, citations, schedules, redirects, index hooks).) |
| info | schema | OpenVibe.Blog:blog_terms | in production (blog.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Blog (Prefixed stores created at runtime by openvibe-publishing (revisions, citations, schedules, redirects, index hooks).) |
| info | schema | OpenVibe.Blog:event_outbox | in production (blog.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Blog (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
++| info | schema | OpenVibe.Chat:chat_event_inbox | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
++| info | schema | OpenVibe.Chat:deploy_releases | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Codes:event_outbox | in production (codes.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Codes (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
| info | schema | OpenVibe.Codes:trust_adr013 | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Coupons:coupons_index_revisions | in production (coupons.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Coupons (Prefixed stores created at runtime by openvibe-publishing (revisions, citations, schedules, redirects, index hooks).) |
@@@ -196,6 +205,8 @@ Deliverable 7. Snapshot of openvibe-oregon taken 2026-09-23 20:32 UTC compared w
| info | schema | OpenVibe.Live:robotstreamer_integrations_new | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Live:stream_controls_new | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Media:event_outbox | in production (media.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Media (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
++| info | schema | OpenVibe.Media:media_upload_parts | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
++| info | schema | OpenVibe.Media:media_uploads | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Network:admin_rate_limits | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Network:analytics_daily | in production (network.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Network (Per-site analytics from openvibe-shared/analytics.js; ADR-021 (2026-09-23): no IP, user id or city stored, raw rows pruned (hazard H11).) |
| info | schema | OpenVibe.Network:analytics_day_salts | in production (network.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Network (Per-site analytics from openvibe-shared/analytics.js; ADR-021 (2026-09-23): no IP, user id or city stored, raw rows pruned (hazard H11).) |
@@@ -205,6 +216,8 @@ Deliverable 7. Snapshot of openvibe-oregon taken 2026-09-23 20:32 UTC compared w
| info | schema | OpenVibe.Network:analytics_visitor_days | in production (network.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Network (Per-site analytics from openvibe-shared/analytics.js; ADR-021 (2026-09-23): no IP, user id or city stored, raw rows pruned (hazard H11).) |
| info | schema | OpenVibe.Network:network_event_inbox | in production (network.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Network (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
| info | schema | OpenVibe.Network:network_event_outbox | in production (network.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Network (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
++| info | schema | OpenVibe.Network:user_module_retirements | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
++| info | schema | OpenVibe.Network:user_module_revisions | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.News:event_outbox | in production (news.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.News (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
| info | schema | OpenVibe.News:idempotency_receipts | in production (news.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.News (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
| info | schema | OpenVibe.News:news_index_revisions | in production (news.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.News (Prefixed stores created at runtime by openvibe-publishing (revisions, citations, schedules, redirects, index hooks).) |
@@@ -236,6 +249,9 @@ Deliverable 7. Snapshot of openvibe-oregon taken 2026-09-23 20:32 UTC compared w
| info | schema | OpenVibe.Search:fts_restricted_idx | in production (search.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Search (FTS5 shadow tables of the per-audience full-text indexes.) |
| info | schema | OpenVibe.Tips:event_outbox | in production (tips.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Tips (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
| info | schema | OpenVibe.Tips:idempotency_receipts | in production (tips.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Tips (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.) |
++| info | schema | OpenVibe.Tips:tip_moderation_log | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
++| info | schema | OpenVibe.Tips:tip_moderator_invites | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
++| info | schema | OpenVibe.Tips:tip_moderators | declared in code but absent from every production database for this service (lazy/unused/legacy migration) |
| info | schema | OpenVibe.Tools:analytics_daily | in production (analytics.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Tools (Per-site analytics from openvibe-shared/analytics.js; ADR-021 (2026-09-23): no IP, user id or city stored, raw rows pruned (hazard H11).) |
| info | schema | OpenVibe.Tools:analytics_day_salts | in production (analytics.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Tools (Per-site analytics from openvibe-shared/analytics.js; ADR-021 (2026-09-23): no IP, user id or city stored, raw rows pruned (hazard H11).) |
| info | schema | OpenVibe.Tools:analytics_events | in production (analytics.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Tools (Per-site analytics from openvibe-shared/analytics.js; ADR-021 (2026-09-23): no IP, user id or city stored, raw rows pruned (hazard H11).) |
ddiff --git a/docs/roadmap-baseline/09-d-status.md b/docs/roadmap-baseline/09-d-status.md
iindex 2ff956c5..34e2b860 100644
---- a/docs/roadmap-baseline/09-d-status.md
++++ b/docs/roadmap-baseline/09-d-status.md
@@@ -7,13 +7,13 @@ Deliverable 8, derived from the [requirement ledger](requirement-ledger.md) (as
| IDs | Family | W0 (2026-09-22) | Now | Requirements | Wave | Verified | Measured |
|---|---|---|---|---|---|---|---|
| D01 | Identity/account | partial | **partial** | D01 partial | W1 | yes | 7 Live tables target OpenVibe.Network |
--| D02-D04 | Registry, capabilities, contracts | absent | **partial** | D02 partial, D03 partial, D04 partial | W1, W2 | yes | 1 charter-only repos of 36; Live 15, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0 |
++| D02-D04 | Registry, capabilities, contracts | absent | **partial** | D02 partial, D03 partial, D04 partial | W1, W2 | yes | 1 charter-only repos of 36; Live 14, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0 |
| D05-D06 | Policy, staff, user modules | partial | **partial** | D05 partial, D06 partial | W1, W2 | yes | - |
| D07-D10 | Themes, notifications, social, analytics | partial | **partial** | D07 partial, D08 partial, D09 partial, D10 partial | W1, W2, Track O | yes | 3 repos carry their own analytics_events |
--| D11-D13 | Events, realtime, SDK | absent | **partial** | D11 met, D12 partial, D13 partial | W2, W3 | yes | 97 caller-file/target pairs across 74 files; 11 WebSocket server constructions |
++| D11-D13 | Events, realtime, SDK | absent | **partial** | D11 met, D12 partial, D13 partial | W2, W3 | yes | 98 caller-file/target pairs across 75 files; 11 WebSocket server constructions |
| D14-D16 | Media | partial | **partial** | D14 partial, D15 partial, D16 partial | W4 | yes | 3 Media tables target OpenVibe.Community |
--| D17-D20 | Live, OpenRe, channel/VOD lineage | partial | **partial** | D17 partial, D18 blocked on owner, D19 partial, D20 not met | W7 | yes | 14 Live tables target OpenRe.Stream; 18 test files |
--| D21-D23 | Chat | partial | **partial** | D21 partial, D22 partial, D23 partial | W6 | yes | 23 Live tables target OpenVibe.Chat; 16 test files |
++| D17-D20 | Live, OpenRe, channel/VOD lineage | partial | **partial** | D17 partial, D18 blocked on owner, D19 partial, D20 partial | W7 | yes | 14 Live tables target OpenRe.Stream; 18 test files |
++| D21-D23 | Chat | partial | **partial** | D21 partial, D22 partial, D23 partial | W6 | yes | 23 Live tables target OpenVibe.Chat; 19 test files |
| D24-D27 | Community | partial | **partial** | D24 partial, D25 met, D26 partial, D27 met | W5 | yes | 20 tables; 4 Live tables target OpenVibe.Community |
| D28-D30 | Billing, Tips, VIP | partial | **blocked on owner** | D28 blocked on owner, D29 blocked on owner, D30 blocked on owner | W8-W10 (ADR-012 first) | yes | 2 Live tables target OpenVibe.Billing; 16 test files |
| D31 | Tools | built | **partial** | D31 partial | W11 | yes | 16 test files |
@@@ -21,15 +21,15 @@ Deliverable 8, derived from the [requirement ledger](requirement-ledger.md) (as
| D33-D34 | Codes, Host | absent | **partial** | D33 partial, D34 partial | W20, W21 | yes | 19 test files; 27 test files |
| D35-D38 | AI, content, sources, search | partial | **partial** | D35 partial, D36 blocked on owner, D37 blocked on owner, D38 blocked on owner | W13-W15 | yes | 14 Live tables target OpenVibe.AI; 17 test files |
| D39 | Mods | absent | **partial** | D39 partial | W12, W21 | yes | - |
--| D40 | Open developer services | absent | **partial** | D40 partial | W20, W21 | yes | 39 of 97 call sites authenticate with the shared internal key |
++| D40 | Open developer services | absent | **partial** | D40 partial | W20, W21 | yes | 39 of 98 call sites authenticate with the shared internal key |
| D41 | Independent runtime lifecycle | partial | **partial** | D41 partial | W7, W21 | yes | - |
--| D42 | Shared component architecture | partial | **partial** | D42 partial | W2, Track R | yes | 23 repos pin a tagged openvibe-shared release (latest v1.4.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0; 20 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Media (v1.3.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0) |
++| D42 | Shared component architecture | partial | **partial** | D42 partial | W2, Track R | yes | 23 repos pin a tagged openvibe-shared release (latest v1.5.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0; 30 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Live (v1.4.0), Media (v1.3.0), Network (v1.4.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Tools/apps/audio (v1.4.0), Tools/apps/docs (v1.4.0), Tools/apps/food (v1.4.0), Tools/apps/gateway (v1.4.0), Tools/apps/img (v1.4.0), Tools/apps/maps (v1.4.0), Tools/apps/text (v1.4.0), Tools/apps/yt (v1.4.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0) |
| D43 | Safe active-client updates | absent | **partial** | D43 partial | Track R | yes | - |
| D44 | Crawlable component rendering | built | **partial** | D44 partial | Track R (preserve) | yes | - |
--| D45 | Release compatibility and recovery | absent | **partial** | D45 partial | Track R, W22 | yes | 15 service(s) not running origin/main |
++| D45 | Release compatibility and recovery | absent | **partial** | D45 partial | Track R, W22 | yes | 21 service(s) not running origin/main |
| D46 | Update observability and acceptance | absent | **partial** | D46 partial | Track R, Track O | yes | 27 of 27 scanned repos have .github/workflows |
--Families: 0 met, 21 partial, 0 not met, 1 blocked on owner (of 22). Requirements: 3 met, 35 partial, 1 not met, 7 blocked on owner (of 46); 46 verified. At Wave 0 the same 22 families were 3 built, 11 partial, 8 absent.
++Families: 0 met, 21 partial, 0 not met, 1 blocked on owner (of 22). Requirements: 3 met, 36 partial, 0 not met, 7 blocked on owner (of 46); 46 verified. At Wave 0 the same 22 families were 3 built, 11 partial, 8 absent.
## Findings
@@@ -39,7 +39,7 @@ Families: 0 met, 21 partial, 0 not met, 1 blocked on owner (of 22). Requirements
- **D07-D10 Themes, notifications, social, analytics** (partial). D07: ADR-024 (accepted 2026-09-23) sets the boundary, and code and production follow it. Shared owns the token vocabulary, the built-in catalog and the first-paint loader, with a parity test. Network seeds its catalog from openvibe-shared/theme-sync and serves /api/themes (35 themes in network.db at 20:22Z). Media's page paints an inline #ov-critical canvas and loads the theme loader deferred. ADR-024's own acceptance tests are not automated: that every site paints with Network down, and that a preference follows the user across sites. The preference is stored in Network's user_preferences table, not in the user module the ADR names. D08: Network consumes three topics through Events: deals.watch.matched, trade.alert.triggered and, since Network 2a95548 (subscribed 2026-09-23 19:54 UTC), live.stream.started. It applies per-category preferences and uses an inbox so a redelivery never notifies twice; test/events-consumer.test.js covers this. In production at 20:22Z the consumer has received nothing: network_event_inbox is empty, and there has been no live.stream.started since 16:21 UTC. Live's direct go-live push still runs beside it (C-85), and all 675 STREAM_LIVE notifications came from that push. Browsers get the inbox by polling every 15 s plus Web Push, not through a realtime plane. D09: There is no canonical social graph yet. Live's follows table (62 rows in production at 20:22Z) is the real follow graph. Since Live 456eccd, other services can read it through GET /internal/followers (service token with live.follower.read, loopback only, paged), and Network's go-live consumer uses that read. Network's own follows table has 0 rows. Blocks exist only as Chat's dm_blocks, and memberships only inside Community and VIP. No product shares a follow, block or membership API. D10: Privacy governance is in place. ADR-021's module moved into Shared v1.4.0 (9aaf919), with a Sec-GPC/DNT opt-out and an analytics/event.v1 schema. Live and Network run it in production (releases c893c6ca7099 and 9bbd90f786fb at 20:22Z, both committed after the scan-root snapshot). Production holds no IP, user id or city in 780,665 Network and 1,773,833 Live analytics rows, and the oldest row is from 2026-08-24 (30-day prune). The analytics are not event-fed: each service runs a request-level tracker, creator analytics are Live's own queries on live.db, and nothing consumes OpenVibe.Events for analytics.
- **D11-D13 Events, realtime, SDK** (partial). D11: OpenVibe.Events is the production event store. At 20:21Z, /api/ready reported ready: db, JWKS and the delivery worker ok, DLQ depth 0. The store held 199 events from Live, Media, Chat, Games, VIP, Network, Wiki, Blog, Trade, OpenRe, Community and a developer app, and 16 subscriptions for 7 consumers; all 20 deliveries so far succeeded, with 0 failed or dead. The restore drill passed at 05:22. Tests prove retry with backoff, dead-lettering after 8 attempts, operator replay (by event and from a sequence), and exactly-once effects through the SDK inbox after a consumer crash. The store is SQLite, not the roadmap's PostgreSQL, a choice that rests on ADR-004 and ADR-007. D12: ADR-005 (accepted 2026-09-22) replaced the separate Realtime service with an SSE plane inside Events. The plane authorises each topic by visibility, resumes from Last-Event-ID, and sends gap markers. Since 18b873f it also redacts deleted chat messages and limits public replay to 300 s. Media and game traffic keep their own protocols. In production at 20:23Z, an anonymous replay from cursor 0 got only a gap marker. However, events_realtime_connections was 0: no product browser uses the plane, and presence does not exist. D13: openvibe-sdk v0.4.0 lives in a public repository and installs by tag. It has hand-written clients (core, auth, registry, identity, modules, events with outbox and inbox, realtime, media, community, jobs, projects), generated ESM and browser bundles, and contract types copied from Contracts' generated output. CI passed on the last three main runs (from 654d4b2, 20:20Z check), and 17 repositories pin it, 12 of them at v0.4.0. It still lacks Chat, Live, Billing and Games clients and a Media v2 object client, its contract types stop at Contracts v0.28.0 (Contracts is at v0.30.2), and it has only been tested against stubs and the mock platform.
- **D14-D16 Media** (partial). D14: The generalised model is in production. At 20:22Z Media held 3,056 media_objects, 2,881 media_locations, 1,288 media_relationships and 998 media_variants; the backfill projected every legacy row, is idempotent, and is tested. But it is still a projection of the predecessor tables: vods, clips and files are written first and then synced, and a failed sync only logs (C-75). So VODs and clips are not yet typed projections over objects. Namespaces are the :app tenants without per-namespace read, write, list, delete and transform grants, and there is no segment model. D15: Objects have a canonical lifecycle: uploading, then ready or failed, then soft delete with restore, plus retention holds and purge. Since cbf8410, Media writes each outcome's Events outbox row in the same transaction as the state change. Live consumes media.vod, media.clip and media.storage outcomes through Events (d2715e5, MEDIA_EVENTS_AUTHORITY=both) and applies each one once. There is no job system: media_jobs had 0 rows in production at 20:22Z, and no outcome has yet been applied through Live's Events inbox (its table is not created yet). Uploads are signed single-part PUTs to Media; there is no multipart or presigned direct-to-bucket upload. D16: Copies are explicit: media_locations holds one row per provider copy. In production at 20:22Z that was local 2,172 present and 2 missing, B2 684 present and 4 corrupt, and R2 19 present. Reconciliation detects missing canonical copies, lost files, size and hash mismatches, orphan location rows and deleted-but-served objects. Since e42af9e, a scheduled verification has run every 10 minutes (11 runs and 550 objects since 18:42 UTC). The v2 object API signs private downloads, and a private object answers exactly like a missing one. Still open: 6 ready objects have no good copy; orphan provider objects and incomplete multipart uploads are not detected; there is no R2-eviction drill; and native objects are never tiered to B2 or R2.
--- **D17-D20 Live, OpenRe, channel/VOD lineage** (partial). D17: Chat (2026-09-23 02:03 UTC), pastes (2026-09-22) and VOD/clip comments (Live b8afb71, deployed 2026-09-23 between 19:00 and 19:25 UTC) have left Live's authority, and the old response shapes and pages were kept. One UX regression from the paste move (broken AI Moments thumbnails) was fixed in Live 047f206. Production on 2026-09-23 20:23 UTC: CHAT_AUTHORITY, PASTES_AUTHORITY and AI_SERVICE are set in live.env, BILLING_AUTHORITY is not, Live still listens on *:1935, and all 102 slots have ingest_authority=live. Live therefore still holds ingest, money and calls. D18: Live f0ca18b (deployed, wired to OpenRe since 2026-09-23 19:23 UTC) rebinds a switched slot's key, ingest URL and key rotation to OpenRe, and sends restream edits to OpenRe's own destinations UI. On 2026-09-23 20:18 UTC no slot is switched (102/102 ingest_authority=live, openre_stream_id set on 0, openre_sessions 0), so no production Stream Manager control operates on OpenRe state yet. D19: OpenRe runs as its own units on production release e0dc1b4 (openre-api, session-coordinator, rtmp-ingest@ and restream-worker@ all active on 2026-09-23 20:19 UTC), with RTMP 1936 reachable from outside the host, a production worker generation rollover (generation 1 stopped, generation 2 ready), and a passed restore drill at 19:24 UTC. It carries no broadcaster: 0 of 102 slots are switched, openre.db has 1 session (the ended rehearsal) and 0 destinations, and WHIP, SFU and JSMPEG are not ported. D20: No lineage-resolver contract or shared resolver exists in any repo (no 'lineage' or resolver code in Contracts, Live, Media, OpenRe or Community on origin/main, 2026-09-23). The pieces that exist are the EntityRef typed-reference schema and OpenRe stream definitions carrying external refs to Live's slot and user; in production no Live slot has an openre_stream_id and openre_sessions is empty, so VOD to channel/stream/session lineage is not recorded.
++- **D17-D20 Live, OpenRe, channel/VOD lineage** (partial). D17: Chat (2026-09-23 02:03 UTC), pastes (2026-09-22) and VOD/clip comments (Live b8afb71, deployed 2026-09-23 between 19:00 and 19:25 UTC) have left Live's authority, and the old response shapes and pages were kept. One UX regression from the paste move (broken AI Moments thumbnails) was fixed in Live 047f206. Production on 2026-09-23 20:23 UTC: CHAT_AUTHORITY, PASTES_AUTHORITY and AI_SERVICE are set in live.env, BILLING_AUTHORITY is not, Live still listens on *:1935, and all 102 slots have ingest_authority=live. Live therefore still holds ingest, money and calls. D18: Live f0ca18b (deployed, wired to OpenRe since 2026-09-23 19:23 UTC) rebinds a switched slot's key, ingest URL and key rotation to OpenRe, and sends restream edits to OpenRe's own destinations UI. On 2026-09-23 20:18 UTC no slot is switched (102/102 ingest_authority=live, openre_stream_id set on 0, openre_sessions 0), so no production Stream Manager control operates on OpenRe state yet. D19: OpenRe runs as its own units on production release e0dc1b4 (openre-api, session-coordinator, rtmp-ingest@ and restream-worker@ all active on 2026-09-23 20:19 UTC), with RTMP 1936 reachable from outside the host, a production worker generation rollover (generation 1 stopped, generation 2 ready), and a passed restore drill at 19:24 UTC. It carries no broadcaster: 0 of 102 slots are switched, openre.db has 1 session (the ended rehearsal) and 0 destinations, and WHIP, SFU and JSMPEG are not ported. D20: The lineage-resolver contract exists (openvibe-contracts v0.32.0: lineage.resolve-request@1 -> lineage.resolution@1, capability live.lineage.resolve) and is implemented once in Live, deployed 2026-09-23 21:36 UTC: it answers which channel, and whose, a slug, nested slug, channel id, stream, slot, VOD, clip, Media object, owner subject or legacy id belongs to, in the roadmap's precedence, with explicit unresolved states (conflict, source_unavailable, display_name_only, not_found) and never from a display name; VODs, clips and objects come from Media. Live's clip owner check uses it. No other service calls it yet (no principal holds live.lineage.resolve), OpenRe sessions record no lineage, and Media objects still lack owner_subject.
- **D21-D23 Chat** (partial). D21: OpenVibe.Chat has been the production chat authority since 2026-09-23 02:03 UTC: CHAT_AUTHORITY is set in live.env, 12 tables have table_authority=chat, and chat.db holds 70,864 stream/global messages and 1,522 DMs in 11 conversations (checked 20:18 UTC; Chat active, NRestarts 0). Six staged tables are still Live's, call signalling is still Live's /ws/call, and Chat has no room, membership or unread model. D22: Chat enforces the chat.message.send capability on its service API (791cd3d, deployed in Chat 7897688 on 2026-09-23), checks DM participants on every route, and publishes chat.message.created (5 public events in Events on 20:23 UTC) with chat.message.deleted redaction. But browser tokens and roles are still resolved by Live, legacy token forms are still accepted, and no consumer subscribes to chat.* events. D23: History, DMs, TTS overrides, sounds and moderation were imported with stable ids and nothing held (70,864 messages and 1,522 DMs in chat.db on 2026-09-23 20:18 UTC; 15/15 read paths identical at cutover). Since the audit, Chat added a restart-and-cursor-resume test (49a5011) and a persisted TTS/sound queue with skip, clear and failure states (bf88760); one post-cutover regression (deploy cards folding across rooms) was fixed in 7897688. Calls are not migrated and there is no browser parity test.
- **D24-D27 Community** (partial). D24: Community is the production authority for pastes (since 2026-09-22) and for typed comment threads, including Live's VOD/clip comments since 2026-09-23 (on 20:18 UTC: 903 pastes; 40 threads = live/vod 22, live/clip 8, wiki/page 10; 20 comments; 3 spaces). Its store is SQLite, not PostgreSQL, under ADR-007, and the categories, attachments, moderation-action and external-message-map schema families do not exist. D25: Community serves spaces, threads, replies (posts), thread and comment votes, and staff moderation (pin, lock, delete, hide) over the API and as no-JS SSR pages; behavioural tests cover each, including concurrent votes. Production serves the forum (openvibe.community/s and /api/v1/spaces answer 200 with 3 public spaces on 2026-09-23 20:22 UTC) but has no threads yet; the wider §15.8 obligations (categories, tags, profiles, search) are outside this target. D26: Community has an outbound Discord relay for new threads, with dedupe, retry/backoff, loop prevention and an allow-list, covered by tests. It is off in production on 2026-09-23 (no DISCORD_* variables in community.env, 0 relay mappings, 0 deliveries). It does not run behind Events (Community publishes no relay events), and it has no edit/delete mapping and no inbound direction (schema allows direction 'out' only). D27: Community has been the paste authority since 2026-09-22 ~23:35 UTC: every source row was imported (889+2 pastes, 60 comments, 48 likes) with a legacy id map, reconciliation and sha256 checks, and 903 pastes, 991 legacy map rows and 3 migration runs were present on 2026-09-23 20:18 UTC. A pre-migration paste (created 2026-03-11) 301s from both Live and Media to Community, and pastes.openvibe.tools 301s to Community. The 5 ambiguous_owner holds (1 paste, 4 comments) were imported ownerless as the import-hold rule requires, and their attribution waits for the owner.
- **D28-D30 Billing, Tips, VIP** (blocked on owner). D28: Billing's balanced, append-only journal is deployed (c646279) with database triggers that refuse updates and deletes, hourly reconciliation (runs at 18:54, 19:05 and 20:04 UTC on 2026-09-23, all ok) and /metrics. It is still a shadow: all 322 transactions are `import`, every provider is off, and BILLING_AUTHORITY does not appear in live.env (count 0 at 20:18 UTC), so Live remains the ledger. D29: Tips settles through Billing and delivers to Live and Chat as retryable effects. It consumes Billing's EXTERNAL PowerChat receipts (Events subscriptions billing.transaction.* and billing.receipt.*). The Live history import was applied: 139 interactions, all test-era (128 imported, 11 external), 4 goals and 143 migration maps. No real settlement has happened yet: Billing is a shadow, the Events store holds 0 billing.* or tips.* events, TIPS_CHAT_ADAPTER=none, Live's /api/funds routes remain the authority, and openvibe.tips serves the Sites placeholder (checked 2026-09-23 20:19 UTC). D30: VIP has immutable plan versions and an entitlement projection fed by Billing events, with a tested convergence bound. Since the audit, consumers gate on it: Chat member badges (d02a73c), Community members-only spaces (57d1dd4), Blog members-only posts (95e99ac) and Network grants (50552b6). In production (2026-09-23 20:18 UTC) VIP holds 44 creators and 43 imported plans, but 0 memberships and 0 projections. Checkout providers are empty, Billing has 0 subscriptions and 0 entitlements, and openvibe.vip is the Sites placeholder.
ddiff --git a/docs/roadmap-baseline/10-hazards.md b/docs/roadmap-baseline/10-hazards.md
iindex f47d49c0..9c4711fb 100644
---- a/docs/roadmap-baseline/10-hazards.md
++++ b/docs/roadmap-baseline/10-hazards.md
@@@ -12,13 +12,13 @@ Deliverable 9. **Not yet reviewed by the production-host owner** (Wave 0 exit cr
| H4 | managed_streams.stream_key values still need rotation after a past leak | high | partial | **needed** | Live maintainers (security track S) | W7 (openre.key.rotate) - or earlier as a standalone rotation | The one key committed to a repository (in Live's control-bridge example since ac0d6a47) was rotated on 2026-09-23 and replaced by a placeholder, with the commit allow-listed in the secret scan. The leaked slot keys are rotated per slot at its OpenRe cutover (ADR-009, openre.key.rotate), or by a standalone rotation in Live if the cutover slips. | - |
| H5 | Multilingual Whisper model missing breaks non-English captions | medium | mitigated | - | Live maintainers | - | Install the model and set WHISPER_MODEL_MULTI in live.env. | WHISPER_MODEL_MULTI is set in live.env |
| H6 | YouTube refuses the server IP; the yt tool needs a proxy | low | blocked-on-owner | **needed** | Platform operator | W11 | Set YT_PROXY and/or YT_COOKIES_FILE for openvibe-tools-yt. | YT_PROXY unset in tools.env |
--| H7 | Workstation root disk near full; headless Chrome can hit ENOSPC | low | open | - | Workstation owner | Track Q | Browser harness must support a remote/containerised runner; prune ~/.claude transcripts (~1.2 GB). | workstation / is 86% used (at generation time) |
++| H7 | Workstation root disk near full; headless Chrome can hit ENOSPC | low | open | - | Workstation owner | Track Q | Browser harness must support a remote/containerised runner; prune ~/.claude transcripts (~1.2 GB). | workstation / is 87% used (at generation time) |
| H8 | A hardcoded internal secret was previously public | high | partial | **needed** | Platform operator (security track S) | W1 (scoped service principals) / Track S | Removed: the hard-coded openvibe-internal-2026 value and the hard-coded quest secret (register C-59, Live e505868). New services use Network-issued service tokens; Network records every legacy-key call per route (principal_usage) and the key-only routes have removal dates (register C-50..C-57). Remaining: rotate INTERNAL_API_KEY in every env file, then retire the key routes by their dates. | - |
| H9 | Removed features and copy rules must not be undone | medium | standing-rule | - | Every product wave | all | Product waves check the prohibitions list (roadmap 9.1) before adding copy or campaigns. | - |
| H10 | Commit identity | medium | partial | **needed** | Every contributor | all | Per-repo git config user.email = [email protected]; every new commit follows it. Older history keeps some assistant trailers. | main history violates the rule in: Live (238 commits with assistant trailers); Network (14 commits with assistant trailers); Media (30 commits with assistant trailers); Tools (9 commits with assistant trailers) |
| H11 | analytics_events grows without pruning | medium | mitigated | - | OpenVibe.Shared maintainers (openvibe-shared/analytics.js) | Track O / ADR-021 - before any schema wave touching Live or Network | ADR-021: no IP, user id or city stored; raw analytics events are pruned after 30 days on a schedule in Live (nightly job), Tools (timer) and Network (openvibe-shared analytics retention.schedulePrune since 9bbd90f), rollups kept. | largest analytics stores: live/data/analytics.db 500.5 MB; network/data/network.db 277.7 MB; tools/apps/audio/data/analytics.db 35.4 MB; tools/apps/text/data/analytics.db 5.5 MB |
| H12 | No Cloudflare cache-purge step after deploys | low | blocked-on-owner | **needed** | Platform operator | W21 / Track I | Cache Rules "browser_ttl respect_origin" on every openvibe.* zone and openre.stream (2026-09-23) make the edge follow origin max-age; Search has a purge queue that stays inert until a purge-scoped token exists (CLOUDFLARE_PURGE_TOKEN). | CLOUDFLARE_PURGE_TOKEN unset in search.env |
--| H13 | Production drifts from main | medium | open | - | Platform operator | W0 (checklist) / W21 (release manifests) | Deploy or record why each lagging service is held back. | ai: deployed 96dc8a3 is 1 commit(s) behind origin/main 3a480ac; billing: deployed c646279 is 1 commit(s) behind origin/main aa445d0; codes: deployed d60f279 is 1 commit(s) behind origin/main 51d2386; coupons: deployed 54df411 is 3 commit(s) behind origin/main 1c57c47; deals: deployed e72aeec is 2 commit(s) behind origin/main 91ca223; events: deployed 3366132 is 1 commit(s) behind origin/main efc09a7; games: deployed 474df50 is 1 commit(s) behind origin/main 7863fc6; host: deployed 30f08d6 is 14 commit(s) behind origin/main ea99b50; news: deployed 5a17e7f is 1 commit(s) behind origin/main 5b393d2; openre: deployed e0dc1b4 is 2 commit(s) behind origin/main c091a09; reviews: deployed 1d462a2 is 1 commit(s) behind origin/main a7b50a6; sites: deployed d3b71af is 2 commit(s) behind origin/main d6e4cbd; tips: deployed 15bfc12 is 1 commit(s) behind origin/main 9a3a186; trade: deployed 9a55644 is 2 commit(s) behind origin/main ddbc60c; wiki: deployed 011a68f is 1 commit(s) behind origin/main b4e70ac |
++| H13 | Production drifts from main | medium | open | - | Platform operator | W0 (checklist) / W21 (release manifests) | Deploy or record why each lagging service is held back. | ai: deployed 96dc8a3 is 1 commit(s) behind origin/main 3a480ac; billing: deployed c646279 is 1 commit(s) behind origin/main aa445d0; chat: deployed 7897688 is 2 commit(s) behind origin/main ed90461; codes: deployed d60f279 is 1 commit(s) behind origin/main 51d2386; community: deployed 57d1dd4 is 1 commit(s) behind origin/main 63b90a8; coupons: deployed 54df411 is 3 commit(s) behind origin/main 1c57c47; deals: deployed e72aeec is 2 commit(s) behind origin/main 91ca223; events: deployed 3366132 is 1 commit(s) behind origin/main efc09a7; games: deployed 474df50 is 1 commit(s) behind origin/main 7863fc6; host: deployed 30f08d6 is 15 commit(s) behind origin/main 03dfcb3; live: deployed c893c6c is 12 commit(s) behind origin/main ca7cc87; media: deployed 9de4b25 is 4 commit(s) behind origin/main ad2217b; network: deployed 9bbd90f is 4 commit(s) behind origin/main 09bf748; news: deployed 5a17e7f is 1 commit(s) behind origin/main 5b393d2; openre: deployed e0dc1b4 is 2 commit(s) behind origin/main c091a09; reviews: deployed 1d462a2 is 1 commit(s) behind origin/main a7b50a6; sites: deployed d3b71af is 2 commit(s) behind origin/main d6e4cbd; tips: deployed 15bfc12 is 6 commit(s) behind origin/main f211c03; trade: deployed 9a55644 is 2 commit(s) behind origin/main ddbc60c; vip: deployed 9668a49 is 1 commit(s) behind origin/main fe7eaad; wiki: deployed 011a68f is 1 commit(s) behind origin/main b4e70ac |
| H14 | Dead and backup database files on the production host | low | open | **needed** | Live maintainers | W0 | Confirm no code opens them, then delete the empty files; move copies (backups, import snapshots, rehearsal databases) to /var/backups/openvibe with a retention date. | community/data/community.db, games/data/legacy-import/world-before-20260923T184930Z.db, live/data/backups/analytics-pre-adr021-2026-09-23.db, live/data/backups/live-pre-643a2e6.db, live/data/hobo.db, live/data/openvibe.db, tips/data/tips.db, tools/backups/analytics-2026-09-23/audio.analytics.db, tools/backups/analytics-2026-09-23/docs.analytics.db, tools/backups/analytics-2026-09-23/food.analytics.db, tools/backups/analytics-2026-09-23/img.analytics.db, tools/backups/analytics-2026-09-23/maps.analytics.db, tools/backups/analytics-2026-09-23/text.analytics.db, tools/backups/analytics-2026-09-23/yt.analytics.db, billing/live-snapshot-202609230121.db, chat/live-snap-a.db, chat/live-snap-b.db, chat/live-snapshot-0159.db, chat/rehearsal.db, community/community.pre-live-comments-20260923T191345Z.db |
| H15 | Media objects with no good copy | medium | blocked-on-owner | **needed** | Media maintainers | W4 (repair) / W22 (DR drills) | Scheduled copy verification now runs inside Media and reports through /api/ready (object_copies); the 6 objects are marked degraded. Each needs a decision: re-upload from a surviving source, or mark it unrecoverable and tell its owner. | - |
| H16 | Off-host backups are unreadable without the backup key, which lives only on the host | high | blocked-on-owner | **needed** | Production-host owner | W22 | Escrow the key offline (password manager or paper), record its key id (`ovhost offsite check`) next to it, and test a restore from the bucket with the escrowed copy. | openvibe-backup.timer is active/waiting |
ddiff --git a/docs/roadmap-baseline/README.md b/docs/roadmap-baseline/README.md
iindex 07bc785a..5986d342 100644
---- a/docs/roadmap-baseline/README.md
++++ b/docs/roadmap-baseline/README.md
@@@ -2,32 +2,32 @@
The audit baseline from the OpenVibe development roadmap (Wave 0; section 12 items 1-3): what exists across the estate, who owns each piece of data today and who should, what production looks like next to the repos, and which hazards constrain later waves. Every file here except `data/*.json` is generated.
--Source commits: Live `c893c6c`, Network `9bbd90f`, Shared `c6405d4`, Media `9de4b25`, Tools `5d1b423`, Community `57d1dd4`, Games `7863fc6`, Sites `d6e4cbd`, Events `efc09a7`, Chat `7897688`, OpenRe.Stream `c091a09`, Billing `aa445d0`, Tips `9a3a186`, VIP `9668a49`, AI `3a480ac`, Search `a707e38`, Sources `2e986af`, Wiki `b4e70ac`, Blog `95e99ac`, News `5b393d2`, Reviews `a7b50a6`, Deals `91ca223`, Coupons `1c57c47`, Trade `ddbc60c`, Codes `51d2386`, Host `ea99b50`, Examples `d5f4efc`. Production snapshot: openvibe-oregon, 2026-09-23.
++Source commits: Live `ca7cc87`, Network `09bf748`, Shared `c272680`, Media `ad2217b`, Tools `5d1b423`, Community `63b90a8`, Games `7863fc6`, Sites `d6e4cbd`, Events `efc09a7`, Chat `ed90461`, OpenRe.Stream `c091a09`, Billing `aa445d0`, Tips `f211c03`, VIP `fe7eaad`, AI `3a480ac`, Search `a707e38`, Sources `2e986af`, Wiki `b4e70ac`, Blog `95e99ac`, News `5b393d2`, Reviews `a7b50a6`, Deals `91ca223`, Coupons `1c57c47`, Trade `ddbc60c`, Codes `51d2386`, Host `03dfcb3`, Examples `d5f4efc`. Production snapshot: openvibe-oregon, 2026-09-23.
## Deliverables
| # | Artifact | Contents |
|---|---|---|
| 1 | [01-services.md](01-services.md) | services, ports, units, env files, repo state, GitHub census |
--| 2 | [02-schema.md](02-schema.md) | 612 tables with current/target owner |
--| 3 | [03-routes.md](03-routes.md), [04-cross-service.md](04-cross-service.md) | 2055 routes; 97 cross-service call sites |
++| 2 | [02-schema.md](02-schema.md) | 621 tables with current/target owner |
++| 3 | [03-routes.md](03-routes.md), [04-cross-service.md](04-cross-service.md) | 2098 routes; 98 cross-service call sites |
| 4 | [05-realtime-and-jobs.md](05-realtime-and-jobs.md) | WebSocket servers and paths, non-HTTP protocols, background jobs |
| 5 | [06-secrets.md](06-secrets.md) | auth mechanisms and secret names (no values) |
| 6 | [07-ownership.md](07-ownership.md) | current vs target data ownership |
--| 7 | [08-discrepancies.md](08-discrepancies.md) | 260 production-vs-repo items |
++| 7 | [08-discrepancies.md](08-discrepancies.md) | 276 production-vs-repo items |
| 8 | [09-d-status.md](09-d-status.md) | D01-D46 family status, derived from the requirement ledger (families: 0 met, 21 partial, 0 not met, 1 blocked on owner) |
| 9 | [10-hazards.md](10-hazards.md) | 18 hazards with owners, mitigations and waves; 10 need the owner's review |
--| 10 | [requirement-ledger.md](requirement-ledger.md), [requirement-ledger.json](requirement-ledger.json) | D01-D46 with acceptance artifacts (roadmap §22.4/§25): 3 met, 35 partial, 1 not met, 7 blocked on owner |
++| 10 | [requirement-ledger.md](requirement-ledger.md), [requirement-ledger.json](requirement-ledger.json) | D01-D46 with acceptance artifacts (roadmap §22.4/§25): 3 met, 36 partial, 0 not met, 7 blocked on owner |
| - | [inventory.json](inventory.json) | everything above, machine-readable |
## Exit criteria
| | Criterion | Result |
|---|---|---|
--| pass | Every table has an owner classification | 612 tables classified, 0 unclassified |
--| pass | Every route is attributed to a repo and source line, with an owner classification | 2055 routes, 0 unclassified; 0 router mounts whose module could not be resolved (their routes are listed without the mount prefix) |
--| pass | Every background job is listed with its location and an owner classification | 141 timers/jobs, 0 unclassified |
--| pass | Every cross-service call records caller, callee, auth, timeout and retry | 97 call sites; 36 with no timeout detected |
++| pass | Every table has an owner classification | 621 tables classified, 0 unclassified |
++| pass | Every route is attributed to a repo and source line, with an owner classification | 2098 routes, 0 unclassified; 0 router mounts whose module could not be resolved (their routes are listed without the mount prefix) |
++| pass | Every background job is listed with its location and an owner classification | 145 timers/jobs, 0 unclassified |
++| pass | Every cross-service call records caller, callee, auth, timeout and retry | 98 call sites; 36 with no timeout detected |
| pass | Unknowns are marked unknown, not guessed | 2 unknown items recorded |
| pass | Every D01-D46 requirement has a status and verified acceptance artifacts (requirement ledger) | 46/46 requirements verified |
| **open** | Hazard register reviewed by the production-host owner | pending: set reviewedBy in data/hazards.json after review |
ddiff --git a/docs/roadmap-baseline/data/requirement-ledger.json b/docs/roadmap-baseline/data/requirement-ledger.json
iindex ef9a5860..17a6efd8 100644
---- a/docs/roadmap-baseline/data/requirement-ledger.json
++++ b/docs/roadmap-baseline/data/requirement-ledger.json
@@@ -1190,38 +1190,37 @@
{
"id": "D20",
"title": "Canonical resolver",
-- "owner": "none (per-product mappings in OpenVibe.Live; typed refs in OpenVibe.Contracts)",
++ "owner": "OpenVibe.Live (server/lineage/resolver.js, GET|POST /internal/lineage/resolve); contract in OpenVibe.Contracts",
"target": "shared lineage-resolver contract",
-- "status": "not-met",
-- "summary": "No lineage-resolver contract or shared resolver exists in any repo (no 'lineage' or resolver code in Contracts, Live, Media, OpenRe or Community on origin/main, 2026-09-23). The pieces that exist are the EntityRef typed-reference schema and OpenRe stream definitions carrying external refs to Live's slot and user; in production no Live slot has an openre_stream_id and openre_sessions is empty, so VOD to channel/stream/session lineage is not recorded.",
++ "status": "partial",
++ "summary": "The lineage-resolver contract exists (openvibe-contracts v0.32.0: lineage.resolve-request@1 -> lineage.resolution@1, capability live.lineage.resolve) and is implemented once in Live, deployed 2026-09-23 21:36 UTC: it answers which channel, and whose, a slug, nested slug, channel id, stream, slot, VOD, clip, Media object, owner subject or legacy id belongs to, in the roadmap's precedence, with explicit unresolved states (conflict, source_unavailable, display_name_only, not_found) and never from a display name; VODs, clips and objects come from Media. Live's clip owner check uses it. No other service calls it yet (no principal holds live.lineage.resolve), OpenRe sessions record no lineage, and Media objects still lack owner_subject.",
"artifacts": [
{
"kind": "doc",
"repo": "OpenVibe.Contracts",
-- "path": "contracts/common/entity-ref.v1.json",
-- "contains": "Typed reference to another service's entity",
-- "proves": "only a typed-reference schema is shared; it carries no resolution rules or lineage"
++ "path": "contracts/lineage/resolve-request.v1.json",
++ "contains": "LineageResolveRequest",
++ "proves": "the shared resolver contract (inputs) is published in v0.32.0"
},
{
"kind": "test",
"repo": "OpenVibe.Live",
-- "path": "test/openre-switch.test.js",
-- "contains": "['live:managed_stream:701', 'live:user:601']",
-- "proves": "an OpenRe definition records typed refs back to Live's slot and owner: one lineage input, not a shared resolver"
++ "path": "test/lineage-resolver.test.js",
++ "contains": "expectUnresolved({ display_name: 'alice' }, 'display_name_only')",
++ "proves": "the resolver never derives ownership from a display name, even one equal to a username; every answer is validated against lineage.resolution@1"
},
{
"kind": "prod",
-- "check": "ssh openvibe-ovh 'sudo -n -u \"$(stat -c %U /opt/openvibe.live/data/live.db)\" sqlite3 -readonly /opt/openvibe.live/data/live.db \"SELECT count(*), sum(openre_stream_id IS NOT NULL) FROM managed_streams; SELECT count(*) FROM openre_sessions;\"'",
-- "observed": "102|0; 0",
-- "at": "2026-09-23T20:18Z",
-- "proves": "no stream/session lineage exists in production to resolve against"
++ "check": "ssh openvibe-ovh 'curl -s -o /dev/null -w \"%{http_code}\" \"http://127.0.0.1:3000/internal/lineage/resolve?slug=goosely\"'",
++ "observed": "401",
++ "at": "2026-09-23T21:37Z",
++ "proves": "the resolver is deployed on production behind a service token (loopback only; 403 through nginx)"
}
],
"remaining": [
-- "Write the lineage-resolver contract in OpenVibe.Contracts (inputs: explicit slug, nested/parent slug, channel id, stream lookup, VOD parent, media lineage, owner subject, legacy metadata and maps; output includes an explicit unresolved state)",
-- "Implement it once and use it from channel, stream, VOD, clip, Pulse and creator UI; never derive ownership from a display name",
-- "Record VOD/clip lineage to channel, stream and OpenRe session (roadmap §20 'VOD lineage maps back to the canonical channel, stream and session') with a test that an unresolvable item returns unresolved",
-- "Backfill Media owner_subject so the resolver has a subject for every object"
++ "Grant live.lineage.resolve to the consumers (OpenRe, Media, Pulse, creator UI) once their contracts pin is 0.32.0+, and switch their per-product channel mappings to the resolver",
++ "Record VOD/clip lineage to OpenRe session (roadmap §20 'VOD lineage maps back to the canonical channel, stream and session'); no OpenRe session exists in production yet",
++ "Backfill Media owner_subject so the resolver has a subject for every object (Live now knows the subject of all 328 linked accounts)"
],
"blockedOn": null,
"ownerReview": false
ddiff --git a/docs/roadmap-baseline/inventory.json b/docs/roadmap-baseline/inventory.json
iindex ad09c1ec..d892e844 100644
---- a/docs/roadmap-baseline/inventory.json
++++ b/docs/roadmap-baseline/inventory.json
@@@ -1,19 +1,19 @@
{
"generatedFrom": {
-- "OpenVibe.Live": "c893c6ca709926635522bac053f52062b5d3e1ad",
-- "OpenVibe.Network": "9bbd90f786fb80b02cbf7592ff9217844a714c32",
-- "OpenVibe.Shared": "c6405d48fabede75e2a9ef417fae46d493cfb940",
-- "OpenVibe.Media": "9de4b2528dd5787e7b5633d16eed40d8b4d43b4b",
++ "OpenVibe.Live": "ca7cc87672602e35756b8b348559543efab1bc38",
++ "OpenVibe.Network": "09bf748b7f459ac127b3f4045085c20189d39dbb",
++ "OpenVibe.Shared": "c2726807c19505bc22d2bce794188a9d1516b022",
++ "OpenVibe.Media": "ad2217be56627efca799fd3ce0987d91cb6f3e24",
"OpenVibe.Tools": "5d1b42357392d47e5cc3f6bef3f22facdc6c23cd",
-- "OpenVibe.Community": "57d1dd4cbdc79f39ae5e98cc0d09b03a75508f5d",
++ "OpenVibe.Community": "63b90a838d280aada7d6c98aee61335b972c1105",
"OpenVibe.Games": "7863fc6a71890b264c29ddd6bfa7e4c162da4883",
"OpenVibe.Sites": "d6e4cbd3a2091bb9970ee15504c7758da8a96a24",
"OpenVibe.Events": "efc09a795ea0fdea9e6eca04f20cc44362b91e3f",
-- "OpenVibe.Chat": "789768806b0d217b0bc735c319d20d1b6ebb4df8",
++ "OpenVibe.Chat": "ed90461e2fd4537332275f6efec8bb878ce4ac2a",
"OpenRe.Stream": "c091a0959a6d727ec702ee589300cd42a0902be9",
"OpenVibe.Billing": "aa445d0c8b7351afae910b9572a2f9ae674e0914",
-- "OpenVibe.Tips": "9a3a186182df7d150780b31d191ea1eb99c95962",
-- "OpenVibe.VIP": "9668a492b8f5b6c111261cf0e4270fc4ffcf521d",
++ "OpenVibe.Tips": "f211c03ed01b58dd52d104bda8b07ce1a82da2db",
++ "OpenVibe.VIP": "fe7eaad183622f303d2ea1efde80d1674478d948",
"OpenVibe.AI": "3a480ac9f20ca018f5c2c8973f92d32dbe1a44cd",
"OpenVibe.Search": "a707e38f87a077bbf2f570537a89b2f890d45e22",
"OpenVibe.Sources": "2e986af27a5554fd01803daf9e55c726deded80d",
@@@ -25,7 +25,7 @@
"OpenVibe.Coupons": "1c57c4743b016ecf6f72d8d03feb7f56806920a6",
"OpenVibe.Trade": "ddbc60c5e2f5ab16cfd17cd126803c9c24784662",
"OpenVibe.Codes": "51d23865f2630203cf734c019309c7ffc053f89c",
-- "OpenVibe.Host": "ea99b502c072ae6635f7705e002e0ec174cae16d",
++ "OpenVibe.Host": "03dfcb32a9fecb85d509f5d92d0a166a26d86fe7",
"OpenVibe.Examples": "d5f4efc02165f42b9feac5d2743de6e6c75c27de"
},
"prodSnapshot": {
@@@ -38,13 +38,13 @@
"service": "live",
"present": true,
"git": {
-- "head": "c893c6ca709926635522bac053f52062b5d3e1ad",
++ "head": "ca7cc87672602e35756b8b348559543efab1bc38",
"branch": "main",
-- "originMain": "c893c6ca709926635522bac053f52062b5d3e1ad",
-- "committedAt": "2026-09-23T13:15:56-07:00"
++ "originMain": "ca7cc87672602e35756b8b348559543efab1bc38",
++ "committedAt": "2026-09-23T14:33:07-07:00"
},
-- "sourceFiles": 189,
-- "loc": 74113,
++ "sourceFiles": 194,
++ "loc": 74460,
"tables": [
{
"table": "arena_profiles",
@@@ -301,175 +301,175 @@
{
"table": "relay_users",
"file": "server/db/database.js",
-- "line": 1473,
++ "line": 1472,
"via": "repo"
},
{
"table": "payment_orders",
"file": "server/db/database.js",
-- "line": 1595,
++ "line": 1567,
"via": "repo"
},
{
"table": "channel_moderators",
"file": "server/db/database.js",
-- "line": 1628,
++ "line": 1600,
"via": "repo"
},
{
"table": "channel_moderation_settings",
"file": "server/db/database.js",
-- "line": 1645,
++ "line": 1617,
"via": "repo"
},
{
"table": "emotes_new",
"file": "server/db/database.js",
-- "line": 1716,
++ "line": 1688,
"via": "repo"
},
{
"table": "channel_sounds",
"file": "server/db/database.js",
-- "line": 1748,
++ "line": 1720,
"via": "repo"
},
{
"table": "channel_sounds_new",
"file": "server/db/database.js",
-- "line": 1772,
++ "line": 1744,
"via": "repo"
},
{
"table": "ai_chatbot_configs",
"file": "server/db/database.js",
-- "line": 1810,
++ "line": 1782,
"via": "repo"
},
{
"table": "channel_ai_bots",
"file": "server/db/database.js",
-- "line": 1835,
++ "line": 1807,
"via": "repo"
},
{
"table": "channel_ai_config",
"file": "server/db/database.js",
-- "line": 1859,
++ "line": 1831,
"via": "repo"
},
{
"table": "ai_viewer_threads",
"file": "server/db/database.js",
-- "line": 1880,
++ "line": 1852,
"via": "repo"
},
{
"table": "ai_viewer_log",
"file": "server/db/database.js",
-- "line": 1894,
++ "line": 1866,
"via": "repo"
},
{
"table": "moderation_actions",
"file": "server/db/database.js",
-- "line": 1927,
++ "line": 1899,
"via": "repo"
},
{
"table": "pastes",
"file": "server/db/database.js",
-- "line": 1946,
++ "line": 1918,
"via": "repo"
},
{
"table": "paste_likes",
"file": "server/db/database.js",
-- "line": 1983,
++ "line": 1955,
"via": "repo"
},
{
"table": "paste_comments",
"file": "server/db/database.js",
-- "line": 2015,
++ "line": 1987,
"via": "repo"
},
{
"table": "stream_first_chats",
"file": "server/db/database.js",
-- "line": 2047,
++ "line": 2019,
"via": "repo"
},
{
"table": "ip_log",
"file": "server/db/database.js",
-- "line": 2058,
++ "line": 2030,
"via": "repo"
},
{
"table": "approved_ips",
"file": "server/db/database.js",
-- "line": 2082,
++ "line": 2054,
"via": "repo"
},
{
"table": "pending_ip_messages",
"file": "server/db/database.js",
-- "line": 2099,
++ "line": 2071,
"via": "repo"
},
{
"table": "hidden_relay_users",
"file": "server/db/database.js",
-- "line": 2119,
++ "line": 2091,
"via": "repo"
},
{
"table": "control_whitelist",
"file": "server/db/database.js",
-- "line": 2284,
++ "line": 2249,
"via": "repo"
},
{
"table": "control_configs",
"file": "server/db/database.js",
-- "line": 2299,
++ "line": 2264,
"via": "repo"
},
{
"table": "control_config_buttons",
"file": "server/db/database.js",
-- "line": 2313,
++ "line": 2278,
"via": "repo"
},
{
"table": "stream_controls_new",
"file": "server/db/database.js",
-- "line": 2392,
++ "line": 2357,
"via": "repo"
},
{
"table": "managed_streams",
"file": "server/db/database.js",
-- "line": 2427,
++ "line": 2392,
"via": "repo"
},
{
"table": "vibe_coding_sessions",
"file": "server/db/database.js",
-- "line": 2649,
++ "line": 2614,
"via": "repo"
},
{
"table": "vibe_coding_events",
"file": "server/db/database.js",
-- "line": 2684,
++ "line": 2649,
"via": "repo"
},
{
"table": "viewer_samples",
"file": "server/db/database.js",
-- "line": 3983,
++ "line": 3832,
"via": "repo"
},
{
@@@ -910,7 +910,7 @@
"method": "GET",
"path": "/api/admin/admins",
"file": "server/admin/routes.js",
-- "line": 788,
++ "line": 796,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -920,7 +920,7 @@
"method": "POST",
"path": "/api/admin/admins",
"file": "server/admin/routes.js",
-- "line": 798,
++ "line": 806,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -930,7 +930,7 @@
"method": "DELETE",
"path": "/api/admin/admins/:id",
"file": "server/admin/routes.js",
-- "line": 817,
++ "line": 825,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -940,7 +940,7 @@
"method": "GET",
"path": "/api/admin/ai/explorer/:userId",
"file": "server/admin/routes.js",
-- "line": 577,
++ "line": 580,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -950,7 +950,7 @@
"method": "GET",
"path": "/api/admin/ai/overviews",
"file": "server/admin/routes.js",
-- "line": 609,
++ "line": 617,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -960,7 +960,7 @@
"method": "GET",
"path": "/api/admin/ai/status",
"file": "server/admin/routes.js",
-- "line": 567,
++ "line": 569,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -970,7 +970,7 @@
"method": "POST",
"path": "/api/admin/ai/streamer/:userId/overview",
"file": "server/admin/routes.js",
-- "line": 618,
++ "line": 626,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -980,7 +980,7 @@
"method": "GET",
"path": "/api/admin/ai/usage",
"file": "server/admin/routes.js",
-- "line": 520,
++ "line": 522,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -990,7 +990,7 @@
"method": "POST",
"path": "/api/admin/ai/viewers/:userId/:action",
"file": "server/admin/routes.js",
-- "line": 548,
++ "line": 550,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1000,7 +1000,7 @@
"method": "GET",
"path": "/api/admin/ai/viewers/:userId/log",
"file": "server/admin/routes.js",
-- "line": 558,
++ "line": 560,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1010,7 +1010,7 @@
"method": "GET",
"path": "/api/admin/ai/viewers/status",
"file": "server/admin/routes.js",
-- "line": 530,
++ "line": 532,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1020,7 +1020,7 @@
"method": "GET",
"path": "/api/admin/analytics",
"file": "server/index.js",
-- "line": 707,
++ "line": 709,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1030,7 +1030,7 @@
"method": "GET",
"path": "/api/admin/analytics/bots",
"file": "server/index.js",
-- "line": 716,
++ "line": 718,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1040,7 +1040,7 @@
"method": "GET",
"path": "/api/admin/bans",
"file": "server/admin/routes.js",
-- "line": 427,
++ "line": 429,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1050,7 +1050,7 @@
"method": "POST",
"path": "/api/admin/broadcast",
"file": "server/index.js",
-- "line": 824,
++ "line": 826,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1060,7 +1060,7 @@
"method": "PUT",
"path": "/api/admin/channels/:id/force-nsfw",
"file": "server/admin/routes.js",
-- "line": 368,
++ "line": 370,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1080,7 +1080,7 @@
"method": "DELETE",
"path": "/api/admin/media-tools/cookies",
"file": "server/admin/routes.js",
-- "line": 1242,
++ "line": 1250,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1090,7 +1090,7 @@
"method": "PUT",
"path": "/api/admin/media-tools/cookies",
"file": "server/admin/routes.js",
-- "line": 1161,
++ "line": 1169,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1100,7 +1100,7 @@
"method": "POST",
"path": "/api/admin/media-tools/cookies/check",
"file": "server/admin/routes.js",
-- "line": 1220,
++ "line": 1228,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1110,7 +1110,7 @@
"method": "DELETE",
"path": "/api/admin/media-tools/extra-args",
"file": "server/admin/routes.js",
-- "line": 1275,
++ "line": 1283,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1120,7 +1120,7 @@
"method": "PUT",
"path": "/api/admin/media-tools/extra-args",
"file": "server/admin/routes.js",
-- "line": 1256,
++ "line": 1264,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1130,7 +1130,7 @@
"method": "GET",
"path": "/api/admin/media-tools/status",
"file": "server/admin/routes.js",
-- "line": 1116,
++ "line": 1124,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1140,7 +1140,7 @@
"method": "POST",
"path": "/api/admin/media-tools/test",
"file": "server/admin/routes.js",
-- "line": 1286,
++ "line": 1294,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1150,7 +1150,7 @@
"method": "GET",
"path": "/api/admin/moderators",
"file": "server/admin/routes.js",
-- "line": 723,
++ "line": 731,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1160,7 +1160,7 @@
"method": "POST",
"path": "/api/admin/moderators",
"file": "server/admin/routes.js",
-- "line": 735,
++ "line": 743,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1170,7 +1170,7 @@
"method": "DELETE",
"path": "/api/admin/moderators/:id",
"file": "server/admin/routes.js",
-- "line": 762,
++ "line": 770,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1180,7 +1180,7 @@
"method": "GET",
"path": "/api/admin/money",
"file": "server/admin/routes.js",
-- "line": 481,
++ "line": 483,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1190,7 +1190,7 @@
"method": "POST",
"path": "/api/admin/money/actions/:id/resolve",
"file": "server/admin/routes.js",
-- "line": 495,
++ "line": 497,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1200,7 +1200,7 @@
"method": "POST",
"path": "/api/admin/money/freeze",
"file": "server/admin/routes.js",
-- "line": 489,
++ "line": 491,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1230,7 +1230,7 @@
"method": "GET",
"path": "/api/admin/settings",
"file": "server/admin/routes.js",
-- "line": 508,
++ "line": 510,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1240,7 +1240,7 @@
"method": "PUT",
"path": "/api/admin/settings",
"file": "server/admin/routes.js",
-- "line": 633,
++ "line": 641,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1250,7 +1250,7 @@
"method": "DELETE",
"path": "/api/admin/settings/:key",
"file": "server/admin/routes.js",
-- "line": 706,
++ "line": 714,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1260,7 +1260,7 @@
"method": "PUT",
"path": "/api/admin/settings/:key",
"file": "server/admin/routes.js",
-- "line": 689,
++ "line": 697,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1280,7 +1280,7 @@
"method": "GET",
"path": "/api/admin/storage",
"file": "server/admin/routes.js",
-- "line": 961,
++ "line": 969,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1290,7 +1290,7 @@
"method": "DELETE",
"path": "/api/admin/storage/clips/bulk",
"file": "server/admin/routes.js",
-- "line": 1066,
++ "line": 1074,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1300,7 +1300,7 @@
"method": "GET",
"path": "/api/admin/storage/vods",
"file": "server/admin/routes.js",
-- "line": 1016,
++ "line": 1024,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1310,7 +1310,7 @@
"method": "DELETE",
"path": "/api/admin/storage/vods/bulk",
"file": "server/admin/routes.js",
-- "line": 1035,
++ "line": 1043,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1320,7 +1320,7 @@
"method": "GET",
"path": "/api/admin/streams",
"file": "server/admin/routes.js",
-- "line": 303,
++ "line": 305,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1330,7 +1330,7 @@
"method": "DELETE",
"path": "/api/admin/streams/:id",
"file": "server/admin/routes.js",
-- "line": 322,
++ "line": 324,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1340,7 +1340,7 @@
"method": "PUT",
"path": "/api/admin/streams/:id/nsfw",
"file": "server/admin/routes.js",
-- "line": 416,
++ "line": 418,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1350,7 +1350,7 @@
"method": "GET",
"path": "/api/admin/users",
"file": "server/admin/routes.js",
-- "line": 119,
++ "line": 121,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1360,7 +1360,7 @@
"method": "PUT",
"path": "/api/admin/users/:id",
"file": "server/admin/routes.js",
-- "line": 156,
++ "line": 158,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1370,7 +1370,7 @@
"method": "DELETE",
"path": "/api/admin/users/:id/ban",
"file": "server/admin/routes.js",
-- "line": 284,
++ "line": 286,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1380,7 +1380,7 @@
"method": "POST",
"path": "/api/admin/users/:id/ban",
"file": "server/admin/routes.js",
-- "line": 246,
++ "line": 248,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1390,7 +1390,7 @@
"method": "PUT",
"path": "/api/admin/users/:id/force-vod-recording",
"file": "server/admin/routes.js",
-- "line": 385,
++ "line": 387,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1400,7 +1400,7 @@
"method": "GET",
"path": "/api/admin/verification-keys",
"file": "server/admin/routes.js",
-- "line": 839,
++ "line": 847,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1410,7 +1410,7 @@
"method": "POST",
"path": "/api/admin/verification-keys",
"file": "server/admin/routes.js",
-- "line": 849,
++ "line": 857,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1420,7 +1420,7 @@
"method": "DELETE",
"path": "/api/admin/verification-keys/:id",
"file": "server/admin/routes.js",
-- "line": 892,
++ "line": 900,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1430,7 +1430,7 @@
"method": "GET",
"path": "/api/admin/vpn-queue",
"file": "server/admin/routes.js",
-- "line": 443,
++ "line": 445,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1440,7 +1440,7 @@
"method": "PUT",
"path": "/api/admin/vpn-queue/:id",
"file": "server/admin/routes.js",
-- "line": 459,
++ "line": 461,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1800,7 +1800,7 @@
"method": "GET",
"path": "/api/auth/avatar/history",
"file": "server/auth/routes.js",
-- "line": 246,
++ "line": 248,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1810,7 +1810,7 @@
"method": "GET",
"path": "/api/auth/callback",
"file": "server/auth/routes.js",
-- "line": 488,
++ "line": 491,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1830,7 +1830,7 @@
"method": "POST",
"path": "/api/auth/fedcm",
"file": "server/auth/routes.js",
-- "line": 465,
++ "line": 468,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1840,7 +1840,7 @@
"method": "GET",
"path": "/api/auth/ice-servers",
"file": "server/auth/routes.js",
-- "line": 900,
++ "line": 903,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1860,7 +1860,7 @@
"method": "GET",
"path": "/api/auth/logout",
"file": "server/auth/routes.js",
-- "line": 627,
++ "line": 630,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1870,7 +1870,7 @@
"method": "POST",
"path": "/api/auth/logout",
"file": "server/auth/routes.js",
-- "line": 620,
++ "line": 623,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1890,7 +1890,7 @@
"method": "GET",
"path": "/api/auth/preferences",
"file": "server/auth/routes.js",
-- "line": 679,
++ "line": 682,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1900,7 +1900,7 @@
"method": "PUT",
"path": "/api/auth/preferences",
"file": "server/auth/routes.js",
-- "line": 689,
++ "line": 692,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1920,7 +1920,7 @@
"method": "POST",
"path": "/api/auth/refresh",
"file": "server/auth/routes.js",
-- "line": 558,
++ "line": 561,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1940,7 +1940,7 @@
"method": "GET",
"path": "/api/auth/sso/login",
"file": "server/auth/routes.js",
-- "line": 312,
++ "line": 315,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1950,7 +1950,7 @@
"method": "GET",
"path": "/api/auth/sso/status",
"file": "server/auth/routes.js",
-- "line": 638,
++ "line": 641,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1980,7 +1980,7 @@
"method": "GET",
"path": "/api/auth/tokens",
"file": "server/auth/routes.js",
-- "line": 859,
++ "line": 862,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -1990,7 +1990,7 @@
"method": "POST",
"path": "/api/auth/tokens",
"file": "server/auth/routes.js",
-- "line": 821,
++ "line": 824,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -2000,7 +2000,7 @@
"method": "DELETE",
"path": "/api/auth/tokens/:id",
"file": "server/auth/routes.js",
-- "line": 879,
++ "line": 882,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -2130,7 +2130,7 @@
"method": "GET",
"path": "/api/chat-ai/live-captions/:username",
"file": "server/ai/chat-ai-routes.js",
-- "line": 230,
++ "line": 236,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -2170,7 +2170,7 @@
"method": "GET",
"path": "/api/chat-ai/transcript/:streamId",
"file": "server/ai/chat-ai-routes.js",
-- "line": 329,
++ "line": 335,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -2190,7 +2190,7 @@
"method": "GET",
"path": "/api/chat-ai/vod-transcripts",
"file": "server/ai/chat-ai-routes.js",
-- "line": 267,
++ "line": 273,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -2410,7 +2410,7 @@
"method": "GET",
"path": "/api/clips",
"file": "server/media-proxy/clips.js",
-- "line": 166,
++ "line": 168,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2420,7 +2420,7 @@
"method": "DELETE",
"path": "/api/clips/:id",
"file": "server/media-proxy/clips.js",
-- "line": 335,
++ "line": 337,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2430,7 +2430,7 @@
"method": "GET",
"path": "/api/clips/:id",
"file": "server/media-proxy/clips.js",
-- "line": 195,
++ "line": 197,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2440,7 +2440,7 @@
"method": "POST",
"path": "/api/clips/:id/recut",
"file": "server/media-proxy/clips.js",
-- "line": 354,
++ "line": 356,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2450,7 +2450,7 @@
"method": "PUT",
"path": "/api/clips/:id/title",
"file": "server/media-proxy/clips.js",
-- "line": 269,
++ "line": 271,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2460,7 +2460,7 @@
"method": "PUT",
"path": "/api/clips/:id/visibility",
"file": "server/media-proxy/clips.js",
-- "line": 286,
++ "line": 288,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2470,7 +2470,7 @@
"method": "POST",
"path": "/api/clips/bulk",
"file": "server/media-proxy/clips.js",
-- "line": 310,
++ "line": 312,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2480,7 +2480,7 @@
"method": "GET",
"path": "/api/clips/mine",
"file": "server/media-proxy/clips.js",
-- "line": 118,
++ "line": 120,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2490,7 +2490,7 @@
"method": "GET",
"path": "/api/clips/my-stream",
"file": "server/media-proxy/clips.js",
-- "line": 132,
++ "line": 134,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2500,7 +2500,7 @@
"method": "GET",
"path": "/api/clips/settings/channel",
"file": "server/media-proxy/clips.js",
-- "line": 144,
++ "line": 146,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -2510,7 +2510,7 @@
"method": "PUT",
"path": "/api/clips/settings/channel",
"file": "server/media-proxy/clips.js",
-- "line": 153,
++ "line": 155,
"target": "OpenVibe.Media",
"disposition": "adapter",
"wave": "W4",
@@@ -3060,7 +3060,7 @@
"method": "POST",
"path": "/api/csp-report",
"file": "server/index.js",
-- "line": 845,
++ "line": 847,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3560,7 +3560,7 @@
"method": "GET",
"path": "/api/health",
"file": "server/index.js",
-- "line": 726,
++ "line": 728,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3570,7 +3570,7 @@
"method": "GET",
"path": "/api/home/digest",
"file": "server/home/routes.js",
-- "line": 457,
++ "line": 437,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3580,7 +3580,7 @@
"method": "GET",
"path": "/api/home/discover",
"file": "server/home/routes.js",
-- "line": 507,
++ "line": 487,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3590,7 +3590,7 @@
"method": "GET",
"path": "/api/home/featured",
"file": "server/home/routes.js",
-- "line": 247,
++ "line": 227,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3600,7 +3600,7 @@
"method": "GET",
"path": "/api/home/hero",
"file": "server/home/routes.js",
-- "line": 333,
++ "line": 313,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3610,7 +3610,7 @@
"method": "GET",
"path": "/api/home/pulse",
"file": "server/home/routes.js",
-- "line": 406,
++ "line": 386,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3620,7 +3620,7 @@
"method": "GET",
"path": "/api/home/star",
"file": "server/home/routes.js",
-- "line": 352,
++ "line": 332,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3630,7 +3630,7 @@
"method": "POST",
"path": "/api/home/star/rotate",
"file": "server/home/routes.js",
-- "line": 569,
++ "line": 549,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3640,7 +3640,7 @@
"method": "GET",
"path": "/api/home/stats-live",
"file": "server/home/routes.js",
-- "line": 287,
++ "line": 267,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3650,7 +3650,7 @@
"method": "GET",
"path": "/api/home/stats/series/:metric",
"file": "server/home/routes.js",
-- "line": 177,
++ "line": 166,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -3710,7 +3710,7 @@
"method": "GET",
"path": "/api/live-events",
"file": "server/index.js",
-- "line": 649,
++ "line": 651,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -4750,7 +4750,7 @@
"method": "GET",
"path": "/api/ready",
"file": "server/index.js",
-- "line": 764,
++ "line": 766,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5100,7 +5100,7 @@
"method": "GET",
"path": "/api/streams",
"file": "server/streaming/routes.js",
-- "line": 1086,
++ "line": 1093,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5110,7 +5110,7 @@
"method": "POST",
"path": "/api/streams",
"file": "server/streaming/routes.js",
-- "line": 1908,
++ "line": 1924,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5120,7 +5120,7 @@
"method": "DELETE",
"path": "/api/streams/:id",
"file": "server/streaming/routes.js",
-- "line": 2103,
++ "line": 2119,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5130,7 +5130,7 @@
"method": "GET",
"path": "/api/streams/:id",
"file": "server/streaming/routes.js",
-- "line": 1860,
++ "line": 1876,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5140,7 +5140,7 @@
"method": "PUT",
"path": "/api/streams/:id",
"file": "server/streaming/routes.js",
-- "line": 2052,
++ "line": 2068,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5150,7 +5150,7 @@
"method": "GET",
"path": "/api/streams/:id/call",
"file": "server/streaming/routes.js",
-- "line": 2422,
++ "line": 2438,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5160,7 +5160,7 @@
"method": "PUT",
"path": "/api/streams/:id/call",
"file": "server/streaming/routes.js",
-- "line": 2383,
++ "line": 2399,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5170,7 +5170,7 @@
"method": "GET",
"path": "/api/streams/:id/endpoint",
"file": "server/streaming/routes.js",
-- "line": 2150,
++ "line": 2166,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5180,7 +5180,7 @@
"method": "POST",
"path": "/api/streams/:id/follow",
"file": "server/streaming/routes.js",
-- "line": 2291,
++ "line": 2307,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5190,7 +5190,7 @@
"method": "POST",
"path": "/api/streams/:id/heartbeat",
"file": "server/streaming/routes.js",
-- "line": 2248,
++ "line": 2264,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5200,7 +5200,7 @@
"method": "GET",
"path": "/api/streams/:id/rtmp-status",
"file": "server/streaming/routes.js",
-- "line": 2266,
++ "line": 2282,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5210,7 +5210,7 @@
"method": "GET",
"path": "/api/streams/broadcast-settings",
"file": "server/streaming/routes.js",
-- "line": 1385,
++ "line": 1393,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5220,7 +5220,7 @@
"method": "PUT",
"path": "/api/streams/broadcast-settings",
"file": "server/streaming/routes.js",
-- "line": 1402,
++ "line": 1410,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5230,7 +5230,7 @@
"method": "GET",
"path": "/api/streams/channel",
"file": "server/streaming/routes.js",
-- "line": 638,
++ "line": 645,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5240,7 +5240,7 @@
"method": "PUT",
"path": "/api/streams/channel",
"file": "server/streaming/routes.js",
-- "line": 650,
++ "line": 657,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5260,7 +5260,7 @@
"method": "PUT",
"path": "/api/streams/channel/:username/about",
"file": "server/streaming/routes.js",
-- "line": 765,
++ "line": 772,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5270,7 +5270,7 @@
"method": "GET",
"path": "/api/streams/channel/:username/bio-en",
"file": "server/streaming/routes.js",
-- "line": 746,
++ "line": 753,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5280,7 +5280,7 @@
"method": "GET",
"path": "/api/streams/channel/:username/clips-taken",
"file": "server/streaming/routes.js",
-- "line": 557,
++ "line": 564,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5290,7 +5290,7 @@
"method": "POST",
"path": "/api/streams/channel/:username/follow",
"file": "server/streaming/routes.js",
-- "line": 2336,
++ "line": 2352,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5300,7 +5300,7 @@
"method": "GET",
"path": "/api/streams/channel/:username/live",
"file": "server/streaming/routes.js",
-- "line": 600,
++ "line": 607,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5310,7 +5310,7 @@
"method": "GET",
"path": "/api/streams/channel/:username/popular",
"file": "server/streaming/routes.js",
-- "line": 531,
++ "line": 538,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5320,7 +5320,7 @@
"method": "GET",
"path": "/api/streams/channel/:username/resolve/:ref",
"file": "server/streaming/routes.js",
-- "line": 1424,
++ "line": 1432,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5330,7 +5330,7 @@
"method": "GET",
"path": "/api/streams/channel/:username/weather",
"file": "server/streaming/routes.js",
-- "line": 975,
++ "line": 982,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5340,7 +5340,7 @@
"method": "POST",
"path": "/api/streams/channel/offline-screen",
"file": "server/streaming/routes.js",
-- "line": 871,
++ "line": 878,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5350,7 +5350,7 @@
"method": "POST",
"path": "/api/streams/diag-log",
"file": "server/streaming/routes.js",
-- "line": 2241,
++ "line": 2257,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5360,7 +5360,7 @@
"method": "POST",
"path": "/api/streams/goal-media",
"file": "server/streaming/routes.js",
-- "line": 836,
++ "line": 843,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5370,7 +5370,7 @@
"method": "GET",
"path": "/api/streams/managed",
"file": "server/streaming/routes.js",
-- "line": 1578,
++ "line": 1594,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5380,7 +5380,7 @@
"method": "POST",
"path": "/api/streams/managed",
"file": "server/streaming/routes.js",
-- "line": 1590,
++ "line": 1606,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5390,7 +5390,7 @@
"method": "DELETE",
"path": "/api/streams/managed/:id",
"file": "server/streaming/routes.js",
-- "line": 1804,
++ "line": 1820,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5400,7 +5400,7 @@
"method": "PUT",
"path": "/api/streams/managed/:id",
"file": "server/streaming/routes.js",
-- "line": 1644,
++ "line": 1660,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5410,7 +5410,7 @@
"method": "POST",
"path": "/api/streams/managed/:id/regenerate-key",
"file": "server/streaming/routes.js",
-- "line": 1829,
++ "line": 1845,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5420,7 +5420,7 @@
"method": "GET",
"path": "/api/streams/managed/:managedStreamId/history",
"file": "server/streaming/routes.js",
-- "line": 1458,
++ "line": 1466,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5430,7 +5430,7 @@
"method": "GET",
"path": "/api/streams/managed/:managedStreamId/profile",
"file": "server/streaming/routes.js",
-- "line": 1472,
++ "line": 1487,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5440,7 +5440,7 @@
"method": "GET",
"path": "/api/streams/mine",
"file": "server/streaming/routes.js",
-- "line": 1122,
++ "line": 1129,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5450,7 +5450,7 @@
"method": "POST",
"path": "/api/streams/panel-image",
"file": "server/streaming/routes.js",
-- "line": 814,
++ "line": 821,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5460,7 +5460,7 @@
"method": "GET",
"path": "/api/streams/recent",
"file": "server/streaming/routes.js",
-- "line": 1134,
++ "line": 1141,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5470,7 +5470,7 @@
"method": "GET",
"path": "/api/streams/recent-vods",
"file": "server/streaming/routes.js",
-- "line": 1204,
++ "line": 1212,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5480,7 +5480,7 @@
"method": "GET",
"path": "/api/streams/recently-online",
"file": "server/streaming/routes.js",
-- "line": 1150,
++ "line": 1158,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5490,7 +5490,7 @@
"method": "GET",
"path": "/api/streams/rtmp-proxy/:streamId.flv",
"file": "server/streaming/routes.js",
-- "line": 2443,
++ "line": 2459,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5500,7 +5500,7 @@
"method": "GET",
"path": "/api/streams/setup-progress",
"file": "server/streaming/routes.js",
-- "line": 1524,
++ "line": 1539,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5510,7 +5510,7 @@
"method": "GET",
"path": "/api/streams/voice-channels",
"file": "server/streaming/routes.js",
-- "line": 1234,
++ "line": 1242,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5520,7 +5520,7 @@
"method": "POST",
"path": "/api/streams/voice-channels",
"file": "server/streaming/routes.js",
-- "line": 1255,
++ "line": 1263,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5530,7 +5530,7 @@
"method": "DELETE",
"path": "/api/streams/voice-channels/:channelId",
"file": "server/streaming/routes.js",
-- "line": 1267,
++ "line": 1275,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5540,7 +5540,7 @@
"method": "GET",
"path": "/api/streams/voice-channels/:channelId",
"file": "server/streaming/routes.js",
-- "line": 1244,
++ "line": 1252,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5550,7 +5550,7 @@
"method": "POST",
"path": "/api/streams/voice-channels/call-user",
"file": "server/streaming/routes.js",
-- "line": 1279,
++ "line": 1287,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5560,7 +5560,7 @@
"method": "POST",
"path": "/api/streams/voice-channels/call-user/respond",
"file": "server/streaming/routes.js",
-- "line": 1348,
++ "line": 1356,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -5770,7 +5770,7 @@
"method": "GET",
"path": "/api/updates",
"file": "server/index.js",
-- "line": 811,
++ "line": 813,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -6010,7 +6010,7 @@
"method": "GET",
"path": "/banned",
"file": "server/index.js",
-- "line": 979,
++ "line": 985,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -6020,7 +6020,7 @@
"method": "POST",
"path": "/banned/continue",
"file": "server/index.js",
-- "line": 949,
++ "line": 955,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -6030,7 +6030,7 @@
"method": "GET",
"path": "/canvas",
"file": "server/index.js",
-- "line": 682,
++ "line": 684,
"target": "OpenVibe.Games",
"disposition": "compat",
"wave": "W12",
@@@ -6040,7 +6040,7 @@
"method": "GET",
"path": "/data/pastes/screenshots/:filename",
"file": "server/index.js",
-- "line": 600,
++ "line": 602,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -6050,7 +6050,7 @@
"method": "GET",
"path": "/dmca",
"file": "server/index.js",
-- "line": 888,
++ "line": 894,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -6090,7 +6090,7 @@
"method": "GET",
"path": "/game",
"file": "server/index.js",
-- "line": 681,
++ "line": 683,
"target": "OpenVibe.Games",
"disposition": "compat",
"wave": "W12",
@@@ -6956,6 +6956,26 @@
"wave": "W3",
"note": "Live consumer and provider endpoints (media events, OpenRe events, followers, tips deliveries, chat context, analytics summary)."
},
++ {
++ "method": "GET",
++ "path": "/internal/lineage/resolve",
++ "file": "server/lineage/routes.js",
++ "line": 33,
++ "target": "OpenVibe.Live",
++ "disposition": "keep",
++ "wave": "W3",
++ "note": "Live consumer and provider endpoints (media events, OpenRe events, followers, tips deliveries, chat context, analytics summary)."
++ },
++ {
++ "method": "POST",
++ "path": "/internal/lineage/resolve",
++ "file": "server/lineage/routes.js",
++ "line": 34,
++ "target": "OpenVibe.Live",
++ "disposition": "keep",
++ "wave": "W3",
++ "note": "Live consumer and provider endpoints (media events, OpenRe events, followers, tips deliveries, chat context, analytics summary)."
++ },
{
"method": "POST",
"path": "/internal/media-events",
@@@ -7030,7 +7050,7 @@
"method": "GET",
"path": "/media/:username",
"file": "server/index.js",
-- "line": 883,
++ "line": 885,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7040,7 +7060,7 @@
"method": "GET",
"path": "/obs/chat/:username",
"file": "server/index.js",
-- "line": 871,
++ "line": 873,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7060,7 +7080,7 @@
"method": "GET",
"path": "/overlay/chat/:username",
"file": "server/index.js",
-- "line": 879,
++ "line": 881,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7070,7 +7090,7 @@
"method": "GET",
"path": "/overlay/chat/:username/:slotIdOrSlug",
"file": "server/index.js",
-- "line": 876,
++ "line": 878,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7080,7 +7100,7 @@
"method": "GET",
"path": "/p/:slug",
"file": "server/index.js",
-- "line": 618,
++ "line": 620,
"target": "OpenVibe.Community",
"disposition": "adapter",
"wave": "W5 (done)",
@@@ -7090,7 +7110,7 @@
"method": "GET",
"path": "/p/:slug/raw",
"file": "server/index.js",
-- "line": 629,
++ "line": 631,
"target": "OpenVibe.Community",
"disposition": "adapter",
"wave": "W5 (done)",
@@@ -7100,7 +7120,7 @@
"method": "GET",
"path": "/p/:slug/screenshot",
"file": "server/index.js",
-- "line": 625,
++ "line": 627,
"target": "OpenVibe.Community",
"disposition": "adapter",
"wave": "W5 (done)",
@@@ -7110,7 +7130,7 @@
"method": "GET",
"path": "/pastes",
"file": "server/index.js",
-- "line": 619,
++ "line": 621,
"target": "OpenVibe.Community",
"disposition": "adapter",
"wave": "W5 (done)",
@@@ -7120,7 +7140,7 @@
"method": "GET",
"path": "/privacy",
"file": "server/index.js",
-- "line": 897,
++ "line": 903,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7130,7 +7150,7 @@
"method": "GET",
"path": "/release.json",
"file": "server/index.js",
-- "line": 751,
++ "line": 753,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7140,7 +7160,7 @@
"method": "GET",
"path": "/sitemap.xml",
"file": "server/seo/seo.js",
-- "line": 597,
++ "line": 602,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7150,7 +7170,7 @@
"method": "GET",
"path": "/terms",
"file": "server/index.js",
-- "line": 894,
++ "line": 900,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7160,7 +7180,7 @@
"method": "GET",
"path": "/tos",
"file": "server/index.js",
-- "line": 891,
++ "line": 897,
"target": "OpenVibe.Live",
"disposition": "keep",
"wave": "-",
@@@ -7170,7 +7190,7 @@
"method": "POST",
"path": "/whip/:streamId",
"file": "server/index.js",
-- "line": 906,
++ "line": 912,
"target": "OpenRe.Stream",
"disposition": "extract",
"wave": "W7",
@@@ -7180,7 +7200,7 @@
"method": "DELETE",
"path": "/whip/:streamId/:resourceId",
"file": "server/index.js",
-- "line": 908,
++ "line": 914,
"target": "OpenRe.Stream",
"disposition": "extract",
"wave": "W7",
@@@ -7190,7 +7210,7 @@
"method": "PATCH",
"path": "/whip/:streamId/:resourceId",
"file": "server/index.js",
-- "line": 907,
++ "line": 913,
"target": "OpenRe.Stream",
"disposition": "extract",
"wave": "W7",
@@@ -7253,50 +7273,45 @@
"file": "server/index.js",
"line": 437
},
-- {
-- "path": "/ws/",
-- "file": "server/index.js",
-- "line": 1000
-- },
{
"path": "/ws/chat",
"file": "server/index.js",
-- "line": 1038
++ "line": 1042
},
{
"path": "/ws/vibe-coding/publish",
"file": "server/index.js",
-- "line": 1040
++ "line": 1044
},
{
"path": "/ws/broadcast",
"file": "server/index.js",
-- "line": 1042
++ "line": 1046
},
{
"path": "/ws/control",
"file": "server/index.js",
-- "line": 1044
++ "line": 1048
},
{
"path": "/ws/call",
"file": "server/index.js",
-- "line": 1046
++ "line": 1050
},
{
"path": "/ws/game",
"file": "server/index.js",
-- "line": 1048
++ "line": 1052
},
{
"path": "/ws/canvas",
"file": "server/index.js",
-- "line": 1048
++ "line": 1052
},
{
"path": "/ws/robotstreamer-publish",
"file": "server/index.js",
-- "line": 1050
++ "line": 1054
},
{
"path": "/ws/robotstreamer-publish",
@@@ -7317,6 +7332,11 @@
"path": "/ws/vibe-coding/publish",
"file": "server/vibe-coding/publish-server.js",
"line": 31
++ },
++ {
++ "path": "/ws/",
++ "file": "server/web/page-status.js",
++ "line": 180
}
]
},
@@@ -7675,6 +7695,10 @@
"RS_PASSTHROUGH_INJECT_PARAMS": [
"server/integrations/rs-passthrough-relay.js"
],
++ "MEDIA_API_KEY": [
++ "server/lineage/media-source.js",
++ "server/media-client.js"
++ ],
"YTDLP_PATH": [
"server/media/media-downloader.js"
],
@@@ -7684,9 +7708,6 @@
"PATH": [
"server/media/media-downloader.js"
],
-- "MEDIA_API_KEY": [
-- "server/media-client.js"
-- ],
"LIVE_THUMBS_PATH": [
"server/media-proxy/live-thumbs.js"
],
@@@ -8243,7 +8264,7 @@
"refs": [
{
"via": "OV_COMMUNITY_URL",
-- "line": 427
++ "line": 432
}
]
}
@@@ -8349,7 +8370,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": 300000,
-- "line": 500,
++ "line": 495,
"file": "server/ai/ai-moments-job.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8360,7 +8381,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 312,
++ "line": 308,
"file": "server/ai/auto-clip-job.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8569,7 +8590,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": 300000,
-- "line": 583,
++ "line": 563,
"file": "server/home/routes.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8591,7 +8612,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": 21600000,
-- "line": 1310,
++ "line": 1314,
"file": "server/index.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8602,7 +8623,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": 45000,
-- "line": 1327,
++ "line": 1331,
"file": "server/index.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8613,7 +8634,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 1351,
++ "line": 1355,
"file": "server/index.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8624,7 +8645,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 1362,
++ "line": 1366,
"file": "server/index.js",
"target": "OpenVibe.Live",
"disposition": "keep",
@@@ -8907,9 +8928,9 @@
"note": "Live product jobs. AI jobs call OpenVibe.AI (AI_SERVICE=remote); analytics is ADR-021; events/stream-events.js relays the outbox; openre/mirror.js is inert until slots cut over."
}
],
-- "contractTodos": 15,
++ "contractTodos": 14,
"unresolvedMounts": [],
-- "testFiles": 78,
++ "testFiles": 81,
"ci": true
},
{
@@@ -8917,13 +8938,13 @@
"service": "network",
"present": true,
"git": {
-- "head": "9bbd90f786fb80b02cbf7592ff9217844a714c32",
++ "head": "09bf748b7f459ac127b3f4045085c20189d39dbb",
"branch": "main",
-- "originMain": "9bbd90f786fb80b02cbf7592ff9217844a714c32",
-- "committedAt": "2026-09-23T13:18:14-07:00"
++ "originMain": "09bf748b7f459ac127b3f4045085c20189d39dbb",
++ "committedAt": "2026-09-23T14:33:16-07:00"
},
-- "sourceFiles": 67,
-- "loc": 14871,
++ "sourceFiles": 68,
++ "loc": 15275,
"tables": [
{
"table": "admin_rate_limits",
@@@ -9156,19 +9177,31 @@
{
"table": "user_modules",
"file": "server/identity/modules.js",
-- "line": 24,
++ "line": 75,
++ "via": "repo"
++ },
++ {
++ "table": "user_module_revisions",
++ "file": "server/identity/modules.js",
++ "line": 86,
++ "via": "repo"
++ },
++ {
++ "table": "user_module_retirements",
++ "file": "server/identity/modules.js",
++ "line": 93,
"via": "repo"
},
{
"table": "principal_grants",
"file": "server/identity/principals.js",
-- "line": 151,
++ "line": 164,
"via": "repo"
},
{
"table": "principal_usage",
"file": "server/identity/principals.js",
-- "line": 161,
++ "line": 174,
"via": "repo"
},
{
@@@ -9180,7 +9213,7 @@
{
"table": "stream_live_announcements",
"file": "server/notifications/stream-live.js",
-- "line": 17,
++ "line": 31,
"via": "repo"
},
{
@@@ -9385,7 +9418,7 @@
"method": "GET",
"path": "/api/auth/anon-identities",
"file": "server/auth/routes.js",
-- "line": 641,
++ "line": 647,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9605,7 +9638,7 @@
"method": "DELETE",
"path": "/api/auth/sessions",
"file": "server/auth/routes.js",
-- "line": 723,
++ "line": 729,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9615,7 +9648,7 @@
"method": "GET",
"path": "/api/auth/sessions",
"file": "server/auth/routes.js",
-- "line": 679,
++ "line": 685,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9625,7 +9658,7 @@
"method": "POST",
"path": "/api/auth/sessions",
"file": "server/auth/routes.js",
-- "line": 692,
++ "line": 698,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9635,7 +9668,7 @@
"method": "DELETE",
"path": "/api/auth/sessions/:id",
"file": "server/auth/routes.js",
-- "line": 714,
++ "line": 720,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9645,7 +9678,7 @@
"method": "GET",
"path": "/api/auth/users/:id/card",
"file": "server/auth/routes.js",
-- "line": 734,
++ "line": 740,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9655,7 +9688,7 @@
"method": "DELETE",
"path": "/api/auth/users/:id/follow",
"file": "server/auth/routes.js",
-- "line": 817,
++ "line": 823,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9665,7 +9698,7 @@
"method": "POST",
"path": "/api/auth/users/:id/follow",
"file": "server/auth/routes.js",
-- "line": 786,
++ "line": 792,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9845,7 +9878,7 @@
"method": "GET",
"path": "/api/modules",
"file": "server/identity/modules.js",
-- "line": 101,
++ "line": 322,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9855,7 +9888,7 @@
"method": "DELETE",
"path": "/api/modules/:ns",
"file": "server/identity/modules.js",
-- "line": 126,
++ "line": 347,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9865,7 +9898,7 @@
"method": "GET",
"path": "/api/modules/:ns",
"file": "server/identity/modules.js",
-- "line": 109,
++ "line": 330,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9875,7 +9908,7 @@
"method": "PUT",
"path": "/api/modules/:ns",
"file": "server/identity/modules.js",
-- "line": 117,
++ "line": 338,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9885,7 +9918,17 @@
"method": "GET",
"path": "/api/modules/:ns/public/:subject",
"file": "server/identity/modules.js",
-- "line": 93,
++ "line": 314,
++ "target": "OpenVibe.Network",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "DELETE",
++ "path": "/api/modules/modules/:ns/:subject",
++ "file": "server/identity/modules.js",
++ "line": 382,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9895,7 +9938,7 @@
"method": "GET",
"path": "/api/modules/modules/:ns/:subject",
"file": "server/identity/modules.js",
-- "line": 140,
++ "line": 362,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -9905,7 +9948,7 @@
"method": "PUT",
"path": "/api/modules/modules/:ns/:subject",
"file": "server/identity/modules.js",
-- "line": 149,
++ "line": 371,
"target": "OpenVibe.Network",
"disposition": "keep",
"wave": "-",
@@@ -12247,7 +12290,18 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 732,
++ "line": 740,
++ "file": "server/index.js",
++ "target": "OpenVibe.Network",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "Runs in, and for, the service that owns it."
++ },
++ {
++ "kind": "setInterval",
++ "name": null,
++ "intervalMs": null,
++ "line": 743,
"file": "server/index.js",
"target": "OpenVibe.Network",
"disposition": "keep",
@@@ -12257,7 +12311,7 @@
],
"contractTodos": 0,
"unresolvedMounts": [],
-- "testFiles": 28,
++ "testFiles": 29,
"ci": true
},
{
@@@ -12265,13 +12319,13 @@
"service": "shared",
"present": true,
"git": {
-- "head": "c6405d48fabede75e2a9ef417fae46d493cfb940",
++ "head": "c2726807c19505bc22d2bce794188a9d1516b022",
"branch": "main",
-- "originMain": "c6405d48fabede75e2a9ef417fae46d493cfb940",
-- "committedAt": "2026-09-23T12:38:03-07:00"
++ "originMain": "c2726807c19505bc22d2bce794188a9d1516b022",
++ "committedAt": "2026-09-23T13:40:53-07:00"
},
-- "sourceFiles": 45,
-- "loc": 10921,
++ "sourceFiles": 47,
++ "loc": 11774,
"tables": [],
"routes": [
{
@@@ -12284,16 +12338,6 @@
"wave": "-",
"note": "The service is the authority for its own API and pages."
},
-- {
-- "method": "GET",
-- "path": "/release.json",
-- "file": "release.js",
-- "line": 8,
-- "target": "OpenVibe.Shared",
-- "disposition": "keep",
-- "wave": "-",
-- "note": "The service is the authority for its own API and pages."
-- },
{
"method": "GET",
"path": "/shared/:file",
@@@ -12466,11 +12510,11 @@
},
{
"via": "/api/auth/me",
-- "line": 1010
++ "line": 1013
},
{
"via": "/api/auth/me",
-- "line": 1013
++ "line": 1016
}
]
}
@@@ -12530,8 +12574,8 @@
{
"kind": "setInterval",
"name": null,
-- "intervalMs": 30000,
-- "line": 88,
++ "intervalMs": null,
++ "line": 170,
"file": "release-watch.js",
"target": "OpenVibe.Shared",
"disposition": "keep",
@@@ -12542,7 +12586,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": 600000,
-- "line": 89,
++ "line": 175,
"file": "release-watch.js",
"target": "OpenVibe.Shared",
"disposition": "keep",
@@@ -12552,7 +12596,7 @@
],
"contractTodos": 0,
"unresolvedMounts": [],
-- "testFiles": 17,
++ "testFiles": 19,
"ci": true
},
{
@@@ -12560,13 +12604,13 @@
"service": "media",
"present": true,
"git": {
-- "head": "9de4b2528dd5787e7b5633d16eed40d8b4d43b4b",
++ "head": "ad2217be56627efca799fd3ce0987d91cb6f3e24",
"branch": "main",
-- "originMain": "9de4b2528dd5787e7b5633d16eed40d8b4d43b4b",
-- "committedAt": "2026-09-23T13:04:44-07:00"
++ "originMain": "ad2217be56627efca799fd3ce0987d91cb6f3e24",
++ "committedAt": "2026-09-23T14:23:36-07:00"
},
-- "sourceFiles": 38,
-- "loc": 11376,
++ "sourceFiles": 47,
++ "loc": 13469,
"tables": [
{
"table": "apps",
@@@ -12655,31 +12699,43 @@
{
"table": "media_jobs",
"file": "server/db/schema.sql",
-- "line": 279,
++ "line": 281,
++ "via": "repo"
++ },
++ {
++ "table": "media_uploads",
++ "file": "server/db/schema.sql",
++ "line": 312,
++ "via": "repo"
++ },
++ {
++ "table": "media_upload_parts",
++ "file": "server/db/schema.sql",
++ "line": 328,
"via": "repo"
},
{
"table": "media_holds",
"file": "server/db/schema.sql",
-- "line": 293,
++ "line": 338,
"via": "repo"
},
{
"table": "media_invariant_violations",
"file": "server/db/schema.sql",
-- "line": 306,
++ "line": 351,
"via": "repo"
},
{
"table": "media_verifications",
"file": "server/db/schema.sql",
-- "line": 320,
++ "line": 365,
"via": "repo"
},
{
"table": "media_verify_runs",
"file": "server/db/schema.sql",
-- "line": 332,
++ "line": 377,
"via": "repo"
},
{
@@@ -12694,7 +12750,7 @@
"method": "GET",
"path": "/api/ready",
"file": "server/observability.js",
-- "line": 132,
++ "line": 140,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13104,7 +13160,7 @@
"method": "GET",
"path": "/api/v1/:app/stats",
"file": "server/index.js",
-- "line": 114,
++ "line": 115,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13114,7 +13170,7 @@
"method": "GET",
"path": "/api/v1/:app/stats/series/:metric",
"file": "server/index.js",
-- "line": 124,
++ "line": 125,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13124,7 +13180,7 @@
"method": "POST",
"path": "/api/v1/:app/thumbnails/:kind/:id",
"file": "server/thumbnails/routes.js",
-- "line": 38,
++ "line": 42,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13270,11 +13326,71 @@
"wave": "-",
"note": "The service is the authority for its own API and pages."
},
++ {
++ "method": "GET",
++ "path": "/api/v2/:app/jobs",
++ "file": "server/jobs/routes.js",
++ "line": 63,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v2/:app/jobs",
++ "file": "server/jobs/routes.js",
++ "line": 76,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "DELETE",
++ "path": "/api/v2/:app/jobs/:jobId",
++ "file": "server/jobs/routes.js",
++ "line": 135,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v2/:app/jobs/:jobId",
++ "file": "server/jobs/routes.js",
++ "line": 108,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v2/:app/jobs/:jobId/approve",
++ "file": "server/jobs/routes.js",
++ "line": 113,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v2/:app/jobs/:jobId/cancel",
++ "file": "server/jobs/routes.js",
++ "line": 134,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
{
"method": "GET",
"path": "/api/v2/:app/objects",
"file": "server/objects/routes.js",
-- "line": 278,
++ "line": 497,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13284,7 +13400,7 @@
"method": "POST",
"path": "/api/v2/:app/objects",
"file": "server/objects/routes.js",
-- "line": 188,
++ "line": 261,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13294,7 +13410,7 @@
"method": "DELETE",
"path": "/api/v2/:app/objects/:id",
"file": "server/objects/routes.js",
-- "line": 308,
++ "line": 527,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13304,7 +13420,7 @@
"method": "GET",
"path": "/api/v2/:app/objects/:id",
"file": "server/objects/routes.js",
-- "line": 303,
++ "line": 522,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13314,7 +13430,7 @@
"method": "GET",
"path": "/api/v2/:app/objects/:id",
"file": "server/objects/routes.js",
-- "line": 382,
++ "line": 601,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13324,7 +13440,7 @@
"method": "POST",
"path": "/api/v2/:app/objects/:id/complete",
"file": "server/objects/routes.js",
-- "line": 244,
++ "line": 371,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13344,7 +13460,7 @@
"method": "GET",
"path": "/api/v2/:app/objects/:id/download",
"file": "server/objects/routes.js",
-- "line": 334,
++ "line": 553,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13354,7 +13470,7 @@
"method": "GET",
"path": "/api/v2/:app/objects/:id/holds",
"file": "server/objects/routes.js",
-- "line": 353,
++ "line": 572,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13364,7 +13480,7 @@
"method": "POST",
"path": "/api/v2/:app/objects/:id/holds",
"file": "server/objects/routes.js",
-- "line": 359,
++ "line": 578,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13374,7 +13490,57 @@
"method": "DELETE",
"path": "/api/v2/:app/objects/:id/holds/:holdId",
"file": "server/objects/routes.js",
-- "line": 368,
++ "line": 587,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v2/:app/objects/:id/multipart",
++ "file": "server/objects/routes.js",
++ "line": 411,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "DELETE",
++ "path": "/api/v2/:app/objects/:id/multipart/:uploadId",
++ "file": "server/objects/routes.js",
++ "line": 486,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v2/:app/objects/:id/multipart/:uploadId",
++ "file": "server/objects/routes.js",
++ "line": 440,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v2/:app/objects/:id/multipart/:uploadId/complete",
++ "file": "server/objects/routes.js",
++ "line": 449,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "PUT",
++ "path": "/api/v2/:app/objects/:id/multipart/:uploadId/parts/:n",
++ "file": "server/index.js",
++ "line": 36,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13384,7 +13550,17 @@
"method": "POST",
"path": "/api/v2/:app/objects/:id/restore",
"file": "server/objects/routes.js",
-- "line": 324,
++ "line": 543,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v2/:app/objects/:id/upload-url",
++ "file": "server/objects/routes.js",
++ "line": 387,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13454,7 +13630,7 @@
"method": "GET",
"path": "/healthz",
"file": "server/index.js",
-- "line": 92,
++ "line": 93,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13464,7 +13640,7 @@
"method": "POST",
"path": "/internal/avatar-ingest",
"file": "server/index.js",
-- "line": 63,
++ "line": 64,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13474,7 +13650,7 @@
"method": "GET",
"path": "/manifest.webmanifest",
"file": "server/index.js",
-- "line": 51,
++ "line": 52,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13484,7 +13660,7 @@
"method": "GET",
"path": "/o",
"file": "server/objects/routes.js",
-- "line": 278,
++ "line": 497,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13494,7 +13670,7 @@
"method": "POST",
"path": "/o",
"file": "server/objects/routes.js",
-- "line": 188,
++ "line": 261,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13504,7 +13680,7 @@
"method": "DELETE",
"path": "/o/:id",
"file": "server/objects/routes.js",
-- "line": 308,
++ "line": 527,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13514,7 +13690,7 @@
"method": "GET",
"path": "/o/:id",
"file": "server/objects/routes.js",
-- "line": 303,
++ "line": 522,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13524,7 +13700,7 @@
"method": "GET",
"path": "/o/:id",
"file": "server/objects/routes.js",
-- "line": 382,
++ "line": 601,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13534,7 +13710,7 @@
"method": "POST",
"path": "/o/:id/complete",
"file": "server/objects/routes.js",
-- "line": 244,
++ "line": 371,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13544,7 +13720,7 @@
"method": "GET",
"path": "/o/:id/download",
"file": "server/objects/routes.js",
-- "line": 334,
++ "line": 553,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13554,7 +13730,7 @@
"method": "GET",
"path": "/o/:id/holds",
"file": "server/objects/routes.js",
-- "line": 353,
++ "line": 572,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13564,7 +13740,7 @@
"method": "POST",
"path": "/o/:id/holds",
"file": "server/objects/routes.js",
-- "line": 359,
++ "line": 578,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13574,7 +13750,47 @@
"method": "DELETE",
"path": "/o/:id/holds/:holdId",
"file": "server/objects/routes.js",
-- "line": 368,
++ "line": 587,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/o/:id/multipart",
++ "file": "server/objects/routes.js",
++ "line": 411,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "DELETE",
++ "path": "/o/:id/multipart/:uploadId",
++ "file": "server/objects/routes.js",
++ "line": 486,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/o/:id/multipart/:uploadId",
++ "file": "server/objects/routes.js",
++ "line": 440,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/o/:id/multipart/:uploadId/complete",
++ "file": "server/objects/routes.js",
++ "line": 449,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13584,7 +13800,17 @@
"method": "POST",
"path": "/o/:id/restore",
"file": "server/objects/routes.js",
-- "line": 324,
++ "line": 543,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/o/:id/upload-url",
++ "file": "server/objects/routes.js",
++ "line": 387,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13594,7 +13820,7 @@
"method": "GET",
"path": "/release.json",
"file": "server/index.js",
-- "line": 90,
++ "line": 91,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13604,7 +13830,7 @@
"method": "GET",
"path": "/tos",
"file": "server/index.js",
-- "line": 48,
++ "line": 49,
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
@@@ -13652,6 +13878,12 @@
"MEDIA_SIGNING_SECRET": [
"server/config.js"
],
++ "MEDIA_JOBS_ENABLED": [
++ "server/config.js"
++ ],
++ "MEDIA_JOBS_HEAVY_WHILE_RECORDING": [
++ "server/config.js"
++ ],
"MEDIA_VERIFY_ENABLED": [
"server/config.js"
],
@@@ -13967,7 +14199,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 64,
++ "line": 73,
"file": "server/events.js",
"target": "OpenVibe.Media",
"disposition": "keep",
@@@ -13978,7 +14210,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": 43200000,
-- "line": 136,
++ "line": 137,
"file": "server/index.js",
"target": "OpenVibe.Media",
"disposition": "keep",
@@@ -13989,13 +14221,35 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 164,
++ "line": 166,
"file": "server/index.js",
"target": "OpenVibe.Media",
"disposition": "keep",
"wave": "-",
"note": "Runs in, and for, the service that owns it."
},
++ {
++ "kind": "setInterval",
++ "name": null,
++ "intervalMs": null,
++ "line": 64,
++ "file": "server/jobs/worker.js",
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "Runs in, and for, the service that owns it."
++ },
++ {
++ "kind": "setInterval",
++ "name": null,
++ "intervalMs": null,
++ "line": 183,
++ "file": "server/jobs/worker.js",
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "Runs in, and for, the service that owns it."
++ },
{
"kind": "setInterval",
"name": null,
@@@ -14066,7 +14320,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 480,
++ "line": 484,
"file": "server/vod/vod-storage.js",
"target": "OpenVibe.Media",
"disposition": "keep",
@@@ -14076,7 +14330,7 @@
],
"contractTodos": 0,
"unresolvedMounts": [],
-- "testFiles": 16,
++ "testFiles": 20,
"ci": true
},
{
@@@ -16181,13 +16435,13 @@
"service": "community",
"present": true,
"git": {
-- "head": "57d1dd4cbdc79f39ae5e98cc0d09b03a75508f5d",
++ "head": "63b90a838d280aada7d6c98aee61335b972c1105",
"branch": "main",
-- "originMain": "57d1dd4cbdc79f39ae5e98cc0d09b03a75508f5d",
-- "committedAt": "2026-09-23T12:38:51-07:00"
++ "originMain": "63b90a838d280aada7d6c98aee61335b972c1105",
++ "committedAt": "2026-09-23T14:22:33-07:00"
},
"sourceFiles": 47,
-- "loc": 7885,
++ "loc": 7886,
"tables": [
{
"table": "pastes",
@@@ -18660,13 +18914,13 @@
"service": "chat",
"present": true,
"git": {
-- "head": "789768806b0d217b0bc735c319d20d1b6ebb4df8",
++ "head": "ed90461e2fd4537332275f6efec8bb878ce4ac2a",
"branch": "main",
-- "originMain": "789768806b0d217b0bc735c319d20d1b6ebb4df8",
-- "committedAt": "2026-09-23T13:06:03-07:00"
++ "originMain": "ed90461e2fd4537332275f6efec8bb878ce4ac2a",
++ "committedAt": "2026-09-23T14:40:27-07:00"
},
-- "sourceFiles": 28,
-- "loc": 11140,
++ "sourceFiles": 34,
++ "loc": 11947,
"tables": [
{
"table": "chat_messages",
@@@ -18859,9 +19113,31 @@
"file": "server/db/schema.sql",
"line": 463,
"via": "repo"
++ },
++ {
++ "table": "deploy_releases",
++ "file": "server/db/schema.sql",
++ "line": 473,
++ "via": "repo"
++ },
++ {
++ "table": "chat_event_inbox",
++ "file": "server/db/schema.sql",
++ "line": 487,
++ "via": "repo"
}
],
"routes": [
++ {
++ "method": "POST",
++ "path": "/",
++ "file": "server/events/consumer.js",
++ "line": 91,
++ "target": "OpenVibe.Chat",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
{
"method": "GET",
"path": "/api/chat/:streamId/history",
@@@ -19012,6 +19288,26 @@
"wave": "-",
"note": "The service is the authority for its own API and pages."
},
++ {
++ "method": "GET",
++ "path": "/api/chat/preferences",
++ "file": "server/prefs/routes.js",
++ "line": 30,
++ "target": "OpenVibe.Chat",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "PUT",
++ "path": "/api/chat/preferences",
++ "file": "server/prefs/routes.js",
++ "line": 34,
++ "target": "OpenVibe.Chat",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
{
"method": "GET",
"path": "/api/chat/relay-user/:platform/:username",
@@@ -19436,7 +19732,7 @@
"method": "GET",
"path": "/health",
"file": "server/app.js",
-- "line": 77,
++ "line": 80,
"target": "OpenVibe.Chat",
"disposition": "keep",
"wave": "-",
@@@ -19456,7 +19752,7 @@
"method": "GET",
"path": "/ready",
"file": "server/app.js",
-- "line": 94,
++ "line": 97,
"target": "OpenVibe.Chat",
"disposition": "keep",
"wave": "-",
@@@ -19474,7 +19770,7 @@
{
"path": "/ws/chat",
"file": "server/app.js",
-- "line": 202
++ "line": 210
},
{
"path": "/ws/chat",
@@@ -19559,12 +19855,33 @@
"CHAT_VIP_BADGE_UNAVAILABLE_TTL_MS": [
"server/config.js"
],
++ "CHAT_PREFS_ENABLED": [
++ "server/config.js"
++ ],
++ "CHAT_PREFS_TTL_MS": [
++ "server/config.js"
++ ],
++ "CHAT_PREFS_TIMEOUT_MS": [
++ "server/config.js"
++ ],
++ "CHAT_PREFS_CACHE_MAX": [
++ "server/config.js"
++ ],
"EVENTS_URL": [
"server/config.js"
],
"EVENTS_RELAY_INTERVAL_MS": [
"server/config.js"
],
++ "CHAT_EVENTS_SECRET": [
++ "server/config.js"
++ ],
++ "CHAT_EVENTS_SUBSCRIBE": [
++ "server/config.js"
++ ],
++ "CHAT_EVENTS_ENDPOINT": [
++ "server/config.js"
++ ],
"SOUNDS_PATH": [
"server/config.js"
],
@@@ -19696,6 +20013,25 @@
],
"timeout": true,
"retry": false
++ },
++ {
++ "file": "server/prefs/network-modules.js",
++ "targets": [
++ {
++ "service": "network",
++ "refs": [
++ {
++ "via": "networkInternalUrl",
++ "line": 21
++ }
++ ]
++ }
++ ],
++ "auth": [
++ "service-token"
++ ],
++ "timeout": true,
++ "retry": true
}
],
"jobs": [
@@@ -19765,6 +20101,17 @@
"wave": "-",
"note": "Runs in, and for, the service that owns it."
},
++ {
++ "kind": "setInterval",
++ "name": null,
++ "intervalMs": 21600000,
++ "line": 136,
++ "file": "server/events/consumer.js",
++ "target": "OpenVibe.Chat",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "Runs in, and for, the service that owns it."
++ },
{
"kind": "setInterval",
"name": null,
@@@ -19801,7 +20148,7 @@
],
"contractTodos": 0,
"unresolvedMounts": [],
-- "testFiles": 16,
++ "testFiles": 19,
"ci": true
},
{
@@@ -21430,96 +21777,114 @@
"service": "tips",
"present": true,
"git": {
-- "head": "9a3a186182df7d150780b31d191ea1eb99c95962",
++ "head": "f211c03ed01b58dd52d104bda8b07ce1a82da2db",
"branch": "main",
-- "originMain": "9a3a186182df7d150780b31d191ea1eb99c95962",
-- "committedAt": "2026-09-23T12:33:56-07:00"
++ "originMain": "f211c03ed01b58dd52d104bda8b07ce1a82da2db",
++ "committedAt": "2026-09-23T14:22:34-07:00"
},
-- "sourceFiles": 26,
-- "loc": 4065,
++ "sourceFiles": 29,
++ "loc": 5250,
"tables": [
{
"table": "settings",
"file": "server/db.js",
-- "line": 30,
++ "line": 31,
"via": "repo"
},
{
"table": "creator_tip_profiles",
"file": "server/db.js",
-- "line": 36,
++ "line": 37,
"via": "repo"
},
{
"table": "tip_interactions",
"file": "server/db.js",
-- "line": 58,
++ "line": 59,
"via": "repo"
},
{
"table": "tip_goals",
"file": "server/db.js",
-- "line": 103,
++ "line": 104,
"via": "repo"
},
{
"table": "tip_goal_contributions",
"file": "server/db.js",
-- "line": 123,
++ "line": 124,
"via": "repo"
},
{
"table": "paid_messages",
"file": "server/db.js",
-- "line": 134,
++ "line": 135,
"via": "repo"
},
{
"table": "paid_media_requests",
"file": "server/db.js",
-- "line": 149,
++ "line": 150,
"via": "repo"
},
{
"table": "overlay_configs",
"file": "server/db.js",
-- "line": 162,
++ "line": 163,
"via": "repo"
},
{
"table": "overlay_tokens",
"file": "server/db.js",
-- "line": 175,
++ "line": 176,
"via": "repo"
},
{
"table": "overlay_deliveries",
"file": "server/db.js",
-- "line": 189,
++ "line": 190,
"via": "repo"
},
{
"table": "interaction_effects",
"file": "server/db.js",
-- "line": 208,
++ "line": 209,
"via": "repo"
},
{
"table": "migration_maps",
"file": "server/db.js",
-- "line": 224,
++ "line": 225,
"via": "repo"
},
{
"table": "import_runs",
"file": "server/db.js",
-- "line": 240,
++ "line": 241,
++ "via": "repo"
++ },
++ {
++ "table": "tip_moderators",
++ "file": "server/db.js",
++ "line": 252,
++ "via": "repo"
++ },
++ {
++ "table": "tip_moderator_invites",
++ "file": "server/db.js",
++ "line": 263,
++ "via": "repo"
++ },
++ {
++ "table": "tip_moderation_log",
++ "file": "server/db.js",
++ "line": 275,
"via": "repo"
},
{
"table": "api_idempotency",
"file": "server/db.js",
-- "line": 249,
++ "line": 287,
"via": "repo"
}
],
@@@ -21528,7 +21893,7 @@
"method": "GET",
"path": "/",
"file": "server/web/routes.js",
-- "line": 54,
++ "line": 65,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21538,7 +21903,7 @@
"method": "GET",
"path": "/:handle",
"file": "server/web/routes.js",
-- "line": 233,
++ "line": 361,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21548,7 +21913,17 @@
"method": "GET",
"path": "/:handle/goals",
"file": "server/web/routes.js",
-- "line": 234,
++ "line": 362,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/:handle/supporters",
++ "file": "server/web/routes.js",
++ "line": 372,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21558,7 +21933,7 @@
"method": "POST",
"path": "/:handle/tip",
"file": "server/web/routes.js",
-- "line": 245,
++ "line": 387,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21588,7 +21963,7 @@
"method": "POST",
"path": "/api/v1/checkout",
"file": "server/api/v1.js",
-- "line": 160,
++ "line": 194,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21598,7 +21973,7 @@
"method": "GET",
"path": "/api/v1/goals",
"file": "server/api/v1.js",
-- "line": 213,
++ "line": 248,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21608,7 +21983,7 @@
"method": "POST",
"path": "/api/v1/goals",
"file": "server/api/v1.js",
-- "line": 226,
++ "line": 262,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21618,7 +21993,7 @@
"method": "GET",
"path": "/api/v1/goals/:id",
"file": "server/api/v1.js",
-- "line": 220,
++ "line": 256,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21628,7 +22003,7 @@
"method": "PATCH",
"path": "/api/v1/goals/:id",
"file": "server/api/v1.js",
-- "line": 238,
++ "line": 274,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21638,7 +22013,7 @@
"method": "POST",
"path": "/api/v1/goals/:id/close",
"file": "server/api/v1.js",
-- "line": 239,
++ "line": 275,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21648,7 +22023,7 @@
"method": "GET",
"path": "/api/v1/interactions",
"file": "server/api/v1.js",
-- "line": 166,
++ "line": 200,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21658,7 +22033,17 @@
"method": "GET",
"path": "/api/v1/interactions/:id",
"file": "server/api/v1.js",
-- "line": 185,
++ "line": 219,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v1/interactions/:id/${action}",
++ "file": "server/api/v1.js",
++ "line": 350,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21668,7 +22053,27 @@
"method": "POST",
"path": "/api/v1/interactions/external",
"file": "server/api/v1.js",
-- "line": 198,
++ "line": 232,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v1/me/erase",
++ "file": "server/api/v1.js",
++ "line": 125,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v1/me/export",
++ "file": "server/api/v1.js",
++ "line": 124,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21678,7 +22083,57 @@
"method": "POST",
"path": "/api/v1/media-requests",
"file": "server/api/v1.js",
-- "line": 163,
++ "line": 197,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v1/moderation",
++ "file": "server/api/v1.js",
++ "line": 338,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v1/moderation/log",
++ "file": "server/api/v1.js",
++ "line": 344,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v1/moderators",
++ "file": "server/api/v1.js",
++ "line": 358,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v1/moderators",
++ "file": "server/api/v1.js",
++ "line": 363,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/api/v1/moderators/:subject/remove",
++ "file": "server/api/v1.js",
++ "line": 370,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21688,7 +22143,7 @@
"method": "GET",
"path": "/api/v1/overlay-configs",
"file": "server/api/v1.js",
-- "line": 264,
++ "line": 301,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21698,7 +22153,7 @@
"method": "POST",
"path": "/api/v1/overlay-configs",
"file": "server/api/v1.js",
-- "line": 275,
++ "line": 312,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21708,7 +22163,7 @@
"method": "GET",
"path": "/api/v1/overlay-configs/:id",
"file": "server/api/v1.js",
-- "line": 269,
++ "line": 306,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21718,7 +22173,7 @@
"method": "PATCH",
"path": "/api/v1/overlay-configs/:id",
"file": "server/api/v1.js",
-- "line": 281,
++ "line": 318,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21728,7 +22183,7 @@
"method": "GET",
"path": "/api/v1/overlay-tokens",
"file": "server/api/v1.js",
-- "line": 242,
++ "line": 278,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21738,7 +22193,7 @@
"method": "POST",
"path": "/api/v1/overlay-tokens",
"file": "server/api/v1.js",
-- "line": 247,
++ "line": 283,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21748,7 +22203,7 @@
"method": "POST",
"path": "/api/v1/overlay-tokens/:id/revoke",
"file": "server/api/v1.js",
-- "line": 257,
++ "line": 294,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21758,7 +22213,7 @@
"method": "POST",
"path": "/api/v1/paid-messages",
"file": "server/api/v1.js",
-- "line": 161,
++ "line": 195,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21768,7 +22223,7 @@
"method": "GET",
"path": "/api/v1/profiles/:creator",
"file": "server/api/v1.js",
-- "line": 82,
++ "line": 93,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21778,7 +22233,17 @@
"method": "PATCH",
"path": "/api/v1/profiles/:creator",
"file": "server/api/v1.js",
-- "line": 93,
++ "line": 127,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/api/v1/profiles/:creator/supporters",
++ "file": "server/api/v1.js",
++ "line": 106,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21788,7 +22253,7 @@
"method": "GET",
"path": "/api/v1/profiles/:creator/totals",
"file": "server/api/v1.js",
-- "line": 112,
++ "line": 146,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21798,7 +22263,7 @@
"method": "POST",
"path": "/api/v1/simulate",
"file": "server/api/v1.js",
-- "line": 289,
++ "line": 377,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21808,7 +22273,7 @@
"method": "POST",
"path": "/api/v1/tts-requests",
"file": "server/api/v1.js",
-- "line": 162,
++ "line": 196,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21878,7 +22343,7 @@
"method": "GET",
"path": "/dashboard",
"file": "server/web/routes.js",
-- "line": 108,
++ "line": 149,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21894,11 +22359,51 @@
"wave": "-",
"note": "The service is the authority for its own API and pages."
},
++ {
++ "method": "GET",
++ "path": "/moderate/:handle",
++ "file": "server/web/routes.js",
++ "line": 321,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/moderate/:handle/:id/:act(hide|restore)",
++ "file": "server/web/routes.js",
++ "line": 327,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/moderate/invite/:token",
++ "file": "server/web/routes.js",
++ "line": 283,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/moderate/invite/:token",
++ "file": "server/web/routes.js",
++ "line": 292,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
{
"method": "GET",
"path": "/overlay/:token",
"file": "server/web/routes.js",
-- "line": 183,
++ "line": 234,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21908,7 +22413,7 @@
"method": "GET",
"path": "/overlay/:token/events",
"file": "server/web/routes.js",
-- "line": 194,
++ "line": 245,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21918,7 +22423,7 @@
"method": "GET",
"path": "/overlay/:token/state",
"file": "server/web/routes.js",
-- "line": 204,
++ "line": 259,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21928,7 +22433,7 @@
"method": "GET",
"path": "/receipts",
"file": "server/web/routes.js",
-- "line": 71,
++ "line": 82,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21938,7 +22443,37 @@
"method": "GET",
"path": "/receipts/:id",
"file": "server/web/routes.js",
-- "line": 76,
++ "line": 112,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/receipts/erase",
++ "file": "server/web/routes.js",
++ "line": 102,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "POST",
++ "path": "/receipts/erase",
++ "file": "server/web/routes.js",
++ "line": 106,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/receipts/export",
++ "file": "server/web/routes.js",
++ "line": 89,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21958,7 +22493,7 @@
"method": "GET",
"path": "/robots.txt",
"file": "server/web/routes.js",
-- "line": 58,
++ "line": 69,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -21968,7 +22503,7 @@
"method": "GET",
"path": "/sitemap.xml",
"file": "server/web/routes.js",
-- "line": 60,
++ "line": 71,
"target": "OpenVibe.Tips",
"disposition": "keep",
"wave": "-",
@@@ -22082,6 +22617,9 @@
"TIPS_OVERLAY_REPLAY_LIMIT": [
"server/config.js"
],
++ "TIPS_OVERLAY_MAX_STREAMS": [
++ "server/config.js"
++ ],
"TIPS_MAX_BITS": [
"server/config.js"
],
@@@ -22091,6 +22629,9 @@
"TIPS_TTS_HARD_CAP": [
"server/config.js"
],
++ "TIPS_MAX_PENDING_CHECKOUTS": [
++ "server/config.js"
++ ],
"TIPS_JOBS": [
"server/config.js"
],
@@@ -22152,7 +22693,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 268,
++ "line": 307,
"file": "server/domain/overlays.js",
"target": "OpenVibe.Tips",
"disposition": "keep",
@@@ -22163,7 +22704,7 @@
"kind": "setInterval",
"name": null,
"intervalMs": null,
-- "line": 21,
++ "line": 22,
"file": "server/index.js",
"target": "OpenVibe.Tips",
"disposition": "keep",
@@@ -22184,7 +22725,7 @@
],
"contractTodos": 0,
"unresolvedMounts": [],
-- "testFiles": 11,
++ "testFiles": 15,
"ci": true
},
{
@@@ -22192,13 +22733,13 @@
"service": "vip",
"present": true,
"git": {
-- "head": "9668a492b8f5b6c111261cf0e4270fc4ffcf521d",
++ "head": "fe7eaad183622f303d2ea1efde80d1674478d948",
"branch": "main",
-- "originMain": "9668a492b8f5b6c111261cf0e4270fc4ffcf521d",
-- "committedAt": "2026-09-23T12:33:56-07:00"
++ "originMain": "fe7eaad183622f303d2ea1efde80d1674478d948",
++ "committedAt": "2026-09-23T13:50:44-07:00"
},
-- "sourceFiles": 27,
-- "loc": 3881,
++ "sourceFiles": 29,
++ "loc": 4194,
"tables": [
{
"table": "settings",
@@@ -22294,7 +22835,7 @@
"method": "GET",
"path": "/:username",
"file": "server/web/routes.js",
-- "line": 219,
++ "line": 220,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22304,7 +22845,7 @@
"method": "GET",
"path": "/:username/plans/:slug",
"file": "server/web/routes.js",
-- "line": 237,
++ "line": 238,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22314,7 +22855,7 @@
"method": "GET",
"path": "/api/health",
"file": "server/app.js",
-- "line": 82,
++ "line": 86,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22324,7 +22865,7 @@
"method": "GET",
"path": "/api/ready",
"file": "server/app.js",
-- "line": 84,
++ "line": 88,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22334,7 +22875,7 @@
"method": "POST",
"path": "/api/v1/checkout",
"file": "server/api/v1.js",
-- "line": 203,
++ "line": 210,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22350,11 +22891,21 @@
"wave": "-",
"note": "The service is the authority for its own API and pages."
},
++ {
++ "method": "GET",
++ "path": "/api/v1/creators/:ref/card",
++ "file": "server/api/v1.js",
++ "line": 111,
++ "target": "OpenVibe.VIP",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
{
"method": "GET",
"path": "/api/v1/creators/:ref/members",
"file": "server/api/v1.js",
-- "line": 331,
++ "line": 338,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22364,7 +22915,7 @@
"method": "GET",
"path": "/api/v1/entitlements/check",
"file": "server/api/v1.js",
-- "line": 269,
++ "line": 276,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22374,7 +22925,7 @@
"method": "POST",
"path": "/api/v1/entitlements/check",
"file": "server/api/v1.js",
-- "line": 270,
++ "line": 277,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22384,7 +22935,7 @@
"method": "POST",
"path": "/api/v1/memberships/:creator/cancel",
"file": "server/api/v1.js",
-- "line": 231,
++ "line": 238,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22394,7 +22945,7 @@
"method": "PUT",
"path": "/api/v1/memberships/:creator/preferences",
"file": "server/api/v1.js",
-- "line": 236,
++ "line": 243,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22404,7 +22955,7 @@
"method": "GET",
"path": "/api/v1/memberships/:subject",
"file": "server/api/v1.js",
-- "line": 215,
++ "line": 222,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22414,7 +22965,7 @@
"method": "GET",
"path": "/api/v1/perks",
"file": "server/api/v1.js",
-- "line": 166,
++ "line": 173,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22424,7 +22975,7 @@
"method": "POST",
"path": "/api/v1/perks",
"file": "server/api/v1.js",
-- "line": 173,
++ "line": 180,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22434,7 +22985,7 @@
"method": "PATCH",
"path": "/api/v1/perks/:id",
"file": "server/api/v1.js",
-- "line": 180,
++ "line": 187,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22444,7 +22995,7 @@
"method": "GET",
"path": "/api/v1/plans",
"file": "server/api/v1.js",
-- "line": 111,
++ "line": 118,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22454,7 +23005,7 @@
"method": "POST",
"path": "/api/v1/plans",
"file": "server/api/v1.js",
-- "line": 132,
++ "line": 139,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22464,7 +23015,7 @@
"method": "GET",
"path": "/api/v1/plans/:id",
"file": "server/api/v1.js",
-- "line": 125,
++ "line": 132,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22474,7 +23025,7 @@
"method": "PATCH",
"path": "/api/v1/plans/:id",
"file": "server/api/v1.js",
-- "line": 148,
++ "line": 155,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22484,7 +23035,7 @@
"method": "POST",
"path": "/api/v1/plans/:id/archive",
"file": "server/api/v1.js",
-- "line": 160,
++ "line": 167,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22494,7 +23045,7 @@
"method": "POST",
"path": "/api/v1/plans/:id/publish",
"file": "server/api/v1.js",
-- "line": 155,
++ "line": 162,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22504,7 +23055,7 @@
"method": "GET",
"path": "/api/v1/plans/:id/versions",
"file": "server/api/v1.js",
-- "line": 126,
++ "line": 133,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22514,7 +23065,7 @@
"method": "GET",
"path": "/api/v1/policies",
"file": "server/api/v1.js",
-- "line": 273,
++ "line": 280,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22524,7 +23075,7 @@
"method": "POST",
"path": "/api/v1/policies",
"file": "server/api/v1.js",
-- "line": 298,
++ "line": 305,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22534,7 +23085,7 @@
"method": "DELETE",
"path": "/api/v1/policies/:id",
"file": "server/api/v1.js",
-- "line": 306,
++ "line": 313,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22544,7 +23095,7 @@
"method": "GET",
"path": "/api/v1/policies/:id",
"file": "server/api/v1.js",
-- "line": 292,
++ "line": 299,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22554,7 +23105,7 @@
"method": "POST",
"path": "/api/v1/policies/evaluate",
"file": "server/api/v1.js",
-- "line": 312,
++ "line": 319,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22630,6 +23181,36 @@
"wave": "-",
"note": "The service is the authority for its own API and pages."
},
++ {
++ "method": "GET",
++ "path": "/embed/:username/badge.svg",
++ "file": "server/web/embeds.js",
++ "line": 103,
++ "target": "OpenVibe.VIP",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/embed/:username/card.json",
++ "file": "server/web/embeds.js",
++ "line": 94,
++ "target": "OpenVibe.VIP",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
++ {
++ "method": "GET",
++ "path": "/embed/:username/widget",
++ "file": "server/web/embeds.js",
++ "line": 113,
++ "target": "OpenVibe.VIP",
++ "disposition": "keep",
++ "wave": "-",
++ "note": "The service is the authority for its own API and pages."
++ },
{
"method": "POST",
"path": "/events",
@@@ -22654,7 +23235,7 @@
"method": "GET",
"path": "/release.json",
"file": "server/app.js",
-- "line": 85,
++ "line": 89,
"target": "OpenVibe.VIP",
"disposition": "keep",
"wave": "-",
@@@ -22782,6 +23363,12 @@
"LIVE_URL": [
"server/config.js"
],
++ "VIP_WIDGET_FRAME_ANCESTORS": [
++ "server/config.js"
++ ],
++ "VIP_MEMBER_COUNT_TTL_MS": [
++ "server/config.js"
++ ],
"MIN_CLIENT_RELEASE": [
"OpenVibe.Shared/release.js"
],
@@@ -22852,7 +23439,7 @@
],
"contractTodos": 0,
"unresolvedMounts": [],
-- "testFiles": 10,
++ "testFiles": 11,
"ci": true
},
{
@@@ -31080,10 +31667,10 @@
"service": "host",
"present": true,
"git": {
-- "head": "ea99b502c072ae6635f7705e002e0ec174cae16d",
++ "head": "03dfcb32a9fecb85d509f5d92d0a166a26d86fe7",
"branch": "main",
-- "originMain": "ea99b502c072ae6635f7705e002e0ec174cae16d",
-- "committedAt": "2026-09-23T13:22:16-07:00"
++ "originMain": "03dfcb32a9fecb85d509f5d92d0a166a26d86fe7",
++ "committedAt": "2026-09-23T13:48:51-07:00"
},
"sourceFiles": 55,
"loc": 8099,
@@@ -32201,7 +32788,7 @@
"repo": "OpenVibe.Live",
"manifest": "package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Media",
@@@ -32213,7 +32800,7 @@
"repo": "OpenVibe.Network",
"manifest": "package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.News",
@@@ -32255,49 +32842,49 @@
"repo": "OpenVibe.Tools",
"manifest": "apps/audio/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/docs/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/food/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/gateway/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/img/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/maps/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/text/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Tools",
"manifest": "apps/yt/package.json",
"spec": "v1.4.0",
-- "state": "current"
++ "state": "behind"
},
{
"repo": "OpenVibe.Trade",
@@@ -33489,6 +34076,20 @@
"wave": "W6 (remainder)",
"note": "table_authority=live: Live still writes these; Chat holds the imported copy."
},
++ {
++ "repo": "OpenVibe.Chat",
++ "table": "chat_event_inbox",
++ "declaredAt": [
++ "server/db/schema.sql:487"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Chat",
++ "disposition": "keep",
++ "wave": "W6",
++ "note": "Chat authority tables (table_authority=chat), bridge/mirror outboxes and import bookkeeping."
++ },
{
"repo": "OpenVibe.Chat",
"table": "chat_messages",
@@@ -33617,6 +34218,20 @@
"wave": "W6",
"note": "Read projection of Live context (channels, managed streams, streams, users) that Chat needs for authorization."
},
++ {
++ "repo": "OpenVibe.Chat",
++ "table": "deploy_releases",
++ "declaredAt": [
++ "server/db/schema.sql:473"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Chat",
++ "disposition": "keep",
++ "wave": "W6",
++ "note": "Chat authority tables (table_authority=chat), bridge/mirror outboxes and import bookkeeping."
++ },
{
"repo": "OpenVibe.Chat",
"table": "dm_blocks",
@@@ -35390,7 +36005,7 @@
"repo": "OpenVibe.Live",
"table": "ai_chatbot_configs",
"declaredAt": [
-- "server/db/database.js:1810"
++ "server/db/database.js:1782"
],
"prodDbs": [
"live.db"
@@@ -35466,7 +36081,7 @@
"repo": "OpenVibe.Live",
"table": "ai_viewer_log",
"declaredAt": [
-- "server/db/database.js:1894"
++ "server/db/database.js:1866"
],
"prodDbs": [
"live.db"
@@@ -35482,7 +36097,7 @@
"repo": "OpenVibe.Live",
"table": "ai_viewer_threads",
"declaredAt": [
-- "server/db/database.js:1880"
++ "server/db/database.js:1852"
],
"prodDbs": [
"live.db"
@@@ -35660,7 +36275,7 @@
"repo": "OpenVibe.Live",
"table": "approved_ips",
"declaredAt": [
-- "server/db/database.js:2082"
++ "server/db/database.js:2054"
],
"prodDbs": [
"live.db"
@@@ -36272,7 +36887,7 @@
"repo": "OpenVibe.Live",
"table": "channel_ai_bots",
"declaredAt": [
-- "server/db/database.js:1835"
++ "server/db/database.js:1807"
],
"prodDbs": [
"live.db"
@@@ -36288,7 +36903,7 @@
"repo": "OpenVibe.Live",
"table": "channel_ai_config",
"declaredAt": [
-- "server/db/database.js:1859"
++ "server/db/database.js:1831"
],
"prodDbs": [
"live.db"
@@@ -36304,7 +36919,7 @@
"repo": "OpenVibe.Live",
"table": "channel_moderation_settings",
"declaredAt": [
-- "server/db/database.js:1645",
++ "server/db/database.js:1617",
"server/db/schema.sql:514"
],
"prodDbs": [
@@@ -36321,7 +36936,7 @@
"repo": "OpenVibe.Live",
"table": "channel_moderators",
"declaredAt": [
-- "server/db/database.js:1628",
++ "server/db/database.js:1600",
"server/db/schema.sql:499"
],
"prodDbs": [
@@@ -36354,7 +36969,7 @@
"repo": "OpenVibe.Live",
"table": "channel_sounds",
"declaredAt": [
-- "server/db/database.js:1748",
++ "server/db/database.js:1720",
"server/db/schema.sql:625"
],
"prodDbs": [
@@@ -36371,7 +36986,7 @@
"repo": "OpenVibe.Live",
"table": "channel_sounds_new",
"declaredAt": [
-- "server/db/database.js:1772"
++ "server/db/database.js:1744"
],
"prodDbs": [],
"inCode": true,
@@@ -36664,7 +37279,7 @@
"repo": "OpenVibe.Live",
"table": "control_config_buttons",
"declaredAt": [
-- "server/db/database.js:2313"
++ "server/db/database.js:2278"
],
"prodDbs": [
"live.db"
@@@ -36680,7 +37295,7 @@
"repo": "OpenVibe.Live",
"table": "control_configs",
"declaredAt": [
-- "server/db/database.js:2299"
++ "server/db/database.js:2264"
],
"prodDbs": [
"live.db"
@@@ -36696,7 +37311,7 @@
"repo": "OpenVibe.Live",
"table": "control_whitelist",
"declaredAt": [
-- "server/db/database.js:2284"
++ "server/db/database.js:2249"
],
"prodDbs": [
"live.db"
@@@ -36880,7 +37495,7 @@
"repo": "OpenVibe.Live",
"table": "emotes_new",
"declaredAt": [
-- "server/db/database.js:1716"
++ "server/db/database.js:1688"
],
"prodDbs": [],
"inCode": true,
@@@ -37237,7 +37852,7 @@
"repo": "OpenVibe.Live",
"table": "hidden_relay_users",
"declaredAt": [
-- "server/db/database.js:2119"
++ "server/db/database.js:2091"
],
"prodDbs": [
"live.db"
@@@ -37267,7 +37882,7 @@
"repo": "OpenVibe.Live",
"table": "ip_log",
"declaredAt": [
-- "server/db/database.js:2058"
++ "server/db/database.js:2030"
],
"prodDbs": [
"live.db"
@@@ -37371,7 +37986,7 @@
"repo": "OpenVibe.Live",
"table": "managed_streams",
"declaredAt": [
-- "server/db/database.js:2427",
++ "server/db/database.js:2392",
"server/db/schema.sql:78"
],
"prodDbs": [
@@@ -37451,7 +38066,7 @@
"repo": "OpenVibe.Live",
"table": "moderation_actions",
"declaredAt": [
-- "server/db/database.js:1927"
++ "server/db/database.js:1899"
],
"prodDbs": [
"live.db"
@@@ -37513,7 +38128,7 @@
"repo": "OpenVibe.Live",
"table": "paste_comments",
"declaredAt": [
-- "server/db/database.js:2015"
++ "server/db/database.js:1987"
],
"prodDbs": [
"live.db"
@@@ -37529,7 +38144,7 @@
"repo": "OpenVibe.Live",
"table": "paste_likes",
"declaredAt": [
-- "server/db/database.js:1983"
++ "server/db/database.js:1955"
],
"prodDbs": [
"live.db"
@@@ -37545,7 +38160,7 @@
"repo": "OpenVibe.Live",
"table": "pastes",
"declaredAt": [
-- "server/db/database.js:1946"
++ "server/db/database.js:1918"
],
"prodDbs": [
"live.db"
@@@ -37561,7 +38176,7 @@
"repo": "OpenVibe.Live",
"table": "payment_orders",
"declaredAt": [
-- "server/db/database.js:1595"
++ "server/db/database.js:1567"
],
"prodDbs": [
"live.db"
@@@ -37577,7 +38192,7 @@
"repo": "OpenVibe.Live",
"table": "pending_ip_messages",
"declaredAt": [
-- "server/db/database.js:2099"
++ "server/db/database.js:2071"
],
"prodDbs": [
"live.db"
@@@ -37655,7 +38270,7 @@
"repo": "OpenVibe.Live",
"table": "relay_users",
"declaredAt": [
-- "server/db/database.js:1473"
++ "server/db/database.js:1472"
],
"prodDbs": [
"live.db"
@@@ -37811,7 +38426,7 @@
"repo": "OpenVibe.Live",
"table": "stream_controls_new",
"declaredAt": [
-- "server/db/database.js:2392"
++ "server/db/database.js:2357"
],
"prodDbs": [],
"inCode": true,
@@@ -37825,7 +38440,7 @@
"repo": "OpenVibe.Live",
"table": "stream_first_chats",
"declaredAt": [
-- "server/db/database.js:2047"
++ "server/db/database.js:2019"
],
"prodDbs": [
"live.db"
@@@ -38192,7 +38807,7 @@
"repo": "OpenVibe.Live",
"table": "vibe_coding_events",
"declaredAt": [
-- "server/db/database.js:2684",
++ "server/db/database.js:2649",
"server/db/schema.sql:198"
],
"prodDbs": [
@@@ -38209,7 +38824,7 @@
"repo": "OpenVibe.Live",
"table": "vibe_coding_sessions",
"declaredAt": [
-- "server/db/database.js:2649",
++ "server/db/database.js:2614",
"server/db/schema.sql:170"
],
"prodDbs": [
@@@ -38226,7 +38841,7 @@
"repo": "OpenVibe.Live",
"table": "viewer_samples",
"declaredAt": [
-- "server/db/database.js:3983"
++ "server/db/database.js:3832"
],
"prodDbs": [
"live.db"
@@@ -38446,7 +39061,7 @@
"repo": "OpenVibe.Media",
"table": "media_holds",
"declaredAt": [
-- "server/db/schema.sql:293"
++ "server/db/schema.sql:338"
],
"prodDbs": [
"media.db"
@@@ -38462,7 +39077,7 @@
"repo": "OpenVibe.Media",
"table": "media_invariant_violations",
"declaredAt": [
-- "server/db/schema.sql:306"
++ "server/db/schema.sql:351"
],
"prodDbs": [
"media.db"
@@@ -38478,7 +39093,7 @@
"repo": "OpenVibe.Media",
"table": "media_jobs",
"declaredAt": [
-- "server/db/schema.sql:279"
++ "server/db/schema.sql:281"
],
"prodDbs": [
"media.db"
@@@ -38554,6 +39169,34 @@
"wave": "W4 (object model)",
"note": "Becomes projections over media_objects/media_locations."
},
++ {
++ "repo": "OpenVibe.Media",
++ "table": "media_upload_parts",
++ "declaredAt": [
++ "server/db/schema.sql:328"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "W4 (object model)",
++ "note": "Becomes projections over media_objects/media_locations."
++ },
++ {
++ "repo": "OpenVibe.Media",
++ "table": "media_uploads",
++ "declaredAt": [
++ "server/db/schema.sql:312"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Media",
++ "disposition": "keep",
++ "wave": "W4 (object model)",
++ "note": "Becomes projections over media_objects/media_locations."
++ },
{
"repo": "OpenVibe.Media",
"table": "media_variants",
@@@ -38574,7 +39217,7 @@
"repo": "OpenVibe.Media",
"table": "media_verifications",
"declaredAt": [
-- "server/db/schema.sql:320"
++ "server/db/schema.sql:365"
],
"prodDbs": [
"media.db"
@@@ -38590,7 +39233,7 @@
"repo": "OpenVibe.Media",
"table": "media_verify_runs",
"declaredAt": [
-- "server/db/schema.sql:332"
++ "server/db/schema.sql:377"
],
"prodDbs": [
"media.db"
@@@ -39212,7 +39855,7 @@
"repo": "OpenVibe.Network",
"table": "principal_grants",
"declaredAt": [
-- "server/identity/principals.js:151"
++ "server/identity/principals.js:164"
],
"prodDbs": [
"network.db"
@@@ -39228,7 +39871,7 @@
"repo": "OpenVibe.Network",
"table": "principal_usage",
"declaredAt": [
-- "server/identity/principals.js:161"
++ "server/identity/principals.js:174"
],
"prodDbs": [
"network.db"
@@@ -39276,7 +39919,7 @@
"repo": "OpenVibe.Network",
"table": "stream_live_announcements",
"declaredAt": [
-- "server/notifications/stream-live.js:17"
++ "server/notifications/stream-live.js:31"
],
"prodDbs": [
"network.db"
@@@ -39369,11 +40012,39 @@
"wave": "W1 (module split)",
"note": "Identity, sessions, OAuth, themes, notifications, registry, chrome, audit, admin."
},
++ {
++ "repo": "OpenVibe.Network",
++ "table": "user_module_retirements",
++ "declaredAt": [
++ "server/identity/modules.js:93"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Network",
++ "disposition": "keep",
++ "wave": "W1 (module split)",
++ "note": "Identity, sessions, OAuth, themes, notifications, registry, chrome, audit, admin."
++ },
++ {
++ "repo": "OpenVibe.Network",
++ "table": "user_module_revisions",
++ "declaredAt": [
++ "server/identity/modules.js:86"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Network",
++ "disposition": "keep",
++ "wave": "W1 (module split)",
++ "note": "Identity, sessions, OAuth, themes, notifications, registry, chrome, audit, admin."
++ },
{
"repo": "OpenVibe.Network",
"table": "user_modules",
"declaredAt": [
-- "server/identity/modules.js:24"
++ "server/identity/modules.js:75"
],
"prodDbs": [
"network.db"
@@@ -40611,7 +41282,7 @@
"repo": "OpenVibe.Tips",
"table": "api_idempotency",
"declaredAt": [
-- "server/db.js:249"
++ "server/db.js:287"
],
"prodDbs": [
"tips.db"
@@@ -40627,7 +41298,7 @@
"repo": "OpenVibe.Tips",
"table": "creator_tip_profiles",
"declaredAt": [
-- "server/db.js:36"
++ "server/db.js:37"
],
"prodDbs": [
"tips.db"
@@@ -40671,7 +41342,7 @@
"repo": "OpenVibe.Tips",
"table": "import_runs",
"declaredAt": [
-- "server/db.js:240"
++ "server/db.js:241"
],
"prodDbs": [
"tips.db"
@@@ -40687,7 +41358,7 @@
"repo": "OpenVibe.Tips",
"table": "interaction_effects",
"declaredAt": [
-- "server/db.js:208"
++ "server/db.js:209"
],
"prodDbs": [
"tips.db"
@@@ -40703,7 +41374,7 @@
"repo": "OpenVibe.Tips",
"table": "migration_maps",
"declaredAt": [
-- "server/db.js:224"
++ "server/db.js:225"
],
"prodDbs": [
"tips.db"
@@@ -40719,7 +41390,7 @@
"repo": "OpenVibe.Tips",
"table": "overlay_configs",
"declaredAt": [
-- "server/db.js:162"
++ "server/db.js:163"
],
"prodDbs": [
"tips.db"
@@@ -40735,7 +41406,7 @@
"repo": "OpenVibe.Tips",
"table": "overlay_deliveries",
"declaredAt": [
-- "server/db.js:189"
++ "server/db.js:190"
],
"prodDbs": [
"tips.db"
@@@ -40751,7 +41422,7 @@
"repo": "OpenVibe.Tips",
"table": "overlay_tokens",
"declaredAt": [
-- "server/db.js:175"
++ "server/db.js:176"
],
"prodDbs": [
"tips.db"
@@@ -40767,7 +41438,7 @@
"repo": "OpenVibe.Tips",
"table": "paid_media_requests",
"declaredAt": [
-- "server/db.js:149"
++ "server/db.js:150"
],
"prodDbs": [
"tips.db"
@@@ -40783,7 +41454,7 @@
"repo": "OpenVibe.Tips",
"table": "paid_messages",
"declaredAt": [
-- "server/db.js:134"
++ "server/db.js:135"
],
"prodDbs": [
"tips.db"
@@@ -40799,7 +41470,7 @@
"repo": "OpenVibe.Tips",
"table": "settings",
"declaredAt": [
-- "server/db.js:30"
++ "server/db.js:31"
],
"prodDbs": [
"tips.db"
@@@ -40815,7 +41486,7 @@
"repo": "OpenVibe.Tips",
"table": "tip_goal_contributions",
"declaredAt": [
-- "server/db.js:123"
++ "server/db.js:124"
],
"prodDbs": [
"tips.db"
@@@ -40831,7 +41502,7 @@
"repo": "OpenVibe.Tips",
"table": "tip_goals",
"declaredAt": [
-- "server/db.js:103"
++ "server/db.js:104"
],
"prodDbs": [
"tips.db"
@@@ -40847,7 +41518,7 @@
"repo": "OpenVibe.Tips",
"table": "tip_interactions",
"declaredAt": [
-- "server/db.js:58"
++ "server/db.js:59"
],
"prodDbs": [
"tips.db"
@@@ -40859,6 +41530,48 @@
"wave": "W9",
"note": "Tip interactions, goals, overlays, imports."
},
++ {
++ "repo": "OpenVibe.Tips",
++ "table": "tip_moderation_log",
++ "declaredAt": [
++ "server/db.js:275"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "W9",
++ "note": "Tip interactions, goals, overlays, imports."
++ },
++ {
++ "repo": "OpenVibe.Tips",
++ "table": "tip_moderator_invites",
++ "declaredAt": [
++ "server/db.js:263"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "W9",
++ "note": "Tip interactions, goals, overlays, imports."
++ },
++ {
++ "repo": "OpenVibe.Tips",
++ "table": "tip_moderators",
++ "declaredAt": [
++ "server/db.js:252"
++ ],
++ "prodDbs": [],
++ "inCode": true,
++ "inProd": false,
++ "target": "OpenVibe.Tips",
++ "disposition": "keep",
++ "wave": "W9",
++ "note": "Tip interactions, goals, overlays, imports."
++ },
{
"repo": "OpenVibe.Tools",
"table": "analytics_daily",
@@@ -41867,6 +42580,16 @@
"timeout": true,
"retry": false
},
++ {
++ "caller": "OpenVibe.Chat",
++ "file": "server/prefs/network-modules.js",
++ "target": "OpenVibe.Network",
++ "via": "networkInternalUrl",
++ "lines": "21",
++ "auth": "service-token",
++ "timeout": true,
++ "retry": true
++ },
{
"caller": "OpenVibe.Chat",
"file": "server/chat/routes.js",
@@@ -42092,7 +42815,7 @@
"file": "server/seo/seo.js",
"target": "OpenVibe.Community",
"via": "OV_COMMUNITY_URL",
-- "lines": "427",
++ "lines": "432",
"auth": "none-detected",
"timeout": false,
"retry": false
@@@ -42562,7 +43285,7 @@
"file": "navbar.js",
"target": "OpenVibe.Network",
"via": "/api/auth/me",
-- "lines": "10,1010,1013",
++ "lines": "10,1013,1016",
"auth": "bearer",
"timeout": false,
"retry": true
@@@ -44786,6 +45509,69 @@
],
"prod": null
},
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_EVENTS_ENDPOINT",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_EVENTS_SECRET",
++ "secret": true,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_EVENTS_SUBSCRIBE",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_PREFS_CACHE_MAX",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_PREFS_ENABLED",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_PREFS_TIMEOUT_MS",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Chat",
++ "name": "CHAT_PREFS_TTL_MS",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
{
"repo": "OpenVibe.Chat",
"name": "CHAT_VIP_BADGE_DENY_TTL_MS",
@@@ -48060,6 +48846,7 @@
"name": "MEDIA_API_KEY",
"secret": true,
"files": [
++ "server/lineage/media-source.js",
"server/media-client.js"
],
"prod": "live.env"
@@@ -49052,6 +49839,24 @@
],
"prod": "media.env"
},
++ {
++ "repo": "OpenVibe.Media",
++ "name": "MEDIA_JOBS_ENABLED",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
++ {
++ "repo": "OpenVibe.Media",
++ "name": "MEDIA_JOBS_HEAVY_WHILE_RECORDING",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
{
"repo": "OpenVibe.Media",
"name": "MEDIA_PUBLIC_URL",
@@@ -51597,6 +52402,15 @@
],
"prod": null
},
++ {
++ "repo": "OpenVibe.Tips",
++ "name": "TIPS_MAX_PENDING_CHECKOUTS",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
{
"repo": "OpenVibe.Tips",
"name": "TIPS_MEDIA_HOSTS",
@@@ -51633,6 +52447,15 @@
],
"prod": null
},
++ {
++ "repo": "OpenVibe.Tips",
++ "name": "TIPS_OVERLAY_MAX_STREAMS",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
{
"repo": "OpenVibe.Tips",
"name": "TIPS_OVERLAY_REPLAY_LIMIT",
@@@ -52844,6 +53667,15 @@
],
"prod": null
},
++ {
++ "repo": "OpenVibe.VIP",
++ "name": "VIP_MEMBER_COUNT_TTL_MS",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
{
"repo": "OpenVibe.VIP",
"name": "VIP_POWERCHAT_LINK_TEMPLATE",
@@@ -52889,6 +53721,15 @@
],
"prod": null
},
++ {
++ "repo": "OpenVibe.VIP",
++ "name": "VIP_WIDGET_FRAME_ANCESTORS",
++ "secret": false,
++ "files": [
++ "server/config.js"
++ ],
++ "prod": null
++ },
{
"repo": "OpenVibe.Wiki",
"name": "BASE_URL",
@@@ -53191,12 +54032,24 @@
"subject": "billing",
"detail": "deployed c646279 is 1 commit(s) behind origin/main aa445d0"
},
++ {
++ "severity": "medium",
++ "area": "deploy",
++ "subject": "chat",
++ "detail": "deployed 7897688 is 2 commit(s) behind origin/main ed90461"
++ },
{
"severity": "medium",
"area": "deploy",
"subject": "codes",
"detail": "deployed d60f279 is 1 commit(s) behind origin/main 51d2386"
},
++ {
++ "severity": "medium",
++ "area": "deploy",
++ "subject": "community",
++ "detail": "deployed 57d1dd4 is 1 commit(s) behind origin/main 63b90a8"
++ },
{
"severity": "medium",
"area": "deploy",
@@@ -53225,7 +54078,25 @@
"severity": "medium",
"area": "deploy",
"subject": "host",
-- "detail": "deployed 30f08d6 is 14 commit(s) behind origin/main ea99b50"
++ "detail": "deployed 30f08d6 is 15 commit(s) behind origin/main 03dfcb3"
++ },
++ {
++ "severity": "medium",
++ "area": "deploy",
++ "subject": "live",
++ "detail": "deployed c893c6c is 12 commit(s) behind origin/main ca7cc87"
++ },
++ {
++ "severity": "medium",
++ "area": "deploy",
++ "subject": "media",
++ "detail": "deployed 9de4b25 is 4 commit(s) behind origin/main ad2217b"
++ },
++ {
++ "severity": "medium",
++ "area": "deploy",
++ "subject": "network",
++ "detail": "deployed 9bbd90f is 4 commit(s) behind origin/main 09bf748"
},
{
"severity": "medium",
@@@ -53255,7 +54126,7 @@
"severity": "medium",
"area": "deploy",
"subject": "tips",
-- "detail": "deployed 15bfc12 is 1 commit(s) behind origin/main 9a3a186"
++ "detail": "deployed 15bfc12 is 6 commit(s) behind origin/main f211c03"
},
{
"severity": "medium",
@@@ -53263,6 +54134,12 @@
"subject": "trade",
"detail": "deployed 9a55644 is 2 commit(s) behind origin/main ddbc60c"
},
++ {
++ "severity": "medium",
++ "area": "deploy",
++ "subject": "vip",
++ "detail": "deployed 9668a49 is 1 commit(s) behind origin/main fe7eaad"
++ },
{
"severity": "medium",
"area": "deploy",
@@@ -53437,6 +54314,12 @@
"subject": "OpenVibe.Billing:STRIPE_WEBHOOK_SECRET",
"detail": "secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback"
},
++ {
++ "severity": "low",
++ "area": "env",
++ "subject": "OpenVibe.Chat:CHAT_EVENTS_SECRET",
++ "detail": "secret-named variable read by code but not set in the service env file: verify it is optional or has no hardcoded fallback"
++ },
{
"severity": "low",
"area": "env",
@@@ -54169,6 +55052,18 @@
"subject": "OpenVibe.Blog:event_outbox",
"detail": "in production (blog.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Blog (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.)"
},
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Chat:chat_event_inbox",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Chat:deploy_releases",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
{
"severity": "info",
"area": "schema",
@@@ -54319,6 +55214,18 @@
"subject": "OpenVibe.Media:event_outbox",
"detail": "in production (media.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Media (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.)"
},
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Media:media_upload_parts",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Media:media_uploads",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
{
"severity": "info",
"area": "schema",
@@@ -54373,6 +55280,18 @@
"subject": "OpenVibe.Network:network_event_outbox",
"detail": "in production (network.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Network (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.)"
},
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Network:user_module_retirements",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Network:user_module_revisions",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
{
"severity": "info",
"area": "schema",
@@@ -54559,6 +55478,24 @@
"subject": "OpenVibe.Tips:idempotency_receipts",
"detail": "in production (tips.db) but no CREATE TABLE in the repo; classified keep -> OpenVibe.Tips (Created at runtime by the openvibe-sdk / openvibe-events outbox and inbox helpers.)"
},
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Tips:tip_moderation_log",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Tips:tip_moderator_invites",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
++ {
++ "severity": "info",
++ "area": "schema",
++ "subject": "OpenVibe.Tips:tip_moderators",
++ "detail": "declared in code but absent from every production database for this service (lazy/unused/legacy migration)"
++ },
{
"severity": "info",
"area": "schema",
@@@ -54742,16 +55679,16 @@
],
"metrics": {
"github.charters": "1 charter-only repos of 36",
-- "contract.todo-markers": "Live 15, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0",
-- "outbound.call-sites": "97 caller-file/target pairs across 74 files",
-- "outbound.internal-key": "39 of 97 call sites authenticate with the shared internal key",
++ "contract.todo-markers": "Live 14, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0",
++ "outbound.call-sites": "98 caller-file/target pairs across 75 files",
++ "outbound.internal-key": "39 of 98 call sites authenticate with the shared internal key",
"ws.servers": "11 WebSocket server constructions",
"tables.analytics-copies": "3 repos carry their own analytics_events",
-- "shared.pins": "23 repos pin a tagged openvibe-shared release (latest v1.4.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0",
-- "shared.drift": "20 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Media (v1.3.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0)",
++ "shared.pins": "23 repos pin a tagged openvibe-shared release (latest v1.5.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0",
++ "shared.drift": "30 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Live (v1.4.0), Media (v1.3.0), Network (v1.4.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Tools/apps/audio (v1.4.0), Tools/apps/docs (v1.4.0), Tools/apps/food (v1.4.0), Tools/apps/gateway (v1.4.0), Tools/apps/img (v1.4.0), Tools/apps/maps (v1.4.0), Tools/apps/text (v1.4.0), Tools/apps/yt (v1.4.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0)",
"ci.repos": "27 of 27 scanned repos have .github/workflows",
-- "deploy.drift": "15 service(s) not running origin/main",
-- "tests.OpenVibe.Live": "78 test files",
++ "deploy.drift": "21 service(s) not running origin/main",
++ "tests.OpenVibe.Live": "81 test files",
"tables.OpenVibe.Live": "125 tables",
"tables.OpenVibe.Live.target:OpenVibe.Games (import source)": "31 Live tables target OpenVibe.Games (import source)",
"tables.OpenVibe.Live.target:OpenVibe.AI": "14 Live tables target OpenVibe.AI",
@@@ -54770,16 +55707,16 @@
"tables.OpenVibe.Live.target:OpenVibe.Billing": "2 Live tables target OpenVibe.Billing",
"tables.OpenVibe.Live.target:OpenVibe.Billing + OpenVibe.VIP": "1 Live tables target OpenVibe.Billing + OpenVibe.VIP",
"tables.OpenVibe.Live.target:OpenVibe.Codes": "2 Live tables target OpenVibe.Codes",
-- "tests.OpenVibe.Network": "28 test files",
-- "tables.OpenVibe.Network": "43 tables",
-- "tables.OpenVibe.Network.target:OpenVibe.Network": "48 Network tables target OpenVibe.Network",
++ "tests.OpenVibe.Network": "29 test files",
++ "tables.OpenVibe.Network": "45 tables",
++ "tables.OpenVibe.Network.target:OpenVibe.Network": "50 Network tables target OpenVibe.Network",
"tables.OpenVibe.Network.target:OpenVibe.Billing (loyalty ledger)": "2 Network tables target OpenVibe.Billing (loyalty ledger)",
"tables.OpenVibe.Network.target:OpenVibe.Events": "1 Network tables target OpenVibe.Events",
-- "tests.OpenVibe.Shared": "17 test files",
++ "tests.OpenVibe.Shared": "19 test files",
"tables.OpenVibe.Shared": "0 tables",
-- "tests.OpenVibe.Media": "16 test files",
-- "tables.OpenVibe.Media": "20 tables",
-- "tables.OpenVibe.Media.target:OpenVibe.Media": "18 Media tables target OpenVibe.Media",
++ "tests.OpenVibe.Media": "20 test files",
++ "tables.OpenVibe.Media": "22 tables",
++ "tables.OpenVibe.Media.target:OpenVibe.Media": "20 Media tables target OpenVibe.Media",
"tables.OpenVibe.Media.target:OpenVibe.Community": "3 Media tables target OpenVibe.Community",
"tests.OpenVibe.Tools": "16 test files",
"tables.OpenVibe.Tools": "3 tables",
@@@ -54795,19 +55732,19 @@
"tests.OpenVibe.Events": "12 test files",
"tables.OpenVibe.Events": "7 tables",
"tables.OpenVibe.Events.target:OpenVibe.Events": "7 Events tables target OpenVibe.Events",
-- "tests.OpenVibe.Chat": "16 test files",
-- "tables.OpenVibe.Chat": "32 tables",
-- "tables.OpenVibe.Chat.target:OpenVibe.Chat": "32 Chat tables target OpenVibe.Chat",
++ "tests.OpenVibe.Chat": "19 test files",
++ "tables.OpenVibe.Chat": "34 tables",
++ "tables.OpenVibe.Chat.target:OpenVibe.Chat": "34 Chat tables target OpenVibe.Chat",
"tests.OpenRe.Stream": "18 test files",
"tables.OpenRe.Stream": "12 tables",
"tables.OpenRe.Stream.target:OpenRe.Stream": "13 OpenRe.Stream tables target OpenRe.Stream",
"tests.OpenVibe.Billing": "16 test files",
"tables.OpenVibe.Billing": "19 tables",
"tables.OpenVibe.Billing.target:OpenVibe.Billing": "19 Billing tables target OpenVibe.Billing",
-- "tests.OpenVibe.Tips": "11 test files",
-- "tables.OpenVibe.Tips": "14 tables",
-- "tables.OpenVibe.Tips.target:OpenVibe.Tips": "16 Tips tables target OpenVibe.Tips",
-- "tests.OpenVibe.VIP": "10 test files",
++ "tests.OpenVibe.Tips": "15 test files",
++ "tables.OpenVibe.Tips": "17 tables",
++ "tables.OpenVibe.Tips.target:OpenVibe.Tips": "19 Tips tables target OpenVibe.Tips",
++ "tests.OpenVibe.VIP": "11 test files",
"tables.OpenVibe.VIP": "13 tables",
"tables.OpenVibe.VIP.target:OpenVibe.VIP": "15 VIP tables target OpenVibe.VIP",
"tests.OpenVibe.AI": "17 test files",
@@@ -54883,7 +55820,7 @@
},
{
"key": "contract.todo-markers",
-- "value": "Live 15, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0"
++ "value": "Live 14, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0"
}
],
"members": [
@@@ -54950,7 +55887,7 @@
"metrics": [
{
"key": "outbound.call-sites",
-- "value": "97 caller-file/target pairs across 74 files"
++ "value": "98 caller-file/target pairs across 75 files"
},
{
"key": "ws.servers",
@@@ -55019,7 +55956,7 @@
"D17 partial",
"D18 blocked on owner",
"D19 partial",
-- "D20 not met"
++ "D20 partial"
],
"status": "partial",
"verified": true
@@@ -55036,7 +55973,7 @@
},
{
"key": "tests.OpenVibe.Chat",
-- "value": "16 test files"
++ "value": "19 test files"
}
],
"members": [
@@@ -55229,7 +56166,7 @@
"metrics": [
{
"key": "outbound.internal-key",
-- "value": "39 of 97 call sites authenticate with the shared internal key"
++ "value": "39 of 98 call sites authenticate with the shared internal key"
}
],
"members": [
@@@ -55264,11 +56201,11 @@
"metrics": [
{
"key": "shared.pins",
-- "value": "23 repos pin a tagged openvibe-shared release (latest v1.4.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0"
++ "value": "23 repos pin a tagged openvibe-shared release (latest v1.5.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0"
},
{
"key": "shared.drift",
-- "value": "20 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Media (v1.3.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0)"
++ "value": "30 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Live (v1.4.0), Media (v1.3.0), Network (v1.4.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Tools/apps/audio (v1.4.0), Tools/apps/docs (v1.4.0), Tools/apps/food (v1.4.0), Tools/apps/gateway (v1.4.0), Tools/apps/img (v1.4.0), Tools/apps/maps (v1.4.0), Tools/apps/text (v1.4.0), Tools/apps/yt (v1.4.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0)"
}
],
"members": [
@@@ -55318,7 +56255,7 @@
"metrics": [
{
"key": "deploy.drift",
-- "value": "15 service(s) not running origin/main"
++ "value": "21 service(s) not running origin/main"
}
],
"members": [
@@@ -55451,7 +56388,7 @@
"status": "open",
"check": "workstation-disk",
"ownerReview": false,
-- "checkResult": "workstation / is 86% used (at generation time)"
++ "checkResult": "workstation / is 87% used (at generation time)"
},
{
"id": "H8",
@@@ -55536,7 +56473,7 @@
"status": "open",
"check": "deploy-drift",
"ownerReview": false,
-- "checkResult": "ai: deployed 96dc8a3 is 1 commit(s) behind origin/main 3a480ac; billing: deployed c646279 is 1 commit(s) behind origin/main aa445d0; codes: deployed d60f279 is 1 commit(s) behind origin/main 51d2386; coupons: deployed 54df411 is 3 commit(s) behind origin/main 1c57c47; deals: deployed e72aeec is 2 commit(s) behind origin/main 91ca223; events: deployed 3366132 is 1 commit(s) behind origin/main efc09a7; games: deployed 474df50 is 1 commit(s) behind origin/main 7863fc6; host: deployed 30f08d6 is 14 commit(s) behind origin/main ea99b50; news: deployed 5a17e7f is 1 commit(s) behind origin/main 5b393d2; openre: deployed e0dc1b4 is 2 commit(s) behind origin/main c091a09; reviews: deployed 1d462a2 is 1 commit(s) behind origin/main a7b50a6; sites: deployed d3b71af is 2 commit(s) behind origin/main d6e4cbd; tips: deployed 15bfc12 is 1 commit(s) behind origin/main 9a3a186; trade: deployed 9a55644 is 2 commit(s) behind origin/main ddbc60c; wiki: deployed 011a68f is 1 commit(s) behind origin/main b4e70ac"
++ "checkResult": "ai: deployed 96dc8a3 is 1 commit(s) behind origin/main 3a480ac; billing: deployed c646279 is 1 commit(s) behind origin/main aa445d0; chat: deployed 7897688 is 2 commit(s) behind origin/main ed90461; codes: deployed d60f279 is 1 commit(s) behind origin/main 51d2386; community: deployed 57d1dd4 is 1 commit(s) behind origin/main 63b90a8; coupons: deployed 54df411 is 3 commit(s) behind origin/main 1c57c47; deals: deployed e72aeec is 2 commit(s) behind origin/main 91ca223; events: deployed 3366132 is 1 commit(s) behind origin/main efc09a7; games: deployed 474df50 is 1 commit(s) behind origin/main 7863fc6; host: deployed 30f08d6 is 15 commit(s) behind origin/main 03dfcb3; live: deployed c893c6c is 12 commit(s) behind origin/main ca7cc87; media: deployed 9de4b25 is 4 commit(s) behind origin/main ad2217b; network: deployed 9bbd90f is 4 commit(s) behind origin/main 09bf748; news: deployed 5a17e7f is 1 commit(s) behind origin/main 5b393d2; openre: deployed e0dc1b4 is 2 commit(s) behind origin/main c091a09; reviews: deployed 1d462a2 is 1 commit(s) behind origin/main a7b50a6; sites: deployed d3b71af is 2 commit(s) behind origin/main d6e4cbd; tips: deployed 15bfc12 is 6 commit(s) behind origin/main f211c03; trade: deployed 9a55644 is 2 commit(s) behind origin/main ddbc60c; vip: deployed 9668a49 is 1 commit(s) behind origin/main fe7eaad; wiki: deployed 011a68f is 1 commit(s) behind origin/main b4e70ac"
},
{
"id": "H14",
@@@ -55615,25 +56552,25 @@
"id": "EC1",
"text": "Every table has an owner classification",
"pass": true,
-- "detail": "612 tables classified, 0 unclassified"
++ "detail": "621 tables classified, 0 unclassified"
},
{
"id": "EC2",
"text": "Every route is attributed to a repo and source line, with an owner classification",
"pass": true,
-- "detail": "2055 routes, 0 unclassified; 0 router mounts whose module could not be resolved (their routes are listed without the mount prefix)"
++ "detail": "2098 routes, 0 unclassified; 0 router mounts whose module could not be resolved (their routes are listed without the mount prefix)"
},
{
"id": "EC3",
"text": "Every background job is listed with its location and an owner classification",
"pass": true,
-- "detail": "141 timers/jobs, 0 unclassified"
++ "detail": "145 timers/jobs, 0 unclassified"
},
{
"id": "EC4",
"text": "Every cross-service call records caller, callee, auth, timeout and retry",
"pass": true,
-- "detail": "97 call sites; 36 with no timeout detected"
++ "detail": "98 call sites; 36 with no timeout detected"
},
{
"id": "EC5",
ddiff --git a/docs/roadmap-baseline/requirement-ledger.json b/docs/roadmap-baseline/requirement-ledger.json
iindex c7753b2a..4a51a2b7 100644
---- a/docs/roadmap-baseline/requirement-ledger.json
++++ b/docs/roadmap-baseline/requirement-ledger.json
@@@ -2,20 +2,20 @@
"_about": "Generated from data/requirement-ledger.json by scripts/roadmap-baseline/generate.js. Umbrella-level ledger (roadmap §22.4/§25): one row per D01-D46 requirement, every artifact re-verified against the scanned origin/main checkouts and prod-snapshot.json. Do not edit; edit the data file and regenerate.",
"asOf": "2026-09-23T20:30Z",
"generatedFrom": {
-- "OpenVibe.Live": "c893c6ca709926635522bac053f52062b5d3e1ad",
-- "OpenVibe.Network": "9bbd90f786fb80b02cbf7592ff9217844a714c32",
-- "OpenVibe.Shared": "c6405d48fabede75e2a9ef417fae46d493cfb940",
-- "OpenVibe.Media": "9de4b2528dd5787e7b5633d16eed40d8b4d43b4b",
++ "OpenVibe.Live": "ca7cc87672602e35756b8b348559543efab1bc38",
++ "OpenVibe.Network": "09bf748b7f459ac127b3f4045085c20189d39dbb",
++ "OpenVibe.Shared": "c2726807c19505bc22d2bce794188a9d1516b022",
++ "OpenVibe.Media": "ad2217be56627efca799fd3ce0987d91cb6f3e24",
"OpenVibe.Tools": "5d1b42357392d47e5cc3f6bef3f22facdc6c23cd",
-- "OpenVibe.Community": "57d1dd4cbdc79f39ae5e98cc0d09b03a75508f5d",
++ "OpenVibe.Community": "63b90a838d280aada7d6c98aee61335b972c1105",
"OpenVibe.Games": "7863fc6a71890b264c29ddd6bfa7e4c162da4883",
"OpenVibe.Sites": "d6e4cbd3a2091bb9970ee15504c7758da8a96a24",
"OpenVibe.Events": "efc09a795ea0fdea9e6eca04f20cc44362b91e3f",
-- "OpenVibe.Chat": "789768806b0d217b0bc735c319d20d1b6ebb4df8",
++ "OpenVibe.Chat": "ed90461e2fd4537332275f6efec8bb878ce4ac2a",
"OpenRe.Stream": "c091a0959a6d727ec702ee589300cd42a0902be9",
"OpenVibe.Billing": "aa445d0c8b7351afae910b9572a2f9ae674e0914",
-- "OpenVibe.Tips": "9a3a186182df7d150780b31d191ea1eb99c95962",
-- "OpenVibe.VIP": "9668a492b8f5b6c111261cf0e4270fc4ffcf521d",
++ "OpenVibe.Tips": "f211c03ed01b58dd52d104bda8b07ce1a82da2db",
++ "OpenVibe.VIP": "fe7eaad183622f303d2ea1efde80d1674478d948",
"OpenVibe.AI": "3a480ac9f20ca018f5c2c8973f92d32dbe1a44cd",
"OpenVibe.Search": "a707e38f87a077bbf2f570537a89b2f890d45e22",
"OpenVibe.Sources": "2e986af27a5554fd01803daf9e55c726deded80d",
@@@ -27,7 +27,7 @@
"OpenVibe.Coupons": "1c57c4743b016ecf6f72d8d03feb7f56806920a6",
"OpenVibe.Trade": "ddbc60c5e2f5ab16cfd17cd126803c9c24784662",
"OpenVibe.Codes": "51d23865f2630203cf734c019309c7ffc053f89c",
-- "OpenVibe.Host": "ea99b502c072ae6635f7705e002e0ec174cae16d",
++ "OpenVibe.Host": "03dfcb32a9fecb85d509f5d92d0a166a26d86fe7",
"OpenVibe.Examples": "d5f4efc02165f42b9feac5d2743de6e6c75c27de"
},
"prodSnapshot": {
@@@ -43,8 +43,8 @@
"counts": {
"requirements": {
"met": 3,
-- "partial": 35,
-- "not-met": 1,
++ "partial": 36,
++ "not-met": 0,
"blocked-on-owner": 7
},
"families": {
@@@ -97,7 +97,7 @@
},
{
"key": "contract.todo-markers",
-- "value": "Live 15, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0"
++ "value": "Live 14, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0"
}
]
},
@@@ -149,7 +149,7 @@
"metrics": [
{
"key": "outbound.call-sites",
-- "value": "97 caller-file/target pairs across 74 files"
++ "value": "98 caller-file/target pairs across 75 files"
},
{
"key": "ws.servers",
@@@ -219,7 +219,7 @@
},
{
"key": "tests.OpenVibe.Chat",
-- "value": "16 test files"
++ "value": "19 test files"
}
]
},
@@@ -375,7 +375,7 @@
"metrics": [
{
"key": "outbound.internal-key",
-- "value": "39 of 97 call sites authenticate with the shared internal key"
++ "value": "39 of 98 call sites authenticate with the shared internal key"
}
]
},
@@@ -404,11 +404,11 @@
"metrics": [
{
"key": "shared.pins",
-- "value": "23 repos pin a tagged openvibe-shared release (latest v1.4.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0"
++ "value": "23 repos pin a tagged openvibe-shared release (latest v1.5.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0"
},
{
"key": "shared.drift",
-- "value": "20 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Media (v1.3.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0)"
++ "value": "30 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Live (v1.4.0), Media (v1.3.0), Network (v1.4.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Tools/apps/audio (v1.4.0), Tools/apps/docs (v1.4.0), Tools/apps/food (v1.4.0), Tools/apps/gateway (v1.4.0), Tools/apps/img (v1.4.0), Tools/apps/maps (v1.4.0), Tools/apps/text (v1.4.0), Tools/apps/yt (v1.4.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0)"
}
]
},
@@@ -449,7 +449,7 @@
"metrics": [
{
"key": "deploy.drift",
-- "value": "15 service(s) not running origin/main"
++ "value": "21 service(s) not running origin/main"
}
]
},
@@@ -1576,41 +1576,40 @@
{
"id": "D20",
"title": "Canonical resolver",
-- "owner": "none (per-product mappings in OpenVibe.Live; typed refs in OpenVibe.Contracts)",
++ "owner": "OpenVibe.Live (server/lineage/resolver.js, GET|POST /internal/lineage/resolve); contract in OpenVibe.Contracts",
"target": "shared lineage-resolver contract",
-- "status": "not-met",
-- "summary": "No lineage-resolver contract or shared resolver exists in any repo (no 'lineage' or resolver code in Contracts, Live, Media, OpenRe or Community on origin/main, 2026-09-23). The pieces that exist are the EntityRef typed-reference schema and OpenRe stream definitions carrying external refs to Live's slot and user; in production no Live slot has an openre_stream_id and openre_sessions is empty, so VOD to channel/stream/session lineage is not recorded.",
++ "status": "partial",
++ "summary": "The lineage-resolver contract exists (openvibe-contracts v0.32.0: lineage.resolve-request@1 -> lineage.resolution@1, capability live.lineage.resolve) and is implemented once in Live, deployed 2026-09-23 21:36 UTC: it answers which channel, and whose, a slug, nested slug, channel id, stream, slot, VOD, clip, Media object, owner subject or legacy id belongs to, in the roadmap's precedence, with explicit unresolved states (conflict, source_unavailable, display_name_only, not_found) and never from a display name; VODs, clips and objects come from Media. Live's clip owner check uses it. No other service calls it yet (no principal holds live.lineage.resolve), OpenRe sessions record no lineage, and Media objects still lack owner_subject.",
"artifacts": [
{
"kind": "doc",
"repo": "OpenVibe.Contracts",
-- "path": "contracts/common/entity-ref.v1.json",
-- "contains": "Typed reference to another service's entity",
-- "proves": "only a typed-reference schema is shared; it carries no resolution rules or lineage",
++ "path": "contracts/lineage/resolve-request.v1.json",
++ "contains": "LineageResolveRequest",
++ "proves": "the shared resolver contract (inputs) is published in v0.32.0",
"ok": true
},
{
"kind": "test",
"repo": "OpenVibe.Live",
-- "path": "test/openre-switch.test.js",
-- "contains": "['live:managed_stream:701', 'live:user:601']",
-- "proves": "an OpenRe definition records typed refs back to Live's slot and owner: one lineage input, not a shared resolver",
++ "path": "test/lineage-resolver.test.js",
++ "contains": "expectUnresolved({ display_name: 'alice' }, 'display_name_only')",
++ "proves": "the resolver never derives ownership from a display name, even one equal to a username; every answer is validated against lineage.resolution@1",
"ok": true
},
{
"kind": "prod",
-- "check": "ssh openvibe-ovh 'sudo -n -u \"$(stat -c %U /opt/openvibe.live/data/live.db)\" sqlite3 -readonly /opt/openvibe.live/data/live.db \"SELECT count(*), sum(openre_stream_id IS NOT NULL) FROM managed_streams; SELECT count(*) FROM openre_sessions;\"'",
-- "observed": "102|0; 0",
-- "at": "2026-09-23T20:18Z",
-- "proves": "no stream/session lineage exists in production to resolve against",
++ "check": "ssh openvibe-ovh 'curl -s -o /dev/null -w \"%{http_code}\" \"http://127.0.0.1:3000/internal/lineage/resolve?slug=goosely\"'",
++ "observed": "401",
++ "at": "2026-09-23T21:37Z",
++ "proves": "the resolver is deployed on production behind a service token (loopback only; 403 through nginx)",
"ok": true
}
],
"remaining": [
-- "Write the lineage-resolver contract in OpenVibe.Contracts (inputs: explicit slug, nested/parent slug, channel id, stream lookup, VOD parent, media lineage, owner subject, legacy metadata and maps; output includes an explicit unresolved state)",
-- "Implement it once and use it from channel, stream, VOD, clip, Pulse and creator UI; never derive ownership from a display name",
-- "Record VOD/clip lineage to channel, stream and OpenRe session (roadmap §20 'VOD lineage maps back to the canonical channel, stream and session') with a test that an unresolvable item returns unresolved",
-- "Backfill Media owner_subject so the resolver has a subject for every object"
++ "Grant live.lineage.resolve to the consumers (OpenRe, Media, Pulse, creator UI) once their contracts pin is 0.32.0+, and switch their per-product channel mappings to the resolver",
++ "Record VOD/clip lineage to OpenRe session (roadmap §20 'VOD lineage maps back to the canonical channel, stream and session'); no OpenRe session exists in production yet",
++ "Backfill Media owner_subject so the resolver has a subject for every object (Live now knows the subject of all 328 linked accounts)"
],
"blockedOn": null,
"ownerReview": false,
ddiff --git a/docs/roadmap-baseline/requirement-ledger.md b/docs/roadmap-baseline/requirement-ledger.md
iindex ce056331..bbad3c88 100644
---- a/docs/roadmap-baseline/requirement-ledger.md
++++ b/docs/roadmap-baseline/requirement-ledger.md
@@@ -20,8 +20,8 @@ Every run re-verifies each artifact: a test, doc or drill file must exist at ori
| Status | Requirements | Families |
|---|---|---|
| met | 3 | 0 |
--| partial | 35 | 21 |
--| not met | 1 | 0 |
++| partial | 36 | 21 |
++| not met | 0 | 0 |
| blocked on owner | 7 | 1 |
@@@ -51,7 +51,7 @@ Every run re-verifies each artifact: a test, doc or drill file must exist at ori
| [D17](#d17) | Live product | **partial** | OpenVibe.Live | 5/5 | Ingest transport: move RTMP slots to OpenRe (0 of 102 switched), then WHIP, JSMPEG and SFU, so Live stops binding 1935 and a Live deploy stops dropping streams |
| [D18](#d18) | Stream Manager | **blocked on owner** | OpenVibe.Live (Stream Manager UX) + OpenRe.Stream (control API) | 4/4 | Switch slots to OpenRe (OpenRe docs/cutover.md A7 rehearsal, then B1-B6 per slot) so the rebinding runs in production |
| [D19](#d19) | OpenRe | **partial** | OpenRe.Stream (runtime); OpenVibe.Live still ingests every slot | 5/5 | Cut slots over (0 of 102 switched; migrate-from-live.js never applied, migration_map 0) so OpenRe owns real sessions |
--| [D20](#d20) | Canonical resolver | **not met** | none (per-product mappings in OpenVibe.Live; typed refs in OpenVibe.Contracts) | 3/3 | Write the lineage-resolver contract in OpenVibe.Contracts (inputs: explicit slug, nested/parent slug, channel id, stream lookup, VOD parent, media lineage, owner subject, legacy metadata and maps; output includes an explicit unresolved state) |
++| [D20](#d20) | Canonical resolver | **partial** | OpenVibe.Live (server/lineage/resolver.js, GET\|POST /internal/lineage/resolve); contract in OpenVibe.Contracts | 3/3 | Grant live.lineage.resolve to the consumers (OpenRe, Media, Pulse, creator UI) once their contracts pin is 0.32.0+, and switch their per-product channel mappings to the resolver |
| [D21](#d21) | Chat model | **partial** | OpenVibe.Chat (Live keeps 6 staged tables, media requests and calls) | 4/4 | Move call signalling and call state from Live's /ws/call into Chat |
| [D22](#d22) | Chat authorization | **partial** | OpenVibe.Chat (user identity still resolved by OpenVibe.Live) | 5/5 | Authenticate browsers in Chat from Network tokens and a central capability/staff map; today Chat's auth.js resolves users, roles and API-token scopes through Live (live-context.authenticate) |
| [D23](#d23) | Chat parity | **partial** | OpenVibe.Chat | 5/5 | Calls: move signalling to Chat with the pending\|ringing\|active\|ended\|missed\|declined\|failed lifecycle and an explicit failure state (roadmap §15.9, §20) |
@@@ -143,7 +143,7 @@ Remaining:
### D02-D04 Registry, capabilities, contracts: partial
--Roadmap §3.2 (W0, 2026-09-22): absent. Waves: W1, W2. Measured this run: 1 charter-only repos of 36; Live 15, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0.
++Roadmap §3.2 (W0, 2026-09-22): absent. Waves: W1, W2. Measured this run: 1 charter-only repos of 36; Live 14, Network 0, Shared 0, Media 0, Tools 0, Community 0, Games 0, Sites 0, Events 0, Chat 0, OpenRe.Stream 0, Billing 0, Tips 0, VIP 0, AI 0, Search 0, Sources 0, Wiki 0, Blog 0, News 0, Reviews 0, Deals 0, Coupons 0, Trade 0, Codes 0, Host 0, Examples 0.
#### D02
@@@ -344,7 +344,7 @@ Remaining:
### D11-D13 Events, realtime, SDK: partial
--Roadmap §3.2 (W0, 2026-09-22): absent. Waves: W2, W3. Measured this run: 97 caller-file/target pairs across 74 files; 11 WebSocket server constructions.
++Roadmap §3.2 (W0, 2026-09-22): absent. Waves: W2, W3. Measured this run: 98 caller-file/target pairs across 75 files; 11 WebSocket server constructions.
#### D11
@@@ -553,26 +553,25 @@ Blocked on the owner: A7 rehearsal inputs (test account + real rtmp:// destinati
#### D20
--**Canonical resolver: not met**. Owner today: none (per-product mappings in OpenVibe.Live; typed refs in OpenVibe.Contracts). Target (§15.0): shared lineage-resolver contract.
++**Canonical resolver: partial**. Owner today: OpenVibe.Live (server/lineage/resolver.js, GET|POST /internal/lineage/resolve); contract in OpenVibe.Contracts. Target (§15.0): shared lineage-resolver contract.
--No lineage-resolver contract or shared resolver exists in any repo (no 'lineage' or resolver code in Contracts, Live, Media, OpenRe or Community on origin/main, 2026-09-23). The pieces that exist are the EntityRef typed-reference schema and OpenRe stream definitions carrying external refs to Live's slot and user; in production no Live slot has an openre_stream_id and openre_sessions is empty, so VOD to channel/stream/session lineage is not recorded.
++The lineage-resolver contract exists (openvibe-contracts v0.32.0: lineage.resolve-request@1 -> lineage.resolution@1, capability live.lineage.resolve) and is implemented once in Live, deployed 2026-09-23 21:36 UTC: it answers which channel, and whose, a slug, nested slug, channel id, stream, slot, VOD, clip, Media object, owner subject or legacy id belongs to, in the roadmap's precedence, with explicit unresolved states (conflict, source_unavailable, display_name_only, not_found) and never from a display name; VODs, clips and objects come from Media. Live's clip owner check uses it. No other service calls it yet (no principal holds live.lineage.resolve), OpenRe sessions record no lineage, and Media objects still lack owner_subject.
Acceptance artifacts:
--- doc: Contracts/contracts/common/entity-ref.v1.json ("Typed reference to another service's entity") - only a typed-reference schema is shared; it carries no resolution rules or lineage.
--- test: Live/test/openre-switch.test.js ("['live:managed_stream:701', 'live:user:601']") - an OpenRe definition records typed refs back to Live's slot and owner: one lineage input, not a shared resolver.
--- prod: `ssh openvibe-ovh 'sudo -n -u "$(stat -c %U /opt/openvibe.live/data/live.db)" sqlite3 -readonly /opt/openvibe.live/data/live.db "SELECT count(*), sum(openre_stream_id IS NOT NULL) FROM managed_streams; SELECT count(*) FROM openre_sessions;"'` (2026-09-23 20:18) - no stream/session lineage exists in production to resolve against. Observed: 102|0; 0.
++- doc: Contracts/contracts/lineage/resolve-request.v1.json ("LineageResolveRequest") - the shared resolver contract (inputs) is published in v0.32.0.
++- test: Live/test/lineage-resolver.test.js ("expectUnresolved({ display_name: 'alice' }, 'display_name_only')") - the resolver never derives ownership from a display name, even one equal to a username; every answer is validated against lineage.resolution@1.
++- prod: `ssh openvibe-ovh 'curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:3000/internal/lineage/resolve?slug=goosely"'` (2026-09-23 21:37) - the resolver is deployed on production behind a service token (loopback only; 403 through nginx). Observed: 401.
Remaining:
--- Write the lineage-resolver contract in OpenVibe.Contracts (inputs: explicit slug, nested/parent slug, channel id, stream lookup, VOD parent, media lineage, owner subject, legacy metadata and maps; output includes an explicit unresolved state)
--- Implement it once and use it from channel, stream, VOD, clip, Pulse and creator UI; never derive ownership from a display name
--- Record VOD/clip lineage to channel, stream and OpenRe session (roadmap §20 'VOD lineage maps back to the canonical channel, stream and session') with a test that an unresolvable item returns unresolved
--- Backfill Media owner_subject so the resolver has a subject for every object
++- Grant live.lineage.resolve to the consumers (OpenRe, Media, Pulse, creator UI) once their contracts pin is 0.32.0+, and switch their per-product channel mappings to the resolver
++- Record VOD/clip lineage to OpenRe session (roadmap §20 'VOD lineage maps back to the canonical channel, stream and session'); no OpenRe session exists in production yet
++- Backfill Media owner_subject so the resolver has a subject for every object (Live now knows the subject of all 328 linked accounts)
### D21-D23 Chat: partial
--Roadmap §3.2 (W0, 2026-09-22): partial. Waves: W6. Measured this run: 23 Live tables target OpenVibe.Chat; 16 test files.
++Roadmap §3.2 (W0, 2026-09-22): partial. Waves: W6. Measured this run: 23 Live tables target OpenVibe.Chat; 19 test files.
#### D21
@@@ -1022,7 +1021,7 @@ Remaining:
### D40 Open developer services: partial
--Roadmap §3.2 (W0, 2026-09-22): absent. Waves: W20, W21. Measured this run: 39 of 97 call sites authenticate with the shared internal key.
++Roadmap §3.2 (W0, 2026-09-22): absent. Waves: W20, W21. Measured this run: 39 of 98 call sites authenticate with the shared internal key.
#### D40
@@@ -1077,7 +1076,7 @@ Blocked on the owner: Open 1936/tcp at the host firewall and at the provider edg
### D42 Shared component architecture: partial
--Roadmap §3.2 (W0, 2026-09-22): partial. Waves: W2, Track R. Measured this run: 23 repos pin a tagged openvibe-shared release (latest v1.4.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0; 20 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Media (v1.3.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0).
++Roadmap §3.2 (W0, 2026-09-22): partial. Waves: W2, Track R. Measured this run: 23 repos pin a tagged openvibe-shared release (latest v1.5.0): OpenRe.Stream v1.2.1, AI v1.3.0, Billing v1.3.0, Blog v1.3.0, Codes v1.3.0, Community v1.3.0, Coupons v1.3.0, Deals v1.3.0, Events v1.3.0, Host v1.3.0, Live v1.4.0, Media v1.3.0, Network v1.4.0, News v1.3.0, Reviews v1.3.0, Search v1.3.0, Sites v1.0.0, Sources v1.3.0, Tips v1.3.0, Tools v1.4.0, Trade v1.3.0, VIP v1.3.0, Wiki v1.3.0; 30 manifests unpinned or behind: OpenRe.Stream (v1.2.1), AI (v1.3.0), Billing (v1.3.0), Blog (v1.3.0), Codes (v1.3.0), Community (v1.3.0), Coupons (v1.3.0), Deals (v1.3.0), Events (v1.3.0), Host (v1.3.0), Live (v1.4.0), Media (v1.3.0), Network (v1.4.0), News (v1.3.0), Reviews (v1.3.0), Search (v1.3.0), Sites (v1.0.0), Sources (v1.3.0), Tips (v1.3.0), Tools/apps/audio (v1.4.0), Tools/apps/docs (v1.4.0), Tools/apps/food (v1.4.0), Tools/apps/gateway (v1.4.0), Tools/apps/img (v1.4.0), Tools/apps/maps (v1.4.0), Tools/apps/text (v1.4.0), Tools/apps/yt (v1.4.0), Trade (v1.3.0), VIP (v1.3.0), Wiki (v1.3.0).
#### D42
@@@ -1158,7 +1157,7 @@ Remaining:
### D45 Release compatibility and recovery: partial
--Roadmap §3.2 (W0, 2026-09-22): absent. Waves: Track R, W22. Measured this run: 15 service(s) not running origin/main.
++Roadmap §3.2 (W0, 2026-09-22): absent. Waves: Track R, W22. Measured this run: 21 service(s) not running origin/main.
#### D45