add read only live runtime drift probe

This commit is contained in:
2026-09-06 19:13:43 +03:00
parent 3fbaa1ca26
commit 5a81be92ba
4 changed files with 78 additions and 10 deletions
+28 -10
View File
@@ -1,19 +1,37 @@
{ {
"date": "2026-09-06", "base": "https://ihaleist.com",
"url": "https://ihaleist.com", "readOnly": true,
"checkedAt": "2026-09-06T16:13:35.286Z",
"checks": { "checks": {
"apiHealth": {"status": 200, "body": {"ok": true}}, "home": {
"apiReady": {"status": 404, "body": {"success": false, "error": "not found"}}, "status": 200,
"securityHeadersObserved": { "headers": {
"apiHealth": {
"access-control-allow-origin": "*",
"x-content-type-options": null, "x-content-type-options": null,
"referrer-policy": null, "referrer-policy": null,
"permissions-policy": null "permissions-policy": null
} }
}, },
"servedAsset": "/assets/index-BtYUXYcw.js" "health": {
"status": 200,
"headers": {
"x-content-type-options": null,
"referrer-policy": null,
"permissions-policy": null
}
},
"ready": {
"status": 404,
"headers": {
"x-content-type-options": null,
"referrer-policy": null,
"permissions-policy": null
}
}
}, },
"scope": "Read-only live probe; no login, mutation, payment, message, or tender submission performed.", "pass": false,
"interpretation": "Live deployment does not yet contain the local readiness endpoint or the local API security headers. Deployment remains pending." "missingHeaders": [
"x-content-type-options",
"referrer-policy",
"permissions-policy"
]
} }
+6
View File
@@ -2200,3 +2200,9 @@ Doğrulama: browser QA başarılı; analitik erişilebilirlik kontrolü, ICS, ç
Belge son kullanma uyarısı artık “bugün” anahtarını UTC tarihinden değil İstanbul tarihinden üretiyor. Yalnız tarih içeren son kullanma değerleri `+03:00` gece yarısı olarak ayrıştırılıyor; böylece Türkiye’de gün değişimi sırasında 30 gün/son kullanma uyarısı bir gün kaymıyor. Geçersiz tarih sessizce yaklaşan belge olarak sayılmıyor. Belge son kullanma uyarısı artık “bugün” anahtarını UTC tarihinden değil İstanbul tarihinden üretiyor. Yalnız tarih içeren son kullanma değerleri `+03:00` gece yarısı olarak ayrıştırılıyor; böylece Türkiye’de gün değişimi sırasında 30 gün/son kullanma uyarısı bir gün kaymıyor. Geçersiz tarih sessizce yaklaşan belge olarak sayılmıyor.
Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gece yarısı sınırı için gerçek saat kontrollü tarayıcı kabulü ayrıca yapılmalı. Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gece yarısı sınırı için gerçek saat kontrollü tarayıcı kabulü ayrıca yapılmalı.
### 2026-09-06 · Tekrarlanabilir canlı drift probe’u
`npm run qa:live -- https://ihaleist.com` komutu eklendi. Probe yalnızca ana sayfa, `/api/health` ve `/api/ready` uç noktalarını GET ile kontrol ediyor; authentication, veri yazma, ödeme veya sağlayıcı çağrısı yapmıyor. Ana sayfa ve health için güvenlik başlıklarını da zorunlu tutup JSON kanıtı `qa-live-runtime.json` içine yazıyor.
6 Eylül 2026 çalıştırmasında ana sayfa ve health 200, readiness 404 döndü; üç güvenlik başlığı canlı yanıtlarda bulunmadı. Probe bu nedenle beklenen şekilde başarısız oldu. Bu sonuç yerel düzeltmelerin canlıya alınmadığını gösteren drift kanıtıdır.
+1
View File
@@ -7,6 +7,7 @@
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"qa:browser": "node tests/browser-acceptance.mjs", "qa:browser": "node tests/browser-acceptance.mjs",
"qa:live": "node tests/live-runtime-probe.mjs",
"preview": "vite preview", "preview": "vite preview",
"server": "node server/index.js", "server": "node server/index.js",
"test": "node --test tests/*.test.mjs" "test": "node --test tests/*.test.mjs"
+43
View File
@@ -0,0 +1,43 @@
// Read-only production drift probe. No authentication, writes, payments or
// provider calls are performed. It intentionally fails when a required
// deployment contract is missing.
import { mkdir, writeFile } from 'node:fs/promises';
const base = String(process.argv[2] || process.env.IHALEIST_LIVE_URL || 'https://ihaleist.com').replace(/\/$/, '');
const timeoutMs = 15_000;
const requiredHeaders = ['x-content-type-options', 'referrer-policy', 'permissions-policy'];
const checks = {};
async function probe(path) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(base + path, { signal: controller.signal, redirect: 'manual' });
return {
status: response.status,
headers: Object.fromEntries(requiredHeaders.map(name => [name, response.headers.get(name)])),
};
} catch (error) {
return { error: error.name === 'AbortError' ? `timeout after ${timeoutMs}ms` : error.message };
} finally {
clearTimeout(timer);
}
}
checks.home = await probe('/');
checks.health = await probe('/api/health');
checks.ready = await probe('/api/ready');
const missingHeaders = requiredHeaders.filter(name => checks.home?.headers?.[name] == null || checks.health?.headers?.[name] == null);
const report = {
base,
readOnly: true,
checkedAt: new Date().toISOString(),
checks,
pass: checks.home?.status === 200 && checks.health?.status === 200 && checks.ready?.status === 200 && missingHeaders.length === 0,
missingHeaders,
};
await mkdir('docs/quality/evidence', { recursive: true });
await writeFile('docs/quality/evidence/qa-live-runtime.json', JSON.stringify(report, null, 2) + '\n');
console.log(JSON.stringify(report));
if (!report.pass) process.exitCode = 1;