openvibers/openvibe.network Commits
Revoke Chat's live.chat_mirror.write: the read mirror to Live is retired (#64)
Changes
@@@ -236,11 +236,10 @@ const DEFAULT_GRANTS = [['live', 'community.comment.write', 'openvibe.community', []],['live', 'community.comment.moderate', 'openvibe.community', []],['live', 'community.pulse.write', 'openvibe.community', []],-- // Wave 6: OpenVibe.Chat reads Live's chat context, asks Live for effects and mirrors chat rows-- // back; Live bridges its remaining chat writers to Chat and reads presence.++ // Wave 6: OpenVibe.Chat reads Live's chat context and asks Live for effects; Live bridges its remaining++ // chat writers to Chat and reads presence. (The read mirror back to Live was retired 2026-10-05: see REVOKED_GRANTS.)['chat', 'live.chat_context.read', 'openvibe.live', []],['chat', 'live.chat_effects.write', 'openvibe.live', []],-- ['chat', 'live.chat_mirror.write', 'openvibe.live', []],// Chat consumes live.release.deployed (the deploy card, register C-84) and network.module.updated// (its chat.preferences cache) through its own Events subscriptions, created at Chat's boot.['chat', 'events.subscription.manage', 'openvibe.events', []],@@@ -285,7 +284,11 @@ const DEFAULT_GRANTS = [];// Grants withdrawn by decision; applied at every boot so an old default can't come back.--const REVOKED_GRANTS = [['live', 'network.coins.transfer', SELF_AUDIENCE]];++const REVOKED_GRANTS = [++ ['live', 'network.coins.transfer', SELF_AUDIENCE],++ // The Live read mirror is retired (2026-10-05): Chat #25 removed the sender, Live the receiver.++ ['chat', 'live.chat_mirror.write', 'openvibe.live'],++];// Default grants whose namespaces changed: a row still exactly as the old default seeded it is moved to// the new list at boot, in this order (a row someone edited is left alone). Live's write grant lostnnew file mode 100644@@@ -0,0 +1,26 @@++'use strict';++// Retired grants stay retired: the Live read mirror was removed on both sides (Chat #25, Live), so Chat's++// live.chat_mirror.write grant is revoked at every boot and no default hands it out again.++const assert = require('assert');++const { getDb } = require('../server/db/database');++++(async () => {++const log = console.log; console.log = () => {};++const db = await getDb();++console.log = log;++const principals = require('../server/identity/principals');++await db.prepare("INSERT INTO oauth_clients (client_id, client_secret, name, redirect_uris, is_first_party) VALUES ('chat', 'x', 'chat', '[]', 1) ON CONFLICT DO NOTHING").run();++const grant = async (cap) => (await principals.grantsFor(db, 'chat', 'openvibe.live')).find((g) => g.capability === cap);++++// A database as an older release left it: Chat still holds the mirror grant.++await principals.ensureSchema(db);++await db.prepare("INSERT INTO principal_grants (client_id, capability, audience, namespaces, granted_by) VALUES ('chat', 'live.chat_mirror.write', 'openvibe.live', '[]', 'default') ON CONFLICT (client_id, capability, audience) DO UPDATE SET revoked_at = NULL").run();++assert.ok(await grant('live.chat_mirror.write'), 'the old mirror grant is there before the boot');++++await principals.ensureSchema(db); // the next boot++assert.strictEqual(await grant('live.chat_mirror.write'), undefined, 'the mirror grant is revoked at boot');++assert.ok(await grant('live.chat_effects.write'), 'Chat keeps its effects grant');++assert.ok(!principals.DEFAULT_GRANTS.some(([c, cap]) => c === 'chat' && cap === 'live.chat_mirror.write'), 'no default hands it out');++++console.log('retired grants: all checks passed');++})().catch(err => { console.error(err); process.exit(1); });
@@ -236,11 +236,10 @@ const DEFAULT_GRANTS = [
@@ -236,11 +236,10 @@ const DEFAULT_GRANTS = [
['live', 'community.comment.write', 'openvibe.community', []],
['live', 'community.comment.write', 'openvibe.community', []],
['live', 'community.comment.moderate', 'openvibe.community', []],
['live', 'community.comment.moderate', 'openvibe.community', []],
['live', 'community.pulse.write', 'openvibe.community', []],
['live', 'community.pulse.write', 'openvibe.community', []],
- // Wave 6: OpenVibe.Chat reads Live's chat context, asks Live for effects and mirrors chat rows
- // back; Live bridges its remaining chat writers to Chat and reads presence.
+ // Wave 6: OpenVibe.Chat reads Live's chat context and asks Live for effects; Live bridges its remaining
+ // chat writers to Chat and reads presence. (The read mirror back to Live was retired 2026-10-05: see REVOKED_GRANTS.)
['chat', 'live.chat_context.read', 'openvibe.live', []],
['chat', 'live.chat_context.read', 'openvibe.live', []],
['chat', 'live.chat_effects.write', 'openvibe.live', []],
['chat', 'live.chat_effects.write', 'openvibe.live', []],
- ['chat', 'live.chat_mirror.write', 'openvibe.live', []],
// Chat consumes live.release.deployed (the deploy card, register C-84) and network.module.updated
// Chat consumes live.release.deployed (the deploy card, register C-84) and network.module.updated
// (its chat.preferences cache) through its own Events subscriptions, created at Chat's boot.
// (its chat.preferences cache) through its own Events subscriptions, created at Chat's boot.
['chat', 'events.subscription.manage', 'openvibe.events', []],
['chat', 'events.subscription.manage', 'openvibe.events', []],
@@ -285,7 +284,11 @@ const DEFAULT_GRANTS = [
@@ -285,7 +284,11 @@ const DEFAULT_GRANTS = [
];
];
// Grants withdrawn by decision; applied at every boot so an old default can't come back.
// Grants withdrawn by decision; applied at every boot so an old default can't come back.
-const REVOKED_GRANTS = [['live', 'network.coins.transfer', SELF_AUDIENCE]];
+const REVOKED_GRANTS = [
+ ['live', 'network.coins.transfer', SELF_AUDIENCE],
+ // The Live read mirror is retired (2026-10-05): Chat #25 removed the sender, Live the receiver.
+ ['chat', 'live.chat_mirror.write', 'openvibe.live'],
+];
// Default grants whose namespaces changed: a row still exactly as the old default seeded it is moved to
// Default grants whose namespaces changed: a row still exactly as the old default seeded it is moved to
// the new list at boot, in this order (a row someone edited is left alone). Live's write grant lost
// the new list at boot, in this order (a row someone edited is left alone). Live's write grant lost
new file mode 100644
new file mode 100644
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
+'use strict';
+// Retired grants stay retired: the Live read mirror was removed on both sides (Chat #25, Live), so Chat's
+// live.chat_mirror.write grant is revoked at every boot and no default hands it out again.
+const assert = require('assert');
+const { getDb } = require('../server/db/database');
+
+(async () => {
+const log = console.log; console.log = () => {};
+const db = await getDb();
+console.log = log;
+const principals = require('../server/identity/principals');
+await db.prepare("INSERT INTO oauth_clients (client_id, client_secret, name, redirect_uris, is_first_party) VALUES ('chat', 'x', 'chat', '[]', 1) ON CONFLICT DO NOTHING").run();
+const grant = async (cap) => (await principals.grantsFor(db, 'chat', 'openvibe.live')).find((g) => g.capability === cap);
+
+// A database as an older release left it: Chat still holds the mirror grant.
+await principals.ensureSchema(db);
+await db.prepare("INSERT INTO principal_grants (client_id, capability, audience, namespaces, granted_by) VALUES ('chat', 'live.chat_mirror.write', 'openvibe.live', '[]', 'default') ON CONFLICT (client_id, capability, audience) DO UPDATE SET revoked_at = NULL").run();
+assert.ok(await grant('live.chat_mirror.write'), 'the old mirror grant is there before the boot');
+
+await principals.ensureSchema(db); // the next boot
+assert.strictEqual(await grant('live.chat_mirror.write'), undefined, 'the mirror grant is revoked at boot');
+assert.ok(await grant('live.chat_effects.write'), 'Chat keeps its effects grant');
+assert.ok(!principals.DEFAULT_GRANTS.some(([c, cap]) => c === 'chat' && cap === 'live.chat_mirror.write'), 'no default hands it out');
+
+console.log('retired grants: all checks passed');
+})().catch(err => { console.error(err); process.exit(1); });