openvibers/openvibe.network Commits

Codes reaches Media with its own token for private pictures; the agent host does not, yet (#432)

OP OpenVibers committed 14 days ago · 7673db09fc · 2 files, +30 −0

Codes (#188) keeps task screenshots in Media as private objects, and Media takes no app keys (C-71), so svc:codes
gets media.object.upload and media.object.read on its own tenant only.

Actor is left out on purpose. It hosts people's agents, and a hosted agent may hold what its host holds
(agent-grants.test.js). A Media grant on Actor would let every agent request read on Actor's whole tenant. Actor's
artifacts wait for a host rule that keeps media.* out of what agents inherit. A test pins both: Codes on its own
tenant, and no Media grant for the agent host.

Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex bc798dd1..236fcec6 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -112,6 +112,11 @@ const DEFAULT_GRANTS = [
// Compatibility register C-71: Inventory (Workshop badge images) and MediaHub (its library) reach Media with their
// own tokens on their own tenants, not with app keys. Upload also covers the delete of an object.
['inventory', 'media.object.upload', 'openvibe.media', ['inventory']],
++ // Codes (C8 proof screenshots, the rich embeds of a task) keeps a person's pictures in Media as private objects on
++ // its own tenant, reached with its own token (10-30). Actor is not granted Media yet: Actor hosts people's agents,
++ // and a hosted agent may hold what its host holds (agent-grants.test.js), so a Media grant on Actor would let every
++ // agent read Actor's tenant. Actor's artifacts wait for a host rule that keeps media.* out of what agents inherit.
++ ...['media.object.upload', 'media.object.read'].map((cap) => ['codes', cap, 'openvibe.media', ['codes']]),
['media-hub', 'media.object.upload', 'openvibe.media', ['media-hub']],
['media-hub', 'media.object.read', 'openvibe.media', ['media-hub']],
// OpenVibe.Video's AI edit (MediaHub server/video/ai-edit.js): media.analyze on finished uploads, local and unpaid;
ddiff --git a/test/media-private-grants.test.js b/test/media-private-grants.test.js
nnew file mode 100644
iindex 00000000..03daf75d
---- /dev/null
++++ b/test/media-private-grants.test.js
@@@ -0,0 +1,25 @@
++/**
++ * OpenVibe.Codes keeps a person's pictures in Media as private objects (task screenshots, 10-30). Media takes no app
++ * keys (C-71), so Codes reaches it with its own Network service token: upload and read, on its own tenant only, and
++ * nothing else of Media's. Actor holds no Media grant: it hosts people's agents, and an agent may hold what its host
++ * holds, so a Media grant there would open Actor's whole tenant to every agent.
++ *
++ * node test/media-private-grants.test.js
++ */
++'use strict';
++const assert = require('assert');
++const contracts = require('openvibe-contracts');
++const principals = require('../server/identity/principals');
++
++for (const svc of ['codes']) {
++ const rows = principals.DEFAULT_GRANTS.filter((g) => g[0] === svc && g[2] === 'openvibe.media');
++ const held = new Map(rows.map((g) => [g[1], g[3]]));
++ assert.deepStrictEqual([...held.keys()].sort(), ['media.object.read', 'media.object.upload'], `${svc} uploads and reads, nothing more`);
++ for (const [cap, ns] of held) {
++ assert.deepStrictEqual(ns, [svc], `${svc}'s ${cap} is on its own tenant only`);
++ const c = contracts.capabilities.get(cap);
++ assert.ok(c && c.status === 'active', `${cap} is an active capability`);
++ }
++}
++assert.strictEqual(principals.DEFAULT_GRANTS.filter((g) => g[0] === 'actor' && g[2] === 'openvibe.media').length, 0, 'the agent host holds no Media grant');
++console.log('media private grants: codes on its own tenant; none for the agent host');