openvibers/openvibe.network Commits
Pin openvibe-sdk to v0.86.0, not a deleted branch; accept the released fingerprint format (#580)
Changes
@@@ -978,7 +978,7 @@ curl -s -H "Authorization: Bearer $TOKEN" https://openvibe.network/api/v1/people"subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","ecdh_public": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },"signing_public": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },-- "fingerprint": "alpha bravo charlie delta-echo foxtrot golf hotel",++ "fingerprint": "alpha bravo charlie delta · echo foxtrot golf hotel","updated_at": "2026-11-06T09:12:00.000Z","changed_at": "2026-11-06T09:12:00.000Z"}@@@ -21,7 +21,7 @@"jsonwebtoken": "^9.0.0","multer": "^1.4.5-lts.1","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.289.1",-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/heads/feat/locker-core-sdk",++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.86.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.114.0","pg": "^8.23.0","qrcode": "1.5.4",@@@ -1739,8 +1739,8 @@},"node_modules/openvibe-sdk": {"version": "0.86.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/heads/feat/locker-core-sdk",-- "integrity": "sha512-MuTtcHtJSv4NgEBPy1nLso6RHppWPIbWzVBL24DtWFPdfVkH+B0yR0H3R73HDNP/Sc0MgKKn11GxcrnSmQlJkA==",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.86.0",++ "integrity": "sha512-APn4qK1ErX9f/gR6l2AhGfj+n8/3ul87Otm69xN4wyJUt43WF6A2b0lMKDG9Ds6oQiOoCZJCjxCSanP0wtMuGA==","license": "MIT","bin": {"openvibe-download": "bin/openvibe-download.js"@@@ -25,7 +25,7 @@"jsonwebtoken": "^9.0.0","multer": "^1.4.5-lts.1","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.289.1",-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/heads/feat/locker-core-sdk",++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.86.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.114.0","pg": "^8.23.0","qrcode": "1.5.4",@@@ -62,7 +62,8 @@ const SUBJECT_RE = /^usr_[0-9A-HJKMNP-TV-Z]{26}$/;/** A name (letters, digits, dot, dash, underscore): exact names only, never a pattern. */const NAME_RE = /^[A-Za-z0-9_.-]{1,40}$/;/** The eight words of a fingerprint, in two groups of four. */--const FINGERPRINT_RE = /^[a-z]+ [a-z]+ [a-z]+ [a-z]+-[a-z]+ [a-z]+ [a-z]+ [a-z]+$/;++// openvibe-sdk/locker's fingerprintOf: eight words in two groups of four, joined by " · " (SDK 0.86.0).++const FINGERPRINT_RE = /^[a-z]+ [a-z]+ [a-z]+ [a-z]+ · [a-z]+ [a-z]+ [a-z]+ [a-z]+$/;/** A base64 ECDSA P-256 signature: 64 bytes, 86 characters and the padding. */const SIGNATURE_RE = /^[A-Za-z0-9+/]{86}==$/;/** How many lookups one caller may do a minute. */@@@ -143,7 +143,7 @@ const notices = async () => (await db.prepare('SELECT message, category, serviceassert.strictEqual(r.body.code, 'locker.bad_signature');// ── A fingerprint that does not match the keys is refused ──-- r = await call('PUT', '/api/v1/me/keys', { headers: await as(1), body: { ...ann.body, fingerprint: 'alpha bravo charlie delta-echo foxtrot golf hotel' } });++ r = await call('PUT', '/api/v1/me/keys', { headers: await as(1), body: { ...ann.body, fingerprint: 'alpha bravo charlie delta · echo foxtrot golf hotel' } });assert.strictEqual(r.status, 400, 'a fingerprint that is not the one the keys produce is refused');assert.strictEqual(r.body.code, 'locker.fingerprint_mismatch');nnew file mode 100644@@@ -0,0 +1,15 @@++'use strict';++// Every git-tarball dependency is pinned to a released tag, never a branch: a branch is deleted when its PR merges,++// and the next deploy's npm install then fails (2026-11-06: #577 pinned openvibe-sdk to refs/heads/feat/locker-core-sdk).++const assert = require('assert');++const pkg = require('../package.json');++const lock = require('../package-lock.json');++const bad = [];++for (const [name, spec] of Object.entries({ ...pkg.dependencies, ...pkg.devDependencies, ...pkg.optionalDependencies })) {++ if (/codeload\.github\.com\/.+\/tar\.gz\/refs\/heads\//.test(String(spec)) || /github\.com\/.+#(?!v?\d)/.test(String(spec))) bad.push(`${name}: ${spec}`);++}++for (const [where, entry] of Object.entries(lock.packages || {})) {++ if (entry && /\/tar\.gz\/refs\/heads\//.test(String(entry.resolved || ''))) bad.push(`${where} resolved from a branch: ${entry.resolved}`);++}++assert.deepStrictEqual(bad, [], 'pin git tarballs to a tag (refs/tags/vX.Y.Z), never a branch');++console.log('pins-are-tags: every tarball dependency is a tag');
@@ -978,7 +978,7 @@ curl -s -H "Authorization: Bearer $TOKEN" https://openvibe.network/api/v1/people
@@ -978,7 +978,7 @@ curl -s -H "Authorization: Bearer $TOKEN" https://openvibe.network/api/v1/people
"subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"ecdh_public": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },
"ecdh_public": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },
"signing_public": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },
"signing_public": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },
- "fingerprint": "alpha bravo charlie delta-echo foxtrot golf hotel",
+ "fingerprint": "alpha bravo charlie delta · echo foxtrot golf hotel",
"updated_at": "2026-11-06T09:12:00.000Z",
"updated_at": "2026-11-06T09:12:00.000Z",
"changed_at": "2026-11-06T09:12:00.000Z"
"changed_at": "2026-11-06T09:12:00.000Z"
}
}
@@ -21,7 +21,7 @@
@@ -21,7 +21,7 @@
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
"multer": "^1.4.5-lts.1",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.289.1",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.289.1",
- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/heads/feat/locker-core-sdk",
+ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.86.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.114.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.114.0",
"pg": "^8.23.0",
"pg": "^8.23.0",
"qrcode": "1.5.4",
"qrcode": "1.5.4",
@@ -1739,8 +1739,8 @@
@@ -1739,8 +1739,8 @@
},
},
"node_modules/openvibe-sdk": {
"node_modules/openvibe-sdk": {
"version": "0.86.0",
"version": "0.86.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/heads/feat/locker-core-sdk",
- "integrity": "sha512-MuTtcHtJSv4NgEBPy1nLso6RHppWPIbWzVBL24DtWFPdfVkH+B0yR0H3R73HDNP/Sc0MgKKn11GxcrnSmQlJkA==",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.86.0",
+ "integrity": "sha512-APn4qK1ErX9f/gR6l2AhGfj+n8/3ul87Otm69xN4wyJUt43WF6A2b0lMKDG9Ds6oQiOoCZJCjxCSanP0wtMuGA==",
"license": "MIT",
"license": "MIT",
"bin": {
"bin": {
"openvibe-download": "bin/openvibe-download.js"
"openvibe-download": "bin/openvibe-download.js"
@@ -25,7 +25,7 @@
@@ -25,7 +25,7 @@
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
"multer": "^1.4.5-lts.1",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.289.1",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.289.1",
- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/heads/feat/locker-core-sdk",
+ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.86.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.114.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.114.0",
"pg": "^8.23.0",
"pg": "^8.23.0",
"qrcode": "1.5.4",
"qrcode": "1.5.4",
@@ -62,7 +62,8 @@ const SUBJECT_RE = /^usr_[0-9A-HJKMNP-TV-Z]{26}$/;
@@ -62,7 +62,8 @@ const SUBJECT_RE = /^usr_[0-9A-HJKMNP-TV-Z]{26}$/;
/** A name (letters, digits, dot, dash, underscore): exact names only, never a pattern. */
/** A name (letters, digits, dot, dash, underscore): exact names only, never a pattern. */
const NAME_RE = /^[A-Za-z0-9_.-]{1,40}$/;
const NAME_RE = /^[A-Za-z0-9_.-]{1,40}$/;
/** The eight words of a fingerprint, in two groups of four. */
/** The eight words of a fingerprint, in two groups of four. */
-const FINGERPRINT_RE = /^[a-z]+ [a-z]+ [a-z]+ [a-z]+-[a-z]+ [a-z]+ [a-z]+ [a-z]+$/;
+// openvibe-sdk/locker's fingerprintOf: eight words in two groups of four, joined by " · " (SDK 0.86.0).
+const FINGERPRINT_RE = /^[a-z]+ [a-z]+ [a-z]+ [a-z]+ · [a-z]+ [a-z]+ [a-z]+ [a-z]+$/;
/** A base64 ECDSA P-256 signature: 64 bytes, 86 characters and the padding. */
/** A base64 ECDSA P-256 signature: 64 bytes, 86 characters and the padding. */
const SIGNATURE_RE = /^[A-Za-z0-9+/]{86}==$/;
const SIGNATURE_RE = /^[A-Za-z0-9+/]{86}==$/;
/** How many lookups one caller may do a minute. */
/** How many lookups one caller may do a minute. */
@@ -143,7 +143,7 @@ const notices = async () => (await db.prepare('SELECT message, category, service
@@ -143,7 +143,7 @@ const notices = async () => (await db.prepare('SELECT message, category, service
assert.strictEqual(r.body.code, 'locker.bad_signature');
assert.strictEqual(r.body.code, 'locker.bad_signature');
// ── A fingerprint that does not match the keys is refused ──
// ── A fingerprint that does not match the keys is refused ──
- r = await call('PUT', '/api/v1/me/keys', { headers: await as(1), body: { ...ann.body, fingerprint: 'alpha bravo charlie delta-echo foxtrot golf hotel' } });
+ r = await call('PUT', '/api/v1/me/keys', { headers: await as(1), body: { ...ann.body, fingerprint: 'alpha bravo charlie delta · echo foxtrot golf hotel' } });
assert.strictEqual(r.status, 400, 'a fingerprint that is not the one the keys produce is refused');
assert.strictEqual(r.status, 400, 'a fingerprint that is not the one the keys produce is refused');
assert.strictEqual(r.body.code, 'locker.fingerprint_mismatch');
assert.strictEqual(r.body.code, 'locker.fingerprint_mismatch');
new file mode 100644
new file mode 100644
@@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
+'use strict';
+// Every git-tarball dependency is pinned to a released tag, never a branch: a branch is deleted when its PR merges,
+// and the next deploy's npm install then fails (2026-11-06: #577 pinned openvibe-sdk to refs/heads/feat/locker-core-sdk).
+const assert = require('assert');
+const pkg = require('../package.json');
+const lock = require('../package-lock.json');
+const bad = [];
+for (const [name, spec] of Object.entries({ ...pkg.dependencies, ...pkg.devDependencies, ...pkg.optionalDependencies })) {
+ if (/codeload\.github\.com\/.+\/tar\.gz\/refs\/heads\//.test(String(spec)) || /github\.com\/.+#(?!v?\d)/.test(String(spec))) bad.push(`${name}: ${spec}`);
+}
+for (const [where, entry] of Object.entries(lock.packages || {})) {
+ if (entry && /\/tar\.gz\/refs\/heads\//.test(String(entry.resolved || ''))) bad.push(`${where} resolved from a branch: ${entry.resolved}`);
+}
+assert.deepStrictEqual(bad, [], 'pin git tarballs to a tag (refs/tags/vX.Y.Z), never a branch');
+console.log('pins-are-tags: every tarball dependency is a tag');