From 3b9cd36f925fec73cd7ae4e1fbc790fc4c801df6 Mon Sep 17 00:00:00 2001 From: Lacky1234union Date: Sat, 3 Oct 2026 14:50:30 +0300 Subject: [PATCH] =?UTF-8?q?chore(core):=20freeze=20shared=20core=20contrac?= =?UTF-8?q?ts=20=E2=80=94=20ScrubbedText,=20RiskLevel,=20AlertLevel,=20pri?= =?UTF-8?q?vacy=20signatures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets #2-#7 proceed in parallel against stable interfaces. Refs #2 Co-Authored-By: Claude Opus 5.5 --- app/core/privacy.py | 13 +++++++++++++ app/core/types.py | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 app/core/privacy.py create mode 100644 app/core/types.py diff --git a/app/core/privacy.py b/app/core/privacy.py new file mode 100644 index 0000000..c81c6c3 --- /dev/null +++ b/app/core/privacy.py @@ -0,0 +1,13 @@ +"""PII scrubbing and pseudonymisation (issue #2). Contract stub — implementation lands in #2.""" + +from app.core.types import ScrubbedText + + +def scrub(text: str) -> ScrubbedText: + """Replace personal data (phones, emails, SNILS, names, addresses...) with placeholders.""" + raise NotImplementedError + + +def pseudo_id(snils: str, key: str | None = None) -> str: + """HMAC-SHA256(PSEUDO_KEY, normalised SNILS) as 32 hex chars — the token linking identity and clinical DBs.""" + raise NotImplementedError diff --git a/app/core/types.py b/app/core/types.py new file mode 100644 index 0000000..cc85392 --- /dev/null +++ b/app/core/types.py @@ -0,0 +1,24 @@ +"""Shared core types. Frozen contract between zones: change only via a separate small PR.""" + +from enum import IntEnum +from typing import NewType + +# Text that has passed `app.core.privacy.scrub()`. The LLM gateway accepts only this type (guardrail #1). +ScrubbedText = NewType("ScrubbedText", str) + + +class RiskLevel(IntEnum): + """Safety risk level. Ordered, so the combined signal is `max(lexicon, llm)`.""" + + NONE = 0 + POSSIBLE = 1 + ACUTE = 2 + + +class AlertLevel(IntEnum): + """Alert level stored in DB. UI colour is derived (ADR-006): ACUTE=red, HIGH/MODERATE=yellow, INFO=grey.""" + + INFO = 0 + MODERATE = 1 + HIGH = 2 + ACUTE = 3