openvibers/openvibe.bot Commits

Kept desk profiles (contracts 0.217.0, Node v0.24.0): a desk start's profile reaches the machine and the audit names it; openvibe-contracts v0.217.0 (#182)

OP OpenVibers committed 17 days ago · 7c1c08da5b · 6 files, +16 −9

Changes

ddiff --git a/README.md b/README.md
iindex bd83839..3d12e50 100644
---- a/README.md
++++ b/README.md
@@@ -187,7 +187,7 @@ Set `BOT_ONVIF_CAMERAS` (JSON, unset by default) to the server-side cameras Bot
OpenVibe.Sites no longer generates `deploy/nginx/openvibe.bot.conf` (sites.json marks the vhost as owned by OpenVibe.Bot), and Bot serves nothing from a Sites checkout: the legal pages, `robots.txt`, `sitemap.xml`, `manifest.webmanifest` and the 404 page all come from the app. A Sites deploy leaves an installed vhost it no longer generates in place, so the current Sites vhost keeps serving openvibe.bot until Bot's first deploy installs this file over it; later Sites deploys never overwrite Bot's `/device` and `/control` routes.
<!-- versions:start -->
--- openvibe-contracts: v0.216.0
++- openvibe-contracts: v0.217.0
- openvibe-sdk: v0.65.0
- openvibe-shared: v4.15.2
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex 3f1bb2c..acc53a9 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -5,11 +5,11 @@
"runtime": "node 22, express 4, ws; PostgreSQL 18 via openvibe-sdk/db (pg, or embedded PGlite in tests); Valkey optional; no build step",
"port": 4630,
"domain": "openvibe.bot (www -> apex; /device and /control WebSockets; /install)",
-- "contracts": "openvibe-contracts v0.216.0",
++ "contracts": "openvibe-contracts v0.217.0",
"sdk": "openvibe-sdk v0.65.0",
"shared": "openvibe-shared v4.15.2",
"packages": [
-- "openvibe-contracts v0.216.0",
++ "openvibe-contracts v0.217.0",
"openvibe-sdk v0.65.0",
"openvibe-shared v4.15.2"
],
ddiff --git a/package-lock.json b/package-lock.json
iindex 6023627..9ffc291 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -13,7 +13,7 @@
"dotenv": "^16.4.7",
"express": "^4.21.2",
"iovalkey": "^0.4.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.216.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.217.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.65.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.15.2",
"pg": "^8.23.0",
@@@ -845,9 +845,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.216.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.216.0",
-- "integrity": "sha512-/oLEtkreLt0fBw5933kzaP0Tk/QeYtWi7F/qxwyTsVWpesVXlDza5P/XK6qoEbzMCSx6sB6lHuSoyxbN6idKwg==",
++ "version": "0.217.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.217.0",
++ "integrity": "sha512-hvLStkPZQmUiXH9MSUo7nzLerg13+xOp4Ear4YXQUOEGtMtCDIbBSXhQxfIvgSkGNox2jR94V8WADY6k8gEmcg==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex eaf7eaa..9736fb3 100644
---- a/package.json
++++ b/package.json
@@@ -25,7 +25,7 @@
"dotenv": "^16.4.7",
"express": "^4.21.2",
"iovalkey": "^0.4.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.216.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.217.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.65.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.15.2",
"pg": "^8.23.0",
ddiff --git a/server/realtime.js b/server/realtime.js
iindex 914fc0d..83bb6b3 100644
---- a/server/realtime.js
++++ b/server/realtime.js
@@@ -65,7 +65,7 @@ const COMPUTER_MAX_MS = 600000;
/** What an audit row keeps of a computer command: never a file's content, stdin or arguments (they may hold secrets). */
function computerSummary(kind, value) {
const where = deskOf(value) !== 'main' ? { desk: deskOf(value) } : {};
-- if (kind === 'desk') return { action: value.action, ...(typeof value.desk === 'string' ? { desk: value.desk } : {}), ...(typeof value.kind === 'string' ? { kind: value.kind } : {}), ...(Number.isInteger(value.width) && Number.isInteger(value.height) ? { width: value.width, height: value.height } : {}) };
++ if (kind === 'desk') return { action: value.action, ...(typeof value.desk === 'string' ? { desk: value.desk } : {}), ...(typeof value.kind === 'string' ? { kind: value.kind } : {}), ...(typeof value.profile === 'string' ? { profile: value.profile } : {}), ...(Number.isInteger(value.width) && Number.isInteger(value.height) ? { width: value.width, height: value.height } : {}) };
if (kind === 'exec') return { program: String(value.argv[0]).slice(0, 120), args: value.argv.length - 1 };
if (kind === 'fs') return { op: value.op, path: String(value.path).slice(0, 300), ...(typeof value.content_b64 === 'string' ? { bytes: Math.floor((value.content_b64.length * 3) / 4) } : {}) };
if (kind === 'probe') { try { const u = new URL(value.target); return { scheme: u.protocol.replace(':', ''), host: u.host }; } catch { return { scheme: null }; } }
ddiff --git a/test/machine-computer.test.js b/test/machine-computer.test.js
iindex 965e55e..e31abe0 100644
---- a/test/machine-computer.test.js
++++ b/test/machine-computer.test.js
@@@ -222,6 +222,13 @@ const { boot, check, done } = require('./helpers/app');
assert.strictEqual((await cmd(old.deviceId, { kind: 'desk', value: { action: 'start', desk: 'desk-task-a' } }, { user: alex })).json.result, 'ack');
const audit = await t.db.many('SELECT value FROM command_audit WHERE robot_id = $1 AND kind = $2 AND result = $3 ORDER BY id', [both.deviceId, 'desk', 'ack']);
assert.deepStrictEqual(audit.map((r) => r.value.kind), ['browser', 'desktop'], 'the audit names the kind');
++ // A kept profile (contracts 0.217.0, Node v0.24.0) reaches the machine and the audit names it.
++ const kept = await cmd(both.deviceId, { kind: 'desk', value: { action: 'start', desk: 'desk-task-k', kind: 'browser', profile: 'agent' } }, { user: alex });
++ assert.strictEqual(kept.json.result, 'ack', kept.text);
++ assert.strictEqual(seen.at(-1).value.profile, 'agent');
++ const keptRow = await t.db.one('SELECT value FROM command_audit WHERE robot_id = $1 AND kind = $2 ORDER BY id DESC LIMIT 1', [both.deviceId, 'desk']);
++ assert.strictEqual(keptRow.value.profile, 'agent');
++ assert.strictEqual((await cmd(both.deviceId, { kind: 'desk', value: { action: 'start', desk: 'desk-task-k', profile: '../x' } }, { user: alex })).status, 422, 'a bad profile name is refused');
both.c.close();
mac.c.close();
old.c.close();