openvibers/openvibe.wiki Commits

Keep Wiki up when INDEXNOWKEY is invalid and warn instead

OP OpenVibers committed 4 Oct 2026 · d1bf414bb7 · 4 files, +26 −2

Asked: Follow-up of https://github.com/OpenVibers/OpenVibe.Search/pull/10 (Serve /llms-full.txt route index and the IndexNow key file): its review asked for a change in OpenVibe.Wiki that the PR cannot make from OpenVibe.Search. The review said: ## Review complete
Harness job wiki-follow-up-of-https-github-com-openv-222747.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 5b24e47..9dc4fe9 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -3,3 +3,4 @@
## Unreleased
- Every page is rendered through `openvibe-publishing/layout` (`openvibe-shared/shell` page()) instead of a local template: the same head tags, stylesheets, feed links, app icon and Frame, with robots still explicit on every page (the gate's decision on an article, a string elsewhere); `openvibe-shared` v2.5.0 → v2.6.0 and `openvibe-publishing` v1.1.0 → v1.2.0, and the JS size budgets rise by the shell's `web-runtime.js` (5 files, 245 KB raw, 59 KB brotli).
++- A set-but-invalid `INDEXNOW_KEY` (not 8–128 hex/alnum) no longer crashes the service at boot: Wiki logs a warning and serves with IndexNow off, exactly as when the key is unset.
ddiff --git a/README.md b/README.md
iindex 8225f92..c309df7 100644
---- a/README.md
++++ b/README.md
@@@ -132,7 +132,8 @@ records who attached each Media object and what Media said about it at that mome
unpublishing and deleting a public, indexable page pings `api.indexnow.org` with the page's
canonical URL and `/sitemap.xml` (the module batches and debounces; a failed ping never takes a
publish down). Drafts, private, members, VIP and noindex pages never ping. Unset: off — no key
-- file, no requests.
++ file, no requests. A key that is not 8–128 hex or alphanumeric is refused by the module: Wiki
++ warns and runs with IndexNow off rather than failing to start.
- **The gate**: `openvibe-publishing/seo` decides indexing per page with explicit reasons
(policy: at least `WIKI_GATE_MIN_WORDS` words and `WIKI_GATE_MIN_SOURCES` citations; AI text and
AI-assisted imports only after a person's review; owner-requested noindex). Only public, published, indexable pages enter sitemaps and
ddiff --git a/server/index.js b/server/index.js
iindex 342dc1b..b3aa080 100644
---- a/server/index.js
++++ b/server/index.js
@@@ -49,7 +49,18 @@ async function start({ config, db: givenDb = null, now = () => Date.now(), fetch
// IndexNow (openvibe-shared/indexnow): created once at boot from INDEXNOW_KEY. Unset → off, nothing
// mounted and nothing sent; a test or a drill injects its own (a spy, or the module's own no-key
// state) through `indexnow`, and the outbound POST goes through `fetchImpl`, this process's stub.
-- const indexnow = givenIndexNow || createIndexNow({ host: config.baseUrl, key: config.indexnow.key, fetch: fetchImpl, log: (...a) => (log.warn || console.warn)(...a) });
++ // A set-but-invalid key (the module refuses anything but 8–128 hex/alnum) is a configuration
++ // mistake, not a reason to leave the wiki down: warn and run with IndexNow off, exactly as unset.
++ let indexnow = givenIndexNow;
++ if (!indexnow) {
++ const logIndexNow = (...a) => (log.warn || console.warn)(...a);
++ try {
++ indexnow = createIndexNow({ host: config.baseUrl, key: config.indexnow.key, fetch: fetchImpl, log: logIndexNow });
++ } catch (err) {
++ logIndexNow(`[Wiki] ${err.message} — IndexNow is off until INDEXNOW_KEY is fixed`);
++ indexnow = createIndexNow({ host: config.baseUrl, key: '', fetch: fetchImpl, log: logIndexNow });
++ }
++ }
// Valkey (ADR-035): shared, never-authoritative state (per-actor limit counters). Optional.
const valkey = config.valkey.url ? require('openvibe-sdk/valkey').createValkey({ url: config.valkey.url, prefix: config.valkey.prefix, log }) : null;
const platform = createPlatform({ config, db, fetchImpl, tokens, now, log });
ddiff --git a/test/indexnow.test.js b/test/indexnow.test.js
iindex f593918..7c435a4 100644
---- a/test/indexnow.test.js
++++ b/test/indexnow.test.js
@@@ -21,6 +21,17 @@ const PAGE = `${BASE}/w/notes/first-light`;
assert.strictEqual((await H.req(off, 'GET', `/${KEY}.txt`)).status, 404, 'no key file is served');
} finally { await off.stop(); }
++ // A set-but-invalid key is a configuration mistake, not a boot failure: the wiki serves, IndexNow
++ // is off, and the mistake is warned about (createIndexNow refuses anything but 8–128 hex/alnum).
++ const warnings = [];
++ const badLog = { log() {}, warn: (m) => warnings.push(String(m)), error() {} };
++ const bad = await H.boot({ env: { BASE_URL: BASE, INDEXNOW_KEY: 'not a key!' }, log: badLog });
++ try {
++ assert.strictEqual(bad.indexnow.enabled, false, 'an invalid key leaves IndexNow off');
++ assert.ok(warnings.some((w) => w.includes('INDEXNOW_KEY')), `the bad key is warned about: ${JSON.stringify(warnings)}`);
++ assert.strictEqual((await H.req(bad, 'GET', `/${KEY}.txt`)).status, 404, 'no key file is served for an invalid key');
++ } finally { await bad.stop(); }
++
// With a key: the key file is served as text/plain with the key.
const on = await H.boot({ env: { BASE_URL: BASE, INDEXNOW_KEY: KEY } });
try {