openvibers/openvibe.network Commits

Grants: Tours' place photos (Media) and cited summaries (AI) (#690)

OP OpenVibers committed 5 days ago · 587973e259 · 2 files, +26 −0

Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex cfd16c9e..7e32c2c7 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -776,6 +776,10 @@ const DEFAULT_GRANTS = [
['tours', 'events.subscription.manage', 'openvibe.events', []],
// Tours publishes its places, cities and walks to OpenVibe.Search as tours.index_document.* (contracts 0.274.0).
['tours', 'events.event.publish', 'openvibe.events', []],
++ // Tours copies licensed Commons/Openverse thumbnails into its own Media tenant (no hotlinking), and asks OpenVibe.AI
++ // for a cited place summary (Tours #106, 2026-11-08). New rows: no RESTORED_GRANTS or CHANGED_DEFAULT_NAMESPACES entry.
++ ['tours', 'media.object.upload', 'openvibe.media', ['tours']],
++ ...['ai.run.create', 'ai.run.read'].map((cap) => ['tours', cap, 'openvibe.ai', ['ai.summarize']]),
['shoes', 'events.subscription.manage', 'openvibe.events', []],
// Shoes publishes its model pages to OpenVibe.Search as shoes.index_document.* (contracts 0.273.0, through its own
// outbox and openvibe-publishing/search-feed).
ddiff --git a/test/tours-grants.test.js b/test/tours-grants.test.js
nnew file mode 100644
iindex 00000000..da79d691
---- /dev/null
++++ b/test/tours-grants.test.js
@@@ -0,0 +1,22 @@
++/**
++ * OpenVibe.Tours' grants for its place guides (Tours #106): it uploads licensed place photos into its own Media
++ * tenant only, and runs OpenVibe.AI's ai.summarize workflow only. Each is a capability the pinned contracts offer,
++ * active.
++ *
++ * node test/tours-grants.test.js
++ */
++'use strict';
++const assert = require('assert');
++const contracts = require('openvibe-contracts');
++const principals = require('../server/identity/principals');
++
++const tours = principals.DEFAULT_GRANTS.filter((g) => g[0] === 'tours');
++const media = tours.filter((g) => g[2] === 'openvibe.media');
++assert.deepStrictEqual(media.map((g) => [g[1], g[3]]), [['media.object.upload', ['tours']]], 'Tours uploads into its own tenant, nothing else of Media');
++const ai = tours.filter((g) => g[2] === 'openvibe.ai');
++assert.deepStrictEqual(ai.map((g) => [g[1], g[3]]).sort(), [['ai.run.create', ['ai.summarize']], ['ai.run.read', ['ai.summarize']]], 'Tours runs and reads only ai.summarize');
++for (const g of [...media, ...ai]) {
++ const cap = contracts.capabilities.get(g[1]);
++ assert.ok(cap && cap.status === 'active', `${g[1]} is an active capability`);
++}
++console.log('Tours grants: its own Media tenant and ai.summarize only');