243 lines
17 KiB
Markdown
243 lines
17 KiB
Markdown
# 05 — Tek-Tık Kurucu (One-Click Installer)
|
||
|
||
> Kısa özet: Sahadaki tek giriş noktası **grafik operatör uygulamasıdır**: `sudo bf` → Kurulum sekmesi → "Bu cihazı kur". Bayi no doğrulaması, 18 modül, idempotent yeniden-koşu ve final-check kapısı `blueforce-install.sh`'ın işidir. Paketler git deposunda taşınır; **kurulum internetsizdir**. Terminal yedeği: `sudo bf --tui`.
|
||
|
||
- Dosya: `docs/05-ONE-CLICK-INSTALLER.md`
|
||
- İlgili kararlar: `24-DECISION-LOG.md#K-09` (tek kurucu), `K-11` (update kapalı), `K-12` (kimlik formatı), `K-03` (bf-gui), `K-10` (Docker disiplini), `K-16` (offline)
|
||
- İlgili dokümanlar: `33-OPERATOR-CONSOLE.md` (arayüz rehberi), `27-OFFLINE-PROVISIONING.md` (paket deposu sözleşmesi)
|
||
- Durum: [ ] Taslak
|
||
|
||
---
|
||
|
||
## 1. Amaç
|
||
|
||
Saha teknisyeninin uzmanlık gerektirmeden cihazı standarda getirmesi: tek giriş noktası (`sudo bf`), tek girdi (8 haneli bayi no), net sonuç (`PROVISIONED_OFFLINE` / hata + neden). Yarım kalan veya hatalı kurulumun güvenli tekrarı.
|
||
|
||
Teknisyen terminal komutu, bayrak veya dosya yolu ezberlemez: kurulum grafik arayüzdeki düğmeyle başlatılır, komut arayüzde gösterilir ve onay alınmadan çalıştırılmaz.
|
||
|
||
## 2. Kapsam
|
||
|
||
- Kapsam içi: grafik uygulama üzerinden kurulum akışı, kurucu betiğin komut yüzeyi, bayi-no doğrulama, 18 modül listesi ve sırası, paket deposu keşfi ve hata durumları, idempotency kuralları, log/çıkış kodları.
|
||
- Kapsam dışı: modül iç kodları (repo `scripts/install/installer/modules/`), imaj üretim yöntemi (04), filo-side yapılandırma (09), arayüzün tüm ekranları (33).
|
||
|
||
## 3. Kararlar
|
||
|
||
```text
|
||
KARAR: Saha kurulumunun tek giriş noktası grafik operatör uygulamasıdır: `sudo bf` → Kurulum sekmesi → "Bu cihazı kur". Kurucu betik (`scripts/install/blueforce-install.sh`) bu düğmenin çağırdığı motordur ve aynı akış terminalden `sudo bf --tui` ile de yürütülebilir.
|
||
GEREKÇE: Tek giriş noktası ve tek düğme teknisyen hatasını en aza indirir; grafik arayüz komutu çalıştırmadan önce gösterir ve onay ister, böylece görünmez komut kalmaz. Bayi no `^[0-9]{8}$` ile doğrulanır; format kapısı yanlış kimliğin 9 sisteme yayılmasını baştan engeller (K-12).
|
||
ALTERNATİF: Çok scriptli kurulum (ağ.sh, gui.sh, …) — sıra hatası ve atlanan adım riski nedeniyle elendi.
|
||
RİSK: Tek dosya büyüdükçe bakımı zorlaşır; azaltma: 18 bağımsız modül + ana orkestratör ayrımı. Grafik arayüz `python3-tk` gerektirir; azaltma: paket offline depoda pinlidir ve ekransız/paketsiz ortamda uygulama Türkçe yönlendirme yapıp `--tui` önerir.
|
||
MALİYET: Ücretsiz.
|
||
LİSANS: Yok (şirket içi script + standart kütüphane ile yazılmış Python arayüz).
|
||
```
|
||
|
||
```text
|
||
KARAR: Kurucu 18 modülden oluşur (`01-precheck` … `18-final-check`); her modül idempotenttir — yeniden koşu güvenli ve kaldığı yerden tamamlayıcıdır. Paketler yerel paket deposundan gelir ve depo otomatik bulunur; `--offline` bayrağı zorunlu değildir.
|
||
GEREKÇE: Saha elektriği/kesintisi yarım kurulum üretir; idempotency olmadan her kesinti temiz-kurulum demektir. Final-check kapısı (modül 18) exit 0 vermeden cihaz kurulu sayılmaz; offline akışta sonuç `PROVISIONED_OFFLINE`, token sonrası `ENROLLED`, yalnız merkezi kanallar doğrulanınca `READY` olur (27/29). Depoyu kuran kişinin hatırlaması gereken bayrak sayısı sıfırdır.
|
||
ALTERNATİF: Tek seferlik (non-idempotent) script — kesinti durumunda belirsiz ara durum nedeniyle elendi. `--offline` bayrağını zorunlu tutmak — operatör bayrağı unuttuğunda kurulum durur; bayrak geriye uyumluluk için korundu.
|
||
RİSK: Modülün idempotent yazılmaması (çift kayıt, çift key); azaltma: §10'daki çift-koşu testi her modül için zorunlu.
|
||
MALİYET: Ücretsiz.
|
||
LİSANS: Yok.
|
||
```
|
||
|
||
## 4. Neden Bu Karar?
|
||
|
||
700 cihaz × teknisyen başına değişen beceri = kurulumun "tek düğme + tek soru" olması şarttır. Grafik arayüz bu düğmeyi verir; 18 modül ise her kararın (update-kapalı, Docker-disiplini, GUI-anahtarı, kimlik, servisler) ayrı denetlenebilir adımıdır. Modül numarası log satırında görünür, arıza hangi adımda kaldıysa oradan devam edilir; arayüz aynı durumu "Kurulum modül durumu" işlemiyle salt-okunur gösterir.
|
||
|
||
## 5. Alternatifler
|
||
|
||
| Alternatif | Artı | Eksi | Sonuç |
|
||
|---|---|---|---|
|
||
| Grafik arayüz + tek kurucu betik | Tek giriş, komut ezberi yok, onay görünür | Grafik katman gerekir (`python3-tk`, ekran) | **Seçildi** |
|
||
| Python TUI (`sudo bf --tui`) | Grafik katman gerekmez | Terminal bilgisi ister | Kanonik terminal yüzeyi |
|
||
| Çok scriptli kurulum | Küçük dosyalar | Sıra/atlama hatası | Elendi |
|
||
| Non-idempotent tek script | Daha basit kod | Kesintide temiz-kurulum zorunluluğu | Elendi |
|
||
| İnteraktif sihirbaz (çok sorulu) | Esnek | Teknisyen hatası, otomasyona kapalı | Elendi |
|
||
|
||
## 6. Avantajlar
|
||
|
||
- Tek giriş noktası (`sudo bf`) = eğitim maliyeti minimum, runbook tek sayfa.
|
||
- Idempotency = kesinti korkusu yok, "bir daha koş" her sorunun ilk cevabı.
|
||
- Final-check = kurulum sonucu ölçülebilir, dalga kapılarına bağlanır.
|
||
- İnternetsiz çalışır: paketler repoda gelir, kuran kişi hiçbir şey indirmez.
|
||
|
||
## 7. Dezavantajlar
|
||
|
||
- 18 modülün her biri için idempotency testi yazma maliyeti.
|
||
- Tek giriş noktası, modül-atlama (debug) ihtiyacında `--from/--only/--resume` bayraklarını zorunlu kılar.
|
||
- Grafik arayüz `python3-tk` paketine ve bir grafik oturuma bağlıdır; bu ikisi yoksa operatör terminal konsoluna (`sudo bf --tui`) düşer.
|
||
|
||
## 8. Riskler
|
||
|
||
| Risk | Olasılık | Etki | Azaltma |
|
||
|---|---|---|---|
|
||
| Modül idempotent değil (çift kayıt) | Orta | Orta | Çift-koşu testi (§10) + code review kuralı |
|
||
| Teknisyen yanlış no girer | Orta | Orta | Format kapısı (`^[0-9]{8}$`) + onay ekranı (`BF-12010193, onaylıyor musunuz?`) |
|
||
| Kurucu yarıda kesilir, cihaz ara durumda sahaya alınır | Düşük | Yüksek | Final-check exit 0 olmadan kurulum tamamlanmaz; arayüzdeki "Kurulum modül durumu" ve `bf-status` bunu gösterir |
|
||
| Grafik arayüz açılmaz (başsız oturum) | Orta | Düşük | Uygulama Türkçe hata + `sudo bf --tui` önerir (19 §T-10) |
|
||
| `python3-tk` eksik kalır | Düşük | Orta | Paket offline depoda pinli; `18-final-check` tkinter'ı denetler ve eksikse WARN yazar |
|
||
|
||
## 9. Uygulama Planı
|
||
|
||
### 1. Giriş noktası — grafik operatör uygulaması (ana yol)
|
||
|
||
```bash
|
||
sudo bf # grafik arayüz (bfos paketi, bfos/ui_gui.py, Tkinter)
|
||
```
|
||
|
||
Akış:
|
||
|
||
1. Pencere açılır: başlık **Blueforce Field OS — Yönetim**.
|
||
2. Basit modda üç düğme vardır: `Kur`, `Durum`, `Çıkış`. Üstteki **`Detaylı mod`** ile 5 sekme açılır: `Kurulum`, `Cihaz işlemleri`, `Merkez hazırlığı`, `Araçlar`, `Cihaz bilgisi`.
|
||
3. Üst çubuktaki **Hedef > Bayi no (8 hane)** alanına numara yazılır (örn. `12010193`); format geçersizse arayüz uyarır ve komut üretilmez.
|
||
4. `Kurulum` sekmesinde **`Bu cihazı kur`** (veya hiçbir şey yazmayan ön kontrol **`Kurulum ön kontrolü (--check)`**) seçilir.
|
||
5. Arayüz komutu **önce ekranda gösterir**, sonra onay ister; onaylanmadan çalıştırılmaz. Yıkıcı işlemler ikinci kez sorar; production kapsamı ayrı onay ister.
|
||
6. Kurulum çıktısı ekranda akar; bitince sonuç ve çıkış kodu görünür.
|
||
|
||
`Bu cihazı kur` işleminin iki opsiyonel seçeneği vardır: `Yerel çevrimdışı depodan kur (--offline)` ve `Zaten OK olan modülleri atla (--resume)`. **`--offline` işaretlenmese de varsayılan kaynak yerel depodur**; bayrak yalnız niyeti sabitler.
|
||
|
||
### 2. Yedek yol — terminal konsolu
|
||
|
||
```bash
|
||
sudo bf --tui # aynı uygulamanın terminal arayüzü (grafik ekran yoksa / tkinter yoksa)
|
||
```
|
||
|
||
- `DISPLAY` ve `WAYLAND_DISPLAY` tanımlı değilse (SSH, başsız kurulum) uygulama Türkçe açıklama yazar ve **çıkış kodu 3** ile `sudo bf --tui` önerir.
|
||
- `python3-tk` kurulu değilse (`tkinter` import edilemiyor) aynı şekilde Türkçe hata + `python3-tk` kurulum ipucu verir ve **çıkış kodu 3** ile terminal konsolunu önerir.
|
||
|
||
### 3. Yetki
|
||
|
||
- `sudo bf` = tam yetki (kurulum, servis, firewall, Ansible).
|
||
- Root değilse uygulama başlangıçta uyarır ve yalnız **salt-okunur raporları** çalıştırır: "Yönetici yetkisi yok: salt-okunur raporlar çalışır, kurulum ve değişiklik gerektiren işlemler kapalıdır. Tam yetki için: sudo bf". Yazma işlemleri hem arayüzde kapalıdır hem de çalıştırma katmanında reddedilir (onaylansa bile komut çalışmaz).
|
||
|
||
### 4. Bayi-no doğrulama
|
||
|
||
`^[0-9]{8}$`; uymazsa arayüz geçersiz numarayı reddeder ve kurucu komut üretilmez (doğrudan CLI kullanımında exit 2 + kullanım mesajı). Geçerliyse onay ekranında `BF-12010193` + hostname `bf-12010193` gösterilir.
|
||
|
||
### 5. 18 modül (sıra sözleşmedir, yeri `scripts/install/installer/modules/`)
|
||
|
||
| # | Modül | İşlev |
|
||
|---|---|---|
|
||
| 01 | `01-precheck` | Root, Ubuntu sürümü, RAM/disk ön kontrolü; ağ yalnız bilgi (kapı değil) |
|
||
| 02 | `02-system` | Temel APT kaynakları, `unattended-upgrades` kapatma, saat dilimi (K-11) |
|
||
| 03 | `03-user` | `blueforce` bakım kullanıcısı, kısıtlı sudoers, zorunlu yönetici anahtarı (K-13) |
|
||
| 04 | `04-hostname` | Doğrulanmış bayi no'dan hostname `bf-<no>` (K-12) |
|
||
| 05 | `05-network` | Ağ raporu: yerel bağlantı, rota/DNS (DNS zorunlu tutulmaz — offline kurulum) |
|
||
| 06 | `06-wireguard` | Cihaz anahtar çifti; `wg0.conf` enrollment'ın işidir (K-05/K-17) |
|
||
| 07 | `07-ssh` | Yönetici anahtarı doğrulandıktan **sonra** sshd sertleştirme |
|
||
| 08 | `08-rdp` | xRDP + GNOME oturumu, terminale boot varsayılanı, multi-user (K-03/K-22) |
|
||
| 09 | `09-rustdesk` | Yalnız pinli/sağlanan paketten RustDesk istemci (K-04) |
|
||
| 10 | `10-docker` | Docker CE + rotasyonlu `daemon.json` + enable (K-10) |
|
||
| 11 | `11-meg` | MEG yer tutucusu: vendor `.deb` varsa kurar, yoksa SKIP + kabul listesi |
|
||
| 12 | `12-monitoring` | Node Exporter + textfile collector dizini (K-07) |
|
||
| 13 | `13-firewall` | UFW deny-in tabanı + Docker yayın-portu politikasının kalıcılığı (K-05/K-10) |
|
||
| 14 | `14-update-policy` | APT hold'ları + otomatik update zamanlayıcılarını kapatma (K-11) |
|
||
| 15 | `15-logrotate` | journald tavanları + uygulama logrotate politikası (K-14) |
|
||
| 16 | `16-gui` | GNOME minimal + bakım araçları; terminale boot varsayılanı (K-03) |
|
||
| 17 | `17-healthcheck` | Teşhis ve enrollment komutlarını kurar; enrollment'ı çalıştırmaz |
|
||
| 18 | `18-final-check` | Son yaşam döngüsü kapısı: offline yerelde tamamlanır, `READY` merkez kanıtı ister; tkinter denetimi (yoksa WARN) |
|
||
|
||
Modül çıkış kodları: `0` OK, `3` SKIP (opsiyonel adım, yapılacak bir şey yok), diğer ≠ 0 FAIL.
|
||
|
||
### 6. Paket deposu — otomatik keşif, iki hata durumu, sıfır indirme
|
||
|
||
Installer paket deposunu **kendi bulur**; `--offline` bayrağı **gerekmez** (geriye uyumluluk için kabul edilir, yalnız yerel depoyu zorlar). Arama sırası (ilk eksiksiz aday kazanır):
|
||
|
||
1. `BF_OFFLINE_REPO` ortam değişkeni (operatör/repo sorumlusu override'ı),
|
||
2. `<repo>/provisioning/offline-repo/built` (git deposuyla gelen paket seti),
|
||
3. `/opt/blueforce/offline-repo` (cihaza kurulmuş paket deposu).
|
||
|
||
Depo bulunduğunda ekrana Türkçe duyuru yazılır: `Yerel paket deposu bulundu: <N> paket, <boyut>` + `Depo`, `Kaynak`, `Kip` satırları. İki farklı başarısızlık vardır ve **ikisinde de paket modüllerinden önce durulur, sistemde hiçbir değişiklik yapılmaz**:
|
||
|
||
| Durum | Ekran | Sonuç |
|
||
|---|---|---|
|
||
| Depo hiçbir yerde yok | `HATA: Yerel paket deposu yok. Repo sorumlusuna başvurun: provisioning/offline-repo/README.md` + aranan yollar + `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.` | exit 1 |
|
||
| Depo bulundu ama bozuk/eksik | `OFFLINE BLOCKED: <sebep>` + Türkçe çıkış nedeni (ör. checksum uyuşmazlığı, eksik `Packages`/`packages.lock.tsv`, eksik pin) | exit 1 |
|
||
|
||
Uzak APT kaynağı, `curl`, `wget`, anahtar indirme veya `apt download` çağrılmaz. Yalnız geliştirme/test için `--online` vardır ve üretim cihazlarında kullanılmaz (DİKKAT uyarısı yazar).
|
||
|
||
### 7. Kurucu betiğin komut yüzeyi (yedek/otomasyon)
|
||
|
||
```bash
|
||
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193 [--from 07] [--only 18-final-check] [--resume] [--check] [--yes]
|
||
# --check : değişiklik yapmadan denetim (final-check + modül durumları)
|
||
# --from : belirtilen modülden devam et | --only: tek modül koş | --resume: OK modülleri atla
|
||
# --yes : onay sormadan başla (otomasyon; GUI bu bayrağı kullanmaz)
|
||
# --offline: yerel depoyu zorla (varsayılan zaten yerel) | --online: yalnız geliştirme/test
|
||
```
|
||
|
||
### 8. Idempotency kuralları (her modül için zorunlu)
|
||
|
||
- Varlık kontrolü önce (`id blueforce`, `dpkg -l`, `systemctl is-enabled`): varsa atla, yoksa kur.
|
||
- Dosya yazımları atomik (tmp + rename) ve tekrarlanabilir (aynı girdi → aynı çıktı).
|
||
- Anahtar/secret üretimi bir kez; `--force` olmadan yeniden üretilmez.
|
||
- Her modül `/var/log/blueforce-install.log` dosyasına modül no + OK/SKIP/FAIL satırı yazar.
|
||
|
||
### 9. Çıkış kodları ve sonuç durumu
|
||
|
||
Kurucu betik: `0` başarı (offline akışta `PROVISIONED_OFFLINE`), `1` engellendi veya modül hatası (no logda), `2` argüman/format hatası. Grafik/terminal arayüz: `3` grafik katman yok (ekran veya `python3-tk`), `2` kullanım hatası (`--tui` + `--gui` birlikte verilemez), `0` normal kapanış.
|
||
|
||
`READY` bir kurucu çıkış kodu değildir: offline akış `PROVISIONED_OFFLINE` yazar, `READY` yalnız merkezi kanallar doğrulandığında (29/30) yazılır.
|
||
|
||
## 10. Test Planı
|
||
|
||
| Test | Beklenen sonuç | Ortam |
|
||
|---|---|---|
|
||
| Geçersiz no (7/9 hane, harf, boş) | Arayüz reddeder / CLI exit 2, kurulum başlamaz | LAB(2) |
|
||
| `sudo bf` ile kurulum (grafik) | Komut önce gösterilir, onay ister, kurulum `PROVISIONED_OFFLINE` ile biter | LAB(2) masaüstü oturumu |
|
||
| `DISPLAY` yokken `sudo bf` | Türkçe yönlendirme + `sudo bf --tui` önerisi, exit 3, sistem değişmez | LAB(2) SSH |
|
||
| `python3-tk` yokken `sudo bf` | Türkçe "tkinter bulunamadı" + paket ipucu, exit 3 | LAB(2) minimal imaj |
|
||
| Her modülün çift-koşusu | İkinci koşu exit 0, durum değişmez (diff boş) | LAB(2) |
|
||
| Elektrik-kesintisi simülasyonu (modül 09 ortasında kill) | `--from 09` veya arayüzdeki `--resume` ile tamamlanır, final exit 0 | LAB(2) |
|
||
| `18-final-check` tüm kapıları | Eksik adımda FAIL + modül nosu, başarı damgası yok | LAB(2) |
|
||
| `--check` kuru koşusu (GUI ön kontrol / CLI) | Değişiklik yapmaz, rapor üretir | P1(5) |
|
||
| Depo yokken kurulum denemesi | Türkçe hata + aranan yollar + çıkış nedeni, exit 1, sistem değişmez | LAB(2) |
|
||
| Depo bozukken kurulum denemesi | `OFFLINE BLOCKED: <sebep>` + Türkçe çıkış nedeni, exit 1 | LAB(2) |
|
||
|
||
## 11. Rollback
|
||
|
||
1. Modül hatası: arayüzdeki "Kurulum modül durumu"/log ile modül nosu bulunur; `--from <no>` veya arayüzdeki `Başarısız kuruluma devam et (--resume)` ile sürdürülür.
|
||
2. Yanlış no: doğru no ile tam yeniden koşu (idempotent, hostname modülü üzerine yazar).
|
||
3. Düzelmeyen cihaz: 17-RECOVERY LEVEL 9 (temiz imaj + kurucu).
|
||
4. Paket deposu bozuksa sahada onarılmaz: repo sorumlusu depoyu yeniden üretip commit eder, güncel git tarafı çekilir ve komut tekrarlanır (27 §11).
|
||
|
||
## 12. Kontrol Listesi
|
||
|
||
- [ ] 18 modül dosyası `scripts/install/installer/modules/` altında numaralı ve çalışır durumda.
|
||
- [ ] Grafik arayüzde `Kurulum` sekmesi ve `Bu cihazı kur` işlemi bayi-no kapısına bağlı.
|
||
- [ ] Uygulama ekransız ortamda ve tkinter yokken Türkçe yönlendirme + `--tui` önerisi verip exit 3 ile çıkıyor.
|
||
- [ ] Her modülde varlık-kontrolü + log satırı var.
|
||
- [ ] Format regex'i 02 ile aynı (`^[0-9]{8}$`).
|
||
- [ ] `18-final-check` K-10/K-11 kapılarını ve tkinter denetimini içeriyor.
|
||
- [ ] Depo keşif sırası ve iki hata durumu (yok / bozuk) ekranda Türkçe ve fail-closed.
|
||
- [ ] `--check/--from/--only/--resume` bayrakları çalışıyor; `--offline` zorunlu değil.
|
||
|
||
## 13. Açık Sorular
|
||
|
||
- [ ] Paket setinin sahaya taşınması: git clone (Git LFS) mı, repo sorumlusunun hazırladığı `/opt/blueforce/offline-repo` kopyası mı birincil? (sahibi: Faz 3, 04/27 yazarları ile ortak)
|
||
- [ ] MEG sabit tag'inin kim tarafından, hangi onay ile güncelleneceği (sahibi: 10-UPDATE / 12-DOCKER yazarları).
|
||
- [ ] Arayüzün grafik ekran gerektirmeyen cihazlarda varsayılan modu (`--tui` mi, grafik mi) — saha ölçümü ile karar (sahibi: 33 + saha operasyonu).
|
||
|
||
---
|
||
|
||
## Ek: Kurulum Akışı (grafik arayüz)
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
CMD["sudo bf<br/>(grafik operatör uygulaması)"] --> EKRAN{"Grafik ekran +<br/>python3-tk var mı?"}
|
||
EKRAN -->|Hayır| TUI["Türkçe yönlendirme + exit 3<br/>sudo bf --tui"]
|
||
EKRAN -->|Evet| HEDEF["Hedef: Bayi no (8 hane)"]
|
||
HEDEF --> FMT{"^[0-9]{8}$ ?"}
|
||
FMT -->|Hayır| UYARI["Arayüz uyarır<br/>komut üretilmez"]
|
||
FMT -->|Evet| KUR["Kurulum sekmesi<br/>'Bu cihazı kur'"]
|
||
KUR --> ONAY["Komut gösterilir + onay<br/>(yıkıcı: ikinci onay)"]
|
||
ONAY --> DEPO{"Yerel paket deposu aranır<br/>BF_OFFLINE_REPO → built → /opt/blueforce/offline-repo"}
|
||
DEPO -->|"hiçbiri yok"| YOK["Türkçe hata + aranan yollar<br/>ÇIKIŞ NEDENİ: bulunamadı · exit 1"]
|
||
DEPO -->|"bozuk/eksik"| BOZ["OFFLINE BLOCKED: sebep<br/>exit 1 · sistem değişmez"]
|
||
DEPO -->|"eksiksiz"| M01["01-precheck … 17-healthcheck<br/>(idempotent modüller)"]
|
||
M01 --> M18["18-final-check"]
|
||
M18 -->|Hepsi OK| OFFLINE["PROVISIONED_OFFLINE"]
|
||
M18 -->|FAIL| LOG["modül nosu + log yolu<br/>--from / --resume ile devam"]
|
||
OFFLINE --> ENR["Token → ENROLLED"]
|
||
ENR --> READY["Merkez kanalları doğrulandı → READY"]
|
||
```
|