openvibers/openvibe.news Commits
openvibe-shared v1.5.0 (Track R release manifest), openvibe-contracts v0.32.0, openvibe-sdk v0.5.0
Changes
@@@ -217,9 +217,9 @@ are the proposals they were released from.## Depends on- **Packages** (pinned by release tarball): `openvibe-publishing` v0.2.1 (revisions, citations,-- authorship, seo, index-hooks, ssr, taxonomy slugify), `openvibe-contracts` v0.21.0,-- `openvibe-shared` v1.3.0 (chrome, app icon, footer, legal, release, metrics, ready, seo),-- `openvibe-sdk` v0.4.0 (events outbox and inbox, webhook signatures v2, service tokens).++ authorship, seo, index-hooks, ssr, taxonomy slugify), `openvibe-contracts` v0.32.0,++ `openvibe-shared` v1.5.0 (chrome, app icon, footer, legal, release, metrics, ready, seo),++ `openvibe-sdk` v0.5.0 (events outbox and inbox, webhook signatures v2, service tokens).- **OpenVibe.Sources** (4720): `sources.item.read`; optionally `sources.source.read` (outletnames and source health; without it the outlet is the URL's host).- **OpenVibe.Events** (4300): `events.event.publish`; `events.subscription.manage` to create the@@@ -7,7 +7,7 @@"runtime": "node 22, express 4, better-sqlite3 11","port": 4820,"domain": "openvibe.news",-- "packages": ["openvibe-publishing v0.2.1", "openvibe-contracts v0.21.0", "openvibe-shared v1.3.0", "openvibe-sdk v0.4.0"],++ "packages": ["openvibe-publishing v0.2.1", "openvibe-contracts v0.32.0", "openvibe-shared v1.5.0", "openvibe-sdk v0.5.0"],"capabilities": ["news.story.create", "news.story.read", "news.story.revise", "news.story.publish", "news.story.retract", "news.cluster.read", "news.cluster.manage", "news.source.attach", "news.timeline.update", "news.perspective.update", "news.topic.manage"],"capabilitiesRegistered": true,"serviceManifestRegistered": true,@@@ -15,10 +15,10 @@"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.21.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.4.0",-- "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"},"devDependencies": {"jsonwebtoken": "^9.0.2"@@@ -1015,9 +1015,9 @@}},"node_modules/openvibe-contracts": {-- "version": "0.21.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.21.0",-- "integrity": "sha512-ckLekaz2IKYmMcapGCeHs85ztxtqr3BGkXXAY/7rQjlzfBHSugSDwsZ/v1SCASG2CnyV/NsRyRojCZWGAB3Gew==",++ "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",@@@ -1060,18 +1060,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"@@@ -22,10 +22,10 @@"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.21.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.4.0",-- "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"},"devDependencies": {"jsonwebtoken": "^9.0.2"@@@ -104,7 +104,8 @@ function createApp(opts = {}) {// ── Machine endpoints ───────────────────────────────────app.get('/api/health', (_req, res) => res.json({ status: 'ok', service: 'openvibe-news', 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 = createNewsReadiness({ store, auth, outbox, ingest, config, release: release.release });app.get('/api/ready', readiness.handler);@@@ -68,8 +68,10 @@ async function startNetwork() {return json(404, { error: 'not found' });});issuer = srv.url;++ // An app token carries its developer project and env, as Network's do (identity.service-token-claims 1.2.0).function signService({ sub, aud, cap, ns, actorType = 'service', extra = {} }) {-- return serviceAuth.signServiceToken({ iss: issuer, sub, actor_type: actorType, aud, cap, ...(ns ? { ns } : {}), iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 300, jti: crypto.randomUUID(), ...extra }, privatePem);++ const app = actorType === 'app' ? { project_id: 'prj_01J8ZQ4Y7N3M2K1H0G9F8E7D6C', env: 'production' } : {};++ return serviceAuth.signServiceToken({ iss: issuer, sub, actor_type: actorType, aud, cap, ...(ns ? { ns } : {}), iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 300, jti: crypto.randomUUID(), ...app, ...extra }, privatePem);}function addUser(username, extra = {}) {const subject = ids.newId('user');@@@ -24,6 +24,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, 'news');++ 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.ok([200, 404].includes(m.status));});
@@ -217,9 +217,9 @@ are the proposals they were released from.
@@ -217,9 +217,9 @@ are the proposals they were released from.
## Depends on
## Depends on
- **Packages** (pinned by release tarball): `openvibe-publishing` v0.2.1 (revisions, citations,
- **Packages** (pinned by release tarball): `openvibe-publishing` v0.2.1 (revisions, citations,
- authorship, seo, index-hooks, ssr, taxonomy slugify), `openvibe-contracts` v0.21.0,
- `openvibe-shared` v1.3.0 (chrome, app icon, footer, legal, release, metrics, ready, seo),
- `openvibe-sdk` v0.4.0 (events outbox and inbox, webhook signatures v2, service tokens).
+ authorship, seo, index-hooks, ssr, taxonomy slugify), `openvibe-contracts` v0.32.0,
+ `openvibe-shared` v1.5.0 (chrome, app icon, footer, legal, release, metrics, ready, seo),
+ `openvibe-sdk` v0.5.0 (events outbox and inbox, webhook signatures v2, service tokens).
- **OpenVibe.Sources** (4720): `sources.item.read`; optionally `sources.source.read` (outlet
- **OpenVibe.Sources** (4720): `sources.item.read`; optionally `sources.source.read` (outlet
names and source health; without it the outlet is the URL's host).
names and source health; without it the outlet is the URL's host).
- **OpenVibe.Events** (4300): `events.event.publish`; `events.subscription.manage` to create the
- **OpenVibe.Events** (4300): `events.event.publish`; `events.subscription.manage` to create the
@@ -7,7 +7,7 @@
@@ -7,7 +7,7 @@
"runtime": "node 22, express 4, better-sqlite3 11",
"runtime": "node 22, express 4, better-sqlite3 11",
"port": 4820,
"port": 4820,
"domain": "openvibe.news",
"domain": "openvibe.news",
- "packages": ["openvibe-publishing v0.2.1", "openvibe-contracts v0.21.0", "openvibe-shared v1.3.0", "openvibe-sdk v0.4.0"],
+ "packages": ["openvibe-publishing v0.2.1", "openvibe-contracts v0.32.0", "openvibe-shared v1.5.0", "openvibe-sdk v0.5.0"],
"capabilities": ["news.story.create", "news.story.read", "news.story.revise", "news.story.publish", "news.story.retract", "news.cluster.read", "news.cluster.manage", "news.source.attach", "news.timeline.update", "news.perspective.update", "news.topic.manage"],
"capabilities": ["news.story.create", "news.story.read", "news.story.revise", "news.story.publish", "news.story.retract", "news.cluster.read", "news.cluster.manage", "news.source.attach", "news.timeline.update", "news.perspective.update", "news.topic.manage"],
"capabilitiesRegistered": true,
"capabilitiesRegistered": true,
"serviceManifestRegistered": true,
"serviceManifestRegistered": true,
@@ -15,10 +15,10 @@
@@ -15,10 +15,10 @@
"express": "^4.21.2",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.21.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-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.4.0",
- "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"
},
},
"devDependencies": {
"devDependencies": {
"jsonwebtoken": "^9.0.2"
"jsonwebtoken": "^9.0.2"
@@ -1015,9 +1015,9 @@
@@ -1015,9 +1015,9 @@
}
}
},
},
"node_modules/openvibe-contracts": {
"node_modules/openvibe-contracts": {
- "version": "0.21.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.21.0",
- "integrity": "sha512-ckLekaz2IKYmMcapGCeHs85ztxtqr3BGkXXAY/7rQjlzfBHSugSDwsZ/v1SCASG2CnyV/NsRyRojCZWGAB3Gew==",
+ "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",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -1060,18 +1060,18 @@
@@ -1060,18 +1060,18 @@
}
}
},
},
"node_modules/openvibe-sdk": {
"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",
"license": "MIT",
"engines": {
"engines": {
"node": ">=20"
"node": ">=20"
}
}
},
},
"node_modules/openvibe-shared": {
"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",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0"
"jsonwebtoken": "^9.0.0"
@@ -22,10 +22,10 @@
@@ -22,10 +22,10 @@
"express": "^4.21.2",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.21.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-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.4.0",
- "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"
},
},
"devDependencies": {
"devDependencies": {
"jsonwebtoken": "^9.0.2"
"jsonwebtoken": "^9.0.2"
@@ -104,7 +104,8 @@ function createApp(opts = {}) {
@@ -104,7 +104,8 @@ function createApp(opts = {}) {
// ── Machine endpoints ───────────────────────────────────
// ── Machine endpoints ───────────────────────────────────
app.get('/api/health', (_req, res) => res.json({ status: 'ok', service: 'openvibe-news', version: VERSION }));
app.get('/api/health', (_req, res) => res.json({ status: 'ok', service: 'openvibe-news', 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 = createNewsReadiness({ store, auth, outbox, ingest, config, release: release.release });
const readiness = createNewsReadiness({ store, auth, outbox, ingest, config, release: release.release });
app.get('/api/ready', readiness.handler);
app.get('/api/ready', readiness.handler);
@@ -68,8 +68,10 @@ async function startNetwork() {
@@ -68,8 +68,10 @@ async function startNetwork() {
return json(404, { error: 'not found' });
return json(404, { error: 'not found' });
});
});
issuer = srv.url;
issuer = srv.url;
+ // An app token carries its developer project and env, as Network's do (identity.service-token-claims 1.2.0).
function signService({ sub, aud, cap, ns, actorType = 'service', extra = {} }) {
function signService({ sub, aud, cap, ns, actorType = 'service', extra = {} }) {
- return serviceAuth.signServiceToken({ iss: issuer, sub, actor_type: actorType, aud, cap, ...(ns ? { ns } : {}), iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 300, jti: crypto.randomUUID(), ...extra }, privatePem);
+ const app = actorType === 'app' ? { project_id: 'prj_01J8ZQ4Y7N3M2K1H0G9F8E7D6C', env: 'production' } : {};
+ return serviceAuth.signServiceToken({ iss: issuer, sub, actor_type: actorType, aud, cap, ...(ns ? { ns } : {}), iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 300, jti: crypto.randomUUID(), ...app, ...extra }, privatePem);
}
}
function addUser(username, extra = {}) {
function addUser(username, extra = {}) {
const subject = ids.newId('user');
const subject = ids.newId('user');
@@ -24,6 +24,8 @@ const { boot, check, done } = require('./helpers/boot');
@@ -24,6 +24,8 @@ const { boot, check, done } = require('./helpers/boot');
const rel = await t.get('/release.json');
const rel = await t.get('/release.json');
assert.strictEqual(rel.status, 200);
assert.strictEqual(rel.status, 200);
assert.strictEqual(rel.json().service, 'news');
assert.strictEqual(rel.json().service, 'news');
+ 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');
const m = await t.get('/metrics');
assert.ok([200, 404].includes(m.status));
assert.ok([200, 404].includes(m.status));
});
});