import type { RawTenderRecord, SourceType } from '../tender.types'; /** * Contract implemented by every tender source adapter (DÖE OpenData this * phase; AI-NetServer/cosinex/RSS/email-alert in later phases). * * `fetchTenders` takes a day-cursor string (`YYYY-MM-DD`), NOT a `since: Date` * timestamp — the DÖE OpenData API is a daily batch-export API with no * incremental/since parameter (RESEARCH.md Pattern 1 corrects the * `ARCHITECTURE.md` sketch's `since?: Date` signature). Day-cursor is kept * as the shared interface shape so future adapters that ARE incremental * (e.g. RSS) can still satisfy it by treating the day as a coarse filter, * rather than forking the interface per source. */ 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 — * implementations must NOT return award/planning/untagged-with-awards * notices. * * @param dayCursor - `YYYY-MM-DD`, must be strictly in the past (today/ * future is rejected upstream by the DÖE API with HTTP 400). Implementations * treat that 400 as an expected no-op and resolve to `[]`, never throw. */ fetchTenders(dayCursor: string): Promise; }