add reproducible live five tender probe
Quality gates / test-build (push) Canceled after 0s
Quality gates / container (push) Canceled after 0s

This commit is contained in:
2026-09-06 20:40:14 +03:00
parent 3c3979a67a
commit f846ad05b9
3 changed files with 96 additions and 18 deletions
+27 -17
View File
@@ -1,10 +1,12 @@
{
"checkedAt": "2026-09-06T17:36:00+03:00",
"checkedAt": "2026-09-06T17:39:49.038Z",
"base": "https://ihaleist.com",
"readOnly": true,
"listCount": 8224,
"tenders": [
{
"ikn": "2026/1582991",
"scenario": "mikroskop",
"id": "ilan-2204986",
"title": "Mikroskop satın alınacaktır",
"institution": "GİRESUN EĞİTİM VE ARAŞTIRMA HASTANESİ BAŞHEKİMLİĞİ",
@@ -14,18 +16,20 @@
"announcementDate": "2026-08-27",
"tenderDate": "10.09.2026",
"tenderTime": "10:00",
"sourceDateTime": "10.09.2026 10:00",
"officialDateSource": "documents/ilan sourceDateTime",
"announcementDateConflict": null,
"detailStatus": true,
"documentProbeStatus": 200,
"documentCount": 0,
"sourceUrl": "https://www.ilan.gov.tr/ilan/2204986/ihale-duyurulari-mal-alim-ihaleleri-mikroskop-satin-alinacaktir",
"announcementCount": 1,
"okasCount": 2,
"sourceDateTime": "10.09.2026 10:00",
"documentEndpointSuccess": true,
"officialDateSource": "documents/ilan sourceDateTime"
"sourceUrl": "https://www.ilan.gov.tr/ilan/2204986/ihale-duyurulari-mal-alim-ihaleleri-mikroskop-satin-alinacaktir"
},
{
"ikn": "2026/1534665",
"scenario": "sarf",
"id": "ilan-2205024",
"title": "26 kalem laboratuvar sarf malzeme alımı",
"institution": "KAYSERİ DEVLET HASTANESİ BAŞHEKİMLİĞİ",
@@ -35,18 +39,20 @@
"announcementDate": "2026-08-31",
"tenderDate": "22.09.2026",
"tenderTime": "11:00",
"sourceDateTime": "22.09.2026 11:00",
"officialDateSource": "documents/ilan sourceDateTime",
"announcementDateConflict": null,
"detailStatus": true,
"documentProbeStatus": 200,
"documentCount": 0,
"sourceUrl": "https://www.ilan.gov.tr/ilan/2205024/ihale-duyurulari-mal-alim-ihaleleri-26-kalem-laboratuvar-sarf-malzeme-alimi",
"announcementCount": 1,
"okasCount": 1,
"sourceDateTime": "22.09.2026 11:00",
"documentEndpointSuccess": true,
"officialDateSource": "documents/ilan sourceDateTime"
"sourceUrl": "https://www.ilan.gov.tr/ilan/2205024/ihale-duyurulari-mal-alim-ihaleleri-26-kalem-laboratuvar-sarf-malzeme-alimi"
},
{
"ikn": "2026/1499061",
"scenario": "cihaz-servis",
"id": "ilan-2204525",
"title": "Laboratuvar malzemesi alınacaktır",
"institution": "AKDENİZ ÜNİVERSİTESİ REKTÖRLÜĞÜ ÜNİVERSİTE HASTANESİ BAŞ MÜDÜRLÜĞÜ",
@@ -56,18 +62,20 @@
"announcementDate": "2026-08-27",
"tenderDate": "22.09.2026",
"tenderTime": "10:30",
"sourceDateTime": "22.09.2026 10:30",
"officialDateSource": "documents/ilan sourceDateTime",
"announcementDateConflict": null,
"detailStatus": true,
"documentProbeStatus": 200,
"documentCount": 0,
"sourceUrl": "https://www.ilan.gov.tr/ilan/2204525/ihale-duyurulari-mal-alim-ihaleleri-laboratuvar-malzemesi-alinacaktir",
"announcementCount": 1,
"okasCount": 1,
"sourceDateTime": "22.09.2026 10:30",
"documentEndpointSuccess": true,
"officialDateSource": "documents/ilan sourceDateTime"
"sourceUrl": "https://www.ilan.gov.tr/ilan/2204525/ihale-duyurulari-mal-alim-ihaleleri-laboratuvar-malzemesi-alinacaktir"
},
{
"ikn": "2026/1573235",
"scenario": "kismi-teklif",
"id": "ilan-2203314",
"title": "Laboratuvar sarf malzemeleri satın alınacak",
"institution": "AKSARAY ÜNİVERSİTESİ EĞİTİM VE ARAŞTIRMA HASTANESİ",
@@ -77,19 +85,20 @@
"announcementDate": "2026-08-24",
"tenderDate": "16.09.2026",
"tenderTime": "10:00",
"sourceDateTime": "16.09.2026 10:00",
"officialDateSource": "documents/ilan sourceDateTime",
"announcementDateConflict": "ilan listesi 09.09.2026; resmi detay 16.09.2026",
"detailStatus": true,
"documentProbeStatus": 200,
"documentCount": 1,
"sourceUrl": "https://www.ilan.gov.tr/ilan/2203314/ihale-duyurulari-mal-alim-ihaleleri-laboratuvar-sarf-malzemeleri-satin-alinacak",
"announcementCount": 1,
"okasCount": 1,
"sourceDateTime": "16.09.2026 10:00",
"documentEndpointSuccess": true,
"officialDateSource": "documents/ilan sourceDateTime",
"announcementDateConflict": "ilan.gov.tr summary shows 09.09.2026; official detail/document source shows 16.09.2026"
"sourceUrl": "https://www.ilan.gov.tr/ilan/2203314/ihale-duyurulari-mal-alim-ihaleleri-laboratuvar-sarf-malzemeleri-satin-alinacak"
},
{
"ikn": "2026/1523851",
"scenario": "100-kalem",
"id": "ilan-2200563",
"title": "Laboratuvar malzemesi satın alınacaktır",
"institution": "İZMİR TEPECİK EĞİTİM VE ARAŞTIRMA HASTANESİ",
@@ -99,15 +108,16 @@
"announcementDate": "2026-08-21",
"tenderDate": "11.09.2026",
"tenderTime": "10:00",
"sourceDateTime": "11.09.2026 10:00",
"officialDateSource": "documents/ilan sourceDateTime",
"announcementDateConflict": null,
"detailStatus": true,
"documentProbeStatus": 200,
"documentCount": 1,
"sourceUrl": "https://www.ilan.gov.tr/ilan/2200563/ihale-duyurulari-mal-alim-ihaleleri-laboratuvar-malzemesi-satin-alinacaktir",
"announcementCount": 1,
"okasCount": 1,
"sourceDateTime": "11.09.2026 10:00",
"documentEndpointSuccess": true,
"officialDateSource": "documents/ilan sourceDateTime"
"sourceUrl": "https://www.ilan.gov.tr/ilan/2200563/ihale-duyurulari-mal-alim-ihaleleri-laboratuvar-malzemesi-satin-alinacaktir"
}
],
"scope": "Live metadata/detail/document endpoint probes only; no authentication, writes, payments, messages, or submissions."
+2 -1
View File
@@ -10,7 +10,8 @@
"qa:live": "node tests/live-runtime-probe.mjs",
"preview": "vite preview",
"server": "node server/index.js",
"test": "node --test tests/*.test.mjs"
"test": "node --test tests/*.test.mjs",
"qa:live-five": "node tests/live-five-probe.mjs"
},
"dependencies": {
"canvas-confetti": "^1.9.4",
+67
View File
@@ -0,0 +1,67 @@
// Read-only production acceptance probe for the five health/laboratory tenders.
// No authentication, writes, payments, messages, or tender submissions.
import { writeFile } from 'node:fs/promises';
import { healthAcceptanceCases } from './fixtures/health-acceptance.mjs';
const base = String(process.argv[2] || 'https://ihaleist.com').replace(/\/$/, '');
const evidencePath = process.env.IHALEIST_LIVE_FIVE_EVIDENCE_PATH || 'docs/quality/evidence/qa-live-five-tenders.json';
const timeoutMs = 30_000;
async function getJson(path) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(`${base}${path}`, { signal: controller.signal, headers: { 'User-Agent': 'ihaleist-live-five-probe/1.0' } });
const data = await response.json().catch(() => null);
if (!response.ok || !data || data.success !== true) throw new Error(`${path}: HTTP ${response.status}`);
return data;
} finally { clearTimeout(timer); }
}
const list = await getJson('/api/tenders?limit=100');
const byIkn = new Map((Array.isArray(list.tenders) ? list.tenders : []).map((tender) => [String(tender.ikn || '').replace(/\s/g, ''), tender]));
const tenders = [];
for (const fixture of healthAcceptanceCases) {
const ikn = `2026/${fixture.ikn}`;
const listed = byIkn.get(ikn);
if (!listed) throw new Error(`${ikn}: live listede bulunamadı`);
const detail = await getJson(`/api/tenders/${encodeURIComponent(listed.id)}/detail`);
const document = await getJson(`/api/documents/ilan?ikn=${encodeURIComponent(ikn)}`);
const officialDate = document.sourceDateTime || `${document.tarih || detail.tarih || ''} ${document.saat || detail.saat || ''}`.trim();
if (!officialDate || !document.ikn || document.ikn !== ikn) throw new Error(`${ikn}: resmi tarih/İKN doğrulanamadı`);
tenders.push({
ikn,
scenario: fixture.scenario,
id: listed.id,
title: listed.baslik,
institution: listed.kurum,
city: listed.sehir,
sector: listed.sektor,
procedure: listed.usul,
announcementDate: listed.ilanTarihi,
tenderDate: document.tarih || detail.tarih || '',
tenderTime: document.saat || detail.saat || '',
sourceDateTime: officialDate,
officialDateSource: 'documents/ilan sourceDateTime',
announcementDateConflict: ikn === '2026/1573235' && listed.tarih !== document.tarih
? `ilan listesi ${listed.tarih}; resmi detay ${document.tarih}` : null,
detailStatus: detail.success === true,
documentProbeStatus: 200,
documentCount: Number(document.dokumanSayisi) || 0,
announcementCount: Number(document.ilanSayisi) || 0,
okasCount: Number(document.okasSayisi) || 0,
documentEndpointSuccess: document.success === true,
sourceUrl: listed.kaynakUrl,
});
}
const result = {
checkedAt: new Date().toISOString(),
base,
readOnly: true,
listCount: Array.isArray(list.tenders) ? list.tenders.length : 0,
tenders,
scope: 'Live metadata/detail/document endpoint probes only; no authentication, writes, payments, messages, or submissions.',
};
await writeFile(evidencePath, `${JSON.stringify(result, null, 2)}\n`);
console.log(JSON.stringify({ base, checkedAt: result.checkedAt, tenders: tenders.map(({ ikn, tenderDate, tenderTime, documentCount }) => ({ ikn, tenderDate, tenderTime, documentCount })) }));