openvibers/openvibe.live Commits

Frozen legacy tables: drop the ten uncalled write helpers for vods/clips/pastes/paste_likes and add test/frozen-tables.test.js, which fails if server code writes them again (Wave 22 register C-73 step 1)

OP OpenVibers committed 23 Sept 2026 · f936ab3c45 · 2 files, +42 −101


Changes

ddiff --git a/server/db/database.js b/server/db/database.js
iindex 60c20bff..1563e18d 100644
---- a/server/db/database.js
++++ b/server/db/database.js
@@@ -3204,10 +3204,6 @@ function getPastesNeedingAnalysis(limit = 5) {
return all("SELECT * FROM pastes WHERE ai_summary IS NULL AND type IN ('paste','screenshot') ORDER BY created_at DESC LIMIT ?", [limit]);
}
// deleteAiMomentTextPastes() removed — the media subsystem (vods/clips/pastes writes) moved to OpenVibe.Media.
--function updatePasteAi(pasteId, { ai_summary = null, ai_tags = null }) {
-- return run('UPDATE pastes SET ai_summary = ?, ai_tags = ?, ai_analyzed_at = CURRENT_TIMESTAMP WHERE id = ?',
-- [ai_summary, ai_tags ? (typeof ai_tags === 'string' ? ai_tags : JSON.stringify(ai_tags)) : null, pasteId]);
--}
// ── One-time cleanup: earlier builds stored raw (often malformed) model JSON like
// `{"description":"…","tags":[…]}` directly into text columns. Extract just the
// human description so cards/overviews stop showing JSON. Idempotent; cheap to re-run.
@@@ -5560,52 +5556,10 @@ function setSubscriptionStatus(id, status, fields = {}) {
[status, status === 'active' ? 1 : 0, cape, cpe, id]);
return get('SELECT * FROM subscriptions WHERE id = ?', [id]);
}
--
// ── VOD helpers ──────────────────────────────────────────────
// createVod() removed — the media subsystem (vods/clips/pastes writes) moved to OpenVibe.Media.
--
--function updateVodHealth(vodId, { status, score, issues = [], probeDuration, probeFormat, quarantine = false, keepPublic = false }) {
-- const updates = [];
-- const params = [];
-- if (status) {
-- updates.push('health_status = ?');
-- params.push(status);
-- }
-- if (typeof score === 'number') {
-- updates.push('health_score = ?');
-- params.push(score);
-- }
-- if (issues) {
-- updates.push('health_issues_json = ?');
-- params.push(JSON.stringify(issues));
-- }
-- if (typeof probeDuration === 'number') {
-- updates.push('probe_duration_seconds = ?');
-- params.push(probeDuration);
-- }
-- if (probeFormat !== undefined) {
-- updates.push('probe_format_json = ?');
-- params.push(JSON.stringify(probeFormat || {}));
-- }
-- if (quarantine) {
-- updates.push('quarantined_at = datetime(\'now\')');
-- if (!keepPublic) {
-- updates.push('is_public = 0');
-- }
-- }
-- updates.push('last_health_scan_at = datetime(\'now\')');
-- params.push(vodId);
-- if (!updates.length) return null;
-- return run(`UPDATE vods SET ${updates.join(', ')} WHERE id = ?`, params);
--}
--
--function repairVodDuration(vodId, duration, fileSize) {
-- return run(
-- `UPDATE vods SET duration_seconds = ?, file_size = ?, probe_duration_seconds = ?, last_health_scan_at = datetime('now') WHERE id = ?`,
-- [duration, fileSize, duration, vodId]
-- );
--}
++// The legacy vods/clips/pastes tables are read-only here: test/frozen-tables.test.js fails on a new write.
function getVodHealthById(id) {
return get(`SELECT * FROM vods WHERE id = ?`, [id]);
@@@ -7290,29 +7244,6 @@ function listPastes({ visibility = 'public', type, search, limit = 30, offset =
return { pastes, total };
}
--function incrementPasteViews(slug) {
-- return run('UPDATE pastes SET views = views + 1 WHERE slug = ?', [slug]);
--}
--
--function updatePaste(slug, fields) {
-- const updates = [];
-- const params = [];
-- for (const [key, val] of Object.entries(fields)) {
-- if (['title', 'content', 'language', 'visibility', 'pinned', 'metadata'].includes(key)) {
-- updates.push(`${key} = ?`);
-- params.push(val);
-- }
-- }
-- if (updates.length === 0) return;
-- updates.push('updated_at = CURRENT_TIMESTAMP');
-- params.push(slug);
-- return run(`UPDATE pastes SET ${updates.join(', ')} WHERE slug = ?`, params);
--}
--
--function deletePaste(slug) {
-- return run('DELETE FROM pastes WHERE slug = ?', [slug]);
--}
--
function getUserPastes(userId, limit = 50) {
return all(`
SELECT id, slug, type, title, language, visibility, burn_after_read, pinned, views, copies, likes, created_at
@@@ -7320,27 +7251,11 @@ function getUserPastes(userId, limit = 50) {
`, [userId, limit]);
}
--function likePaste(pasteId, userId) {
-- run('INSERT OR IGNORE INTO paste_likes (paste_id, user_id) VALUES (?, ?)', [pasteId, userId]);
-- run('UPDATE pastes SET likes = (SELECT COUNT(*) FROM paste_likes WHERE paste_id = ?) WHERE id = ?', [pasteId, pasteId]);
-- return get('SELECT likes FROM pastes WHERE id = ?', [pasteId]);
--}
--
--function unlikePaste(pasteId, userId) {
-- run('DELETE FROM paste_likes WHERE paste_id = ? AND user_id = ?', [pasteId, userId]);
-- run('UPDATE pastes SET likes = (SELECT COUNT(*) FROM paste_likes WHERE paste_id = ?) WHERE id = ?', [pasteId, pasteId]);
-- return get('SELECT likes FROM pastes WHERE id = ?', [pasteId]);
--}
--
function hasUserLikedPaste(pasteId, userId) {
const row = get('SELECT 1 FROM paste_likes WHERE paste_id = ? AND user_id = ?', [pasteId, userId]);
return !!row;
}
--function incrementPasteCopies(slug) {
-- return run('UPDATE pastes SET copies = copies + 1 WHERE slug = ?', [slug]);
--}
--
function countUserPastesToday(userId, ip) {
if (userId) {
return get("SELECT COUNT(*) as c FROM pastes WHERE user_id = ? AND created_at > datetime('now', '-1 day')", [userId])?.c || 0;
@@@ -7380,16 +7295,6 @@ function getLastPasteTime(userId, ip) {
return row ? new Date(row.created_at + (row.created_at.includes('Z') ? '' : 'Z')).getTime() : 0;
}
--function deleteAllForks() {
-- const forks = all('SELECT id, screenshot_path FROM pastes WHERE forked_from IS NOT NULL');
-- // Unlink the fork screenshots so they don't leak on disk.
-- for (const f of forks) {
-- if (f.screenshot_path) { try { fs.unlinkSync(f.screenshot_path); } catch { /* ignore */ } }
-- }
-- run('DELETE FROM pastes WHERE forked_from IS NOT NULL');
-- return forks.length;
--}
--
function getPasteStats() {
const total = get('SELECT COUNT(*) as c FROM pastes')?.c || 0;
const textPastes = get("SELECT COUNT(*) as c FROM pastes WHERE type = 'paste'")?.c || 0;
@@@ -8437,7 +8342,7 @@ module.exports = {
setVodAiOverview, setClipAiOverview, setVodTranscript, setClipTranscript, getStreamMemoriesInRange,
getVodsNeedingOverview, getClipsNeedingOverview, getVodsNeedingTimeline, getVodsNeedingTranscript, getClipsNeedingTranscript, getPastesNeedingAnalysis,
setVodTranscriptStatus, setClipTranscriptStatus, bumpVodTranscriptAttempt, bumpClipTranscriptAttempt,
-- updatePasteAi, cleanupMalformedAiText, recordAiUsage, getAiCostToday, getAiCostTodayForUser, getAiUsageSummary,
++ cleanupMalformedAiText, recordAiUsage, getAiCostToday, getAiCostTodayForUser, getAiUsageSummary,
getStreamMemoriesByUser, countStreamMemoriesByUser, getAiMomentCandidates, getStreamTranscriptSegments, getUserPastesForAi,
addTimelineEvents, getTimeline, getTimelineText, getTimelineCoverage, linkTimelineToVod, getTimelineByVod, getTimelineVodId,
getVodsForMomentRanking, getClipStartTimesForStream, getChatSpikeOffsets,
@@@ -8508,7 +8413,7 @@ module.exports = {
renormalizePendingMediaRequestPositions,
// VODs
getVodById, getVodsByUser, countVodsByUser, getPublicVods, countPublicVods, listVodStreamers, getActiveVodByStream,
-- updateVodHealth, repairVodDuration, getVodHealthById, getVodScanCandidates,
++ getVodHealthById, getVodScanCandidates,
getVodsNeedingHealthScan, getQuarantinedVodsForCleanup,
// Clips
getClipById, getClipsByUser, countClipsByUser, getPublicClips, countPublicClips, listClipStreamers, getClipsByStream, getClipsOfUserStreams,
@@@ -8558,9 +8463,8 @@ module.exports = {
getChannelModerationSettings, upsertChannelModerationSettings,
// Pastes
getPasteBySlug, getPasteById, listPastes,
-- incrementPasteViews, updatePaste, deletePaste, getUserPastes, getUserPastesForChannel, countUserPastesForChannel,
-- likePaste, unlikePaste, hasUserLikedPaste, incrementPasteCopies,
-- countUserPastesToday, getLastPasteTime, deleteAllForks, getPasteStats, getUserTotalGameLevel,
++ getUserPastes, getUserPastesForChannel, countUserPastesForChannel,
++ hasUserLikedPaste, countUserPastesToday, getLastPasteTime, getPasteStats, getUserTotalGameLevel,
// Paste Comments
createPasteComment, getPasteComments, getPasteCommentReplies,
getPasteCommentById, getPasteCommentCount, deletePasteComment,
ddiff --git a/test/frozen-tables.test.js b/test/frozen-tables.test.js
nnew file mode 100644
iindex 00000000..e8aa964c
---- /dev/null
++++ b/test/frozen-tables.test.js
@@@ -0,0 +1,37 @@
++'use strict';
++
++// Live's legacy vods/clips/pastes tables are frozen: Media and Community own that data now
++// (AGENTS.md, Wave 22 register C-73). Live may read them for pre-cutover pages, but no server code
++// may write them. The only writes allowed are the two guarded one-time visibility backfills that
++// run when the column is first added.
++
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++
++const ROOT = path.join(__dirname, '..');
++const WRITE = /\b(INSERT(?:\s+OR\s+\w+)?\s+INTO|UPDATE|DELETE\s+FROM|REPLACE\s+INTO)\s+(vods|clips|pastes|paste_likes)\b/i;
++const ALLOWED = [
++ "UPDATE vods SET visibility = CASE WHEN is_public = 1 THEN 'public' ELSE 'private' END",
++ "UPDATE clips SET visibility = CASE WHEN is_public = 1 THEN 'public' ELSE 'unlisted' END",
++];
++
++function walk(dir, out = []) {
++ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
++ const p = path.join(dir, e.name);
++ if (e.isDirectory()) walk(p, out);
++ else if (e.name.endsWith('.js')) out.push(p);
++ }
++ return out;
++}
++
++const offenders = [];
++for (const file of [...walk(path.join(ROOT, 'server')), ...walk(path.join(ROOT, 'scripts'))]) {
++ fs.readFileSync(file, 'utf8').split('\n').forEach((line, i) => {
++ if (!WRITE.test(line) || /^\s*(\/\/|\*)/.test(line)) return;
++ if (ALLOWED.some((a) => line.includes(a))) return;
++ offenders.push(`${path.relative(ROOT, file)}:${i + 1}: ${line.trim().slice(0, 120)}`);
++ });
++}
++assert.deepStrictEqual(offenders, [], `writes to frozen tables:\n${offenders.join('\n')}`);
++console.log('frozen tables: all checks passed');