From 1b11ada112cb8986d171ac9145dbda1c3fbc85a5 Mon Sep 17 00:00:00 2001 From: Schalli Date: Thu, 23 Jul 2026 08:42:23 +0200 Subject: [PATCH] feat(13-02): generalize adapter contract with portals[] array TenderSourceAdapter gains a readonly portals: readonly string[] field so one adapter can serve multiple portals (NetServer: 3, Plan 13-04) and so SourceRegistry can gate registration per-portal (INGEST-07). DoeOpenDataAdapter declares portals = ['doe-opendata'] additively, no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/api/src/tenders/adapters/doe-opendata.adapter.ts | 2 ++ .../adapters/tender-source-adapter.interface.ts | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/apps/api/src/tenders/adapters/doe-opendata.adapter.ts b/apps/api/src/tenders/adapters/doe-opendata.adapter.ts index 970c017..667bd6d 100644 --- a/apps/api/src/tenders/adapters/doe-opendata.adapter.ts +++ b/apps/api/src/tenders/adapters/doe-opendata.adapter.ts @@ -56,6 +56,8 @@ export function isOpenTenderNotice(tag: string[] | undefined): boolean { @Injectable() export class DoeOpenDataAdapter implements TenderSourceAdapter { readonly sourceType: SourceType = 'doe-opendata'; + /** Single-portal adapter — see TenderSourceAdapter.portals doc. */ + readonly portals = ['doe-opendata'] as const; private readonly logger = new Logger(DoeOpenDataAdapter.name); private readonly xmlParser = new XMLParser({ diff --git a/apps/api/src/tenders/adapters/tender-source-adapter.interface.ts b/apps/api/src/tenders/adapters/tender-source-adapter.interface.ts index 3065114..5de02f3 100644 --- a/apps/api/src/tenders/adapters/tender-source-adapter.interface.ts +++ b/apps/api/src/tenders/adapters/tender-source-adapter.interface.ts @@ -15,6 +15,17 @@ import type { RawTenderRecord, SourceType } from '../tender.types'; export interface TenderSourceAdapter { readonly sourceType: SourceType; + /** + * The source portal(s) this adapter serves (e.g. `['doe-opendata']`, or + * `['tender24', 'lhs-vpbw', 'vergabe.landbw']` for the config-driven + * NetServer adapter, Plan 13-04). `portals` decouples "one adapter" from + * "one portal" (INGEST-02) and is the hook `SourceRegistry.register()` + * checks against the AGB-prohibited denylist (INGEST-07/D-06) — every + * portal an adapter declares is checked, so a mixed array containing a + * denylisted portal alongside legitimate ones is rejected wholesale. + */ + readonly portals: readonly string[]; + /** * Fetch and lightly parse all open-tender ("tender"-tagged", D-02) * notices for the given calendar day (Europe/Berlin), already filtered —