openvibers/openvibe.work Commits

Ingest: a listing with a one-letter title or company is a board's test post (#133)

OP OpenVibers committed 14 days ago · f61d4774fd · 2 files, +9 −1

RemoteOK carried three "z at y" listings on 2026-10-30, and the network's home
showed them as new jobs. A title or a company with fewer than two letters is now
refused like a listing with no link back; a short real title (QA) still passes.
The ones already stored expire when they are no longer kept.

Changes

ddiff --git a/server/jobs/sources.js b/server/jobs/sources.js
iindex aacf631..2847bf9 100644
---- a/server/jobs/sources.js
++++ b/server/jobs/sources.js
@@@ -161,11 +161,15 @@ const ids = () => SOURCES.map((s) => s.id);
* with no id, no title, no company or no http(s) URL to link back to — without those a listing has no provenance and
* must not be published. The excerpt is what is stored; the board keeps the full description.
*/
++const letters = (v) => (String(v == null ? '' : v).match(/\p{L}/gu) || []).length;
function toRow(raw, { sourceId, fetchedAt, idOf }) {
// The URL is checked again here even though each parse does it: this is the last gate before anything is stored,
// and a listing without an http(s) link back to its board has no provenance and is not published.
const url = raw && httpUrl(raw.url);
if (!raw || !raw.source_id || !raw.title || !raw.company || !url) return null;
++ // Nor one nobody could act on: a title or a company with fewer than two letters is a board's test post (RemoteOK
++ // carried three "z at y" listings on 2026-10-30, and the network's home showed them as new jobs).
++ if (letters(raw.title) < 2 || letters(raw.company) < 2) return null;
const tags = list(raw.tags);
const row = {
id: idOf(sourceId, raw.source_id),
ddiff --git a/test/ingest.test.js b/test/ingest.test.js
iindex d9a7088..190d069 100644
---- a/test/ingest.test.js
++++ b/test/ingest.test.js
@@@ -176,10 +176,14 @@ const DAY = 86_400_000;
await check('a page that is not a listing is refused rather than published', async () => {
// A row with no URL to link back to, or a URL that is not http(s), has no provenance: it is not kept.
const { toRow } = require('../server/jobs/sources');
-- const base = { source_id: 'x', title: 't', company: 'c', url: 'https://example.org/x', tags: [], description_html: '<p>hi</p>' };
++ const base = { source_id: 'x', title: 'Tester', company: 'Acme', url: 'https://example.org/x', tags: [], description_html: '<p>hi</p>' };
assert.strictEqual(toRow({ ...base, url: 'javascript:alert(1)' }, { sourceId: 'remotive', fetchedAt: 'x', idOf: store.idOf }), null);
assert.strictEqual(toRow({ ...base, url: null }, { sourceId: 'remotive', fetchedAt: 'x', idOf: store.idOf }), null);
assert.strictEqual(toRow({ ...base, title: '' }, { sourceId: 'remotive', fetchedAt: 'x', idOf: store.idOf }), null);
++ // A board's test post ("z at y") is not a listing; a short real title ("QA at Acme") still is.
++ assert.strictEqual(toRow({ ...base, title: 'z', company: 'y' }, { sourceId: 'remoteok', fetchedAt: 'x', idOf: store.idOf }), null);
++ assert.strictEqual(toRow({ ...base, company: '1' }, { sourceId: 'remoteok', fetchedAt: 'x', idOf: store.idOf }), null);
++ assert.ok(toRow({ ...base, title: 'QA' }, { sourceId: 'remoteok', fetchedAt: 'x', idOf: store.idOf }), 'two letters is a title');
const row = toRow(base, { sourceId: 'remotive', fetchedAt: '2026-10-01T00:00:00.000Z', idOf: store.idOf });
assert.strictEqual(row.sort_at, '2026-10-01T00:00:00.000Z', 'a listing with no date sorts by when we read it');
});