openvibers/openvibe.help Commits
openvibe-contracts v0.205.2 (was v0.205.1) (#69)
Changes
@@@ -279,7 +279,7 @@ Reporting a vulnerability: [SECURITY.md](SECURITY.md).Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).<!-- versions:start -->--- openvibe-contracts: v0.205.1++- openvibe-contracts: v0.205.2- openvibe-sdk: v0.50.1- openvibe-shared: v4.4.0- openvibe-publishing: v1.4.0@@@ -7,11 +7,11 @@"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db, async) + Valkey 9","port": "5020","domain": "openvibe.help",-- "contracts": "openvibe-contracts v0.205.1",++ "contracts": "openvibe-contracts v0.205.2","sdk": "openvibe-sdk v0.50.1","shared": "openvibe-shared v4.4.0","packages": [-- "openvibe-contracts v0.205.1",++ "openvibe-contracts v0.205.2","openvibe-sdk v0.50.1","openvibe-shared v4.4.0","openvibe-publishing v1.4.0"@@@ -55,5 +55,5 @@"deploy files"],"deployment": "openvibe-ovh: unit openvibe-help.service on 127.0.0.1:5020 (git checkout /opt/openvibe.help, env /etc/openvibe/help.env, database ov_help), deployed with `sudo ovhost deploy help`; public at https://openvibe.help since 2026-10-08.",-- "updated": "2026-10-18"++ "updated": "2026-10-19"}@@@ -15,7 +15,7 @@"express-rate-limit": "^7.5.0","helmet": "^8.1.0","iovalkey": "^0.4.0",-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.1",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.2","openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.50.1","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.4.0",@@@ -872,9 +872,9 @@}},"node_modules/openvibe-contracts": {-- "version": "0.205.1",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.1",-- "integrity": "sha512-pWkrBgkGRxFEns3x1TKegnyI49FR62Hz+5kzJpTyCiGnJZ2BIQgzMfvSGHAoRGJqyzLixmyAE1X4u30K5Kl0fQ==",++ "version": "0.205.2",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.2",++ "integrity": "sha512-IG2/+Ut+BKb9Vb4WfaLsBmg4xw9GwcYqpAAA5l/mzNpd2uXHcretXtOp7xS1ZwKRQu/ZI5ragyJ4dWAI2q4Btg==","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -22,7 +22,7 @@"express-rate-limit": "^7.5.0","helmet": "^8.1.0","iovalkey": "^0.4.0",-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.1",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.2","openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.50.1","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.4.0",@@@ -89,7 +89,7 @@ function createPageRoutes(ctx) {actions: signedIn(req)? [{ label: 'Your tickets', href: '/tickets' }, { label: 'Open a ticket', href: '/tickets/new', primary: true }]: [{ label: 'Search the answers', href: '#search', primary: true }, { label: 'Sign in to open a ticket', href: '/auth/login?next=%2Ftickets%2Fnew' }],-- note: `Open source (AGPL-3.0). ${catalog.sites.length} sites in the catalog: ${live.length} live, ${catalog.sites.length - live.length} still coming.`,++ note: `Open source (AGPL-3.0). ${catalog.sites.length} sites in the catalog${live.length === catalog.sites.length ? ', every one live' : `: ${live.length} live, ${catalog.sites.length - live.length} still coming`}.`,});page(req, res, {index: true, cache: signedIn(req) ? null : PUBLIC_CACHE,@@@ -132,7 +132,7 @@ ${raw(showcase.cta({ title: 'What shipped on OpenVibe.Help', text: 'The update lseo.jsonLd.itemList('OpenVibe sites', catalog.sites.map((x) => ({ name: x.name, url: `${base()}/sites/${x.id}`, description: x.oneLine })), { url: `${base()}/sites` }),],body: html`<h1>Every OpenVibe site</h1>--<p class="sc-lede">${catalog.sites.length} addresses, ${catalog.sites.filter((x) => x.live).length} of them live. The state is the service manifest's own <code>exposure.state</code>: a site is live when a service exposes it live. Everything else on this page is that site's manifest, word for word.</p>++<p class="sc-lede">${catalog.sites.length} addresses, ${catalog.sites.every((x) => x.live) ? 'every one live' : `${catalog.sites.filter((x) => x.live).length} of them live`}. The state is the service manifest's own <code>exposure.state</code>: a site is live when a service exposes it live. Everything else on this page is that site's manifest, word for word.</p>${provenance(catalog.source)}${group('live', 'Live', 'These answer today.')}${group('coming', 'Coming', 'Registered in the catalog, not serving yet, or serving something else for now.')}`,@@@ -14,7 +14,7 @@ const siteDomain = contracts.products.siteDomain;const PRODUCTS = contracts.products.manifests;const SERVICE_SITES = contracts.services.manifests.filter((m) => m.site);const WITH_FAQ = [-- ...PRODUCTS.filter((p) => Array.isArray(p.faq) && p.faq.length).map((p) => ({ domain: p.domain, faq: p.faq, name: p.name })),++ ...PRODUCTS.filter((p) => !p.kind && Array.isArray(p.faq) && p.faq.length).map((p) => ({ domain: p.domain, faq: p.faq, name: p.name })),...SERVICE_SITES.filter((m) => Array.isArray(m.site.faq) && m.site.faq.length).map((m) => ({ domain: siteDomain(m), faq: m.site.faq, name: m.site.name })),];@@@ -51,7 +51,7 @@ const WITH_FAQ = [if (m.site && m.site.tld) live.add(siteDomain(m));}for (const s of catalog.sites) assert.strictEqual(s.state, live.has(s.id) ? 'live' : 'coming', `${s.id}: ${s.state}`);-- assert.ok(catalog.sites.some((s) => s.state === 'live') && catalog.sites.some((s) => s.state === 'coming'));++ assert.ok(catalog.sites.some((s) => s.state === 'live'));// Ordered live first, so a reader meets the working sites first.const first = catalog.sites.findIndex((s) => s.state === 'coming');if (first !== -1) assert.ok(catalog.sites.slice(first).every((s) => s.state === 'coming'), 'live and coming sites are interleaved');
@@ -279,7 +279,7 @@ Reporting a vulnerability: [SECURITY.md](SECURITY.md).
@@ -279,7 +279,7 @@ Reporting a vulnerability: [SECURITY.md](SECURITY.md).
Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).
Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).
<!-- versions:start -->
<!-- versions:start -->
-- openvibe-contracts: v0.205.1
+- openvibe-contracts: v0.205.2
- openvibe-sdk: v0.50.1
- openvibe-sdk: v0.50.1
- openvibe-shared: v4.4.0
- openvibe-shared: v4.4.0
- openvibe-publishing: v1.4.0
- openvibe-publishing: v1.4.0
@@ -7,11 +7,11 @@
@@ -7,11 +7,11 @@
"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db, async) + Valkey 9",
"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db, async) + Valkey 9",
"port": "5020",
"port": "5020",
"domain": "openvibe.help",
"domain": "openvibe.help",
- "contracts": "openvibe-contracts v0.205.1",
+ "contracts": "openvibe-contracts v0.205.2",
"sdk": "openvibe-sdk v0.50.1",
"sdk": "openvibe-sdk v0.50.1",
"shared": "openvibe-shared v4.4.0",
"shared": "openvibe-shared v4.4.0",
"packages": [
"packages": [
- "openvibe-contracts v0.205.1",
+ "openvibe-contracts v0.205.2",
"openvibe-sdk v0.50.1",
"openvibe-sdk v0.50.1",
"openvibe-shared v4.4.0",
"openvibe-shared v4.4.0",
"openvibe-publishing v1.4.0"
"openvibe-publishing v1.4.0"
@@ -55,5 +55,5 @@
@@ -55,5 +55,5 @@
"deploy files"
"deploy files"
],
],
"deployment": "openvibe-ovh: unit openvibe-help.service on 127.0.0.1:5020 (git checkout /opt/openvibe.help, env /etc/openvibe/help.env, database ov_help), deployed with `sudo ovhost deploy help`; public at https://openvibe.help since 2026-10-08.",
"deployment": "openvibe-ovh: unit openvibe-help.service on 127.0.0.1:5020 (git checkout /opt/openvibe.help, env /etc/openvibe/help.env, database ov_help), deployed with `sudo ovhost deploy help`; public at https://openvibe.help since 2026-10-08.",
- "updated": "2026-10-18"
+ "updated": "2026-10-19"
}
}
@@ -15,7 +15,7 @@
@@ -15,7 +15,7 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.1",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.2",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.50.1",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.50.1",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.4.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.4.0",
@@ -872,9 +872,9 @@
@@ -872,9 +872,9 @@
}
}
},
},
"node_modules/openvibe-contracts": {
"node_modules/openvibe-contracts": {
- "version": "0.205.1",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.1",
- "integrity": "sha512-pWkrBgkGRxFEns3x1TKegnyI49FR62Hz+5kzJpTyCiGnJZ2BIQgzMfvSGHAoRGJqyzLixmyAE1X4u30K5Kl0fQ==",
+ "version": "0.205.2",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.2",
+ "integrity": "sha512-IG2/+Ut+BKb9Vb4WfaLsBmg4xw9GwcYqpAAA5l/mzNpd2uXHcretXtOp7xS1ZwKRQu/ZI5ragyJ4dWAI2q4Btg==",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -22,7 +22,7 @@
@@ -22,7 +22,7 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.1",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.205.2",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.50.1",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.50.1",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.4.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.4.0",
@@ -89,7 +89,7 @@ function createPageRoutes(ctx) {
@@ -89,7 +89,7 @@ function createPageRoutes(ctx) {
actions: signedIn(req)
actions: signedIn(req)
? [{ label: 'Your tickets', href: '/tickets' }, { label: 'Open a ticket', href: '/tickets/new', primary: true }]
? [{ label: 'Your tickets', href: '/tickets' }, { label: 'Open a ticket', href: '/tickets/new', primary: true }]
: [{ label: 'Search the answers', href: '#search', primary: true }, { label: 'Sign in to open a ticket', href: '/auth/login?next=%2Ftickets%2Fnew' }],
: [{ label: 'Search the answers', href: '#search', primary: true }, { label: 'Sign in to open a ticket', href: '/auth/login?next=%2Ftickets%2Fnew' }],
- note: `Open source (AGPL-3.0). ${catalog.sites.length} sites in the catalog: ${live.length} live, ${catalog.sites.length - live.length} still coming.`,
+ note: `Open source (AGPL-3.0). ${catalog.sites.length} sites in the catalog${live.length === catalog.sites.length ? ', every one live' : `: ${live.length} live, ${catalog.sites.length - live.length} still coming`}.`,
});
});
page(req, res, {
page(req, res, {
index: true, cache: signedIn(req) ? null : PUBLIC_CACHE,
index: true, cache: signedIn(req) ? null : PUBLIC_CACHE,
@@ -132,7 +132,7 @@ ${raw(showcase.cta({ title: 'What shipped on OpenVibe.Help', text: 'The update l
@@ -132,7 +132,7 @@ ${raw(showcase.cta({ title: 'What shipped on OpenVibe.Help', text: 'The update l
seo.jsonLd.itemList('OpenVibe sites', catalog.sites.map((x) => ({ name: x.name, url: `${base()}/sites/${x.id}`, description: x.oneLine })), { url: `${base()}/sites` }),
seo.jsonLd.itemList('OpenVibe sites', catalog.sites.map((x) => ({ name: x.name, url: `${base()}/sites/${x.id}`, description: x.oneLine })), { url: `${base()}/sites` }),
],
],
body: html`<h1>Every OpenVibe site</h1>
body: html`<h1>Every OpenVibe site</h1>
-<p class="sc-lede">${catalog.sites.length} addresses, ${catalog.sites.filter((x) => x.live).length} of them live. The state is the service manifest's own <code>exposure.state</code>: a site is live when a service exposes it live. Everything else on this page is that site's manifest, word for word.</p>
+<p class="sc-lede">${catalog.sites.length} addresses, ${catalog.sites.every((x) => x.live) ? 'every one live' : `${catalog.sites.filter((x) => x.live).length} of them live`}. The state is the service manifest's own <code>exposure.state</code>: a site is live when a service exposes it live. Everything else on this page is that site's manifest, word for word.</p>
${provenance(catalog.source)}
${provenance(catalog.source)}
${group('live', 'Live', 'These answer today.')}
${group('live', 'Live', 'These answer today.')}
${group('coming', 'Coming', 'Registered in the catalog, not serving yet, or serving something else for now.')}`,
${group('coming', 'Coming', 'Registered in the catalog, not serving yet, or serving something else for now.')}`,
@@ -14,7 +14,7 @@ const siteDomain = contracts.products.siteDomain;
@@ -14,7 +14,7 @@ const siteDomain = contracts.products.siteDomain;
const PRODUCTS = contracts.products.manifests;
const PRODUCTS = contracts.products.manifests;
const SERVICE_SITES = contracts.services.manifests.filter((m) => m.site);
const SERVICE_SITES = contracts.services.manifests.filter((m) => m.site);
const WITH_FAQ = [
const WITH_FAQ = [
- ...PRODUCTS.filter((p) => Array.isArray(p.faq) && p.faq.length).map((p) => ({ domain: p.domain, faq: p.faq, name: p.name })),
+ ...PRODUCTS.filter((p) => !p.kind && Array.isArray(p.faq) && p.faq.length).map((p) => ({ domain: p.domain, faq: p.faq, name: p.name })),
...SERVICE_SITES.filter((m) => Array.isArray(m.site.faq) && m.site.faq.length).map((m) => ({ domain: siteDomain(m), faq: m.site.faq, name: m.site.name })),
...SERVICE_SITES.filter((m) => Array.isArray(m.site.faq) && m.site.faq.length).map((m) => ({ domain: siteDomain(m), faq: m.site.faq, name: m.site.name })),
];
];
@@ -51,7 +51,7 @@ const WITH_FAQ = [
@@ -51,7 +51,7 @@ const WITH_FAQ = [
if (m.site && m.site.tld) live.add(siteDomain(m));
if (m.site && m.site.tld) live.add(siteDomain(m));
}
}
for (const s of catalog.sites) assert.strictEqual(s.state, live.has(s.id) ? 'live' : 'coming', `${s.id}: ${s.state}`);
for (const s of catalog.sites) assert.strictEqual(s.state, live.has(s.id) ? 'live' : 'coming', `${s.id}: ${s.state}`);
- assert.ok(catalog.sites.some((s) => s.state === 'live') && catalog.sites.some((s) => s.state === 'coming'));
+ assert.ok(catalog.sites.some((s) => s.state === 'live'));
// Ordered live first, so a reader meets the working sites first.
// Ordered live first, so a reader meets the working sites first.
const first = catalog.sites.findIndex((s) => s.state === 'coming');
const first = catalog.sites.findIndex((s) => s.state === 'coming');
if (first !== -1) assert.ok(catalog.sites.slice(first).every((s) => s.state === 'coming'), 'live and coming sites are interleaved');
if (first !== -1) assert.ok(catalog.sites.slice(first).every((s) => s.state === 'coming'), 'live and coming sites are interleaved');