Appearance
Veritabanı Şeması (Database Schema Definition)
Bu doküman, Humindx platformunun PostgreSQL veritabanı şemasını, tablo ilişkilerini, indeksleri ve Row-Level Security (RLS) politikalarını tanımlar. Tüm doküman boyunca referans edilen tablolar (context_rooms, trait_scores, audit_events, consent_grants vb.) burada tek bir kaynakta birleştirilmiştir.
Kapsam Uyarısı: Bu doküman, veritabanı yapısını ve migration stratejisini kapsar. RLS politikalarının mimari gerekçeleri için
context-rooms-design.md, audit loglarının olay yapısı için../security/audit-trail.mddosyasına bakınız.
1. ER Diyagramı (Entity-Relationship)
2. Tablo Detayları ve İndeksler
2.1. users
Kimlik veritabanı (Identity DB). Psikometrik motorun erişemediği alan.
sql
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT NOT NULL UNIQUE, -- AES-256 ile şifreli
password_hash TEXT NOT NULL,
locale VARCHAR(10) DEFAULT 'tr-TR',
genome_id UUID NOT NULL UNIQUE, -- Anonim referans
subscription VARCHAR(20) DEFAULT 'FREE',
created_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ -- NULL = aktif, SET = ghost node
);
CREATE INDEX idx_users_genome ON users(genome_id);
CREATE INDEX idx_users_email ON users(email);2.2. context_rooms
Kullanıcı başına 4 oda. Oluşturma: kayıt anında otomatik.
sql
CREATE TABLE context_rooms (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
room_type VARCHAR(20) NOT NULL CHECK (room_type IN ('PROFESSIONAL', 'SOCIAL', 'CLINICAL', 'DISCOVERY')),
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, room_type)
);2.3. trait_scores
Materialized State — Odalar bazlı güncel skorlar.
sql
CREATE TABLE trait_scores (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
room_id UUID NOT NULL REFERENCES context_rooms(id) ON DELETE CASCADE,
trait_name VARCHAR(50) NOT NULL, -- 'bigfive_openness', 'riasec_social' vb.
current_score FLOAT NOT NULL CHECK (current_score >= 0 AND current_score <= 100),
confidence_score FLOAT DEFAULT 0.0 CHECK (confidence_score >= 0 AND confidence_score <= 1),
interaction_count INT DEFAULT 0,
metadata JSONB DEFAULT '{}',
updated_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(room_id, trait_name)
);
-- RLS aktifleştirme
ALTER TABLE trait_scores ENABLE ROW LEVEL SECURITY;
-- B2B Gateway rolü sadece PROFESSIONAL odayı görebilir
CREATE POLICY b2b_isolation ON trait_scores
FOR SELECT TO b2b_gateway_role
USING (
room_id IN (
SELECT id FROM context_rooms
WHERE room_type = 'PROFESSIONAL'
)
);
CREATE INDEX idx_trait_room ON trait_scores(room_id);
CREATE INDEX idx_trait_name ON trait_scores(trait_name);2.4. audit_events
Append-only, immutable log. Hash chaining ile korunan.
sql
CREATE TABLE audit_events (
event_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
genome_id UUID NOT NULL, -- FK yok: ghost node sonrası bile yaşar
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
actor_type VARCHAR(10) NOT NULL CHECK (actor_type IN ('SYSTEM', 'LLM', 'USER')),
event_type VARCHAR(30) NOT NULL,
context_room VARCHAR(20),
payload JSONB NOT NULL,
event_hash TEXT NOT NULL,
prev_hash TEXT NOT NULL,
-- Bu tabloya UPDATE ve DELETE yasak
CHECK (TRUE) -- Uygulama seviyesinde enforce
);
-- Zaman bazlı sorgular için
CREATE INDEX idx_audit_genome_time ON audit_events(genome_id, timestamp DESC);
CREATE INDEX idx_audit_event_type ON audit_events(event_type);
-- Append-only garantisi: DBA bile silemez
REVOKE DELETE, UPDATE ON audit_events FROM PUBLIC;
REVOKE DELETE, UPDATE ON audit_events FROM app_role;2.5. consent_grants
Akıllı Gizlilik Sözleşmesi izin tablosu.
sql
CREATE TABLE consent_grants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
tenant_id UUID NOT NULL REFERENCES tenants(id),
target_workspace VARCHAR(20) NOT NULL CHECK (target_workspace IN ('hiring', 'talent')),
level INT NOT NULL CHECK (level IN (1, 2, 3)),
is_active BOOLEAN DEFAULT TRUE,
granted_at TIMESTAMPTZ DEFAULT NOW(),
revoked_at TIMESTAMPTZ
);
CREATE INDEX idx_consent_user_tenant ON consent_grants(user_id, tenant_id);
CREATE INDEX idx_consent_active ON consent_grants(is_active) WHERE is_active = TRUE;2.6. vector_embeddings
Gürültü enjekte edilmiş vektörler. RAG pipeline'ı besler.
sql
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE vector_embeddings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
genome_id UUID NOT NULL,
room_id UUID NOT NULL REFERENCES context_rooms(id) ON DELETE CASCADE,
embedding vector(1536), -- OpenAI text-embedding-3-small boyutu
source_label VARCHAR(10) CHECK (source_label IN ('PRO', 'SOCIAL', 'NEUTRAL')),
epsilon_used FLOAT NOT NULL, -- DP gürültü bütçesi kaydı
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- RAG sorguları için HNSW indeksi
CREATE INDEX idx_vector_hnsw ON vector_embeddings
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Oda filtresi (RAG'da SOCIAL hariç tutma) için
CREATE INDEX idx_vector_room_label ON vector_embeddings(room_id, source_label);2.7. B2B Tabloları (tenants, workspaces, tenant_members, culture_templates)
sql
CREATE TABLE tenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
company_name TEXT NOT NULL,
culture_dna JSONB,
active_culture_version VARCHAR(10),
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE workspaces (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
type VARCHAR(20) NOT NULL CHECK (type IN ('hiring', 'talent'))
);
CREATE TABLE tenant_members (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
user_id UUID NOT NULL, -- B2B panel kullanıcısı (İK, yönetici)
role VARCHAR(20) NOT NULL CHECK (role IN ('HR_ADMIN', 'RECRUITER', 'TEAM_LEADER')),
team_id UUID -- Sadece TEAM_LEADER için
);
CREATE TABLE culture_templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
version VARCHAR(10) NOT NULL,
ideal_profile JSONB NOT NULL,
riasec_target VARCHAR(10),
effective_date TIMESTAMPTZ DEFAULT NOW(),
is_active BOOLEAN DEFAULT TRUE
);
-- Workspace bazlı RLS
ALTER TABLE tenant_members ENABLE ROW LEVEL SECURITY;2.8. chat_sessions ve passport_shares
sql
CREATE TABLE chat_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
genome_id UUID NOT NULL,
agent_type VARCHAR(20) NOT NULL,
scenario_label VARCHAR(10),
label_overridden BOOLEAN DEFAULT FALSE,
status VARCHAR(20) DEFAULT 'ACTIVE',
started_at TIMESTAMPTZ DEFAULT NOW(),
ended_at TIMESTAMPTZ
);
CREATE TABLE passport_shares (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
signed_token TEXT NOT NULL,
granted_level INT NOT NULL CHECK (granted_level IN (1, 2, 3)),
expires_at TIMESTAMPTZ NOT NULL,
is_revoked BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW()
);3. Migration Stratejisi
| Aşama | Kapsam | Araç |
|---|---|---|
| Geliştirme | Lokal Docker PostgreSQL, seed data ile | Prisma Migrate veya golang-migrate |
| Staging | Managed PostgreSQL (RDS/Cloud SQL), RLS politikalarının testi | CI/CD pipeline'da otomatik migration |
| Production | Blue-Green deployment, zero-downtime migration | Flyway veya Prisma Migrate + manual review |
Kritik Kurallar:
audit_eventstablosuna asla destructive migration (DROP COLUMN, ALTER TYPE) uygulanmaz. Yeni alanlar sadece eklenir (additive-only).- RLS politikaları her migration'da test edilir: "B2B rolü SOCIAL odayı görebiliyor mu?" assertion'ı CI'da çalışır.
4. Seed Data (Geliştirme Ortamı)
environment-setup.md'deki Docker kurulumu sonrası, test verileriyle hızlı başlangıç için:
sql
-- Test kullanıcısı
INSERT INTO users (id, email, password_hash, genome_id, subscription)
VALUES ('uuid-test-1', 'test@humindx.dev', '$2b$...', 'genome-test-1', 'PREMIUM');
-- 4 Bağlam Odası
INSERT INTO context_rooms (user_id, room_type) VALUES
('uuid-test-1', 'PROFESSIONAL'),
('uuid-test-1', 'SOCIAL'),
('uuid-test-1', 'CLINICAL'),
('uuid-test-1', 'DISCOVERY');
-- Başlangıç çapası skorları (S0)
INSERT INTO trait_scores (room_id, trait_name, current_score, confidence_score)
SELECT cr.id, trait.name, trait.score, 0.14
FROM context_rooms cr
CROSS JOIN (VALUES
('bigfive_openness', 65), ('bigfive_conscientiousness', 55),
('bigfive_extraversion', 70), ('bigfive_agreeableness', 80),
('bigfive_neuroticism', 35)
) AS trait(name, score)
WHERE cr.user_id = 'uuid-test-1' AND cr.room_type = 'DISCOVERY';
-- Test tenant
INSERT INTO tenants (id, company_name, active_culture_version)
VALUES ('tenant-test-1', 'Acme Corp Test', 'v1');Son Güncelleme: 2026-04-15 — Tam ER diyagramı, SQL DDL (RLS dahil), HNSW vektör indeksi, migration stratejisi ve seed data tanımlandı.