@appaflytech/zeyrek-ai-mcp 0.0.30 → 0.0.32
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 +0 -15
- package/README.md +5 -5
- package/dist/config.js +0 -37
- package/dist/index.js +0 -2
- package/dist/knowledge/backendConstraints.js +1 -18
- package/dist/knowledge/boxSections.js +184 -0
- package/dist/knowledge/componentCatalog.js +232 -562
- package/dist/knowledge/componentEvents.js +21 -141
- package/dist/knowledge/layoutSummary.js +2 -140
- package/dist/knowledge/normalize.js +67 -236
- package/dist/knowledge/outlines.js +0 -36
- package/dist/knowledge/policy.js +4 -18
- package/dist/knowledge/reservedTables.js +0 -79
- package/dist/knowledge/rules.js +21 -319
- package/dist/knowledge/schemaGuard.js +0 -11
- package/dist/knowledge/styleResolve.js +38 -55
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +3 -6
- package/dist/platform/diagnostics.js +4 -10
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/errors.js +10 -162
- package/dist/platform/http.js +8 -29
- package/dist/platform/responses.js +5 -39
- package/dist/platform/{capture/capture.js → screenshot.js} +519 -105
- package/dist/platform/secrets.js +1 -17
- package/dist/platform/strictArguments.js +12 -68
- package/dist/platform/tokenVault.js +4 -187
- package/dist/resources/examples/layout-app-shell.json +707 -229
- package/dist/resources/examples/page-detail-profile.json +1 -2
- package/dist/resources/examples/page-dynamic-form.json +2 -3
- 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 +2 -8
- package/dist/resources/guides/component.md +4 -91
- package/dist/resources/guides/entity.md +8 -50
- package/dist/resources/guides/expressions.md +5 -14
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/getting-started.md +1 -38
- package/dist/resources/guides/layout.md +58 -55
- package/dist/resources/guides/microservice.md +2 -81
- package/dist/resources/guides/middleware.md +2 -44
- package/dist/resources/guides/page.md +75 -454
- package/dist/resources/guides/theme.md +2 -8
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +1 -58
- package/dist/resources/rules.js +5 -11
- package/dist/resources/schema-fingerprint.json +5 -7
- package/dist/resources/schemas/CreateEntityCommand.json +0 -118
- package/dist/resources/schemas/CreateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/CreateQueryCommand.json +0 -4
- package/dist/resources/schemas/CreateWorkflowCommand.json +1 -143
- package/dist/resources/schemas/DataJobDto.json +1 -6
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +1 -21
- package/dist/resources/schemas/MicroserviceDto.json +3 -15
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +1 -10
- package/dist/resources/schemas/PreviewWorkflowCommand.json +1 -22
- package/dist/resources/schemas/StepDto.json +1 -22
- package/dist/resources/schemas/UpdateEntityCommand.json +0 -118
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/UpdateQueryCommand.json +0 -4
- package/dist/resources/schemas/UpdateViewCommand.json +2 -0
- package/dist/resources/schemas/UpdateWorkflowCommand.json +1 -143
- package/dist/server.js +1 -27
- package/dist/tools/access.js +2 -369
- package/dist/tools/applications.js +3 -60
- package/dist/tools/common.js +0 -7
- package/dist/tools/components.js +14 -118
- package/dist/tools/datasources.js +3 -3
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +2 -2
- package/dist/tools/designSchemaPatch.js +18 -34
- package/dist/tools/dtos.js +5 -36
- package/dist/tools/entities.js +12 -79
- package/dist/tools/externalComponents.js +5 -26
- package/dist/tools/flows.js +14 -122
- package/dist/tools/folders.js +1 -1
- package/dist/tools/imports.js +2 -5
- package/dist/tools/layouts.js +17 -50
- package/dist/tools/merges.js +1 -1
- package/dist/tools/microservices.js +25 -77
- package/dist/tools/pages.js +112 -465
- package/dist/tools/platformInfo.js +8 -27
- package/dist/tools/projects.js +9 -71
- package/dist/tools/rows.js +13 -69
- package/dist/tools/schemaOps.js +1 -61
- package/dist/tools/screenWrite.js +8 -37
- package/dist/tools/screens.js +5 -95
- package/dist/tools/templates.js +1 -26
- package/dist/tools/translations.js +1 -1
- package/dist/tools/variables.js +5 -11
- package/dist/tools/workflows.js +5 -10
- package/package.json +2 -2
- package/dist/knowledge/access.js +0 -802
- package/dist/knowledge/case.js +0 -41
- package/dist/knowledge/connectDataBind.js +0 -819
- package/dist/knowledge/connectDataDefinition.js +0 -341
- package/dist/knowledge/connectDataExecute.js +0 -93
- package/dist/knowledge/connectDataRules.js +0 -128
- package/dist/knowledge/decision.js +0 -121
- package/dist/knowledge/expressionPrelude.js +0 -59
- package/dist/knowledge/microserviceParameters.js +0 -58
- package/dist/knowledge/mining.js +0 -94
- package/dist/knowledge/mobileComponentCatalog.js +0 -859
- package/dist/knowledge/mobileComponentEvents.js +0 -239
- package/dist/knowledge/platform/lint.js +0 -385
- package/dist/knowledge/platform/mobile.js +0 -142
- package/dist/knowledge/platform/mobileLayoutLint.js +0 -324
- package/dist/knowledge/platform/mobileRules.js +0 -231
- package/dist/knowledge/platform/mobileSpacing.js +0 -82
- package/dist/knowledge/platform/mobileTabs.js +0 -108
- package/dist/knowledge/platform/nativeBoxModel.js +0 -44
- package/dist/knowledge/platform/profile.js +0 -25
- package/dist/knowledge/platform/resolve.js +0 -122
- package/dist/knowledge/platform/web.js +0 -39
- package/dist/knowledge/process.js +0 -510
- package/dist/knowledge/rowFilter.js +0 -43
- package/dist/knowledge/styleResolveNative.js +0 -527
- package/dist/platform/argumentAliases.js +0 -128
- package/dist/platform/bodyFile.js +0 -103
- package/dist/platform/capture/actions.js +0 -333
- package/dist/platform/capture/browser.js +0 -1
- package/dist/platform/capture/console-log.js +0 -122
- package/dist/platform/capture/index.js +0 -11
- package/dist/platform/capture/readiness.js +0 -103
- package/dist/platform/capture/summary.js +0 -77
- package/dist/platform/capture/target.js +0 -5
- package/dist/platform/capture/targets/studio-mobile.js +0 -15
- package/dist/platform/capture/targets/studio-web.js +0 -5
- package/dist/platform/impersonation.js +0 -45
- package/dist/platform/jsonArray.js +0 -24
- package/dist/platform/schemaReadMemory.js +0 -60
- package/dist/resources/examples/bpm-gorev-kontrol.json +0 -294
- package/dist/resources/examples/bpm-iso-dokuman.json +0 -228
- package/dist/resources/examples/bpm-satinalma.json +0 -376
- package/dist/resources/examples/connect-data-convert-verify.json +0 -107
- package/dist/resources/examples/connect-data-dropdown-roles.json +0 -66
- package/dist/resources/examples/connect-data-edit-m2m.json +0 -73
- package/dist/resources/examples/connect-data-query-params.json +0 -50
- package/dist/resources/examples/connect-data-table-entity.json +0 -147
- package/dist/resources/examples/connect-data-workflow-microservice.json +0 -65
- package/dist/resources/examples/mobile-app-shell-drawer.json +0 -243
- package/dist/resources/examples/mobile-app-shell-stack.json +0 -157
- package/dist/resources/examples/mobile-app-shell-tab.json +0 -208
- package/dist/resources/examples/mobile-form-screen.json +0 -365
- package/dist/resources/examples/mobile-list-detail-form.json +0 -672
- package/dist/resources/guides/access.md +0 -796
- package/dist/resources/guides/bpm.md +0 -686
- package/dist/resources/guides/case.md +0 -153
- package/dist/resources/guides/decision.md +0 -185
- package/dist/resources/guides/mobile-layout.md +0 -193
- package/dist/resources/guides/mobile.md +0 -495
- package/dist/resources/read.js +0 -41
- package/dist/resources/schemas/AccessExplanationDto.json +0 -144
- package/dist/resources/schemas/AccessMatrixDto.json +0 -170
- package/dist/resources/schemas/AccessPermissionDto.json +0 -57
- package/dist/resources/schemas/AccessPolicyDto.json +0 -223
- package/dist/resources/schemas/AccessResourceDto.json +0 -86
- package/dist/resources/schemas/AppSessionDto.json +0 -53
- package/dist/resources/schemas/ConnectDataDescribeDto.json +0 -344
- package/dist/resources/schemas/ConnectDataRequestModel.json +0 -202
- package/dist/resources/schemas/ConnectDataResultDto.json +0 -421
- package/dist/resources/schemas/ConnectorCredentialDto.json +0 -70
- package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +0 -37
- package/dist/resources/schemas/CreateAccessPolicyCommand.json +0 -209
- package/dist/resources/schemas/CreateDecisionCommand.json +0 -221
- package/dist/resources/schemas/CreateProcessDefinitionCommand.json +0 -1337
- package/dist/resources/schemas/DecisionDto.json +0 -302
- package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +0 -28
- package/dist/resources/schemas/ExplainAccessQuery.json +0 -33
- package/dist/resources/schemas/GenerateProcessDocumentCommand.json +0 -116
- package/dist/resources/schemas/OrganizationProjectDto.json +0 -335
- package/dist/resources/schemas/OrganizationSchemaDto.json +0 -196
- package/dist/resources/schemas/OrganizationSchemaVersionDto.json +0 -207
- package/dist/resources/schemas/PatchProcessDefinitionCommand.json +0 -76
- package/dist/resources/schemas/ProcessDefinitionDto.json +0 -1480
- package/dist/resources/schemas/ProcessSimulationDto.json +0 -96
- package/dist/resources/schemas/SaveConnectorCredentialCommand.json +0 -90
- package/dist/resources/schemas/SaveProcessEventSourceCommand.json +0 -61
- package/dist/resources/schemas/SaveProcessMailSourceCommand.json +0 -89
- package/dist/resources/schemas/SignProcessTaskCommand.json +0 -73
- package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +0 -92
- package/dist/resources/schemas/UpdateAccessPolicyCommand.json +0 -209
- package/dist/resources/schemas/UpdateDecisionCommand.json +0 -216
- package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +0 -1357
- package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +0 -1339
- package/dist/tools/accessOperations.js +0 -135
- package/dist/tools/accessPolicies.js +0 -170
- package/dist/tools/accessRuntime.js +0 -203
- package/dist/tools/bpm.js +0 -343
- package/dist/tools/bpmGovernance.js +0 -266
- package/dist/tools/bpmOperations.js +0 -230
- package/dist/tools/bpmReporting.js +0 -154
- package/dist/tools/bpmRouting.js +0 -150
- package/dist/tools/bpmRuntime.js +0 -396
- package/dist/tools/case.js +0 -178
- package/dist/tools/caseRuntime.js +0 -89
- package/dist/tools/connectData.js +0 -449
- package/dist/tools/connectors.js +0 -193
- package/dist/tools/decisions.js +0 -206
- package/dist/tools/mobile.js +0 -221
- package/dist/tools/modules.js +0 -48
- package/dist/tools/organizationStructure.js +0 -137
- package/dist/tools/profileWrite.js +0 -92
|
@@ -1,796 +0,0 @@
|
|
|
1
|
-
# Erişim Rehberi — organizasyon şeması, erişim politikası, alan koruması
|
|
2
|
-
|
|
3
|
-
Kompleks projenin (`project_create` `accessModel: 'complex'`) yetki modeli: kim hangi kaydı görür,
|
|
4
|
-
hangi eylemi yapar, hangi alanı maskeli ya da açık görür. Basit projede izin kataloğu boştur ve
|
|
5
|
-
policy yazılmaz; alan koruması ise iki türde de kullanılır.
|
|
6
|
-
|
|
7
|
-
Araçlar: `organization_schema_get` · `access_permission_list` · `access_resource_list` ·
|
|
8
|
-
`access_policy_list` · `access_policy_get` · `access_policy_create` · `access_policy_update` ·
|
|
9
|
-
`access_policy_delete` · `entity_protection_update` · `access_preview` · `access_session_create`.
|
|
10
|
-
Gateway kuralları: ORG-001…003, ACC-001…010, PROT-001…004 — her biri aşağıda ilgili başlıkta.
|
|
11
|
-
|
|
12
|
-
## Kavramlar
|
|
13
|
-
|
|
14
|
-
| Terim | Ne | Nerede okunur |
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| Birim | Organizasyon ağacının düğümü; tür holding · company · branch · region · department · team · other; `function_code` birimin işlevi (it, hr, finance…) | `row_list('organization_units')` |
|
|
17
|
-
| Pozisyon | Birimdeki koltuk; idari üst `parent_position_id`, işlevsel üst `functional_parent_position_id`; her pozisyonun bir rolü var; `is_multi_seat` (varsayılan false: aynı anda tek kalıcı kişi) | `organization_positions` |
|
|
18
|
-
| Rol | Benzersiz unvan (Satış Müdürü); kompleks projede organizasyon şemasından gelir | `roles` |
|
|
19
|
-
| Kullanıcı ataması | Kim hangi koltukta oturuyor; dönemli, `is_primary`, vekâlet için `assignment_type`; tek koltuklu pozisyonda çakışan ikinci kalıcı atama 409 `OrganizationPositionSeatOccupied`, vekâlet (`acting`) sınıra girmez | `user_positions` |
|
|
20
|
-
| Kaynak | Yetkinin bağlandığı şey: entity, alan, microservice, sayfa, workflow… — katalogdaki anahtar | `access_resource_list` |
|
|
21
|
-
| İzin | `<tip>.<eylem>`: `entity.read`, `field.read`, `microservice.execute`… | `access_permission_list` |
|
|
22
|
-
| Grant | İzin × kaynak × etki (allow/deny) + opsiyonel kapsam, koşul, alan erişimi | politika gövdesi |
|
|
23
|
-
| Politika | Grant'ler + atamalar paketi | `access_policy_list` |
|
|
24
|
-
| Atama | Politikayı özneye bağlar: rol · pozisyon · birim · kullanıcı | politika gövdesi |
|
|
25
|
-
| Özne | İsteği yapan uygulama kullanıcısı: id'si, pozisyonları, birimleri, şirketleri, rol slug'ları, işlev kodları | runtime |
|
|
26
|
-
|
|
27
|
-
## Organizasyon ağacı
|
|
28
|
-
|
|
29
|
-
Organizasyonun tek bir rol yönetim şeması vardır; yönetim konsolunda düzenlenir ve yayınlanır
|
|
30
|
-
(`organization_schema_get` taslağı, `version` ile bir yayını gösterir). Kompleks proje açılınca
|
|
31
|
-
yayınlı son sürümün **kopyası** projenin her ortamına yazılır (ORG-002); yayın yoksa tablolar boştur.
|
|
32
|
-
|
|
33
|
-
- **Abonelik:** `project_get` → `organizationSchema`. Yeni yayın abone projeye senkronla gelir.
|
|
34
|
-
Projede yapı değişikliği (birim ekle/sil/taşı, pozisyon ya da organizasyondan gelen rol) aboneliği
|
|
35
|
-
kapatır; `customizedAt` görünür ve sonraki sürümler gelmez. Kişi atamaları aboneliği etkilemez.
|
|
36
|
-
- **Okuma:** `row_list` ile hazır entity'ler. Alt ağaç kapanış tablolarındadır:
|
|
37
|
-
`organization_unit_closure` (`ancestor_id` → `descendant_id`, `depth` 0 düğümün kendisi),
|
|
38
|
-
`organization_position_closure` (ayrıca `line_type`: administrative · functional).
|
|
39
|
-
- **Yazma yok (ORG-001, block).** Organizasyon ve erişim tablolarına `row_create` / `row_update` /
|
|
40
|
-
`row_delete`, table kaynaklı uç ve table step `400 SystemEntityWriteNotAllowed` alır; gateway
|
|
41
|
-
isteği göndermez. Projeye özel birim/pozisyon ve kullanıcı ataması Studio › Organizasyon
|
|
42
|
-
ekranındadır; dal ortamında yapı yazımı zaten 409'dur.
|
|
43
|
-
- **Birim yöneticisi** bir kişi değil pozisyondur (`manager_position_id`). **Matris organizasyon:**
|
|
44
|
-
destek departmanı (IT) idari olarak şirkete, işlevsel olarak holding direktörüne bağlanır — ikinci
|
|
45
|
-
hat pozisyondaki işlevsel üsttür, birim ağacı tek ebeveynli kalır.
|
|
46
|
-
|
|
47
|
-
## İzin kataloğu
|
|
48
|
-
|
|
49
|
-
Katalog yalnız kompleks projede tohumlanır; `access_permission_list` boş dönüyorsa proje basittir.
|
|
50
|
-
|
|
51
|
-
| Tip | İzinler | Kapsam alır | Alan erişimi alır |
|
|
52
|
-
|---|---|---|---|
|
|
53
|
-
| entity | read · create · update · delete · export · import · reveal · reassign · audit | read · update · delete · export · reveal · reassign | — |
|
|
54
|
-
| field | read · write · filter | — | yalnız `field.read` |
|
|
55
|
-
| row | read · update · delete · export · reveal | — | — |
|
|
56
|
-
| çalıştırma | `microservice.execute` · `page.view` · `workflow.execute` · `ui-flow.run` · `function.execute` · `microfunction.execute` | — | — |
|
|
57
|
-
| veri | `query.execute` · `query.unrestricted` · `view.read` | — | — |
|
|
58
|
-
| dosya | `file.read` · `file.upload` · `file.delete` · `folder.read` · `folder.upload` · `folder.delete` | — | — |
|
|
59
|
-
| organizasyon | `organization-unit.read` · `organization-unit.manage` · `organization-unit.assign` | — | — |
|
|
60
|
-
| sistem | `system.access.manage` · `system.access.explain` | — | — |
|
|
61
|
-
| süreç | `process.start` · `process.manage` · `process.view-all` (anahtar `process:<tanımId>`) | yalnız `view-all` | — |
|
|
62
|
-
| görev | `task.complete` · `task.reassign` (süreç kaynağına bağlanır) | — | — |
|
|
63
|
-
|
|
64
|
-
Otomasyon katalogda **yoktur** ve ona grant yazılmaz: satır yazımı otomasyonu yazanın yetkisinden
|
|
65
|
-
bağımsız tetikler; adımların hangi kimlikle koştuğunu otomasyonun `runAs`'ı seçer
|
|
66
|
-
(`platform_guide('workflow')` §Kompleks projede özne ve runAs).
|
|
67
|
-
|
|
68
|
-
## Kaynak anahtarı
|
|
69
|
-
|
|
70
|
-
Grant kaynağa id ile değil **anahtarla** bağlanır; anahtar yeniden kurma, deployment ve dal boyunca
|
|
71
|
-
kararlıdır.
|
|
72
|
-
|
|
73
|
-
- Biçim: `entity:<entityId>` · `field:<entityId>:<fieldId>` · diğer tiplerde `<tip>:<id>`. Anahtar
|
|
74
|
-
verilmeyen grant iznin tipinin **tamamına** uygulanır.
|
|
75
|
-
- Anahtar iznin tipiyle başlar: `entity.read` → `entity:…`, `field.read` → `field:…` (ACC-001).
|
|
76
|
-
- `access_resource_list { type, search, parentId }` — `key` alanı anahtardır. `parentId` bir
|
|
77
|
-
**katalog** id'sidir (listedeki `id`), entity id değil: bir entity'nin alanları için önce entity
|
|
78
|
-
satırını bul, onun `id`'siyle çağır.
|
|
79
|
-
- Katalogda türetilmiş alanlar vardır (`isDerived`), korumalı alanlar işaretlidir (`isProtected`);
|
|
80
|
-
gizli sistem alanları (sahiplik alanları dahil) **yoktur**.
|
|
81
|
-
- Kaynak silinince grant kalır ve `orphaned: true` görünür. Güncelleme var olan yetim anahtara
|
|
82
|
-
toleranslıdır; **yeni** gelen bilinmeyen anahtar `400 AccessResourceUnknown`.
|
|
83
|
-
|
|
84
|
-
## Kapsam
|
|
85
|
-
|
|
86
|
-
Kapsam satırın **sahiplik alanlarına** göre SQL'de süzülür (`sys_owner_user_id`, `sys_owner_unit_id`).
|
|
87
|
-
|
|
88
|
-
| scope | Satır görünür, eğer |
|
|
89
|
-
|---|---|
|
|
90
|
-
| `own` | sahip kullanıcı öznenin kendisi |
|
|
91
|
-
| `unit` | sahip birim öznenin birimlerinden biri |
|
|
92
|
-
| `unit-tree` | sahip birim öznenin birimi ya da onun alt birimi |
|
|
93
|
-
| `subordinates` | sahip kullanıcı, öznenin pozisyonlarının altındaki bir pozisyonda şu an oturuyor; hat `subordinatesLine`: `administrative` (varsayılan) · `functional` · `both` |
|
|
94
|
-
| `function` | sahip birimin işlev kodu öznenin birimlerinin işlev kodlarından biri (IT direktörü üç şirketin IT kayıtlarını görür) |
|
|
95
|
-
| `company` | sahip birim öznenin şirketinin altında |
|
|
96
|
-
| `all` | tümü |
|
|
97
|
-
|
|
98
|
-
- Öznenin birimi ya da pozisyonu yoksa ilgili kapsam **hiçbir satır** döndürmez.
|
|
99
|
-
- Kapsamlı grant entity'de sahiplik alanı ister (ACC-003, warn — platform 400
|
|
100
|
-
`AccessScopeRequiresOwnerFields`). Kompleks projede yeni entity iki alanı kendiliğinden alır; eski
|
|
101
|
-
entity için `POST /{proje}/DataJobs/owner-fields/{datasourceId}` işi kolonları ekler.
|
|
102
|
-
- Var olan satırların sahibi geri doldurulmaz: sahipsiz satırı yalnız `all` kapsamı görür. Yeni
|
|
103
|
-
satırda sahip yazma yolunda dolar; gövdede gönderilen değer yok sayılır.
|
|
104
|
-
|
|
105
|
-
## Grant kuralları (ACC-001 · ACC-002 · ACC-003)
|
|
106
|
-
|
|
107
|
-
Gateway politika gövdesini istek göndermeden denetler (ACC-001 block, ACC-002 block, ACC-003 warn):
|
|
108
|
-
|
|
109
|
-
- **Etki zorunlu.** Allow'lar toplanır, **kapsamsız deny kazanır**. Deny kapsam (ve kapsamla
|
|
110
|
-
birlikte koşul) taşıyabilir: kapsamlı deny eylemi kesmez, yalnız kapsamındaki satırları süzer —
|
|
111
|
-
`rowScope` metninde `except` olarak görünür. **İstisna koşulsuz `scope: 'all'`:** koşulsuz `all`
|
|
112
|
-
daraltıcı bir kapsam değildir, "bütün satırlar hariç" demektir; böyle bir deny **kapsamsız sayılır
|
|
113
|
-
ve eylemi keser** (`explicit-deny`, izde `outcome: applied` — TB-132). `scope: 'all'` + koşul ise
|
|
114
|
-
yalnız koşula uyan satırları dışlar (`all except condition(…)`). Kapsam **atamanın öznesine** göre çözülür: birim
|
|
115
|
-
atamasında o birim, pozisyon atamasında pozisyonun birimi, rol/kullanıcı atamasında öznenin
|
|
116
|
-
birimleri. Deny alan erişimi taşımaz (`AccessDenyFieldAccessNotSupported`).
|
|
117
|
-
- **Kapsam** yalnız altı entity izninde ve `process.view-all`'da (tablo yukarıda); `subordinatesLine` yalnız
|
|
118
|
-
`scope: 'subordinates'` ile.
|
|
119
|
-
- **Alan erişimi** yalnız `field.read`'te: `hidden` · `masked` · `plain`. Birden çok allow'da en
|
|
120
|
-
genişi kazanır (`plain` > `masked` > `hidden`); korumalı alanın varsayılanı maskelidir.
|
|
121
|
-
**`masked` ancak korumalı alanda maskeler:** maske alanın depolama korumasından gelir. Korumasız alana
|
|
122
|
-
`fieldAccess: 'masked'` verilirse değer DÜZ döner (ölçüldü 38/M-3) — önce `entity_protection_update`
|
|
123
|
-
ile alanı koruyun ya da `hidden` verin. Gateway bunu `access_policy_create/update`'te uyarır (ACC-017).
|
|
124
|
-
- **Bir alanı kapatmanın iki yolu aynı şey değildir.** Kapsamsız `deny` ile `allow + hidden`
|
|
125
|
-
okumada farklı davranır, yazmada aynı davranır — ikinci bir rol eklendiğinde fark ortaya çıkar
|
|
126
|
-
(ölçüldü 2026-09-20, S2-16):
|
|
127
|
-
|
|
128
|
-
| Yazım | Tek başına | Kullanıcıya `plain` veren ikinci bir rol de eklendiğinde |
|
|
129
|
-
|---|---|---|
|
|
130
|
-
| kapsamsız `deny` | alan satırda yok | **yine yok** — kapsamsız deny her allow'u ezer |
|
|
131
|
-
| `allow` + `fieldAccess: hidden` | alan satırda yok | **görünür olur** — `plain` `hidden`'ı yener |
|
|
132
|
-
|
|
133
|
-
"Bu rol bunu asla görmesin" istiyorsanız `deny`; "bu rolün varsayılanı kapalı olsun ama başka bir
|
|
134
|
-
rol açabilsin" istiyorsanız `hidden`. İkisi de alanı **yazılamaz** yapar.
|
|
135
|
-
- **Koşul** kapsama AND ile eklenir; kapsamsız koşul yazılmaz — saf koşul için `scope: 'all'`.
|
|
136
|
-
Koşul yalnız anahtarlı grant'te çalışır ve alanları **o entity'nin katalogdaki korumasız
|
|
137
|
-
alanlarıdır** (gizli ve sistem alanı yok).
|
|
138
|
-
- **Koşulda korumalı alan yok (ACC-002).** Ana kolonda maske durur; sorgulanabilir parça
|
|
139
|
-
türetilmiş alanla kurulur.
|
|
140
|
-
- Aynı izin + anahtar + etki bir politikada tek grant'tir.
|
|
141
|
-
|
|
142
|
-
Koşul düğümü: `{ all: [...] }`, `{ any: [...] }` ya da `{ field, op, value }`; derinlik ≤ 5, düğüm ≤ 50.
|
|
143
|
-
|
|
144
|
-
| Değer | İşleçler |
|
|
145
|
-
|---|---|
|
|
146
|
-
| sabit (`'onaylı'`, `100`) | `eq` · `neq` · `lt` · `lte` · `gt` · `gte` |
|
|
147
|
-
| dizi (`['a','b']`) | `in` · `notin` |
|
|
148
|
-
| `{ subject: 'userId' }` | `eq` · `neq` |
|
|
149
|
-
| `{ subject: 'unitIds' \| 'positionIds' \| 'companyIds' \| 'roleSlugs' \| 'functionCodes' }` | `in` · `notin` |
|
|
150
|
-
| `{ now: true }` | `eq` · `neq` · `lt` · `lte` · `gt` · `gte` |
|
|
151
|
-
| yok | `isnull` · `isnotnull` |
|
|
152
|
-
|
|
153
|
-
**Koşul dili alanlar arası hesap yapmaz.** Sağ taraf ya sabit ya `{ subject }` ya `{ now }`;
|
|
154
|
-
`alanA + alanB <= 100` yazılamaz. Limit türetilmiş bir büyüklüğe bakacaksa (ör. "etkili iskonto =
|
|
155
|
-
nominal iskonto + aksesuar + takas farkı") o büyüklüğü **entity'de hesaplanan bir alan** olarak
|
|
156
|
-
tutup koşulu ona kurun — yoksa kullanıcı nominal alanı limitin altında bırakıp gerçekte limiti
|
|
157
|
-
aşabilir (ölçüldü 2026-09-20, S2-13: nominal %2,5 görünen teklif gerçekte %6,98 idi ve limiti %3
|
|
158
|
-
olan kişi onayladı).
|
|
159
|
-
|
|
160
|
-
Hesaplanan alanı kurmanın iki yolu vardır ve ikisi de koşul dilinden ÖNCE gelir:
|
|
161
|
-
|
|
162
|
-
| Kaynak | Nasıl | Ne zaman |
|
|
163
|
-
|---|---|---|
|
|
164
|
-
| Aynı satırın başka bir alanından **türetiliyor** | `fields[].derivedFromFieldId` + `derivationRule` (§Türetilmiş sorgu alanı) | Değer tek bir alanın dilimi/deseni ise |
|
|
165
|
-
| Birkaç alandan **hesaplanıyor** (toplam, yüzde, fark) | Kalıcı bir alan açın ve satır yazımında doldurun: yazan ucun `fields[]` listesine `source: 'expression'` ile ekleyin ya da entity'ye `automation` bağlayın | Değer aritmetik ise — koşul o alana kurulur |
|
|
166
|
-
|
|
167
|
-
Kural: **limiti gerçekten belirleyen sayı satırda bir kolon olarak durmalıdır.** Koşul yalnız
|
|
168
|
-
kolon okur; ekranda hesaplanan bir toplam politika için yok hükmündedir.
|
|
169
|
-
|
|
170
|
-
```jsonc
|
|
171
|
-
// "Birimi ve alt birimleri — yalnız onaylı olanlar"
|
|
172
|
-
{ "permission": "entity.read", "resourceKey": "entity:<musteriler id>", "effect": "allow",
|
|
173
|
-
"scope": "unit-tree", "condition": { "field": "durum", "op": "eq", "value": "onaylı" } }
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Atama
|
|
177
|
-
|
|
178
|
-
- `subjectType`: `role` · `position` · `unit` · `user`; `subjectId` ilgili tablonun satır id'si
|
|
179
|
-
(`row_list('roles')`, `organization_positions`, `organization_units`, `users`).
|
|
180
|
-
- `includeDescendants` yalnız birimde (alt birimlerdekiler de politikayı alır).
|
|
181
|
-
- `startsAt` verilmezse şimdi; `endsAt` sonra olmalı. Aynı özne bir politikada bir kez atanır.
|
|
182
|
-
- `overridesDeny: true` yalnız `subjectType: 'user'` ve **dolu** `endsAt` ile yazılır
|
|
183
|
-
(`AccessOverrideRequiresUserWithEndDate`); atama bütün deny'leri aşar — kapsamlısını da
|
|
184
|
-
kapsamsızını da. Yazmak `access.override.manage` iznini ister (var olan bir istisnanın süresini
|
|
185
|
-
uzatmak ya da öznesini — `subjectId`/`subjectType` — değiştirmek de yazmaktır); izinsiz istek
|
|
186
|
-
403 `AccessOverridePermissionRequiredException` döner ve hiçbir şey yazılmaz.
|
|
187
|
-
**İstisna taşıyan politikanın grant'lerine dokunmak da aynı izni ister** — ekleme, silme ve
|
|
188
|
-
değiştirme, `access_policy_update` ve `access_matrix_save` yollarının ikisinde de: istisna o
|
|
189
|
-
grant kümesi kadar yasak aşar, küme değişince istisnanın sınırı da değişir. Ölçüt istisnanın
|
|
190
|
-
**süresinin dolmamış** olmasıdır (`endsAt` gelecekte), şu an yürürlükte olması değil: `startsAt`'i
|
|
191
|
-
ileri tarihli, henüz başlamamış bir istisna da izin ister. Grant listesini **id'siz** göndermek
|
|
192
|
-
kümenin tamamını değiştirmek sayılır — aynı grant'leri id'siz yeniden göndermek de izin ister,
|
|
193
|
-
o yüzden `access_policy_get`'ten gelen `id`'leri koru. İzin istemeyenler: istisnayı kapatmak,
|
|
194
|
-
süresini kısaltmak, atamayı silmek. `access_preview` kararı
|
|
195
|
-
`allowed-by-override`, ezilen deny izleri `outcome: 'overridden'` olur.
|
|
196
|
-
- **Atamasız politika hiç kimseye uygulanmaz.**
|
|
197
|
-
- **Yeni kompleks proje yetkili bir özneyle doğar.** Sistem politikası `system-admin` iki atama
|
|
198
|
-
taşır: Super Admin **rolü** ve projeyi açan **kullanıcı** (`subjectType: 'user'`). İkincisi
|
|
199
|
-
2026-09-22'de eklendi, çünkü S-15'ten sonra kurucunun Super Admin rolü kompleks projede özneye
|
|
200
|
-
hiç girmiyor ve koltuğu olmadığı için proje yetkili bir öznesiz doğuyordu. Aynı atama basit →
|
|
201
|
-
kompleks dönüşümünde de yazılır. Bu, "yetki koltuktan gelir" ilkesinin iz bırakan istisnasıdır:
|
|
202
|
-
gerçek yönetici koltuğu kurulduğunda `access_policy_update` ile **silinmesi beklenir**.
|
|
203
|
-
|
|
204
|
-
## Hiyerarşi yetki vermez
|
|
205
|
-
|
|
206
|
-
Ağaçta üstte olmak ya da bir birimin yönetici koltuğunda oturmak **tek başına hiçbir kaydı açmaz**.
|
|
207
|
-
Yetki yalnız grant ve atamadan gelir:
|
|
208
|
-
|
|
209
|
-
- "Müdür ekibinin kayıtlarını görür" → müdür pozisyonuna (ya da rolüne) `entity.read` +
|
|
210
|
-
`subordinates` ya da `unit-tree`.
|
|
211
|
-
- "Bölge müdürü okur ama güncelleyemez" → `entity.read` allow `unit-tree` + `entity.update` **deny**.
|
|
212
|
-
- "Herkes kendi kaydını düzenler" → `entity.update` allow `own`, bir role ya da en üst birime
|
|
213
|
-
`includeDescendants` ile.
|
|
214
|
-
|
|
215
|
-
## Politika araçları
|
|
216
|
-
|
|
217
|
-
- **Veri bağlama (Connect Data) politikayı her istekte uygular:** `connect_data_describe` alan başına
|
|
218
|
-
efektif `access` ve izinli `operators`'ı döner; gizli alan yanıtta ve kolonda yoktur, korumalı alanda
|
|
219
|
-
yalnız `eq` · `neq` · `in` · `notin` çalışır (CD-002). `asUserId` ile başka kullanıcının gözüyle okunur.
|
|
220
|
-
|
|
221
|
-
- `access_policy_create` — ad, slug (projede tekil), grant'ler, atamalar tek gövdede.
|
|
222
|
-
- `access_policy_update` — platform ucu **tam değiştirmedir**. Gateway kaydı önce okur: verilmeyen
|
|
223
|
-
alan taşınır ve bu `gatewayNormalized` ile söylenir. `grants` / `assignments` verilirse **tam
|
|
224
|
-
listedir**: listede olmayan silinir; var olanı değiştirmek için `id`'sini koru.
|
|
225
|
-
- `access_policy_delete` — grant ve atamalarıyla birlikte.
|
|
226
|
-
- `access_matrix_get` / `access_matrix_save` — Studio'nun yetki matrisinin okuma ve yazma yüzü.
|
|
227
|
-
Matris tek bir kaynak tipini tablolar (satır = kaynak, sütun = izin, hücre = o politikadaki grant).
|
|
228
|
-
`access_policy_update`'ten farkı: grant listesinin tamamı değil **yalnız değişen hücreler** gider
|
|
229
|
-
(`changes` yazar/günceller, `removedGrantIds` siler). Atamalara dokunmaz.
|
|
230
|
-
- `access_resource_rebuild` — kaynak kataloğunu projenin güncel tanımlarından yeniden üretir; yeni
|
|
231
|
-
entity/alan/uç katalogda yoksa ya da `orphaned: true` satırlar kaldıysa bunu düzeltir.
|
|
232
|
-
- **Tasarım eseridir:** development'ta ya da dalda yazılır, production'a deployment taşır, merge'de
|
|
233
|
-
izlenir. Dikey çözümün production'da değiştirdiği politika `origin: 'runtime'` olur ve deployment
|
|
234
|
-
ona dokunmaz.
|
|
235
|
-
- `origin`: `system` · `project` · `runtime` · `module`.
|
|
236
|
-
|
|
237
|
-
## Örnek: CZA Holding — Müşteriler
|
|
238
|
-
|
|
239
|
-
`musteriler` entity'si: `ad` (display), `tckn` (maskeli+şifreli, son 4), `telefon` (maskeli),
|
|
240
|
-
`telefon_operator` (telefondan türetilmiş), sahiplik alanları. Id'ler `access_resource_list` ve
|
|
241
|
-
`row_list` ile okunur.
|
|
242
|
-
|
|
243
|
-
```jsonc
|
|
244
|
-
// 1) Satış personeli — yalnız kendi kayıtları, TCKN maskeli (varsayılan)
|
|
245
|
-
{ "name": "Satış personeli", "slug": "satis-personeli",
|
|
246
|
-
"grants": [
|
|
247
|
-
{ "permission": "entity.read", "resourceKey": "entity:<musteriler>", "effect": "allow", "scope": "own" },
|
|
248
|
-
{ "permission": "entity.update", "resourceKey": "entity:<musteriler>", "effect": "allow", "scope": "own" } ],
|
|
249
|
-
"assignments": [ { "subjectType": "role", "subjectId": "<satis-personeli rol id>" } ] }
|
|
250
|
-
|
|
251
|
-
// 2) İstanbul Müdürü — departmanlarının kayıtları, TCKN açık, tek hücre açma (reveal)
|
|
252
|
-
{ "name": "İstanbul müdürü", "slug": "istanbul-muduru",
|
|
253
|
-
"grants": [
|
|
254
|
-
{ "permission": "entity.read", "resourceKey": "entity:<musteriler>", "effect": "allow", "scope": "unit-tree" },
|
|
255
|
-
{ "permission": "entity.update", "resourceKey": "entity:<musteriler>", "effect": "allow", "scope": "unit-tree" },
|
|
256
|
-
{ "permission": "entity.reveal", "resourceKey": "entity:<musteriler>", "effect": "allow", "scope": "unit-tree" },
|
|
257
|
-
{ "permission": "field.read", "resourceKey": "field:<musteriler>:<tckn>", "effect": "allow", "fieldAccess": "plain" } ],
|
|
258
|
-
"assignments": [ { "subjectType": "position", "subjectId": "<İstanbul Müdürü pozisyon id>" } ] }
|
|
259
|
-
|
|
260
|
-
// 3) Bölge müdürleri — alt ağacı okur, güncelleyemez
|
|
261
|
-
{ "name": "Bölge müdürü", "slug": "bolge-muduru",
|
|
262
|
-
"grants": [
|
|
263
|
-
{ "permission": "entity.read", "resourceKey": "entity:<musteriler>", "effect": "allow", "scope": "unit-tree" },
|
|
264
|
-
{ "permission": "entity.update", "resourceKey": "entity:<musteriler>", "effect": "deny" } ],
|
|
265
|
-
"assignments": [ { "subjectType": "role", "subjectId": "<bolge-muduru rol id>" } ] }
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
CEO için `scope: 'company'`. Kapsam dışı bir kaydın id'siyle okuma/güncelleme runtime'da 404,
|
|
269
|
-
izin yoksa 403 döner.
|
|
270
|
-
|
|
271
|
-
**Tek kayıt ucu.** Kompleks projede `isSingle` uç bulunamayan **ya da** kapsam dışı id için
|
|
272
|
-
`404 NotFoundException` döner — modtan bağımsız, okuma ve yazma aynı. Basit projede aynı uç
|
|
273
|
-
boş gövdeyle `204 No Content` döndürür; iki proje türü arasında bu fark bilinçlidir (TB-97).
|
|
274
|
-
|
|
275
|
-
## Alan koruması
|
|
276
|
-
|
|
277
|
-
Tanım yalnız platformda (entity alanında) yapılır; **kimin** maskeli ya da açık gördüğünü politika
|
|
278
|
-
(`field.read` + `fieldAccess`) belirler.
|
|
279
|
-
|
|
280
|
-
| mode | Ana kolon | Gizli kolonlar | Anahtar |
|
|
281
|
-
|---|---|---|---|
|
|
282
|
-
| `none` | düz değer | — | — |
|
|
283
|
-
| `masked` | maske metni (`*******1234`) | `sys_<alan>_plain` | gerekmez |
|
|
284
|
-
| `encrypted` | boş | `sys_<alan>_enc` · `sys_<alan>_kv` (+ `sys_<alan>_bidx`) | gerekir |
|
|
285
|
-
| `masked-encrypted` | maske metni | `sys_<alan>_enc` · `sys_<alan>_kv` (+ `sys_<alan>_bidx`) | gerekir |
|
|
286
|
-
|
|
287
|
-
- Gizli kolonlar son kullanıcıya ve kataloğa görünmez. Şifreleme AES-256-GCM, tam eşleşme için
|
|
288
|
-
HMAC blind index (`exactSearch: true`); `normalize` (`digits` · `lower` · `trim`) eşleşmeden önce
|
|
289
|
-
uygulanır — TCKN için `digits`.
|
|
290
|
-
- Maske türü (`mask.type`): `last-n` (`visible` > 0) · `first-n` · `first-last` · `email` ·
|
|
291
|
-
`phone` (varsayılan son 2 hane; `mask.char` ayırıcı ya da boşluk olamaz — `+ - ( ) . /`) · `full` ·
|
|
292
|
-
`pattern` (`#` açık karakter) · `first-n-last-n`
|
|
293
|
-
(`visible` baştan, `visibleEnd` sondan, ikisi de > 0 — `{ type: 'first-n-last-n', visible: 3,
|
|
294
|
-
visibleEnd: 2 }`: `10000000146` → `100******46`). `masked` ve `masked-encrypted` modunda maske
|
|
295
|
-
zorunludur. Değer maskenin görünen hanelerinden kısaysa tamamı maskelenir.
|
|
296
|
-
- **Maskeli değer geri yazılırsa yok sayılır — her türde.** Satırı okuyup gövdeyi olduğu gibi geri
|
|
297
|
-
gönderen bir istemci korumalı alanı ezmez: platform gelen değer kendi maskesine eşitse alanı ve
|
|
298
|
-
ondan türetilen alanı değişmemiş sayar (maskeler idempotenttir; 2026-09-23'e kadar `phone` değildi
|
|
299
|
-
ve maskeli telefon gerçek numaranın yerine yazılıyordu — VK-1). `visibleEnd` yalnız
|
|
300
|
-
`first-n-last-n`'de saklanır; başka türe gönderilirse platform onu 0 sayar.
|
|
301
|
-
- **Hangi alan:** yalnız düz metin; display, birincil anahtar, identity, çok dilli ve ilişki alanı
|
|
302
|
-
korunamaz (PROT-003, block). Yalnız şifreli modda ana kolon boş kalır: NOT NULL alan bu modla
|
|
303
|
-
korunursa yazma düşer — alanı nullable yapın.
|
|
304
|
-
- **Yeni alan:** korumayı `entity_create` / `entity_patch` / `entity_update` gövdesinde
|
|
305
|
-
`fields[].protection` ile alır.
|
|
306
|
-
- **Var olan alan:** yalnız `entity_protection_update`. Güncelleme araçları var olan alanın
|
|
307
|
-
korumasını değiştiremez (`400 ProtectionChangeNotAllowed`; `entity_patch` bunu istek göndermeden
|
|
308
|
-
durdurur). Dolu satırlar arka plan işiyle dönüşür: yanıt `jobId`, ilerleme `import_status`. İş
|
|
309
|
-
sürerken aynı entity'ye yazım `409 ProtectionMigrationInProgress`; bu arada işlenmiş satırlar
|
|
310
|
-
maskeli, işlenmemişler düz görünebilir. İş hata verirse **aynı çağrıyı aynı gövdeyle** tekrarlamak
|
|
311
|
-
kaldığı yerden sürdürür.
|
|
312
|
-
- Ortamda anahtar yapılandırılmamışsa şifreli mod `ProtectionKeyUnavailable` ile düşer — anahtar
|
|
313
|
-
kurulumu insan işidir.
|
|
314
|
-
- `row_list` (tasarım ucu) ana kolonu döner: maskeli modlarda maske metni, yalnız şifreli modda boş.
|
|
315
|
-
Düz değer MCP'den okunmaz.
|
|
316
|
-
- **Korumalı alana YAZMAK ayrı bir grant ister.** `entity.create` / `entity.update` izni olan bir
|
|
317
|
-
rol korumalı bir alana değer yazamaz: `403 AccessFieldWriteDenied`. Karar motoru yazma hakkını
|
|
318
|
-
`level != hidden && (field.write ALLOW || (entity.update && alan KORUMASIZ))` diye kuruyor, yani
|
|
319
|
-
korumalı alan için **açık `field.write` grant'i şarttır** — korumasız alanlarda `entity.update`
|
|
320
|
-
yeter. Fikstür yükleyen ilk çağrı çoğunlukla burada düşer (S-14, ölçüldü 2026-09-19:
|
|
321
|
-
`tckn` alanına 20/20 satır 403 aldı, `field.write` verilince 20/20 geçti).
|
|
322
|
-
- **Denetim izi korumalı alanın düz/şifreli kopyasını tutmaz** (2026-09-20'den beri): `sys_<alan>_plain`,
|
|
323
|
-
`_enc`, `_bidx`, `_kv` yardımcı kolonları denetim kaydına hiç girmez; defterde yalnız maskeli değer
|
|
324
|
-
durur. Silme kaydı da öyle — önce silinen satırın tam şifreli metni defterde kalıyordu (S2-4).
|
|
325
|
-
- **Denetim izini açmak iki alandır.** `isAuditTrailActive: true` **tek başına hiçbir şey yazmaz**;
|
|
326
|
-
`auditTrailType` (`simple` | `detailed`) verilmezse kayıt sessizce oluşmaz ve hata da dönmez.
|
|
327
|
-
Geçmişe telafi yok: bayrak açıkken tipi boş geçen dönemde yapılan yazmalar kalıcı olarak izsizdir
|
|
328
|
-
(ölçüldü 2026-09-20, S2-3). Fikstür kurarken ikisini birlikte yazın ve ilk yazmadan sonra
|
|
329
|
-
`entity_audit_trails` ile bir satır görün.
|
|
330
|
-
- Bilinen sınır: template'ten kurulan projede korumalı kolonlar kaynak projenin anahtarıyla gelir ve
|
|
331
|
-
hedefte yeniden şifrelenmez.
|
|
332
|
-
|
|
333
|
-
## Türetilmiş sorgu alanı
|
|
334
|
-
|
|
335
|
-
Korumalı alanın sorgulanabilir parçası ayrı bir **metin** alanda saklanır; platform yazma yolunda
|
|
336
|
-
hesaplar.
|
|
337
|
-
|
|
338
|
-
- `fields[].derivedFromFieldId` + `derivationRule { type, start, length, pattern }` birlikte verilir
|
|
339
|
-
(PROT-004, block); alan kendisinden türetilemez.
|
|
340
|
-
- `slice` — `start` (≥ 0) ve `length` (> 0): telefon `05321234567` → `{ type: 'slice', start: 1, length: 3 }` → `532`.
|
|
341
|
-
- `regex` — `pattern`; ilk yakalama grubu, grup yoksa eşleşmenin tamamı. Platform .NET Regex'le derler.
|
|
342
|
-
- `domain` — e-postanın alan adı, küçük harf.
|
|
343
|
-
- Türetilmiş alan katalogdadır; filtrede ve policy koşulunda kullanılabilir. Kaynak korumalı olsa da
|
|
344
|
-
türetilmiş değer **düz** saklanır — ne açığa çıkardığını seçerken düşün.
|
|
345
|
-
- Değer üç yerde hesaplanır: her satır yazımında, koruma dönüşüm işinde (`entity_protection_update`)
|
|
346
|
-
ve türetilmiş alan eklendiğinde ya da kaynağı/kuralı değiştiğinde. Sonuncusu `entity_update` /
|
|
347
|
-
`entity_patch` kaydından sonra açılan `derived-fill` işidir: var olan satırları kaynaktan (şifreliyse
|
|
348
|
-
çözerek) doldurur, tabloyu kilitlemez (yazım 409 almaz), yanıt iş numarası taşımaz. Bitişi
|
|
349
|
-
`import_history { entityId }` ile izleyin — en yeni satır `kind: 'derived-fill'`, `status: 'completed'`
|
|
350
|
-
olunca değerler yerindedir; o ana kadar yeni kolona filtre 0 satır dönebilir. Kaynak alan o sırada
|
|
351
|
-
dönüşümdeyse doldurma onu atlar; dönüşüm bitince (`protection-*` `completed`) platform aynı tabloya
|
|
352
|
-
bir `derived-fill` işi daha açar ve dönüşümün önceden işlediği satırları da doldurur — değerleri o
|
|
353
|
-
işin bitişinden sonra okuyun. Yalnız ad değişikliği ve silme iş açmaz. Bilinen eksik:
|
|
354
|
-
deployment/merge ya da şablon kurulumuyla hedef ortama gelen türetilmiş alan orada kendiliğinden
|
|
355
|
-
dolmaz (platform bulgusu VK-21).
|
|
356
|
-
|
|
357
|
-
## Arama ve sıralama (PROT-001 · PROT-002)
|
|
358
|
-
|
|
359
|
-
- Korumalı alanda yalnız `eq` · `neq` · `in` · `notin` · `isnull` · `isnotnull`. `contains`,
|
|
360
|
-
`startswith`, `endswith` (ve büyük/küçük harf duyarsız eşleri), `lt`/`gt` karşılaştırmaları
|
|
361
|
-
`400 ProtectionOperatorNotAllowed` (PROT-001, block — `row_list` istek göndermeden durur).
|
|
362
|
-
- Şifreli modda eşitlik yalnız `exactSearch: true` ile çalışır (blind index); yoksa `eq` de reddedilir.
|
|
363
|
-
- Korumalı alana göre sıralama `400 ProtectionSortNotAllowed` (PROT-002, block).
|
|
364
|
-
- Denetim kök entity'nin alanındadır (`tckn` ya da `musteriler.tckn`); ilişki join'i üzerinden
|
|
365
|
-
korumalı alana filtre yazmayın — o yol denetlenmez.
|
|
366
|
-
- Kısmi arama ihtiyacı türetilmiş alanla karşılanır (`telefon_operator eq 532`).
|
|
367
|
-
|
|
368
|
-
## Runtime: uygulama oturumu ve özne
|
|
369
|
-
|
|
370
|
-
Kompleks projede kimliği platform yönetir; uygulamanın kendi kimlik middleware'i gerekmez (ACC-006).
|
|
371
|
-
|
|
372
|
-
| Uç | Ne |
|
|
373
|
-
|---|---|
|
|
374
|
-
| `POST /{proje}/runtime/{app}/auth/sign-in` | `{ email, password }` → erişim jetonu (15 dk) + üç çerez: `ZY_App_{proje}` (HttpOnly), `ZY_AppRefresh_{proje}` (30 gün), `ZY_Csrf_{proje}` |
|
|
375
|
-
| `POST …/auth/refresh` | yenileme çerezi (ya da gövdede `refreshToken`) → yeni jetonlar; eski yenileme jetonu tekrar gelirse bütün aile iptal, 401 |
|
|
376
|
-
| `POST …/auth/sign-out` | çerezleri siler |
|
|
377
|
-
| `GET …/auth/me` | kullanıcı, roller, pozisyonlar, birimler, şirketler |
|
|
378
|
-
| `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) |
|
|
379
|
-
|
|
380
|
-
- Jeton önce çerezden, yoksa `Authorization: Bearer`'dan okunur. Çerezle gelen **durum değiştiren**
|
|
381
|
-
istek `X-ZY-CSRF` başlığında `ZY_Csrf_{proje}` değerini ister (yoksa `403 CsrfTokenMismatch`);
|
|
382
|
-
Bearer'lı istek CSRF istemez. Giriş hız sınırı 5 dk'da 10 deneme (429).
|
|
383
|
-
- Kullanıcı projenin `users` tablosundadır; parola biçimi değişmedi (`Hasher.Hash`).
|
|
384
|
-
- **Özne:** kullanıcı id'si, pozisyonları, birimleri, şirketleri, rol slug'ları, işlev kodları.
|
|
385
|
-
**Kompleks projede rol YALNIZ pozisyondan gelir** (2026-09-21, S-15): `users` ekranından verilen
|
|
386
|
-
doğrudan rol (`user_roles`) özneye girmez ve hiçbir yetki vermez — koltuğu olmayan kullanıcı
|
|
387
|
-
rolsüzdür ve her kapsamlı grant'ten reddedilir. Doğrudan rol birleşimi yalnız **basit** projede
|
|
388
|
-
sürer. Dönüşümden önce kimin yetki kaybedeceğini `access_model_preflight` `usersWithDirectRoles`
|
|
389
|
-
sayar. Workflow
|
|
390
|
-
bağlamında `user` değişkeni **önceden dolar**: `id`, `email`, `roles`, `roles_csv`, `positions`, `units`.
|
|
391
|
-
Salt okunur `subject` nesnesi ve `Can(izin, anahtar)` yardımcısı **henüz yok** — yetkiyi ifadede yeniden
|
|
392
|
-
kurmayın; uç, sayfa, satır ve alan kararı platformdadır.
|
|
393
|
-
- **Anonim uç işareti yok:** kompleks + `enforce` ortamda oturumsuz her microservice ve sayfa isteği
|
|
394
|
-
`401 AppSessionRequired` döner. İstisna, koruması `anonymous` olan system operation'dır
|
|
395
|
-
(`access.session.create`; uç `isAnonymous: true` olmak zorunda).
|
|
396
|
-
- **Sayfa akışı bu uçlara ham `fetch` atmaz (FLOW-028).** Giriş `access.session.create`, kullanıcı
|
|
397
|
-
kartı `access.session.get` system microservice'iyle `microservice` adımından çağrılır: runtime
|
|
398
|
-
`X-Environment`'ı, CSRF'i ve 401'de tek yenilemeyi kendisi yapar, giriş gövdesi jeton taşımaz.
|
|
399
|
-
Yanlış parola `401 AppSignInFailedException` döner (oturum hatası değildir, yenileme tetiklemez).
|
|
400
|
-
|
|
401
|
-
## Zorlama modu
|
|
402
|
-
|
|
403
|
-
| Mod | Ne olur |
|
|
404
|
-
|---|---|
|
|
405
|
-
| `off` | Karar motoru devrede değil; kimlik ve yetki bugünkü gibi middleware'de. **Korumalı alanlar AÇIK döner** (`__protected: { <alan>: 'plain' }`), reveal 403 (açacak bir şey yok) |
|
|
406
|
-
| `shadow` | Karar motoru her istekte çalışır ama **engellemez**; yanıt `off` ile aynıdır (korumalı alanlar açık), ayrıca "reddedilirdi / süzülürdü / maskelenirdi" kaydı karar günlüğüne yazılır |
|
|
407
|
-
| `enforce` | İzin yoksa 403, kapsam dışı kayıt 404, satırlar SQL'de süzülür, alanlar gizli ya da maskeli döner |
|
|
408
|
-
|
|
409
|
-
- Mod **ortam başına** bir ayardır: `project_get` → `environments[].enforcementMode`. Yeni kompleks proje
|
|
410
|
-
`enforce` başlar, dal ortamı üst ortamın modunu alır. Değişiklik runtime'a en geç ~30 sn'de yansır.
|
|
411
|
-
- Eski rol listelerini (`page.roleIds`, `microservice.roles`) platform **hiçbir modda** karar için kullanmaz:
|
|
412
|
-
liste yalnız `triggerSource.roles`'a geçer ve `Authorized(user.roles)` çağıran middleware okur. Uç ve
|
|
413
|
-
sayfa izninin kapısı `shadow`/`enforce`'ta erişim politikasıdır; bağlı middleware'ler ise her modda koşar
|
|
414
|
-
ve reddedebilir (ACC-006).
|
|
415
|
-
|
|
416
|
-
## Zorlama modunu kim değiştirir (ACC-007)
|
|
417
|
-
|
|
418
|
-
Mod değişikliği **ölçülerek** yapılır; MCP'de artık hem ölçen hem yazan araç var:
|
|
419
|
-
|
|
420
|
-
1. `access_decision_log_summary` / `access_decision_log_users` — gölge modun biriktirdiği
|
|
421
|
-
"reddedilirdi" kayıtlarını izin × kaynak ve kullanıcı kırılımında okur; `access_decision_log_list`
|
|
422
|
-
tek tek kayıtları verir. Platform üç karar yazar: `would-deny` (istek reddedilirdi),
|
|
423
|
-
`would-filter` (istek geçerdi, satırlar süzülürdü) ve `would-mask` (alan maskeli ya da gizli
|
|
424
|
-
dönerdi — `permission: 'field.read'`, `resourceKey: 'field:<entityId>:<fieldId>'`,
|
|
425
|
-
`reason: 'masked' | 'hidden'`). `decision` süzgeci **opsiyoneldir** — vermezseniz hepsi gelir.
|
|
426
|
-
`filteredRowCount` yalnız **liste okuma** yolundaki `would-filter` kayıtlarında doludur (gerçek
|
|
427
|
-
sorgunun toplamı − kapsamlı toplam); güncelleme ve silme yolunda `null` kalır. Kayıt dakikalık
|
|
428
|
-
pencerede toplanır, bu yüzden alan **pencere toplamıdır**: istek başına düşen satır sayısı
|
|
429
|
-
`filteredRowCount / count`'tur (ölçüldü 2026-09-19: `count: 22`, `filteredRowCount: 352` →
|
|
430
|
-
istek başına 16). Studio'nun gölge raporu bu bölmeyi kendisi yapar ve istek başına değeri
|
|
431
|
-
gösterir; ham toplamı okuyan başka bir istemci bölmeyi kendi yapmalıdır. `would-mask`
|
|
432
|
-
istek başına entity başına bir kez **çözülür**, ama maskeli/gizli **her alan** için bir kayıt
|
|
433
|
-
düşer ve yalnız sorgu satır döndürdüğünde yazılır.
|
|
434
|
-
2. `access_enforcement_readiness { days }` — pencerede kaç "reddedilirdi" olduğunu sayar.
|
|
435
|
-
`isReady: false` ise `enforce` bugün çalışan bir şeyi keser. `true` olması hiçbir şeyin
|
|
436
|
-
kesilmeyeceğini **kanıtlamaz**: yalnız o pencerede denenen yolları kapsar, az kullanılan uçları
|
|
437
|
-
`access_preview` ile ayrıca sınayın.
|
|
438
|
-
3. `access_enforcement_mode_set { projectId, environmentId, enforcementMode, confirm }` — modu
|
|
439
|
-
değiştirir. Platform iki durumda `confirm` ister: production ortamında **her** değişiklik (409
|
|
440
|
-
`ProductionEnforcementChangeRequiresConfirmation`) ve **her ortamda `off`'a geçiş** (409
|
|
441
|
-
`EnforcementOffRequiresConfirmation`). `off` süzmeyi kaldırmakla kalmaz, korumalı alanları da
|
|
442
|
-
herkese açık döndürür: karar kullanıcınındır, aracın değil — hangi ortam ve neden olduğunu
|
|
443
|
-
söyleyin.
|
|
444
|
-
|
|
445
|
-
Değişiklik runtime'a en geç ~30 sn'de yansır.
|
|
446
|
-
|
|
447
|
-
## Runtime'da kapsam, alan erişimi ve reveal
|
|
448
|
-
|
|
449
|
-
- **Table kaynaklı uç, table step ve dışa aktarma** satırları öznenin kapsamıyla SQL'de süzer. Kapsam dışı
|
|
450
|
-
id ile okuma/güncelleme/silme **404** (tek kayıt ucunda da 404; basit projede 204); eylem izni yoksa
|
|
451
|
-
**403** `ForbiddenException` (mesaj hangi izin olduğunu söylemez — `access_preview`).
|
|
452
|
-
- **Alan erişimi:** `hidden` alan satırdan tamamen çıkar; korumalı alan varsa satırda
|
|
453
|
-
`__protected: { <alan>: 'masked' | 'plain' }` bulunur. Maskeli değer bir metindir — forma değer olarak
|
|
454
|
-
bağlanmaz, geri yazılmaz.
|
|
455
|
-
- Yazma yetkisi olmayan alana değer → `403 AccessFieldWriteDenied`; filtre yetkisi olmayan alana filtre →
|
|
456
|
-
`403 AccessFilterDenied`; sıralama yetkisi olmayan alana sıralama → `403 AccessSortDenied`. Korumalı
|
|
457
|
-
alanda tam eşleşme araması ayrı `field.filter` iznidir ("TCKN ile bul, maskeli gör"). Gizli alan bu iki
|
|
458
|
-
uçta da **sızmaz**: süzme ve sıralama denemesi 403 döner, boş sonuç değil.
|
|
459
|
-
- **Yazma denetimine yalnız satıra gerçekten değer yazılan alan girer.** Bir table-source yazma
|
|
460
|
-
ucunun `fields[]` listesinde `writeOn: always` ile duran alan, kaynağı gövde/başlık/query ise ve
|
|
461
|
-
istekte **hiç gönderilmemişse** satıra anahtar olarak girmez, yazma kararına da sokulmaz
|
|
462
|
-
(TB-110, 2026-09-20). Sabit değeri ya da ifadesi olan alan yazılıyor sayılır ve denetlenir; gövdede
|
|
463
|
-
açıkça `null` gönderilen alan da yazılıyor sayılır. Eskiden gönderilmeyen alan da satıra girdiği
|
|
464
|
-
için kapalı tek bir alan **bütün ucu** `403 AccessFieldWriteDenied` ile kapatıyordu (ölçüldü
|
|
465
|
-
2026-09-20, S2-15).
|
|
466
|
-
- **`deny` ile `allow + fieldAccess: hidden` okumada farklı, yazmada aynıdır:** ikisi de alanı
|
|
467
|
-
**yazılamaz** yapar. Okumada `deny` alanı hiç getirmez, `hidden` alanı satırdan çıkarır; yazmada
|
|
468
|
-
ikisi de `403 AccessFieldWriteDenied` verir.
|
|
469
|
-
- **Reveal:** `access_reveal { application, asUser, entityId, rowId, fieldSlug, reason }` →
|
|
470
|
-
`POST /{proje}/runtime/{app}/reveal`. Kapsamlı `entity.reveal` izni ister; gerekçe zorunlu
|
|
471
|
-
(≤ 1000 karakter) ve denetim kaydına düşer; hız sınırı ayrıdır (varsayılan 5 dk'da 20 → 429).
|
|
472
|
-
Proje ayarı `revealReasonMinLength` (varsayılan 0, `project_get` / `project_update`) daha kısa
|
|
473
|
-
gerekçeyi `400 RevealReasonTooShort` ile reddeder: deneme hız sınırını tüketir ve denetim
|
|
474
|
-
defterine `REVEAL-DENIED` düşer. Gateway asgariyi projeden okur ve kısa gerekçeyi hiç göndermez
|
|
475
|
-
(ACC-010); kasıtlı olumsuz ölçümde `expectFailure: true` ön denetimi atlatır.
|
|
476
|
-
Basit projede ve `off` modda 403. Değer istemcide kısa süre gösterilip atılır.
|
|
477
|
-
**Reddedilen deneme de kayda geçer** (2026-09-19'dan beri): izin yoksa, satır kapsam dışıysa ya da
|
|
478
|
-
satır bulunamadıysa denetim defterine `REVEAL-DENIED` satırı yazılır — gerekçe `currentValue`'da,
|
|
479
|
-
ret sebebi `previousValue`'da. Kayıt isteğin transaction'ı geri alınsa da kalır; başarılı
|
|
480
|
-
`REVEAL` satırında `previousValue` null olduğu için iki durum ayrılır.
|
|
481
|
-
- **Kullanıcının bütün yüzeyi:** `access_runtime_get { application, asUser }` →
|
|
482
|
-
`GET /{proje}/runtime/{app}/access`: zorlama modu, görülebilen sayfa ve uç slug'ları, entity başına
|
|
483
|
-
eylemler ve alan erişimleri. `access_preview` tek kararı açıklar, bu araç haritanın tamamını verir.
|
|
484
|
-
İkisi de `asUser` ister — gateway'in servis jetonu bir uygulama kullanıcısı değildir.
|
|
485
|
-
- İlişki join'iyle gelen alanlar süzülmez: ilişkinin görünen adı her zaman döner.
|
|
486
|
-
|
|
487
|
-
## Kısıtsız sorgu ve runAs (ACC-004 · ACC-005)
|
|
488
|
-
|
|
489
|
-
- **Ham SQL** (query kaynaklı uç, query step): sorgu metni sahiplik alanlı ya da korumalı bir entity'nin
|
|
490
|
-
slug'ını geçiriyorsa `403 AccessQueryNotScoped`. Eşleşme sözcük düzeyindedir — slug kolon ya da takma ad
|
|
491
|
-
olarak geçse de sayılır. `isUnrestricted: true` sorgu çalışır ve **yalnız satır kapsamını**
|
|
492
|
-
kaldırır; yazması `query.unrestricted` iznini ister (ACC-005, warn).
|
|
493
|
-
**Koruma yardımcı sütunları sorgu metninde yasaktır** (TB-103, 2026-09-20): `sys_<alan>_plain`,
|
|
494
|
-
`_enc`, `_bidx`, `_kv` geçen bir sorgu kayıtta **400** `QueryProtectionColumnNotAllowed`, koşuda
|
|
495
|
-
**403** `AccessQueryProtectionColumnDenied` verir — `isUnrestricted` olsun ya da olmasın.
|
|
496
|
-
Her `isUnrestricted` koşusu karar günlüğüne **`unrestricted`** kaydı yazar (enforce modda da);
|
|
497
|
-
`access_decision_log_list { decision: "unrestricted" }` ile okunur. **Sınır:** kayıt, sorgu korumalı
|
|
498
|
-
ya da sahiplik alanlı bir entity'ye dokunduğunda düşer — kapsız bir tabloyu okuyan `isUnrestricted`
|
|
499
|
-
sorgusu zaten bir şey atlamadığı için iz bırakmaz. **İkinci sınır:** yasak sütun taraması sorgu
|
|
500
|
-
metnindeki ADLARA bakar; `select *` ile gelen koruma sütunlarını göremez — rapor ucunda sütunları
|
|
501
|
-
açıkça saydırın.
|
|
502
|
-
Eskiden ölçülen açık (2026-09-20, S2-8): kapsamı üç satır olan bir kullanıcı aynı uçla on bir
|
|
503
|
-
satırın hepsini aldı ve `sys_telefon_plain` kolonunu takma adla seçerek `masked` bir alanın **düz
|
|
504
|
-
değerini** okudu.
|
|
505
|
-
- **Adım kimliği** (table, query ve process step, `rule.runAs`): `inherit` (varsayılan, çağıranın kapsamı) ·
|
|
506
|
-
`system` (kapsam ve alan erişimi atlanır, denetim kaydı yok — ACC-004 warn; gerekçeyi adımın
|
|
507
|
-
`caution`'ına yazın) · `triggering-user` (bastırma geri alınır ve adım **tetikleyen kullanıcının**
|
|
508
|
-
kapsamıyla koşar; tetikleyen bilinmiyorsa hiçbir şey değişmez). `workflow_step_schema` bu alanı
|
|
509
|
-
göstermez; gövdeye yazılır.
|
|
510
|
-
**`runAs: system` bir yetki yükseltmesidir ve `workflow.runas.manage` platform iznini ister**
|
|
511
|
-
(TB-105, 2026-09-20): akışın kendisine ya da herhangi bir adımına `system` yazan `workflow_create` /
|
|
512
|
-
`workflow_update` isteği izin yoksa **403** `WorkflowRunAsPermissionRequired` alır; `inherit`'e
|
|
513
|
-
dönmek serbesttir. Uçların kendisi 2026-09-21'den beri **`workflow.write`** platform izniyle de
|
|
514
|
-
korunur (RA-11): izni olmayan kullanıcı gövdesiz **403** alır (middleware), izni olup
|
|
515
|
-
`workflow.runas.manage` olmayan kullanıcı uca ulaşır ve gövdeli **403
|
|
516
|
-
`WorkflowRunAsPermissionRequired`** görür. Okuma uçları (`Get` tekil ve liste ·
|
|
517
|
-
`GenerateStepSchema` · `GetMiddlewareVariables` · `GetDependencies`) 2026-09-21'den beri
|
|
518
|
-
**`workflow.read`** ister (RA-15): önceden öznitelik taşımadıkları için super-admin'e kilitliydiler
|
|
519
|
-
ve `workflow.write` verilen kullanıcı akışı yazabiliyor ama okuyamıyordu. `Preview` ucu
|
|
520
|
-
**`workflow.write`** ister (RA-16, 2026-09-21): uç kayıtlı bir akışı değil **istemcinin gövdede
|
|
521
|
-
yazdığı adımları** koşturur, yani veri önizleme değil akış yazma sınıfındadır. Query, table ve
|
|
522
|
-
process adımlarının her sistem koşusu karar günlüğüne **`elevated`** kaydı yazar
|
|
523
|
-
— akış id/slug'ı, akışı yazan kullanıcı ve adına koşulan kullanıcı orada durur
|
|
524
|
-
(`access_decision_log_list { decision: "elevated" }`); `process` adımı 2026-09-21'e kadar bu kaydı
|
|
525
|
-
yazmıyordu (RA-17, düzeltildi). Ölçülen açık (2026-09-20, S2-10): onay limiti
|
|
526
|
-
200 bin olan kullanıcı `runAs: system` bir adımla 6 M TL'lik kaydı onayladı; aynı iş `inherit` iken
|
|
527
|
-
`ForbiddenException` alıyordu. Kullanıcı isteğiyle tetiklenen akışlarda `inherit` bırakın.
|
|
528
|
-
- **Tasarım zamanı: Studio erişimi veri erişimidir ve `project.data.preview` ile daraltılır.**
|
|
529
|
-
`microservice_preview` ile Studio satır ızgarası (`row_list`) çağıranın kapsamıyla değil, kapsamsız
|
|
530
|
-
koşar: bütün satırlar ve kapsamsız `deny` ile kapatılmış alanlar **düz** döner; yalnız alan koruması
|
|
531
|
-
(masked/encrypted) depolama katmanında olduğu için durur (ölçüldü 2026-09-20, S2-20). Bu yüzden iki
|
|
532
|
-
uç da **`project.data.preview` platform iznini** ister (TB-114, 2026-09-20); izni olmayan platform
|
|
533
|
-
kullanıcısı **403** alır ve Studio ızgarasında "Veri önizlemesi için izin gerekir" boş durumunu
|
|
534
|
-
görür. İzin verilen tasarımcı hâlâ kapsamsız görür — bir rolün ne göreceğini önizlemeyle değil
|
|
535
|
-
`access_preview` / `access_runtime_get` / `asUser` ile ölçün.
|
|
536
|
-
**Akış önizlemesinde zorlama hiç açılmaz** (ölçüldü 2026-09-21, RA-19): `Activate(...)` yalnız
|
|
537
|
-
microservice / sayfa / connect-data / debug yollarında çağrılır, `POST workflows/{app}/preview`
|
|
538
|
-
yolunda çağrılmaz — kompleks projede bile önizleme `Mode = Off` ile koşar, adım kapsamı
|
|
539
|
-
uygulanmaz ve `runAs: system` adımı `elevated` yazmaz. Önizlemenin kapısı bu yüzden zorlama değil
|
|
540
|
-
**izindir** (`workflow.write`).
|
|
541
|
-
- **Workflow kimliği** (`workflow.runAs`, otomasyonlarda): `inherit` (varsayılan) **tetikleyen çağrının
|
|
542
|
-
kapsamıdır** — otomasyon, satırı değiştiren kullanıcı neyi yapabiliyorsa onu yapar; `system` bir
|
|
543
|
-
yükseltmedir, `workflow.runas.manage` ister ve `elevated` kaydı yazar; `triggering-user` iç içe
|
|
544
|
-
bastırmayı da geri alır (üst düzeyde `inherit` ile aynı sonucu verir). Aynı üç değer, aynı anlam —
|
|
545
|
-
adım düzeyi workflow düzeyini ezer.
|
|
546
|
-
**Ölçülen açık kapandı (RA-10, 2026-09-21):** `inherit` 2026-09-21 öncesinde zorlamayı **tamamen
|
|
547
|
-
bastırıyordu**, yani `runAs` yazmadan otomasyon açan herkes `workflow.runas.manage` kapısını atlayarak
|
|
548
|
-
yükseliyor ve geriye `elevated` kaydı bile kalmıyordu. Ölçüm: kapsamı `own` olan bir müşteri
|
|
549
|
-
temsilcisi kendi satırını güncelledi, otomasyon **başkasının** satırını değiştirdi ve karar günlüğü
|
|
550
|
-
boş kaldı. Artık kapsam dışına yazan `inherit` otomasyon reddedilir; **satır içi** otomasyonda bu
|
|
551
|
-
tetikleyen satır yazımını da düşürür (`ForbiddenException` akış içinden bugün 500 döner — TB-124),
|
|
552
|
-
kuyruk otomasyonunda `automation_histories` `failed` olur ve satır yazımı etkilenmez. Akış içinden
|
|
553
|
-
gelen ret 2026-09-21'den beri **doğru HTTP kodunu** taşır (TB-124): `ForbiddenException` → **403**,
|
|
554
|
-
kapsam dışı satırda `NotFoundException` → **404**; gövde yine `WorkflowStepErrorResponse`'tur
|
|
555
|
-
(`code` · `message` · `step`). **Sınır:** akışın kendi global hata dalı varsa kodu o dalın
|
|
556
|
-
`response` adımı belirler — gateway'in her akışa eklediği `gatewayOnError` adımı 500 döndürür.
|
|
557
|
-
**Sınır:** aktörsüz kuyruk olayında (zamanlanmış mikroservis, deployment içe aktarımı) özne hiç
|
|
558
|
-
kurulmaz, bağlam pasiftir ve otomasyon eskisi gibi zorlamasız koşar. `shadow` ortamda reddetmez,
|
|
559
|
-
`would-deny` yazar.
|
|
560
|
-
- **Otomasyon aktörü:** satır olayındaki kullanıcı hem satır içi hem kuyruk otomasyonunda taşınır;
|
|
561
|
-
kuyruk tüketicisi özneyi kurup ortamın modunu etkinleştirir. Aktör otomasyon geçmişinde
|
|
562
|
-
`queued_events.actor_user_id` kolonunda durur.
|
|
563
|
-
- **Workflow JS'inde özne:** her adımın JS bağlamında dondurulmuş `subject` nesnesi vardır
|
|
564
|
-
(`userId` · `roleSlugs` · `positionIds` · `unitIds` · `companyUnitIds` · `functionCodes`) ve
|
|
565
|
-
`Can(permission, resourceKey)` karar motoruna yan etkisiz sorar. Zorlama kapalıyken `Can` her zaman
|
|
566
|
-
`true` döner — "kapalıyken de reddet" davranışı istiyorsanız kendiniz kontrol edin.
|
|
567
|
-
|
|
568
|
-
## Açıklama ve sınama
|
|
569
|
-
|
|
570
|
-
- **Neden?** → `access_preview { userId, permission, resourceKey, rowId? }`: karar, gerekçe, satır
|
|
571
|
-
kapsamı, alan erişimi ve iz (atama → politika → grant). Yan etkisizdir ve zorlama modundan bağımsız
|
|
572
|
-
hesaplanır — gölge moddaki "reddedilirdi" kaydını da böyle okuyun. `rowId` verildiğinde `isAllowed`
|
|
573
|
-
**tablonun** cevabı olarak kalır; satırın cevabı `rowInScope` (özet: `summary.row`
|
|
574
|
-
`in-scope` / `out-of-scope`). Kapsam dışı satır çalışma zamanında 404 döner.
|
|
575
|
-
- **Kullanıcı gözüyle sına (parolasız)** → runtime araçlarına `asUserId: '<users satır id'si>'`:
|
|
576
|
-
`connect_data_execute`, `microservice_execute`, `microservice_debug`, `page_runtime_get`, `page_screenshot`
|
|
577
|
-
(ayrıca Studio uçları `connect_data_describe/preview/get/bind`). İstek gateway kimliği + `impersonated-user-id`
|
|
578
|
-
başlığıyla gider; platform özneyi o kullanıcı kurar (`AppSessionMiddleware`) — politika, kapsam, maske onun.
|
|
579
|
-
Yalnız development/dal (production'da başlık düşer, gateway isteği göndermez); kullanıcı projede olmalı.
|
|
580
|
-
Parolasız açılan test kullanıcısı için yeterlidir; sayfayı açabilmesi için politikasında `page.view` olmalı.
|
|
581
|
-
**Parolasız kullanıcı `user_create` ile AÇILMAZ** — şeması `password`'ü zorunlu tutar ve AI hiçbir alana parola
|
|
582
|
-
yazmaz. Yol: `row_create { entityId: 'users', rows: [{ email, first_name, last_name }] }` → dönen satır id'si
|
|
583
|
-
`asUserId`'dir; pozisyon/politika ataması `user_position_replace` ve `access_policy_create` ile aynı kalır
|
|
584
|
-
(ölçüldü 2026-09-21, 39/05 D-19: iki test kullanıcısı böyle açıldı, `asUserId` ile 200/403 beklendiği gibi).
|
|
585
|
-
- **Oturum açılmış üye olarak sına** → `access_session_create { application, email, password }`; yanıttaki
|
|
586
|
-
`tokenRefs` referansını `microservice_execute` / `microservice_debug` / `page_runtime_get` `asUser`
|
|
587
|
-
alanına verin. Jeton Bearer olarak gider (CSRF gerekmez), ne yanıta ne günlüğe düz yazılır.
|
|
588
|
-
- `microservice_debug` ve `page_runtime_get` kompleks projede yanıta `accessDecision` ekler: `decision`
|
|
589
|
-
(allow · deny · not-enforced · unknown), `mode`, hata kodu, izin, `reason`, `next`.
|
|
590
|
-
- `microservice_preview` bir Studio ucudur: uygulama jetonuyla sınanamaz — uygulama kullanıcısı olarak
|
|
591
|
-
`microservice_execute` / `microservice_debug`.
|
|
592
|
-
|
|
593
|
-
## Basit ↔ kompleks dönüşüm
|
|
594
|
-
|
|
595
|
-
1. `access_model_preflight { projectId }` — ortam ortam ölçer: entity ve satır sayısı, sahiplik alanı
|
|
596
|
-
olmayan entity'ler, dış datasource'lu entity'ler, sorgu ve kısıtsız sorgu sayısı, rol sayısı,
|
|
597
|
-
**rezerve tablo adı çakışmaları**, `sys_created_user_id`'den doldurulabilir satır sayısı,
|
|
598
|
-
middleware'e bağlı uç ve sayfa listesi, pozisyonsuz kullanıcı sayısı, kapsamlı tabloya dokunan ham
|
|
599
|
-
SQL sorguları. `slugCollisions` boş değilse dönüşüm yapılmamalıdır: kompleks model o adlarla kendi
|
|
600
|
-
sistem tablolarını kurar.
|
|
601
|
-
2. `access_model_convert { projectId, target, enforcementMode }` — `enforce` kabul edilmez; yeni
|
|
602
|
-
kompleks proje önce `shadow`'da izlenir. Yanıt "başladı" demektir.
|
|
603
|
-
3. `access_model_conversion_tasks { projectId }` — ortam başına görev: `pending` · `processing` ·
|
|
604
|
-
`completed` · `error`, deneme sayısı ve hata metniyle. **Bittiğinin tek kanıtı budur**; `error`
|
|
605
|
-
kalan ortam dönüştürülmemiştir.
|
|
606
|
-
|
|
607
|
-
## Organizasyon yapısını yazmak
|
|
608
|
-
|
|
609
|
-
Kompleks projede elle (row API'siyle) yazılması kilitli olan tablolar **üçtür**: `organization_units` ·
|
|
610
|
-
`organization_positions` · `user_positions` (ORG-001). **`roles` bu listede değildir** — sıradan bir
|
|
611
|
-
entity'dir ve kompleks projede de `row_create` ile yazılabilir; proje rolleri fikstür kurarken böyle
|
|
612
|
-
açılır (ölçüldü 2026-09-20, S2-32).
|
|
613
|
-
|
|
614
|
-
Projenin kendi birim/pozisyon ağacı `organization_tree_get` ile okunur; `organization_unit_create` ·
|
|
615
|
-
`organization_unit_update` · `organization_position_create` · `organization_position_update` ile
|
|
616
|
-
yazılır. Kullanıcının rolü, birimi ve şirketi pozisyonundan gelir: `user_position_list` /
|
|
617
|
-
`user_position_replace` (liste **tam değiştirmedir**, boş dizi kullanıcıyı pozisyonsuz bırakır).
|
|
618
|
-
|
|
619
|
-
Proje organizasyon şemasına aboneyse buradan yazmak projeyi "özelleştirilmiş" işaretler ve sonraki
|
|
620
|
-
yayın otomatik inmez; hizalamak için `organization_schema_resubscribe_preview` →
|
|
621
|
-
`organization_schema_resubscribe`. Yayın tarafı: `organization_schema_versions` ·
|
|
622
|
-
`organization_schema_diff` · `organization_schema_subscribers` · `organization_schema_publish`
|
|
623
|
-
(geri alınamaz ve abone projelerin **production** şemasına da yazar) ·
|
|
624
|
-
`project_organization_schema_tasks` (yayının o projeye indiğinin kanıtı).
|
|
625
|
-
|
|
626
|
-
### Organizasyon şeması: taslağı AI yazar, yayını insan yapar
|
|
627
|
-
|
|
628
|
-
Merkezi şemanın **taslağına** `organization_schema_unit_create` · `organization_schema_unit_update` ·
|
|
629
|
-
`organization_schema_position_create` · `organization_schema_position_update` ile yazılır. Bu dört
|
|
630
|
-
araç yalnız taslağı değiştirir: hiçbir projeye inmez, production'a dokunmaz ve verilmeyen alanı
|
|
631
|
-
korur (gateway taslağı okur, tek düğümü değiştirir, listeyi geri yazar — platformda düğüm başına
|
|
632
|
-
uç yoktur, yazma tek parçadır; arada başkası yazdıysa onun değişikliği ezilir).
|
|
633
|
-
|
|
634
|
-
**Yayın AI'ın işi değildir.** `organization_schema_publish` geri alınamaz, bütün abone projelere
|
|
635
|
-
senkronize olur ve abone projenin **production** şemasına da yazar; repo anayasası AI'ın hiçbir
|
|
636
|
-
ortamda production'a yazmasını yasaklar. Taslağı hazırlayın, farkı `organization_schema_diff`
|
|
637
|
-
(`to` verilmezse **taslak ↔ verilen yayın** karşılaştırılır) ile gösterin ve yayını insana bırakın.
|
|
638
|
-
|
|
639
|
-
Ağacın bugünkü kuralları — hepsi 2026-09-20'de ölçüldü (S2-17 · S2-18 · S2-30):
|
|
640
|
-
|
|
641
|
-
- **Tek kök zorunlu.** İkinci bir kök açmak ya da bir birimi köke taşımak `400` döner. Proje kendi
|
|
642
|
-
kökünü açamaz; yayımlanmış şemanın köküne eklenir.
|
|
643
|
-
- **`unitType` yalnız etikettir.** `holding` · `company` · `branch` · `region` · `department` ·
|
|
644
|
-
`team` · `other` arasında izinli-ebeveyn kuralı **yok**: şube doğrudan şirketin altına alınabilir
|
|
645
|
-
(200). Denetlenen tek şey döngü ve kod tekilliği. Anlamlı hiyerarşiyi siz koruyun. Bu bilinçli bir
|
|
646
|
-
karardır (TB-111): sabit bir tip matrisi gerçek organizasyonlara uymuyor, şema düzeyinde
|
|
647
|
-
yapılandırılabilir kural faz 2 adayıdır. Tipin tek işlevsel etkisi `company`'dir — kapsam
|
|
648
|
-
hesabında şirket sınırı odur.
|
|
649
|
-
- **Şemadan gelen düğüm (`origin: "organization"`) kilitli değildir.** Proje onu taşıyabilir,
|
|
650
|
-
yeniden adlandırabilir, **arşivleyebilir** ve içine kendi rolüyle koltuk açabilir. `origin`
|
|
651
|
-
denetimi hiçbir yazma yolunda yok; tek koruma dal ortamıdır.
|
|
652
|
-
- **Arşivleme geri alınabilir** (2026-09-21, TB-112). `organization_unit_activate` ve
|
|
653
|
-
`organization_position_activate` pasifleştirilmiş düğümü geri açar; id, kod ve alt ağaç korunur.
|
|
654
|
-
Kural kökten yaprağa işler: üst düğüm pasifken alt düğüm açılmaz — `400`
|
|
655
|
-
`OrganizationStructureParentInactive`. Pozisyonda üç ayrı sebep sayılır (birimi pasif, idari üst
|
|
656
|
-
pozisyonu pasif, işlevsel üst pozisyonu pasif). Koltuk **boş** açılır: eski atama geri gelmez,
|
|
657
|
-
`user_position_replace` ile yeniden oturtulur. Güncelleme araçları hâlâ `isActive` almaz.
|
|
658
|
-
- **Sapma raporu `organization_schema_drift`'tir** (2026-09-21, TB-112). `organization_schema_diff`
|
|
659
|
-
iki **yayımlanmış sürümü** karşılaştırır ve projenin kopyasını hiç görmez; `organization_schema_drift`
|
|
660
|
-
tam tersine projeye bakar ve ortam başına iki ekseni **ayırır**: `driftFromApplied` = projenin
|
|
661
|
-
uyguladığı sürüme göre yerel kopyadaki fark (`updated` proje düğümü yeniden adlandırdı/taşıdı,
|
|
662
|
-
`removed` proje onu **arşivledi**), `newerInSchema` = aynı sürümden son yayına kadar şemada olanlar.
|
|
663
|
-
`customNodes` projenin kendi (`origin: "project"`) düğümleridir ve sapma sayılmaz. Salt okunur;
|
|
664
|
-
basit projede `400`.
|
|
665
|
-
- **Abonelik hep-ya-hiçtir**: abone proje şemadaki **bütün** birimleri görür (başka iş kollarınınkini
|
|
666
|
-
de); alt ağaca abone olma yolu yok. Projenin kendi (`origin: "project"`) birimleri ise yalnız kendi
|
|
667
|
-
veritabanında kalır, projeler arasında karışmaz.
|
|
668
|
-
- **Pasifleştirme araçları:** `organization_unit_deactivate` · `organization_position_deactivate`
|
|
669
|
-
(2026-09-20'de eklendi; uygulama oturumu istemez). Kapatma sırası yapraktan köke: kullanıcıyı
|
|
670
|
-
koltuktan al (`user_position_replace`) → pozisyonu pasifleştir → alt birimler → birimi
|
|
671
|
-
pasifleştir. Ara adımda `400 OrganizationStructureNodeInUse` alırsınız ve gateway hangi sıranın
|
|
672
|
-
izleneceğini mesaja ekler. Pasifleştirilen birimin sahiplendiği satırlar kimsenin kapsamına
|
|
673
|
-
girmez — `row_reassign` ile devredin (§Sahiplik ve devir).
|
|
674
|
-
- **Dizin (LDAP/AD/SCIM) entegrasyonu yoktur.** Kullanıcı yalnız elle (`user_create` /
|
|
675
|
-
yönetim konsolu) açılır; toplu içe aktarma ya da dizinden eşitleme operasyonu da yok.
|
|
676
|
-
|
|
677
|
-
## Toplu işlem
|
|
678
|
-
|
|
679
|
-
Kapsam ve koşul her satırda ayrı ayrı uygulanır; dolayısıyla "hepsini birden onayla" bir POLİTİKA
|
|
680
|
-
sorusu değil bir UÇ sorusudur ve table-source `update` bunu **filtreyle yapamaz** — tam olarak bir
|
|
681
|
-
tekil alan filtresi ister (`InvalidFilterCountException` · `FilterFieldMustUniqueException`,
|
|
682
|
-
ölçüldü 2026-09-20, S2-22). Doğru kurulum: anahtarlar elindeyse `bulk-update` ucu (tek çağrı, tek
|
|
683
|
-
transaction), satır başına sonuç ve satır başına yetki kararı gerekiyorsa **iş akışı + döngü**
|
|
684
|
-
(liste → her satır için `microservice` adımı → özet). Akış içinden yazmak yetki YÜKSELTMEZ: her
|
|
685
|
-
satır çağıranın kimliğiyle denetlenir ve reddedilen satır ötekileri geri almaz. Reçete:
|
|
686
|
-
`platform_guide('microservice')` §"Toplu güncelleme FİLTREYLE kurulmaz".
|
|
687
|
-
|
|
688
|
-
## Sahiplik ve devir (ORG-006)
|
|
689
|
-
|
|
690
|
-
Sahiplik alanları (`sys_owner_user_id` · `sys_owner_unit_id`) satır kapsamının dayanağıdır ve
|
|
691
|
-
**satır yazma yolundan yazılmaz**: `row_create` bunları çağırandan ve pozisyonundan kendisi
|
|
692
|
-
doldurur, `row_update` / toplu güncelleme gövdesinde görürse istek `400
|
|
693
|
-
OwnershipFieldNotWritable` alır (2026-09-20 öncesinde sessizce düşüyordu, S2-7).
|
|
694
|
-
|
|
695
|
-
Sahip değiştirmenin tek yolu **`row_reassign`**'dır:
|
|
696
|
-
|
|
697
|
-
- Hedef satırlar `rowIds` ya da `filter` ile seçilir; hedef sahip `ownerUnitId` ve/veya
|
|
698
|
-
`ownerUserId`'dir. Yalnız `ownerUserId` verilirse birim o kişinin aktif birincil pozisyonundan
|
|
699
|
-
türetilir (pozisyonu yoksa satırın birimi olduğu gibi kalır).
|
|
700
|
-
- Her satıra `REASSIGN` denetim kaydı düşer (eski sahip → yeni sahip); `entity_audit_trails` ile
|
|
701
|
-
okunur.
|
|
702
|
-
- Hedef birim/kullanıcı var olmalı (birim ayrıca aktif olmalı), yoksa 404; tek çağrıda en çok 1000
|
|
703
|
-
satır devredilir.
|
|
704
|
-
|
|
705
|
-
**Kimlik iki yol ayırır.** `row_reassign` öteki `row_*` araçları gibi bir **Studio** ucudur ve
|
|
706
|
-
gateway'in platform kimliğiyle koşar — uygulama jetonu (`asUser`) orada geçmez, 401 alır. İzin
|
|
707
|
-
`entity.reassign` ve **kapsamlıdır**, ama o kapsam ancak istekte bir uygulama öznesi varken
|
|
708
|
-
hesaplanır. Uygulama kullanıcısının kendi kapsamıyla devretmesi için (ve kapsamı gerçekten
|
|
709
|
-
ölçmek için) sistem operasyonunu kullanın: `systemOperation: 'entity.row.reassign'` olan bir uç
|
|
710
|
-
açıp `microservice_execute { asUser }` ile çağırın. Kapsam kuralı orada işler ve kapsamı `unit` ya
|
|
711
|
-
da `unit-tree` olan çağıran için **sahipsiz satır** (`sys_owner_unit_id` NULL) de kapsam içi
|
|
712
|
-
sayılır — şubesi kapanan kayda başka türlü kimse ulaşamazdı.
|
|
713
|
-
|
|
714
|
-
**Sistem operasyonunun izni** katalogdaki `permission`'dır (`microservice_system_operation_list`);
|
|
715
|
-
çalıştırıcı onu işlemden önce karar motoruna sorar. `permission` **boş** olan işlemde izni işlemin
|
|
716
|
-
çağırdığı servis verir: süreç çalışma zamanı (`process.*`) görevi, bildirimi, vekaleti kişiye ve kayda
|
|
717
|
-
göre çözer ve REST `bpm/*` ucuyla aynı görünürlüğü verir; yalnız `process.override.*` `process.manage`
|
|
718
|
-
(kaynak `process:<id>`) ister. Modül kurulumu "Modül kullanıcısı" politikasına yalnız işaretli
|
|
719
|
-
işlemlerin iznini yazar — `process.manage`'ı yazmaz, açık bir politikayla verin.
|
|
720
|
-
|
|
721
|
-
**Kullanıcı silinince** satırları sarkık kalmaz: `user.delete` sahiplik taşıyan her entity'de o
|
|
722
|
-
kullanıcının satırlarının `sys_owner_user_id` alanını NULL'a çeker, `sys_owner_unit_id`'yi
|
|
723
|
-
**korur** (birimin sahipsiz kaydı olurlar, birim yöneticisi görmeye devam eder) ve entity başına bir
|
|
724
|
-
`OWNER-RELEASED` denetim kaydı yazar (kaç satır, hangi kullanıcı). Silme çağrısına
|
|
725
|
-
`transferToUserId` verilirse satırlar bunun yerine devralan kişiye ve birimine geçer ve kayıt
|
|
726
|
-
`REASSIGN` olur; devralan var olmalı (404) ve silinen kişinin kendisi olamaz (400). Devralanın
|
|
727
|
-
birimi, o kişinin **birincil aktif pozisyonunun** biriminden okunur — aktif pozisyonu yoksa
|
|
728
|
-
`sys_owner_unit_id` hiç değişmez. Ajan yolu `user_delete { transferToUserId }`; aynı seçenek
|
|
729
|
-
REST yolunda da vardır: `DELETE /{proje}/users/{id}?transferToUserId=…`. Sahipliğin çözülmesi
|
|
730
|
-
kompleks projeye özgüdür: basit modelde silme çalışır ama bu adım hiç işlemez.
|
|
731
|
-
|
|
732
|
-
## Kompleks projede kimlik middleware'i (ACC-006)
|
|
733
|
-
|
|
734
|
-
Set-user'lı kimlik middleware'i (`platform_guide('middleware')` Tarif 1) kompleks projede gereksizdir, bağlı
|
|
735
|
-
kalırsa da etkisiz değildir: platform oturumu kurar ve uç yolunda `user`'ı doldurur, ama bağlı middleware'ler
|
|
736
|
-
zorlama modundan bağımsız **her modda koşar** ve reddedebilir; set-user adımı ya da yanıttaki `user`
|
|
737
|
-
platformun `user`'ını **ezer**. Karar motoru özneyi oturumdan okur; ezilen `user` ise ifadelerde ikinci bir
|
|
738
|
-
doğruluk kaynağı olur. Kimlik middleware'ini uçların ve sayfaların `middlewareIds`'inden çıkarın. Gateway
|
|
739
|
-
`set-user` taşıyan middleware yazımında uyarır (warn). Ayar setter'ı gibi kimlik dışı middleware'ler serbesttir.
|
|
740
|
-
|
|
741
|
-
## Eski rol listeleri (ACC-008)
|
|
742
|
-
|
|
743
|
-
`page.roleIds` ve `microservice.roles` kompleks projede **karar girdisi değildir**: `enforce`'ta tek kapı
|
|
744
|
-
karar motorudur ve platform bu listeyi hiçbir modda yetki için okumaz — liste yalnız `triggerSource.roles`'a
|
|
745
|
-
geçer, yani ona anlam veren tek şey `Authorized(user.roles)` çağıran bir middleware'dir (K-29). Yetkiyi
|
|
746
|
-
`access_policy_create` + `access_matrix_save` ile verin ve listeyi boş bırakın; gateway dolu listede uyarır
|
|
747
|
-
(warn, çünkü `off` ve `shadow` modunda eski davranış sürer) ve Studio kompleks projede rol seçicisini zaten
|
|
748
|
-
çizmez.
|
|
749
|
-
|
|
750
|
-
**Kullanıcıya DOĞRUDAN atanan rol de yetki vermez** (2026-09-21, S-15). Özne kurulurken roller
|
|
751
|
-
kompleks projede **yalnız pozisyonlardan** gelir (`AppSubjectResolver.ResolveAsync`): `user_roles`
|
|
752
|
-
satırı — `PUT /{proje}/users/{id}` ile verilen eski yol — özneye hiç girmez, `auth/me`'de rol olarak
|
|
753
|
-
sayılmaz ve o rolün politikaları uygulanmaz. "Kullanıcının rolü pozisyonundan gelir" cümlesi artık
|
|
754
|
-
bu yolu da kapsıyor: koltuğu gişe olan bir kullanıcıya temsilci rolü atanırsa **yalnız gişe** sayılır,
|
|
755
|
-
hiç koltuğu olmayan kullanıcı ise rolsüzdür ve her kapsamlı grant'ten reddedilir. Birleşim yalnız
|
|
756
|
-
**basit** projede sürer. 2026-09-19'da ölçülen eski davranış (ikisi de sayılıyordu) artık geçerli
|
|
757
|
-
değildir. Basit → kompleks dönüşümünde kimin yetki kaybedeceğini `access_model_preflight`
|
|
758
|
-
`usersWithDirectRoles` sayar; o kullanıcılar dönüşümden önce `user_position_replace` ile koltuğa
|
|
759
|
-
oturtulur.
|
|
760
|
-
|
|
761
|
-
Bunun tek istisnası **projeyi açan kullanıcıdır**: koltuğu olmasa da yetkilidir, çünkü `system-admin`
|
|
762
|
-
politikası ona ayrıca `subjectType: 'user'` ile atanır (§Atama). Kurucu dışında koltuksuz kimse
|
|
763
|
-
yetkili değildir — "neden göremiyor?" sorusunda ilk bakılacak yer hâlâ `user_position_list`'tir.
|
|
764
|
-
|
|
765
|
-
## Hatalar
|
|
766
|
-
|
|
767
|
-
| Anahtar | Durum | Ne yapmalı |
|
|
768
|
-
|---|---|---|
|
|
769
|
-
| `SystemEntityWriteNotAllowed` | 400 | Organizasyon/erişim tablosuna genel satır yazımı (ORG-001) — Studio ya da `access_policy_*` |
|
|
770
|
-
| `AccessPermissionUnknown` | 400 | İzin slug'ı katalogda yok — `access_permission_list` |
|
|
771
|
-
| `AccessResourceTypeMismatch` | 400 | Anahtar iznin tipiyle başlamıyor |
|
|
772
|
-
| `AccessResourceUnknown` | 400 | Yeni gelen anahtar katalogda yok — `access_resource_list` |
|
|
773
|
-
| `AccessScopeNotSupported` · `AccessFieldAccessNotSupported` | 400 | Kapsam/alan erişimi o izinde yok (ACC-001) |
|
|
774
|
-
| `AccessDenyFieldAccessNotSupported` · `AccessConditionRequiresScope` · `AccessSubordinatesLineRequiresSubordinatesScope` | 400 | Grant biçimi (ACC-001) — deny kapsam taşıyabilir, alan erişimi taşıyamaz |
|
|
775
|
-
| `AccessOverrideRequiresUserWithEndDate` | 400 | `overridesDeny` yalnız `user` öznesi + dolu `endsAt` (ACC-009) |
|
|
776
|
-
| `AccessOverridePermissionRequiredException` | 403 | İstisnayı açmak/genişletmek ya da istisna taşıyan politikanın grant'lerine dokunmak `access.override.manage` ister (ACC-009) |
|
|
777
|
-
| `AccessConditionInvalidException` | 400 | Koşul alanı/işleci/değeri (ACC-001 · ACC-002) |
|
|
778
|
-
| `AccessScopeRequiresOwnerFields` | 400 | Entity'de sahiplik alanı yok (ACC-003) |
|
|
779
|
-
| `AccessAssignmentDescendantsRequiresUnit` · `AccessAssignmentPeriodInvalid` · `AccessSubjectMissing` | 400 / 422 | Atama biçimi |
|
|
780
|
-
| `AccessPolicySlugDuplicate` | 409 | Slug projede tekil |
|
|
781
|
-
| `OrganizationPositionSeatOccupied` | 409 | Tek koltuklu pozisyonda çakışan ikinci kalıcı atama (ORG-003) — vekâlet için `assignmentType: 'acting'`, kalıcı ikinci kişi için pozisyonu `isMultiSeat` yapın |
|
|
782
|
-
| `RevealReasonTooShort` | 400 | Gerekçe projenin asgarisinin altında (`revealReasonMinLength`, ACC-010); deneme `REVEAL-DENIED` olarak kaydedilir |
|
|
783
|
-
| `EnforcementOffRequiresConfirmation` | 409 | `off`'a geçiş korumalı alanları herkese açar — bilinçliyse `confirm: true` |
|
|
784
|
-
| `ProtectionFieldTypeNotSupported` · `ProtectionDisplayFieldNotAllowed` | 400 / 422 | Korunamayan alan (PROT-003) |
|
|
785
|
-
| `ProtectionDerivedSourceInvalid` · `ProtectionDerivedRuleInvalid` | 400 / 422 | Türetme kuralı (PROT-004) |
|
|
786
|
-
| `ProtectionOperatorNotAllowed` · `ProtectionSortNotAllowed` | 400 | Korumalı alanda arama/sıralama (PROT-001 · PROT-002) |
|
|
787
|
-
| `ProtectionChangeNotAllowed` | 400 | Var olan alanın koruması — `entity_protection_update` |
|
|
788
|
-
| `ProtectionMigrationInProgress` | 409 | Koruma işi sürüyor — `import_status`, gerekirse aynı çağrıyı tekrarla |
|
|
789
|
-
| `ProtectionKeyUnavailable` | — | Ortamda anahtar yok (insan işi) |
|
|
790
|
-
| `AppSessionRequiredException` | 401 | Oturum yok (kompleks + `enforce`) — parolasız `asUserId` (development) ya da `access_session_create` + `asUser` |
|
|
791
|
-
| `AppSessionInvalidException` | 401 | Jeton geçersiz ya da süresi dolmuş — yeniden giriş |
|
|
792
|
-
| `AppSessionRateLimitedException` | 429 | Giriş ya da reveal hız sınırı — bekleyin |
|
|
793
|
-
| `CsrfTokenMismatchException` | 403 | Çerezli durum değiştiren istekte `X-ZY-CSRF` yok — Bearer (`asUser`) |
|
|
794
|
-
| `ForbiddenException` | 403 | İzin reddi (mesaj izni adıyla söylemez) — `access_preview` |
|
|
795
|
-
| `AccessQueryNotScopedException` | 403 | Ham SQL kapsamlı/korumalı tabloya dokunuyor — table kaynağı ya da `isUnrestricted` (ACC-005) |
|
|
796
|
-
| `AccessFieldWriteDeniedException` · `AccessFilterDeniedException` · `AccessRevealDeniedException` | 403 | Alan erişimi — `access_preview` `fieldAccess` |
|