Ana içeriğe geç

Migration Playbook (Deterministik Sira)

Bu dokumanin amaci, migration calistirma sirasini tek kurala baglamak ve development/staging/production ortamlari arasinda ayni sonucu garantilemektir.

Garanti Sozlesmesi

Asagidaki 5 kural birlikte saglanmadan birebirlik garantisi verilmis sayilmaz:

  1. Her migration immutable olmalidir: merge sonrasi dosya icerigi degistirilemez.
  2. Calisma sirasi yalnizca version alanina gore belirlenmelidir.
  3. Her migration checksum ile dogrulanmalidir.
  4. Migration kosumu tek yazici (global lock) ile korunmalidir.
  5. Kosum sonrasinda schema fingerprint ayni degere ulasmelidir.

Dosya Adlandirma Standardi

Migration dosyalari su formatla adlandirilir:

VYYYYMMDDHHMMSS__kisa-aciklama.sql

Ornek:

V20260409103000__create_rule_events_indexes.sql
V20260409104500__add_synthesis_scope_constraints.sql

Kurallar:

  • YYYYMMDDHHMMSS UTC olmalidir.
  • Ayni timestamp ikinci kez kullanilamaz.
  • Sira lexicographic olarak da ayni kalmalidir.

Fazlara Gore Zorunlu Migration Sirasi

Bir release icindeki migrationlar asagidaki faz sirasiyla yazilir ve calistirilir:

  1. TYPES: enum, domain, custom type degisiklikleri
  2. REF: sozluk/referans tablolari (statuses, message_types, vb.)
  3. CORE: ana varlik tablolari (users, devices, streams, vb.)
  4. REL: iliski/atama tablolari (*_assignments, *_state, vb.)
  5. CONSTRAINT: FK, unique, check, not null
  6. INDEX: performans indeksleri ve index concurrent operasyonlari
  7. BACKFILL: veri tasima/normalizasyon scriptleri
  8. VIEW_TRG_JOB: view, trigger, function, scheduled-job baglantilari
  9. GRANT: rol ve yetki dagitimi

Not: INDEX CONCURRENTLY gibi transaction-disinda kosmasi gereken operasyonlar ayri migration dosyasinda tutulur.

Zorunlu Meta Tablolari

Tum ortamlarda ayni yapiyla bulunmalidir:

CREATE TABLE IF NOT EXISTS schema_migrations (
version varchar(20) PRIMARY KEY,
name varchar(255) NOT NULL,
checksum_sha256 varchar(64) NOT NULL,
executed_at timestamp NOT NULL DEFAULT now(),
execution_ms int NOT NULL,
tool_version varchar(64) NOT NULL
);

CREATE TABLE IF NOT EXISTS migration_lock (
id int PRIMARY KEY,
is_locked boolean NOT NULL,
updated_at timestamp NOT NULL DEFAULT now()
);

INSERT INTO migration_lock (id, is_locked)
VALUES (1, false)
ON CONFLICT (id) DO NOTHING;

Calistirma Protokolu (Her Ortam Icin Ayni)

  1. Migration lock al.
  2. schema_migrations icindeki son version degerini oku.
  3. Yeni dosyalari artan version sirasinda sec.
  4. Her dosya icin checksum dogrula.
  5. Dosyayi calistir, basariliysa schema_migrations kaydi yaz.
  6. Tum dosyalar bitince lock birak.

Basarisizlik kurali:

  • Hata halinde lock birakilir.
  • Basarisiz migration tekrar denenmeden once yeni bir duzeltme migrationi yazilir.
  • Daha once basarili kosmus migration dosyasi geriye donuk degistirilmez.

Schema Fingerprint Kontrolu

Her ortam migration sonrasi ayni fingerprint uretmelidir. Asagidaki sorgu mantigi kullanilir:

SELECT md5(string_agg(row_text, E'\n' ORDER BY row_text)) AS schema_fingerprint
FROM (
SELECT concat_ws('|', table_schema, table_name, column_name, data_type, is_nullable, ordinal_position) AS row_text
FROM information_schema.columns
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
) t;

Kurallar:

  • schema_fingerprint degeri release notuna yazilir.
  • staging ve production fingerprint degeri ayni degilse deploy tamamlanmis sayilmaz.

CI Gate (Zorunlu)

Her PR icin asagidaki kontroller kosulur:

  1. Sifir veritabani uzerinde bastan sona migration replay
  2. Son production snapshot klonu uzerinde ileri migration replay
  3. Checksum dogrulamasi (schema_migrations ile dosya checksum karsilastirmasi)
  4. Fingerprint uretimi ve beklenen deger karsilastirmasi

Bu adimlardan biri basarisizsa merge bloklanir.

Yedekleme, Geri Yukleme ve Rollback Tatbikati (Zorunlu)

Yedekleme ve rollback surecleri yalnizca dokumanda kalamaz; duzenli tatbikat ve kanit zorunludur.

Tatbikat Ritmi

  1. Her ay en az 1 kez tam tatbikat: backup -> restore -> rollback.
  2. Her release oncesi staging ortaminda en az 1 restore provasi.
  3. Her ceyrekte production benzeri snapshot ile game-day tatbikati.

Basari Kriterleri

  • Backup dosyasi olusmali ve checksum dogrulanmali.
  • Restore sonrasi schema_fingerprint beklenen degerle eslesmeli.
  • Rollback sonrasi uygulama kritik sorgulari hata vermeden calismali.
  • RTO/RPO olcumleri kaydedilmeli ve hedef sinirlarin icinde olmali.

Kanit Zorunlulugu

Her tatbikat icin kanit dosyasi zorunludur:

  • Dizin: project-qapu/backend/migrations/drills/
  • Dosya adi: YYYY-MM-DD-backup-restore-rollback.md
  • Icerik: Backup Kaniti, Restore Kaniti, Rollback Kaniti, Sonuc bolumleri
  • Her bolumde Durum: PASS veya Durum: FAIL acikca yazilmalidir.

CI Denetimi

  • validate:drills komutu son tatbikat tarihini ve kanit formatini denetler.
  • Son tatbikat 45 gunden eskiyse CI fail olur.
  • Kanit dosyasinda zorunlu bolumler veya PASS/FAIL kaydi yoksa CI fail olur.

Otomasyon Komutlari

Bu repoda migration denetimi icin su komutlar kullanilir:

npm run lock:migration-checksums
npm run validate:migrations

Aciklama:

  • lock:migration-checksums: project-qapu/backend/migrations altindaki SQL dosyalarinin checksum manifestini (checksums.sha256) olusturur/gunceller.
  • validate:migrations: dosya adi formati, sira ve checksum manifest tutarliligini dogrular.

Policy:

  • PR merge oncesi validate:migrations zorunlu pass etmelidir.
  • Migration dosyasi eklenip checksum manifest guncellenmediyse PR reddedilir.

Branch ve Hotfix Kurali

  • Iki branch ayni anda migration eklediyse daha gec merge olan branch yeni timestamp ile migration dosyasini yeniden olusturur.
  • Hotfix migrationlari da ayni naming ve checksum kurallarina tabidir.
  • Rebase sirasinda migration dosyasi icerigi degistirilmez; gerekiyorsa yeni migration eklenir.

Data-Model ile Uyum

  • FK ekleme/silme gibi iliski degisikliklerinde once Master ERD, sonra migration, sonra ilgili tablo dokumani guncellenir.
  • Migration fazi CONSTRAINT ise FK degisikligi acikca migration isminde gecmelidir.

FK Davranis Zorunlulugu

Tum yeni FK migrationlari asagidaki kurala uymak zorundadir:

  • Her FK tanimi acikca ON DELETE ve ON UPDATE davranisi icermelidir.
  • NO ACTION veya varsayilan davranisa birakma kabul edilmez.
  • Davranis secimi yalnizca RESTRICT, CASCADE, SET NULL arasindan yapilir.

Kaynak politika:

  • Kritik iliskiler icin resmi matris Master ERD sayfasindaki Kritik FK Davranis Kurallari bolumudur.

Ornek migration kalibi:

ALTER TABLE child_table
ADD CONSTRAINT fk_child_parent
FOREIGN KEY (parent_id)
REFERENCES parent_table(id)
ON DELETE RESTRICT
ON UPDATE CASCADE;

PR kontrolu:

  • FK iceren migration dosyasinda ON DELETE ve ON UPDATE ifadeleri yoksa PR reddedilir.

Is Kurali Zorunlulugu (DB-First)

Is kurallari yalniz uygulama koduna birakilamaz. Veri butunlugunu koruyan kurallar veritabaninda zorunlu olarak tanimlanir.

Zorunlu araclar:

  • UNIQUE
  • Partial UNIQUE INDEX (CREATE UNIQUE INDEX ... WHERE ...)
  • CHECK

Uygulama kurali:

  • Uygulama katmani ek kontrol yapabilir, ancak DB tarafindaki kuralin yerine gecemez.
  • Constraint migrationlari __constraint- adlandirma desenini kullanmalidir.

Ornek Kurallar

-- Ayni cihaz + grup atamasi ikinci kez yazilamaz
ALTER TABLE group_assignments
ADD CONSTRAINT uq_group_assignments_device_group UNIQUE (device_id, group_id);

-- Ayni user + message icin tek okuma durumu kaydi
ALTER TABLE message_read_state
ADD CONSTRAINT uq_message_read_state_message_user UNIQUE (message_id, user_id);

-- Scope tipi ile hedef kolonlarin tutarliligi
ALTER TABLE synthesis_assignments
ADD CONSTRAINT ck_synthesis_assignments_scope
CHECK (
(scope_type = 'global' AND device_id IS NULL AND group_id IS NULL) OR
(scope_type = 'device' AND device_id IS NOT NULL AND group_id IS NULL) OR
(scope_type = 'group' AND device_id IS NULL AND group_id IS NOT NULL)
);

-- Sadece aktif satirlar icin tek global atama
CREATE UNIQUE INDEX uq_synth_assignments_active_global
ON synthesis_assignments (rule_id)
WHERE scope_type = 'global' AND is_active = true;

CI Denetimi

  • validate:migrations komutu su kontrolleri zorunlu uygular:
    • FK varsa ON DELETE + ON UPDATE zorunlu
    • __constraint- migrationlarinda en az bir UNIQUE/Partial UNIQUE/CHECK/ADD CONSTRAINT tanimi zorunlu
    • Dosya adinda partial-unique geciyorsa SQL icinde CREATE UNIQUE INDEX ... WHERE ... zorunlu

Idempotency ve Duplicate Onleme (DB-Embedded)

Idempotency ve duplicate onleme uygulama koduna birakilamaz; veri modelinde zorunlu olarak tanimlanir.

Zorunlu Veri Modeli Kurallari

  1. Dis sistemden gelen write islemlerinde idempotency anahtari kalici tabloda saklanir.
  2. Ayni idempotency anahtari ikinci kez kabul edilmez (UNIQUE).
  3. Event/inbox/outbox benzeri tekrar riski olan tablolarda dogal anahtar veya kaynak olay kimligi uniq olmalidir.
  4. Tekrarli yazimlarda davranis acik olmalidir: ON CONFLICT DO NOTHING veya ON CONFLICT ... DO UPDATE.

Onerilen Sema Kalibi

CREATE TABLE IF NOT EXISTS idempotency_keys (
id bigserial PRIMARY KEY,
scope varchar(64) NOT NULL,
idempotency_key varchar(128) NOT NULL,
request_hash varchar(64) NOT NULL,
first_seen_at timestamp NOT NULL DEFAULT now(),
expires_at timestamp NULL,
CONSTRAINT uq_idempotency_keys_scope_key UNIQUE (scope, idempotency_key)
);

-- Harici olay duplicate onleme (ornek)
CREATE UNIQUE INDEX uq_rule_events_source_event
ON rule_events (source_system, source_event_id);

Yazma Semantigi

INSERT INTO idempotency_keys (scope, idempotency_key, request_hash)
VALUES ('rule-engine', :idempotency_key, :request_hash)
ON CONFLICT (scope, idempotency_key) DO NOTHING;

Yorum:

  • Insert 0 satir etkilediyse islem duplicate kabul edilir ve side-effect calistirilmaz.
  • Idempotency kaydina bagli asil write islemi ayni transaction sinirlari icinde ele alinmalidir.

CI Denetimi

  • Dosya adinda idempotency, dedup veya duplicate gecen migrationlar icin validate:migrations su kurallari zorunlu uygular:
    • En az bir UNIQUE veya CREATE UNIQUE INDEX olmali.
    • SQL icinde INSERT INTO varsa ON CONFLICT davranisi da tanimli olmali.

Soft Delete, Audit Log ve Kim-Ne-Zaman Zorunlulugu

Kritik tablolarda degisiklik izi uygulama koduna birakilamaz; veri modelinde zorunlu tutulur.

Kritik Tablolar (Append-Only Istisna)

  • streams
  • rule_events
  • logs

Bu tablolarda soft delete uygulanmaz; bunun yerine asagidaki kural zorunludur:

  • Fiziksel UPDATE/DELETE yasak (append-only yazma modeli)
  • Olay zamani zorunlu (create_time veya stream_time)
  • Kaynagi tanimlayan actor baglami zorunlu (user_id, service_id, device_id, details vb.)

Audit Log Zorunlulugu

  • Kritik mutable tablolarda UPDATE/DELETE aksiyonlari icin append-only audit log tablosuna yazim zorunludur.
  • Audit kaydi asgari su alanlari icermelidir:
    • table_name
    • row_pk
    • operation (INSERT/UPDATE/SOFT_DELETE/RESTORE)
    • changed_by
    • changed_at
    • before_json
    • after_json

Mevcut logs tablosu uzerinden audit yapmak mumkundur; ancak yalnizca asagidaki sozlesme saglanirsa kabul edilir:

  • event_code zorunlu olarak AUDIT_MUTATION olmalidir.
  • details JSON icinde su alanlar zorunludur:
    • table_name
    • row_pk
    • operation
    • changed_by
    • changed_at
    • before_json
    • after_json
  • Audit kayitlari append-only kalmali, logs uzerinde UPDATE/DELETE uygulanmamalidir.
  • Audit saklama suresi operasyonel loglardan bagimsiz yonetilmelidir (retention ayrimi).

Ornek details semasi:

{
"table_name": "inbox",
"row_pk": "101",
"operation": "SOFT_DELETE",
"changed_by": 7,
"changed_at": "2026-04-09T12:10:00Z",
"before_json": {"is_deleted": false, "delete_time": null},
"after_json": {"is_deleted": true, "delete_time": "2026-04-09T12:10:00Z"}
}

CI Denetimi

  • Dosya adinda audit, soft-delete veya delete-policy gecen migrationlar icin validate:migrations su kontrolleri uygular:
    • Kritik tablolardan en az birine dokunulmus olmalidir.
    • SQL icinde soft-delete (is_deleted veya deleted_at) ifadesi bulunmalidir.
    • SQL icinde audit actor/zaman (created_by, updated_by, changed_by, changed_at) ifadelerinden en az biri bulunmalidir.

Enum ve Sozluk Versiyonlama

Enum ve sozluk (reference dictionary) degisiklikleri versiyonlu ve geri uyumlu yonetilir.

Zorunlu Adlandirma

  • Enum tipi degisikligi iceren migration dosyalari: __types-...
  • Sozluk veri/model degisikligi iceren migration dosyalari: __ref-...

SQL Baslik Sozlesmesi (Zorunlu)

__types- ve __ref- migration dosyalarinin basinda asagidaki baslik bulunur:

-- COMPAT: backward-compatible

Eger degisiklik breaking ise ek alanlar zorunludur:

-- COMPAT: breaking
-- COMPATIBILITY-WINDOW: 2-release
-- FALLBACK: enum_alias_mapping_v2

Geriye Uyumluluk Kurallari

  1. Enum degerleri ayni major hatta silinmez veya yeniden adlandirilmaz; yalnizca ekleme yapilir.
  2. Sozluk kodlari (code, name gibi dis entegrasyona acik anahtarlar) in-place degistirilmez; yeni versiyonlu kayit eklenir.
  3. Breaking degisiklikte en az 2 release boyunca eski degerler deprecated olarak yasatilir.
  4. Eski degerlerin kullanimdan cikmasi icin mapping/fallback katmani zorunludur.
  5. Uygulama kodu yeni degeri desteklemeden enum/sozluk breaking migration productiona cikamaz.

Sozluk Tablolari Icin Onerilen Sema

ALTER TABLE message_types
ADD COLUMN IF NOT EXISTS version integer NOT NULL DEFAULT 1;

ALTER TABLE message_types
ADD COLUMN IF NOT EXISTS is_deprecated boolean NOT NULL DEFAULT false;

ALTER TABLE message_types
ADD COLUMN IF NOT EXISTS replaced_by_code varchar(64) NULL;

Enum Degisimi Icin Onerilen Akis

  1. __types- migration: yeni enum degerini ekle (breaking degilse append-only).
  2. __ref- migration: sozluk tablosuna yeni degeri ekle, eskiyi is_deprecated=true yap.
  3. BACKFILL: gerekiyorsa eski kayitlari yeni degere map et.
  4. CONSTRAINT: yeni versiyon kurallarini zorunlu kil.

CI Denetimi

  • validate:migrations komutu __types- ve __ref- dosyalarinda COMPAT basligini zorunlu kontrol eder.
  • COMPAT: breaking ise COMPATIBILITY-WINDOW ve FALLBACK satirlari yoksa PR reddedilir.

Isimlendirme Standardi (Kesin)

Tum tablo ve SQL nesneleri tek dil ve tek formatta tutulur.

Dil Kurali

  • SQL identifier adlari (tablo, kolon, constraint, index, enum/type) yalnizca Ingilizce ve ASCII olmalidir.
  • Dokuman aciklamalari Turkce yazilir.
  • Identifier icinde Turkce karakter, bosluk ve tire kullanilmaz.

Format Kurali

  • Tablo adlari: lower_snake_case ve cogul (users, rule_events, message_read_state)
  • Kolon adlari: lower_snake_case
  • Constraint adlari:
    • Primary key: pk_<table>
    • Foreign key: fk_<table>_<ref_table>
    • Unique: uq_<table>_<columns>
    • Check: ck_<table>_<rule>
  • Index adlari:
    • Normal index: ix_<table>_<columns>
    • Unique index: uq_<table>_<columns>
  • Enum/type adlari: lower_snake_case

Tablo Dokumani Format Kurali

project-qapu/backend/data-model/tables/** altindaki tum tablo dokumanlari su kalibi izler:

  1. Baslik: <table_name> Tablosu
  2. Ana H1: `table_name`
  3. Kolonlar bolumu
  4. Indeksler bolumu
  5. Ornek Kayitlar bolumu

Not: table_name daima SQL'deki canonical tablo adiyla birebir ayni yazilir.

CI Denetimi

  • validate:migrations komutu migration SQL icindeki identifier adlandirma kurallarini zorunlu denetler.
  • Kural disi adlandirma tespit edilirse PR reddedilir.

Indeks Tasarimi ve EXPLAIN Zorunlulugu

Indeksler varsayimla degil, kritik sorgularin sorgu planiyla tasarlanir.

Faz ve Dosya Kurali

  • Indeks migration dosyalari __index- ile baslamalidir.
  • Her __index- migration icin zorunlu bir plan raporu bulunmalidir:
    • project-qapu/backend/migrations/explain/<migration-dosyasi>.md

Ornek:

V20260409120000__index-add-rule-events-device-time.sql
project-qapu/backend/migrations/explain/V20260409120000__index-add-rule-events-device-time.md

EXPLAIN Komutu (Zorunlu)

Her kritik sorgu icin asagidaki format kullanilir:

EXPLAIN (ANALYZE, BUFFERS, VERBOSE, FORMAT JSON)
<kritik-sorgu>;

Rapor hem oncesi hem sonrasi plani icermelidir.

Kritik Sorgu Katalogu

Kritik sorgular tek listede tutulur:

  • project-qapu/backend/migrations/explain/critical-queries.md

Indeks migration raporu, etkiledigi kritik sorgu kimliklerini acikca belirtmelidir.

Kabul Kriterleri

Bir indeks migrationinin kabul edilmesi icin:

  1. En az bir kritik sorgu icin BEFORE PLAN ve AFTER PLAN bulunmali.
  2. Plan tipinde iyilesme hedeflenmeli (or. Seq Scan -> Index Scan/Bitmap Heap Scan).
  3. actual total time, rows, shared read/hit gibi metrikler raporda yer almali.
  4. Regresyon varsa migration merge edilmez.

CI Denetimi

  • validate:migrations komutu __index- migrationlar icin explain raporu varligini ve temel bolumlerini zorunlu denetler.
  • Explain raporu yoksa veya eksikse PR reddedilir.