openvibers/openvibe.events Commits

Accept watch.* publishes from a svc:watch token (#14)

OP OpenVibers committed 5 Oct 2026 · 4d35c0d1c8 · 2 files, +17 −1

Changes:
- `server/config.js:24-26` — added `'watch'` to `DEFAULT_SOURCES` with a comment listing the three `watch.*` ids.
- `test/publish.test.js:106-119` — new test `a watch service principal publishes watch.* only`: `svc:watch` may publish `watch.watch.triggered` (201) and not `live.stream.started` (403 `events.type_not_allowed`); an unlisted source publishing `watch.watch.triggered` gets 403 `events.unknown_source`.

Real ids confirmed from the Contracts v0.102.0+/main catalog (catalog.json:4235, 4244, 4253): `watch.observation.recorded`, `watch.watch.triggered`, `watch.check.failed`.

Test: `nice -n 15 ov test --no-cache test/publish.test.js` → **1 passed in 4 s** (only `test/publish.test.js` reached).

Changes

ddiff --git a/server/config.js b/server/config.js
iindex 9213acb..e743dec 100644
---- a/server/config.js
++++ b/server/config.js
@@@ -21,7 +21,9 @@ const DEFAULT_SOURCES = ['live', 'media', 'network', 'community', 'chat', 'openr
// Publication products (Waves 16-19): each publishes <product>.<type>.<action> via openvibe-publishing.
'wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade',
// Robot control (OpenVibe.Bot): bot.robot.*, bot.estop.*, bot.command.*
-- 'bot'];
++ 'bot',
++ // Watch (OpenVibe.Watch): watch.observation.recorded, watch.watch.triggered, watch.check.failed
++ 'watch'];
/**
* Namespaces that belong to the network rather than to one service. `provider.*` carries storage
ddiff --git a/test/publish.test.js b/test/publish.test.js
iindex 6ecd5b8..ce6813e 100644
---- a/test/publish.test.js
++++ b/test/publish.test.js
@@@ -103,6 +103,20 @@ t('a bot service principal publishes bot.* only', async () => {
assert.strictEqual(r.body.code, 'events.type_not_allowed');
});
++t('a watch service principal publishes watch.* only', async () => {
++ const watch = serviceToken('watch', ['events.event.publish']);
++ // Real ids from openvibe-contracts (Watch, v0.102.0+): watch.watch.triggered, not watch.triggered.
++ let r = await request(h.base, 'POST', '/api/v1/events', { token: watch, body: envelope('watch', { event_type: 'watch.watch.triggered' }) });
++ assert.strictEqual(r.status, 201, r.text);
++ r = await request(h.base, 'POST', '/api/v1/events', { token: watch, body: envelope('watch', { event_type: 'live.stream.started' }) });
++ assert.strictEqual(r.status, 403);
++ assert.strictEqual(r.body.code, 'events.type_not_allowed');
++ // A source not in the list cannot claim the watch namespace.
++ r = await request(h.base, 'POST', '/api/v1/events', { token: serviceToken('stranger', ['events.event.publish']), body: envelope('stranger', { event_type: 'watch.watch.triggered' }) });
++ assert.strictEqual(r.status, 403);
++ assert.strictEqual(r.body.code, 'events.unknown_source');
++});
++
t('unknown source (not in the manifest map) -> 403', async () => {
const r = await request(h.base, 'POST', '/api/v1/events', { token: serviceToken('stranger', ['events.event.publish']), body: envelope('stranger') });
assert.strictEqual(r.status, 403);