openvibers/openvibe.network Commits
Chat may manage its own OpenVibe.Events subscriptions: default grant chat events.subscription.manage on openvibe.events (seeded at boot like the others). Chat subscribes to live.release.deployed (the deploy card; register C-84, so the Live bridge's deployNotice can go after one clean deploy) and network.module.updated (its chat.preferences cache drops a changed record at once instead of within 60 s). Events checks only this capability for a service subscription; it has no per-topic read grants. test/module-events.test.js: the chat client gets a token for audience openvibe.events with that scope
Changes
@@@ -137,6 +137,9 @@ const DEFAULT_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', []],['live', 'chat.live_bridge.write', 'openvibe.chat', []],['live', 'chat.presence.read', 'openvibe.chat', []],['live', 'chat.message.send', 'openvibe.chat', []],@@@ -71,6 +71,9 @@ const valid = (e) => { const v = contracts.validate('events.event-envelope@1', eassert.deepStrictEqual(grant('chat', 'network.modules.write'), ['chat.preferences']);assert.deepStrictEqual(grant('live', 'network.modules.write'), ['chat.tts_defaults', 'live.profile'], 'the old default narrows at boot');assert.ok(grant('live', 'network.modules.read').includes('chat.preferences'), 'Live keeps reading it');++ // Chat manages its own Events subscriptions (live.release.deployed, network.module.updated).++ const chatEvents = await fetch(`${base}/oauth/token`, { method: 'POST', body: new URLSearchParams({ grant_type: 'client_credentials', client_id: 'chat', client_secret: 'chat-secret', audience: 'openvibe.events', scope: 'events.subscription.manage' }) }).then(r => r.json());++ assert.strictEqual(chatEvents.scope, 'events.subscription.manage', JSON.stringify(chatEvents));const chatTok = await svc('chat');const claims = JSON.parse(Buffer.from(chatTok.access_token.split('.')[1], 'base64url').toString());assert.deepStrictEqual(claims.ns, ['chat.preferences']);
@@ -137,6 +137,9 @@ const DEFAULT_GRANTS = [
@@ -137,6 +137,9 @@ const DEFAULT_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', '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', []],
['live', 'chat.live_bridge.write', 'openvibe.chat', []],
['live', 'chat.live_bridge.write', 'openvibe.chat', []],
['live', 'chat.presence.read', 'openvibe.chat', []],
['live', 'chat.presence.read', 'openvibe.chat', []],
['live', 'chat.message.send', 'openvibe.chat', []],
['live', 'chat.message.send', 'openvibe.chat', []],
@@ -71,6 +71,9 @@ const valid = (e) => { const v = contracts.validate('events.event-envelope@1', e
@@ -71,6 +71,9 @@ const valid = (e) => { const v = contracts.validate('events.event-envelope@1', e
assert.deepStrictEqual(grant('chat', 'network.modules.write'), ['chat.preferences']);
assert.deepStrictEqual(grant('chat', 'network.modules.write'), ['chat.preferences']);
assert.deepStrictEqual(grant('live', 'network.modules.write'), ['chat.tts_defaults', 'live.profile'], 'the old default narrows at boot');
assert.deepStrictEqual(grant('live', 'network.modules.write'), ['chat.tts_defaults', 'live.profile'], 'the old default narrows at boot');
assert.ok(grant('live', 'network.modules.read').includes('chat.preferences'), 'Live keeps reading it');
assert.ok(grant('live', 'network.modules.read').includes('chat.preferences'), 'Live keeps reading it');
+ // Chat manages its own Events subscriptions (live.release.deployed, network.module.updated).
+ const chatEvents = await fetch(`${base}/oauth/token`, { method: 'POST', body: new URLSearchParams({ grant_type: 'client_credentials', client_id: 'chat', client_secret: 'chat-secret', audience: 'openvibe.events', scope: 'events.subscription.manage' }) }).then(r => r.json());
+ assert.strictEqual(chatEvents.scope, 'events.subscription.manage', JSON.stringify(chatEvents));
const chatTok = await svc('chat');
const chatTok = await svc('chat');
const claims = JSON.parse(Buffer.from(chatTok.access_token.split('.')[1], 'base64url').toString());
const claims = JSON.parse(Buffer.from(chatTok.access_token.split('.')[1], 'base64url').toString());
assert.deepStrictEqual(claims.ns, ['chat.preferences']);
assert.deepStrictEqual(claims.ns, ['chat.preferences']);