openvibers/openvibe.network Commits
Codes reaches Media with its own token for private pictures; the agent host does not, yet (#432)
Changes
@@@ -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;nnew file mode 100644@@@ -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');
@@ -112,6 +112,11 @@ const DEFAULT_GRANTS = [
@@ -112,6 +112,11 @@ const DEFAULT_GRANTS = [
// Compatibility register C-71: Inventory (Workshop badge images) and MediaHub (its library) reach Media with their
// 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.
// 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']],
['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.upload', 'openvibe.media', ['media-hub']],
['media-hub', 'media.object.read', '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;
// OpenVibe.Video's AI edit (MediaHub server/video/ai-edit.js): media.analyze on finished uploads, local and unpaid;
new file mode 100644
new file mode 100644
@@ -0,0 +1,25 @@
@@ -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');