openvibers/openvibe.network Commits

Grant live identity.subject.resolve (it names the acting person by subject when writing pastes into Community)

OP OpenVibers committed 22 Sept 2026 · 1b79576cb0 · 2 files, +5 −4


Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex a07c0e46..238edd4b 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -33,6 +33,7 @@ const DEFAULT_GRANTS = [
// pastes into Community on behalf of its users and its AI jobs.
['community', 'identity.subject.resolve', SELF_AUDIENCE, []],
['community', 'media.object.upload', 'openvibe.media', ['community']],
++ ['live', 'identity.subject.resolve', SELF_AUDIENCE, []],
['live', 'community.paste.create', 'openvibe.community', []],
['live', 'community.paste.write', 'openvibe.community', []],
['live', 'community.paste.moderate', 'openvibe.community', []],
ddiff --git a/test/principals.test.js b/test/principals.test.js
iindex 6bbbf0f9..783ddeaa 100644
---- a/test/principals.test.js
++++ b/test/principals.test.js
@@@ -50,7 +50,7 @@ const server = http.createServer(app);
const claims = serviceAuth.verifyServiceToken(t.body.access_token, { publicKey: keys.publicKey, issuer: ISSUER, audience: 'openvibe.network' });
assert.ok(claims.ok, claims.reason);
assert.strictEqual(claims.claims.sub, 'svc:live');
-- assert.deepStrictEqual(claims.claims.cap, ['network.coins.credit', 'network.coins.debit', 'network.coins.transfer', 'network.modules.read', 'network.modules.write', 'network.notifications.push']);
++ assert.deepStrictEqual(claims.claims.cap, ['identity.subject.resolve', 'network.coins.credit', 'network.coins.debit', 'network.coins.transfer', 'network.modules.read', 'network.modules.write', 'network.notifications.push']);
assert.ok(validate('identity.service-token-claims@1', claims.claims).valid);
assert.ok(claims.claims.exp - claims.claims.iat <= 300, 'short-lived');
const full = t.body.access_token;
@@@ -62,7 +62,7 @@ const server = http.createServer(app);
t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.network', scope: 'network.coins.credit' });
assert.strictEqual(t.status, 200); assert.strictEqual(t.body.scope, 'network.coins.credit', 'scope narrows the token');
const creditOnly = t.body.access_token;
-- t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.network', scope: 'network.coins.credit identity.subject.resolve' });
++ t = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.network', scope: 'network.coins.credit network.coins.mint' });
assert.strictEqual(t.status, 400); assert.strictEqual(t.body.error, 'invalid_scope', 'asking for an ungranted capability fails');
t = await token({ client_id: 'media', client_secret: 'media-secret', audience: 'openvibe.network' });
assert.strictEqual(t.status, 400); assert.strictEqual(t.body.error, 'invalid_scope', 'a client with no grants gets no token');
@@@ -106,8 +106,8 @@ const server = http.createServer(app);
assert.deepStrictEqual(com.body.scope.split(' '), ['identity.subject.resolve']);
r = await post('/internal/identity/resolve-batch', { system: 'network', ids: ['7'] }, { authorization: `Bearer ${com.body.access_token}` });
assert.strictEqual(r.status, 200); assert.strictEqual(r.body.results['7'].username, 'payee');
-- r = await post('/internal/identity/resolve-batch', { system: 'network', ids: ['7'] }, { authorization: `Bearer ${full}` });
-- assert.strictEqual(r.status, 403, 'live has no identity.subject.resolve grant');
++ r = await post('/internal/identity/resolve-batch', { system: 'network', ids: ['7'] }, { authorization: `Bearer ${creditOnly}` });
++ assert.strictEqual(r.status, 403, 'a token narrowed to coins cannot resolve identities');
const media = await token({ client_id: 'community', client_secret: 'community-secret', audience: 'openvibe.media' });
assert.strictEqual(media.body.scope, 'media.object.upload', 'community may upload screenshot bytes to Media');
const cm = await token({ client_id: 'live', client_secret: 'live-secret', audience: 'openvibe.community' });