openvibers/openvibe.wiki Commits

openvibe-shared v1.5.0 (Track R release manifest), openvibe-contracts v0.32.0, openvibe-sdk v0.5.0

OP OpenVibers committed 23 Sept 2026 · 06b6054174 · 7 files, +36 −26

- /release.json is mounted with release.mount(app, { registry }): POST /release-metrics takes open
  tabs' update reports into /metrics (release_client_updates_total). On contracts 0.32.0 the
  manifest carries the release-manifest 1.1.0 fields; no components are declared, so every
  release still prompts a reload. test/auth.test.js validates the served manifest against the
  contracts.
- identity.service-token-claims 1.2.0 (contracts 0.26.0) requires project_id and env on app tokens:
  the test helper's app tokens carry them, as Network's do. Sandbox app tokens are refused (no
  acceptSandbox); no wiki.* capability can be granted to a developer app (all first-party).
- Contracts 0.32.0 names the revision review and space import routes on wiki.revision.publish and
  wiki.page.create; README and STATUS list the new pins. SDK 0.2.2 -> 0.5.0: Wiki uses
  verifyUserToken, the token client, createClient and the events outbox, none of which changed
  behaviour.

Changes

ddiff --git a/README.md b/README.md
iindex 1fedc89..154b0cb 100644
---- a/README.md
++++ b/README.md
@@@ -189,9 +189,9 @@ applies). Errors are RFC 9457 problem+json. The full route list is at the top of
The ids were proposed in [docs/capabilities-proposal/](docs/capabilities-proposal/) (the plan's
`wiki.search` becomes the three-segment `wiki.search.query`) and are released in openvibe-contracts
--v0.17.0 with the service manifest (this repo pins v0.19.0) ([docs/service-manifest-proposal.json](docs/service-manifest-proposal.json)).
--The proposal for `wiki.revision.publish` now also lists the revision review route, which the
--released manifest does not name yet.
++v0.17.0 with the service manifest (this repo pins v0.32.0) ([docs/service-manifest-proposal.json](docs/service-manifest-proposal.json)).
++The proposal for `wiki.revision.publish` also lists the revision review route, which the released
++capability names since v0.32.0 (as `wiki.page.create` does the space import route).
## Events
@@@ -221,8 +221,8 @@ Production: `/opt/openvibe.wiki`, env `/etc/openvibe/wiki.env`, unit
## Depends on
--- `openvibe-publishing` v0.2.1, `openvibe-contracts` v0.19.0, `openvibe-shared` v1.3.0 (chrome,
-- release, metrics, readiness, SEO helpers, legal pages), `openvibe-sdk` v0.2.2 (auth, events
++- `openvibe-publishing` v0.2.1, `openvibe-contracts` v0.32.0, `openvibe-shared` v1.5.0 (chrome,
++ release, metrics, readiness, SEO helpers, legal pages), `openvibe-sdk` v0.5.0 (auth, events
outbox) — pinned release tarballs.
- OpenVibe.Network (SSO, JWKS, service principal `wiki`), OpenVibe.Events, OpenVibe.Community,
OpenVibe.Sources, OpenVibe.Media, OpenVibe.Search (consumer of the index events). All but the
ddiff --git a/STATUS.json b/STATUS.json
iindex f005bf0..cebfe8f 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,11 +7,11 @@
"runtime": "node 22, express, better-sqlite3",
"port": 4800,
"domain": "openvibe.wiki",
-- "contracts": "openvibe-contracts v0.19.0",
++ "contracts": "openvibe-contracts v0.32.0",
"packages": [
"openvibe-publishing v0.2.1",
-- "openvibe-shared v1.3.0",
-- "openvibe-sdk v0.2.2"
++ "openvibe-shared v1.5.0",
++ "openvibe-sdk v0.5.0"
],
"capabilities": [
"wiki.space.create",
ddiff --git a/package-lock.json b/package-lock.json
iindex a50d647..ff7be51 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -14,10 +14,10 @@
"dotenv": "^16.4.7",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.19.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.1",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.2.2",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0"
++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0"
},
"engines": {
"node": ">=22.0.0"
@@@ -999,9 +999,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.19.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.19.0",
-- "integrity": "sha512-5DjPvXIfc68wZhFXgKlCzDarbbFD5dUV4yYQIKEK1qD+VIuR+4twbON1brdyM9rYZyRyYClPigAqReocmRGytg==",
++ "version": "0.32.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.0",
++ "integrity": "sha512-ntN58SIG03YDxbhsiIzOM5GRH19jRMHZUYWI3xU2VwovExagF5DdwApLVfezsu84UTJ+V2Jfn+LWDc+Oz8ab+g==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
@@@ -1044,18 +1044,18 @@
}
},
"node_modules/openvibe-sdk": {
-- "version": "0.2.2",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.2.2",
-- "integrity": "sha512-kDifUp3EcmnTWzElAmaCZnX659WErcnm4+qVEoAiYQWX/w/1p4TWvoHbUPsrX65TSROVR3tiyVkl801n/0yyCw==",
++ "version": "0.5.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
++ "integrity": "sha512-QVJkR5iazQX0ZwIrDp2A88ZeYYBSXEmSzhpgURPUSnzezIM3jz0HBhVKowyhkvg2aBO61XNf77eb4zJGkMjZiw==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/openvibe-shared": {
-- "version": "1.3.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0",
-- "integrity": "sha512-w8yl/5+9eend8I2O/DzAJnEAL2N3GTUY7c7pzK+MLJuLAGD8FmJJQ9gwbgyrq70Snjt3ebrg3TlpORhRAp2kgA==",
++ "version": "1.5.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0",
++ "integrity": "sha512-cehnscuYMkJwuCYGcI6wPSswbUn0bhTyGAaD5feNCoO//2e9gyC7cgjkEcIOtM8DQF3yTuUNyXnOwckIeM4fUg==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0"
ddiff --git a/package.json b/package.json
iindex f4b277e..740125d 100644
---- a/package.json
++++ b/package.json
@@@ -20,10 +20,10 @@
"dotenv": "^16.4.7",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.19.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.1",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.2.2",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0"
++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0"
},
"engines": {
"node": ">=22.0.0"
ddiff --git a/server/app.js b/server/app.js
iindex a123de5..849ffc7 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -59,7 +59,8 @@ function createApp({ config, svc, viewers, platform, keys, db, log = console, ra
{ const legal = require('openvibe-shared/legal'); app.get(legal.PATHS, legal.handler({ id: 'wiki', service: 'wiki', host: 'openvibe.wiki', name: 'OpenVibe.Wiki', profile: 'ugc' })); }
app.get('/api/health', (_req, res) => res.json({ status: 'ok', service: 'openvibe-wiki', version: VERSION }));
-- app.get('/release.json', release.handler);
++ // GET /release.json (ADR-016) and POST /release-metrics: open tabs' update reports into /metrics.
++ release.mount(app, { registry: metrics.registry });
const ready = createReadiness({
service: 'wiki', release: release.release,
checks: [
ddiff --git a/test/auth.test.js b/test/auth.test.js
iindex 31ecca1..929e2bd 100644
---- a/test/auth.test.js
++++ b/test/auth.test.js
@@@ -68,6 +68,11 @@ const { sanitizeNext } = require('../server/auth/session');
const ready = await H.req(h, 'GET', '/api/ready');
assert.strictEqual(ready.status, 200);
assert.strictEqual(ready.json.checks.db.status, 'ok');
++ // The release manifest (registry.release-manifest@1) names where open tabs report updates.
++ const rel = await H.req(h, 'GET', '/release.json');
++ assert.strictEqual(rel.json.service, 'wiki');
++ assert.deepStrictEqual(require('openvibe-contracts').validate('registry.release-manifest@1', rel.json).errors, []);
++ assert.strictEqual(rel.json.metrics_url, '/release-metrics');
console.log('auth ok');
} finally {
await h.stop();
ddiff --git a/test/helpers.js b/test/helpers.js
iindex 8a82965..91e992b 100644
---- a/test/helpers.js
++++ b/test/helpers.js
@@@ -22,10 +22,14 @@ function userToken({ subject: sub = subject(), username = 'someone', role = 'use
return serviceAuth.signServiceToken({ iss: issuer, aud, sub: 42, id: 42, subject_id: sub, username, display_name: username, role, iat: now, exp: now + exp }, privateKey);
}
--/** A principal token: svc:<client> by default; `sub` + `actorType` for an app:/mod: principal, `extra` for on_behalf_of, env… */
++/**
++ * A principal token: svc:<client> by default; `sub` + `actorType` for an app:/mod: principal, `extra` for on_behalf_of, env…
++ * An app token carries its developer project and env, as Network's do (identity.service-token-claims 1.2.0).
++ */
function serviceToken({ client = 'ai', cap = [], aud = 'openvibe.wiki', exp = 300, sub, actorType = 'service', extra = {} } = {}) {
const now = Math.floor(Date.now() / 1000);
-- return serviceAuth.signServiceToken({ iss: ISSUER, sub: sub || `svc:${client}`, actor_type: actorType, aud: [aud], cap, ns: [], iat: now, exp: now + exp, jti: `tok_${crypto.randomBytes(8).toString('hex')}`, ...extra }, privateKey);
++ const app = actorType === 'app' ? { project_id: 'prj_01J8ZQ4Y7N3M2K1H0G9F8E7D6C', env: 'production' } : {};
++ return serviceAuth.signServiceToken({ iss: ISSUER, sub: sub || `svc:${client}`, actor_type: actorType, aud: [aud], cap, ns: [], iat: now, exp: now + exp, jti: `tok_${crypto.randomBytes(8).toString('hex')}`, ...app, ...extra }, privateKey);
}
const quiet = { log() {}, warn() {}, error() {} };