K0NSULT // ai-truth/ipIII
k0nsult.cloud / ai-truth / ipIII / model-rozszerzony

Rozszerzony model danych

Rozszerzenie rdzenia z model-danych o warstwy wymagane przez audyt (§4.2 brakujące moduły, §4.3 nowe tabele). Domyka luki: tożsamość i uprawnienia, ślad audytowy, retencję, podstawę prawną przetwarzania, wielodostępność, notyfikacje, prowadzenie sprawy, wersjonowanie dokumentów, akceptację ryzyka oraz ścieżkę odwoławczą. To specyfikacja docelowego schematu — nie działający backend.

Specyfikacja referencyjna. Nie stanowi certyfikacji ani opinii prawnej; implementacja produkcyjna ma status ROADMAP. Poniższe tabele SQL to szkic docelowego schematu (PostgreSQL-owy dialekt poglądowy), a nie kod wdrożony w bazie produkcyjnej. Żywa autentykacja, realna baza i egzekwowanie polityk mają status GAP / ROADMAP do czasu wdrożenia i weryfikacji.
Rozszerzenie rdzenia model-danych, nie jego zamiennik.

Tabele incidents, evidence, classifications, playbook_runs pochodzą z rdzenia. Ta strona dodaje warstwy okołordzeniowe i dopina je kluczami obcymi (FK) do incidents(id) i evidence(id). Zasada nadrzędna pozostaje: claim ≤ proof — żaden rekord twierdzenia nie istnieje bez powiązanego dowodu.

WARSTWY: RDZEŃ (incidents/evidence)IAM + AUDITLEGAL + CONSENTCASE + NOTIFYRETENCJA + APPEALSZGODNOŚĆ
LIVE = zaimplementowane i zweryfikowane GAP = brak implementacji ROADMAP = zaplanowane DANE = warstwa danych/schemat

§4.2 — Brakujące moduły GAP

Audyt wskazał dziesięć modułów, których rdzeń nie pokrywa. Każdy jest warunkiem dojrzałości GRC/SOC i zgodności (NIS2, RODO, AI Act). Wszystkie mają status implementacji ROADMAP.

ModułPo co (uzasadnienie)Główne tabeleStatus
IAM — tożsamość i dostępKto może czytać/zmieniać incydent i dowód. Uwierzytelnianie, role, uprawnienia, MFA. Warunek rozliczalności każdego wpisu.users, roles_permissions, organizationsROADMAP
Audit Log — ślad audytowyNiezmienialny zapis „kto, co, kiedy, na jakim rekordzie". Dowód dla KNF/CSIRT, wykrywanie manipulacji statusem.audit_eventsROADMAP
Data Retention — retencjaPolityki przechowywania i usuwania (RODO art. 5 ust. 1 lit. e, minimalizacja). Automatyczne wygaszanie danych po terminie.data_processing_records, pola retention_untilROADMAP
Consent / Legal Basis — podstawa prawnaPodstawa przetwarzania każdego zbioru danych osobowych (RODO art. 6/9). Rejestr zgód i podstaw dla zgłaszających i poszkodowanych.data_processing_records, legal_assessmentsROADMAP
Tenant / Organizations — wielodostępnośćIzolacja danych między podmiotami (bank A nie widzi banku B). Warunek wdrożenia SaaS dla wielu instytucji.organizationsROADMAP
Notification Engine — notyfikacjePowiadomienia o zegarach raportowych (24h/72h NIS2), eskalacjach P0/P1, wygaśnięciu SLA. Kanały: e-mail, webhook.notificationsROADMAP
Case Management — prowadzenie sprawyGrupowanie powiązanych incydentów w sprawę, przypisania, statusy postępowania, kolejka analityka.disputes, rozszerzenia incidentsROADMAP
Document Versioning — wersjonowanieHistoria zmian raportów, playbooków, ocen prawnych. Kto i kiedy zmienił, poprzednia wersja, hash. Integralność dowodowa.documentsROADMAP
Risk Acceptance — akceptacja ryzykaŚwiadoma decyzja o zaakceptowaniu ryzyka rezydualnego (kto zaakceptował, uzasadnienie, termin przeglądu). Ślad odpowiedzialności.legal_assessments, pola risk_accepted_byROADMAP
Appeals / Dispute Path — ścieżka odwoławczaKwestionowanie klasyfikacji lub statusu dowodu. Rejestr sporów, rozstrzygnięcia, zgodność z zasadą claim ≤ proof.disputes, truth_claimsROADMAP

§4.3 — Nowe tabele (szkic SQL) DANE ROADMAP

Poniżej szkielety CREATE TABLE z kluczowymi kolumnami i kluczami obcymi do rdzenia (incidents(id), evidence(id)). Typy poglądowe (PostgreSQL). To projekt schematu — nie migracja uruchomiona na bazie produkcyjnej.

IAM — tożsamość, organizacje, role

CREATE TABLE organizations (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  public_id     TEXT UNIQUE NOT NULL,        -- np. ORG-BANK-001
  name          TEXT NOT NULL,
  kind          TEXT NOT NULL,               -- bank | podmiot_kluczowy | regulator | csirt
  tenant_scope  TEXT NOT NULL DEFAULT 'isolated',
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE users (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id          UUID NOT NULL REFERENCES organizations(id),
  email           TEXT UNIQUE NOT NULL,
  display_name    TEXT,
  status          TEXT NOT NULL DEFAULT 'active',   -- active|suspended|revoked
  mfa_enabled     BOOLEAN NOT NULL DEFAULT false,
  last_login_at   TIMESTAMPTZ,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE roles_permissions (
  id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id      UUID NOT NULL REFERENCES users(id),
  org_id       UUID NOT NULL REFERENCES organizations(id),
  role         TEXT NOT NULL,               -- analyst|soc_lead|dpo|auditor|admin|reporter
  permission   TEXT NOT NULL,               -- incident.read|incident.write|evidence.verify|legal.assess...
  granted_by   UUID REFERENCES users(id),
  granted_at   TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (user_id, role, permission)
);

Audit Log — niezmienialny ślad

CREATE TABLE audit_events (
  id            BIGSERIAL PRIMARY KEY,
  actor_user_id UUID REFERENCES users(id),
  org_id        UUID REFERENCES organizations(id),
  action        TEXT NOT NULL,              -- create|update|status_change|verify|close|export
  entity_type   TEXT NOT NULL,             -- incident|evidence|classification|legal_assessment
  entity_id     UUID NOT NULL,             -- FK logiczny; dla incydentu -> incidents(id)
  incident_id   UUID REFERENCES incidents(id),  -- kontekst nadrzędny, gdy dotyczy
  before_hash   TEXT,                      -- SHA-256 stanu sprzed zmiany
  after_hash    TEXT,                      -- SHA-256 stanu po zmianie
  ip_addr       INET,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- append-only: brak UPDATE/DELETE (egzekwowane politykami i rolą DB)

Legal / Consent / Retention

CREATE TABLE legal_assessments (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id       UUID NOT NULL REFERENCES incidents(id),
  framework         TEXT NOT NULL,          -- ai_act|nis2|ksc|rodo
  obligation        TEXT,                   -- art.73|24h|72h|art.33|art.34
  duty_triggered    BOOLEAN NOT NULL DEFAULT false,
  deadline_at       TIMESTAMPTZ,
  risk_accepted     BOOLEAN NOT NULL DEFAULT false,
  risk_accepted_by  UUID REFERENCES users(id),
  rationale         TEXT,
  assessed_by       UUID REFERENCES users(id),
  created_at        TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE data_processing_records (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id       UUID REFERENCES incidents(id),
  data_category     TEXT NOT NULL,          -- osobowe|wrazliwe|techniczne|ioc
  legal_basis       TEXT NOT NULL,          -- rodo_6_1_c|rodo_6_1_f|rodo_9_2_g|zgoda
  consent_ref       TEXT,                   -- odnośnik do zgody, gdy podstawa=zgoda
  purpose           TEXT NOT NULL,
  retention_until   TIMESTAMPTZ,            -- termin usunięcia (retencja)
  controller_org_id UUID REFERENCES organizations(id),
  created_at        TIMESTAMPTZ NOT NULL DEFAULT now()
);

Notyfikacje

CREATE TABLE notifications (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID REFERENCES incidents(id),
  recipient_id  UUID REFERENCES users(id),
  channel       TEXT NOT NULL,             -- email|webhook|inapp
  kind          TEXT NOT NULL,             -- sla_breach|clock_24h|clock_72h|escalation_p0
  payload       JSONB,
  status        TEXT NOT NULL DEFAULT 'queued',  -- queued|sent|failed
  sent_at       TIMESTAMPTZ,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

Case management / spory / dowód-twierdzenie

CREATE TABLE truth_claims (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID NOT NULL REFERENCES incidents(id),
  claim_text    TEXT NOT NULL,
  proof_evidence_id UUID REFERENCES evidence(id),   -- claim <= proof: brak dowodu => status GAP
  confidence    INT CHECK (confidence BETWEEN 0 AND 100),
  status        TEXT NOT NULL DEFAULT 'gap',        -- gap|confirmed|disputed
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE disputes (
  id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id    UUID NOT NULL REFERENCES incidents(id),
  claim_id       UUID REFERENCES truth_claims(id),
  raised_by      UUID REFERENCES users(id),
  reason         TEXT NOT NULL,            -- klasyfikacja|status_dowodu|priorytet
  resolution     TEXT,
  resolved_by    UUID REFERENCES users(id),
  status         TEXT NOT NULL DEFAULT 'open',  -- open|upheld|rejected
  created_at     TIMESTAMPTZ NOT NULL DEFAULT now()
);

Dokumenty (wersjonowanie)

CREATE TABLE documents (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID REFERENCES incidents(id),
  kind          TEXT NOT NULL,            -- raport|ocena_prawna|playbook_snapshot
  version       INT NOT NULL DEFAULT 1,
  parent_doc_id UUID REFERENCES documents(id),   -- poprzednia wersja
  content_hash  TEXT NOT NULL,           -- SHA-256 treści
  author_id     UUID REFERENCES users(id),
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (incident_id, kind, version)
);

Domena incydentu — poszkodowani, szkody, aktorzy, źródła

CREATE TABLE victims (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID NOT NULL REFERENCES incidents(id),
  kind          TEXT NOT NULL,           -- osoba|organizacja|system
  sector        TEXT,                    -- finanse|zdrowie|energetyka...
  impact_note   TEXT,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE damages (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID NOT NULL REFERENCES incidents(id),
  victim_id     UUID REFERENCES victims(id),
  damage_type   TEXT NOT NULL,           -- finansowy|dane|reputacja|ciaglosc
  estimate_pln  NUMERIC(14,2),
  is_confirmed  BOOLEAN NOT NULL DEFAULT false,
  evidence_id   UUID REFERENCES evidence(id),
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE actors (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID NOT NULL REFERENCES incidents(id),
  actor_type    TEXT NOT NULL,           -- apt|insider|automat|nieznany
  alias         TEXT,
  attribution_confidence INT CHECK (attribution_confidence BETWEEN 0 AND 100),
  evidence_id   UUID REFERENCES evidence(id),
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE sources (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID NOT NULL REFERENCES incidents(id),
  source_type   TEXT NOT NULL,           -- osint|siem|cert|zgloszenie|media
  url           TEXT,
  reliability   TEXT,                    -- A-F (skala NATO admiralty)
  captured_at   TIMESTAMPTZ,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

Szkolenia, podatności, badacze, zależności

CREATE TABLE training_records (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id       UUID NOT NULL REFERENCES users(id),
  module        TEXT NOT NULL,           -- evidence-first|playbook|ai-risk
  passed        BOOLEAN NOT NULL DEFAULT false,
  score         INT CHECK (score BETWEEN 0 AND 100),
  completed_at  TIMESTAMPTZ,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE vulnerabilities (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID REFERENCES incidents(id),
  cve_id        TEXT,                    -- np. CVE-2026-XXXX
  cvss          NUMERIC(3,1),
  affected_asset TEXT,
  status        TEXT NOT NULL DEFAULT 'open',   -- open|patched|mitigated
  evidence_id   UUID REFERENCES evidence(id),
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE researchers (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  handle        TEXT UNIQUE NOT NULL,
  org_id        UUID REFERENCES organizations(id),
  vdp_accepted  BOOLEAN NOT NULL DEFAULT false,   -- akceptacja VDP/RoE
  reputation    INT DEFAULT 0,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE third_party_dependencies (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  incident_id   UUID REFERENCES incidents(id),
  vendor        TEXT NOT NULL,
  component     TEXT,                    -- biblioteka|usluga|dostawca
  risk_level    TEXT,                    -- low|medium|high|critical
  sbom_ref      TEXT,                    -- odnośnik do SBOM
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);
Reguła integralności. Tabela truth_claims egzekwuje doktrynę claim ≤ proof na poziomie danych: rekord bez proof_evidence_id ma status gap i nie może zostać oznaczony jako confirmed. audit_events jest append-only — status incydentu nie może zmienić się bez śladu. To nie jest jeszcze wdrożone (GAP), to wymóg projektowy dla implementacji.
Zakres i uczciwość. Ta strona jest dokumentacją/referencją schematu. Nie ma tu żywej bazy, autentykacji ani egzekwowania polityk — te elementy mają status GAP / ROADMAP. Rozszerzenie zakłada rdzeń opisany w model-danych; wszystkie FK wskazują na tabele rdzenia (incidents, evidence). Zero payloadów ofensywnych — to schemat danych GRC, nie narzędzie ataku.

← Rdzeń: model danych · API → · ← ipIII hub