openvibers/openvibe.codes Commits

Codes C3: Codes reaches OpenVibe.AI's vault over the loopback (#169)

OP OpenVibers committed 14 days ago · 930bba56c8 · 3 files, +10 −2

A person's key is sealed in OpenVibe.AI's vault, and that API is host-local: nginx answers 403 for /api/
on the public address ("Service API: host-local only"). Codes reached for the public address, so every
connection — putting a key, reading it back, testing it, forgetting it — was refused with 403.

Codes now has two addresses for AI: the public one (what a harness on the person's machine is given) and its
own (the loopback, where the vault lives), like the other services' internal addresses. The harness's
environment still names the public address.

The test gives Codes an address that cannot answer, so a reach for the public one fails the test.

Changes

ddiff --git a/server/config.js b/server/config.js
iindex 78a4659..e8e7644 100644
---- a/server/config.js
++++ b/server/config.js
@@@ -66,7 +66,11 @@ function load(env = process.env) {
// OpenVibe.AI (Codes C3): where a person's own provider key is sealed (it never leaves AI) and where the
// harnesses run. Codes talks to it with its own Network token (audience openvibe.ai).
ai: {
++ // The public address: what a harness on the person's own machine is given.
url: trim(env.CODES_AI_URL || 'https://ai.openvibe.services'),
++ // Codes' own address for AI: the vault (a person's keys) is a host-local API, so Codes reaches it over
++ // the loopback. The public address answers 403 there (nginx: /api/ is host-local only).
++ internalUrl: trim(env.CODES_AI_INTERNAL_URL || 'http://127.0.0.1:4700'),
audience: 'openvibe.ai',
// The scopes Codes asks Network for: it stores a person's key with the first and runs a test request
// (and the harnesses' requests) with the second.
ddiff --git a/server/domain/connections.js b/server/domain/connections.js
iindex d329ef1..9b6adc8 100644
---- a/server/domain/connections.js
++++ b/server/domain/connections.js
@@@ -49,7 +49,9 @@ function present(row) {
}
function createConnections({ config, fetchImpl = globalThis.fetch, log = console } = {}) {
-- const base = String((config.ai && config.ai.url) || 'https://ai.openvibe.services').replace(/\/+$/, '');
++ // Codes' own address for AI: the vault (a person's keys) is a host-local API, so Codes reaches it over the
++ // loopback. The public address answers 403 there (nginx: /api/ is host-local only).
++ const base = String((config.ai && (config.ai.internalUrl || config.ai.url)) || 'https://ai.openvibe.services').replace(/\/+$/, '');
const scope = (config.ai && config.ai.scope) || 'ai.credential.manage ai.run.create';
// Codes' own Network token for OpenVibe.AI: the consent grant (ai.credential.manage) lets it store a person's
// key; ai.run.create lets it make the test request. Five minutes, cached by the SDK client.
ddiff --git a/test/connections.test.js b/test/connections.test.js
iindex 1deb8f0..bd9843b 100644
---- a/test/connections.test.js
++++ b/test/connections.test.js
@@@ -14,7 +14,9 @@ const router = require('../engine/router');
(async () => {
const KEY = 'sk-ant-0123456789abcdefXYZ';
-- const t = await boot({ env: (network) => ({ CODES_AI_URL: network.url }) });
++ // The public address is an address that cannot answer (the vault is a host-local API): if Codes reached for it
++ // instead of its own loopback address, every call here would fail.
++ const t = await boot({ env: (network) => ({ CODES_AI_URL: 'https://ai.openvibe.services.invalid', CODES_AI_INTERNAL_URL: network.url }) });
const db = t.ctx.store.db;
const ada = t.network.addUser('ada');
const bo = t.network.addUser('bo');