openvibers/openvibe.shared Commits

Shared 2.0.0: X-Internal-Key is gone from the shared package (plan T2). internalApiAuth, OpenVibeAuthClient#verifyTokenInternal (Network's deleted /internal/verify-token) and #getUserProfile (a route Network never had) are removed, and the deprecated openvibe-shared/chrome-ssr alias with them (use openvibe-shared/frame). Nothing in the estate used any of it. A test asserts the helpers stay gone. npm test 42/42.

OP OpenVibers committed 29 Sept 2026 · 47719cc3e8 · 10 files, +25 −74


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex b895852..0252180 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,15 @@ All notable changes to `openvibe-shared`. Versions follow [semver](https://semve
breaking change to any exported module, browser global or served file name is a new major.
A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
++## 2.0.0 — 2026-09-29
++
++**X-Internal-Key is gone from the shared package** (plan T2: every internal call in the estate uses a service token).
++Breaking, and nothing in the estate used any of it:
++- `internalApiAuth` (the `middleware` export and the index re-export) is removed.
++- `OpenVibeAuthClient#verifyTokenInternal` (Network's `/internal/verify-token`, deleted) and `#getUserProfile` (a route
++ Network never had) are removed; the rest of the client is unchanged.
++- The deprecated `openvibe-shared/chrome-ssr` alias is removed: use `openvibe-shared/frame`.
++
## 1.30.1 — 2026-09-28
Page moves, measured on Live with a 400 ms network: the bar runs from the click, "Loading Content…" appears at 150 ms and follows the phase ("starting up"), the styled page fades in, and nothing shows unstyled in between. Fixes to 1.30.0: the first move after a server-rendered page is animated (the "first page" is the first `enter()` before any route change, route generation ≤ 1, not simply the first call); `route-transition.js` is fetched a few seconds after load, so it is ready for the first click; the loading line sits over the page's visible area but outside the section (a page script that re-renders its section while loading can no longer take it away); the file is requested by path, so the site's versions map hashes it.
ddiff --git a/README.md b/README.md
iindex 9e3fc2b..72b598d 100644
---- a/README.md
++++ b/README.md
@@@ -20,7 +20,7 @@ were reconciled first.
| Kind | Files |
|---|---|
| Browser scripts, served at `/shared/<file>` (listed in `files.js`) | `navbar.js`, `nav-icons.js`, `theme-loader.js`, `footer.js`, `notification-ui.js`, `notification-live.js`, `account-switcher.js`, `user-card.js`, `ov-mark.js`, `ov-icons.js`, `history.js`, `sso-client.js`, `panels.js`, `ui.js`, `island.js`, `tooltip.js`, `release-watch.js`, `release-update.js`, `web-runtime.js`, `openvibe-sw.js` |
--| Node modules (`require('openvibe-shared/<name>')`) | `index` (`.`), `analytics` (+ `analytics/{privacy,tracker,retention,schema,event,prune-cli}`), `app-icon`, `auth-client`, `brand`, `builtin-themes`, `frame` (the OpenVibe Frame on the server; `chrome-ssr` is a deprecated alias), `legal`, `middleware`, `notifications`, `seo`, `theme-sync`, `url-resolver`, `files`, `egress` (SSRF-safe addresses and connect-time DNS for outbound fetches of user-chosen hosts), `trace` (the request's W3C trace on outbound calls inside the network), `release`, `release-compat` (tests), `metrics`, `ready`, `config` (the configuration model: revisioned, validated, classified settings with last-known-good and `/api/admin/config`), `test-runner` (the `npm test` runner of every service's `test/run.js`: each `*.test.js` in its own process; a line `<label>: skipped (<why>)` makes a file skipped, listed with ○ and never counted as passed, and `--strict` fails on skips), `perf-budget` (size budgets for a page's first load, measured from the running server: HTML, same-origin scripts and stylesheets, raw and brotli; for `npm test`), `browser-harness` (real-Chrome checks of a running site: status, console errors, overflow, duplicate scripts, no-JS text, canonical, JSON-LD against visible text, axe-core, repeated-navigation growth and idle work; Node 22, Chrome); `footer`, `shipped` (the shared "shipped X ago" pill, recent list and `/updates` log, from the network changelog) and `icons` (= `ov-icons.js`) work on both sides, and `release-update` gives Node its pure `plan()` |
++| Node modules (`require('openvibe-shared/<name>')`) | `index` (`.`), `analytics` (+ `analytics/{privacy,tracker,retention,schema,event,prune-cli}`), `app-icon`, `auth-client`, `brand`, `builtin-themes`, `frame` (the OpenVibe Frame on the server), `legal`, `middleware`, `notifications`, `seo`, `theme-sync`, `url-resolver`, `files`, `egress` (SSRF-safe addresses and connect-time DNS for outbound fetches of user-chosen hosts), `trace` (the request's W3C trace on outbound calls inside the network), `release`, `release-compat` (tests), `metrics`, `ready`, `config` (the configuration model: revisioned, validated, classified settings with last-known-good and `/api/admin/config`), `test-runner` (the `npm test` runner of every service's `test/run.js`: each `*.test.js` in its own process; a line `<label>: skipped (<why>)` makes a file skipped, listed with ○ and never counted as passed, and `--strict` fails on skips), `perf-budget` (size budgets for a page's first load, measured from the running server: HTML, same-origin scripts and stylesheets, raw and brotli; for `npm test`), `browser-harness` (real-Chrome checks of a running site: status, console errors, overflow, duplicate scripts, no-JS text, canonical, JSON-LD against visible text, axe-core, repeated-navigation growth and idle work; Node 22, Chrome); `footer`, `shipped` (the shared "shipped X ago" pill, recent list and `/updates` log, from the network changelog) and `icons` (= `ov-icons.js`) work on both sides, and `release-update` gives Node its pure `plan()` |
| Schemas | `docs/schemas/analytics-event.v1.json` (`analytics/event.v1`, exported as `openvibe-shared/analytics/event.v1.json`) |
| Generators | `scripts/build-nav-icons.py` (Font Awesome glyphs → `nav-icons.js`, `ov-icons.js`), `scripts/build-navbar-icons.js` (navbar.js's built-in glyphs), `scripts/build-theme-loader.js`, `scripts/build-app-icons.js` |
ddiff --git a/auth-client.js b/auth-client.js
iindex 7a53335..167a3fa 100644
---- a/auth-client.js
++++ b/auth-client.js
@@@ -116,49 +116,6 @@ class OpenVibeAuthClient {
return null;
}
}
--
-- /**
-- * Verify a token via the internal API (server-to-server).
-- * Useful as a fallback or for getting fresh user data.
-- * @param {string} token
-- * @param {string} internalKey - X-Internal-Key header value
-- * @returns {Promise<Object|null>}
-- */
-- async verifyTokenInternal(token, internalKey) {
-- try {
-- const res = await fetch(`${this.internalBase}/internal/verify-token`, {
-- method: 'POST',
-- headers: {
-- 'Content-Type': 'application/json',
-- 'X-Internal-Key': internalKey,
-- },
-- body: JSON.stringify({ token }),
-- });
-- if (!res.ok) return null;
-- return res.json();
-- } catch {
-- return null;
-- }
-- }
--
-- /**
-- * Get fresh user profile data via internal API.
-- * @param {number} userId
-- * @param {string} internalKey
-- * @returns {Promise<Object|null>}
-- */
-- async getUserProfile(userId, internalKey) {
-- try {
-- const res = await fetch(`${this.internalBase}/internal/user/${userId}/sync`, {
-- method: 'POST',
-- headers: { 'X-Internal-Key': internalKey },
-- });
-- if (!res.ok) return null;
-- return res.json();
-- } catch {
-- return null;
-- }
-- }
}
module.exports = { OpenVibeAuthClient };
ddiff --git a/chrome-ssr.js b/chrome-ssr.js
ddeleted file mode 100644
iindex e31673f..0000000
---- a/chrome-ssr.js
++++ /dev/null
@@@ -1,4 +0,0 @@
--'use strict';
--// Deprecated alias: openvibe-shared/chrome-ssr is now openvibe-shared/frame (the OpenVibe Frame). Kept so
--// sites on older code keep working; it goes away in 2.0.0.
--module.exports = require('./frame');
ddiff --git a/frame.js b/frame.js
iindex c11f67b..a123f16 100644
---- a/frame.js
++++ b/frame.js
@@@ -1,6 +1,6 @@
'use strict';
// openvibe-shared/frame — the OpenVibe Frame (the navbar, footer and "shipped" views every OpenVibe site sits
--// in): the parts that can be baked into HTML on the server. (Formerly openvibe-shared/chrome-ssr, still an alias.)
++// in): the parts that can be baked into HTML on the server. (Formerly openvibe-shared/chrome-ssr; the alias was removed in 2.0.0.)
// footer(cfg) the full shared footer (HTML + CSS); the browser's footer.js renders into the same element
// noscriptNav(site) a plain navigation bar inside <noscript>: the JavaScript navbar cannot exist without
// scripts, so visitors who block them (and text browsers) still get the brand and the network
ddiff --git a/index.js b/index.js
iindex 2981bd7..db30153 100644
---- a/index.js
++++ b/index.js
@@@ -3,7 +3,7 @@
const { BRAND, BRAND_DEFAULTS, resolveBrandUrls, buildBrandFromRegistry } = require('./brand');
const { OpenVibeAuthClient } = require('./auth-client');
const { CSS_VARIABLES, DEFAULT_VARS, BUILTIN_THEMES, applyTheme, resolveBuiltinTheme, sanitizeCssValue, loadFromStorage, saveToStorage, syncThemeToServer } = require('./theme-sync');
--const { extractToken, requireOpenVibeAuth, optionalOpenVibeAuth, internalApiAuth } = require('./middleware');
++const { extractToken, requireOpenVibeAuth, optionalOpenVibeAuth } = require('./middleware');
const { PRIORITY, CATEGORY, TYPES, SOUNDS, EMAIL_ELIGIBLE_CATEGORIES, createNotification, DEFAULT_NOTIFICATION_PREFS } = require('./notifications');
const { AnalyticsTracker, classifyRequest, parseUserAgent, ANALYTICS_SCHEMA, BOT_USER_AGENTS, SUSPICIOUS_PATTERNS } = require('./analytics');
const { URL_DEFINITIONS, normalizeValue, validateValue, resolveRegistryValues, formatRegistryEntry } = require('./url-resolver');
@@@ -18,7 +18,6 @@ module.exports = {
extractToken,
requireOpenVibeAuth,
optionalOpenVibeAuth,
-- internalApiAuth,
// Themes
CSS_VARIABLES,
DEFAULT_VARS,
ddiff --git a/middleware.js b/middleware.js
iindex 4509e16..a4df217 100644
---- a/middleware.js
++++ b/middleware.js
@@@ -69,26 +69,8 @@ function optionalOpenVibeAuth(authClient) {
};
}
--/**
-- * Internal API authentication middleware.
-- * Verifies X-Internal-Key header for server-to-server calls.
-- *
-- * @param {string} internalKey - Expected key value
-- * @returns {Function} Express middleware
-- */
--function internalApiAuth(internalKey) {
-- return (req, res, next) => {
-- const provided = req.headers['x-internal-key'];
-- if (!provided || provided !== internalKey) {
-- return res.status(403).json({ error: 'Forbidden' });
-- }
-- next();
-- };
--}
--
module.exports = {
extractToken,
requireOpenVibeAuth,
optionalOpenVibeAuth,
-- internalApiAuth,
};
ddiff --git a/package.json b/package.json
iindex 7716ead..becc589 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-shared",
-- "version": "1.30.1",
++ "version": "2.0.0",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"exports": {
@@@ -20,7 +20,6 @@
"./brand": "./brand.js",
"./browser-harness": "./browser-harness.js",
"./builtin-themes": "./builtin-themes.js",
-- "./chrome-ssr": "./chrome-ssr.js",
"./config": "./config.js",
"./config-pg": "./config-pg.js",
"./egress": "./egress.js",
ddiff --git a/test/frame.test.js b/test/frame.test.js
iindex 50bdf20..b9fe440 100644
---- a/test/frame.test.js
++++ b/test/frame.test.js
@@@ -3,7 +3,7 @@
// block for a home page and the body of a site's /updates page (shipped.js fills both).
const assert = require('assert');
const frame = require('../frame');
--assert.strictEqual(require('../chrome-ssr'), frame, 'the old name is an alias');
++assert.throws(() => require('../chrome-ssr'), /Cannot find module/, 'the chrome-ssr alias is gone (2.0.0)');
const home = frame.shipped({ service: 'wiki', title: 'Recently shipped on OpenVibe.Wiki <x>' });
assert.ok(home.includes('data-ov-shipped="latest" data-service="wiki" href="/updates"'));
ddiff --git a/test/package.test.js b/test/package.test.js
iindex d8b01cd..5349ac4 100644
---- a/test/package.test.js
++++ b/test/package.test.js
@@@ -18,11 +18,11 @@ for (const [sub, target] of Object.entries(pkg.exports)) {
assert.strictEqual(require.resolve(sub === '.' ? pkg.name : `${pkg.name}/${sub.slice(2)}`), path.join(ROOT, target), `${sub} resolves`);
}
// Subpaths in use across Network, Live, Media, Tools, Community and Sites (2026-09-22).
--for (const sub of ['analytics', 'app-icon', 'auth-client', 'brand', 'chrome-ssr', 'footer', 'icons', 'legal', 'notifications', 'seo', 'theme-sync', 'url-resolver', 'package.json', 'navbar', 'files']) {
++for (const sub of ['analytics', 'app-icon', 'auth-client', 'brand', 'footer', 'icons', 'legal', 'notifications', 'seo', 'theme-sync', 'url-resolver', 'package.json', 'navbar', 'files']) {
assert.doesNotThrow(() => require.resolve(`openvibe-shared/${sub}`), `openvibe-shared/${sub}`);
}
// Server modules load in Node; the navbar module loads too (UMD, no DOM touched at require time).
--for (const sub of ['analytics', 'app-icon', 'brand', 'chrome-ssr', 'footer', 'icons', 'legal', 'notifications', 'seo', 'url-resolver', 'files', 'nav-icons', 'metrics', 'ready', 'egress', 'trace', 'config', 'browser-harness']) require(`openvibe-shared/${sub}`);
++for (const sub of ['analytics', 'app-icon', 'brand', 'footer', 'icons', 'legal', 'notifications', 'seo', 'url-resolver', 'files', 'nav-icons', 'metrics', 'ready', 'egress', 'trace', 'config', 'browser-harness']) require(`openvibe-shared/${sub}`);
// analytics is dependency-free: its parts require only Node built-ins and each other.
for (const f of fs.readdirSync(path.join(ROOT, 'analytics'))) {
const src = fs.readFileSync(path.join(ROOT, 'analytics', f), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
@@@ -35,3 +35,12 @@ assert.strictEqual(typeof require('openvibe-shared/navbar').init, 'function');
assert.ok(/^\d+\.\d+\.\d+$/.test(pkg.version), 'semver version');
assert.ok(fs.readFileSync(path.join(ROOT, 'CHANGELOG.md'), 'utf8').includes(`## ${pkg.version}`), 'CHANGELOG has an entry for this version');
console.log(`package: ${Object.keys(pkg.exports).length} exports resolve`);
++
++// 2.0.0: the X-Internal-Key helpers are gone (plan T2), and nothing exported names the key.
++{
++ const shared = require('..');
++ assert.strictEqual(shared.internalApiAuth, undefined, 'internalApiAuth is removed');
++ const { OpenVibeAuthClient } = require('../auth-client');
++ assert.strictEqual(OpenVibeAuthClient.prototype.verifyTokenInternal, undefined, 'verifyTokenInternal is removed');
++ assert.strictEqual(OpenVibeAuthClient.prototype.getUserProfile, undefined, 'getUserProfile is removed');
++}