CNCK0NSULTAI-Truthuni0naiHackatonipIII ↗k0nsult.dev ↗ dla botówDomeny osobne, spięte siecią CNC + kernelem.
K0NSULT // ai-truth/ipIII
k0nsult.cloud / ai-truth / ipIII / orchestrator / tenant-model

Multi-Tenant & Data Isolation — app-level scoping (MVP), DB RLS (ROADMAP)

Jak dane wielu banków, partnerów i urzędów są odseparowane na jednej instancji ipIII. Warstwa aplikacyjna (scopeClause/canAccess, org-scoping) jest zaimplementowana i dowiedziona na realnym PostgreSQL — cross-org odczyt zwraca 404, nie dane cudzej organizacji. Warstwa bazodanowa (PostgreSQL Row-Level Security) i pełna czterowarstwowa hierarchia najmu to nadal ROADMAP P1. Na produkcji publicznej działa dziś świadomy tryb single-tenant-demo (jedna organizacja demo). Zgodnie z doktryną claim ≤ proof.

Stan faktyczny na 2026-07-20 (skorygowany). Wcześniejsza wersja tej strony (z 2026-07-05) twierdziła „single-org, brak izolacji wielodostępnej, RLS to spec nie kod" — to opis zaniżony względem stanu kodu. Warstwa app-level (routes/ip3-tenancy.js: scopeClause/canAccess) jest zaimplementowana, jest secure-by-default (scoping aktywny, jeśli nie ustawiono jawnie trybu demo) i jest pokryta testami przechodzącymi na żywym Express + PostgreSQL. To, co nadal jest specyfikacją projektową (szkielet), to: PostgreSQL Row-Level Security w samej bazie (warstwa 2, obrona nawet gdy aplikacja pominie filtr) oraz pełna czterowarstwowa hierarchia tenant/org/project/engagement poniżej poziomu org. Każdy taki element jest oznaczony ROADMAP.
Dziś: app-level org-scoping zaimplementowany i dowiedziony (real PG). DB RLS = ROADMAP P1.

Izolacja danych między klientami to warunek wejścia dla banku SIFI, partnera SaaS i urzędu. ipIII ma dziś działającą warstwę evidence (import → incydent → evidence-package → retest → close, z JWT/RBAC/audit na żywej PostgreSQL) oraz warstwę app-level scopingu po org_id: scope pochodzi z tokenu sesji (nie z parametru żądania), a domyślne zachowanie (secure-by-default) to izolacja włączona — tryb bez filtrowania wymaga jawnej bramki demo. To, czego jeszcze nie ma, to druga warstwa obrony w samej bazie (PostgreSQL RLS) i pełna hierarchia najmu poniżej org (project, engagement jako osobne granice scope'u).

OŚ DOJRZAŁOŚCI: app-scoping org_id (dowiedzione)testy IDOR/BOLA (12/0, 14/0)PostgreSQL RLS (ROADMAP)pełna hierarchia tenant/project/engagement (ROADMAP)audit + lifecycle per tenant (ROADMAP)

Dowód na realnym PostgreSQL (2026-07-20, staging)

Poniższy przebieg wykonano na realnym środowisku PostgreSQL (staging), nie na atrapie w pamięci — to uzupełnienie testów jednostkowych z sekcją poniżej, na rzeczywistej bazie danych.

Zasiew danych

2 organizacje + po jednym użytkowniku w każdej. Scoping aktywny: flag:on, scoping_active:true.

Widoczność własnych danych

Użytkownik org A tworzy incydent. Org A widzi go (1 incydent) — org B widzi 0.

Cross-org GET = 404

Org B próbuje pobrać incydent org A po identyfikatorze: odpowiedź 404, nie 403 — brak wycieku informacji o istnieniu cudzego zasobu.

Testy jednostkowe/integracyjne pokrywające tę ścieżkę: tests/ip3-tenant-idor.test.js (12 PASS / 0 FAIL) i tests/ip3-tenancy.test.js (14 PASS / 0 FAIL).

Czego to NIE dowodzi. To dowód izolacji na poziomie aplikacji (warstwa 1), na jednej instancji, z dwoma organizacjami testowymi. Nie jest to dowód na pełną czterowarstwową hierarchię najmu (project/engagement jako osobne granice), nie jest to dowód na PostgreSQL RLS (warstwa 2 — obrona w bazie, gdyby aplikacja pominęła filtr) i nie jest to deklaracja „gotowe dla banku SIFI". Produkcja publiczna działa dziś w trybie single-tenant-demo — świadomie, jako jedna organizacja demo.

Model hierarchii najmu

Czterowarstwowa struktura scopingu. Poziom 2 — Org jest dziś zaimplementowany na app-level i dowiedziony (patrz sekcja wyżej); poziom 1 (grupowanie wielu org w jeden tenant nadrzędny, klucz dla RLS) oraz poziomy 3-4 (project/engagement jako osobne granice scope'u) to nadal spec docelowa (ROADMAP).

PoziomEncjaRola w izolacjiPrzykładStatus
1 — Tenant tenant Najwyższa granica izolacji, nadrzędna wobec wielu org (np. grupa kapitałowa). Klucz scopingu docelowo używany przez RLS. Bank A · Partner B · Urząd C ROADMAP P1 — dziś istnieje tylko poziom org
2 — Org org Granica izolacji app-level, dziś realnie egzekwowana: scope z tokenu sesji (org_id), fail-closed bez org, cross-org GET = 404. Bank A / Pion Cyber · Bank A / Compliance MVP — zaimplementowane i dowiedzione
3 — Project project Kontener pracy w ramach org (system, aplikacja, obszar audytu). Grupuje engagementy i evidence. Bankowość internetowa · Aplikacja mobilna ROADMAP P1
4 — Engagement engagement Pojedyncze zaangażowanie (pilot, PoC, cykl retestu) w granicach RoE. Najniższy scope, do którego wiążą się findings, incydenty i evidence-package. PoC purple-team Q3 · Retest po remediacji ROADMAP P1
Zasada scopingu. Dziś każde zapytanie do danych niesie kontekst org_id — scope pochodzi z tokenu sesji, nie z parametru żądania sterowanego przez klienta, co eliminuje klasę podatności, w której użytkownik podstawia cudzy identyfikator, żeby sięgnąć po nieswoje dane (IDOR/BOLA). Docelowo (ROADMAP) ten sam mechanizm ma zejść niżej, do project_id / engagement_id, i wznieść się wyżej, do nadrzędnego tenant_id grupującego wiele org. Na produkcji publicznej scoping jest dziś świadomie wyłączony trybem single-tenant-demo (jedna organizacja demo) — nie dlatego, że kod go nie ma, tylko dlatego, że na jednej organizacji demo nie ma co izolować.

PostgreSQL Row-Level Security (szkielet)

RLS to warstwa obrony w samej bazie: nawet gdy warstwa aplikacyjna pominie filtr, baza nie zwróci wierszy spoza aktywnego tenanta. Poniższy szkielet jest ilustracją docelowej polityki (ROADMAP), nie fragmentem wdrożonego kodu.

-- SPEC / ROADMAP (nie wdrożone) — szkic polityki RLS per tenant
ALTER TABLE evidence     ENABLE ROW LEVEL SECURITY;
ALTER TABLE incidents    ENABLE ROW LEVEL SECURITY;
ALTER TABLE findings     ENABLE ROW LEVEL SECURITY;

-- scope pochodzi z sesji (SET app.tenant_id = ... przy uwierzytelnieniu),
-- nie z parametru sterowanego przez klienta
CREATE POLICY tenant_isolation ON evidence
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation ON incidents
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

-- FORCE RLS = polityka obowiązuje także właściciela tabeli
ALTER TABLE evidence  FORCE ROW LEVEL SECURITY;
ALTER TABLE incidents FORCE ROW LEVEL SECURITY;
Wymóg migracji. Włączenie RLS wymaga dodania kolumny tenant_id do istniejących tabel, backfillu danych, przepięcia ścieżki uwierzytelnienia na ustawianie app.tenant_id oraz zestawu testów regresji. To migracja schematu produkcyjnej bazy — nie zmiana kosmetyczna. Uruchamiana wyłącznie po ACK operatora i na planie z rollbackiem.

Testy izolacji — pozytywne i negatywne

Sama polityka nie wystarczy — trzeba udowodnić, że działa, także w scenariuszach nadużycia. Na poziomie org (app-level) zestaw testów pozytywnych i negatywnych istnieje i przechodzi. Na poziomie DB (RLS) i pełnej hierarchii (project/engagement) zestaw jest dalej specyfikacją (ROADMAP).

Pozytywne — org

Org A odczytuje wyłącznie własne evidence/incydenty. Scope z sesji zwraca komplet swoich rekordów, żaden nie ginie.

MVP — dowiedzione (real PG + 26 testów)

Negatywne — IDOR (org)

Org B podstawia identyfikator rekordu należącego do Org A (bezpośrednie odwołanie do obiektu). Wynik: 404, zero wierszy — bez ujawniania, że zasób istnieje.

MVP — dowiedzione

Negatywne — BOLA (org)

Autoryzowany użytkownik Org B próbuje operacji na obiekcie poza swoim scope (broken object-level authorization). Wynik: odmowa na poziomie canAccess, nie tylko UI.

MVP — dowiedzione

Cross-scope w dół (project/engagement) + RLS w bazie

Użytkownik org próbuje sięgnąć do project/engagementu spoza swojego poddrzewa; drugorzędna obrona w bazie (RLS), gdyby aplikacja pominęła filtr. Oba elementy poza dzisiejszym zakresem app-level.

ROADMAP

Dlaczego testy negatywne są kluczowe. Izolacji nie dowodzi się pokazując, że własne dane są widoczne — dowodzi się pokazując, że cudze nie są, nawet gdy atakujący celowo manipuluje identyfikatorami. Testy IDOR/BOLA są wykonywane wyłącznie defensywnie, na danych syntetycznych, w granicach pisemnych Rules of Engagement — jako weryfikacja własnej izolacji, nie jako działanie wobec cudzych systemów.

Audit per tenant

Dziś audit-log nie jest jeszcze scope'owany per org (produkcja publiczna = single-tenant-demo, jedna organizacja). Docelowo (ROADMAP) każdy wpis audytu jest kotwiczony do tenant_id, a dostęp do logów jest scope'owany tak samo jak dane — administrator Tenanta A nie widzi zdarzeń Tenanta B.

Kotwica tenantowa

Każde zdarzenie (kto, co, kiedy, na jakim rekordzie) nosi tenant_id. Log jest niereużywalny między tenantami.

ROADMAP

Scoped odczyt

Widok audytu respektuje tę samą politykę RLS co dane. Brak globalnego „superwidoku" bez wyraźnej roli platformy i śladu.

ROADMAP

Append-only

Wpisy audytu tylko dopisywane, z chain-of-custody. Zachowanie integralności śladu (dziś: hash + chain w DB, MVP).

MVP / ROADMAP (per-tenant)

Data lifecycle — retencja / purge / eksport (DPA-aligned)

Cykl życia danych klienta zgodny z umową powierzenia (DPA) i zasadami RODO (minimalizacja, ograniczenie przechowywania, prawo do usunięcia/przenoszenia). Spec docelowa; realizacja per tenant = ROADMAP.

FazaCo obejmujeOdniesienieStatus
Retencja Okres przechowywania danych engagementu ustalany per tenant w DPA; po jego upływie dane kwalifikują się do usunięcia. Zasada ograniczenia przechowywania. RODO art. 5(1)(e); zapisy DPA ROADMAP P1
Purge Trwałe usunięcie danych tenanta na żądanie lub po terminie retencji, wraz z evidence i kopiami roboczymi; potwierdzenie usunięcia w audycie (scoped do tenanta). RODO art. 17 (prawo do usunięcia) ROADMAP P1
Eksport Przenoszalny pakiet danych tenanta (evidence-package, incydenty, audit) w formacie strukturalnym; do migracji, offboardingu lub realizacji prawa do przenoszenia. RODO art. 20 (przenoszalność) ROADMAP P1
DPA-aligned, nie porada prawna. Powyższe mapowanie na RODO/DPA to wsparcie decyzji (decision-support), nie porada prawna. Konkretne okresy retencji, zakres purge i format eksportu wymagają zapisania w umowie powierzenia przetwarzania i przeglądu przez radcę/kancelarię przed wdrożeniem.

Skrót stanu

2
Org zasiane na dowód (staging)
app-level scoping · real PostgreSQL
26
Testy izolacji PASS / 0 FAIL
12 IDOR + 14 tenancy (off/on/admin/fail-closed)
4
Poziomy najmu (spec)
tenant · org(MVP) · project · engagement
P1
Priorytet DB RLS
wymaga migracji DB + ACK

Czego ta strona NIE deklaruje

To nie jest ogłoszenie gotowej wielodostępności dla banku SIFI. App-level org-scoping jest zaimplementowany i dowiedziony (MVP), ale RLS w bazie, pełna hierarchia tenant/project/engagement, audit i lifecycle per tenant pozostają szkieletem do zbudowania (ROADMAP P1). Produkcja publiczna działa dziś w trybie single-tenant-demo (jedna organizacja demo) — świadomie, nie z powodu braku kodu. Dowody: roadmapie dev.
„100%" u nas znaczy pokrycie dowodowe, nie nieprzenikalność. Mamy dziś dowód (kod+test+endpoint) na izolację app-level po org — mówimy o niej jako MVP. Nie mamy dowodu na RLS w bazie ani na pełną hierarchię najmu — te elementy pozostają ROADMAP. Pełny rejestr granic dojrzałości: /known-limitations; przetwarzanie danych: /data-processing; gotowość enterprise: /enterprise-readiness.
Granica etyczna i prawna. ipIII jest narzędziem obrony i zgodności (GRC/blue). Testy izolacji (IDOR/BOLA) prowadzone są wyłącznie defensywnie, na danych syntetycznych i w granicach pisemnych Rules of Engagement — jako weryfikacja własnej separacji, nie działanie wobec cudzych systemów. Mapowania obowiązków (RODO/DPA) to wsparcie decyzji, nie porada prawna.

Powiązane: rejestr granic dojrzałości → /known-limitations · przetwarzanie danych → /data-processing · gotowość enterprise → /enterprise-readiness.