openvibers/openvibe.network Commits

Moderation audit: media.moderation.action too (Media's staff holds), in the consumer, the subscription topics and the admin filter; contracts 0.54.0

OP OpenVibers committed 26 Sept 2026 · ce7596b1cd · 6 files, +10 −9


Changes

ddiff --git a/package-lock.json b/package-lock.json
iindex 4e0a36c7..83afe7be 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -20,7 +20,7 @@
"helmet": "^8.1.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.53.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.54.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.11.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.13.0",
"uuid": "^11.1.0",
@@@ -1465,9 +1465,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.53.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.53.0",
-- "integrity": "sha512-U+/QMB9dYHF+1ZS7ZZf+aYDokI8nuZmMZh1qOvisT7iB+QQ4uxr03E3wHm1/qOr+IHlt+7BzFaOPVw6K6cOSxA==",
++ "version": "0.54.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.54.0",
++ "integrity": "sha512-jOYCWRtK6LWvsc1u1XL85GzH93EMm4qXjAHOnZp9hP3d8kxg0pQc25yuHWLhh3tYR5e4BH2pz0opKrkpwBtu5w==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 104a881a..f60d7363 100644
---- a/package.json
++++ b/package.json
@@@ -23,7 +23,7 @@
"helmet": "^8.1.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.53.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.54.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.11.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.13.0",
"uuid": "^11.1.0",
ddiff --git a/public/admin.html b/public/admin.html
iindex fad84e17..72186a00 100644
---- a/public/admin.html
++++ b/public/admin.html
@@@ -393,7 +393,7 @@ body{min-height:100%;color:var(--text);font-family:'Inter',-apple-system,BlinkMa
<p class="muted" style="margin:0 0 10px">Staff actions reported by Chat, Live, Community, Tips, Billing and the other services (Tools, Games, Wiki, Blog, News, Reviews, Deals, Coupons, Trade, Codes). Each service enforces its own moderation; this is the record.</p>
<form id="modlog-filters" style="display:flex;flex-wrap:wrap;gap:8px;align-items:end;margin-bottom:10px" onsubmit="event.preventDefault(); loadModLog(true)">
<label class="muted" style="font-size:12px;display:flex;flex-direction:column;gap:2px">Service
-- <select id="modlog-service" onchange="loadModLog(true)"><option value="">All</option><option value="chat">Chat</option><option value="live">Live</option><option value="community">Community</option><option value="tips">Tips</option><option value="billing">Billing</option><option value="blog">Blog</option><option value="codes">Codes</option><option value="coupons">Coupons</option><option value="deals">Deals</option><option value="games">Games</option><option value="news">News</option><option value="reviews">Reviews</option><option value="tools">Tools</option><option value="trade">Trade</option><option value="wiki">Wiki</option></select></label>
++ <select id="modlog-service" onchange="loadModLog(true)"><option value="">All</option><option value="chat">Chat</option><option value="live">Live</option><option value="community">Community</option><option value="tips">Tips</option><option value="billing">Billing</option><option value="blog">Blog</option><option value="codes">Codes</option><option value="coupons">Coupons</option><option value="deals">Deals</option><option value="games">Games</option><option value="media">Media</option><option value="news">News</option><option value="reviews">Reviews</option><option value="tools">Tools</option><option value="trade">Trade</option><option value="wiki">Wiki</option></select></label>
<label class="muted" style="font-size:12px;display:flex;flex-direction:column;gap:2px">Action<input id="modlog-action" placeholder="e.g. site_ban" maxlength="64" style="width:130px"></label>
<label class="muted" style="font-size:12px;display:flex;flex-direction:column;gap:2px">By (subject)<input id="modlog-actor" placeholder="usr_…" maxlength="64" style="width:150px"></label>
<label class="muted" style="font-size:12px;display:flex;flex-direction:column;gap:2px">Target<input id="modlog-target" placeholder="subject or id" maxlength="200" style="width:150px"></label>
ddiff --git a/server/admin/moderation-audit.js b/server/admin/moderation-audit.js
iindex 9a280091..30ff7805 100644
---- a/server/admin/moderation-audit.js
++++ b/server/admin/moderation-audit.js
@@@ -24,7 +24,7 @@ const { staff } = require('openvibe-contracts');
const { staffClaims } = require('../auth/staff-claims');
// Producers whose event is common.moderation-action@1 (action, target { type, id, owner_subject }, actor_subject, reason, details).
--const COMMON_SERVICES = Object.freeze(['tools', 'games', 'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes']);
++const COMMON_SERVICES = Object.freeze(['media', 'tools', 'games', 'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes']);
const TOPICS = Object.freeze(['chat.moderation.action', 'live.moderation.action', 'community.moderation.action', 'tips.interaction.moderated', 'billing.staff.action',
...COMMON_SERVICES.map((svc) => `${svc}.moderation.action`)]);
const str = (v, n) => (v == null || v === '' ? null : String(v).replace(/[\u0000-\u001f\u007f]/g, ' ').slice(0, n));
@@@ -79,6 +79,7 @@ function rowOf(event) {
target_type: 'interaction', target_id: str(p.interaction_id, 64), target_subject: str(c.id, 64), scope: str(`by:${p.by || 'unknown'}`, 64), reason: null,
details: json({ moderation_state: p.moderation_state, cancelled_effects: p.cancelled_effects }) };
}
++ case 'media.moderation.action':
case 'tools.moderation.action':
case 'games.moderation.action':
case 'wiki.moderation.action':
ddiff --git a/test/events-consumer.test.js b/test/events-consumer.test.js
iindex bee66ab2..243df67a 100644
---- a/test/events-consumer.test.js
++++ b/test/events-consumer.test.js
@@@ -59,7 +59,7 @@ const rows = (userId) => db.prepare('SELECT * FROM notifications WHERE user_id =
(async () => {
// The subscriptions this consumer is meant for, and nothing else.
assert.deepStrictEqual(TOPICS, ['deals.watch.matched', 'trade.alert.triggered', 'live.stream.started', 'chat.moderation.action', 'live.moderation.action', 'community.moderation.action', 'tips.interaction.moderated', 'billing.staff.action',
-- ...['tools', 'games', 'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes'].map((svc) => `${svc}.moderation.action`)]);
++ ...['media', 'tools', 'games', 'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes'].map((svc) => `${svc}.moderation.action`)]);
assert.deepStrictEqual(topicsFrom([]), TOPICS, 'scripts/subscribe-events.js subscribes every topic');
assert.deepStrictEqual(topicsFrom(['--topic', 'live.stream.started']), ['live.stream.started']);
assert.throws(() => topicsFrom(['--topic', 'live.*']));
ddiff --git a/test/moderation-audit.test.js b/test/moderation-audit.test.js
iindex 396ba438..1af97d4b 100644
---- a/test/moderation-audit.test.js
++++ b/test/moderation-audit.test.js
@@@ -62,7 +62,7 @@ const ev = (type, payload, actor = { type: 'user', id: MOD }) => ({ event_id: id
// The ten services on common.moderation-action@1 (Contracts 0.53.0): subscribed, one row each, the service from the prefix.
const contracts = require('openvibe-contracts');
const { TOPICS } = require('../server/notifications/events-consumer');
-- const COMMON = ['tools', 'games', 'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes'];
++ const COMMON = ['media', 'tools', 'games', 'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes'];
for (const svc of COMMON) {
const type = `${svc}.moderation.action`;
assert.ok(TOPICS.includes(type), `${type} is one of the consumer's subscriptions`);