openvibers/openvibe.sources Commits

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

OP OpenVibers committed 23 Sept 2026 · 1d591a1752 · 6 files, +22 −13

- /release.json is mounted with release.mount(app, { registry }), which also answers POST
  /release-metrics (release_client_updates_total in /metrics; Sources has no tabs and nginx
  proxies no such path). On contracts 0.32.0 the manifest carries the release-manifest 1.1.0
  fields; no components are declared. The observability test validates the served manifest
  against the contracts.
- Contracts 0.13.0 -> 0.32.0 is additive for Sources (sources.item.*, sources.fetch.failed and
  sources.index_document.* payload contracts since 0.30.0); the tests and the contracts check pass
  unchanged.

Changes

ddiff --git a/README.md b/README.md
iindex 285f369..e153f6f 100644
---- a/README.md
++++ b/README.md
@@@ -126,7 +126,7 @@ Callers use an OpenVibe.Network client-credentials token for audience `openvibe.
`GET /api/v1/items` pages in change order (creations, revisions and — with `include_removed=1` —
removals); resume from `next_after`. Every page carries the status and staleness of the sources
it contains. The capability ids (first proposed in [docs/capabilities-proposal/](docs/capabilities-proposal/))
--are released in `openvibe-contracts` v0.12.0 (this repo pins v0.13.0); [server/auth.js](server/auth.js)
++are released in `openvibe-contracts` v0.12.0 (this repo pins v0.32.0); [server/auth.js](server/auth.js)
decides them with the contracts grant rule.
## Events (transactional outbox → OpenVibe.Events when `EVENTS_URL` is set)
ddiff --git a/STATUS.json b/STATUS.json
iindex daaea10..7093ce8 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,7 +7,7 @@
"runtime": "node 22, express, better-sqlite3, fast-xml-parser",
"port": 4720,
"domain": "sources.openvibe.network (vhost in deploy/nginx, not installed: until it is, the name falls through to the admin.openvibe.network placeholder; once installed it answers an internal-service page, health and JSON 404s, API loopback-only; README \"Public host\")",
-- "contracts": "openvibe-contracts v0.13.0",
++ "contracts": "openvibe-contracts v0.32.0",
"capabilities": ["sources.source.read", "sources.item.read", "sources.source.manage"],
"capabilitiesRegistered": true,
"contractsProposed": ["sources.source@1 (released in openvibe-contracts v0.12.0)", "sources.item@1 (released in openvibe-contracts v0.12.0)"],
ddiff --git a/package-lock.json b/package-lock.json
iindex ff41977..a70e1b3 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -13,8 +13,8 @@
"dotenv": "^16.4.7",
"express": "^4.21.2",
"fast-xml-parser": "^4.5.3",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.13.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-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0"
},
"devDependencies": {
"ajv": "^8.20.0",
@@@ -990,9 +990,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.13.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.13.0",
-- "integrity": "sha512-MeIGJYHQsbr6ISeEErduUw/PD52X5IBclH2ht/G/t4lSX5X4o2AwcZYLEzOZrcbaXQyplgC7r86RCGFvi1ifUA==",
++ "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",
@@@ -1006,9 +1006,9 @@
}
},
"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 3f1625b..bbc3ae5 100644
---- a/package.json
++++ b/package.json
@@@ -27,8 +27,8 @@
"dotenv": "^16.4.7",
"express": "^4.21.2",
"fast-xml-parser": "^4.5.3",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.13.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-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 55d790a..ad152b3 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -87,7 +87,8 @@ function createApp({ config, db, registry, items, ingest, scheduler, auth, keys,
// fetcher (worker running, queue keeping up) are optional and degrade it (see observability.js).
const readiness = createSourcesReadiness({ db, keys, config, registry, ingest, scheduler, outbox, relay, now, release: release.release });
app.get('/api/ready', readiness.handler);
-- 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 });
app.use(sourcesRouter({ db, registry, ingest, auth }));
app.use(itemsRouter({ db, registry, items, auth, relay, now }));
ddiff --git a/test/observability.test.js b/test/observability.test.js
iindex fef1312..8ec4a78 100644
---- a/test/observability.test.js
++++ b/test/observability.test.js
@@@ -77,6 +77,14 @@ t('/metrics: 404 through a proxy; route templates and Sources gauges direct', as
assert.ok(/\nsources_outbox_pending \d+\n/.test(text));
});
++t('/release.json: a registry.release-manifest@1 that names where tabs report updates', async () => {
++ const r = await request(svc.base, 'GET', '/release.json');
++ assert.strictEqual(r.status, 200, r.text);
++ assert.strictEqual(r.body.service, 'sources');
++ assert.deepStrictEqual(require('openvibe-contracts').validate('registry.release-manifest@1', r.body).errors, []);
++ assert.strictEqual(r.body.metrics_url, '/release-metrics');
++});
++
t('a broken database makes the service unready (503); /metrics still answers', async () => {
svc.db.close();
const r = await request(svc.base, 'GET', '/api/ready');