feat(dane): mechanizm rekordów-pułapek (canary) — wykrywanie wycieku baz (DAN-26)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m29s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 11s
Testy / Kontrola składni wszystkich warstw (push) Successful in 7s

Zabezpieczenie DETEKCYJNE (nie prewencyjne): kilka unikalnych, wiarygodnie
wyglądających rekordów-pułapek w bazach. Nie zmieniają interpretacji (odsiewamy
je z wyników), ale jeśli pojawią się w cudzej kopii — są dowodem pochodzenia, a
przy wariancie na kopię — wskazują ŹRÓDŁO wycieku.

`canary.py`: pułapkę rozpoznajemy po MARKERZE (unikalny ciąg z ENV, nieobecny w
realnych danych). `screen(rows, query_value)`:
- ODSIEWA rekordy z markerem z wyników — i to na WYJŚCIU z warstwy danych
  (`/search`), więc nie dotrą wyżej ani do promptu LLM (LOG-30), niezależnie od
  dostawcy (Excel/SQL);
- TRIPWIRE: gdy zapytanie celuje wprost w marker (enumeracja bazy, nie liczenie
  horoskopu) → log warning.
Bez `CANARY_MARKERS` — przezroczyste, zero kosztu dla normalnego ruchu.

Rejestr wariant→kopia (traitor tracing) i wstrzyknięcie do REALNYCH baz to krok
właściciela (poza kodem — nie ruszamy kupionych plików automatycznie);
instrukcja: docs/canary-registry.md. Mechanizm zbudowany i przetestowany na
syntetycznych pułapkach.

Testy: +7 (przezroczystość bez markerów, odsiewanie, tripwire, marker w dowolnym
polu, endpoint odsiewa przed zwrotem). Pierwsze testy w usłudze `data`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #52.
This commit is contained in:
2026-08-03 21:15:53 +02:00
parent 7b435d4263
commit 78af6d4755
4 changed files with 198 additions and 2 deletions
+9 -2
View File
@@ -11,7 +11,7 @@ from contextlib import asynccontextmanager
from fastapi import FastAPI
from app import link_crypto, security
from app import canary, link_crypto, security
from app.config import settings
from app.models import HealthInfo, SearchQuery, SearchResult
from app.providers.factory import build_provider
@@ -34,7 +34,14 @@ link_crypto.install(app, link_crypto.ENV_LOGIC_DATA, "danych")
@app.post("/search", response_model=SearchResult)
def search(query: SearchQuery) -> SearchResult:
return provider.search(query)
result = provider.search(query)
# Rekordy-pułapki (DAN-26) odsiewamy TU, na wyjściu z warstwy danych — dzięki
# temu nie dotrą ani wyżej, ani do promptu LLM (LOG-30), niezależnie od dostawcy.
visible, report = canary.screen(result.rows, query.value)
if report["active"]:
result.rows = visible
result.total = len(visible)
return result
@app.get("/health", response_model=HealthInfo)