openvibers/openvibe.network Commits
Tips may ask VIP whether a reader is a member (members-only posts) (#582)
Changes
@@@ -551,6 +551,8 @@ const DEFAULT_GRANTS = [// WS-K task 8: Wiki's VIP spaces and pages (Wiki server/integrations/vip.js).['wiki', 'vip.resource.policy.evaluate', 'openvibe.vip', []],['live', 'vip.entitlement.check', 'openvibe.vip', []],++ // Tips' members-only posts (Tips #194): the post text only for a member of the post's tier.++ ['tips', 'vip.entitlement.check', 'openvibe.vip', []],['community', 'events.subscription.manage', 'openvibe.events', []],['community', 'events.event.read', 'openvibe.events', []],['community', 'events.event.publish', 'openvibe.events', []], // community.* events (Community server/events.js, 2026-09-24)@@@ -391,6 +391,12 @@ const server = http.createServer(app);// Plan T5 (Wave 9): Tips' chat adapter mints a token for 'chat.message.send chat.event.publish' on// openvibe.chat with its own service token (OpenVibe.Tips server/delivery/chat.js); without both rows// TIPS_CHAT_ADAPTER=chat can never deliver a paid effect.++ {++ // Tips' members-only posts ask VIP whether the reader is a member of the post's tier.++ const tv = await token({ client_id: 'tips', client_secret: 'tips-secret', audience: 'openvibe.vip' });++ assert.strictEqual(tv.status, 200, 'Tips can get a VIP token: ' + JSON.stringify(tv.body));++ assert.ok(String(tv.body.scope || '').split(' ').includes('vip.entitlement.check'), 'and it carries vip.entitlement.check');++ }const tc = await token({ client_id: 'tips', client_secret: 'tips-secret', audience: 'openvibe.chat' });assert.strictEqual(tc.status, 200, JSON.stringify(tc.body));assert.deepStrictEqual(tc.body.scope.split(' '), ['chat.event.publish', 'chat.message.send'], "Tips delivers paid chat effects through Chat's ingress");
@@ -551,6 +551,8 @@ const DEFAULT_GRANTS = [
@@ -551,6 +551,8 @@ const DEFAULT_GRANTS = [
// WS-K task 8: Wiki's VIP spaces and pages (Wiki server/integrations/vip.js).
// WS-K task 8: Wiki's VIP spaces and pages (Wiki server/integrations/vip.js).
['wiki', 'vip.resource.policy.evaluate', 'openvibe.vip', []],
['wiki', 'vip.resource.policy.evaluate', 'openvibe.vip', []],
['live', 'vip.entitlement.check', 'openvibe.vip', []],
['live', 'vip.entitlement.check', 'openvibe.vip', []],
+ // Tips' members-only posts (Tips #194): the post text only for a member of the post's tier.
+ ['tips', 'vip.entitlement.check', 'openvibe.vip', []],
['community', 'events.subscription.manage', 'openvibe.events', []],
['community', 'events.subscription.manage', 'openvibe.events', []],
['community', 'events.event.read', 'openvibe.events', []],
['community', 'events.event.read', 'openvibe.events', []],
['community', 'events.event.publish', 'openvibe.events', []], // community.* events (Community server/events.js, 2026-09-24)
['community', 'events.event.publish', 'openvibe.events', []], // community.* events (Community server/events.js, 2026-09-24)
@@ -391,6 +391,12 @@ const server = http.createServer(app);
@@ -391,6 +391,12 @@ const server = http.createServer(app);
// Plan T5 (Wave 9): Tips' chat adapter mints a token for 'chat.message.send chat.event.publish' on
// Plan T5 (Wave 9): Tips' chat adapter mints a token for 'chat.message.send chat.event.publish' on
// openvibe.chat with its own service token (OpenVibe.Tips server/delivery/chat.js); without both rows
// openvibe.chat with its own service token (OpenVibe.Tips server/delivery/chat.js); without both rows
// TIPS_CHAT_ADAPTER=chat can never deliver a paid effect.
// TIPS_CHAT_ADAPTER=chat can never deliver a paid effect.
+ {
+ // Tips' members-only posts ask VIP whether the reader is a member of the post's tier.
+ const tv = await token({ client_id: 'tips', client_secret: 'tips-secret', audience: 'openvibe.vip' });
+ assert.strictEqual(tv.status, 200, 'Tips can get a VIP token: ' + JSON.stringify(tv.body));
+ assert.ok(String(tv.body.scope || '').split(' ').includes('vip.entitlement.check'), 'and it carries vip.entitlement.check');
+ }
const tc = await token({ client_id: 'tips', client_secret: 'tips-secret', audience: 'openvibe.chat' });
const tc = await token({ client_id: 'tips', client_secret: 'tips-secret', audience: 'openvibe.chat' });
assert.strictEqual(tc.status, 200, JSON.stringify(tc.body));
assert.strictEqual(tc.status, 200, JSON.stringify(tc.body));
assert.deepStrictEqual(tc.body.scope.split(' '), ['chat.event.publish', 'chat.message.send'], "Tips delivers paid chat effects through Chat's ingress");
assert.deepStrictEqual(tc.body.scope.split(' '), ['chat.event.publish', 'chat.message.send'], "Tips delivers paid chat effects through Chat's ingress");