openvibers/openvibe.network Commits

Grant coupons events.subscription.manage on openvibe.events (#36)

OP OpenVibers committed 4 Oct 2026 · 8dc56513fa · 2 files, +7 −0

local checks ✓ 3/3 · CI ✓ 3/3 · review SHIP by DeepSeek harness

https://github.com/OpenVibers/OpenVibe.Network/pull/36

Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex ff820456..bf0f0100 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -138,6 +138,8 @@ const DEFAULT_GRANTS = [
['deals', 'community.comment.write', 'openvibe.community', []],
['deals', 'community.comment.moderate', 'openvibe.community', []],
['coupons', 'events.event.publish', 'openvibe.events', []],
++ // Coupons subscribes to the sources it watches (OpenVibe.Coupons scripts/subscribe.js), as Deals does.
++ ['coupons', 'events.subscription.manage', 'openvibe.events', []],
['coupons', 'sources.item.read', 'openvibe.sources', []],
['host', 'events.event.publish', 'openvibe.events', []],
// ADR-030 (WS-E task 4): Live rebuilds its follows projection from Network's graph.
ddiff --git a/test/principals.test.js b/test/principals.test.js
iindex 37980ba7..8fc7b1be 100644
---- a/test/principals.test.js
++++ b/test/principals.test.js
@@@ -162,6 +162,11 @@ const server = http.createServer(app);
await db.prepare("UPDATE oauth_clients SET client_secret = 'tools-secret' WHERE client_id = 'tools'").run();
const ts = await token({ client_id: 'tools', client_secret: 'tools-secret', audience: 'openvibe.search' });
assert.strictEqual(ts.body.scope, 'search.document.write', 'Tools indexes its tools in Search');
++ // Coupons subscribes to its Events sources with its own token (OpenVibe.Coupons scripts/subscribe.js).
++ await db.prepare("UPDATE oauth_clients SET client_secret = 'coupons-secret' WHERE client_id = 'coupons'").run();
++ const cps = await token({ client_id: 'coupons', client_secret: 'coupons-secret', audience: 'openvibe.events', scope: 'events.subscription.manage' });
++ assert.strictEqual(cps.status, 200, JSON.stringify(cps.body));
++ assert.strictEqual(cps.body.scope, 'events.subscription.manage', 'Coupons manages its Events subscriptions');
// Go-live fan-out accepts Live's token (network.notifications.push); a narrower token is refused.
r = await post('/internal/events/stream-live', {}, { authorization: `Bearer ${full}` });