openvibers/openvibe.network Commits

Allow Mail to run private Inbox AI for mailbox owners (#675)

OP OpenVibers committed 5 days ago · 4f083d86ca · 2 files, +7 −0

Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex 35cf9c28..68b225da 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -712,6 +712,9 @@ const DEFAULT_GRANTS = [
// OpenVibe.Vision (contracts 0.235.0): model calls through AI's OpenAI-compatible endpoint (workflow ai.complete),
// its account-event subscriptions, and the export/deletion pair above. It has no public records, so no Search grant.
['vision', 'ai.run.create', 'openvibe.ai', ['ai.complete']],
++ // Mail's opt-in Inbox AI runs only ai.complete through OpenVibe.AI, attributed to the mailbox owner.
++ ['mail', 'ai.run.create', 'openvibe.ai', ['ai.complete']],
++ ['mail', 'ai.run.read', 'openvibe.ai', ['ai.complete']],
['vision', 'events.subscription.manage', 'openvibe.events', []],
// VIS-6: the operator review, its evidence view and the decision that releases Media's evidence hold.
// The media namespaces are the first-party tenants whose objects can be reviewed.
ddiff --git a/test/principals.test.js b/test/principals.test.js
iindex 590ac2f6..82d653ef 100644
---- a/test/principals.test.js
++++ b/test/principals.test.js
@@@ -126,6 +126,10 @@ const server = http.createServer(app);
// Vision also publishes its own vision.result.ready and vision.alert (VIS-5; granted 11-02).
assert.strictEqual(t.body.scope, client === 'vision' ? 'events.event.publish events.subscription.manage' : 'events.subscription.manage', `${client} subscribes to the account events at boot`);
}
++
++ await db.prepare('UPDATE oauth_clients SET client_secret = ? WHERE client_id = ?').run('mail-secret', 'mail');
++ t = await token({ client_id: 'mail', client_secret: 'mail-secret', audience: 'openvibe.ai' });
++ assert.deepStrictEqual(t.body.scope.split(' ').sort(), ['ai.run.create', 'ai.run.read']);
t = await token({ client_id: 'vision', client_secret: 'vision-secret', audience: 'openvibe.ai' });
assert.strictEqual(t.status, 200, JSON.stringify(t.body));
const visionAiClaims = serviceAuth.verifyServiceToken(t.body.access_token, { publicKey: keys.publicKey, issuer: ISSUER, audience: 'openvibe.ai' });