@appaflytech/zeyrek-ai-mcp 0.0.43 → 0.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/knowledge/backendConstraints.js +86 -2
  2. package/dist/knowledge/componentCatalog.js +63 -26
  3. package/dist/knowledge/componentEvents.js +6 -0
  4. package/dist/knowledge/connectDataBind.js +43 -6
  5. package/dist/knowledge/connectDataDefinition.js +74 -3
  6. package/dist/knowledge/connectDataRules.js +14 -0
  7. package/dist/knowledge/mobileComponentCatalog.js +67 -8
  8. package/dist/knowledge/mobileStore.js +61 -2
  9. package/dist/knowledge/platform/lint.js +23 -0
  10. package/dist/knowledge/platform/mobile.js +1 -1
  11. package/dist/knowledge/platform/mobileOffline.js +45 -0
  12. package/dist/knowledge/platform/mobileRules.js +8 -1
  13. package/dist/knowledge/platform/mobileTabs.js +31 -2
  14. package/dist/knowledge/platform/web.js +1 -1
  15. package/dist/knowledge/rules.js +220 -7
  16. package/dist/knowledge/textHooks.js +434 -0
  17. package/dist/platform/capture/capture.js +1 -1
  18. package/dist/platform/capture/readiness.js +4 -0
  19. package/dist/platform/errors.js +22 -2
  20. package/dist/prompts/mobilePublish.js +21 -0
  21. package/dist/resources/examples/flow-biometric-confirm.json +199 -0
  22. package/dist/resources/examples/microfunction-node-dependencies.json +19 -0
  23. package/dist/resources/examples/mobile-offline-list.json +357 -0
  24. package/dist/resources/examples/mobile-offline-queue.json +82 -0
  25. package/dist/resources/examples/mobile-offline-seamless.json +1520 -0
  26. package/dist/resources/guides/access.md +4 -4
  27. package/dist/resources/guides/component.md +20 -4
  28. package/dist/resources/guides/deployment.md +98 -0
  29. package/dist/resources/guides/entity.md +1 -1
  30. package/dist/resources/guides/expressions.md +5 -1
  31. package/dist/resources/guides/external-component.md +6 -4
  32. package/dist/resources/guides/merge.md +81 -4
  33. package/dist/resources/guides/microfunction.md +104 -9
  34. package/dist/resources/guides/microservice.md +34 -5
  35. package/dist/resources/guides/mobile-connect-data.md +70 -0
  36. package/dist/resources/guides/mobile-flow.md +64 -0
  37. package/dist/resources/guides/mobile-publish.md +161 -16
  38. package/dist/resources/guides/mobile-steps.md +21 -1
  39. package/dist/resources/guides/mobile.md +45 -23
  40. package/dist/resources/guides/page.md +122 -5
  41. package/dist/resources/guides/translation.md +97 -2
  42. package/dist/resources/knowledge.js +3 -1
  43. package/dist/resources/prompts/mobile-publish-prepare.md +89 -0
  44. package/dist/resources/schema-fingerprint.json +4 -4
  45. package/dist/resources/schemas/ApplyMicrofunctionArchiveChangesCommand.json +76 -0
  46. package/dist/resources/schemas/ConnectDataDescribeDto.json +44 -0
  47. package/dist/resources/schemas/ConnectDataResultDto.json +10 -0
  48. package/dist/resources/schemas/CreateMicrofunctionCommand.json +8 -0
  49. package/dist/resources/schemas/CreateMicroserviceCommand.json +3 -0
  50. package/dist/resources/schemas/InvokeMicrofunctionCommand.json +0 -4
  51. package/dist/resources/schemas/MicroserviceDto.json +3 -0
  52. package/dist/resources/schemas/MobileStorePreflightScope.json +13 -0
  53. package/dist/resources/schemas/StartMobileBuildCommand.json +35 -1
  54. package/dist/resources/schemas/UpdateMicrofunctionCommand.json +8 -0
  55. package/dist/resources/schemas/UpdateMicroserviceCommand.json +3 -0
  56. package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +75 -0
  57. package/dist/server.js +2 -0
  58. package/dist/tools/accessRuntime.js +1 -1
  59. package/dist/tools/applications.js +16 -2
  60. package/dist/tools/common.js +6 -0
  61. package/dist/tools/components.js +19 -6
  62. package/dist/tools/connectData.js +9 -4
  63. package/dist/tools/deployments.js +1 -1
  64. package/dist/tools/designSchemaPatch.js +16 -4
  65. package/dist/tools/environments.js +3 -3
  66. package/dist/tools/files.js +1 -1
  67. package/dist/tools/flows.js +118 -7
  68. package/dist/tools/layouts.js +32 -12
  69. package/dist/tools/merges.js +8 -8
  70. package/dist/tools/microfunctions.js +53 -3
  71. package/dist/tools/mobileStore.js +83 -21
  72. package/dist/tools/pages.js +59 -24
  73. package/dist/tools/platformInfo.js +4 -2
  74. package/dist/tools/textHookGuard.js +116 -0
  75. package/package.json +2 -2
@@ -95,7 +95,7 @@ alanlar denetlenmez); katalog okunamazsa denetim susar ve yazma eskisi gibi geç
95
95
  `Data = RedirectPage.Slug`). Sabit `'/hastalar'` yazarsan sayfa slug'ı değişince bağlantı
96
96
  sessizce kırılır; `pageId` referansı değişiklikten etkilenmez. Aynısı `flow` prop'u için
97
97
  `type: 'flow'` + `ref: <flowId>`, dosya için `type: 'file'` + `ref: <fileId>`.
98
- İSTİSNA: form dosya alanının (fileInput / filebutton / fileUpload) `value`'suna `type: 'file'` bağlama — çip
98
+ İSTİSNA: form dosya alanının (fileInput / filebutton / fileUpload / attachments) `value`'suna `type: 'file'` bağlama — çip
99
99
  URL yazar ve kullanıcı dokunmadan kaydederse tekil FILE alanı sessizce NULL'lanır (ölçüldü 2026-10-02). Varsayılan
100
100
  dosya için `{ type: 'static', data: { type: 'ref', value: <fileId>, fileName, absolute_path } }` ver (`component_get`
101
101
  notu).
@@ -443,6 +443,8 @@ göstermek error flow'un işidir.
443
443
  > | `Steps.<adımAdı>.error.message` | Patlayan adımın KENDİ storage'ında ucun mesajı — `error` dalında da `always`'te de okunur, sıra aynı: `err.reason` → HTTP durum metni → `'Service request failed'` | `microservice.ts` `.catch` |
444
444
  > | `Steps.<adımAdı>.error.status` | HTTP durum KODU (sayı) — parametre ifadesi patladıysa `null` | `microservice.ts` `.catch` |
445
445
  > | `Steps.<adımAdı>.error.body` | Ucun hata gövdesi — eski `Steps.<adımAdı>.data`'nın taşındığı yer | `microservice.ts` `.catch` |
446
+ > | `Steps.<adımAdı>.error.network` | **Yalnız mobil, veri önbelleği açıkken:** yanıt hiç alınamadı (bağlantı yok; süre sınırı yalnız saklanan okumalarda, 8 sn) — `true`; `status` yine 503. Önbellek kapalıyken ve web'de alan yoktur (Kural 1g-4) | `microservice.ts` `.catch` |
447
+ > | `Steps.<adımAdı>.cache.at` | Hata değil, BAŞARI şekli: yanıt cihazdaki kayıttan geldi, `at` saklandığı an (ms). Ağdan gelen yanıtta `cache` yoktur (Kural 1g-4) | `microservice.ts` `.then` |
446
448
  > | `Steps.<adımAdı>.data` | **HER ZAMAN `null`**'dır — başarı gövdesi değil, hiçbir gövde değil (eskiden hata gövdesiydi) | `microservice.ts` `.catch` |
447
449
  >
448
450
  > **`alert` adımının `message`'ı ve `description`'ı METİN ŞABLONUDUR — yalnız `{{ }}` içi çözülür.**
@@ -1061,16 +1063,19 @@ parametresini geçir.
1061
1063
 
1062
1064
  | istenen | yol |
1063
1065
  |---|---|
1064
- | Değere göre sabit renk | `tag` kolonu + `colorMap`: `[{ value: 'Active', label: 'Aktif', color: 'success' }]` — hücrenin KENDİ değerine bakar, satırın başka alanına göre hesaplanamaz |
1066
+ | Değere göre sabit renk | `tag` kolonu + `colorMap`: `[{ value: 'Active', label: 'Aktif', color: 'success' }]` — hücrenin KENDİ değerine bakar, satırın başka alanına göre hesaplanamaz. `value` KOD, `label` görünen yazıdır (çeviri sarmalı olabilir); `value`'ya görünen yazı yazılmaz (TR-005) |
1065
1067
  | Satıra göre koşullu renk | hücre değerini `{ label, color }` nesnesi olarak yaz: renk satır verisinde taşınır |
1066
1068
 
1067
1069
  ```jsonc
1068
1070
  // setter: rows'a yazmadan önce hücreyi { label, color } nesnesine çevir
1069
1071
  { "type": "change", "element": "tbl", "property": "rows", "source": "component",
1070
1072
  "mapping": { "source": "", "mappings": {} },
1071
- "value": { "type": "code", "ref": "(Steps.listele?.data || []).map(function (r) { return Object.assign({}, r, { durum: { label: r.durum, color: r.durum === 'İptal' ? 'error' : 'success' } }); })" } }
1073
+ "value": { "type": "code", "ref": "(Steps.listele?.data || []).map(function (r) { return Object.assign({}, r, { durum: { label: t('common.status.' + r.status), color: r.status === 'Cancelled' ? 'error' : 'success' } }); })" } }
1072
1074
  ```
1073
1075
 
1076
+ Renk kararı KODA bakar (`r.status === 'Cancelled'`), görünen yazıya değil (`r.durum === 'İptal'` dil değişince tutmaz —
1077
+ gateway TR-005 ile durdurur; `platform_guide('translation')` §Mantık görünen metne bağlanmaz).
1078
+
1074
1079
  Renk semantik ad (`primary · info · success · warning · error` — tema token'ına çözülür, tema
1075
1080
  değişince izler) ya da hex/rgb/CSS renk adıdır; temalarda `info` neredeyse beyazdır, mavi için
1076
1081
  `primary` yaz. `colorMap` satırının `mode: 'solid'`'i o değeri dolu zemin + beyaz yazıyla çizer.
@@ -1504,6 +1509,115 @@ Liste → ayrıntı, üç adım:
1504
1509
 
1505
1510
  Web uygulamasında alan yoktur.
1506
1511
 
1512
+ ## Kural 1g-4 — Mobil çevrimdışı: ayar, önbellek işareti, ağ hatası
1513
+
1514
+ Mobil uygulama ağ yokken iki şeyi cihazdaki kopyadan açar. Hangisinin açık olduğu uygulamanın ayarıdır:
1515
+ `application_update` `properties.mobile.offline` (`properties.mobile.tabs`'in yanındaki anahtar). Gövde REPLACE'tir:
1516
+ `application_get`'teki `properties`'in TAMAMI aynen gönderilir, yalnız `offline` eklenir — eksik anahtar silinir. Studio'da Nav Bar panelinin "Çevrimdışı" bölümü aynı alanı yazar.
1517
+
1518
+ | Alan | Değer | Varsayılan | Ne saklanır |
1519
+ |---|---|---|---|
1520
+ | `screens` | boolean | `true` | Ekran tanımları: açılan ekranların kopyası + uygulama paketi (korumasız ekranların gövdesi hiç açılmadan iner, korumalı ekranlar oturumluya ön yüklenir). Ağ yokken ekran kopyadan çizilir; sayfa isteği düşünce kabuk üstte "Çevrimdışı · son güncelleme …" bandını kendisi gösterir. Hazırlık: `Device.offline` |
1521
+ | `data` | boolean | `false` | Son okunan veri: `isRaw: false` YAZILMIŞ GET `microservice` adımı ve connectData okumaları (`list`, `describe`, `lookup`). `isRaw` yazılmamış ya da `true` olan adım ve dosya/akış sonucu dönen servis saklanmaz |
1522
+ | `maxAgeDays` | `1` · `7` · `30` | `7` | İkisinin de kayıt ömrü |
1523
+ | `banner` | boolean | `true` | Kabuğun çevrimdışı bandı ("Çevrimdışı · son güncelleme", "Yenilenemedi"). `false`: uygulama ağsızken fark göstermez — kendi uyarılarını da kaldırmak yazarın işidir (kök ADR 0026). Saklama ve kuyruk değişmez |
1524
+
1525
+ Yalnız varsayılandan ayrılan alanı yazın (`{ data: true }` yeter). Backend alanı doğrulamaz; cihaz okuyamadığı değeri
1526
+ (nesne olmayan ayar, boolean olmayan `screens`/`data`/`banner`, kümede olmayan ya da metin `maxAgeDays`, tanınmayan anahtar)
1527
+ SESSİZCE varsayılana düşürür — bunu söyleyen tek yer `application_create` / `application_update` yanıtındaki
1528
+ `platformWarnings`'tir (**MOB-033**).
1529
+
1530
+ **Saklanmayan:** yazma servisleri (POST/PUT/DELETE) ve connectData yazmaları — önbellekten yanıt almazlar.
1531
+ Kayıtlar kullanıcıya, ortama ve veri diline bağlıdır; çıkışta ve kullanıcı değişince silinir.
1532
+
1533
+ **Yazma kuyruğu (kök ADR 0022) — iki taraf da izin vermeli:**
1534
+
1535
+ - **Servis:** tanımında `offlineWritable: true` (`microservice_patch` `/offlineWritable`). Anlamı: "aynı istek iki kez
1536
+ gelirse bir kez uygulanır, çakışmada son yazan kazanır". Platform yazmayı sınıflamaz — iş akışı kaynaklı servisin
1537
+ yazıp yazmadığını bildirimi veren söyler. Okuyan uca (tablo `get`/`count`, görünüm kaynağı) verilirse **MS-025** uyarır.
1538
+ - **Akış:** `microservice` adımına `queued` dalı (yalnız mobil). Ağ hatasında (yanıt hiç yok) dal bağlıysa, yöntem
1539
+ yazansa (POST/PUT/DELETE) ve dosya parametresi yoksa kayıt kuyruğa girer ve `queued` koşar; `Steps.<ad>.data` `null`,
1540
+ `Steps.<ad>.queued = { clientRequestId, at }`. Dal bağlı değilse adım bugünkü gibi `error`'a gider; dosya
1541
+ parametresinde `Steps.<ad>.error.code = 'fileNotQueued'`. HTTP hatası — önündeki vekil sunucunun 502/503'ü dahil —
1542
+ kuyruğa girmez. Web uygulamasında ya da bildirimsiz servise bağlanan `queued` için yazım **FLOW-043** uyarısı alır.
1543
+ - **Sunucu karar verir:** cihaz servisin bildirimini bilmez. `queued` dalı bağlı yazmanın İLK isteği de
1544
+ `Idempotency-Key` taşır ve kuyruğa aynı kimlikle girer; aynı anahtar bir kez uygulanır, ikincisi 200
1545
+ `{ code: "Duplicate" }` alır — yanıtı yolda kaybolan yazma iki kez uygulanmaz. Bildirimsiz servis anahtarlı isteği
1546
+ 422 `OfflineReplayNotAllowedException` ile reddeder: `queued` bağlı adım çevrimiçiyken de HER ÇAĞRIDA `error`'a gider.
1547
+ FLOW-043 uyarısını bu yüzden geçiştirmeyin.
1548
+ - **Sınır:** kuyruktaki kayda bağlı ikinci işlem (yarat → sonra güncelle) yoktur; dönen kimliği bekleyen adım
1549
+ (`Steps.<ad>.data.id` ile yönlendirme, bildirim kurma) çevrimdışıyken koşamaz — o akışa `queued` dalı vermeyin.
1550
+ - **Gönderim:** bağlantı dönünce, uygulama ön plana dönünce ve ağla soğuk açılışta; kuyruğa giriş sırasıyla tek tek.
1551
+ 4xx kaydı reddeder ve sıra sürer; oturum (401/403), 408, 429, 5xx ve ağ hatası sırayı durdurur. 7 günde
1552
+ gönderilemeyen kayıt `expired` ile reddedilir. Kayıtlar kullanıcıya bağlıdır, çıkışta silinmez. Ağ açık ama
1553
+ sunucu ulaşılmazken bağlantı dönüşü tetiği gelmez — beklemesini istemediğiniz akışta `Page.offline.sync()` çağırın.
1554
+ - **Görünürlük:** kaydın sonucu akışa dönmez. `Device.offline.queue = { pending, rejected }` ve
1555
+ `Device.offline.rejected` (`id`, `service`, `at`, `status`, `code`, `message`); kod adımında `Page.offline.list()`,
1556
+ `.count()`, `.sync()`, `.resolve(id, 'retry' | 'discard')`. Süresi dolan kayıt yeniden denenmez.
1557
+ - **Önizleme:** Studio ve web'de kuyruk yoktur, `queued` hiç koşmaz; `page_screenshot` ağı kesemez. Açık ekran ilk
1558
+ çizildiği kopyayla kalır — akışa eklenen dal ekran bir sonraki açılışta etkindir.
1559
+
1560
+ Örnek: `ngapps://examples/mobile-offline-queue` (doz işaretleme: servis bildirimi + `queued` dalı).
1561
+
1562
+ **Veri önbelleği açıkken akış ne görür:**
1563
+
1564
+ - Saklanan okuma 8 sn süre sınırı taşır; yanıt gelirse olduğu gibi döner ve arkada saklanır. Saklanmayan isteklerde
1565
+ (yazmalar dahil) süre sınırı YOKTUR: yanıt vermeyen sunucuda adım bekler.
1566
+ - Yanıt gelmezse (bağlantı yok, süre doldu) ve kayıt varsa adım **başarı yolundan** sürer; storage'ı
1567
+ `{ data, headers, error: null, cache: { at } }` olur — `at` kaydın saklandığı an (ms). Ağdan gelen yanıtta `cache`
1568
+ alanı YOKTUR: "son güncelleme" satırını `Steps.<ad>.cache`'ten kurun, ağ varken gizli kalır.
1569
+ - Kayıt da yoksa adım hata yoluna gider: `Steps.<ad>.error.network` `true`, `status` 503. "Bağlantı yok" demek için
1570
+ **önce `error.network`'e bakın** — 503'ü sunucu da döner (bakım, aşırı yük); sunucu arızası
1571
+ `status == 503 && !error.network`'tür. Akış 503'ü `network`'süz karşılaştırıyorsa yazım **MOB-033** bilgi notu alır.
1572
+ Bağlantı yoksa `network` her istekte yazılır (saklanmayanlarda da); önbellek kapalıyken hiç yazılmaz.
1573
+ - connectData bağı kayıttan dolarsa düğüme `cachedAt` yazar (`{{ <öğe>.cachedAt }}`; ağdan gelince `null`), yükleme ve
1574
+ hata görünümü çıkmaz; bağlantı dönünce bağ sunucudan yeniden okunur. Kayıttan dönen `lookup` sonucu `cachedAt` taşır.
1575
+ - **Önbellek son başarılı yanıtı aynen verir.** Her çağrıda değişen bir GET (sayaç, saat, rastgele değer) ağ yokken
1576
+ eski değerini döner. Parametre, sayfa, arama ve süzgeç isteğin parçasıdır: başka parametreli çağrı başka kayıttır,
1577
+ hiç açılmamış sayfa ağ yokken gelmez.
1578
+
1579
+ **Doğrulama sınırı:** önizleme (`/dev`, Studio kanvası) ve `page_screenshot` önbellek KULLANMAZ — ayar açık olsa da her
1580
+ okuma ağdan gider, `cache` ve `cachedAt` hiç yazılmaz. `page_screenshot` ağı kesemez; çevrimdışı davranış yalnız
1581
+ cihazda görülür (uçak modu). Ölçüldü 2026-10-20 (simülatör, mağaza kabuğu): GET servis okuması ağ varken 149 ms'de
1582
+ ağdan, sunucu yanıt vermezken 8,03 sn'de kesilip kayıttan döndü.
1583
+
1584
+ Örnek: `ngapps://examples/mobile-offline-list` (liste + "son güncelleme" satırı + bağlantı yok uyarısı). Web
1585
+ uygulamasında alan yoktur; gateway web profilinde bu konuda bulgu üretmez.
1586
+
1587
+ ### Ağsızken fark göstermeyen uygulama (tarif)
1588
+
1589
+ Kullanıcı "uygulama internet yokken de normal çalışsın" dediğinde hedef: ağsızken ekran, uyarılar ve akış çevrimiçiyle
1590
+ AYNI; veri bağlantı gelince Zeyrek'e kendiliğinden gider. Altı adım birlikte kurulur — biri eksikse fark görünür
1591
+ (iPhone'da uçak kipiyle ölçüldü 2026-10-22, `mobile-offline-seamless` örneğinin kaynağı):
1592
+
1593
+ 1. **Ayar:** `properties.mobile.offline = { data: true, banner: false }` — veri önbelleği açık, kabuğun
1594
+ "Çevrimdışı · son güncelleme" bandı kapalı (kök ADR 0026).
1595
+ 2. **Okuma GET:** okuyan uç `httpMethod: 'get'`, adım `isRaw: false`; uç filtreleri ve adım parametreleri
1596
+ `source: 'query-string'` (GET'te gövde gitmez). Önbellek yalnız GET okumayı saklar; POST ile okuyan adım ağsızken
1597
+ kayıttan dönemez ve hata yoluna düşer — **FLOW-044** uyarır (yöntem servis tanımındandır, adıma yazılan saklanmaz).
1598
+ (Ölçüm: POST okuyan bir uygulamanın listesi ağsızken "yüklenemedi" dedi.)
1599
+ 3. **Yazma kuyruğu, uyarısız:** yazan uç `offlineWritable: true`; `microservice` adımının `queued` dalı `always` ile
1600
+ **aynı adıma** bağlanır — ağsız yazma da çevrimiçi gibi biter. Adımın `error` dalı çevrimiçi reddi uyarır; kuyruktaki
1601
+ kayıt sonradan reddedilirse (4xx, 7 günde `expired`) bu akışa DÖNMEZ — `Device.offline.rejected` ile gösterin,
1602
+ `Page.offline.resolve(id, 'retry' | 'discard')` ile karar verdirin; göstermemek bilinçli bir ödünleşimdir.
1603
+ 4. **Liste bekleyenleri gösterir:** yükleme akışı sunucunun yanıtına `await Page.offline.list()`'teki
1604
+ `status === 'pending'` kayıtları katar (`service` yazma ucunun slug'ı, alan değeri `parameters[].value`'dan); ağ
1605
+ yokluğu hata metni göstermez (`Steps.<ad>.error && !Steps.<ad>.error.network`).
1606
+ 5. **Düğme kilidi:** yazan düğme istek süresince `isLoading` + `isDisabled`; her dalın sonunda açılır. Kilitsiz düğmede
1607
+ hızlı ikinci dokunuş yeni bir istek ve yeni bir `Idempotency-Key`'dir — sunucu ikisini de uygular (ölçüm: 1,6 sn'de
1608
+ üç dokunuş, üç kayıt).
1609
+ 6. **Açılış ve yenileme (geçici çareler):** açılış sayfası korumasız giriş ekranıdır; kalıcı `state.app` oturum işareti
1610
+ (`storage: 'device'`) varsa mount akışı listeye `presentation: 'replace'` ile geçer, giriş yazar, çıkış siler —
1611
+ korumalı açılış sayfası ağsız ilk açılışta çizilemiyor (kök ADR 0024 taslak) ve cihazda kabuk bilgisi yokken
1612
+ middleware'in reddi girişe yönlenmiyor (zeyrek-frontend `docs/issues.md` ARC-342). Liste `scroll-view` `refreshable` +
1613
+ `refresh` olayı yükleme akışına bağlıdır — bağlantı dönünce açık ekranın mount akışı kendiliğinden koşmaz (kök ADR
1614
+ 0025 taslak). İki karar kapanınca bu adım sadeleşir.
1615
+
1616
+ Fark yalnız üç yerde kalır: giriş (ağ ister), hiç açılmamış ekran (cihazda kopyası yok) ve bağlantı dönünce gönderilen
1617
+ kayıt — artık bekleyen değildir, önbellekteki eski listede de yoktur; liste aşağı çekilene kadar görünmez (ADR 0025). Önizleme ve
1618
+ `page_screenshot` önbellek ve kuyruk kullanmaz — davranış yalnız cihazda görülür. Tam gövde (iki ekran, beş akış, iki
1619
+ uç, ayar ve değişken): `ngapps://examples/mobile-offline-seamless`.
1620
+
1507
1621
  ## Kural 1h — Tasarım: `style` prop'u ve tema değişkenleri
1508
1622
 
1509
1623
  Her komponentin `style` prop'u vardır ve emotion `css()` bloğudur: iç seçiciler, pseudo-class'lar
@@ -2119,6 +2233,9 @@ de silip yeniden ekleme gerekmez:
2119
2233
  { "op": "set_appearance", "target": "box_summary", "appearance": { "heightType": "auto", "tooltip": null } }
2120
2234
  ```
2121
2235
 
2236
+ İpucunu çeviriye bağlamak için metne `t:` öneki konur (`"tooltip": "t:shell.profile"`); ayrıntı
2237
+ `platform_guide('translation')` §Bileşen ipucu.
2238
+
2122
2239
  Op **birleştirir**: yalnız verilen alanları yazar, gerisini korur; `null` alanı temizler (null
2123
2240
  kabul etmeyen `heightType` gibi alanlar hariç). Alan adları `page_schema_get`'in döndürdüğü
2124
2241
  appearance anahtarlarıdır; bilinmeyen alan `unknown-appearance-field`, tanınmayan ya da null
@@ -2340,7 +2457,7 @@ bağlanır, filtre `source:'expression'` + `value:'user.id'` olur.
2340
2457
  | Puan / kod girişi | `rating` · `otpinput` |
2341
2458
  | Tarih / saat / aralık | `datepicker` · `datetimepicker` · `daterangepicker` · `datetimerangepicker` · `timepicker` (yalnız HH:mm) |
2342
2459
  | Kimlik alanları | `textinput` (e-posta için `inputMask` Email hazır maskesi ya da `regex` kuralı — `email` diye bir bileşen YOK, `add_component` `unknown-type` ile reddedilir) · `password` |
2343
- | Dosya | `fileUpload` (dropzone) · `fileInput` · `filebutton` · `file-viewer` |
2460
+ | Dosya | `attachments` (ek dosyalar: sürükle-bırak ya da düğme + önizlemeli kartlar, görsel/video/PDF popupta) · `fileUpload` (dropzone) · `fileInput` · `filebutton` · `file-viewer` |
2344
2461
  | Liste | `datatable` (Kural 1e) · `repeater` (kart listesi VE dinamik form — Kural 1g) · `tree-view` (hiyerarşi; `isSearchable` ile istemci içi arama) · `timeline` (tarihli olay akışı) |
2345
2462
  | Pano / takvim | `kanban` (durum kolonlarında sürüklenebilir kartlar; taşıma `cardMove` ile `event.data`'dan okunur, kalıcılık AKIŞIN işidir) · `eventcalendar` (ay/hafta/gün/ajanda; veri `rows`'a akışla yazılır, `monthChange`/`viewChange` görünen `start`/`end` aralığıyla tazeleme kancasıdır) |
2346
2463
  | Kayıt detayı | `detailview` — tek kaydı etiket/değer ızgarası basar (alan başına format, iç içe alan yolu); OLAY YAYMAZ, tıklanabilirlik gerekiyorsa kapsayıcıya sar |
@@ -2730,7 +2847,7 @@ micro-op hattına dönün.
2730
2847
  korumalı sayfada `middlewareBlocked` dönmesi beklenen davranıştır ve kendisi bir
2731
2848
  doğrulamadır. Tam doğrulama seti: `page_schema_validate` (kuru koşu) + `page_get` (bağlar)
2732
2849
  + `page_runtime_get` (son hâl).
2733
- - **Sayfada dosya toplanabilir:** `fileUpload` (dropzone) · `fileInput` · `filebutton`
2850
+ - **Sayfada dosya toplanabilir:** `attachments` (ek dosya listesi) · `fileUpload` (dropzone) · `fileInput` · `filebutton`
2734
2851
  komponentleri vardır, göstermek için `image` · `file-viewer`. Yani "dosya yükleyerek cevapla"
2735
2852
  tipi bir alan kurulabilir. Gateway tarafında `file_upload`/`file_download` tool'ları eklendi
2736
2853
  (multipart / `outPath`) ama **canlı platforma karşı henüz doğrulanmadı** — ilk kullanımda
@@ -119,6 +119,45 @@ backend'de zaten tanımlı, Studio'nun "Translate" aksiyonunun ürettiği şekil
119
119
  tipli prop'larda "Translate" aksiyonu gösterilir, ama şema düzeyinde her static prop aynı Prop
120
120
  şeklini kabul eder).
121
121
 
122
+ ## Mantık görünen metne bağlanmaz (TR-005 / TR-006)
123
+
124
+ Davranışı (koşul, görünürlük, renk, ikon, dal, CSS seçici) ekranda GÖRÜNEN bir yazıya bağlayan kod **metin kancasıdır**:
125
+ yazı dile, çeviriye ve tasarımcının düzeltmesine göre değişir; değişince karşılaştırma sessizce tutmaz. qm'de İngilizceye
126
+ geçince ev ikonu kayboldu, onay düğmeleri görünür oldu, durum renkleri griye düştü (2026-10-13…16, onlarca yer). Kural
127
+ tek dilli uygulamada da geçerlidir: yazı düzeltilince aynı kırılma olur. **Hiçbir karar görünen metne bağlanmaz.**
128
+
129
+ | Yasak (kanca) | Doğru |
130
+ |---|---|
131
+ | `r.durum === 'Onaylandı' ? 'success' : 'warning'` | Kayıttaki kod: `r.status === 'Approved'`; yazıyı ayrıca `t('common.status.' + r.status)` ile bas |
132
+ | `{{ bc.title !== 'Aksiyonlar' ? 'home' : '' }}` (başlığa göre ikon) | Adres parametresi (`Page.queryParams.task`) ya da akışın açıkça yazdığı state |
133
+ | `statusText === 'Açma onayı'` (düğme görünürlüğü) | Kodu ayrı alanda taşı: `statusCode === 'ActionOpenApproval'` |
134
+ | `['Onaylandı', 'Reddedildi'].includes(durum)` | Kod listesi: `['Approved', 'Rejected'].includes(status)` |
135
+ | `/Klasörler/.test(panel.textContent)` (html betiği) | Dilden bağımsız işaret: sınıf (`klasor-paneli`), `data-*` özniteliği, `elementId` |
136
+ | CSS `[aria-label="Kolonlar"]` | Yapısal seçici (`.ng-tools__button[aria-expanded]`) ya da sınıf |
137
+ | `colorMap: [{ value: 'Aktif', color: 'success' }]` | `value` kod, görünen yazı `label`'da (çeviri sarmalı olabilir) |
138
+ | `currentItem.title === 'Dokümanlar'` (breadcrumb tıklaması) | Öğeye ek alan: `{ key: 'klasor', title }` → `currentItem.key === 'klasor'` |
139
+ | Sekmeyi ya da hata satırını yazısıyla tanımak | Sekme `key`'i / kimliği (`<tabs>__tab-<key>`), bağlamdaki kod |
140
+
141
+ Gateway akış, sayfa, layout ve widget yazımında denetler (`flow_*`, `page_schema_patch` / `_validate`, `page_create`,
142
+ `page_update`, `layout_*`, `component_schema_patch`, `component_create` / `_update`):
143
+
144
+ - **TR-005 (block):** bu yazımla gelen kanca isteği platforma göndermeden durdurur. Kanca sayılan: ASCII dışı (Türkçe)
145
+ harfli ya da boşluklu metinle karşılaştırma (`===`, `!==`, `case`, `includes`, `startsWith`, `indexOf`, düzenli ifade
146
+ testi, dizi üyeliği), görünen alana bakan karşılaştırma (`title`, `label`, `text`, `textContent`, `innerText`,
147
+ `nodeValue`, `getAttribute('aria-label')` …), etiket CSS seçicisi (`[aria-label=…]`, `[title=…]`), `colorMap` değerinde
148
+ görünen metin. Tek harf (`case 'ş'`), karakter sınıfı (`/[çğıöşü]/`), `Page.queryParams` değeri ve `${…}` ile kurulan
149
+ seçici kanca sayılmaz. Yalnız ASCII harfli boşluklu metin (`'User Group'` sunucu kodu da olabilir) sözlükte ya da
150
+ sayfanın yazısında geçiyorsa kanca sayılır.
151
+ - Kayıtta zaten duran kanca **warn**: yazım durmaz. Dokunduğunuz yerdeyse aynı değişiklikte koda çevirin; o metni
152
+ çevirmeyin — karşılaştırma kırılır.
153
+ - **TR-006 (warn):** tek kelimelik metin (`'Aktif'`, `'Evet'`, `'Anasayfa'`) biçimden koddan ayrılmaz; projenin varsayılan
154
+ dilindeki sözlük değeriyle ya da sayfanın yazısıyla aynıysa uyarır. Bir kod değeriyse yok sayın.
155
+ - Kaçış: sunucu yalnız metin döndürüyor ve karşılaştırılacak kod yoksa aynı çağrıya `policyOverride: true` — bulgu
156
+ yanıtta uyarı olarak kalır. Kalıcı çözüm sunucudan kod istemektir (`platform_gap_report`).
157
+
158
+ Denetim sözdizimseldir: kodun içindeki karşılaştırmayı arar, etiket ve mesaj gibi düz metni kanca saymaz. Sunucu tarafı
159
+ (workflow, microservice, Studio fonksiyonu) denetlenmez — orada da aynı kural geçerlidir.
160
+
122
161
  ## Dil değiştirme: `language-selector`
123
162
 
124
163
  Son kullanıcı dili `language-selector` komponentiyle değiştirir (`platform_guide('component')`
@@ -153,6 +192,46 @@ budur. Lambda yalnız `{{#t}}` geçen şablona eklenir; `context` kendi `t` alan
153
192
  basılır; datatable'ın `html` hücresi bu sözdizimini tanımaz. 2026-10-14 frontend'i (frontend ADR 0021),
154
193
  uzak kurulumda dağıtımdan sonra.
155
194
 
195
+ ## Bileşenin kendi kelimeleri: `compProp.<bileşen>.<kelime>`
196
+
197
+ Web bileşenleri son kullanıcıya kendi kelimelerini gösterir — tablonun "Rows per page"i, boş durumu,
198
+ filtre kurucusu, açılır kutunun "Bir seçenek seçin"i, adım bileşeninin "İleri / Geri"si, etkinlik takviminin "Bugün"ü.
199
+ 2026-10-15'ten beri web bileşenleri bu modelde (`attachments` 2026-10-21'den beri, ortak kelimelerle). Bunlar prop değildir; uygulama sözlüğünde satırdır (frontend ADR 0023 / 0024, 2026-10-15):
200
+
201
+ - bileşenin **kendi** kelimesi `compProp.<bileşen>.<kelime>` — `datatable` (eski adı `table` aynı anahtarları
202
+ kullanır), `version-compare`, `chart` (tip seçicinin adları `type<Tür>`: `compProp.chart.typeBar`) ve `pagination`
203
+ (`compProp.pagination.next`, `…rowsOption` — tablonun aynı adlı kelimelerinden ayrı satırdır);
204
+ - birçok bileşende geçen **ortak** kelime tek satır `compProp.common.<kelime>` ("Yükleniyor…", "Kapat",
205
+ "Temizle", "Ara", korumalı değer penceresi …) — bir kez çevrilir, bütün bileşenlerde değişir;
206
+ - form alanının **varsayılan doğrulama mesajı** da ortak kelimedir: kuralın `message`'ı boşsa
207
+ `compProp.common.validationRequired` / `validationMinLength` / `validationMaxLength` / `validationMinValue` /
208
+ `validationMaxValue` / `validationRegex` / `validationEmail` gösterilir, `{value}` kuraldan dolar. Doğrulama kelimesi
209
+ taşıyan bir bileşen studio'da tohumlanınca yedi kuralın hepsinin satırı yazılır (akışın doğrulama adımı her kuralı
210
+ uygulayabilir).
211
+
212
+ Ekrandaki zincir: düğümün `texts` prop'u → sözlükteki satır (bileşenin dili → varsayılan dil) → bileşenin
213
+ tohum metni (dil → İngilizce). Sözlükte satır yokken ekran eskisiyle aynıdır. Bir dilde satır yoksa varsayılan
214
+ dildeki satır görünür (K60).
215
+
216
+ - **Bütün tablolarda değiştirmek:** sözlüğe yaz — `translation_update` ile
217
+ `compProp.datatable.rowsPerPage` = `{ tr: 'Sayfa başına kayıt', en: 'Records per page' }`.
218
+ - **Yalnız bir tabloda değiştirmek:** o düğümün gizli `texts` prop'una yalnız o kelimeyi yaz —
219
+ `{ "op": "replace_prop", "target": "<tablo>", "prop": "texts", "value": { "rowsPerPage":
220
+ { "type": "translation", "ref": "page.x.kayitSayisi" } } }`. Yazılmayan kelime sözlükten gelir;
221
+ `texts`'e bütün kelimeleri kopyalama.
222
+ - Tablonun kelime adlarının tam listesi (124) `component_get('datatable')` › `propNotes.texts`'te; her
223
+ bileşenin listesi studio'nun Translations sekmesinde. İşleç yazıları `op<İşleç>` (`opEq`) ve kısa hâlleri
224
+ `opShort<İşleç>` (`opShortContains`). Listede olmayan ad yazılmaz — bileşen onu okumaz.
225
+ - Kelime gibi çalışan ayarlar (`placeholder`, `emptyText`, `trueLabel` …) boş bırakılır; boşken ortak kelime
226
+ görünür. Ayrıntı `platform_guide('component')` §Arayüz metni.
227
+ - Satırları studio yazar, yalnız iki yoldan: kelimeli bileşen studio'da **paletten** sayfaya konunca eksik
228
+ bileşen satırları tohumla (tr / en / ar) eklenir; çeviri panelindeki "Eksik bileşen
229
+ kelimelerini ekle" bütün sayfa, layout ve widget'ları tarar ve satırları Kaydet'le yazar. Dolu
230
+ satıra ikisi de dokunmaz. **MCP ile eklenen bileşen (`add_component`, `page_schema_patch`) satır
231
+ yazdırmaz** — sözlükte satır yokken bileşen tohum metnini gösterir; kelimeyi değiştireceksen satırı
232
+ `translation_update` ile kendin yaz. Tohumu olmayan dil (ru) boş kalır — onu da `translation_update`
233
+ ile doldur. Mobil bileşenler kelimeleri henüz sözlükten okumaz (tohum gösterir).
234
+
156
235
  ## Kareyi ikinci dilde almak: `page_screenshot(language:)`
157
236
 
158
237
  Dil değiştirici **kanıt için gerekli değildir.** Runtime boot dilini şu sırayla seçer:
@@ -221,6 +300,22 @@ Runtime `t:` ile başlayan bir mesajı anahtar sayar ve normal zincirden çözer
221
300
  olduğu gibi gösterilir. Çözüm çalışma anında olduğu için şema varsayılanlarını değiştirmek
222
301
  gerekmez — `schema.ts`'e dokunulmaz, katalog yeniden yüklenmez.
223
302
 
303
+ ## Bileşen ipucu: `appearance.tooltip` ve `t:` öneki
304
+
305
+ Üstüne gelince çıkan ipucu bir prop değil, düğümün `appearance.tooltip` alanıdır (düz metin);
306
+ `set_prop_type` ona uygulanamaz. Doğrulama mesajıyla aynı sözleşme geçerlidir — metnin kendisine
307
+ `t:` öneki konur:
308
+
309
+ ```jsonc
310
+ { "op": "set_appearance", "target": "shell_profile", "appearance": { "tooltip": "t:shell.profile" } }
311
+ ```
312
+
313
+ Ekran anahtarı uygulama sözlüğünden okur (aktif dil → varsayılan dil → anahtarın kendisi) ve dil
314
+ değişince ipucu da değişir; öneksiz metin olduğu gibi kalır. Studio'da bağ, ipucu yazılmış
315
+ bileşenin Translations sekmesindeki "İpucu" satırından kurulur ve kaldırılır; Properties'teki kutu
316
+ bağlıyken anahtarı çip olarak gösterir. Yalnız web: mobil panelde ipucu alanı yoktur
317
+ (`platform_guide('mobile')`). Tasarım kanvası ipucu çizmez; önizleme ve çalışma anı çizer.
318
+
224
319
  ## Dosyayla toplu çeviri (Excel)
225
320
 
226
321
  İnsan bir çevirmene yeni bir dil yaptıracaksa: sözlük Excel'e iner, çevirmen hedef sütunu doldurur,
@@ -256,8 +351,8 @@ yazılır ama yanıt `applicationMismatch: true` ve not taşır.
256
351
  `project_update` gerekmez; ama dil production'a da gider ve orada çeviriler deployment'la gelene
257
352
  kadar runtime varsayılan dile düşer.
258
353
  - Dosya platformda **saklanmaz**: ne dışa aktarma ne içe aktarma Sürücü'ye bir şey bırakır.
259
- - Studio'nun çeviri panelindeki JSON içe aktarma bundan farklıdır: o yalnız boşları doldurur ve
260
- projede olmayan dili atlar.
354
+ - Studio'nun çeviri panelindeki "Excel'e aktar" / "Excel'den içe aktar" düğmeleri (2026-10-21) aynı
355
+ uçları kullanır; panelin eski JSON içe / dışa aktarması kaldırıldı.
261
356
  - Sınırlar: `.xlsx` (`.xls`, csv, json reddedilir), 10 MB, 10.000 satır.
262
357
 
263
358
  ## Bilinen sınırlar
@@ -13,7 +13,9 @@ export function listKnowledgeFiles(kind) {
13
13
  /**
14
14
  * `schemas` MCP kaynağı olarak YAYINLANMAZ (yalnız `guides` ve `examples` kayıtlıdır) ama
15
15
  * dosyalar aynı klasör düzeninde durur ve drift testleri onları da okur — şema kaynağı
16
- * platformun swagger'ından üretiliyor ve bir alanın oradan düşmesi sessizce olur.
16
+ * platformun swagger'ından üretiliyor ve bir alanın oradan düşmesi sessizce olur. `prompts`
17
+ * kaynak değil MCP prompt'udur (`src/prompts/`, ADR 0003); metni burada durur ki `copy-assets`
18
+ * onu `dist`'e taşısın ve gözden geçirme metin olarak yapılsın.
17
19
  */
18
20
  export function readKnowledgeFile(kind, file) {
19
21
  return readFileSync(join(resourcesDirectory, kind, file), 'utf8');
@@ -0,0 +1,89 @@
1
+ # Mobil uygulamayı yayına hazırla
2
+
3
+ Uygulama: `{{applicationId}}`. Görev: Studio › Yayınla'nın **3 · Test sürümü** (kimlik ve sürüm, Apple hesabı,
4
+ Google Play hesabı, test ön kontrolü) ve **4 · Yayına hazırla** (mağaza metinleri, görseller, yaş derecelendirmesi,
5
+ gizlilik, beyanlar, sürüm-fiyat-yayın, konsolda kalanlar) adımlarını zeyrek-ai araçlarıyla doldurmak, ön kontrolü
6
+ kuru koşmak ve insana kalan işi tek listede vermek. Kurallar ve alan sınırları `platform_guide('mobile-publish')`'dedir;
7
+ başlamadan önce §Yolculuk, §Test derlemesi, §Akış, §Yaş derecelendirmesi ve §Ön kontrol bölümlerini oku.
8
+
9
+ ## Sınırlar — bunlar pazarlık konusu değil
10
+
11
+ - **Gizli bilgi girmezsin:** Apple/Google hesabı, sertifika, profil, keystore, harita anahtarı, demo parolası,
12
+ APNs anahtarı, `google-services.json`. Bunlar Studio › Yayın › Hesaplar'da insanın işidir.
13
+ - **Beyanı kendin işaretlemezsin:** `mobile_store_update { applicationId, declarations }` ile `true` yalnız kullanıcı o formu
14
+ App Store Connect / Play Console'da doldurduğunu **bu konuşmada açıkça söyledikten sonra** yazılır.
15
+ - **Geri dönüşsüz bir şey kendiliğinden başlatmazsın:** production'a dağıtım ve mağazaya gönderim yok; ön kontrol
16
+ `mobile_build_start` ile yalnız `dryRun: true` koşulur. Test derlemesi isteğe bağlıdır ve **yalnız kullanıcı bu
17
+ konuşmada açıkça isterse** `dryRun`'sız başlatılır (adım 4). Apple'daki kimlik kaydı da silinemez: yalnız
18
+ kullanıcı kimliği bu konuşmada onayladıktan sonra yapılır (adım 4).
19
+ - **Kilitli alana dokunmazsın:** `lockedFields` içindeki kimlik ve sayaçlar ilk derlemeden sonra değişmez.
20
+ - Bir alanın değerini uydurmazsın: uygulamanın içeriğinden (sayfalar, akışlar, mevcut ayar) çıkaramadığın her
21
+ şeyi — şirket adı, destek e-postası, gizlilik politikası adresi, fiyat — kullanıcıya **tek seferde, liste
22
+ olarak** sor.
23
+
24
+ ## Sıra
25
+
26
+ ### 3 · Test sürümü
27
+
28
+ 1. **Durumu oku.** `mobile_store_get { applicationId, detail: ['assets', 'signing', 'changes'] }`. Not et:
29
+ `persisted`, `lockedFields`, `settings.releaseTargets` (bu sürüm hangi mağazalara gidiyor), mevcut `listing`
30
+ dilleri, görsel yuvaları, beyanlar, `signing` eksikleri. Kapalı mağazanın alanlarını doldurma.
31
+ 2. **Kimlik ve sürüm.** `persisted: false` ise kimlik otomatik varsayılandır: kullanıcı onaylarsa
32
+ `bundleIdentifier`, `androidPackage`, `scheme`'i ilk derlemeden önce yaz. `displayName` ve `version`
33
+ (MAJOR.MINOR.PATCH) dolu olsun.
34
+ 3. **Hesaplar.** Bu sürümün gittiği mağazaların `signing` eksiklerini (Apple hesabı, Google Play hesabı, sertifika,
35
+ profil, keystore) kalanlar listesine yaz — Studio › Yayın › Hesaplar.
36
+ 4. **Test ön kontrolü.** Açık her platform için
37
+ `mobile_build_start { applicationId, platform, target, scope: 'test', dryRun: true }` (iOS `testflight`, Android
38
+ `internal`). Kullanıcı başka bir ortamdan (development ya da hazır bir dal) test etmek istiyorsa `environment` ekle;
39
+ ön kontrol o ortamda sorar. Ajanın düzeltebildiği `fail` satırlarını düzelt ve yeniden koş; düzeltemediklerini
40
+ kalanlara yaz. iOS'ta `asc_bundle_id_missing` çıkarsa kimliği (`bundleIdentifier`) kullanıcıya göster ve Apple'daki
41
+ kaydın silinemeyeceğini söyle; yalnız açık onayıyla `mobile_store_update { applicationId, registerAppleBundleId: true }`,
42
+ sonra ön kontrolü yeniden koş. Onay yoksa kalanlara yaz. Test derlemesi isteğe bağlıdır: yalnız kullanıcı açıkça
43
+ isterse aynı çağrıyı `dryRun`'sız yap — her başlatma derleme numarası ayırır ve kimliği kilitler. Production'dan
44
+ alınan test derlemesi sonradan yeniden derlenmeden incelemeye / yükseltmeye gidebilir; development ya da dal
45
+ derlemesi asla mağazaya gitmez — kullanıcıya bunu ortamı seçerken söyle.
46
+
47
+ ### 4 · Yayına hazırla
48
+
49
+ 5. **Mağaza metinleri.** Uygulamanın dilleri için `settings.listing.<dil>`: `title` (≤ 30), `subtitle` (≤ 30),
50
+ `shortDescription` (≤ 80), `description` (≤ 4000), `keywords` (dizi; virgülle birleşince ≤ 100), `releaseNotes`. Metni
51
+ uygulamanın gerçek ekranlarından yaz; reklam dili, rakip adı, "en iyi" gibi ifadeler yok. iOS açıksa
52
+ `apple.categories.primary` ve `apple.copyright`, Android açıksa `play.contactEmail`.
53
+ 6. **Görseller.** Derleme görselleri (`icon`, `adaptiveForeground`, `adaptiveBackground`,
54
+ `adaptiveMonochrome`, `splash`) eksikse kullanıcıdan dosya iste ya da var olan dosyanın yolunu sor.
55
+ Ekran görüntüsü: her mağaza dili ve açık platformun cihaz sınıfı için 3–5 gerçek ekran —
56
+ `page_screenshot { applicationSlug, pageSlug, environment: 'production', device, format: 'jpeg', quality: 92, language, colorScheme: 'light', outPath }`
57
+ → `mobile_asset_create { applicationId, kind: 'screenshot', deviceClass, locale, path }`. `applicationSlug`
58
+ `application_list`'ten, `pageSlug` `page_list`'ten; `device` rehberdeki cihaz tablosundan; `language` o
59
+ yuvanın `locale`'idir — verilmezse kare projenin varsayılan dilinde çıkar ve başka dilin yuvasına yanlış dilde
60
+ yüklenir. Yuva birikimlidir (en çok 10 görsel): 1. adımda okuduğun yuvada görsel varsa kullanıcıya sormadan
61
+ ekleme yapma. Giriş ve splash sayfası çekilmez. Production'da sayfa yoksa kullanıcıya sor: ekran görüntüsü
62
+ canlıya almadan sonraya kalabilir.
63
+ 7. **Yaş derecelendirmesi** (iOS açıksa). `settings.apple.advisory`: rehberdeki **bütün** soruları cevapla;
64
+ reklam açıksa `advertising: 'true'`. Emin olmadığın soruyu kullanıcıya sor.
65
+ 8. **Gizlilik.** `settings.urls.privacyPolicy` (https). Yoksa kullanıcıdan iste; uydurma adres yazma.
66
+ 9. **Beyanlar.** Açık mağazanın beyanlarını (`appPrivacy` · `dataSafety`, `contentRating`, `targetAudience`,
67
+ `appAccess`) kullanıcıya hatırlat; onay gelenleri işaretle, gelmeyenleri kalanlar listesine yaz.
68
+ 10. **Sürüm, fiyat, yayın.** `apple.releaseType` (varsayılan `manual`), `apple.pricing`, `apple.territories`;
69
+ kullanıcının tercihi yoksa varsayılanı koru ve bunu raporda söyle. Konsolda elle yapılanları (fiyat planı,
70
+ içerik derecelendirme anketi gibi) kalanlara yaz.
71
+ 11. **Mağaza ön kontrolü.** Açık her platform için `mobile_build_start { applicationId, platform, target, dryRun: true }`
72
+ (iOS `testflight`, Android `internal`; kapsam `store` — mağazaya giden işin bütün kuralları). Ajanın düzeltebildiği
73
+ `fail` satırlarını düzelt ve yeniden koş; düzeltemediklerini kalanlara yaz.
74
+
75
+ Her `mobile_store_update` yanıtındaki `changed` ve MOB-022 uyarılarını oku; 409 (bayat kayıt) gelirse aynı
76
+ yamayla yeniden çağır.
77
+
78
+ ## Rapor
79
+
80
+ Sonunda iki tablo ver:
81
+
82
+ 1. **Doldurduklarım** — adım · bölüm · alan · yazılan değer (uzun metinde ilk 60 karakter).
83
+ 2. **Sana kalanlar** — iş · nerede (Studio › Yayın › Hesaplar, App Store Connect, Play Console) · neden ·
84
+ hangi adımı kilitliyor.
85
+
86
+ Ardından tek cümleyle sıradaki adımı söyle. Studio sonraki adımı ancak öncekinin koşulu karşılanınca açar:
87
+ 3 · Test sürümü'nde kimlik ya da bu sürümün gittiği mağazanın hesap bölümü eksikse 4 · Yayına hazırla açılmaz (test
88
+ derlemesi kapı değildir); 4 · Yayına hazırla'da eksik bölüm kalırsa 5 · Canlıya al açılmaz; 5'te production'a gitmemiş
89
+ değişiklik (`changes.live`) varsa dağıtım insan onaylıdır — kullanıcıya Studio'dan canlıya almasını söyle.
@@ -1,8 +1,8 @@
1
1
  {
2
- "hash": "ba18a5111614d9b1e63e0d50f1a06a4dce1081b3d482c88e7620ca4bda9a466b",
3
- "generatedAt": "2026-10-14T08:45:02.944Z",
4
- "types": 337,
5
- "files": 167,
2
+ "hash": "638d3ad06d25c77b52f15815d4a450310d1158b5a2823627934cc7a4af6532cd",
3
+ "generatedAt": "2026-10-21T22:18:11.599Z",
4
+ "types": 348,
5
+ "files": 173,
6
6
  "note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
7
7
  "missing": [
8
8
  "NgApps.Infrastructure.Models.IdNamePair`1[[System.Guid, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]",
@@ -0,0 +1,76 @@
1
+ {
2
+ "schema": {
3
+ "required": [
4
+ "operations"
5
+ ],
6
+ "type": "object",
7
+ "properties": {
8
+ "id": {
9
+ "type": "string",
10
+ "format": "uuid"
11
+ },
12
+ "expectedHash": {
13
+ "type": "string",
14
+ "nullable": true
15
+ },
16
+ "operations": {
17
+ "minItems": 1,
18
+ "type": "array",
19
+ "items": {
20
+ "$ref": "#/components/schemas/NgApps.Application.Contexts.Studio.Microfunctions.MicrofunctionArchiveOperationDto"
21
+ }
22
+ }
23
+ },
24
+ "additionalProperties": false
25
+ },
26
+ "components": {
27
+ "schemas": {
28
+ "NgApps.Application.Contexts.Studio.Microfunctions.MicrofunctionArchiveOperationDto": {
29
+ "required": [
30
+ "path"
31
+ ],
32
+ "type": "object",
33
+ "properties": {
34
+ "type": {
35
+ "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.Microfunctions.MicrofunctionArchiveOperationType"
36
+ },
37
+ "path": {
38
+ "minLength": 1,
39
+ "pattern": "^(?!.*(?:^|/)\\.{1,2}(?:/|$))[^/\\\\\\x00]+(?:/[^/\\\\\\x00]+)*$",
40
+ "type": "string"
41
+ },
42
+ "content": {
43
+ "type": "string",
44
+ "nullable": true
45
+ },
46
+ "encoding": {
47
+ "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.Microfunctions.MicrofunctionArchiveContentEncoding"
48
+ },
49
+ "newPath": {
50
+ "type": "string",
51
+ "nullable": true
52
+ }
53
+ },
54
+ "additionalProperties": false
55
+ },
56
+ "NgApps.Domain.Contexts.Studio.Microfunctions.MicrofunctionArchiveOperationType": {
57
+ "enum": [
58
+ "write-file",
59
+ "create-directory",
60
+ "delete",
61
+ "rename"
62
+ ],
63
+ "type": "string",
64
+ "format": ""
65
+ },
66
+ "NgApps.Domain.Contexts.Studio.Microfunctions.MicrofunctionArchiveContentEncoding": {
67
+ "enum": [
68
+ "utf8",
69
+ "base64"
70
+ ],
71
+ "type": "string",
72
+ "format": ""
73
+ }
74
+ }
75
+ }
76
+ }
@@ -28,6 +28,9 @@
28
28
  },
29
29
  "source": {
30
30
  "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.ConnectData.ConnectDataSourceMetaModel"
31
+ },
32
+ "lookupMobile": {
33
+ "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.ConnectData.ConnectDataLookupMobileModel"
31
34
  }
32
35
  },
33
36
  "additionalProperties": false
@@ -100,6 +103,13 @@
100
103
  },
101
104
  "isMultiple": {
102
105
  "type": "boolean"
106
+ },
107
+ "dateBuckets": {
108
+ "type": "array",
109
+ "items": {
110
+ "type": "string"
111
+ },
112
+ "nullable": true
103
113
  }
104
114
  },
105
115
  "additionalProperties": false
@@ -190,6 +200,9 @@
190
200
  "isSchemaSampled": {
191
201
  "type": "boolean"
192
202
  },
203
+ "grouping": {
204
+ "type": "boolean"
205
+ },
193
206
  "parameters": {
194
207
  "type": "array",
195
208
  "items": {
@@ -200,6 +213,19 @@
200
213
  },
201
214
  "additionalProperties": false
202
215
  },
216
+ "NgApps.Domain.Contexts.Studio.ConnectData.ConnectDataLookupMobileModel": {
217
+ "type": "object",
218
+ "properties": {
219
+ "mode": {
220
+ "type": "string",
221
+ "nullable": true
222
+ },
223
+ "row": {
224
+ "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.ConnectData.ConnectDataMobileRowModel"
225
+ }
226
+ },
227
+ "additionalProperties": false
228
+ },
203
229
  "NgApps.Domain.Contexts.Access.Policies.FieldAccess": {
204
230
  "enum": [
205
231
  "hidden",
@@ -338,6 +364,24 @@
338
364
  }
339
365
  },
340
366
  "additionalProperties": false
367
+ },
368
+ "NgApps.Domain.Contexts.Studio.ConnectData.ConnectDataMobileRowModel": {
369
+ "type": "object",
370
+ "properties": {
371
+ "title": {
372
+ "type": "string",
373
+ "nullable": true
374
+ },
375
+ "subtitle": {
376
+ "type": "string",
377
+ "nullable": true
378
+ },
379
+ "trailing": {
380
+ "type": "string",
381
+ "nullable": true
382
+ }
383
+ },
384
+ "additionalProperties": false
341
385
  }
342
386
  }
343
387
  }
@@ -177,6 +177,13 @@
177
177
  },
178
178
  "isMultiple": {
179
179
  "type": "boolean"
180
+ },
181
+ "dateBuckets": {
182
+ "type": "array",
183
+ "items": {
184
+ "type": "string"
185
+ },
186
+ "nullable": true
180
187
  }
181
188
  },
182
189
  "additionalProperties": false
@@ -249,6 +256,9 @@
249
256
  "isSchemaSampled": {
250
257
  "type": "boolean"
251
258
  },
259
+ "grouping": {
260
+ "type": "boolean"
261
+ },
252
262
  "parameters": {
253
263
  "type": "array",
254
264
  "items": {
@@ -70,6 +70,14 @@
70
70
  },
71
71
  "nullable": true
72
72
  },
73
+ "dependencies": {
74
+ "type": "string",
75
+ "nullable": true
76
+ },
77
+ "testArguments": {
78
+ "type": "string",
79
+ "nullable": true
80
+ },
73
81
  "publish": {
74
82
  "type": "boolean"
75
83
  }
@@ -117,6 +117,9 @@
117
117
  },
118
118
  "isAnonymous": {
119
119
  "type": "boolean"
120
+ },
121
+ "offlineWritable": {
122
+ "type": "boolean"
120
123
  }
121
124
  },
122
125
  "additionalProperties": false