@appaflytech/zeyrek-ai-mcp 0.0.28 → 0.0.30
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.
- package/.env.example +15 -0
- package/README.md +5 -5
- package/dist/config.js +37 -0
- package/dist/index.js +2 -0
- package/dist/knowledge/access.js +802 -0
- package/dist/knowledge/backendConstraints.js +18 -1
- package/dist/knowledge/case.js +41 -0
- package/dist/knowledge/componentCatalog.js +494 -34
- package/dist/knowledge/componentEvents.js +132 -7
- package/dist/knowledge/connectDataBind.js +819 -0
- package/dist/knowledge/connectDataDefinition.js +341 -0
- package/dist/knowledge/connectDataExecute.js +93 -0
- package/dist/knowledge/connectDataRules.js +128 -0
- package/dist/knowledge/decision.js +121 -0
- package/dist/knowledge/expressionPrelude.js +59 -0
- package/dist/knowledge/layoutSummary.js +140 -2
- package/dist/knowledge/microserviceParameters.js +58 -0
- package/dist/knowledge/mining.js +94 -0
- package/dist/knowledge/mobileComponentCatalog.js +859 -0
- package/dist/knowledge/mobileComponentEvents.js +239 -0
- package/dist/knowledge/normalize.js +236 -67
- package/dist/knowledge/outlines.js +36 -0
- package/dist/knowledge/platform/lint.js +385 -0
- package/dist/knowledge/platform/mobile.js +142 -0
- package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
- package/dist/knowledge/platform/mobileRules.js +231 -0
- package/dist/knowledge/platform/mobileSpacing.js +82 -0
- package/dist/knowledge/platform/mobileTabs.js +108 -0
- package/dist/knowledge/platform/nativeBoxModel.js +44 -0
- package/dist/knowledge/platform/profile.js +25 -0
- package/dist/knowledge/platform/resolve.js +122 -0
- package/dist/knowledge/platform/web.js +39 -0
- package/dist/knowledge/policy.js +18 -4
- package/dist/knowledge/process.js +510 -0
- package/dist/knowledge/reservedTables.js +79 -0
- package/dist/knowledge/rowFilter.js +43 -0
- package/dist/knowledge/rules.js +319 -21
- package/dist/knowledge/schemaGuard.js +11 -0
- package/dist/knowledge/styleResolve.js +50 -4
- package/dist/knowledge/styleResolveNative.js +527 -0
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +6 -3
- package/dist/platform/argumentAliases.js +128 -0
- package/dist/platform/bodyFile.js +103 -0
- package/dist/platform/capture/actions.js +333 -0
- package/dist/platform/capture/browser.js +1 -0
- package/dist/platform/{screenshot.js → capture/capture.js} +105 -519
- package/dist/platform/capture/console-log.js +122 -0
- package/dist/platform/capture/index.js +11 -0
- package/dist/platform/capture/readiness.js +103 -0
- package/dist/platform/capture/summary.js +77 -0
- package/dist/platform/capture/target.js +5 -0
- package/dist/platform/capture/targets/studio-mobile.js +15 -0
- package/dist/platform/capture/targets/studio-web.js +5 -0
- package/dist/platform/diagnostics.js +10 -4
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/errors.js +162 -10
- package/dist/platform/http.js +29 -8
- package/dist/platform/impersonation.js +45 -0
- package/dist/platform/jsonArray.js +24 -0
- package/dist/platform/responses.js +39 -5
- package/dist/platform/schemaReadMemory.js +60 -0
- package/dist/platform/secrets.js +17 -1
- package/dist/platform/strictArguments.js +68 -12
- package/dist/platform/tokenVault.js +187 -4
- package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
- package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
- package/dist/resources/examples/bpm-satinalma.json +376 -0
- package/dist/resources/examples/connect-data-convert-verify.json +107 -0
- package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
- package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
- package/dist/resources/examples/connect-data-query-params.json +50 -0
- package/dist/resources/examples/connect-data-table-entity.json +147 -0
- package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
- package/dist/resources/examples/mobile-app-shell-drawer.json +243 -0
- package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
- package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
- package/dist/resources/examples/mobile-form-screen.json +365 -0
- package/dist/resources/examples/mobile-list-detail-form.json +672 -0
- package/dist/resources/examples/page-detail-profile.json +2 -1
- package/dist/resources/examples/page-dynamic-form.json +3 -2
- package/dist/resources/examples/page-flex-sections.json +1 -1
- package/dist/resources/examples/page-html-embed.json +1 -1
- package/dist/resources/examples/workflow-basic.json +8 -2
- package/dist/resources/guides/access.md +796 -0
- package/dist/resources/guides/bpm.md +686 -0
- package/dist/resources/guides/case.md +153 -0
- package/dist/resources/guides/component.md +91 -4
- package/dist/resources/guides/decision.md +185 -0
- package/dist/resources/guides/entity.md +50 -8
- package/dist/resources/guides/expressions.md +14 -5
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/getting-started.md +38 -1
- package/dist/resources/guides/layout.md +11 -7
- package/dist/resources/guides/microservice.md +81 -2
- package/dist/resources/guides/middleware.md +44 -2
- package/dist/resources/guides/mobile-layout.md +193 -0
- package/dist/resources/guides/mobile.md +495 -0
- package/dist/resources/guides/page.md +454 -75
- package/dist/resources/guides/theme.md +8 -2
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +58 -1
- package/dist/resources/read.js +41 -0
- package/dist/resources/rules.js +11 -5
- package/dist/resources/schema-fingerprint.json +7 -5
- package/dist/resources/schemas/AccessExplanationDto.json +144 -0
- package/dist/resources/schemas/AccessMatrixDto.json +170 -0
- package/dist/resources/schemas/AccessPermissionDto.json +57 -0
- package/dist/resources/schemas/AccessPolicyDto.json +223 -0
- package/dist/resources/schemas/AccessResourceDto.json +86 -0
- package/dist/resources/schemas/AppSessionDto.json +53 -0
- package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
- package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
- package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
- package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
- package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
- package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
- package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
- package/dist/resources/schemas/CreateEntityCommand.json +118 -0
- package/dist/resources/schemas/CreateMicroserviceCommand.json +13 -1
- package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
- package/dist/resources/schemas/CreateQueryCommand.json +4 -0
- package/dist/resources/schemas/CreateWorkflowCommand.json +143 -1
- package/dist/resources/schemas/DataJobDto.json +6 -1
- package/dist/resources/schemas/DecisionDto.json +302 -0
- package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
- package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
- package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +21 -1
- package/dist/resources/schemas/MicroserviceDto.json +15 -3
- package/dist/resources/schemas/OrganizationProjectDto.json +335 -0
- package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
- package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
- package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +10 -1
- package/dist/resources/schemas/PreviewWorkflowCommand.json +22 -1
- package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
- package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
- package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
- package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
- package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
- package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
- package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
- package/dist/resources/schemas/StepDto.json +22 -1
- package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
- package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
- package/dist/resources/schemas/UpdateEntityCommand.json +118 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +13 -1
- package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
- package/dist/resources/schemas/UpdateQueryCommand.json +4 -0
- package/dist/resources/schemas/UpdateViewCommand.json +0 -2
- package/dist/resources/schemas/UpdateWorkflowCommand.json +143 -1
- package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
- package/dist/server.js +27 -1
- package/dist/tools/access.js +369 -2
- package/dist/tools/accessOperations.js +135 -0
- package/dist/tools/accessPolicies.js +170 -0
- package/dist/tools/accessRuntime.js +203 -0
- package/dist/tools/applications.js +60 -3
- package/dist/tools/bpm.js +343 -0
- package/dist/tools/bpmGovernance.js +266 -0
- package/dist/tools/bpmOperations.js +230 -0
- package/dist/tools/bpmReporting.js +154 -0
- package/dist/tools/bpmRouting.js +150 -0
- package/dist/tools/bpmRuntime.js +396 -0
- package/dist/tools/case.js +178 -0
- package/dist/tools/caseRuntime.js +89 -0
- package/dist/tools/common.js +7 -0
- package/dist/tools/components.js +118 -14
- package/dist/tools/connectData.js +449 -0
- package/dist/tools/connectors.js +193 -0
- package/dist/tools/datasources.js +3 -3
- package/dist/tools/decisions.js +206 -0
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +2 -2
- package/dist/tools/designSchemaPatch.js +34 -9
- package/dist/tools/dtos.js +36 -5
- package/dist/tools/entities.js +79 -12
- package/dist/tools/externalComponents.js +26 -5
- package/dist/tools/flows.js +122 -14
- package/dist/tools/folders.js +1 -1
- package/dist/tools/imports.js +5 -2
- package/dist/tools/layouts.js +50 -17
- package/dist/tools/merges.js +1 -1
- package/dist/tools/microservices.js +77 -25
- package/dist/tools/mobile.js +221 -0
- package/dist/tools/modules.js +48 -0
- package/dist/tools/organizationStructure.js +137 -0
- package/dist/tools/pages.js +465 -98
- package/dist/tools/platformInfo.js +27 -8
- package/dist/tools/profileWrite.js +92 -0
- package/dist/tools/projects.js +71 -9
- package/dist/tools/rows.js +69 -13
- package/dist/tools/schemaOps.js +61 -1
- package/dist/tools/screenWrite.js +37 -8
- package/dist/tools/screens.js +95 -5
- package/dist/tools/templates.js +26 -1
- package/dist/tools/translations.js +1 -1
- package/dist/tools/variables.js +11 -5
- package/dist/tools/workflows.js +10 -5
- package/package.json +2 -2
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Vaka Rehberi — CMMN 1.1 vaka yönetimi
|
|
2
|
+
|
|
3
|
+
Adımları önceden bilinmeyen işler içindir: müşteri şikâyeti, soruşturma, hasar dosyası, uygunsuzluk incelemesi. Süreç tanımı
|
|
4
|
+
(`process_definition_*`) sırayı çizer; **vaka** ise aşamaları, isteğe bağlı görevleri ve "şu olunca şu açılır" koşullarını
|
|
5
|
+
(sentry) tanımlar, sırayı olaylar ve kişiler belirler. İnsan görevleri süreç görevleriyle **aynı kutuya** düşer
|
|
6
|
+
(`kind: case-task`) ve `process_task_update` ile tamamlanır. Süreçten vaka `case` düğümüyle başlatılır (§Süreçten vaka).
|
|
7
|
+
|
|
8
|
+
Modüller: `case` (tanım: `case_definition_*`, `case_cmmn_*`) ve `caseRuntime` (`case_execute`, `case_instance_*`).
|
|
9
|
+
|
|
10
|
+
## Başlangıç
|
|
11
|
+
|
|
12
|
+
1. **Modeli yazın** — `case_definition_create { case }`. Taslak sürüm oluşur. Gateway yazmadan önce CASE-001'i denetler
|
|
13
|
+
(§Lint); `case_definition_preview { case }` aynı denetimi istek göndermeden yapar.
|
|
14
|
+
2. **Yayınlayın** — `case_definition_publish { id }`. Çalışan vakalar başladıkları sürümde kalır; production'a yayın yok (BPM-001).
|
|
15
|
+
3. **Başlatın** — `case_execute { slug, subjectRowId, caseFile, asUser }`. Yanıt `planItems[]` ve `availableActions[]` taşır.
|
|
16
|
+
4. **Yürütün** — `case_instance_get` → `availableActions` → `case_instance_update { operation, planItemId }`; insan görevleri
|
|
17
|
+
`process_task_list` / `process_task_update`.
|
|
18
|
+
|
|
19
|
+
Düzeltmede tam modeli yeniden göndermeyin: `case_definition_get` → `case_definition_patch` (`/planItems[id=<öğe>]/…`).
|
|
20
|
+
Başka modelleyiciden gelen CMMN için `case_cmmn_update { filePath }`; dışa aktarma `case_cmmn_get { outPath }`.
|
|
21
|
+
|
|
22
|
+
## Model
|
|
23
|
+
|
|
24
|
+
```jsonc
|
|
25
|
+
{
|
|
26
|
+
"slug": "musteri-sikayeti", "name": { "tr": "Müşteri şikâyeti" }, "description": { "tr": "Şikâyeti inceler ve kapatır." },
|
|
27
|
+
"caseFile": [{ "id": "musteriCevabi" }, { "id": "oncelik", "default": "normal" }],
|
|
28
|
+
"planItems": [
|
|
29
|
+
{ "id": "inceleme", "type": "stage", "required": true, "autoComplete": true },
|
|
30
|
+
{ "id": "sikayeti-incele", "type": "human-task", "parent": "inceleme", "required": true, "assignee": { "rule": "user", "arg": "<kullanıcı id>" } },
|
|
31
|
+
{ "id": "hukuk-gorusu", "type": "human-task", "parent": "inceleme", "discretionary": true, "assignee": { "rule": "role", "arg": "hukuk" } },
|
|
32
|
+
{ "id": "yanit-alindi", "type": "milestone", "entry": ["musteri-cevapladi"] },
|
|
33
|
+
{ "id": "kapanis", "type": "stage", "required": true, "manualActivation": true, "autoComplete": true, "entry": ["musteri-cevapladi"] }
|
|
34
|
+
],
|
|
35
|
+
"sentries": [
|
|
36
|
+
{ "id": "musteri-cevapladi",
|
|
37
|
+
"onParts": [{ "source": "inceleme", "event": "complete" }, { "source": "musteriCevabi", "event": "update" }],
|
|
38
|
+
"ifPart": "caseFile.musteriCevabi != 'yok'" }
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| Alan | Kural (backend `CaseValidator`, hata 422 `CaseInvalid` + bulgu yolu `/planItems[id=x]/alan`) |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `slug`, plan öğesi ve sentry `id` | kebab-case, benzersiz; ilk yayından sonra slug değişmez (400) |
|
|
46
|
+
| `caseFile[].id` | harf, rakam, alt çizgi; `default` herhangi bir JSON |
|
|
47
|
+
| `planItems[].type` | `stage` · `human-task` · `milestone` |
|
|
48
|
+
| `parent` | yalnız bir `stage`; döngü yasak. `parent` yoksa öğe vaka planının köküdür |
|
|
49
|
+
| `required` | aşama tamamlanmadan önce bitmesi gereken öğe; `disable` edilemez |
|
|
50
|
+
| `repeatable` | tamamlanınca yeni `occurrence` açılır; giriş sentry'si ister, kilometre taşında olmaz |
|
|
51
|
+
| `manualActivation` | koşul sağlanınca `enabled` olur, biri `start` edene kadar bekler |
|
|
52
|
+
| `discretionary` | tanımda durur, kişi `add-discretionary` ile ekleyene kadar oluşmaz |
|
|
53
|
+
| `autoComplete` | yalnız `stage`: etkin çocuk kalmayınca ve zorunlular bitince kendiliğinden kapanır |
|
|
54
|
+
| `assignee` | `human-task` için zorunlu: `user` (`arg` kullanıcı id), `role` (`arg` rol slug'ı, aday kaydı), `initiator` |
|
|
55
|
+
| `entry` / `exit` | sentry kimlikleri; girişlerden biri yeter, çıkış öğeyi ve alt ağacını `terminated` yapar |
|
|
56
|
+
| `onParts[].event` | kaynak kilometre taşıysa yalnız `occur`; başka plan öğesiyse `complete` · `start` · `terminate`; vaka dosyası öğesiyse `update` |
|
|
57
|
+
| `ifPart` | Jint; `caseFile.x` (ya da `vars.x`) vaka dosyasını, `initiator` başlatanı okur |
|
|
58
|
+
|
|
59
|
+
Süreç tanımındaki `assignee` sözlüğü (`unit-manager of …`, `position:`) vakada **yoktur**; yalnız üç kural.
|
|
60
|
+
|
|
61
|
+
## Yaşam döngüsü
|
|
62
|
+
|
|
63
|
+
Plan öğesi: `available → enabled → active → completed | terminated | disabled`. Vaka: `active → completed | terminated`.
|
|
64
|
+
|
|
65
|
+
Her değişiklikten sonra platform yerleşimi sabitlenene kadar yeniden çalıştırır: çıkış sentry'si sağlanan öğe `terminated`;
|
|
66
|
+
ebeveyni etkin ve giriş koşulu sağlanan öğe `manualActivation` ise `enabled`, değilse etkin olur (insan görevi görev açar,
|
|
67
|
+
kilometre taşı doğrudan `completed`); kökteki her şey bitince vaka `completed`.
|
|
68
|
+
|
|
69
|
+
Aşama kapanışı **turun sonunda ve yalnız o turda başka hiçbir öğe hareket etmediyse** denenir — bir çocuk daha açılabiliyorken
|
|
70
|
+
aşama kapatılmaz. `autoComplete` aşama etkin çocuğu yokken ve zorunlu çocukları bitmişken kapanır, bekleyen çocuklarını
|
|
71
|
+
`terminated` eder. `autoComplete` **olmayan** aşama da kendiliğinden kapanır ama **bütün** çocukları terminal olmalıdır;
|
|
72
|
+
bekleyen çocuğu varken bekler ve onları terminale çekmez. Çocuğu olmayan aşama yalnız `autoComplete` ise kendiliğinden kapanır,
|
|
73
|
+
değilse elle `complete` bekler (elle `complete` her zaman gevşek koşulu kullanır: etkin çocuk yok + zorunlular bitmiş).
|
|
74
|
+
|
|
75
|
+
Sentry **durum tabanlıdır**: `onPart` kaynağın şu anki durumuna bakar (`complete`/`occur` → tamamlanmış, `start` → etkin ya da
|
|
76
|
+
tamamlanmış, `update` → vaka dosyası öğesi dolu) ve `ifPart` her turda yeniden çalışır. Bu yüzden vaka dosyasını değiştirmek
|
|
77
|
+
(`update-case-file`) bekleyen öğeyi açabilir.
|
|
78
|
+
|
|
79
|
+
## Eylemler
|
|
80
|
+
|
|
81
|
+
`case_instance_get` yanıtındaki `availableActions[] { action, itemId, planItemId }` o an yapılabilecekleri listeler:
|
|
82
|
+
|
|
83
|
+
| `case_instance_update { operation }` | Ne yapar | Hata |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `start` (`planItemId`) | `enabled` öğeyi başlatır | yanlış durum 409 `InstanceStateTransitionNotAllowed` |
|
|
86
|
+
| `complete` (`planItemId`) | etkin aşamayı kapatır (etkin çocuk yok, zorunlular bitmiş); insan görevi görev ucundan kapanır | 409 |
|
|
87
|
+
| `disable` (`planItemId`) | zorunlu olmayan `enabled` öğeyi devre dışı bırakır | 409 |
|
|
88
|
+
| `enable` (`planItemId`) | `available` öğeyi elle açar; giriş sentry'si **varsa** biri sağlanmalı (sentry'si olmayan öğe koşulsuz açılır) | sentry sağlanmıyorsa **422 `CaseSentryNotSatisfied`**, `available` değilse 409 |
|
|
89
|
+
| `add-discretionary` (`itemDefinitionId`) | isteğe bağlı öğeyi ebeveyn aşaması etkinken ekler | aynı öğenin bitmemiş örneği varsa 409 |
|
|
90
|
+
| `update-case-file` (`itemId`, `value`) | vaka dosyasına yazar, yerleşimi yeniden çalıştırır | tanımsız öğe 400 |
|
|
91
|
+
|
|
92
|
+
`enable` `availableActions`'ta **listelenmez**: yerleşim, giriş sentry'si sağlanan ya da hiç sentry'si olmayan öğeyi zaten açar,
|
|
93
|
+
dolayısıyla listede kalan `available` öğe sentry'sini bekliyordur ve ona `enable` 422 döner. Bu bir lint değil çalışma zamanı
|
|
94
|
+
kuralıdır — koşulu sağlamak için vaka dosyasını güncelleyin ya da kaynak öğeyi bitirin. Kapanmış vakada her değişiklik 409.
|
|
95
|
+
|
|
96
|
+
## Görevler
|
|
97
|
+
|
|
98
|
+
`human-task` etkinleşince `ProcessTask` açılır: `kind: case-task`, `instanceId` = vaka kimliği, `nodeId` = plan öğesi `id`,
|
|
99
|
+
`definitionSlug` = vaka slug'ı. `user` ve `initiator` doğrudan atanır; `role` aday kaydı açar ve görev `claim` ister. Tamamlama
|
|
100
|
+
`process_task_update { action: complete, payload, asUser }` — plan öğesi `completed` olur, yük vaka defterine yazılır. Vaka
|
|
101
|
+
görevi süreç defterine yazmaz; görev yardımcısı (`process_task_get { view: 'assistant' }`) çalışır ama `ai-suggestion` satırı
|
|
102
|
+
yalnız öneri tablosuna düşer.
|
|
103
|
+
|
|
104
|
+
Görünürlük: vakayı başlatan, görevi atanan ya da tamamlayan kişi `case_instance_get` ile okur; liste (`case_instance_list`)
|
|
105
|
+
ve başkalarının vakaları `process.view-all` ister. Başlatma `process.start`, tanım yazımı `process.manage` ister.
|
|
106
|
+
|
|
107
|
+
## Süreçten vaka
|
|
108
|
+
|
|
109
|
+
Süreç tanımında `case` düğümü yayındaki vakayı başlatır ve **beklemez** (akış devam eder):
|
|
110
|
+
|
|
111
|
+
```jsonc
|
|
112
|
+
{ "id": "sikayet-ac", "type": "case", "description": "Şikâyet vakasını açar.", "caseSlug": "musteri-sikayeti",
|
|
113
|
+
"input": { "musteriCevabi": "'yok'" }, "output": "vars.sikayetVakasi" }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Başlatan süreç örneğinin başlatanı, iş satırı süreç konusudur; `output` yoluna vaka kimliği yazılır, süreç defterine
|
|
117
|
+
`case-started`. Bilinmeyen ya da yayınlanmamış slug tanım doğrulamasında `CaseUnknown`, çalışma anında düğüm hatası.
|
|
118
|
+
|
|
119
|
+
## CMMN XML
|
|
120
|
+
|
|
121
|
+
`case_cmmn_get` CMMN 1.1 XML üretir (`zeyrek:` uzantısı atamayı, çok dilli ad/açıklamayı, varsayılanı ve sırayı taşır);
|
|
122
|
+
`case_cmmn_update { xml | filePath }` içe aktarır: aynı slug varsa taslağına yazar, yoksa yeni tanım açar. `stage`, `humanTask`,
|
|
123
|
+
`milestone` dışındaki öğeler (`processTask`, `caseTask`, olay dinleyicileri) ve DTD içeren XML 400'dür. Başka araçta
|
|
124
|
+
çizilmiş vakanın atamaları uzantı taşımıyorsa içe aktarma sonrası `case_definition_patch` ile ekleyin.
|
|
125
|
+
|
|
126
|
+
## Lint
|
|
127
|
+
|
|
128
|
+
| Kural | Ne zaman | Önem |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| CASE-001 | `onParts[].source` bir plan öğesi ya da vaka dosyası öğesi değil; `entry`/`exit` tanımsız sentry'ye bakıyor | block |
|
|
131
|
+
|
|
132
|
+
Denetim `case_definition_create`, `case_definition_update`, `case_definition_patch`, `case_definition_publish` öncesinde ve
|
|
133
|
+
`case_definition_preview`'da çalışır. Diğer model kuralları backend'dedir (422 `CaseInvalid` bulgu listesi).
|
|
134
|
+
|
|
135
|
+
## Hata sözlüğü
|
|
136
|
+
|
|
137
|
+
| Kod | Anlamı | Ne yapılır |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `CaseInvalid` (422) | Model kuralı ihlali; `errors[]` yol ve mesaj taşır | yolu `case_definition_patch` ile düzeltin |
|
|
140
|
+
| `CaseSentryNotSatisfied` (422) | `enable` edilen öğenin giriş koşulu sağlanmıyor | kaynak öğeyi bitirin ya da `update-case-file` |
|
|
141
|
+
| `InstanceStateTransitionNotAllowed` (409) | öğe ya da vaka bu eyleme uygun durumda değil | `case_instance_get` ile `availableActions`'a bakın |
|
|
142
|
+
| `CaseUnknown` (422) | süreçteki `case` düğümü yayında olmayan vakaya bakıyor | vakayı yayınlayın |
|
|
143
|
+
| `ReferencedByProcess` (422) | silinen vaka tanımına bir süreç `case` düğümüyle başvuruyor | önce süreci güncelleyin |
|
|
144
|
+
| `InvalidOperation` (400) | vakası olan tanım silinemez | tanımı yerinde bırakın |
|
|
145
|
+
|
|
146
|
+
## Sık tuzaklar
|
|
147
|
+
|
|
148
|
+
- **Sırayı vaka ile çizmek.** Adımlar belliyse süreç tanımı kullanın; vaka bekleme ve dallanmayı sentry'ye çevirir, okunması zorlaşır.
|
|
149
|
+
- **`enable`'ı düzeltme sanmak.** 422 aldıysanız koşul sağlanmamıştır; tekrar denemek değil koşulu sağlamak gerekir.
|
|
150
|
+
- **`repeatable` öğeyi giriş sentry'siz yazmak.** Model reddedilir; tekrar tetikleyicisiz sonsuz döngü olurdu.
|
|
151
|
+
- **Vaka görevini `case_instance_update { complete }` ile kapatmaya çalışmak.** `complete` yalnız aşama içindir; görev
|
|
152
|
+
`process_task_update` ile kapanır.
|
|
153
|
+
- **`caseFile` öğesini tanımlamadan `ifPart`'ta kullanmak.** Tanımsız değer `undefined` okunur; öğeyi `caseFile[]`'a ekleyin.
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
Sayfaya konan her şeyin ortak kuralları. Kuruluş sırası ve şema gövdesi için
|
|
4
4
|
`platform_guide('page')`; HTML kaçış kapısının derin sözleşmesi için `platform_guide('html')`.
|
|
5
5
|
|
|
6
|
+
> **Mobil uygulamada** katalog ayrıdır: `component_list`/`component_get` mobil satırları okur,
|
|
7
|
+
> `component_get` `mobileKnowledge` (bileşenin mobil farkları) ve `mobileNotes` ekler; katalogda
|
|
8
|
+
> olmayan tip `MOB-003` alır. Stil CSS değil React Native'dir — `page_runtime_get(resolveStyles)`
|
|
9
|
+
> `nativeStyle` döner (`platform_guide('mobile')`).
|
|
10
|
+
|
|
6
11
|
## Keşif: iki tool, üç bilgi katmanı
|
|
7
12
|
|
|
8
13
|
```
|
|
@@ -23,7 +28,9 @@ component_get → tek tipin TAM sözleşmesi, üç katman birleşik:
|
|
|
23
28
|
- **`isHidden`** her komponenti gizler; setter ile yazmak katalogda listelenmeyen tiplerde de
|
|
24
29
|
çalışır. Gizli komponent `mount` olayını görünür olana dek TETİKLEMEZ.
|
|
25
30
|
- **`mount`** olayını komponentin kendisi değil ortak katman yayar: komponent ilk kez
|
|
26
|
-
görünür olduğunda bir kez. Sayfa açılış akışı `page_container.mount`'a
|
|
31
|
+
görünür olduğunda bir kez. Sayfa açılış akışı `page_container.mount`'a DEĞİL, sayfanın kendi
|
|
32
|
+
`mount` olayına bağlanır (`page_update { events }`, `platform_guide('page')` Kural 1d-2) —
|
|
33
|
+
`page_container` Studio'nun Layers ağacında görünmez.
|
|
27
34
|
- **`name` = `elementId`** kuralı: runtime her komponent için `const <name> = Components[...]`
|
|
28
35
|
üretir; bozuk ad sayfadaki BÜTÜN ifadeleri öldürür (`platform_guide('page')` Kural 1c-2).
|
|
29
36
|
- **Boyut:** `blocks[].size` katalogdaki `maxSize`'ı aşamaz; yükseklikte
|
|
@@ -74,6 +81,51 @@ Doğrulama mesajını çeviriye bağlamak ayrı bir sözleşmedir (`t:` öneki,
|
|
|
74
81
|
İstisna: `html` komponentinin
|
|
75
82
|
aksiyonları kendi `flow` prop'uyla bağlanır (`platform_guide('html')`).
|
|
76
83
|
|
|
84
|
+
## Korumalı değer ve arayüz yetkisi (kompleks proje)
|
|
85
|
+
|
|
86
|
+
Kompleks projede ortamın zorlama modu `enforce` iken runtime iki şey taşır; ikisi de **yalnız
|
|
87
|
+
arayüzdür**, yetkiyi backend her istekte yeniden denetler.
|
|
88
|
+
|
|
89
|
+
- **Satır metası.** Table-source uçtan dönen satırda korumalı alan varsa
|
|
90
|
+
`__protected: { <alanSlug>: 'masked' | 'plain' }` bulunur; `hidden` alan satırda hiç yoktur.
|
|
91
|
+
`table` · `datatable` · `detailview` · `text` (`record` + `recordField` ile) `masked` alanı
|
|
92
|
+
kilitli maske olarak çizer; "Göster" → gerekçe → değer 30 sn görünür, sonra yeniden maskelenir.
|
|
93
|
+
"Göster" yalnız erişim özeti yüklüyken çıkar: `off`'ta (basit proje hep `off`) hiç çıkmaz —
|
|
94
|
+
backend her reveal'i reddeder; `shadow`'da çıkar — backend reveal'i yine denetler, yetkisiz
|
|
95
|
+
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
|
|
97
|
+
kullanıcıya sunulacağı yerde etkisiz çizilir (kullanıcı seçili değilken tasarımcının
|
|
98
|
+
`project.data.reveal` izni karar verir); gerçek açma önizlemededir.
|
|
99
|
+
Açılan değer prop'a, akışa, olaya yazılmaz. Entity `revealEntity` prop'undan (slug ya da id) ya
|
|
100
|
+
da boşsa erişim özetinden çözülür (`component_get` → `knowledge.propNotes.revealEntity`).
|
|
101
|
+
- **Maske forma bağlanmaz.** Güncelleme formunda korumalı alanın `textinput`'u her zamanki gibi
|
|
102
|
+
`value` ile kaydın alanına bağlanır, yanına `isMasked` eklenir:
|
|
103
|
+
`{{ Steps.<adım>.data.__protected?.tckn === 'masked' }}`. `isMasked` açıkken bağlı değer maske
|
|
104
|
+
metni sayılır ve gösterilmez: alan boş başlar, "Değiştirmek için yeni değer girin" yer tutucusunu
|
|
105
|
+
gösterir, mount sonrası düğüm değerini `null`'a çeker ve `required`'a takılmaz. Kullanıcı yazınca
|
|
106
|
+
sıradan girdidir; değer girdinin yazmadığı bir değere dönerse (forma başka satır seçildi, akış
|
|
107
|
+
alanı sıfırladı) yeni kaydın maskesi yine gizlenir ve temizlenir.
|
|
108
|
+
- **Izgarada kör üzerine yazma (ADR 0007).** Bağlı `datatable`'da `capability.canWrite` politikadan gelir;
|
|
109
|
+
maskeli okumak yazmayı kapatmaz. Maskeli hücre düzenlemeye **boş** açılır, yazılan değer gider, boş bırakılan
|
|
110
|
+
maske gitmez; hücre seçimine girmez, toplu düzenleme maskeli kolonu sunmaz. Korumalı alanı güncellemek için
|
|
111
|
+
form kurmak zorunlu değildir. Eski değeri görerek düzeltmek gerekiyorsa önce "Göster" (30 sn, editöre ön
|
|
112
|
+
doldurulmaz). Bağlı olmayan tabloda ve `table` bileşeninde maskeli hücre düzenlenmez.
|
|
113
|
+
- **Boş değerin gönderilmemesi isteğin kuruluşuna bağlıdır.** Microservice çağrısının parametre
|
|
114
|
+
bağı boş (`null`/`''`) değeri gövdeye koymaz → saklı değer korunur. Gövdeyi akış kodunda ya da
|
|
115
|
+
setter göreviyle elle kuruyorsan (`{ tckn: TextInput1.value }`) `null` gider: `canWrite` yoksa
|
|
116
|
+
403 `AccessFieldWriteDeniedException`, varsa saklı değer **silinir**. Boş maskeli alanı böyle bir
|
|
117
|
+
gövdeye koyma.
|
|
118
|
+
- **`Page.can(permission, resourceKey)`** her ifadede (görünürlük bağı, akış kodu) kullanılır:
|
|
119
|
+
`Page.can('reveal', 'entity:musteriler')` · `Page.can('entity.update', 'entity:<id>')` ·
|
|
120
|
+
`Page.can('view', 'page:musteri/detay')` · `Page.can('execute', 'microservice:musteri-listesi')`.
|
|
121
|
+
İzin kısa eylem adı ya da katalog slug'ıdır; anahtar `entity:<slug|id>` · `page:<slug>` ·
|
|
122
|
+
`microservice:<slug>`. `enforce` dışında (ya da özet yüklenmemişken) HER ZAMAN `true`; okunamayan
|
|
123
|
+
anahtar ya da başka kaynak tipinin izni `enforce`'ta `false`.
|
|
124
|
+
- **Oturum.** `/view` runtime isteklerinde oturum çerezi gider, durum değiştiren isteğe `X-ZY-CSRF`
|
|
125
|
+
eklenir; oturum 401'i bir kez yenilenir (`auth/refresh`) ve istek tekrarlanır. Yenilenemezse
|
|
126
|
+
uygulamanın giriş sayfasına gidilir — sayfa yükü bugün giriş sayfasını taşımadığı için yönlendirme
|
|
127
|
+
backend bunu gönderene dek olmaz (teknik borç). Özetin listelemediği sayfa ana sayfaya döner.
|
|
128
|
+
|
|
77
129
|
## Stil
|
|
78
130
|
|
|
79
131
|
Her komponentin `style` prop'u vardır ve iç parçalara iner (`textinput.style`: `&__label` ·
|
|
@@ -88,7 +140,10 @@ Widget, kendi komponent ağacını taşıyan yeniden kullanılabilir pakettir (`
|
|
|
88
140
|
|
|
89
141
|
1. **Kayıt:** `component_create` — `kind:'widget'`, `widgetType`, `schema` (widget'ın kendi
|
|
90
142
|
ağacı; `name = elementId` kuralı burada da geçerli — layout gibi widget adları da kullanan
|
|
91
|
-
sayfaya sızar).
|
|
143
|
+
sayfaya sızar). Ağacın KÖKÜ tiplidir: `container` → `widget-area`, `modal`/`drawer` → kendi
|
|
144
|
+
tipi (+ düğümde `widgetType`). Runtime widget'ı yalnız bu kökten çizer; düz `container` kökle
|
|
145
|
+
kayıt 200 döner ama boş çizilir. Kök vermezsen gateway düğümlerini Studio'nun kurduğu köke
|
|
146
|
+
sarar ve `gatewayNormalized`'da CMP-002 ile bildirir (`component_update` şemada da aynı).
|
|
92
147
|
2. **Sayfaya koyma:** `add_component` düğümünde `kind:'widget'` ve **`type` = widget KAYDININ
|
|
93
148
|
ID'si** — slug DEĞİL (runtime widget'ı `widget.id === node.type` ile çözer; slug yazarsan
|
|
94
149
|
kayıt 200 döner, render sessizce boş kalır — gateway **PAGE-012/LAY-005** ile reddeder).
|
|
@@ -102,15 +157,30 @@ Widget, kendi komponent ağacını taşıyan yeniden kullanılabilir pakettir (`
|
|
|
102
157
|
micro-op'ları `PATCH /components/{app}/{id}/schema`'ya yazar; `component_update` ise slug alan
|
|
103
158
|
tam gövde PUT'tur. Widget'ın düzey olayı yoktur, `remove_event` yalnız komponent hedefler.
|
|
104
159
|
|
|
160
|
+
## Satır başına çizilen çocuklar ve `item`
|
|
161
|
+
|
|
162
|
+
İki komponent çocuklarını VERİ SATIRI başına çizer; çocukların kod bağlamalarında o satır `item`'dır
|
|
163
|
+
(`{{ item.title }}`):
|
|
164
|
+
|
|
165
|
+
| Host | Hangi çocuklar | `item` |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `repeater` | Bütün çocukları, `rows`'un her satırında | Satır; `item.x = …` satıra geri YAZAR |
|
|
168
|
+
| `datatable` | Yalnız `datatable-cell` çocukları: her biri `column` prop'undaki kolonun hücresine, her satırda | Satır; SALT OKUNUR |
|
|
169
|
+
|
|
170
|
+
`datatable`'ın kendisi `isDroppable` DEĞİLDİR: çocuğu yalnız `datatable-cell` olabilir
|
|
171
|
+
(`props.column = <columns[].name>`), asıl içerik onun içine konur. Şablonu olan kolonda kolonun
|
|
172
|
+
`type`/format ayarı çizilmez; sıralama, filtre ve dışa aktarma ham değerle çalışır. Hangi türün host
|
|
173
|
+
olduğu tek kayıttadır: `zeyrek-frontend/packages/ng-apps-ui/src/shared/render/row-scope.ts`.
|
|
174
|
+
|
|
105
175
|
## `states` ve `appearance` sözlükleri
|
|
106
176
|
|
|
107
177
|
Her şema düğümünde iki sözlük vardır; ikisi de ortak render katmanında çözülür:
|
|
108
178
|
|
|
109
179
|
| `states` | Anlamı |
|
|
110
180
|
|---|---|
|
|
111
|
-
| `isDroppable` | İçine komponent alır (container/form/repeater true) |
|
|
181
|
+
| `isDroppable` | İçine komponent alır (container/form/repeater true). **Değer kataloğun kararıdır** (`component_list` `droppable` sütunu): Studio kanvası bırakma hedefini bu alandan çözer, bu yüzden gateway yazdığı düğümlerde alanı katalogdan doldurur ve `gatewayNormalized` ile bildirir (PAGE-040). `false` yazılmış bir kabın içine kanvasta bırakma yapılamaz — bilerek kapatmak için `resize_component`/`set_states` |
|
|
112
182
|
| `isScrollable` | İçeriği kendi alanında kaydırır (sabit yükseklikte `overflow-y: auto`) |
|
|
113
|
-
| `isWrapper` | Sayfanın/layout'un/widget'ın ANA kabı — salt düzen elemanı: `height:100%` + **`min-height:80vh`**, kap başlığı ÇİZİLMEZ. **Yalnız sayfa boyu kaplaması gereken tek kap için kullan:** iç içe kutuya verirsen 720px'lik pencerede o kutu 36px içerikle bile 576px çizilir (ölçüldü, `platform_guide('page')` Kural 1f). Çerçeve/başlık gizlemek için wrapper
|
|
183
|
+
| `isWrapper` | Sayfanın/layout'un/widget'ın ANA kabı — salt düzen elemanı: `height:100%` + **`min-height:80vh`**, kap başlığı ÇİZİLMEZ. **Yalnız sayfa boyu kaplaması gereken tek kap için kullan:** iç içe kutuya verirsen 720px'lik pencerede o kutu 36px içerikle bile 576px çizilir (ölçüldü, `platform_guide('page')` Kural 1f). Çerçeve/başlık gizlemek için wrapper kullanma: çerçevesiz kutu `box`'tır; `container`'da çerçeve `surfaceStyle`'ın dört `border*` yönüne `'none'` yazılarak kapatılır (`platform_guide('page')` §Kap seçimi). Kurulmuş bir düğümün bayrağını `resize_component` micro-op'unun `states` alanı değiştirir — düğümü yeniden kurmak gerekmez |
|
|
114
184
|
| `isSticky` | Kaydırmada yerinde kalır (header/sidebar; z-index'i otomatik) |
|
|
115
185
|
| `isFloating` | Düğümü akıştan çıkarıp yüzdürür (katman davranışı; nadir) |
|
|
116
186
|
| `isQuickStack` | Studio'nun Quick Stack iskelet hücresi işareti — editörde kesikli çerçeve çizer, **runtime'da hiçbir etkisi yoktur**. MCP'den iskelet kurarken yazmak serbesttir ama gerekmez |
|
|
@@ -189,6 +259,23 @@ ve `layout` grubundaki adlar giremez. **MCP tarafında karşılığı yoktur:**
|
|
|
189
259
|
bir prop'tur, `set_prop` ile aynı şekilde yazılır. Bu bilgi yalnız "studio'da neden o
|
|
190
260
|
düğmeler var" sorusuna cevaptır.
|
|
191
261
|
|
|
262
|
+
## Bağlanabilir prop'lar (`connectData`)
|
|
263
|
+
|
|
264
|
+
`component_get` yanıtındaki `connectData` bileşenin hangi prop'unun veri kaynağına bağlanabileceğini
|
|
265
|
+
söyler; alan yoksa bileşen bağlanamaz (`connectDataNote`). Kaynak platform kataloğudur.
|
|
266
|
+
|
|
267
|
+
| Alan | Anlamı |
|
|
268
|
+
|---|---|
|
|
269
|
+
| `primary` | Birincil bağlanabilir prop (`rows`, `options`); Studio "Veriye bağla" düğmesi bunu açar |
|
|
270
|
+
| `trigger` | "Veriye bağla" düğmesinin yeri: `toolbar` (bileşen araç çubuğu) · `canvas` (kanvastaki bileşenin üstü) |
|
|
271
|
+
| `props.<yol>.roles` | Rol → tür (`any` · `string` · `number` · `boolean` · `date` · `parent`); dropdown `{ label, value }`, grafik `{ category, value }` |
|
|
272
|
+
| `props.<yol>.required` | Doldurulmadan bağlanamayan roller |
|
|
273
|
+
| `props.<yol>.fields` | Rol → bileşenin alan ADI prop'u (grafik `category → categoryField`, kanban `title → titleField`); bağlama o prop'lara seçilen alanın slug'ını yazar. Kaydında `fields` olmayan bileşen (dropdown) satırı rol adlarıyla okur |
|
|
274
|
+
| `props.<yol>.fieldsFrom` | Satırların alanlarını tanımlayan liste prop'u (`datatable.rows → columns`); rol yerine kolon listesi üretilir |
|
|
275
|
+
|
|
276
|
+
Yol joker olabilir: `series[].data` kaydı `series.1.data` prop'unu kapsar. Bağlamanın kendisi, tanım
|
|
277
|
+
şekli ve kurallar: `platform_guide('page')` §Kural 1c-3.
|
|
278
|
+
|
|
192
279
|
## Komponent seçimi
|
|
193
280
|
|
|
194
281
|
"Hangi işe hangi komponent" tablosu ve `table` / `datatable` karşılaştırması:
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Karar Rehberi — DMN karar tabloları
|
|
2
|
+
|
|
3
|
+
Eşik, seviye, oran, uygunluk gibi **kuralları süreç tanımından ayırır**: iş birimi tabloyu değiştirir, süreç
|
|
4
|
+
yeniden yayınlanmaz. Karar bir DMN 1.3 karar tablosu (`kind: table`) ya da tek bir FEEL ifadesidir
|
|
5
|
+
(`kind: literal`). Süreçte `decision` düğümüyle çağrılır; tek başına `decision_preview` ile değerlendirilir.
|
|
6
|
+
Karar **workflow değildir** (yan etkisi yoktur, veri okumaz — girdileri çağıran verir) ve **süreç değildir**
|
|
7
|
+
(beklemez).
|
|
8
|
+
|
|
9
|
+
## Başlangıç
|
|
10
|
+
|
|
11
|
+
1. **Tabloyu yazın** — `decision_create { decision }`. Taslak sürüm oluşur. Gateway yazmadan önce DMN-001 ve
|
|
12
|
+
DMN-002 denetimini çalıştırır (§Lint).
|
|
13
|
+
2. **Deneyin** — `decision_preview { id, inputs }`. Her sınır değerini ayrı deneyin (§Deneme).
|
|
14
|
+
3. **Yayınlayın** — `decision_publish { id }`. Motor yalnız aktif sürümü kullanır; production'a yayın yoktur
|
|
15
|
+
(BPM-001).
|
|
16
|
+
4. **Süreçte kullanın** — `decision` düğümü (§Süreçte kullanım); tanımı `process_definition_preview` ile doğrulayın
|
|
17
|
+
(bilinmeyen `decisionSlug` → `DecisionUnknown`).
|
|
18
|
+
|
|
19
|
+
Düzeltmede tam modeli yeniden göndermeyin: `decision_get` → `decision_patch` (`/rules[id=<kural>]/…`).
|
|
20
|
+
Başka modelleyiciden (Camunda Modeler, Trisotech) gelen tablo için `decision_dmn_update { filePath }`.
|
|
21
|
+
|
|
22
|
+
## Karar modeli
|
|
23
|
+
|
|
24
|
+
```jsonc
|
|
25
|
+
{
|
|
26
|
+
"slug": "siparis-onay-limitleri", // tekil; yayından sonra değişmez
|
|
27
|
+
"name": { "tr": "Sipariş onay limitleri" },
|
|
28
|
+
"variable": "siparisOnayLimitleri", // üst kararların gördüğü ad; yoksa slug'daki '-' → '_'
|
|
29
|
+
"kind": "table", // table | literal
|
|
30
|
+
"hitPolicy": "unique", // §İsabet politikaları
|
|
31
|
+
"aggregation": null, // collect + tek çıktı: sum | min | max | count
|
|
32
|
+
"requires": [], // DRD: önce değerlendirilecek alt kararlar (slug)
|
|
33
|
+
"inputData": [], // { name, typeRef, source: "authority-limits", category }
|
|
34
|
+
"inputs": [
|
|
35
|
+
{ "id": "tutar", "label": "Tutar", "expression": "tutar", "typeRef": "number" },
|
|
36
|
+
{ "id": "kategori", "label": "Kategori", "expression": "kategori", "typeRef": "string", "allowedValues": "\"makine\", \"sarf\"" }
|
|
37
|
+
],
|
|
38
|
+
"outputs": [
|
|
39
|
+
{ "id": "seviye", "name": "seviye", "typeRef": "number", "allowedValues": "3, 2, 1", "defaultOutputEntry": "1" }
|
|
40
|
+
],
|
|
41
|
+
"rules": [
|
|
42
|
+
{ "id": "kucuk", "description": "10 binin altı", "inputEntries": ["< 10000", "-"], "outputEntries": ["1"] },
|
|
43
|
+
{ "id": "orta", "inputEntries": ["[10000..100000)", "-"], "outputEntries": ["2"] },
|
|
44
|
+
{ "id": "buyuk", "inputEntries": [">= 100000", "-"], "outputEntries": ["3"] }
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `inputEntries[i]` `inputs[i]`'nin **tekli testidir**, `outputEntries[j]` `outputs[j]`'nin **FEEL ifadesidir**.
|
|
50
|
+
Sütun sayısı eşleşmezse 422 `DecisionInvalid` (yol `/rules/{i}/inputEntries`).
|
|
51
|
+
- `inputs[].expression` girdinin bağlamdaki adıdır ya da ifadesidir (`siparis.tutar`, `tutar * 1.2`).
|
|
52
|
+
- Metin değerler FEEL'de **çift tırnaklıdır**: `"makine"`. Tırnaksız `makine` bir değişken adıdır ve `null` olur.
|
|
53
|
+
- `typeRef`: `number`, `string`, `boolean`, `date`, `time`, `dateTime`, `dayTimeDuration`,
|
|
54
|
+
`yearMonthDuration`, `list`, `context`. Dönüştürme yalnız metin girdiye uygulanır (`"2026-09-17"` → tarih).
|
|
55
|
+
- Literal karar: `{ "kind": "literal", "literalExpression": "tutar * oran", "typeRef": "number" }`.
|
|
56
|
+
|
|
57
|
+
## İsabet politikaları
|
|
58
|
+
|
|
59
|
+
| Politika | Ne döner | Ne zaman |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `unique` | En çok bir kural; ikisi eşleşirse 422 `DecisionHitPolicyViolated` | Kurallar kesin ayrık (varsayılan) |
|
|
62
|
+
| `any` | Eşleşenlerin çıktıları aynı olmalı, yoksa 422 | Aynı sonucu farklı yollardan veren kurallar |
|
|
63
|
+
| `first` | Kural sırasındaki ilk eşleşme | "Özel durum önce, genel en sonda" |
|
|
64
|
+
| `priority` | Çıktının `allowedValues` sırasına göre en yüksek (ilk yazılan) | Birden çok eşleşmede en katısı kazanır |
|
|
65
|
+
| `collect` | Eşleşenlerin listesi; `aggregation` ile tek sayı | Puanlama, kontrol listesi |
|
|
66
|
+
| `rule-order` | Eşleşenler kural sırasıyla | Sıralı öneriler |
|
|
67
|
+
| `output-order` | Eşleşenler `priority` sırasıyla | Önceliğe göre sıralı liste |
|
|
68
|
+
|
|
69
|
+
Tek çıktılı tabloda karar değeri çıktının kendisidir; çok çıktılıda `{ çıktıAdı: değer }`. Çok isabetli
|
|
70
|
+
politikada değer listedir. Hiç kural eşleşmezse `defaultOutputEntry` olan çıktılar varsayılanı alır, yoksa `null`
|
|
71
|
+
— `null` sonucu süreçte gateway koşulunu sessizce yanlış dala gönderebilir; ya varsayılan verin ya da son kurala
|
|
72
|
+
joker (`-`) koyup `first` kullanın.
|
|
73
|
+
|
|
74
|
+
## FEEL
|
|
75
|
+
|
|
76
|
+
**Tekli testler** (`inputEntries`):
|
|
77
|
+
|
|
78
|
+
| Yazım | Anlamı |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `-` ya da boş | her şey |
|
|
81
|
+
| `< 100` · `>= 5` | karşılaştırma |
|
|
82
|
+
| `[10..20)` · `]1..5]` | aralık; `[` `]` dahil, `(` `)` ya da ters köşe hariç |
|
|
83
|
+
| `"makine"` · `3` · `null` · `esik` | eşitlik (değer ya da bağlamdaki ad) |
|
|
84
|
+
| `"makine", "sarf"` | virgül = VEYA |
|
|
85
|
+
| `not("makine", "sarf")` | hiçbiri |
|
|
86
|
+
| `? > esik * 2` | `?` girdinin kendisi; ifade mantıksal döner |
|
|
87
|
+
|
|
88
|
+
**İfadeler** (`outputEntries`, `expression`, `literalExpression`): `+ - * / **`; `= != < <= > >=`;
|
|
89
|
+
`and`/`or` üç değerli (`true and null` → `null`); `x between 1 and 5`; `x in [1..5]`;
|
|
90
|
+
`if … then … else …`; `for x in liste return x * 2`; `some x in liste satisfies x > 3`; liste filtresi
|
|
91
|
+
`kalemler[tutar > 100]`, indeks `liste[1]` (1'den başlar), `liste[-1]` (son); yol `siparis.musteri.ad`; bağlam
|
|
92
|
+
`{ ad: "x", tutar: 5 }`; zamansal değişmez `@"2026-09-17"`, `@"P3D"`.
|
|
93
|
+
|
|
94
|
+
**Yerleşik işlevler** (tam liste; başkası DMN-002):
|
|
95
|
+
`date`, `time`, `date and time`, `duration`, `years and months duration`, `string length`, `substring`,
|
|
96
|
+
`substring before`, `substring after`, `upper case`, `lower case`, `contains`, `starts with`, `ends with`,
|
|
97
|
+
`matches`, `replace`, `string`, `number`, `not`, `list contains`, `count`, `sum`, `product`, `min`, `max`, `mean`,
|
|
98
|
+
`all`, `any`, `append`, `concatenate`, `flatten`, `reverse`, `distinct values`, `index of`, `get value`, `abs`,
|
|
99
|
+
`floor`, `ceiling`, `decimal` (yarıdan çifte yuvarlar), `modulo`, `sqrt`, `odd`, `even`.
|
|
100
|
+
|
|
101
|
+
Özellikler: tarihte `year month day weekday`, zamanda `hour minute second`, sürede `days hours minutes seconds`
|
|
102
|
+
ve `years months`, aralıkta `start end`.
|
|
103
|
+
|
|
104
|
+
**Yok:** `round up/down/half`, `sort`, `now()`/`today()` (bugünü girdi olarak verin), işlev tanımı, adlı
|
|
105
|
+
argüman, `instance of`, BKM çağrısı, saat dilimli zaman. Sözdizimi hatası 422 `ExpressionInvalid`; tür uyuşmazlığı,
|
|
106
|
+
sıfıra bölme ve tanımsız ad hata değil `null`'dır.
|
|
107
|
+
|
|
108
|
+
## DRD ve girdi verisi
|
|
109
|
+
|
|
110
|
+
`requires: ["risk-skoru"]` alt kararı önce değerlendirir ve sonucunu `variable` adıyla (yoksa `risk_skoru`)
|
|
111
|
+
bağlama ekler; üst tablonun sütunu `{ "expression": "risk_skoru" }` olur. Döngü yayında 422 `DecisionInvalid`;
|
|
112
|
+
alt kararın aktif sürümü yoksa 422 `DecisionUnknown`. Silme: süreç başvuruyorsa 422 `ReferencedByProcess`,
|
|
113
|
+
başka karar `requires` ile başvuruyorsa 422 `DecisionInvalid`.
|
|
114
|
+
|
|
115
|
+
**Yetki limitleri:** `inputData: [{ "name": "limitler", "typeRef": "list", "source": "authority-limits",
|
|
116
|
+
"category": "makine" }]` — girdi verilmezse `process_authority_limit_list` satırları
|
|
117
|
+
`[{ subjectKind, subjectId, category, limit, currency }]` listesi olarak yüklenir. Tabloda
|
|
118
|
+
`count(limitler[limit >= tutar])` gibi kullanılır.
|
|
119
|
+
|
|
120
|
+
## Süreçte kullanım
|
|
121
|
+
|
|
122
|
+
```jsonc
|
|
123
|
+
{ "id": "limit", "type": "decision", "description": "Onay seviyesini belirler",
|
|
124
|
+
"decisionSlug": "siparis-onay-limitleri",
|
|
125
|
+
"binding": "latest", // latest | deployed | "v:2" (sabit sürüm)
|
|
126
|
+
"input": { "tutar": "vars.tutar", "kategori": "row.kategori" }, // Jint; yoksa vars + row
|
|
127
|
+
"output": "vars.onay" } // yoksa her çıktı vars'a kendi adıyla
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Sonraki gateway'de `vars.onay.seviye >= 2` (çok çıktılı) ya da `vars.onay >= 2` (tek çıktılı). Değerlendirme
|
|
131
|
+
hatası örneği `faulted` yapar; `process_instance_get { view: 'timeline' }` → `decision-evaluated`
|
|
132
|
+
`{ decisionSlug, version, inputs, matchedRules, outputs }`. Tanım yayını karar yayınını beklemez ama motor
|
|
133
|
+
aktif sürüm ister: önce kararı yayınlayın.
|
|
134
|
+
|
|
135
|
+
## Deneme
|
|
136
|
+
|
|
137
|
+
`decision_preview { id, inputs, version? }` yan etkisizdir; `version` yoksa taslak (yoksa aktif), alt kararlar da
|
|
138
|
+
taslak/son modelle çalışır. Yanıt `{ value, outputs, matchedRules, decisions[] }` — `decisions[]` DRD'deki her
|
|
139
|
+
kararın girdisini ve eşleşen kuralını gösterir.
|
|
140
|
+
|
|
141
|
+
Her kuralı en az bir kez tetikleyin ve **sınırları** ayrı deneyin: `[10000..100000)` için 9999, 10000, 99999,
|
|
142
|
+
100000. Aralık uçlarındaki `[`/`)` hatası en sık kusurdur; DMN-001 bunu yakalamaz (§Lint).
|
|
143
|
+
|
|
144
|
+
## DMN XML
|
|
145
|
+
|
|
146
|
+
- `decision_dmn_get { id, outPath? }` kararı ve alt kararlarını DMN 1.3 XML'e yazar; çok dilli ad, `kind`,
|
|
147
|
+
`variable`, `inputData` kaynağı `zeyrek:` uzantısıyla (`https://zeyrek.dev/dmn`) gidiş-dönüş kayıpsızdır.
|
|
148
|
+
- `decision_dmn_update { xml | filePath }` DMN 1.3/1.2/1.1 içe aktarır: `decision id` → slug (küçük harf),
|
|
149
|
+
var olan slug yeni taslak alır, yoksa oluşturulur; bir karar geçersizse hiçbiri yazılmaz. Kutulu bağlam/ilişki,
|
|
150
|
+
BKM ve DMNDI desteklenmez. İçe aktardıktan sonra `decision_preview` — başka motorun FEEL işlevleri (ör.
|
|
151
|
+
Camunda `round up`) içe aktarmada 422 ile reddedilir.
|
|
152
|
+
- Ortamlar arası taşıma: kararlar deployment/merge zincirinde **yoktur**; dışa aktarıp hedef dalda içe aktarın.
|
|
153
|
+
|
|
154
|
+
## Lint
|
|
155
|
+
|
|
156
|
+
| Kural | Ne | Şiddet |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| DMN-001 | `unique` tabloda iki kural her girdi sütununda aynı testi ya da `-` taşıyor → aynı girdi ikisini eşler | block (istek gitmez) |
|
|
159
|
+
| DMN-002 | FEEL alt kümesinde olmayan işlev çağrısı | warn (istek gider; backend yazımı 422 ile reddeder) |
|
|
160
|
+
|
|
161
|
+
DMN-001 temkinlidir: yalnız **kesin** çakışmayı yakalar. `< 20` ile `< 10` ya da `[1..5]` ile `[5..9]` kesişir ama
|
|
162
|
+
yakalanmaz — `decision_preview` ile sınır değeri deneyin. Bilinçli istisna `policyOverride: true`.
|
|
163
|
+
|
|
164
|
+
## Hata sözlüğü
|
|
165
|
+
|
|
166
|
+
| Kod | Anlamı | Ne yapılır |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| 422 `DecisionHitPolicyViolated` | unique/any tabloda çakışan kurallar (yanıtta kural kimlikleri) | Kuralları ayırın ya da politikayı değiştirin |
|
|
169
|
+
| 422 `ExpressionInvalid` | FEEL sözdizimi ya da bilinmeyen işlev (yol `/rules/{i}/…`) | §FEEL listesine bakın |
|
|
170
|
+
| 422 `DecisionInvalid` | Model hatası (sütun sayısı, politika, döngü) | Yoldaki alanı düzeltin |
|
|
171
|
+
| 422 `DecisionUnknown` | `requires` ya da süreç `decisionSlug`'ı aktif kararı bulamadı | Alt kararı yayınlayın |
|
|
172
|
+
| 422 `ReferencedByProcess` | Silinmek istenen karara süreç başvuruyor | Önce süreci değiştirin |
|
|
173
|
+
|
|
174
|
+
## Sık tuzaklar
|
|
175
|
+
|
|
176
|
+
- **Tırnaksız metin:** `inputEntries: ["makine"]` değil `["\"makine\""]`. Tırnaksız ad bağlamda aranır, `null` olur ve
|
|
177
|
+
kural hiç eşleşmez.
|
|
178
|
+
- **Sayı metin geliyor:** satırdaki `"180000"` metni `number` sütunda karşılaştırılamaz; `typeRef: "number"` verin ya da
|
|
179
|
+
düğüm girdisinde `Number(row.tutar)`.
|
|
180
|
+
- **Boşluk bırakan aralıklar:** `< 10000` ve `(10000..100000)` → tam 10000 hiçbir kurala düşmez.
|
|
181
|
+
- **`null` sonuç:** eşleşme yoksa varsayılan yoksa `null` döner; süreçte koşul `vars.onay.seviye >= 2` `false`
|
|
182
|
+
olur, hata vermez.
|
|
183
|
+
- **Bugünün tarihi:** FEEL'de `today()` yok; süreç düğümü girdisinde `{ "bugun": "new Date().toISOString().slice(0, 10)" }`.
|
|
184
|
+
- **Taslakla çalıştığını sanmak:** `decision_preview` taslağı, süreç motoru aktif sürümü kullanır — yayınlamayı unutmak
|
|
185
|
+
"önizlemede doğruydu, süreçte eski sonuç" demektir.
|
|
@@ -15,7 +15,9 @@ uzayındadır. Çakışan slug `Migration failed … relation "X" already exists
|
|
|
15
15
|
kaydı hiç oluşmaz**. Rezerve adlardan bilinenler: `branches`, `applications`, `caches`,
|
|
16
16
|
`components`, `datasources`, `entities`, `fields`, `files`, `flows`, `folders`, `layouts`,
|
|
17
17
|
`microservices`, `pages`, `permissions`, `projects`, `queries`, `queued_events`, `roles`,
|
|
18
|
-
`steps`, `users`, `variables`, `views`, `workflows
|
|
18
|
+
`steps`, `users`, `variables`, `views`, `workflows` — ve rol yönetim şemasının tabloları:
|
|
19
|
+
`organization_units`, `organization_positions`, `user_positions`, `access_policies`, `access_grants`
|
|
20
|
+
(tam liste gateway'in rezerve ad kontrolündedir). Alan adı bunlardan biriyse eş anlamlısını
|
|
19
21
|
seç (ör. şube/branş için `branches` değil `specialties`).
|
|
20
22
|
|
|
21
23
|
> **Ama `users`/`roles`/`files`/`folders` bir istisna:** bunlar "dolu olduğu için kaçınılacak"
|
|
@@ -24,7 +26,7 @@ seç (ör. şube/branş için `branches` değil `specialties`).
|
|
|
24
26
|
|
|
25
27
|
## Hazır entity'ler — kimlik tablosu ZATEN VAR
|
|
26
28
|
|
|
27
|
-
Her projeye seed sırasında
|
|
29
|
+
Her projeye seed sırasında hazır entity'ler açılır ve **id'leri her kurulumda aynı sabitlerdir**
|
|
28
30
|
(`Defaults` sınıfı) — aramana gerek yok, doğrudan `entity_get` ile çekebilirsin:
|
|
29
31
|
|
|
30
32
|
| slug | id | Ne için |
|
|
@@ -35,12 +37,33 @@ Her projeye seed sırasında 9 entity açılır ve **id'leri her kurulumda aynı
|
|
|
35
37
|
| `permissions` · `role_permissions` | `01917ede-a457-…` · `01917ede-d450-…` | yetki matrisi |
|
|
36
38
|
| `files` · `folders` | `0191dbf2-39c4-…` · `0191df94-f635-…` | Drive; `FILE` alanları buraya bağlanır (`entity_list`'te GİZLİ) |
|
|
37
39
|
| `audit_trails` · `audit_trail_values` | `01961f53-25c3-…` · `01961f53-3552-…` | denetim izi |
|
|
40
|
+
| `organization_units` · `organization_unit_closure` | `01a0a05e-1c9a-7022-a0c7-6b8320756a4c` · `01a0a05e-1ca3-7b6a-9f1b-7f1633f7f05a` | **Organizasyon ağacı** (yalnız okunur, aşağıda): birimler — `parent_id` · `unit_type` (holding/company/branch/region/department/team/other) · `function_code` · `name` · `code` · `manager_position_id` · `origin` · `is_active` — ve ata/torun kapanışı |
|
|
41
|
+
| `organization_positions` · `organization_position_closure` | `01a0a05e-1ca3-700f-95c6-18fe1e30079c` · `01a0a05e-1ca4-7b73-b90e-4aa7d8eeeeef` | birimdeki koltuklar — `unit_id` · `parent_position_id` (idari hat) · `functional_parent_position_id` (işlevsel hat) · `role_id` · `name` · `code`; kapanışta `line_type` |
|
|
42
|
+
| `user_positions` | `01a0a05e-1ca4-7841-b6b3-45c5892d5501` | kullanıcı ↔ pozisyon — `user_id` · `position_id` · `is_primary` · `assignment_type` · `starts_at` · `ends_at` |
|
|
38
43
|
|
|
39
44
|
**`users` gerçek bir entity'dir**, sahte bir sistem tablosu değil: `entity_get` alanlarını verir,
|
|
40
45
|
`RELATION` alanı hedef alabilir, table step / microservice okur, `row_create` yazar, kendi default
|
|
41
46
|
DTO'su vardır. Auth middleware tarifi zaten bunu okur — `ngapps://examples/middleware-authenticate`
|
|
42
47
|
`entityId` olarak `users`'ı kullanır.
|
|
43
48
|
|
|
49
|
+
### Organizasyon ağacı tabloları — okunur, genel yolla YAZILMAZ (ORG-001 · ORG-002)
|
|
50
|
+
|
|
51
|
+
Beş organizasyon tablosu **her projede vardır**; basit projede boştur, kompleks projede
|
|
52
|
+
(`project_create` `accessModel: 'complex'`) organizasyonun rol yönetim şemasının kopyasını taşır.
|
|
53
|
+
|
|
54
|
+
- **Yazma kapalı (ORG-001, block).** `row_create` / `row_update` / `row_delete`, table kaynaklı uç
|
|
55
|
+
ve table step bu tablolara platformda `400 SystemEntityWriteNotAllowed` alır; gateway isteği hiç
|
|
56
|
+
göndermez. Ağaç organizasyon şemasından **senkronla** gelir (yönetim konsolunda yayın → abone
|
|
57
|
+
projenin her ortamı); projeye özel birim/pozisyon ve kullanıcı ataması Studio › Organizasyon
|
|
58
|
+
ekranındadır — MCP'de bu yazma yolu bilinçli olarak yoktur: projede yapı değişikliği aboneliği
|
|
59
|
+
kapatır (`receiveUpdates = false`) ve dal ortamında 409 döner.
|
|
60
|
+
- **Kompleks proje yayınlı son şemayla doğar (ORG-002).** Organizasyonda yayın yoksa tablolar boş
|
|
61
|
+
kalır; önce `organization_schema_get` ile `publishedVersion`'a bak. Abonelik ve özelleştirme
|
|
62
|
+
durumu `project_get` → `organizationSchema`.
|
|
63
|
+
- **Okuma serbest:** `row_list('organization_units')`, pozisyonlar için `row_list('organization_positions')`.
|
|
64
|
+
Alt ağaç sorusu (bir birimin bütün torunları) kapanış tablosundan `ancestor_id` filtresiyle
|
|
65
|
+
okunur; `depth` 0 düğümün kendisidir.
|
|
66
|
+
|
|
44
67
|
### Neden gözden kaçıyor
|
|
45
68
|
|
|
46
69
|
`entity_list`'i **`applicationId` ile** çağırdığında hazır entity'ler listede **görünmez**: seed
|
|
@@ -94,6 +117,12 @@ yapıyorsan devam et).
|
|
|
94
117
|
uygulamanın rol açması/düzenlemesi gerekiyorsa yol her domain tablosuyla aynıdır: entity + kendi
|
|
95
118
|
microservice ucun + sayfa. `role_list` yalnız okur.
|
|
96
119
|
|
|
120
|
+
> **Kompleks projede roller organizasyon şemasından gelir** (`roles.origin = 'organization'`;
|
|
121
|
+
> `role_list` bu alanı döndürmez, `row_list('roles')` okur). Şemadan gelen rol MCP'den yazılmaz,
|
|
122
|
+
> yönetim konsolunda düzenlenir; yetki `page.roleIds` ile değil erişim politikasıyla verilir.
|
|
123
|
+
> Aşağıdaki reçete basit proje içindir — kompleks projede kendi rolünü açan uç yine uyarı alır
|
|
124
|
+
> (ROL-002 warn), dikey çözümün açtığı rol projeye özgü kalır.
|
|
125
|
+
|
|
97
126
|
`roles` entity'sinin açtığı alanlar — fiziksel tabloda ayrıca `template_*` kolonları var, hepsi
|
|
98
127
|
nullable, gateway'den görünmez:
|
|
99
128
|
|
|
@@ -134,6 +163,15 @@ Rol açma reçetesi:
|
|
|
134
163
|
`permissions` / `role_permissions` **Studio'nun yetki matrisidir**, uygulama sayfasının yetkisi
|
|
135
164
|
değil; uygulama tarafında yetkiyi `page.roleIds` ve middleware ifadesi kurar.
|
|
136
165
|
|
|
166
|
+
## Veri koruma — maskeli, şifreli ve türetilmiş alan
|
|
167
|
+
|
|
168
|
+
TCKN, telefon gibi alanlar `fields[].protection` ile maskeli ve/veya şifreli saklanır; telefonun
|
|
169
|
+
operatör kodu gibi sorgulanabilir parça `derivedFromFieldId` + `derivationRule` ile türetilmiş alan
|
|
170
|
+
olur. Koruma yalnız düz metin alana konur (display, birincil anahtar, ilişki, çok dilli değil —
|
|
171
|
+
PROT-003), korumalı alanda metin araması ve sıralama yoktur (PROT-001, PROT-002). Modlar, maske
|
|
172
|
+
türleri, dolu kolonda geçiş ve hatalar: `platform_guide('access')` §'Alan koruması'. Satırları bir
|
|
173
|
+
bileşene bağlamak (liste, dropdown, grafik) akış değil `connect_data_bind`: `platform_guide('page')` §Kural 1c-3.
|
|
174
|
+
|
|
137
175
|
## Alan tipleri (dbType + commonType İKİSİ birden verilir)
|
|
138
176
|
|
|
139
177
|
| dbType (BÜYÜK HARF zorunlu) | commonType |
|
|
@@ -159,6 +197,9 @@ değil; uygulama tarafında yetkiyi `page.roleIds` ve middleware ifadesi kurar.
|
|
|
159
197
|
`description`'a yaz: para → `INT8` kuruş (`*_minor`), süre → `INT4` dakika, yüzde →
|
|
160
198
|
`INT4` ×100, puan → `INT4` ×10.
|
|
161
199
|
- `commonType`'sız `UUID`/`BOOL` "isn't a supported database type" hatasıyla reddedilir.
|
|
200
|
+
- Birincil anahtar `properties.generationType` taşımak ZORUNDADIR: `properties` hiç verilmezse create
|
|
201
|
+
`Please select a valid generation type for 'id'` ile düşer (38/U-14). `0` (Always) ve `1` (ByDefault) ikisi de
|
|
202
|
+
geçerlidir — `UUID` anahtarda ikisiyle de satır id'si üretildi (ölçüldü 2026-09-21, 39/05 D-15).
|
|
162
203
|
- **Katalogu okumak gerekiyorsa** (bu datasource'ta hangi `dbType` var, hangisi varsayılan, tip
|
|
163
204
|
hangi seçenekleri kabul ediyor, hangi tipe dönüştürülebilir) `datasource_configuration_options`
|
|
164
205
|
çağır: varsayılan yanıt ~5 KB'lık **özettir**; 816 kayıtlık collation DEĞER listesi yalnız
|
|
@@ -680,12 +721,13 @@ orada `undefined` alır.
|
|
|
680
721
|
> `Sequence contains no **elements**` (satır yok — genelde preview rollback'i) **farklı**
|
|
681
722
|
> sorunlardır; karıştırmak teşhisi saptırır.
|
|
682
723
|
|
|
683
|
-
- **Audit izi ne zaman gerçekten yazılır?** `
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
724
|
+
- **Audit izi ne zaman gerçekten yazılır?** Tek koşul `isAuditTrailActive: true`. Bayrak açık ve
|
|
725
|
+
`auditTrailType` boş gelirse **`simple`** yazılır (TB-101, 2026-09-20 — eskiden bayrak tek başına
|
|
726
|
+
hiçbir şey yazmıyordu, sessiz tuzaktı); okuma yolunda da tipsiz ama açık entity `simple` sayılır.
|
|
727
|
+
Üç tip, aynı satır başlığını yazar, farkları okumada: `simple` yalnız "kim oluşturdu / kim
|
|
728
|
+
güncelledi" meta'sını besler (geçmiş listesi dönmez) · `basic` geçmiş listesini döndürür, değişen
|
|
729
|
+
alanları döndürmez · `detailed` değişen alanları da yazar. Enum yalnız bu üç değeri tanır
|
|
730
|
+
(`AuditTrailType.cs`); `advanced` diye bir değer **yoktur**, gönderirsen bağlama hatası alırsın.
|
|
689
731
|
- **Audit izi IP adresi tutar.** `audit_trails.IpAddress`, isteğin
|
|
690
732
|
`HttpContext.Connection.RemoteIpAddress` değerinden doldurulur (`UserContext.cs`) ve satır
|
|
691
733
|
olaylarıyla (`Row.Created/Updated/Deleted` → `UserIpAddress`) audit consumer'a taşınır; kullanıcı
|