openvibers/openvibe.network Commits
Grants for plan T3 and T4, on Contracts 0.80.0: Live reads a channel's moderation settings, moderators and emote count from Chat (chat.moderation.read); Chat uploads and deletes emote images in Media's chat namespace and runs the chat-AI summaries with its own token (ai.run.create/read, chat.*); Live reads, lists, uploads and deletes its objects in Media's live namespace and OpenRe uploads there, so both drop Media API keys. principals.test.js pins Live's Media scope. npm test green.
Changes
@@@ -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.79.0",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.80.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.12.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2","uuid": "^11.1.0",@@@ -1465,9 +1465,9 @@}},"node_modules/openvibe-contracts": {-- "version": "0.79.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",-- "integrity": "sha512-FY5GLbiOq0kDw5lUPPzX6h3ATbzvsr/mX5DUCF4GRfn6vGMP0p89rZZDhgtVDaS+yCBCYMZ8zFaZxuHEkEVwVg==",++ "version": "0.80.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.80.0",++ "integrity": "sha512-7RCNFKxFRey3PquBwyQkSu8Bu2q2Ek0yb248SJWaymcg/g9PrlStFVUDTLMgh8i7BZSaZSngj0nojpwYTLGYDQ==","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -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.79.0",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.80.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.12.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2","uuid": "^11.1.0",@@@ -49,6 +49,17 @@ const DEFAULT_GRANTS = [['tools', 'media.object.upload', 'openvibe.media', ['tools', 'tools.*']],['tools', 'media.object.read', 'openvibe.media', ['tools', 'tools.*']],['games', 'media.object.upload', 'openvibe.media', ['games']],++ // Plan T4 (Media cleanup): Live and OpenRe reach Media with their own tokens instead of API keys. Live keeps++ // its objects under the live namespace (VOD/clip/thumbnail uploads, reads, lists, deletes); OpenRe uploads the++ // recordings and thumbnails it produces there too.++ ...['media.object.read', 'media.object.list', 'media.object.upload', 'media.object.delete'].map(cap => ['live', cap, 'openvibe.media', ['live']]),++ ['openre', 'media.object.upload', 'openvibe.media', ['live']],++ // Plan T3: Chat owns the six chat tables. Emote images go to Media under the chat namespace, and++ // the chat-AI summaries run in Chat with its own token.++ ['chat', 'media.object.upload', 'openvibe.media', ['chat']],++ ['chat', 'media.object.delete', 'openvibe.media', ['chat']],++ ['chat', 'ai.run.create', 'openvibe.ai', ['chat.*']],++ ['chat', 'ai.run.read', 'openvibe.ai', ['chat.*']],['games', 'identity.subject.resolve', SELF_AUDIENCE, []],// Games subscribes to network.user.token_valid_after (sign-out everywhere closes game sessions).['games', 'events.subscription.manage', 'openvibe.events', []],@@@ -214,6 +225,8 @@ const DEFAULT_GRANTS = [['community', 'network.blocks.read', SELF_AUDIENCE, []],['live', 'chat.live_bridge.write', 'openvibe.chat', []],['live', 'chat.presence.read', 'openvibe.chat', []],++ // Plan T3: Live reads a channel's moderation settings, its moderators and emote count from Chat.++ ['live', 'chat.moderation.read', 'openvibe.chat', []],['live', 'chat.message.send', 'openvibe.chat', []],// Wave 8: Live as a Billing client (used only with BILLING_AUTHORITY=billing). Never cashout.manage// or ledger.admin: approving payouts is a separately controlled capability (ADR-012 rule 10).@@@ -93,6 +93,9 @@ const server = http.createServer(app);assert.strictEqual(t.body.scope, 'identity.subject.resolve network.account.deletion.confirm network.account.export.contribute', 'Media resolves object owners to subjects and takes part in account export and deletion (ADR-033), nothing else here');const mediaResolve = t.body.access_token;t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.media' });++ assert.strictEqual(t.status, 200, JSON.stringify(t.body));++ assert.deepStrictEqual(t.body.scope.split(' ').sort(), ['media.object.delete', 'media.object.list', 'media.object.read', 'media.object.upload'], 'plan T4: Live reaches Media with its own token, nothing more');++ t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.games' });assert.strictEqual(t.status, 400, 'no grants for that audience');// ── Guarded routes ──
@@ -20,7 +20,7 @@
@@ -20,7 +20,7 @@
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
"multer": "^1.4.5-lts.1",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.80.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.12.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.12.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
"uuid": "^11.1.0",
"uuid": "^11.1.0",
@@ -1465,9 +1465,9 @@
@@ -1465,9 +1465,9 @@
}
}
},
},
"node_modules/openvibe-contracts": {
"node_modules/openvibe-contracts": {
- "version": "0.79.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
- "integrity": "sha512-FY5GLbiOq0kDw5lUPPzX6h3ATbzvsr/mX5DUCF4GRfn6vGMP0p89rZZDhgtVDaS+yCBCYMZ8zFaZxuHEkEVwVg==",
+ "version": "0.80.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.80.0",
+ "integrity": "sha512-7RCNFKxFRey3PquBwyQkSu8Bu2q2Ek0yb248SJWaymcg/g9PrlStFVUDTLMgh8i7BZSaZSngj0nojpwYTLGYDQ==",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -23,7 +23,7 @@
@@ -23,7 +23,7 @@
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
"multer": "^1.4.5-lts.1",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.80.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.12.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.12.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
"uuid": "^11.1.0",
"uuid": "^11.1.0",
@@ -49,6 +49,17 @@ const DEFAULT_GRANTS = [
@@ -49,6 +49,17 @@ const DEFAULT_GRANTS = [
['tools', 'media.object.upload', 'openvibe.media', ['tools', 'tools.*']],
['tools', 'media.object.upload', 'openvibe.media', ['tools', 'tools.*']],
['tools', 'media.object.read', 'openvibe.media', ['tools', 'tools.*']],
['tools', 'media.object.read', 'openvibe.media', ['tools', 'tools.*']],
['games', 'media.object.upload', 'openvibe.media', ['games']],
['games', 'media.object.upload', 'openvibe.media', ['games']],
+ // Plan T4 (Media cleanup): Live and OpenRe reach Media with their own tokens instead of API keys. Live keeps
+ // its objects under the live namespace (VOD/clip/thumbnail uploads, reads, lists, deletes); OpenRe uploads the
+ // recordings and thumbnails it produces there too.
+ ...['media.object.read', 'media.object.list', 'media.object.upload', 'media.object.delete'].map(cap => ['live', cap, 'openvibe.media', ['live']]),
+ ['openre', 'media.object.upload', 'openvibe.media', ['live']],
+ // Plan T3: Chat owns the six chat tables. Emote images go to Media under the chat namespace, and
+ // the chat-AI summaries run in Chat with its own token.
+ ['chat', 'media.object.upload', 'openvibe.media', ['chat']],
+ ['chat', 'media.object.delete', 'openvibe.media', ['chat']],
+ ['chat', 'ai.run.create', 'openvibe.ai', ['chat.*']],
+ ['chat', 'ai.run.read', 'openvibe.ai', ['chat.*']],
['games', 'identity.subject.resolve', SELF_AUDIENCE, []],
['games', 'identity.subject.resolve', SELF_AUDIENCE, []],
// Games subscribes to network.user.token_valid_after (sign-out everywhere closes game sessions).
// Games subscribes to network.user.token_valid_after (sign-out everywhere closes game sessions).
['games', 'events.subscription.manage', 'openvibe.events', []],
['games', 'events.subscription.manage', 'openvibe.events', []],
@@ -214,6 +225,8 @@ const DEFAULT_GRANTS = [
@@ -214,6 +225,8 @@ const DEFAULT_GRANTS = [
['community', 'network.blocks.read', SELF_AUDIENCE, []],
['community', 'network.blocks.read', SELF_AUDIENCE, []],
['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', []],
+ // Plan T3: Live reads a channel's moderation settings, its moderators and emote count from Chat.
+ ['live', 'chat.moderation.read', 'openvibe.chat', []],
['live', 'chat.message.send', 'openvibe.chat', []],
['live', 'chat.message.send', 'openvibe.chat', []],
// Wave 8: Live as a Billing client (used only with BILLING_AUTHORITY=billing). Never cashout.manage
// Wave 8: Live as a Billing client (used only with BILLING_AUTHORITY=billing). Never cashout.manage
// or ledger.admin: approving payouts is a separately controlled capability (ADR-012 rule 10).
// or ledger.admin: approving payouts is a separately controlled capability (ADR-012 rule 10).
@@ -93,6 +93,9 @@ const server = http.createServer(app);
@@ -93,6 +93,9 @@ const server = http.createServer(app);
assert.strictEqual(t.body.scope, 'identity.subject.resolve network.account.deletion.confirm network.account.export.contribute', 'Media resolves object owners to subjects and takes part in account export and deletion (ADR-033), nothing else here');
assert.strictEqual(t.body.scope, 'identity.subject.resolve network.account.deletion.confirm network.account.export.contribute', 'Media resolves object owners to subjects and takes part in account export and deletion (ADR-033), nothing else here');
const mediaResolve = t.body.access_token;
const mediaResolve = t.body.access_token;
t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.media' });
t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.media' });
+ assert.strictEqual(t.status, 200, JSON.stringify(t.body));
+ assert.deepStrictEqual(t.body.scope.split(' ').sort(), ['media.object.delete', 'media.object.list', 'media.object.read', 'media.object.upload'], 'plan T4: Live reaches Media with its own token, nothing more');
+ t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.games' });
assert.strictEqual(t.status, 400, 'no grants for that audience');
assert.strictEqual(t.status, 400, 'no grants for that audience');
// ── Guarded routes ──
// ── Guarded routes ──