openvibers/openvibe.codes 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 · e5a6280382 · 8 files, +31 −28

- /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-ops.test.js validates the served manifest against the
  contracts.
- The generated docs now come from contracts v0.32.0 and SDK v0.5.0: the docs test pins those tags
  (the tag and the package version agree again, so pages no longer say they differ); README and
  STATUS list the new pins.
- Contracts 0.28.0 -> 0.32.0 and SDK 0.4.0 -> 0.5.0 are additive for Codes; the contracts check
  passes.

Changes

ddiff --git a/README.md b/README.md
iindex b6d8193..d7f9c18 100644
---- a/README.md
++++ b/README.md
@@@ -47,7 +47,7 @@ Everything is server-rendered and usable without JavaScript. The only scripts of
- **OpenVibe.Network** — SSO (OAuth client `codes`, PKCE S256), JWKS, `/api/v1/projects` (called server-side with the person's Network access token), the registry (`/api/v1/registry/services`, `/.well-known/openvibe`), client-credentials tokens (Codes' own for the events relay; the app's own in playgrounds).
- **OpenVibe.Events** — the outbox relay publishes `codes.app.*` with Codes' service token (`events.event.publish`); the Events playground calls it with the app's token (`events.app.publish`).
- **OpenVibe.Media** — the Media playground uploads with the app's token into the project's namespace.
--- **openvibe-contracts** tag v0.27.0 (its package.json says 0.28.0; the docs show both), **openvibe-sdk v0.4.0**, **openvibe-shared v1.3.0** (pinned tag tarballs).
++- **openvibe-contracts** v0.32.0, **openvibe-sdk v0.5.0**, **openvibe-shared v1.5.0** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).
No path in Codes sends or accepts a shared loopback key (tested by grep and at runtime).
@@@ -58,7 +58,7 @@ In Network (`server/identity/principals.js` / `server/db/database.js`, as for co
- OAuth client `codes`, name `OpenVibe.Codes`, redirect URI `https://openvibe.codes/auth/callback`.
- Service grant `['codes', 'events.event.publish', 'openvibe.events', []]` (the outbox relay).
--The Codes service manifest, `codes.release.manage|read` and `codes.app-manifest@1` are released in openvibe-contracts (tag v0.27.0; this repository pins v0.28.0, same content); the CI contracts check is blocking.
++The Codes service manifest, `codes.release.manage|read` and `codes.app-manifest@1` are released in openvibe-contracts (tag v0.27.0; this repository pins v0.32.0); the CI contracts check is blocking.
For the playgrounds to succeed end to end (not Codes' code; configuration elsewhere): Network `DEV_SANDBOX_AUDIENCES` including `openvibe.media` and `openvibe.events`, a staff-set allowance containing `media.object.upload` and `events.app.publish` for the project, a Media tenant keyed by the project id, and OpenVibe.Events serving `events.app.publish` for app tokens. On 2026-09-23 these were in place on production: a sandbox app uploaded to Media (tenant `prj_…-sandbox`) and published and read app events through public endpoints. That run used curl, not the Codes playgrounds, and it is not yet a committed, repeatable check.
ddiff --git a/STATUS.json b/STATUS.json
iindex 83cf8ee..63dfb63 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -8,9 +8,9 @@
"port": 4900,
"domain": "openvibe.codes",
"packages": [
-- "openvibe-contracts v0.28.0 (same content as tag v0.27.0; the latest contracts release is v0.29.0)",
-- "openvibe-sdk v0.4.0",
-- "openvibe-shared v1.3.0"
++ "openvibe-contracts v0.32.0",
++ "openvibe-sdk v0.5.0",
++ "openvibe-shared v1.5.0"
],
"summary": "Deployed and public since 2026-09-23: https://openvibe.codes is served by this portal (openvibe-ovh, unit openvibe-codes on 127.0.0.1:4900 behind nginx, release a9371c3), and the domain left OpenVibe.Sites. Sign-in uses the registered Network OAuth client `codes` (PKCE S256); the principal `codes` holds events.event.publish and the Events relay is configured. It is barely used yet: production holds 0 manifests, 0 releases and 0 playground runs. The external-developer path (account, project, sandbox app, grants, Media upload, app events) was run once on production on 2026-09-23 with public endpoints and curl, not through these playgrounds; that check is not committed to a repository or CI.",
"works": [
ddiff --git a/package-lock.json b/package-lock.json
iindex a352c97..2c17af0 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -16,9 +16,9 @@
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.28.0",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.4.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0"
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.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"
@@@ -1023,9 +1023,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.28.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.28.0",
-- "integrity": "sha512-cOOEmIhcjDmnWbo4jsz6kYOKT+Kc+aitYoc4w/EJOKg5uvJDt10vctjKB3IIl53UXeuDOhbckP53yBdBeewC1A==",
++ "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",
@@@ -1039,18 +1039,18 @@
}
},
"node_modules/openvibe-sdk": {
-- "version": "0.4.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.4.0",
-- "integrity": "sha512-Hyz55YOMIs0xwCQ1NXsN0sUYhlbKXAX3uWY2fPCdEEL18FXUYVhK8wlG/5JMMypFHnjDiSd9VHzBNG12hWsmkQ==",
++ "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 a553eac..6af6498 100644
---- a/package.json
++++ b/package.json
@@@ -27,9 +27,9 @@
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.28.0",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.4.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0"
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.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 c2a3037..5e5728f 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -95,7 +95,8 @@ function createApp(opts = {}) {
// ── Machine endpoints ───────────────────────────────────
app.get('/api/health', (_req, res) => res.json({ status: 'ok', service: 'openvibe-codes', 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 readiness = createCodesReadiness({ store, keys, network, outbox, docs, config, release: release.release });
app.get('/api/ready', readiness.handler);
ddiff --git a/test/auth-ops.test.js b/test/auth-ops.test.js
iindex e9e346b..8cf4de1 100644
---- a/test/auth-ops.test.js
++++ b/test/auth-ops.test.js
@@@ -85,6 +85,8 @@ const { boot, check, done } = require('./helpers/boot');
const rel = await t.get('/release.json');
assert.strictEqual(rel.status, 200);
assert.strictEqual(rel.json().service, 'codes');
++ assert.deepStrictEqual(require('openvibe-contracts').validate('registry.release-manifest@1', rel.json()).errors, []);
++ assert.strictEqual(rel.json().metrics_url, '/release-metrics');
const m = await t.get('/metrics');
assert.strictEqual(m.status, 200);
assert.match(m.text, /http_requests_total|release_info/);
ddiff --git a/test/contracts.test.js b/test/contracts.test.js
iindex 79aafcd..938c511 100644
---- a/test/contracts.test.js
++++ b/test/contracts.test.js
@@@ -1,6 +1,6 @@
'use strict';
/**
-- * The released contracts (openvibe-contracts tag v0.28.0) describe what the code does: the codes
++ * The released contracts (openvibe-contracts tag v0.32.0) describe what the code does: the codes
* service manifest's events are exactly what the outbox can produce, its capabilities are the ones
* the API guards with requireCapability, and the release API answers with the contracts' problems.
*/
ddiff --git a/test/docs.test.js b/test/docs.test.js
iindex 2710600..24d3329 100644
---- a/test/docs.test.js
++++ b/test/docs.test.js
@@@ -19,11 +19,11 @@ const sdkPkg = require('openvibe-sdk/package.json');
await check('package.json pins the contracts, SDK and shared tags that are installed', async () => {
const tag = (dep) => (pkg.dependencies[dep].match(/refs\/tags\/(v[0-9.]+)$/) || [])[1];
-- assert.strictEqual(tag('openvibe-contracts'), 'v0.28.0');
++ assert.strictEqual(tag('openvibe-contracts'), 'v0.32.0');
assert.strictEqual(tag('openvibe-sdk'), `v${sdkPkg.version}`);
assert.strictEqual(tag('openvibe-shared'), `v${require('openvibe-shared/package.json').version}`);
-- assert.strictEqual(sdkPkg.version, '0.4.0');
-- // The contracts tag v0.28.0 carries the released codes manifest and codes.app-manifest@1.
++ assert.strictEqual(sdkPkg.version, '0.5.0');
++ // The contracts tag v0.32.0 carries the released codes manifest and codes.app-manifest@1.
assert.ok(contracts.services.get('codes') && contracts.services.get('codes').status === 'alpha');
assert.ok(contracts.resolve('codes.app-manifest@1'));
});
@@@ -33,13 +33,13 @@ const sdkPkg = require('openvibe-sdk/package.json');
const r = await t.get(p);
assert.strictEqual(r.status, 200, p);
assert.ok(r.text.includes(`openvibe-contracts v${contractsVersion}`), `${p} names the installed contracts version`);
-- assert.ok(r.text.includes('OpenVibe.Contracts/tree/v0.28.0'), `${p} links the pinned tag`);
-- if (contractsVersion !== '0.28.0') assert.ok(r.text.includes('(tag v0.28.0)'), `${p} says the tag differs from the package version`);
++ assert.ok(r.text.includes('OpenVibe.Contracts/tree/v0.32.0'), `${p} links the pinned tag`);
++ if (contractsVersion !== '0.32.0') assert.ok(r.text.includes('(tag v0.32.0)'), `${p} says the tag differs from the package version`);
assert.ok(r.text.includes(`openvibe-sdk v${sdkPkg.version}`), `${p} names the SDK version`);
}
const v = (await t.get('/api/v1/docs/versions')).json();
assert.strictEqual(v.contracts, contractsVersion);
-- assert.strictEqual(v.contracts_tag, 'v0.28.0');
++ assert.strictEqual(v.contracts_tag, 'v0.32.0');
assert.strictEqual(v.sdk, sdkPkg.version);
});