openvibers/openvibe.search Commits

Search: accept Work, Rent, Help, Inventory and Quest documents (#29)

OP OpenVibers committed 10 Oct 2026 · fbe71b7c6c · 7 files, +28 −8

OpenVibe.Search accepts the record products' documents (Contracts 0.128.0, sent through openvibe-publishing/search-feed): Work (job listings), Rent (rental listings), Help (articles), Inventory (item definitions) and Quest (quests). Plan T9: "Search: real documents from every product".

- `server/config.js`: `work`, `rent`, `help`, `inventory` and `quest` are added to `DEFAULT_EVENT_OWNERS`.
- The front page's "Browse by source" gets a card for each (name and one line, linking to `?owner=`). Their ring icons come with openvibe-shared 2.21.0.
- openvibe-contracts v0.128.0.

**Production note.** `/etc/openvibe/search.env` sets `SEARCH_EVENT_OWNERS` to an older list (sources, wiki, blog, news, reviews, trade, deals, coupons, live, media, community). After this deploys, the override is removed (with a backup) so the code's list governs. That list is a superset: it adds tools, codes and games, which were missing from the override, plus these five.

webhook-inbox has a new check that one document from each of the five owners is applied and found (16/16). `ov test`: green.

Changes

ddiff --git a/README.md b/README.md
iindex 0ee0cb0..f00d5fa 100644
---- a/README.md
++++ b/README.md
@@@ -367,7 +367,7 @@ repository's own vhost serves it.
Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).
<!-- versions:start -->
--- openvibe-contracts: v0.127.0
++- openvibe-contracts: v0.128.0
- openvibe-sdk: v0.35.0
- openvibe-shared: v2.20.4
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex d16b223..8db4400 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,7 +7,7 @@
"runtime": "node 22, express, PostgreSQL full-text search (openvibe-sdk/db)",
"port": 4710,
"domain": "search.openvibe.network (vhost in deploy/nginx; the service manifest records the search page and query API as public since 2026-09-23)",
-- "contracts": "openvibe-contracts v0.127.0",
++ "contracts": "openvibe-contracts v0.128.0",
"sdk": "openvibe-sdk v0.35.0",
"shared": "openvibe-shared v2.20.4",
"capabilities": [
ddiff --git a/package-lock.json b/package-lock.json
iindex a3a4c49..18ae153 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -13,7 +13,7 @@
"ajv-formats": "^3.0.1",
"dotenv": "^16.4.7",
"express": "^4.21.2",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.127.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.128.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.35.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.20.4",
"pg": "^8.23.0"
@@@ -750,9 +750,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.127.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.127.0",
-- "integrity": "sha512-ySC+Qh8I3OlN5MULCqv0vfcAGubZQzWM0Fw7EOpnOo76vVnrkwx+m33aTxDum2yQqPkU8Ot5UtMuMwm1Cc1k3g==",
++ "version": "0.128.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.128.0",
++ "integrity": "sha512-r/WKk3NhdqxEsVxqsVPjg+HTD2So1amRx0BY6EOHhvmwjLuL9j5XJrNDZAfqf/4/P2xZCBzTLrtUqlWxC2EA6Q==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex b911361..e843617 100644
---- a/package.json
++++ b/package.json
@@@ -25,7 +25,7 @@
"ajv-formats": "^3.0.1",
"dotenv": "^16.4.7",
"express": "^4.21.2",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.127.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.128.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.35.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.20.4",
"pg": "^8.23.0"
ddiff --git a/server/config.js b/server/config.js
iindex 74a7f6b..0825956 100644
---- a/server/config.js
++++ b/server/config.js
@@@ -43,7 +43,10 @@ function parseZones(v) {
* sources may feed the index at all. The direct API is decided by the search.document.write grant.
*/
const DEFAULT_EVENT_OWNERS = ['wiki', 'blog', 'news', 'reviews', 'deals', 'coupons', 'trade',
-- 'community', 'live', 'media', 'codes', 'games', 'tools', 'sources'];
++ 'community', 'live', 'media', 'codes', 'games', 'tools', 'sources',
++ // Record products (openvibe-publishing/search-feed, contracts 0.128.0): job listings, rental listings, help
++ // articles, item definitions and quests.
++ 'work', 'rent', 'help', 'inventory', 'quest'];
function load(env = process.env) {
const nodeEnv = env.NODE_ENV || 'development';
ddiff --git a/server/web/page.js b/server/web/page.js
iindex 084dc0b..8fa4e88 100644
---- a/server/web/page.js
++++ b/server/web/page.js
@@@ -199,6 +199,11 @@ const SOURCES = {
games: ['OpenVibe.Games', 'Browser games.'],
tools: ['OpenVibe.Tools', 'Every online tool, by what it does.'],
sources: ['OpenVibe.Sources', 'The registry of news and data sources.'],
++ work: ['OpenVibe.Work', 'Job listings from open boards, each linked to the original.'],
++ rent: ['OpenVibe.Rent', 'Places and things people offer for rent.'],
++ help: ['OpenVibe.Help', 'Answers about every OpenVibe site.'],
++ inventory: ['OpenVibe.Inventory', 'Items, badges and effects you can earn and wear.'],
++ quest: ['OpenVibe.Quest', 'Quests across the network and the badges they give.'],
};
const ICON_OF = { sources: 'docs' };
// The front page's kit sections sit in this page's 760 px column, which already has its gutter.
ddiff --git a/test/webhook-inbox.test.js b/test/webhook-inbox.test.js
iindex 74979bf..b547119 100644
---- a/test/webhook-inbox.test.js
++++ b/test/webhook-inbox.test.js
@@@ -120,6 +120,18 @@ t('unknown owners, subject mismatches and invalid documents are refused', async
assert.strictEqual((await search('sigmaword')).length, 0);
});
++t('the record products are accepted owners: a Work job, a Rent listing, a Help article, an Inventory definition and a Quest', async () => {
++ const docs = [
++ doc({ owner: 'work', type: 'job', id: 'job_0123456789abcdefghjkmnpqrs', canonical_url: 'https://openvibe.work/jobs/job_0123456789abcdefghjkmnpqrs', title: 'Backend engineer recordsword', authorship: 'imported' }),
++ doc({ owner: 'rent', type: 'listing', id: 'rnt_01JAB2C3D4E5F6G7H8J9K0MNPQ', canonical_url: 'https://openvibe.rent/listings/rnt_01JAB2C3D4E5F6G7H8J9K0MNPQ', title: 'Room near the park recordsword' }),
++ doc({ owner: 'help', type: 'article', id: 'openvibe.live:how-do-i-go-live', canonical_url: 'https://openvibe.help/a/openvibe.live/how-do-i-go-live', title: 'How do I go live recordsword' }),
++ doc({ owner: 'inventory', type: 'definition', id: 'itd_01JAB2C3D4E5F6G7H8J9K0MNPQ', canonical_url: 'https://openvibe.inventory/definitions/itd_01JAB2C3D4E5F6G7H8J9K0MNPQ', title: 'Fire Name recordsword' }),
++ doc({ owner: 'quest', type: 'quest', id: 'go-live', canonical_url: 'https://openvibe.quest/quests/go-live', title: 'Go live once recordsword' }),
++ ];
++ for (const d of docs) assert.strictEqual((await deliver(svc.base, indexEvent(d))).body.outcome, 'applied', d.owner);
++ assert.deepStrictEqual((await search('recordsword')).map((r) => r.owner).sort(), ['help', 'inventory', 'quest', 'rent', 'work']);
++});
++
t('events that are not index documents are acknowledged and ignored', async () => {
const e = { ...indexEvent(doc()), event_type: 'wiki.page.published' };
const r = await deliver(svc.base, e);