openvibers/openvibe.network Commits

Live may run media.analyze on OpenVibe.AI (roadmap WS-O task 5): its ai.run.create and ai.run.read grants for openvibe.ai carry the namespaces live.*, network.site_copy and media.analyze (AI 67fb2a4, local-first VOD and clip analysis). test/principals.test.js pins Live's AI token: those two capabilities and those three namespaces, nothing else.

OP OpenVibers committed 27 Sept 2026 · d0729284b0 · 2 files, +9 −4


Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex ca89e67d..405a6dea 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -139,10 +139,10 @@ const DEFAULT_GRANTS = [
['codes', 'events.event.publish', 'openvibe.events', []],
['ai', 'events.event.publish', 'openvibe.events', []], // ai.run.* (AI server/events.js, 2026-09-24)
// Wave 13: Live's AI features run as OpenVibe.AI workflows (AI_SERVICE=remote in live.env).
-- // Live runs its own live.* workflows and, as the footer-copy fallback, network.site_copy
-- // (OpenVibe.AI fails closed on a token with no ns).
-- ['live', 'ai.run.create', 'openvibe.ai', ['live.*', 'network.site_copy']],
-- ['live', 'ai.run.read', 'openvibe.ai', ['live.*', 'network.site_copy']],
++ // Live runs its own live.* workflows, network.site_copy as the footer-copy fallback, and media.analyze
++ // (local-first VOD/clip analysis, roadmap WS-O task 5) (OpenVibe.AI fails closed on a token with no ns).
++ ['live', 'ai.run.create', 'openvibe.ai', ['live.*', 'network.site_copy', 'media.analyze']],
++ ['live', 'ai.run.read', 'openvibe.ai', ['live.*', 'network.site_copy', 'media.analyze']],
// Wave 3: producers publish to OpenVibe.Events (their own source only, enforced by Events).
...['live', 'media', 'network', 'community', 'billing', 'chat', 'tools', 'games', 'search', 'sources', 'tips'].map(c => [c, 'events.event.publish', 'openvibe.events', []]),
// Wave 14: Search subscribes to <owner>.index_document.* deliveries.
ddiff --git a/test/principals.test.js b/test/principals.test.js
iindex 03805678..3374634e 100644
---- a/test/principals.test.js
++++ b/test/principals.test.js
@@@ -54,6 +54,11 @@ const server = http.createServer(app);
assert.ok(validate('identity.service-token-claims@1', claims.claims).valid);
assert.ok(claims.claims.exp - claims.claims.iat <= 300, 'short-lived');
const full = t.body.access_token;
++ // Live's OpenVibe.AI token: its own workflows, the footer copy and media.analyze (WS-O task 5), nothing else.
++ t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.ai' });
++ const aiClaims = serviceAuth.verifyServiceToken(t.body.access_token, { publicKey: keys.publicKey, issuer: ISSUER, audience: 'openvibe.ai' });
++ assert.ok(aiClaims.ok, aiClaims.reason);
++ assert.deepStrictEqual([aiClaims.claims.cap, aiClaims.claims.ns], [['ai.run.create', 'ai.run.read'], ['live.*', 'network.site_copy', 'media.analyze']]);
t = await token({ client_id: 'live', client_secret: 'wrong', audience: 'openvibe.network' });
assert.strictEqual(t.status, 401); assert.strictEqual(t.body.error, 'invalid_client');