openvibers/openvibe.extensions Commits

Rename Extensions machine references to Link (#20)

OP OpenVibers committed 4 days ago · cba54c5771 · 5 files, +22 −12

Changes

ddiff --git a/README.md b/README.md
iindex 22ce9aa..e3164ee 100644
---- a/README.md
++++ b/README.md
@@@ -150,7 +150,7 @@ browser/
lib/api.js the only code that makes requests to the Coupons API
lib/network-api.js the Dock's state on the Network (GET/PUT /api/v1/me/dock), with the person's own token
lib/auth.js the Dock's one-click OAuth sign-in: PKCE, state, refresh, sign-out
-- lib/controller.js popup logic without the DOM (tested in Node)
++ lib/controller.js popup logic without the DOM (tested in Link)
lib/platform.js chrome.* / browser.*: tabs.query, tabs.create (hand-off pages only), storage.local, permissions
lib/format.js wording ("Expiry unknown", "No restrictions stated", …)
icons/ generated by scripts/icons.js
@@@ -162,7 +162,7 @@ scripts/
icons.js draws the icons (no dependencies)
```
--## Tests (Node 22, no browser, no dependencies)
++## Tests (Link 22, no browser, no dependencies)
```bash
npm test
@@@ -250,7 +250,7 @@ shows "Allow access to openvibe.coupons".
- [OpenVibe.Live](https://github.com/OpenVibers/OpenVibe.Live) `/embed/agent/<ags_id>?vt=…`, the
agent view's frame. Its `frame-ancestors` list is first-party site origins; an extension origin is
not on it yet.
--- No npm dependencies. Tests and scripts use Node's standard library.
++- No npm dependencies. Tests and scripts use Link's standard library.
---
ddiff --git a/browser/lib/locker-vault.js b/browser/lib/locker-vault.js
iindex 90f6d81..44737c1 100644
---- a/browser/lib/locker-vault.js
++++ b/browser/lib/locker-vault.js
@@@ -93,7 +93,7 @@
}
if (action === 'seal-fill') {
if (!fillApi || m.clicked !== true || !FILL_REQUEST_ID.test(String(m.request_id || '')) || typeof m.origin !== 'string' || !EXACT_HTTPS_ORIGIN.test(m.origin) || origin(m.origin) !== m.origin
-- || !/^nod_[0-9A-HJKMNP-TV-Z]{26}$/.test(String(m.machine_id || '')) || typeof m.item_id !== 'string') throw new Error('Choose a valid sign-in request.');
++ || !/^lnk_[0-9A-HJKMNP-TV-Z]{26}$/.test(String(m.machine_id || '')) || typeof m.item_id !== 'string') throw new Error('Choose a valid sign-in request.');
const s = await unlocked();
const requests = await fillApi.requests();
const pending = (requests.requests || []).find((r) => r.id === m.request_id && r.origin === m.origin && r.machine_node_id === m.machine_id && r.expires_at > now());
@@@ -107,7 +107,7 @@
if (m.include_code === true && login.totp) grant.code = await passwords.totp(login.totp);
const plain = new TextEncoder().encode(JSON.stringify(grant));
try {
-- const envelope = await core.seal(plain, { lock: 'people', keys: [{ subject: { type: 'node', id: m.machine_id }, publicKey: target.public_key }] });
++ const envelope = await core.seal(plain, { lock: 'people', keys: [{ subject: { type: 'link', id: m.machine_id }, publicKey: target.public_key }] });
await still(s);
let binary = ''; for (const b of envelope.bytes) binary += String.fromCharCode(b);
return { ok: true, envelope: btoa(binary), thumbprint: target.thumbprint };
ddiff --git a/hardware/README.md b/hardware/README.md
iindex e923b0f..95c503c 100644
---- a/hardware/README.md
++++ b/hardware/README.md
@@@ -2,8 +2,8 @@
Scripts for streaming from and controlling hardware devices (Raspberry Pi, single-board computers, etc.) with OpenVibe.Live.
--> **Connecting a new robot? Use [OpenVibe.Bot](https://openvibe.bot) and the [OpenVibe Node](https://github.com/OpenVibers/OpenVibe.Node).**
--> The Node pairs with a one-time code (no stream key) and runs your driver as a plugin
++> **Connecting a new robot? Use [OpenVibe.Bot](https://openvibe.bot) and the [OpenVibe Link](https://github.com/OpenVibers/OpenVibe.Link).**
++> The Link pairs with a one-time code (no stream key) and runs your driver as a plugin
> ([write a driver](https://openvibe.bot/docs/drivers)); Bot gives the robot a panel built from its profile, roles, a
> queue, limits and a latched e-stop, and a Live channel can show that panel under its stream. The controller here
> uses Live's stream-key hardware socket, which keeps working for existing setups and is retired once they have moved
ddiff --git a/test/link-brand.test.js b/test/link-brand.test.js
nnew file mode 100644
iindex 0000000..eaa904f
---- /dev/null
++++ b/test/link-brand.test.js
@@@ -0,0 +1,10 @@
++'use strict';
++const assert = require('node:assert/strict');
++const { spawnSync } = require('node:child_process');
++const path = require('node:path');
++const root = path.resolve(__dirname, '..');
++const oldName = ['OpenVibe[ .-]No' + 'de', 'openvibe-' + 'node', 'no' + 'd_', 'node[.]openvibe[.]network', 'node:lnk_', 'openvibe[.](bot|my|network)/mach' + 'ines'].join('|');
++const result = spawnSync('git', ['grep', '-n', '-I', '-i', '-E', oldName, '--', '.', ':!migrations/**', ':!test/link-brand.test.js'], { cwd: root, encoding: 'utf8' });
++assert.ok(result.status === 0 || result.status === 1, result.stderr || 'git grep failed');
++assert.equal(result.status, 1, `Old Link brand or principal returned:\n${(result.stdout || '').split('\n').slice(0, 10).join('\n')}`);
++console.log(' ok old Link brand and principal IDs are absent');
ddiff --git a/test/locker.test.js b/test/locker.test.js
iindex 2fac22c..2f4df57 100644
---- a/test/locker.test.js
++++ b/test/locker.test.js
@@@ -24,7 +24,7 @@ async function fixture() {
content: async (id) => ciphertexts.get(id), save: async (bytes) => { ciphertexts.set(String(ciphertexts.size + 1), bytes); return { id: '1' }; },
};
const storage = { getSession: async (k) => memory.get(k), setSession: async (obj) => { writes.push(obj); for (const [k, v] of Object.entries(obj)) memory.set(k, v); }, removeSession: async (keys) => keys.forEach((k) => memory.delete(k)) };
-- const options = { core, payload, passwords, api, fillApi: { requests: async () => ({ requests: [{ id: 'fr_01JAB2C3D4E5F6G7H8J9K0MNPQ', origin: 'https://example.test', machine_node_id: 'nod_01JAB2C3D4E5F6G7H8J9K0MNPQ', expires_at: 60_000 }] }), targets: async () => ({ machines: [{ id: 'nod_01JAB2C3D4E5F6G7H8J9K0MNPQ', public_key: options.nodeKey, thumbprint: 'network-thumbprint' }] }), grant: async () => ({ outcome: 'ok' }) }, storage, scheduleLock: async () => {}, cancelLock: async () => {}, tabs: { active: async () => active }, fill: async (...args) => { fills.push(args); return { ok: true }; }, clipboard: { write: async (v) => clipboard.push(v) }, account: async () => account, now: () => clock };
++ const options = { core, payload, passwords, api, fillApi: { requests: async () => ({ requests: [{ id: 'fr_01JAB2C3D4E5F6G7H8J9K0MNPQ', origin: 'https://example.test', machine_node_id: 'lnk_01JAB2C3D4E5F6G7H8J9K0MNPQ', expires_at: 60_000 }] }), targets: async () => ({ machines: [{ id: 'lnk_01JAB2C3D4E5F6G7H8J9K0MNPQ', public_key: options.nodeKey, thumbprint: 'network-thumbprint' }] }), grant: async () => ({ outcome: 'ok' }) }, storage, scheduleLock: async () => {}, cancelLock: async () => {}, tabs: { active: async () => active }, fill: async (...args) => { fills.push(args); return { ok: true }; }, clipboard: { write: async (v) => clipboard.push(v) }, account: async () => account, now: () => clock };
const vault = create(options);
const ask = (type, values = {}, sender = { url: POPUP }) => vault.handle({ type: 'locker:' + type, tabId: 1, site: 'https://example.test', ...values }, sender, POPUP);
return { vault, ask, memory, fills, clipboard, api, options, writes, pass, recovery, ciphertexts,
@@@ -90,16 +90,16 @@ test('locking during a pending decrypt cancels the fill', async () => {
test('Companion seals a selected login to one machine and returns ciphertext only', async () => {
const f = await fixture(); await f.ask('unlock', { clicked: true, secret: f.pass });
await f.ask('save', { clicked: true, username: 'alice', password: 'fixture password', totp: 'otpauth://totp/x?secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ' });
-- const node = await core.generatePersonKeys(), machine = 'nod_01JAB2C3D4E5F6G7H8J9K0MNPQ';
++ const node = await core.generatePersonKeys(), machine = 'lnk_01JAB2C3D4E5F6G7H8J9K0MNPQ';
f.options.nodeKey = node.ecdhPublic;
await assert.rejects(f.ask('seal-fill', { clicked: true, request_id: 'fr_01JAB2C3D4E5F6G7H8J9K0MNPQ', origin: 'http://example.test', machine_id: machine, public_key: node.ecdhPublic, item_id: '1', include_code: true, submit: false }), /valid sign-in request/);
const other = await core.generatePersonKeys();
const sealed = await f.ask('seal-fill', { clicked: true, request_id: 'fr_01JAB2C3D4E5F6G7H8J9K0MNPQ', origin: 'https://example.test', machine_id: machine, public_key: other.ecdhPublic, item_id: '1', include_code: true, submit: false });
assert.equal(sealed.ok, true);
assert.equal(sealed.thumbprint, 'network-thumbprint');
-- await assert.rejects(core.open(Uint8Array.from(Buffer.from(sealed.envelope, 'base64')), { privateKey: other.ecdh.privateKey, subject: { type: 'node', id: machine } }));
++ await assert.rejects(core.open(Uint8Array.from(Buffer.from(sealed.envelope, 'base64')), { privateKey: other.ecdh.privateKey, subject: { type: 'link', id: machine } }));
assert.ok(!sealed.envelope.includes('fixture password'));
-- const plain = await core.open(Uint8Array.from(Buffer.from(sealed.envelope, 'base64')), { privateKey: node.ecdh.privateKey, subject: { type: 'node', id: machine } });
++ const plain = await core.open(Uint8Array.from(Buffer.from(sealed.envelope, 'base64')), { privateKey: node.ecdh.privateKey, subject: { type: 'link', id: machine } });
const grant = JSON.parse(new TextDecoder().decode(plain));
assert.deepEqual({ request_id: grant.request_id, origin: grant.origin, username: grant.username, password: grant.password, submit: grant.submit }, {
request_id: 'fr_01JAB2C3D4E5F6G7H8J9K0MNPQ', origin: 'https://example.test', username: 'alice', password: 'fixture password', submit: false,
@@@ -111,7 +111,7 @@ test('Companion seals a selected login to one machine and returns ciphertext onl
test('seal-fill rechecks pending request and owned target before creating an envelope', async () => {
const f = await fixture(); await f.ask('unlock', { clicked: true, secret: f.pass });
await f.ask('save', { clicked: true, username: 'alice', password: 'fixture password' });
-- const machine = 'nod_01JAB2C3D4E5F6G7H8J9K0MNPQ';
++ const machine = 'lnk_01JAB2C3D4E5F6G7H8J9K0MNPQ';
f.options.nodeKey = (await core.generatePersonKeys()).ecdhPublic;
f.options.fillApi.requests = async () => ({ requests: [] });
await assert.rejects(f.ask('seal-fill', { clicked: true, request_id: 'fr_01JAB2C3D4E5F6G7H8J9K0MNPQ', origin: 'https://example.test', machine_id: machine, item_id: '1' }), /no longer waiting/);