openvibers/openvibe.host Commits

Compatibility register: C-14 closed, C-75 narrowed (43 closed, 1 kept, 5 open) (#67)

OP OpenVibers committed 11 Oct 2026 · f6879be67a · 1 file, +4 −4

Two more entries move on the same night:

- **C-14 closes.** Comment threads are addressed by access id only, services included.
  - Live#96 addresses threads by access id.
  - Community#63 hands services the access id.
  - Every stored numeric id in Blog (49), Wiki (10) and Deals (758) was backfilled to its access id, with backups. News and Reviews had none.
  - Community#64 refuses sequential ids. Live's unused `comment_thread_refs.thread_id` goes in a contract migration after 2026-10-18.
- **C-75 narrows.** Media#87 removed the per-app webhooks. Left: the dual write and the old routes. Live still produces `/api/thumbnails/…` and `/f/screenshots/…` URLs, so Live moves to `/o/<id>` object URLs first.

**Summary:** 43 closed, 1 kept, 5 open. Of the five, C-30/C-32 and C-40/C-41 wait on the owner, and C-75 is the remaining engineering item. C-30's final import now works on Live's PostgreSQL (Billing#47, dry-run on production data).

Changes

ddiff --git a/docs/compatibility-register.md b/docs/compatibility-register.md
iindex 979a395..2d6dc03 100644
---- a/docs/compatibility-register.md
++++ b/docs/compatibility-register.md
@@@ -27,9 +27,9 @@ Contracts has no deprecated contracts and no aliases (`OpenVibe.Contracts/compat
| Status as checked 2026-10-11 (second pass) | Count | Entries |
|---|---:|---|
--| Closed | 42 | C-01, C-02, C-03, C-04, C-05, C-06, C-10, C-11, C-12, C-13, C-15, C-20, C-21, C-22, C-23, C-24, C-42, C-50, C-51, C-52, C-53, C-54, C-55, C-56, C-57, C-58, C-59, C-60, C-61, C-70, C-71, C-72, C-73, C-74, C-76, C-77, C-80, C-81, C-82, C-83, C-84, C-85 |
++| Closed | 43 | C-01, C-02, C-03, C-04, C-05, C-06, C-10, C-11, C-12, C-13, C-14, C-15, C-20, C-21, C-22, C-23, C-24, C-42, C-50, C-51, C-52, C-53, C-54, C-55, C-56, C-57, C-58, C-59, C-60, C-61, C-70, C-71, C-72, C-73, C-74, C-76, C-77, C-80, C-81, C-82, C-83, C-84, C-85 |
| Kept (not a shim) | 1 | C-31 |
--| Open | 6 | C-14, C-30, C-32, C-40, C-41, C-75 |
++| Open | 5 | C-30, C-32, C-40, C-41 (all four wait on the owner), C-75 |
C-72 retains its earlier host-backup closure claim; source checkouts cannot verify deleted host backups. Number gaps have no entries in this register.
@@@ -52,7 +52,7 @@ C-72 retains its earlier host-backup closure claim; source checkouts cannot veri
| C-11 | **Closed (verified 2026-10-11):** Live `server/media-proxy/pastes.js:2-5` forwards to Community without a `PASTES_AUTHORITY` or Media branch. **Live `PASTES_AUTHORITY=community`** plus the Media paste router it replaces. Unset sends `/api/pastes` to Media. The value is read on every request. `PASTES_ON_COMMUNITY=1` 301s `/p/:slug` and `/pastes` to Community. `PASTES_AUTHORITY` and `OV_COMMUNITY_INTERNAL_URL` are missing from `.env.example`; `PASTES_ON_COMMUNITY=0` is at `.env.example:130-132`. | Live `server/pastes-client.js:5-18`, `server/media-proxy/pastes.js:250-319`, `server/index.js:597-612` | Live | Same as C-10. | 2026-11-06 | Unset `PASTES_AUTHORITY` (no restart needed). `PASTES_ON_COMMUNITY=0` needs a restart, and browsers may have cached the 301s. |
| C-12 | **Closed (verified 2026-10-11):** Media's paste write code is gone (no `server/pastes/`, no `PASTES_FROZEN_APPS`). `/p/:slug` and `/p/:slug/raw` 301 to Community permanently (`server/public/routes.js`, default `https://openvibe.community` built in), as the entry intended. **Media paste writes frozen**: `PASTES_FROZEN_APPS=live` makes every paste write answer 410 `pastes.moved`. `PASTES_MOVED_TO=https://openvibe.community` 301s `/p/:slug` and `/p/:slug/raw`. Screenshot bytes are still served by Media. | Media `server/pastes/routes.js:47-55`, `server/public/routes.js:446-494` | Media | *proposed*: the 410 path is unused for 30 days. The 301s stay as permanent redirects, because old links exist. Delete the paste write code, keep the redirect. | 2026-11-06 (write code); redirects kept | Remove both flags (ADR-011 §Rollback). |
| C-13 | **Closed (2026-10-11):** Tools#48: the gateway header, README and `.env.example` name Community as the paste backend, and the dead `LIVE_URL`/`config.liveUrl` is gone. The forwarding itself is the product path, not a shim. **Tools paste forwarding**: `/api/pastes/*` goes to Community (`OV_COMMUNITY_INTERNAL_URL`) with the visitor's `ov_token` and no service token. `pastes.openvibe.tools` redirects to Community. **There is no flag.** Commit `fd5d318` (2026-09-22) replaced the Live proxy, and only a revert rolls it back. | Tools `apps/gateway/server/index.js:183-207, 296-309` | Tools | *proposed*: keep the forwarding as the product path, and remove the stale comments that say Media backs pastes (`apps/gateway/server/index.js:8,12`, `apps/gateway/README.md:17-59`). `LIVE_URL` is dead apart from the startup banner (`apps/gateway/server/config.js:35-39`). Remove it. | 2026-10-09 | `git revert fd5d318` in Tools, then deploy. |
--| C-14 | **Open (2026-10-11):** Community still hands services numeric thread ids (`server/comments/service.js`). Every stored id is numeric: Blog 49, Wiki 10, Deals 758, Reviews 0 (`*_discussion_refs.thread_id`, all `text` columns); Live keeps `thread_id` and `access_id` in `comment_thread_refs`. Plan: Community hands services `cth_` ids, each caller backfills its rows from Community's map (Live switches to the access id it already stores), then numeric ids are refused. **Community numeric thread ids for services.** A `/^\d{1,15}$/` id resolves only for service tokens. `threadIdFor` hands services the sequential id and browsers the `cth_` access id. The documented service callers are Blog, Wiki, Deals, Reviews and Live. | Community `server/comments/service.js:63-69,104-110`, `server/comments/api.js:28-40`, `README.md:174-178`; tests `test/comments.test.js:271-340` | Community | **No removal condition in the repo.** The code treats it as the intended design. *Proposed*: every service caller stores and sends `cth_` ids; then refuse numeric ids. This needs a per-principal counter of numeric lookups, which does not exist yet. | 2026-12-18 | Numeric ids keep existing service rows working. |
++| C-14 | **Closed (2026-10-11):** threads are addressed by access id only, services included. Live#96 addresses threads by access id; Community#63 hands services the access id; every stored numeric id (Blog 49, Wiki 10, Deals 758; News and Reviews none) was backfilled to its access id with backups (`/var/backups/openvibe/c14-thread-ids-2026-10-11`); Community#64 refuses sequential ids. Live's now-unused `comment_thread_refs.thread_id` is dropped by a contract migration after 2026-10-18. **Community numeric thread ids for services.** A `/^\d{1,15}$/` id resolves only for service tokens. `threadIdFor` hands services the sequential id and browsers the `cth_` access id. The documented service callers are Blog, Wiki, Deals, Reviews and Live. | Community `server/comments/service.js:63-69,104-110`, `server/comments/api.js:28-40`, `README.md:174-178`; tests `test/comments.test.js:271-340` | Community | **No removal condition in the repo.** The code treats it as the intended design. *Proposed*: every service caller stores and sends `cth_` ids; then refuse numeric ids. This needs a per-principal counter of numeric lookups, which does not exist yet. | 2026-12-18 | Numeric ids keep existing service rows working. |
| C-15 | **Closed (2026-10-11):** Community#62: a user JWT without `subject_id` is no identity (every token has carried one since 2026-09-22, and access tokens live 7 days), `subjectForNetworkUser` is gone, and the staff censor route takes a slug only (Live's UI sends slugs). `legacy_id_map` and the import columns stay as provenance. **Community legacy id columns**: `pastes.legacy_media_id`, `legacy_user_id`, `paste_comments.legacy_media_id`, and `legacy_id_map`. The map also serves old JWTs that have no `subject_id`. The staff censor route also falls back to a numeric id. | Community `server/db.js:49-50,84,118-125`, `server/identity/network.js:90-103`, `server/pastes/service.js:593-596` | Community | The columns are import provenance and stay. *Proposed*: the JWT fallback goes once Network tokens older than their maximum lifetime cannot exist (every token carries `subject_id` since Wave 1, ADR-001). | 2026-10-23 (JWT fallback) | none needed |
## AI (Wave 13: `AI_SERVICE=remote` in production since 2026-09-23 ~15:40 UTC)
@@@ -119,7 +119,7 @@ estate now carries a service token with the one capability it performs (Contract
| C-72 | **Closed 2026-10-10:** the ADR-021 backups that still held IPs were deleted: `/opt/openvibe.live/data/backups/analytics-pre-adr021-2026-09-23.db` (1.7 GB), `/opt/openvibe.tools/backups/analytics-2026-09-23` (76 MB) and Network's `data/backups/network.db.pre-adr021-20260923T1634` (731 MB), each with its -wal/-shm. No other copy holds them: the oldest ovhost backup on the host is 2026-09-27, and the first off-site run (2026-09-23 18:47 UTC) came after the scrub. | host | Live, Tools, Network | *closed* | — | Pre-ADR-021 analytics are gone for good, as ADR-021 intends. |
| C-73 | **Closed (verified 2026-10-11):** Live `migrations/0002_live.sql:9-13` omits frozen `vods`, `clips` and `pastes` from its PostgreSQL schema; `server/db/database.js:2361-2365` has no reader. *Steps 1-2 DONE 2026-09-23: no Live code reads or writes the frozen tables (Live `9b80d2b`, `9b3be33`; the test refuses both, with an empty allow-list); deployed, 13 public endpoints keep their shape and counts. Step 3 (drop) not before 2026-10-23, procedure in Live `docs/vods-and-clips.md`.* **Live's legacy `vods`/`clips`/`pastes` tables**. They were frozen for the Media cutover, and the canonical copies are now in Media and Community. **There is no tripwire; only comments** (`server/db/database.js:3223-3224`). One write path remains: `PUT /api/admin/pastes/:id/nsfw` (`server/admin/routes.js:427-434`). Exported write helpers with no callers remain: `updatePasteAi`, `updateVodHealth`, `repairVodDuration`, `updatePaste`, `deletePaste`, `likePaste`. Live still **reads** them for live pages: `server/ai/chat-ai-routes.js:337`, `server/admin/routes.js:91-92`, `server/arena/arena-service.js:436`, `server/streaming/routes.js:1547`, and about 70 queries in `database.js`. These reads serve pre-cutover data. | Live (above); `docs/vods-and-clips.md:3-5` | Live | **No removal plan in the repo.** *Proposed*: (1) remove the nsfw write and the dead helpers, and add a tripwire like `assertLiveLedger`, by 2026-10-09; (2) move the four readers to Media or Community; (3) back up and drop the tables after 30 days with no reader. | 2026-11-06 | The tables are the only local copy of pre-Media rows. Keep the backup. |
| C-74 | **Closed (verified 2026-10-11):** Live `server/config.js:246-247` records removal of its pre-Media path settings; Media owns its own storage paths. **Pre-Media local paths** `VOD_PATH`, `CLIPS_PATH`, `COLD_STORAGE_PATH`, `THUMBNAILS_PATH` are still read by Live's config. | Live `server/config.js:251-257` | Live | *proposed*: no code reads the directories. **Unknown** whether any does. Grep for each config key. | 2026-11-06 | none needed |
--| C-75 | **Open (2026-10-11):** the webhook strand is being removed (Media's `server/webhooks.js` sender; no tenant has a `webhook_url`, and Live's receiver was retired on 2026-10-10). The dual write (old rows synced into `media_objects`) and the old routes remain. **Media dual write**: the old tables are written first, then synced into `media_objects`. A sync failure only logs. Old routes also stay: `/v/:id` basename fallback, `/api/thumbnails/:name` with app `live` hard-coded, `/f/screenshots/:name`, and `/tos` → `/terms`. Webhooks to Live are published alongside Events. | Media `docs/object-model.md:3-7,88-112`, `server/db/database.js:100-124`, `server/public/routes.js:176-190,346-384`, `server/events.js:1-18` | Media | *documented*: "The object layer is additive; old routes keep working throughout" (ADR-006 §Rollback). Webhooks stay "until every consumer reads events" (`server/events.js`). *Proposed*: Live consumes `media.*` events instead of `/internal/media-webhook`, then remove the webhooks. | 2026-12-18 | Old routes and tables. |
++| C-75 | **Open (2026-10-11):** Media's per-app webhooks are gone (Media#87: `server/webhooks.js` deleted; outcomes are OpenVibe.Events events only). Left: the dual write (old rows synced into `media_objects`) and the old routes. Live still produces those routes' URLs (`/api/thumbnails/<name>` through its thumbnails proxy, `/f/screenshots/<name>` from `media-client.screenshotUrl`), so Live moves to object URLs (`/o/<id>`) first; the routes were last requested on 2026-10-02. **Media dual write**: the old tables are written first, then synced into `media_objects`. A sync failure only logs. Old routes also stay: `/v/:id` basename fallback, `/api/thumbnails/:name` with app `live` hard-coded, `/f/screenshots/:name`, and `/tos` → `/terms`. Webhooks to Live are published alongside Events. | Media `docs/object-model.md:3-7,88-112`, `server/db/database.js:100-124`, `server/public/routes.js:176-190,346-384`, `server/events.js:1-18` | Media | *documented*: "The object layer is additive; old routes keep working throughout" (ADR-006 §Rollback). Webhooks stay "until every consumer reads events" (`server/events.js`). *Proposed*: Live consumes `media.*` events instead of `/internal/media-webhook`, then remove the webhooks. | 2026-12-18 | Old routes and tables. |
| C-76 | **Closed (verified 2026-10-11):** Live `deploy/scripts/deploy.sh:4-16` delegates to ovhost release layout and supports rollback. **Live legacy (in-place) deploy layout**, "current production" (Live `docs/deploy.md:31-32`). A rollback resets the checkout but not `node_modules`. `--rollback` is refused in this layout. | Live `deploy/scripts/deploy.sh:347,394-419`, `deploy/systemd/openvibe-live.service` | Live | **retired 2026-09-24 05:51 UTC**: `migrate-to-releases.sh` ran on the host (one restart, no streams live); Live runs `/opt/openvibe.live/current` → `releases/<time>-<sha>` and deploys from there; the inventory reads Live's release as root (`owner: root`, `runAs: ubuntu`); the Live restore drill passed after the switch. | 2026-10-09 | `git reset` to the old commit. |
| C-77 | **Closed (verified 2026-10-11):** No `ALLOW_P2P_FALLBACK` reader or P2P relay path remains under Live `server/`. **`ALLOW_P2P_FALLBACK`** (default `false`), an "emergency rollback" to legacy P2P relays, which can expose viewer IPs. | Live `server/config.js:87-93`, `SETUP.md:136` | Live | **No condition documented.** *Proposed*: remove the flag and the P2P relay path. | 2026-11-06 | Set the flag to `true` (not recommended). |