@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
@@ -374,7 +374,7 @@ Kompleks projede kimliği platform yönetir; uygulamanın kendi kimlik middlewar
374
374
  | `POST …/auth/refresh` | yenileme çerezi (ya da gövdede `refreshToken`) → yeni jetonlar; eski yenileme jetonu tekrar gelirse bütün aile iptal, 401 |
375
375
  | `POST …/auth/sign-out` | çerezleri siler |
376
376
  | `GET …/auth/me` | kullanıcı, roller, pozisyonlar, birimler, şirketler |
377
- | `GET /{proje}/runtime/{app}/access` | izin özeti: `mode`, izinli sayfa ve uç slug'ları, entity başına eylemler ve alan düzeyleri (arayüzde gizleme için; `enforce` dışında her şey açık döner) |
377
+ | `GET /{proje}/runtime/{app}/access` | izin özeti: `mode`, izinli sayfa ve uç slug'ları, entity başına eylemler ve alan düzeyleri (arayüzde gizleme için; `enforce` dışında her şey açık döner — basit projede `off` ve listeler boş, kompleks projede `off`/`shadow` her şeyi listeler). **Runtime basit projede bu ucu çağırmaz:** tür sayfa yanıtının `project.accessModel`'inde ve `uiActions` yanıtının `accessModel`'inde gelir; özet istemcide kurulur (ADR 0021) |
378
378
 
379
379
  - Jeton önce çerezden, yoksa `Authorization: Bearer`'dan okunur. Çerezle gelen **durum değiştiren**
380
380
  istek `X-ZY-CSRF` başlığında `ZY_Csrf_{proje}` değerini ister (yoksa `403 CsrfTokenMismatch`);
@@ -691,9 +691,9 @@ Ağacın bugünkü kuralları — hepsi 2026-09-20'de ölçüldü (S2-17 · S2-1
691
691
  ## Toplu işlem
692
692
 
693
693
  Kapsam ve koşul her satırda ayrı ayrı uygulanır; dolayısıyla "hepsini birden onayla" bir POLİTİKA
694
- sorusu değil bir UÇ sorusudur ve table-source `update` bunu **filtreyle yapamaz** — tam olarak bir
695
- tekil alan filtresi ister (`InvalidFilterCountException` · `FilterFieldMustUniqueException`,
696
- ölçüldü 2026-09-20, S2-22). Doğru kurulum: anahtarlar elindeyse `bulk-update` ucu (tek çağrı, tek
694
+ sorusu değil bir UÇ sorusudur ve table-source `update` bunu **filtreyle yapamaz** — hedefi her
695
+ zaman tek satırdır: tek kök filtre, benzersiz alan + `eq`, ek koşullar yalnız AND grubunda
696
+ (MS-019; `platform_guide('microservice')` §"Güncelle/sil filtresi"). Doğru kurulum: anahtarlar elindeyse `bulk-update` ucu (tek çağrı, tek
697
697
  transaction), satır başına sonuç ve satır başına yetki kararı gerekiyorsa **iş akışı + döngü**
698
698
  (liste → her satır için `microservice` adımı → özet). Akış içinden yazmak yetki YÜKSELTMEZ: her
699
699
  satır çağıranın kimliğiyle denetlenir ve reddedilen satır ötekileri geri almaz. Reçete:
@@ -51,8 +51,21 @@ Komponentlerin KENDİ arayüz metni (tablo sayfalaması, filtre operatörleri, b
51
51
  düğmeleri) ve sayı/tarih biçimleri uygulamanın aktif dilinden gelir — prop vermene gerek yok.
52
52
  İki ayrı kural işliyor ve karıştırılmamalı:
53
53
 
54
- - **Metin İngilizceye düşer.** Kütüphanenin sözlüğü tr/en taşır; projede `de` seçiliyse o metinler
55
- İngilizce çıkar. Yeni dil eklemek sözlüğe satır eklemektir, komponent değişikliği değil.
54
+ - **Metin önce uygulama sözlüğünden gelir; Metin İngilizceye düşer** (bileşen kelimeleri, frontend ADR 0023 / 0024;
55
+ 2026-10-15).
56
+ Kelime listesi olan bileşen (tablo, sürüm karşılaştırma, qm'in kullandığı form ve gösterim bileşenleri) her kelimesini
57
+ önce uygulama sözlüğünde arar: kendi kelimesi `compProp.<bileşen>.<kelime>`, birçok bileşende geçen kelime ("Yükleniyor…",
58
+ "Kapat", "Ara") tek satır `compProp.common.<kelime>`. Satır yoksa kütüphanenin tr/en/ar tohumu, o da yoksa İngilizce.
59
+ Yeni dil eklemek sözlüğe satır eklemektir. Ayrıntı ve yazım yolları: `platform_guide('translation')` §Bileşenin kendi
60
+ kelimeleri.
61
+ - **`texts` ayarı:** kelimesi olan web bileşeninin gizli `texts` ayarı yalnız o düğümde değiştirilen kelimeleri taşır
62
+ (`{ rowsPerPage: { type: 'translation', ref: 'page.x.y' } }` ya da düz metin). Bütün bileşenlerin kelimesini değiştirmek
63
+ için `texts`'e değil sözlüğe yaz. Mobil bileşenlerde `texts` yoktur.
64
+ - **Kelime gibi çalışan ayar boş bırakılır.** Açılır kutu ve çoklu seçim `placeholder`'ı, etiket kutusu `placeholder` /
65
+ `createNewLabel`'ı, ağaç görünümü `searchPlaceholder` / `emptyText` / `actionsTitle`'ı, tarih-saat `placeholder` /
66
+ `timePlaceholder`'ı, tarih-saat aralığının saat yer tutucuları, seçicinin `trueLabel` / `falseLabel`'ı boşken ortak kelimeyi
67
+ gösterir ("Bir seçenek seçin", "Ara", "Açık / Kapalı" …). Web kataloğunda bunların varsayılanı yoktur; yalnız sayfaya özel
68
+ metin yaz. Ayarı hiç yazmamak kelimeyi gösterir; bilerek boş metin (`''`) yazmak yer tutucuyu / etiketi kaldırır.
56
69
  - **Biçim düşmez.** Sayı ayraçları ve tarih adları seçilen dilin kendi kuralını kullanır
57
70
  (`de` → `1.234,5`). Dili olmayan bir biçim yoktur; dil verilmediğinde taban İngilizcedir.
58
71
 
@@ -60,7 +73,9 @@ Bazı komponentlerin `locale` prop'u geriye uyum için durur ve **doluysa kazan
60
73
  sabitleme içindir. Boş bırakmak doğru varsayılandır.
61
74
 
62
75
  Doğrulama mesajını çeviriye bağlamak ayrı bir sözleşmedir (`t:` öneki, `platform_guide('page')`
63
- §validasyon); prop'ları bağlamak için `set_prop_type` (`platform_guide('translation')`).
76
+ §validasyon); prop'ları bağlamak için `set_prop_type` (`platform_guide('translation')`). **Kuralın mesajı boşsa** ekran
77
+ kuralın varsayılan kelimesini gösterir (`compProp.common.validationRequired`, `…MinLength` "En az {value} karakter girin" …;
78
+ sayı kuralın `value`'sundan) — varsayılan mesaj için kurala İngilizce cümle yazma, `message`'ı boş bırak.
64
79
 
65
80
  ## Olay modeli
66
81
 
@@ -93,7 +108,8 @@ arayüzdür**, yetkiyi backend her istekte yeniden denetler.
93
108
  "Göster" yalnız erişim özeti yüklüyken çıkar: `off`'ta (basit proje hep `off`) hiç çıkmaz —
94
109
  backend her reveal'i reddeder; `shadow`'da çıkar — backend reveal'i yine denetler, yetkisiz
95
110
  kullanıcı ret mesajını görür; `enforce`'ta yalnız entity'nin `actions`'ında `reveal` varsa.
96
- Değeri boş maskeli hücrede "Göster" çıkmaz. Tasarımcı kanvasında (**View as user**) düğme seçilen
111
+ Değeri boş maskeli hücrede "Göster" çıkmaz. Web tasarımcı kanvasında (**Kullanıcı gözüyle** / View as user; mobil
112
+ ekran tasarımcısındaki karşılığı **Kim olarak** çipidir; mobil `datatable` `revealEntity`'yi düşürür) düğme seçilen
97
113
  kullanıcıya sunulacağı yerde etkisiz çizilir (kullanıcı seçili değilken tasarımcının
98
114
  `project.data.reveal` izni karar verir); gerçek açma önizlemededir.
99
115
  Açılan değer prop'a, akışa, olaya yazılmaz. Entity `revealEntity` prop'undan (slug ya da id) ya
@@ -0,0 +1,98 @@
1
+ # Deployment Rehberi (development → production)
2
+
3
+ `deployment_start` projeyi `development`'tan `production`'a taşır; production'a giden **tek** yol
4
+ budur ve **insan onaylıdır**. Bu rehber deploy'un neyi taşıdığını, neyi taşımadığını ve production'da
5
+ eksik çıkan satırın ya da dosyanın neden eksik olduğunu anlatır. Dal açma ve merge için
6
+ `platform_guide('merge')`.
7
+
8
+ ## Varsayılan: yalnız tanım taşınır
9
+
10
+ Deploy bir **tanım** aktarımıdır. Ayar açılmadıkça tablo satırları ve dosyalar production'a gitmez —
11
+ development'ta doldurulan bir tablo production'da boş, development'a yüklenen bir görsel production'da
12
+ 404 çıkar. Bu tasarım gereğidir, hata değildir: development verisini production'a kopyalamak bir veri
13
+ kazasıdır, bu yüzden her tablo ve her dosya ayrıca seçilir.
14
+
15
+ | Ne | Taşınır mı | Kural |
16
+ |---|---|---|
17
+ | Entity, alan, index, sayfa, layout, workflow, DTO, query, microservice, fonksiyon, çeviri, tema | evet | her deploy'da |
18
+ | Süreç tanımı ve iş takvimi | evet | yalnız aktif model; yayınlanmamış taslak taşınmaz (`deployment_start` yanıtı `unpublishedDrafts`) |
19
+ | Microfunction | evet | yalnız YAYINLANMIŞ kod; hedefte yayınlanır (DEP-006) |
20
+ | Tablo satırları | **yalnız tabloda kayıt taşıma açıksa** | §Tablo satırları |
21
+ | Dosyalar | **yalnız id referansıyla** | §Dosyalar |
22
+ | Kullanıcı, rol ataması, süreç örneği, görev, defter | hayır | ortama özgüdür |
23
+
24
+ Kaynak yalnız `development`'tır (DEP-003); deploy başlamadan production verisi ön denetimden geçer
25
+ (DEP-004). İkisinin ayrıntısı `deployment_start` açıklamasında.
26
+
27
+ ## Tablo satırları (recordTransferMode)
28
+
29
+ Satırlar **tablo başına** açılan kayıt taşıma ayarıyla gider. Ayar entity tanımındadır:
30
+
31
+ | `recordTransferMode` | Ne taşınır |
32
+ |---|---|
33
+ | yok (`null`, varsayılan) | hiçbir satır |
34
+ | `'all'` | tablonun bütün satırları |
35
+ | `'specific'` + `transferRowIds: ['<id>', …]` | yalnız seçilen satırlar ve bu satırların FK ile gösterdiği satırlar |
36
+
37
+ - **Yazmak:** `entity_patch` ile `{op:'replace', path:'/recordTransferMode', value:'all'}` (seçili
38
+ satırlar için ayrıca `/transferRowIds`), ya da `entity_update` tam gövdesi. `'specific'` iken
39
+ `transferRowIds` dolu, tekil ve boşsuz olmalıdır (ENT-018).
40
+ - **Studio karşılığı:** Tablo paneli → **"Sistem kayıtlarını dağıtımlar/şablonlar üzerinden aktar"**.
41
+ Aynı ayar şablon kurulumunda da geçerlidir.
42
+ - **Birlikte giden:** çok dilli tablonun `*_localization` çeviri tablosu ve junction (çoka-çok)
43
+ satırları ana tabloyla **otomatik** gider; onlara ayrıca ayar açılmaz. Junction satırı yalnız iki
44
+ tarafı da taşınıyorsa gider (dosya tarafı her zaman geçer).
45
+ - **Kimlikler 1:1 korunur:** satır production'a aynı birincil anahtarla yazılır, identity sayacı
46
+ taşınan id'lerin ötesine ilerletilir. Production'da aynı id'li satır varsa üzerine yazılır.
47
+ - **`'all'` = ayna (DEP-005, backend ADR 0011):** promote'ta production o tabloda development'ın
48
+ aynasıdır. Kaynakta olmayan satır, çevirisi ve junction satırı production'da **silinir** —
49
+ production'a doğrudan girilmiş satırlar dahil. Kaynak tablo boşsa hedef tablo boşalır. Platformun
50
+ kendi tabloları (`users`, `roles`, `permissions`) taşımaya açılabilir ama aynalanmaz.
51
+ - **`'specific'` silmez:** yalnız upsert yapar. Seçili satırın FK ile gösterdiği satırlar zincirleme
52
+ gelir (bir satır seçmek birkaçını taşıyabilir); seçilmemiş bir satıra giden çoka-çok bağı düşer.
53
+ - **İlişki sırası:** `'all'` açılan tablonun ilişki hedefinde de taşıma açık olmalıdır, yoksa kayıt
54
+ `RelationTransferNotEnabledException` ile reddedilir — önce hedef (ebeveyn) tabloyu açın. `'all'`
55
+ bir tablonun gösterdiği tabloda taşımayı kapatmak da reddedilir. `'specific'` bu denetimden muaftır:
56
+ seçili satırın ilişki sütunu taşınmayan bir satırı gösterirse hata production'da FK ihlali olarak
57
+ çıkar.
58
+
59
+ Kayıt taşıma deploy'un kuralıdır. Dal açarken `includeRecords: true` bu ayara bakmadan bütün veri
60
+ tablolarını kopyalar; merge satır taşımaz (`platform_guide('merge')` §Dalda çalışmak).
61
+
62
+ ## Dosyalar
63
+
64
+ `files` tablosu ortama aittir ve **toptan taşınmaz**. Bir dosya production'a yalnız iki yoldan biriyle,
65
+ **id'siyle başvurulduğu için** gider:
66
+
67
+ 1. **Dosya tipli prop:** sayfa ya da komponent prop'unda `{ type:'file', ref:'<fileId>' }` —
68
+ Studio panelinin dosya seçicisinin yazdığı şekil budur. Tasarım bu dosyayı id'siyle tutar.
69
+ 2. **Taşınan bir satırın dosya sütunu:** kayıt taşıması açık tabloda tekil dosya alanının ya da dosya
70
+ çoka-çok alanının taşıdığı dosya id'leri. Satır gitmiyorsa dosyası da gitmez.
71
+
72
+ Dosya production'a **aynı id'yle** yazılır. Production'da o id zaten varsa yalnız adı güncellenir;
73
+ içerik yeniden yüklenmez ve kaynakta değişen içerik production'a geçmez.
74
+
75
+ **Sabit URL tuzağı.** Sayfaya metin olarak yazılmış bir dosya adresi (görselin `src`'sine düz URL,
76
+ html içeriği, stil) deploy'da **yeniden yazılır** — development serve öneki `…/files/serve/d/…`
77
+ production'da `…/files/serve/p/…` olur (dal öneki de aynı biçimde çevrilir). Ama bu yalnız metin
78
+ değişimidir: adresin gösterdiği **dosya kopyalanmaz**, production'da adres **404** döner. Görseli
79
+ production'a taşımak için onu dosya tipli prop'a (`ref`) ya da taşınan bir satırın dosya sütununa
80
+ bağlayın.
81
+
82
+ ## Production'a doğrudan yazılmaz
83
+
84
+ Eksik satır ya da dosya production'da elle tamamlanamaz. Production ortamında `file_upload`,
85
+ `row_create`, `row_update`, `row_delete` ve `import_*` araçları backend'de yazma korumasına
86
+ (`ProductionWriteGuardBehavior`) takılır ve **400 `CantWriteInProductionException`** döner. Yol her
87
+ zaman aynıdır: düzeltmeyi development'ta yapın (ayarı açın, prop'u bağlayın), sonra insan onaylı
88
+ yeni bir deploy.
89
+
90
+ ## Production'da eksik veri teşhisi
91
+
92
+ | Belirti | Bak | Düzeltme (development'ta) |
93
+ |---|---|---|
94
+ | Tablo production'da boş ya da eksik | `entity_get` → `recordTransferMode` | `'all'` ya da `'specific'` + `transferRowIds`; ilişki hedeflerini önce açın |
95
+ | Çeviriler eksik, satırlar var | ana tablonun ayarı | çeviri tablosu ana tabloyla gider; ana tabloda ayar açık olmalı |
96
+ | Görsel production'da 404 | `page_schema_get` → prop düz URL mi, `{ type:'file', ref }` mi | prop'u `ref` ile bağlayın ya da dosyayı taşınan satırın dosya sütunundan okuyun |
97
+ | Satırın dosyası 404, satır var | satır taşınıyor mu (`recordTransferMode`) | dosya yalnız taşınan satırla gider |
98
+ | Production'da silinmiş satırlar | tablo `'all'` mı | ayna kuralı (DEP-005); production'a girilen veri bu tabloda tutulmaz |
@@ -624,7 +624,7 @@ karakter, primaryKey yok). Tam katalog, kaynak referanslı JSON: `ngapps://rules
624
624
  | `folderId` | yalnız `commonType: 'file'` alanında | ENT-017 |
625
625
  | `properties.generationType` | yalnız `commonType` `guid` ya da `number` | ENT-017 |
626
626
  | `commonType` / `defaultValueType` / `relationType` | sözlükten; bilinmeyen değer 400 `InvalidEnumTokenException` (`multiFile` diye bir tip YOK) | ENT-017 |
627
- | `recordTransferMode: 'specific'` | `transferRowIds` dolu, tekil, boşsuz | ENT-018 |
627
+ | `recordTransferMode: 'specific'` | `transferRowIds` dolu, tekil, boşsuz; ayar yoksa deploy satır taşımaz — `platform_guide('deployment')` §Tablo satırları | ENT-018 |
628
628
  | `indexes[]` | ad önek hariç en fazla 32, `fieldIds` dolu ve tekil, adlar tekil | ENT-013 |
629
629
 
630
630
  **Birincil anahtar kalıbı** (bu rehberde yoktu; 2026-09-08 koşusunda iki hatalı çağrı + bir
@@ -10,6 +10,10 @@
10
10
 
11
11
  Uydurma fonksiyon adı runtime'da `X is not defined` 500'üdür — yalnız buradakileri kullan.
12
12
 
13
+ **Hiçbir ifade görünen metinle karşılaştırılmaz** (`durum === 'Onaylandı'`, `title !== 'Aksiyonlar'`,
14
+ `/Klasörler/.test(...)`): kod değerine, state'e, değişkene, `Page.queryParams`'a, elementId / sınıfa bağlanır. UI flow
15
+ yazımında gateway yeni kancayı TR-005 ile durdurur — `platform_guide('translation')` §Mantık görünen metne bağlanmaz.
16
+
13
17
  ## 1. Backend ifadeleri — kullanılabilir bağlam
14
18
 
15
19
  **Değişkenler:** step çıktıları (`<stepAdı>.data`), middleware değişkenleri (`user`,
@@ -107,7 +111,7 @@ dalından devam eder.
107
111
  | `setComponentProperty(name, key, value)` / `getComponentProperty(name, key)` | fonksiyon alternatifi |
108
112
  | `resetForm(name)` | Formu sıfırlar: alanlar başlangıç değerine döner, form "gönderilmemiş" olur, doğrulama mesajları silinir. Kayıt sonrası "yeni kayıt" için alanları tek tek `null`'a çekme — gönderilmiş formda her biri "zorunlu alan" mesajı çıkarır. Ad ya da komponent değişkeni alır: `resetForm('risk_form')` / `resetForm(risk_form)`. **Yalnız UI flow kodunda** |
109
113
  | `LocalStorage` · `Widget` · `params` | yerel veri · widget bağlamı · olay parametreleri. `LocalStorage` barındırıcının deposudur, salt okunur ve değerler METİNdir: web'de uygulamanın kökenindeki `localStorage` (Studio önizlemesinde Studio'nun kendi anahtarları da görünür), cihazda akışın `storage` deposu. `storage` adımı düz bir anahtara yazınca `LocalStorage.<anahtar>` aynı akışta yeni değeri verir ve sayfanın bağları yeniden değerlendirilir (`isSelected: {{ LocalStorage['zeyrek:theme-mode'] === 'dark' }}`). `state.page\|app.<key>`'e yazan adım `LocalStorage`'a girmez (ARC-147, 2026-09-29) |
110
- | `Device` | Salt okunur cihaz durumu, barındırıcı günceller: `Device.isOnline` — ağ bağlantısı var mı (bilinmiyorsa `true`). Değişince sayfanın bütün bağları yeniden değerlendirilir; çevrimdışı bandı: `isHidden: {{ Device.isOnline }}`. Cihazda `expo-network`, web'de tarayıcının `online`/`offline` olayları. `Device` adında komponent ifade bağlamından süzülür (ayrılmış ad) |
114
+ | `Device` | Salt okunur cihaz durumu, barındırıcı günceller: `Device.isOnline` — ağ bağlantısı var mı (bilinmiyorsa `true`). Değişince sayfanın bütün bağları yeniden değerlendirilir; çevrimdışı bandı: `isHidden: {{ Device.isOnline }}`. Cihazda `expo-network`, web'de tarayıcının `online`/`offline` olayları. `Device.biometric = { available, enrolled, kinds }` (kök ADR 0021): `available` cihaz kullanıcıyı şu an doğrulayabilir (biyometri **ya da** cihaz parolası kurulu), `enrolled` biyometri kayıtlı, `kinds` ⊆ `face · fingerprint · iris`; barındırıcı vermezse (web, derleme taşımıyor) `{ available: false, enrolled: false, kinds: [] }`, Studio önizlemesi ve kanvas senaryosu `{ true, true, ['face'] }`. Uygulama ön plana dönünce yeniden okunur. Ağ yokken okumaların ne döndüğü (`Steps.<ad>.cache.at`, `error.network`): `platform_guide('page')` §Kural 1g-4. `Device.offline` (yalnız cihazda): `{ ready, total }` — uygulamanın kaç ekranı çevrimdışı açılmaya hazır; paket inmeden ve web/önizlemede yoktur (`Device.offline?.ready`); servis yazması kuyruğu varsa `queue: { pending, rejected }` ve `rejected` (reddedilen kayıtlar) da buradadır. `Device` adında komponent ifade bağlamından süzülür (ayrılmış ad) |
111
115
  | **Ayrılmış adlar** | Bu tablodaki globallerle (ve önsözün iç adlarıyla: `payload`, `error`, `repeaterId`, `_` ile başlayanlar…) aynı `name`'i taşıyan komponent (runtime yalnız İLK `-`'yi siler: `ite-m` da `item` sayılır) ifadede kendi adıyla GÖRÜNMEZ — süzülür, uyarı loglanır (liste: `@ng-apps/flow` `EXPRESSION_PRELUDE_NAMES`). Eskiden aynı ad sayfanın BÜTÜN ifadelerini `SyntaxError`'la düşürürdü (ARC-143). Gateway artık bu adların HEPSİNİ **PAGE-009** ile sayfa/layout yazma yollarında ve `page_schema_validate`'te istek gitmeden reddeder — komponente `t`, `state`, `event`, `item`, `self`, `Page`, `Row` gibi ad verme |
112
116
  | `t(key)` | Çeviri anahtarını çözer: aktif dil → projenin varsayılan dili → anahtarın kendisi. Boş string de "eksik" sayılır. Sözlük `machine.context.state.translations`'tan gelir; dil `language-selector` ile değişince bir sonraki çağrı yeni dili görür. **Yalnız UI flow kodunda vardır** — backend ifadelerinde karşılığı `Loc()`'tur (`platform_guide('workflow')`) | `t('home.welcome')` |
113
117
  | `log(...)` | console (proxy'leri temizler) |
@@ -109,10 +109,12 @@ platform yeniden başlamaz, açık oturumlar bozulmaz.
109
109
 
110
110
  ## Editor modu
111
111
 
112
- `zxContext.editorMode` true olduğunda element Studio kanvasında statik bir
113
- önizleme olarak duruyor: zamanlayıcı kurmayın, ağ çağrısı yapmayın, tıklamayı
114
- işlemeyin. Kanvasta etkileşim host tarafından zaten engellenir, ama gereksiz iş
115
- yapmamak kanvası hızlı tutar.
112
+ `zxContext.editorMode` yalnız web sayfa tasarımcısının kanvasında true'dur;
113
+ önizlemede ve runtime'da false. True iken element statik bir önizleme olarak
114
+ duruyor: zamanlayıcı kurmayın, ağ çağrısı yapmayın, tıklamayı işlemeyin.
115
+ Kanvasta etkileşim host tarafından zaten engellenir, ama gereksiz iş yapmamak
116
+ kanvası hızlı tutar. Mobil uygulamada dış bileşen çizilmez; mobil ekran
117
+ tasarımcısının Düzenle / Dene kipi bu bayrağı taşımaz.
116
118
 
117
119
  ## Geliştirici kiti
118
120
 
@@ -10,6 +10,10 @@ onaylıdır**. Buradaki tool'ların hiçbiri production'a yazmaz.
10
10
  - **Production'a merge eden tool yoktur.** Production'a giden tek yol insan onaylı deployment'tır.
11
11
  - Sabit environment'lar (`development`, `production`) silinemez; `environment_delete` bunu HTTP'ye
12
12
  gitmeden reddeder.
13
+ - **Şablondan kurulup güncellemeleri alan projede dal açılamaz, var olan dal değiştirilemez** (`project_get` →
14
+ `templateMetadata.installedTemplateReceiveUpdates: true`): dal açma/silme ve merge planının her adımı
15
+ 400 döner (MRG-018). Değişiklik şablonun kaynak projesinde yapılır, `template_create` ile yayımlanır,
16
+ abone projede `template_check_updates` → `template_receive_updates` ile alınır.
13
17
 
14
18
  ## Akış
15
19
 
@@ -36,9 +40,9 @@ yazmaya çalışmak 400 döner — `environment_list` ile durumu doğrula.
36
40
  Dal açılırken **yalnız tanımlar** kopyalanır. `includeRecords: true` verirsen projenin kendi
37
41
  veritabanındaki **bütün** veri tablolarının satırları da gelir — entity'de kayıt taşıması ayarı
38
42
  açık olmasa bile (çok dilli companion tablolar ve junction'lar dahil; `files`/`folders` ve audit
39
- trail tabloları hariç, dış datasource'lara dokunulmaz). Kayıt taşıması ayarı deployment'ın
40
- (`promote`) kuralıdır ve orada aynen geçerlidir. **Satırlar merge'de geri taşınmaz** — merge yalnız
41
- tanım işidir.
43
+ trail tabloları hariç, dış datasource'lara dokunulmaz). Merge'de geri gelen satırlar yalnız **kayıt
44
+ taşıması ayarı açık** tablolarınkidir; promote (`platform_guide('deployment')`) ve şablonla aynı
45
+ ayar, ama kural üç yollu: aşağıda "Tablo kayıtları".
42
46
 
43
47
  Tanım sayılan ve merge'in taşıdığı üç şey 2026-09-25'ten beri listede: **çeviriler**
44
48
  (translation kalemi, adı çeviri anahtarı), **microfunction'lar** (kod ve arşiv; hedefte **taslak**
@@ -169,6 +173,16 @@ runtime'ın çizdiği satırlar `….children`. **Kararı `ref`'e verin**; `chil
169
173
  seçimi aynen geçer; `both` ve `custom` satırlara listeden yeniden kurulur. `children`'a ayrı ve farklı karar vermek
170
174
  ekranda listenin değil satırların çizilmesine yol açar.
171
175
 
176
+ **Widget prop'unda da yollar aynıdır** (2026-10-15'ten beri). Widget prop'larını düz satırda tutar ama merge onları
177
+ sayfa gibi ağaç olarak karşılaştırır: dizi prop'unun satırları `widgetComponentProps[id=<prop>].children` yolunda gelir,
178
+ kararı `widgetComponentProps[id=<prop>].ref`'e verin. Öncesinde satırlar ayrı ayrı `add` geliyordu. İki taraf aynı
179
+ widget'ı kaydedince satırlar çoğalıyor, `ref` kararı satırlara geçmiyordu (MRG-017). O tarihten önce açılmış plan
180
+ eski yollarla da doğru uygulanır; ağaç görünümü için `merge_refresh` yeter.
181
+
182
+ **Sınır (sayfa ve widget):** iki taraf listenin öğe sayısını değiştirmeden aynı öğeyi farklı değiştirdiyse liste
183
+ konumsal karşılaştırılır. `ref`'in alt yollarında (`….ref[1].label.data`) ve satırlarda (`….children[2].ref`) ayrı
184
+ çakışmalar gelir; `ref` kararı satırlara geçmez. Hepsine **aynı tarafı** seçin, yoksa liste ile satırlar ayrışır (P-19).
185
+
172
186
  **Nesne prop'unda** (butonun `icon`'u, `surfaceStyle`) aynı kural anahtar düzeyindedir: anahtarın değeri
173
187
  `….ref.<anahtar>…`, runtime'ın çizdiği satırı `….children[name=<anahtar>]…`. İki taraf aynı anahtara farklı yazdıysa
174
188
  ikisi de çakışma gelir; **kararı `ref.<anahtar>`'a verin**. Satır karar istemez ve `summary.unresolved`'a girmez:
@@ -220,7 +234,7 @@ yine ayrı eklenir.
220
234
  |---|---|---|
221
235
  | `unresolved` | error | çözülmemiş çakışma ya da `slug` taşıyan çözümsüz kopya; apply 409 döner. Dizi prop'unun `children`'ı `ref` açıkken, nesne prop'unun satırı (`children[name=…]`) değeri çakışırken, türetilmiş DTO elemanı kaynağı açıkken ayrı satır almaz ve `summary.unresolved`'a girmez: kaynağı çözünce kendiliğinden çözülür |
222
236
  | `duplicate-open` | warning | çözümsüz kopya (`combinable: true`), ikisi de yazılacak |
223
- | `name-clash` | warning | birleşik gövdede aynı adla iki kardeş (örneğin iki `telefon` sütunu) |
237
+ | `name-clash` | warning | birleşik gövdede aynı adla iki kardeş (örneğin iki `telefon` sütunu). Widget prop'unda kardeş, aynı öğenin aynı üst prop ve satırdaki prop'udur; iki ayrı öğenin aynı adlı prop'u uyarı vermez |
224
238
  | `dangling-reference` | warning | merge'ün sildiği ya da kopya kararında düşen bir kimliğe hâlâ başvuru var |
225
239
 
226
240
  Uyarılar apply'ı engellemez; ama okunmadan `merge_apply` çağrılmaz.
@@ -229,6 +243,51 @@ Uyarılar apply'ı engellemez; ama okunmadan `merge_apply` çağrılmaz.
229
243
  yoktur; kalan çakışmalar için `merge_get {planId, view:"conflicts"}` çağırın.
230
244
  `summary.unresolved` 0 olduğunda `merge_apply` yolu açıktır.
231
245
 
246
+ ## Tablo kayıtları
247
+
248
+ 2026-10-17'den beri merge, **kayıt taşıması ayarı açık** tabloların satırlarını da taşır ("Transfer system records
249
+ through deployments/templates"; `specific`'te yalnız seçili satırlar). Ayarın kapsamı toplayıcınındır: tablonun
250
+ çeviri tablosu ve iki ucu ayarlı bağlantı tablosu da gelir. Kullanıcılar ve kullanıcı ↔ grup üyelikleri hiçbir ayarla
251
+ taşınmaz; roller için aşağıdaki **Roller** maddesi.
252
+
253
+ - **Kalem tablodur:** `module: "row"`, `recordId` = entity kimliği, `name` = tablo adı. Satır farkı `rows.<anahtar>`,
254
+ hücre farkı `rows.<anahtar>.<sütun>` yolundadır; etiket anahtar + satırın okunur alanıdır (`571 · dm-documents-compare`).
255
+ - **Yalnız dalın değişiklikleri kalem üretir.** Taban dal açılışındaki satırlardır. Development'ın kendi eklediği ya da
256
+ değiştirdiği satır plana girmez ve apply ona dokunmaz. Denetim sütunları (`sys_created_at`, `sys_updated_at`,
257
+ `sys_created_user_id`, `sys_updated_user_id`) sayılmaz.
258
+ - **Silme** yalnız dalda `all` olan tabloda çıkar: dalın sildiği, development'ın dokunmadığı satır `delete` gelir.
259
+ `specific` ve çeviri tablolarında dalın silmesi taşınmaz. **Ek alansız bağlantı tablosu** (junction, iki bağ alanı)
260
+ satırını `(sol, sağ)` çiftiyle tanır: anahtar `rows.<sol>|<sağ>`'dir, aynı bağ iki tarafta farklı kimlikle tek bağdır;
261
+ sahibi (sol taraf) dalda `all` ise dalın kaldırdığı bağ development'tan da kalkar (ADR 0031).
262
+ - **Kimlik çakışması:** iki taraf tabanda olmayan aynı anahtarla farklı satır açtıysa `rows.<anahtar>` yolunda tek
263
+ `conflict` gelir, `base` boştur. `source` dalın satırını yazar, development'ınki ezilir. `target` dalın satırını düşürür.
264
+ `custom` `value`'daki satırı yazar. `both` ikisini de tutar: development'ın satırı yerinde kalır, dalın satırı
265
+ **yeni anahtarla** eklenir. Sayı anahtarda en büyüğün bir fazlası, `uuid`'de yeni kimlik verilir. Dalın o satıra bakan
266
+ satırları yeni anahtara çevrilir. `both` yalnız `combinable: true`'da geçer; metin anahtarda 400 döner.
267
+ - **Development tabloyu taşımıyorsa** (entity var, ayarı kapalı) development'ın satırları bilinmez: tablo kökünde tek
268
+ çakışma gelir. `source` dalın satırlarını yazar (silmeden), `target` atlar. Tablo development'ta hiç yoksa satırlar
269
+ `add`'dir.
270
+ - **Veri olmadan açılmış dal**da taban yoktur: yalnız dalda olan satır `add`, iki tarafta farklı olan satır kimlik
271
+ çakışması gelir.
272
+ - **Roller `[SY] Roles`'un kendi ayarıyla gelir** (2026-10-18). Rol kalemi `module: "role"`dur, satır kalemi değil;
273
+ gövdesi uygulamanın `roles`'a eklediği alanları (`code` …) da taşır. Dalda `roles` `all` ya da `specific` ise ayarın
274
+ kapsadığı roller `add` / `update` gelir (`delete` yalnız `all`'da), rolün kendi bağları (rol ↔ izin) satır kalemidir.
275
+ **Ayar kapalıysa** yalnız dalın bir sayfası, ucu, klasörü, erişim politikası ataması ya da taşınan bir satırı
276
+ kimliğiyle, bir süreç tanımı slug'ıyla gösterdiği **yeni** rol `add` gelir; rol ↔ izin bağları gelmez, development'taki
277
+ rol değişmez. Dalın yeni rolleri ve bağları gidecekse `merge_plan`'dan önce dalda `entity_patch roles` ile
278
+ `recordTransferMode`'u `all` ya da `specific` (+ `transferRowIds`) yapın. Başka tablonun role bağı (grup ↔ rol) o
279
+ tablonun ayarıyla gelir, gösterdiği rol development'ta yoksa kurulur. İki tarafın da eklediği aynı bağ (ek alansız
280
+ bağlantı tablosu) tek bağ sayılır, `23505` vermez. Development'ta ayar kapalıyken dalda ilk açılışta rolün bağ tablosu
281
+ kökte tek çakışma gelir → `source` (o ilk merge'te silme çıkmaz, development'ın bağları bilinmiyordur). Ayar iki
282
+ tarafta da açıkken dalda kaldırılan izin ve silinen rolün bağları development'tan da kalkar, rol de silinir.
283
+ - **Apply ayna yapmaz.** Yalnız planın değiştirdiği satırlar yazılır, silinecek anahtarlar önce silinir.
284
+ Development'ta ayarlı bir tablo plandan sonra değişirse plan bayatlar (`isStale`) ve `merge_refresh` ister.
285
+ `merge_revert` satırları da ters çevirir: merge'ün eklediği satır `delete` gelir.
286
+
287
+ ```json
288
+ { "itemKey": "row:01a0…", "path": "rows.571", "choice": "both" }
289
+ ```
290
+
232
291
  ## Apply'ın reddettiği üç durum
233
292
 
234
293
  | Durum | Kod | Ne yapmalı |
@@ -239,6 +298,17 @@ yoktur; kalan çakışmalar için `merge_get {planId, view:"conflicts"}` çağı
239
298
 
240
299
  Aynı `merge_apply` çağrısını tekrarlamak sonucu değiştirmez — 409 geçici bir hata değildir.
241
300
 
301
+ Bir kararın yazılacağı yer development'ın gövdesinde yoksa `merge_get { checks: true }` hata düzeyinde bir
302
+ `not-applicable` kontrolü döner (yol `path`'tedir). O hâlde apply etme: planı yenile (`merge_refresh`), o yoldaki kararı
303
+ yeniden ver ve kontrolleri tekrar oku. Kontrol sürerse `platform_gap_report` ile bildir; bu, motorun eşleyemediği bir
304
+ dizi demektir.
305
+
306
+ Kontrol okunmadan apply edilirse süreç `MergeResolutionNotApplicableException` ile hataya düşer. Plan `failed` olur ve
307
+ yenilenemez; yeni plan gerekir.
308
+
309
+ 2026-10-18 öncesinde bu kararlar sessizce düşüyordu. Workflow dalları artık adla eşlenir (`branches[name=…]`); adı
310
+ değişen dal kayıt kimliğiyle tanınır, kimliği Studio'da yenilenmiş dal da kaybolmaz.
311
+
242
312
  ## Başlık zorunludur
243
313
 
244
314
  İsteğin adı **plan açılırken** `merge_plan`'ın `title` alanında verilir; `merge_apply` ve `merge_revert` ayrı bir
@@ -332,6 +402,13 @@ plan `applied` kalır.
332
402
  - `applied` → dal `merged` olur ve **şeması düşer**; `environment_list` artık göstermez.
333
403
  - `applied-with-drift` → dal ve şeması **durur**. `verification.driftTables` dal ile development
334
404
  arasında hâlâ farklı olan tabloları listeler; incelenmeden dal silinmez.
405
+ - **Bilinen yanlış alarm — platform tabloları (geçici çözüm, 2026-10-15).** `driftTables` yalnız `users`,
406
+ `roles`, `files`, `folders` ve `permissions`'tan oluşuyorsa fark gerçek değildir. Bu tabloların zorunlu
407
+ sütunları, platformun 2026-10-06 öncesi koduyla dokunulmuş bir development'ta `NOT NULL`, yeni açılan dalda
408
+ `NULL`'dır; doğrulama bu farkı görür. Merge'ün içeriği development'a tam geçmiştir. Dal ise `merged` ve aktif
409
+ kalır: proje başına 5 dal sınırından yer tutar, taban görüntüsü temizlenmez. Bu tablolara dokunan her merge'de
410
+ tekrar eder. Yapılacak: dalı elle silin — `environment_delete {projectId, environmentId}` (`merged` dal
411
+ silinir, şeması düşer). `driftTables`'ta bunların dışında bir tablo varsa dalı silmeden önce o farkı inceleyin.
335
412
  - `failed` → plan `failed`, dal `ready`'ye döner. Dal ve içindeki iş kaybolmaz; yeniden planlanır.
336
413
 
337
414
  ## Sınırlar
@@ -17,7 +17,7 @@ verir (gateway kendi çağrısında 200 gönderir; platform varsayılanı 10'dur
17
17
  |---|---|
18
18
  | Birkaç satır dönüşüm, alan eşleme, koşul | `code` step / ifade (aynı süreç, en ucuz) |
19
19
  | İfadelerde çıplak adla çağrılacak yardımcı | global function (`global_function_create`, JS) |
20
- | Kütüphane gerektiren iş (kriptografi, PDF, görüntü, parse) | microfunction (zip kaynak) |
20
+ | Kütüphane gerektiren iş (kriptografi, PDF, görüntü, parse) | microfunction + bağımlılık (§Bağımlılıklar) |
21
21
  | Python gereken iş | microfunction — platformun ifade motoru YALNIZ JavaScript'tir |
22
22
  | Uzun süren/CPU yiyen iş | microfunction (kendi bütçesi, API sürecini bloke etmez) |
23
23
 
@@ -42,12 +42,13 @@ def handler(args, context):
42
42
  return {"total": args["a"] + args["b"], "environment": context["environment"]}
43
43
  ```
44
44
 
45
- - `args` — adımın `rule.expression`'ından üretilen argüman nesnesi. Fonksiyonun
46
- `parameterDtoId`'si yoksa `{}` gelir.
45
+ - `args` — adımın `rule.expression`'ından üretilen argüman. Şekli `parameterBehavior`'dır:
46
+ `object` ⇒ nesne, `array` ⇒ dizi, `primitive` ⇒ tek değer. Fonksiyonun `parameterDtoId`'si
47
+ yoksa `{}` gelir.
47
48
  - `context` — **salt okunur anlık görüntü**. İçine yazmak hiçbir şeyi değiştirmez; akışa dönen
48
49
  tek kanal fonksiyonun DÖNÜŞ DEĞERİdir.
49
50
 
50
- `context` şekli (ölçüldü, `MicrofunctionStep.BuildContext`):
51
+ `context` şekli (ölçüldü, `MicrofunctionStep.EvaluateAsync`'in kurduğu sözlük):
51
52
 
52
53
  ```jsonc
53
54
  {
@@ -96,6 +97,16 @@ draft ──publish──▶ publishing ──▶ published ──update──
96
97
  4. `microfunction_delete` runtime'daki fonksiyonu da kaldırır; bir workflow adımı kaydı
97
98
  kullanıyorsa 400 ile reddedilir.
98
99
 
100
+ ## Test çağrısı ve kayıtlı argüman
101
+
102
+ - `microfunction_invoke`'un `args`'ı **herhangi bir JSON değeridir** — liste modelli fonksiyona
103
+ dizi, tek değer modelliye sayı/metin gönderin; workflow adımının gönderdiği şekille aynıdır.
104
+ - `testArguments` Studio'nun Test call sekmesinin kayıtlı argüman metnidir (≤ 64 KB). Olduğu gibi
105
+ saklanır, JSON geçerliliği denetlenmez, koşuma girmez; deployment ve template onu taşır.
106
+ - `microfunction_update` **tam gövdedir**: `testArguments` verilmezse kayıtlı metin silinir —
107
+ güncellemeden önce `microfunction_get`'ten alın. Kaydetmek `revision`'ı artırır (yayındaki
108
+ kayıt `hasUnpublishedChanges: true` olur).
109
+
99
110
  ## Workflow adımı (WF-MF-001)
100
111
 
101
112
  Adım tipi `microfunction`; `workflow`, `automation` ve `middleware` akışlarının hepsinde
@@ -177,13 +188,97 @@ kullanıcısı verin, `roleArn` fonksiyonun koşacağı execution rolüdür ve *
177
188
  deseni tutmayan hesap gateway'de durur (MFR-001, block). Kaydettikten sonra
178
189
  `microfunction_runtime_test_connection` ile doğrulayın.
179
190
 
191
+ ## Bağımlılıklar: dış paketler (MF-001, MF-007)
192
+
193
+ Paketlerin tek gerçeği dilin manifest dosyasıdır: Python `requirements.txt`, Node `package.json`.
194
+
195
+ | Kaynak | Nerede bildirilir |
196
+ |---|---|
197
+ | `inline` | `dependencies` alanı — **satır başına bir paket**; platform yayında manifest dosyasını bu metinden yazar |
198
+ | `archive` | Zip'teki `requirements.txt` / `package.json` (`microfunction_files_apply` ile düzenlenir); `dependencies` alanı yok sayılır |
199
+
200
+ Satır biçimi (inline; boş ve `#` satırları yorumdur, toplam ≤ 16 KB):
201
+
202
+ - **python:** requirements.txt satırı olduğu gibi — `pillow==11.1.0`, `requests>=2.32`,
203
+ `python-dateutil==2.9.0.post0`. pip seçeneği (`-r`, `--index-url`, `-e`) **yasak**.
204
+ - **node:** `ad@aralık` — `sharp@^0.33.0`, `@scope/ad@1.2`; aralıksız satır (`dayjs`) `latest` olur.
205
+ Ad küçük harftir.
206
+
207
+ Kural dışı satır istek gitmeden durur (MF-001, block; platform 422
208
+ `MicrofunctionDependenciesInvalid`).
209
+
210
+ **Yayın.** Etkili satır varsa Built-In yayın paketleri Fission builder'da kurar (`pip install -r
211
+ requirements.txt` / `npm install`); kayıt build süresince `publishing` kalır — ölçülen süreler 4–30 sn,
212
+ tavan 300 sn. Kurulum düşerse kayıt `publish-failed` olur ve `publishError` build günlüğünün son
213
+ 4 KB'ını taşır (`No matching distribution found for …` gibi) — bağımlılığı düzeltip yeniden yayınlayın.
214
+ Etkili satır yoksa yayın build'siz ve bugünkü hızındadır.
215
+
216
+ **Sembolik bağ.** Built-In paketi sembolik bağ taşıyamaz. Platform `.bin` dizinlerindeki bağları
217
+ (`node_modules/.bin/*`: npm'in kurduğu ya da zip'te gelen) kendisi atar; bu yüzden çalışma anında
218
+ paketlerin komut satırı araçları yoktur — kütüphaneyi `require` / `import` ile kullanın. Zip'te başka
219
+ bir bağ varsa yayın `publish-failed` olur ve mesaj bağın yolunu verir: bağı gösterdiği dosyayla
220
+ değiştirin. `file:` ile bağlanan yerel paket de npm kurulumunda bağ olur; zip'e `.npmrc` koyup
221
+ `install-links=true` yazın (ölçüldü 2026-09-30). Eski `.npmrc` `bin-links=false` geçici çözümü artık
222
+ gerekmez; bin komutu çağıran kurulum betiklerini (`bcrypt` gibi yerel paketler) kırdığı için önerilmez.
223
+
224
+ **Eski archive kayıtları:** Faz 1'de paketleri zip'e koyup `requirements.txt` / `package.json`'da da
225
+ bildiren kayıt, bir sonraki yayında build'e girer (manifest artık okunur). Bu kurulum ağa çıkar ve
226
+ birkaç saniye–dakika sürer; zip'teki kurulu paketler yerinde kalır.
227
+
228
+ **Built-In Python 3.13, Node 22'dir** (AWS Lambda'daki `python3.13` / `nodejs22.x` ile aynı). C
229
+ uzantılı paketler (Pillow gibi) hazır wheel'den kurulur — ölçüldü 2026-09-29: `pillow==11.1.0` ile
230
+ bir PNG'yi açıp boyutlandıran inline fonksiyon yayınlandı ve çağrıldı. 2026-09-29'a kadar Built-In
231
+ Python 3.7'ydi; o sürümde kurulmuş paketler yeniden yayında 3.13 için yeniden kurulur.
232
+
233
+ **AWS Lambda'da kurulmaz** (MF-007, warn): paket olduğu gibi gider. Lambda'da paketler kurulmuş
234
+ hâlde zip'in içinde gelmelidir (archive kaynağı; Python'da paket klasörleri, Node'da `node_modules`);
235
+ aksi hâlde yayının probe adımı import hatasıyla `publish-failed` olur.
236
+
237
+ Örnek: `ngapps://examples/microfunction-node-dependencies`.
238
+
239
+ ## Zip kaynağı: arşiv dosyaları (MF-006)
240
+
241
+ `sourceKind: 'archive'` kaydın dosyaları platformdaki zip'in İÇİNDE yaşar; tek gerçek kaynak o
242
+ zip'tir (yayın, deployment ve şablon onu okur). Dört tool:
243
+
244
+ | Tool | Ne yapar |
245
+ |---|---|
246
+ | `microfunction_archive_scaffold` | Arşivi olmayan kayda dilin iskeletini yazar ve kaydı zip kaynağına çevirir: node → `main.js` + `package.json` (`dependencies: {}`), python → `main.py` + `requirements.txt` (yalnız yorum); entrypoint `main.handler`. Boş manifest build gerektirmez. Arşiv varsa 409 |
247
+ | `microfunction_files_list` | `{ hash, entries: [{ path, size, isDirectory }] }` — yalnız açık girdisi olan klasörler listelenir, ara klasörler yollardan çıkar |
248
+ | `microfunction_file_get` | `{ path, size, isBinary, content }` — 1 MB üstü ya da UTF-8 olmayan dosyada `isBinary: true`, içerik yok |
249
+ | `microfunction_files_apply` | `{ expectedHash, operations[] }` işlemlerini SIRAYLA uygular, yeni zip üretir, eski zip'i siler |
250
+
251
+ İşlemler: `write-file` (oluştur ya da değiştir; ikili dosyada `content` base64 +
252
+ `encoding: 'base64'`, MCP'den ≤ 8 MB; satırlara bölünmüş base64 da olur, platform boşluğu yok
253
+ sayar) · `create-directory` · `delete` (klasörse altındaki her
254
+ girdiyle) · `rename` (`newPath`; klasörse altındakilerle birlikte). Yol `'/'` ayraçlıdır, kökle
255
+ başlamaz, `/` ile bitmez, boş/`.`/`..` segmenti ve ters bölü içermez — klasör de sondaki `/`
256
+ olmadan yazılır (`lib`). Kural dışı gövde istek gitmeden durur (MF-006, block).
257
+
258
+ **Yalnız zip kaynaklı kayıtta:** satır içi kayıtta `microfunction_files_apply` 400 döner
259
+ (`sourceKind`); önce `microfunction_archive_scaffold` (arşiv yoksa) ya da `microfunction_update`
260
+ ile `sourceKind: 'archive'`. Aynı anda iki yazan olursa biri kazanır, öteki 409 alır.
261
+
262
+ **`expectedHash` zorunlu sıra:** önce `microfunction_files_list`, dönen `hash`'i `apply`'a verin.
263
+ Kayıt o arada değiştiyse 409 (`MicrofunctionArchiveConflictException`) döner ve hiçbir şey
264
+ yazılmaz — listeyi yeniden okuyup işlemleri ona göre kurun. Arşivi olmayan kayıtta hash verilmez.
265
+
266
+ **Entrypoint yayında denetlenir.** Değişiklik entrypoint modülünü silse ya da taşısa bile yazılır
267
+ (MF-006 warn; sonraki bir işlem modülü ya da klasörünü aynı yola geri getiriyorsa uyarı yok), ama `microfunction_publish` modül zip'te yoksa 400 döner. Modül yolu entrypoint'in
268
+ son `.`'sından öncesi + dilin uzantısıdır: `handlers/sum.handler` → `handlers/sum.js`
269
+ (Python'da `.py`). **Node'da giriş modülü `index.js` olamaz**: o ad platform shim'inindir; yayın
270
+ bunu da 400 ile reddeder.
271
+
272
+ Paketler zip'teki `requirements.txt` / `package.json`'a yazılır ve Built-In yayında kurulur
273
+ (§Bağımlılıklar). Yayındaki kaydı değiştirmek `hasUnpublishedChanges` üretir; yeni kod
274
+ `microfunction_publish` ile canlıya alınır.
275
+
180
276
  ## Sınırlar (v1)
181
277
 
182
- - **Bağımlılık build'i yok:** inline kod yalnız standart kütüphanedir; bağımlılık zip içinde gelir.
183
- - **MCP'den zip yükleme ve indirme yok** (`sourceKind: 'archive'` kaydı açılabilir, dosya
184
- Studio'dan yüklenir) — Faz 2. Yüklenmiş zip platform ucunda okunabilir durumdadır
185
- (`GET /{proje}/microfunctions/{id}/archive`, `application/zip`) ve Studio inspector'ında bir
186
- indirme düğmesi taşır.
278
+ - **Bağımlılık build'i yalnız Built-In'de:** AWS Lambda'da paketler zip'te gelmelidir (MF-007).
279
+ - **Tek parça zip yükleme ve indirme MCP'de yok:** zip'in içeriği dosya düzeyinde okunur ve yazılır
280
+ (§Zip kaynağı). Zip'in tamamı platform ucunda okunabilir durumdadır
281
+ (`GET /{proje}/microfunctions/{id}/archive`, `application/zip`) ve Studio'dan indirilir.
187
282
  - `timeoutSeconds` ve `memoryMb` komutta non-nullable int'tir: **göndermezseniz 0 gider ve platform
188
283
  422 döner.** Gateway değer uydurmaz, eksikliği çağrıdan önce söyler (MF-001, block; ürün
189
284
  varsayılanları 30 / 256). Aynı kural provider ↔ `runtimeId` eşleşmesini, inline kaynakta `code`
@@ -344,13 +344,42 @@ kart doğru sütuna geçer, başlığı ve sorumlusu silinir.
344
344
  > ifadeden gelir ve `undefined` dönen ifade de `null` yazar —
345
345
  > `platform_guide('workflow')` §"Table update adımı".
346
346
 
347
+ ### Güncelle/sil filtresi: tek satır + sahiplik koşulu (MS-019, block)
348
+
349
+ `update` · `upsert` · `delete` ucu **tek kök** filtre ister ve hedef her zaman **tek satırdır**:
350
+
351
+ | Filtre ağacı | Sonuç |
352
+ |---|---|
353
+ | Tek filtre: benzersiz alan + `eq` | Geçer |
354
+ | Tek kök `group`; çocukların hepsi tekil ve `conditionType: 'and'` (ilki dahil); biri benzersiz alan + `eq` | Geçer |
355
+ | Benzersiz alan `neq`/`in`/`contains`… · çocuklardan biri `or` · iç içe grup · kökte iki filtre | Gateway MS-019 ile durdurur; platform `FilterFieldMustUniqueEqException` / `InvalidFilterCountException` |
356
+ | Koşullarda benzersiz alan yok | Platform `FilterFieldMustUniqueException` (gateway alanın benzersizliğini bilmez) |
357
+
358
+ **Basit erişim modelinde sahiplik koşulunu uç kendisi koyar.** Kimliği bilen herkes `id eq`
359
+ filtreli bir uçla başkasının satırını değiştirebilir; bunu kapatan grup:
360
+
361
+ ```jsonc
362
+ "filters": [{
363
+ "filterType": "group", "conditionType": "and",
364
+ "children": [
365
+ { "filterType": "single", "conditionType": "and", "fieldId": "<id alanı>", "alias": "<entity slug>", "operator": "eq", "source": "query-string" },
366
+ { "filterType": "single", "conditionType": "and", "fieldId": "<sahip alanı>", "alias": "<entity slug>", "operator": "eq", "source": "expression", "value": "user.id" }
367
+ ]
368
+ }]
369
+ ```
370
+
371
+ `user.id` için uca auth middleware'i bağlanır (MS-011). Sahip koşulu tutmazsa işlem **0 satır**
372
+ döner, hata vermez. Karmaşık erişim modelinde platform sahip koşulunu satır kapsamından kendisi
373
+ AND'ler (`platform_guide('access')`); orada bu grup gereksizdir ama zararsızdır. AND/OR filtrenin
374
+ kendinde değil **bir öncekine bağlantısındadır**: `or` taşıyan çocuk, ilk çocuk bile olsa hedefi
375
+ genişletir. Kural yalnız kayıtta uygulanır; 2026-10-15'ten önce kaydedilmiş uyumsuz uç yeniden
376
+ kaydedilince reddedilir. Workflow table adımı bu kuralı uygulamaz.
377
+
347
378
  ### Toplu güncelleme FİLTREYLE kurulmaz
348
379
 
349
- "Bekleyen bütün başvuruları onayla" bir table-source `update` ucuyla YAZILAMAZ. `update`
350
- operasyonu tam olarak **bir tekil alan filtresi** ister: birden çok filtre
351
- `InvalidFilterCountException`, tekil olmayan alanla filtre `FilterFieldMustUniqueException`
352
- döndürür (ölçüldü 2026-09-20, S2-22). Yani hedef kümeyi bir KOŞUL belirleyemez, yalnız bir ANAHTAR
353
- belirler. İki doğru yol var:
380
+ "Bekleyen bütün başvuruları onayla" bir table-source `update` ucuyla YAZILAMAZ: hedef kümeyi bir
381
+ KOŞUL belirleyemez, yalnız bir ANAHTAR belirler (yukarıdaki §"Güncelle/sil filtresi"; ilk ölçüm
382
+ 2026-09-20, S2-22). İki doğru yol var:
354
383
 
355
384
  | Ne istiyorsun | Yol |
356
385
  |---|---|