openvibers/openvibe.events Commits

Events: inventory and services may publish their own events (they were refused as unknown sources); a test keeps every Contracts producer allowed (#32)

OP OpenVibers committed 9 Oct 2026 · 260792169a · 2 files, +22 −1

Changes

ddiff --git a/server/config.js b/server/config.js
iindex 73967f2..55aa2a0 100644
---- a/server/config.js
++++ b/server/config.js
@@@ -27,7 +27,11 @@ const DEFAULT_SOURCES = ['live', 'media', 'network', 'community', 'chat', 'openr
// Run (OpenVibe.Run, plan T14): run.job.queued|started|succeeded|failed|cancelled|expired
'run',
// Space (OpenVibe.Space, plan T10 step 3): space.thread.created, space.post.created, space.moderation.action
-- 'space'];
++ 'space',
++ // Inventory (OpenVibe.Inventory, ADR-054): inventory.item.granted|equipped|consumed|revoked, inventory.definition.published
++ 'inventory',
++ // Services (OpenVibe.Services, the developer console): its services.* events
++ 'services'];
/**
* Namespaces that belong to the network rather than to one service. `provider.*` carries storage
ddiff --git a/test/sources-cover-producers.test.js b/test/sources-cover-producers.test.js
nnew file mode 100644
iindex 0000000..b3aacaa
---- /dev/null
++++ b/test/sources-cover-producers.test.js
@@@ -0,0 +1,17 @@
++'use strict';
++// Every service whose openvibe-contracts manifest declares events it produces may publish them: its id is one of the
++// default sources (server/config.js), so a new producer cannot ship with its events refused as events.unknown_source
++// (OpenVibe.Inventory's were, 2026-10-09). Events itself publishes its own events internally, not through the API.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++const { DEFAULT_SOURCES } = require('../server/config');
++
++const dir = path.join(path.dirname(require.resolve('openvibe-contracts/package.json')), 'manifests', 'services');
++const manifests = fs.readdirSync(dir).filter((f) => f.endsWith('.json')).map((f) => JSON.parse(fs.readFileSync(path.join(dir, f), 'utf8')));
++const producers = manifests.filter((m) => (m.eventsProduced || []).length).map((m) => m.id || m.service).filter((id) => id !== 'events');
++const missing = producers.filter((id) => !DEFAULT_SOURCES.includes(id));
++assert.deepStrictEqual(missing, [], `producers that may not publish: ${missing.join(', ')}`);
++const outside = manifests.flatMap((m) => (m.eventsProduced || []).filter((t) => (m.id || m.service) !== 'events' && t.split('.')[0] !== (m.id || m.service) && !t.startsWith('provider.')).map((t) => `${m.id || m.service}: ${t}`));
++assert.deepStrictEqual(outside, [], 'every produced event type is in its producer\'s own namespace');
++console.log(`sources cover producers: ${producers.length} producers, all allowed`);