@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.
Files changed (201) hide show
  1. package/.env.example +15 -0
  2. package/README.md +5 -5
  3. package/dist/config.js +37 -0
  4. package/dist/index.js +2 -0
  5. package/dist/knowledge/access.js +802 -0
  6. package/dist/knowledge/backendConstraints.js +18 -1
  7. package/dist/knowledge/case.js +41 -0
  8. package/dist/knowledge/componentCatalog.js +494 -34
  9. package/dist/knowledge/componentEvents.js +132 -7
  10. package/dist/knowledge/connectDataBind.js +819 -0
  11. package/dist/knowledge/connectDataDefinition.js +341 -0
  12. package/dist/knowledge/connectDataExecute.js +93 -0
  13. package/dist/knowledge/connectDataRules.js +128 -0
  14. package/dist/knowledge/decision.js +121 -0
  15. package/dist/knowledge/expressionPrelude.js +59 -0
  16. package/dist/knowledge/layoutSummary.js +140 -2
  17. package/dist/knowledge/microserviceParameters.js +58 -0
  18. package/dist/knowledge/mining.js +94 -0
  19. package/dist/knowledge/mobileComponentCatalog.js +859 -0
  20. package/dist/knowledge/mobileComponentEvents.js +239 -0
  21. package/dist/knowledge/normalize.js +236 -67
  22. package/dist/knowledge/outlines.js +36 -0
  23. package/dist/knowledge/platform/lint.js +385 -0
  24. package/dist/knowledge/platform/mobile.js +142 -0
  25. package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
  26. package/dist/knowledge/platform/mobileRules.js +231 -0
  27. package/dist/knowledge/platform/mobileSpacing.js +82 -0
  28. package/dist/knowledge/platform/mobileTabs.js +108 -0
  29. package/dist/knowledge/platform/nativeBoxModel.js +44 -0
  30. package/dist/knowledge/platform/profile.js +25 -0
  31. package/dist/knowledge/platform/resolve.js +122 -0
  32. package/dist/knowledge/platform/web.js +39 -0
  33. package/dist/knowledge/policy.js +18 -4
  34. package/dist/knowledge/process.js +510 -0
  35. package/dist/knowledge/reservedTables.js +79 -0
  36. package/dist/knowledge/rowFilter.js +43 -0
  37. package/dist/knowledge/rules.js +319 -21
  38. package/dist/knowledge/schemaGuard.js +11 -0
  39. package/dist/knowledge/styleResolve.js +50 -4
  40. package/dist/knowledge/styleResolveNative.js +527 -0
  41. package/dist/knowledge/themeResolve.js +3 -3
  42. package/dist/observability/trace.js +6 -3
  43. package/dist/platform/argumentAliases.js +128 -0
  44. package/dist/platform/bodyFile.js +103 -0
  45. package/dist/platform/capture/actions.js +333 -0
  46. package/dist/platform/capture/browser.js +1 -0
  47. package/dist/platform/{screenshot.js → capture/capture.js} +105 -519
  48. package/dist/platform/capture/console-log.js +122 -0
  49. package/dist/platform/capture/index.js +11 -0
  50. package/dist/platform/capture/readiness.js +103 -0
  51. package/dist/platform/capture/summary.js +77 -0
  52. package/dist/platform/capture/target.js +5 -0
  53. package/dist/platform/capture/targets/studio-mobile.js +15 -0
  54. package/dist/platform/capture/targets/studio-web.js +5 -0
  55. package/dist/platform/diagnostics.js +10 -4
  56. package/dist/platform/domSummary.js +1 -1
  57. package/dist/platform/errors.js +162 -10
  58. package/dist/platform/http.js +29 -8
  59. package/dist/platform/impersonation.js +45 -0
  60. package/dist/platform/jsonArray.js +24 -0
  61. package/dist/platform/responses.js +39 -5
  62. package/dist/platform/schemaReadMemory.js +60 -0
  63. package/dist/platform/secrets.js +17 -1
  64. package/dist/platform/strictArguments.js +68 -12
  65. package/dist/platform/tokenVault.js +187 -4
  66. package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
  67. package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
  68. package/dist/resources/examples/bpm-satinalma.json +376 -0
  69. package/dist/resources/examples/connect-data-convert-verify.json +107 -0
  70. package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
  71. package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
  72. package/dist/resources/examples/connect-data-query-params.json +50 -0
  73. package/dist/resources/examples/connect-data-table-entity.json +147 -0
  74. package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
  75. package/dist/resources/examples/mobile-app-shell-drawer.json +243 -0
  76. package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
  77. package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
  78. package/dist/resources/examples/mobile-form-screen.json +365 -0
  79. package/dist/resources/examples/mobile-list-detail-form.json +672 -0
  80. package/dist/resources/examples/page-detail-profile.json +2 -1
  81. package/dist/resources/examples/page-dynamic-form.json +3 -2
  82. package/dist/resources/examples/page-flex-sections.json +1 -1
  83. package/dist/resources/examples/page-html-embed.json +1 -1
  84. package/dist/resources/examples/workflow-basic.json +8 -2
  85. package/dist/resources/guides/access.md +796 -0
  86. package/dist/resources/guides/bpm.md +686 -0
  87. package/dist/resources/guides/case.md +153 -0
  88. package/dist/resources/guides/component.md +91 -4
  89. package/dist/resources/guides/decision.md +185 -0
  90. package/dist/resources/guides/entity.md +50 -8
  91. package/dist/resources/guides/expressions.md +14 -5
  92. package/dist/resources/guides/functions.md +1 -1
  93. package/dist/resources/guides/getting-started.md +38 -1
  94. package/dist/resources/guides/layout.md +11 -7
  95. package/dist/resources/guides/microservice.md +81 -2
  96. package/dist/resources/guides/middleware.md +44 -2
  97. package/dist/resources/guides/mobile-layout.md +193 -0
  98. package/dist/resources/guides/mobile.md +495 -0
  99. package/dist/resources/guides/page.md +454 -75
  100. package/dist/resources/guides/theme.md +8 -2
  101. package/dist/resources/guides/translation.md +1 -1
  102. package/dist/resources/guides/workflow.md +58 -1
  103. package/dist/resources/read.js +41 -0
  104. package/dist/resources/rules.js +11 -5
  105. package/dist/resources/schema-fingerprint.json +7 -5
  106. package/dist/resources/schemas/AccessExplanationDto.json +144 -0
  107. package/dist/resources/schemas/AccessMatrixDto.json +170 -0
  108. package/dist/resources/schemas/AccessPermissionDto.json +57 -0
  109. package/dist/resources/schemas/AccessPolicyDto.json +223 -0
  110. package/dist/resources/schemas/AccessResourceDto.json +86 -0
  111. package/dist/resources/schemas/AppSessionDto.json +53 -0
  112. package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
  113. package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
  114. package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
  115. package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
  116. package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
  117. package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
  118. package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
  119. package/dist/resources/schemas/CreateEntityCommand.json +118 -0
  120. package/dist/resources/schemas/CreateMicroserviceCommand.json +13 -1
  121. package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
  122. package/dist/resources/schemas/CreateQueryCommand.json +4 -0
  123. package/dist/resources/schemas/CreateWorkflowCommand.json +143 -1
  124. package/dist/resources/schemas/DataJobDto.json +6 -1
  125. package/dist/resources/schemas/DecisionDto.json +302 -0
  126. package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
  127. package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
  128. package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
  129. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +21 -1
  130. package/dist/resources/schemas/MicroserviceDto.json +15 -3
  131. package/dist/resources/schemas/OrganizationProjectDto.json +335 -0
  132. package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
  133. package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
  134. package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
  135. package/dist/resources/schemas/PreviewMicroserviceCommand.json +10 -1
  136. package/dist/resources/schemas/PreviewWorkflowCommand.json +22 -1
  137. package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
  138. package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
  139. package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
  140. package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
  141. package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
  142. package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
  143. package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
  144. package/dist/resources/schemas/StepDto.json +22 -1
  145. package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
  146. package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
  147. package/dist/resources/schemas/UpdateEntityCommand.json +118 -0
  148. package/dist/resources/schemas/UpdateMicroserviceCommand.json +13 -1
  149. package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
  150. package/dist/resources/schemas/UpdateQueryCommand.json +4 -0
  151. package/dist/resources/schemas/UpdateViewCommand.json +0 -2
  152. package/dist/resources/schemas/UpdateWorkflowCommand.json +143 -1
  153. package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
  154. package/dist/server.js +27 -1
  155. package/dist/tools/access.js +369 -2
  156. package/dist/tools/accessOperations.js +135 -0
  157. package/dist/tools/accessPolicies.js +170 -0
  158. package/dist/tools/accessRuntime.js +203 -0
  159. package/dist/tools/applications.js +60 -3
  160. package/dist/tools/bpm.js +343 -0
  161. package/dist/tools/bpmGovernance.js +266 -0
  162. package/dist/tools/bpmOperations.js +230 -0
  163. package/dist/tools/bpmReporting.js +154 -0
  164. package/dist/tools/bpmRouting.js +150 -0
  165. package/dist/tools/bpmRuntime.js +396 -0
  166. package/dist/tools/case.js +178 -0
  167. package/dist/tools/caseRuntime.js +89 -0
  168. package/dist/tools/common.js +7 -0
  169. package/dist/tools/components.js +118 -14
  170. package/dist/tools/connectData.js +449 -0
  171. package/dist/tools/connectors.js +193 -0
  172. package/dist/tools/datasources.js +3 -3
  173. package/dist/tools/decisions.js +206 -0
  174. package/dist/tools/dependencies.js +1 -1
  175. package/dist/tools/deployments.js +2 -2
  176. package/dist/tools/designSchemaPatch.js +34 -9
  177. package/dist/tools/dtos.js +36 -5
  178. package/dist/tools/entities.js +79 -12
  179. package/dist/tools/externalComponents.js +26 -5
  180. package/dist/tools/flows.js +122 -14
  181. package/dist/tools/folders.js +1 -1
  182. package/dist/tools/imports.js +5 -2
  183. package/dist/tools/layouts.js +50 -17
  184. package/dist/tools/merges.js +1 -1
  185. package/dist/tools/microservices.js +77 -25
  186. package/dist/tools/mobile.js +221 -0
  187. package/dist/tools/modules.js +48 -0
  188. package/dist/tools/organizationStructure.js +137 -0
  189. package/dist/tools/pages.js +465 -98
  190. package/dist/tools/platformInfo.js +27 -8
  191. package/dist/tools/profileWrite.js +92 -0
  192. package/dist/tools/projects.js +71 -9
  193. package/dist/tools/rows.js +69 -13
  194. package/dist/tools/schemaOps.js +61 -1
  195. package/dist/tools/screenWrite.js +37 -8
  196. package/dist/tools/screens.js +95 -5
  197. package/dist/tools/templates.js +26 -1
  198. package/dist/tools/translations.js +1 -1
  199. package/dist/tools/variables.js +11 -5
  200. package/dist/tools/workflows.js +10 -5
  201. package/package.json +2 -2
@@ -0,0 +1,193 @@
1
+ import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
2
+ import { PlatformApiError } from '../platform/errors.js';
3
+ import { handle } from '../platform/responses.js';
4
+ import { assertProcessNotProduction } from './bpm.js';
5
+ import { z } from 'zod';
6
+ const credentialKinds = ['api-key', 'basic', 'bearer', 'oauth2-client', 'oauth2-auth-code', 'webhook'];
7
+ const eventSourceKinds = ['http', 'rabbitmq', 'kafka', 'service-bus'];
8
+ const mailSourceKinds = ['imap', 'graph'];
9
+ const credentialFields = {
10
+ name: z.string().min(1).max(100).describe("kasa adı (tekil); düğümde credentialRef, kanal kimliklerinde sabit ad: notification-sms · notification-teams · notification-slack"),
11
+ connectorName: z.string().min(1).max(50).describe('connector_list adı; kaydedildikten sonra değişmez'),
12
+ kind: z.enum(credentialKinds),
13
+ baseUrl: z.string().max(500).optional().describe('instance/taban URL (Salesforce instance, Jira site, Camunda REST kökü)'),
14
+ tokenUrl: z.string().max(500).optional().describe('oauth2 belirteç ucu'),
15
+ clientId: z.string().max(200).optional(),
16
+ username: z.string().max(200).optional(),
17
+ scopes: z.array(z.string().max(200)).max(50).optional(),
18
+ apiKeyHeader: z.string().max(100).optional().describe("api-key başlığı; yoksa Authorization"),
19
+ clientSecret: z.string().max(4000).optional(),
20
+ password: z.string().max(4000).optional(),
21
+ apiKey: z.string().max(4000).optional().describe('webhook türünde webhook URL\'si buraya yazılır'),
22
+ refreshToken: z.string().max(4000).optional(),
23
+ accessToken: z.string().max(4000).optional()
24
+ };
25
+ function catalogOf(payload) {
26
+ const data = payload?.data ?? payload;
27
+ return Array.isArray(data) ? data : [];
28
+ }
29
+ export function registerConnectorTools(server, platform) {
30
+ const config = platform.config;
31
+ server.registerTool('connector_list', {
32
+ title: 'Bağlayıcı kataloğu',
33
+ description: "Kayıtlı bağlayıcıları listeler (GET bpm/connectors): ad, kategori (ai | process-engine | productivity | messaging | business-app | rpa), başlık, sürüm, desteklenen kimlik türleri ve işlem adları. category verilirse yalnız o kategori döner (süzme gateway'de). İşlem girdi/çıktı şemaları için connector_get. Süreçte kullanım: service düğümü connector { name, operation, credentialRef, input } ya da dış motor için externalEngine { engine: camunda8 | camunda7 | flowable, processKey, credentialRef, input }.",
34
+ inputSchema: {
35
+ project: projectParam,
36
+ environment: environmentParam,
37
+ category: z.enum(['ai', 'process-engine', 'productivity', 'messaging', 'business-app', 'rpa']).optional().describe('yalnız bu kategorideki bağlayıcılar')
38
+ },
39
+ annotations: readOnly
40
+ }, handle(config, async ({ project, environment, category }) => catalogOf(await platform.tenant('GET', project, '/bpm/connectors', { environment }))
41
+ .filter(connector => !category || connector.category === category)
42
+ .map(connector => ({
43
+ name: connector.name,
44
+ category: connector.category,
45
+ title: connector.title,
46
+ version: connector.version,
47
+ credentialKinds: connector.credentialKinds,
48
+ operations: (Array.isArray(connector.operations) ? connector.operations : []).map(operation => operation.name)
49
+ }))));
50
+ server.registerTool('connector_get', {
51
+ title: 'Bağlayıcıyı getir',
52
+ description: 'Bağlayıcının işlemlerini girdi ve çıktı şemalarıyla döner (katalogdan adla). Girdi doğrulaması zorunlu alanlar ve temel türlerle sınırlıdır; düğümde input değerleri Jint ifadesidir.',
53
+ inputSchema: { project: projectParam, environment: environmentParam, name: z.string().min(1).max(50) },
54
+ annotations: readOnly
55
+ }, handle(config, async ({ project, environment, name }) => {
56
+ const catalog = catalogOf(await platform.tenant('GET', project, '/bpm/connectors', { environment }));
57
+ const connector = catalog.find(candidate => candidate.name === name);
58
+ if (!connector)
59
+ throw new PlatformApiError(`connector_get: '${name}' diye bağlayıcı yok. Mevcutlar: ${catalog.map(candidate => String(candidate.name)).join(', ')}.`, 404);
60
+ return connector;
61
+ }));
62
+ server.registerTool('connector_credential_list', {
63
+ title: 'Kimlik kasasını listele',
64
+ description: "Kasa kayıtlarını listeler (GET bpm/connector-credentials): ad, bağlayıcı, tür, taban/belirteç URL'si, istemci kimliği, kapsamlar, secretFields (yalnız saklı sırların ADLARI) ve anahtar sürümü. Platform sırrı hiç döndürmez; gateway sır ya da belirteç adlı alanları ayrıca *** ile maskeler (BPM-017). Yetki process.manage.",
65
+ inputSchema: { project: projectParam, environment: environmentParam },
66
+ annotations: readOnly
67
+ }, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/bpm/connector-credentials', { environment })));
68
+ server.registerTool('connector_credential_create', {
69
+ title: 'Kasaya kimlik yaz',
70
+ description: "Bağlayıcı kimliği oluşturur (POST bpm/connector-credentials). Sırlar (clientSecret, password, apiKey, refreshToken, accessToken) proje veri anahtarıyla şifrelenir; yanıtta ve gateway günlüğünde görünmez (BPM-017). Türler: basic · api-key (apiKeyHeader) · bearer · oauth2-client (tokenUrl, clientId, clientSecret, scopes) · oauth2-auth-code (refreshToken elle) · webhook (URL apiKey'de; teams-webhook, slack). Yazdıktan sonra connector_credential_update { operation: 'test' }.",
71
+ inputSchema: { project: projectParam, environment: environmentParam, ...credentialFields },
72
+ annotations: writes
73
+ }, handle(config, async ({ project, environment, ...credential }) => {
74
+ assertProcessNotProduction('connector_credential_create', environment, config);
75
+ return platform.tenant('POST', project, '/bpm/connector-credentials', { environment, body: credential });
76
+ }));
77
+ server.registerTool('connector_credential_update', {
78
+ title: 'Kasa kimliğini güncelle / test et / döndür',
79
+ description: "operation save (varsayılan; PUT bpm/connector-credentials/{id}, tam gövde — bütün sır alanları boşsa saklı sırlar korunur; TEK bir sır alanı bile gönderilirse saklı sırların tamamı gönderilenle değişir, o türün bütün sırlarını birlikte verin: oauth2-client clientSecret · oauth2-auth-code clientSecret + refreshToken · basic password · api-key/webhook apiKey · bearer accessToken) · test (POST …/{id}/test-connection; bağlayıcının bağlantı denemesi, hata 502 ConnectorFailed) · rotate (POST …/rotate; bütün sırları en yeni proje anahtar sürümüyle yeniden şifreler, id almaz, değişen sayısını döner; şifreleme anahtarı yapılandırılmamışsa kasa boş olsa bile ProtectionKeyUnavailable hatası döner — 0 başarı değildir).",
80
+ inputSchema: {
81
+ project: projectParam,
82
+ environment: environmentParam,
83
+ id: guid.optional().describe('save ve test için zorunlu'),
84
+ operation: z.enum(['save', 'test', 'rotate']).optional(),
85
+ ...z.object(credentialFields).partial().shape
86
+ },
87
+ annotations: updates
88
+ }, handle(config, async ({ project, environment, id, operation, ...credential }) => {
89
+ assertProcessNotProduction('connector_credential_update', environment, config);
90
+ const resolvedOperation = operation ?? 'save';
91
+ if (resolvedOperation === 'rotate')
92
+ return platform.tenant('POST', project, '/bpm/connector-credentials/rotate', { environment });
93
+ if (!id)
94
+ throw new PlatformApiError(`connector_credential_update: operation '${resolvedOperation}' id ister (istek gönderilmedi).`, 400);
95
+ if (resolvedOperation === 'test')
96
+ return platform.tenant('POST', project, `/bpm/connector-credentials/${id}/test-connection`, { environment });
97
+ if (!credential.name || !credential.connectorName || !credential.kind)
98
+ throw new PlatformApiError("connector_credential_update: save tam gövde ister — name, connectorName, kind (connector_credential_list çıktısından) (istek gönderilmedi).", 400);
99
+ return platform.tenant('PUT', project, `/bpm/connector-credentials/${id}`, { environment, body: credential });
100
+ }));
101
+ server.registerTool('connector_credential_delete', {
102
+ title: 'Kasa kimliğini sil',
103
+ description: 'Kimliği siler (DELETE bpm/connector-credentials/{id}). Bir süreç düğümü kullanıyorsa 422 ReferencedByProcess, bir olay ya da e-posta kaynağı kullanıyorsa 400 RowHasExistingRelation döner; önce başvuruları değiştirin.',
104
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid },
105
+ annotations: destructive
106
+ }, handle(config, async ({ project, environment, id }) => {
107
+ assertProcessNotProduction('connector_credential_delete', environment, config);
108
+ return platform.tenant('DELETE', project, `/bpm/connector-credentials/${id}`, { environment });
109
+ }));
110
+ server.registerTool('process_event_source_list', {
111
+ title: 'Olay kaynaklarını listele',
112
+ description: 'Olay kaynaklarını listeler (GET bpm/event-sources): ad, tür, adres, mesaj adı, korelasyon anahtarı ifadesi, tampon süresi, etkinlik ve son olay zamanı.',
113
+ inputSchema: { project: projectParam, environment: environmentParam },
114
+ annotations: readOnly
115
+ }, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/bpm/event-sources', { environment })));
116
+ server.registerTool('process_event_source_create', {
117
+ title: 'Olay kaynağı yaz',
118
+ description: "Dış olayı BPM mesajına çeviren kaynak oluşturur (POST bpm/event-sources) ya da id verilirse tam gövdeyle günceller (PUT …/{id}). Olay girişi process_trigger { kind: 'event-source', name, eventId, payload }: payload korelasyon anahtarı Jint ifadesiyle (ör. 'payload.siparisNo') mesaja dönüşür, aynı eventId ikinci kez işlenmez. kind http taşımadan bağımsızdır; kafka/service-bus tüketicisi henüz yok (NuGet), rabbitmq dinleyicisi borç.",
119
+ inputSchema: {
120
+ project: projectParam,
121
+ environment: environmentParam,
122
+ id: guid.optional().describe('verilirse güncelleme'),
123
+ name: z.string().min(1).max(100),
124
+ kind: z.enum(eventSourceKinds),
125
+ address: z.string().max(500).optional().describe('konu/kuyruk adresi'),
126
+ credentialRef: z.string().max(100).optional().describe('kasadaki kaydın adı (connector_credential_list); olmayan ad 404'),
127
+ messageName: z.string().min(1).max(100),
128
+ correlationKey: z.string().max(500).optional().describe("Jint ifadesi, ör. 'payload.siparisNo'"),
129
+ bufferSeconds: z.number().int().min(0).max(86400).optional(),
130
+ isActive: z.boolean().optional()
131
+ },
132
+ annotations: writes
133
+ }, handle(config, async ({ project, environment, id, ...source }) => {
134
+ assertProcessNotProduction('process_event_source_create', environment, config);
135
+ return id
136
+ ? platform.tenant('PUT', project, `/bpm/event-sources/${id}`, { environment, body: source })
137
+ : platform.tenant('POST', project, '/bpm/event-sources', { environment, body: source });
138
+ }));
139
+ server.registerTool('process_event_source_delete', {
140
+ title: 'Olay kaynağını sil',
141
+ description: 'Olay kaynağını siler (DELETE bpm/event-sources/{id}); o ada gelen olaylar 404 alır.',
142
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid },
143
+ annotations: destructive
144
+ }, handle(config, async ({ project, environment, id }) => {
145
+ assertProcessNotProduction('process_event_source_delete', environment, config);
146
+ return platform.tenant('DELETE', project, `/bpm/event-sources/${id}`, { environment });
147
+ }));
148
+ server.registerTool('process_mail_source_list', {
149
+ title: 'E-posta kaynaklarını listele',
150
+ description: 'E-posta kaynaklarını listeler (GET bpm/mail-sources): tür (imap | graph), sunucu, posta kutusu, klasör, kurallar, son UID ve son yoklama zamanı.',
151
+ inputSchema: { project: projectParam, environment: environmentParam },
152
+ annotations: readOnly
153
+ }, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/bpm/mail-sources', { environment })));
154
+ server.registerTool('process_mail_source_create', {
155
+ title: 'E-posta kaynağı yaz',
156
+ description: "Gelen e-postayı kurallarla BPM mesajına çeviren kaynak oluşturur (POST bpm/mail-sources) ya da id verilirse günceller (PUT …/{id}). Kural { subjectPattern, fromPattern (regex), messageName, correlationKey (Jint; mail.subject, mail.from, match.groups) }; ekler files'a yazılır, aynı Message-ID ikinci kez işlenmez. credentialRef kasadaki bir kaydın adıdır (connector_credential_list): kayıtta kimliğe çözülür, olmayan ad 404 (connector-credential: <ad>) döner; kasa kaydının adı sonradan değişirse kaynak yeni adı gösterir. imap kimliği 'imap' bağlayıcısının kasa kaydıdır (basic), graph kimliği 'microsoft-graph' (oauth2-client). Zamanlanmış yoklama yok: process_trigger { kind: 'mail-source', sourceId }.",
157
+ inputSchema: {
158
+ project: projectParam,
159
+ environment: environmentParam,
160
+ id: guid.optional().describe('verilirse güncelleme'),
161
+ name: z.string().min(1).max(100),
162
+ kind: z.enum(mailSourceKinds),
163
+ host: z.string().max(200).optional(),
164
+ port: z.number().int().min(1).max(65535).optional(),
165
+ useSsl: z.boolean().optional(),
166
+ mailbox: z.string().max(200).optional(),
167
+ folder: z.string().max(200).optional(),
168
+ credentialRef: z.string().min(1).max(100).describe('kasadaki kaydın adı (connector_credential_list); olmayan ad 404'),
169
+ rules: z.array(z.object({
170
+ subjectPattern: z.string().max(500).optional(),
171
+ fromPattern: z.string().max(500).optional(),
172
+ messageName: z.string().min(1).max(100),
173
+ correlationKey: z.string().max(500).optional()
174
+ })).min(1).max(50),
175
+ isActive: z.boolean().optional()
176
+ },
177
+ annotations: writes
178
+ }, handle(config, async ({ project, environment, id, ...source }) => {
179
+ assertProcessNotProduction('process_mail_source_create', environment, config);
180
+ return id
181
+ ? platform.tenant('PUT', project, `/bpm/mail-sources/${id}`, { environment, body: source })
182
+ : platform.tenant('POST', project, '/bpm/mail-sources', { environment, body: source });
183
+ }));
184
+ server.registerTool('process_mail_source_delete', {
185
+ title: 'E-posta kaynağını sil',
186
+ description: 'E-posta kaynağını siler (DELETE bpm/mail-sources/{id}).',
187
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid },
188
+ annotations: destructive
189
+ }, handle(config, async ({ project, environment, id }) => {
190
+ assertProcessNotProduction('process_mail_source_delete', environment, config);
191
+ return platform.tenant('DELETE', project, `/bpm/mail-sources/${id}`, { environment });
192
+ }));
193
+ }
@@ -75,7 +75,7 @@ export function registerDatasourceTools(server, platform) {
75
75
  inputSchema: { project: projectParam, environment: environmentParam, ...connectionInput },
76
76
  annotations: writes
77
77
  }, handle(config, async ({ project, environment, ...body }) => {
78
- const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'datasource', body, { operation: 'create' }));
78
+ const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'datasource', body, { operation: 'create' }), false);
79
79
  return attachFindings(await platform.tenant('POST', project, '/datasources', { environment, body }), findings);
80
80
  }));
81
81
  server.registerTool('datasource_update', {
@@ -84,7 +84,7 @@ export function registerDatasourceTools(server, platform) {
84
84
  inputSchema: { project: projectParam, environment: environmentParam, id: guid, ...connectionInput },
85
85
  annotations: updates
86
86
  }, handle(config, async ({ project, environment, id, ...body }) => {
87
- const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'datasource', body, { operation: 'update' }));
87
+ const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'datasource', body, { operation: 'update' }), false);
88
88
  return attachFindings(await platform.tenant('PUT', project, `/datasources/${id}`, { environment, body }), findings);
89
89
  }));
90
90
  server.registerTool('datasource_delete', {
@@ -118,7 +118,7 @@ export function registerDatasourceTools(server, platform) {
118
118
  }, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/datasources/resources', { environment })));
119
119
  server.registerTool('datasource_configuration_options', {
120
120
  title: 'Yapılandırma seçenekleri',
121
- description: "Datasource'un alan tipi kataloğunu döner: commonType başına dbType listesi, varsayılan tip, tipin kabul ettiği seçenek anahtarları (length/precision/collation/...) ve dönüştürülebilir tipler; ayrıca ilişki kuralları (onUpdate/onDelete) ve identity generation tipleri. VARSAYILAN YANIT ÖZETTİR (~5 KB): collation DEĞER listesi (816 kayıt, tam yanıtın %79'u) dışarıdadır — tipin collation kabul edip etmediği zaten options'ta yazar. Collation değerleri gerçekten gerekiyorsa includeCollations: true ile tam yanıtı isteyin (~45 KB).",
121
+ description: "Datasource'un alan tipi kataloğunu döner: commonType başına dbType listesi, varsayılan tip, tipin kabul ettiği seçenek anahtarları (length/precision/collation/...) ve dönüştürülebilir tipler; ayrıca ilişki kuralları (onUpdate/onDelete) ve identity generation tipleri. İlişki alanına yazarken kuralı SAYI olarak verin (`None` 0 · `Cascade` 1 · `SetNull` 2 · `SetDefault` 3 — `Rule` sırası): her backend sürümünde çalışır. Katalog adı listeler; `onDelete` adı (`Cascade`) 2026-09-27'den sonraki backend'de de kabul edilir, `onUpdate` adı hâlâ reddedilir (500). VARSAYILAN YANIT ÖZETTİR (~5 KB): collation DEĞER listesi (816 kayıt, tam yanıtın %79'u) dışarıdadır — tipin collation kabul edip etmediği zaten options'ta yazar. Collation değerleri gerçekten gerekiyorsa includeCollations: true ile tam yanıtı isteyin (~45 KB).",
122
122
  inputSchema: {
123
123
  project: projectParam,
124
124
  environment: environmentParam,
@@ -0,0 +1,206 @@
1
+ import { guid, projectParam, environmentParam, pagingParams, readOnly, writes, updates, destructive, microOps } from './common.js';
2
+ import { applyPolicyMode, attachFindings, PolicyBlockError } from '../knowledge/policy.js';
3
+ import { assertInline, writeLocalFile } from './bpmGovernance.js';
4
+ import { assertProcessNotProduction, dataOf } from './bpm.js';
5
+ import { unmappedMembers, withUnmappedMembers } from '../knowledge/schemaGuard.js';
6
+ import { resolvePatchOperations } from '../knowledge/outlines.js';
7
+ import { decisionFindings } from '../knowledge/decision.js';
8
+ import { withNormalization } from '../knowledge/normalize.js';
9
+ import { PlatformApiError } from '../platform/errors.js';
10
+ import { handle } from '../platform/responses.js';
11
+ import { readFile } from 'node:fs/promises';
12
+ import fastJsonPatch from 'fast-json-patch';
13
+ import { resolve } from 'node:path';
14
+ import { z } from 'zod';
15
+ const maxInlineXmlBytes = 256_000;
16
+ const maxDmnBytes = 5_000_000;
17
+ const decisionParam = z.record(z.unknown())
18
+ .describe("Karar modeli: { slug, name, kind: table | literal, hitPolicy: unique | any | first | priority | collect | rule-order | output-order, aggregation?, inputs[{ id, label, expression, typeRef, allowedValues }], outputs[{ id, name, typeRef, allowedValues, defaultOutputEntry }], rules[{ id, description, inputEntries[], outputEntries[] }], requires[], inputData[], literalExpression?, typeRef? }. Hücreler FEEL; '-' joker. Ayrıntı platform_guide('decision').");
19
+ const policyOverrideParam = z.boolean().optional()
20
+ .describe("true: politika block bulgularını warn'a indirir (bilinçli istisna; yanıtta işaretlenir)");
21
+ const patchOperationsParam = z.array(z.record(z.unknown())).min(1)
22
+ .describe("RFC 6902 JSON Patch işlemleri, yollar karar modeline göre. Kural ve sütun hedeflerken İNDEKS YERİNE SEÇİCİ: { op: 'replace', path: '/rules[id=buyuk]/outputEntries/0', value: '3' }; yeni kural '/rules/-'.");
23
+ function lintDecision(config, decision, policyOverride) {
24
+ if (config.policyMode === 'off')
25
+ return [];
26
+ const findings = applyPolicyMode(config, decisionFindings(decision), policyOverride === true);
27
+ const blocking = findings.filter(finding => finding.severity === 'block');
28
+ if (blocking.length > 0)
29
+ throw new PolicyBlockError(blocking);
30
+ return findings;
31
+ }
32
+ export function registerDecisionTools(server, platform) {
33
+ const config = platform.config;
34
+ server.registerTool('decision_list', {
35
+ title: 'Kararları listele',
36
+ description: "DMN karar tablolarını ve literal kararları listeler (GET bpm/decisions): slug, ad, kind, hitPolicy, aktif ve taslak sürüm numarası. Süreçte 'decision' düğümü decisionSlug ile başvurur.",
37
+ inputSchema: { project: projectParam, environment: environmentParam, searchTerm: z.string().max(200).optional(), applicationId: guid.optional(), ...pagingParams },
38
+ annotations: readOnly
39
+ }, handle(config, ({ project, environment, ...query }) => platform.tenant('GET', project, '/bpm/decisions', { environment, query })));
40
+ server.registerTool('decision_get', {
41
+ title: 'Kararı getir',
42
+ description: "Kararı getirir (GET bpm/decisions/{id}): decision güncel model (taslak varsa taslak), activeDecision yayındaki model, versions[] (draft → active → retiring → retired). Değerlendirme için decision_preview.",
43
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid },
44
+ annotations: readOnly
45
+ }, handle(config, ({ project, environment, id }) => platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment })));
46
+ server.registerTool('decision_create', {
47
+ title: 'Karar oluştur',
48
+ description: "Yeni karar yazar (POST bpm/decisions; taslak sürüm). İlk kullanımdan önce platform_guide('decision') okuyun. Gateway yazmadan önce denetler: DMN-001 (unique tabloda aynı girdiyi eşleyen iki kural, block) ve DMN-002 (FEEL alt kümesinde olmayan işlev, warn — backend yine de yazımı 422 ile reddeder). Yayın decision_publish; süreçte kullanım 'decision' düğümü { decisionSlug, input, output }.",
49
+ inputSchema: { project: projectParam, environment: environmentParam, applicationId: guid.optional(), decision: decisionParam, policyOverride: policyOverrideParam },
50
+ annotations: writes
51
+ }, handle(config, async ({ project, environment, applicationId, decision, policyOverride }) => {
52
+ assertProcessNotProduction('decision_create', environment, config);
53
+ const findings = lintDecision(config, decision, policyOverride);
54
+ const saved = await platform.tenant('POST', project, '/bpm/decisions', { environment, body: { applicationId, decision } });
55
+ return withUnmappedMembers(attachFindings(dataOf(saved), findings), unmappedMembers('CreateDecisionCommand', { applicationId, decision }));
56
+ }));
57
+ server.registerTool('decision_update', {
58
+ title: 'Kararı güncelle',
59
+ description: "Kararın taslağını tam modelle yazar (PUT bpm/decisions/{id}; taslak yoksa açılır) ya da retireVersion ile aktif/emekliye ayrılan sürümü emekliye ayırır (POST …/versions/{n}/retire). İkisinden biri. Backend sürüm denetimi yapmaz: aynı kararı iki ajan yazıyorsa son yazan kazanır; hedefli değişiklik için decision_patch. Yayından sonra slug değişmez. DMN-001/002 denetimi decision_create ile aynı.",
60
+ inputSchema: {
61
+ project: projectParam,
62
+ environment: environmentParam,
63
+ id: guid,
64
+ decision: decisionParam.optional(),
65
+ retireVersion: z.number().int().min(1).optional().describe('emekliye ayrılacak sürüm numarası (decision yerine)'),
66
+ policyOverride: policyOverrideParam
67
+ },
68
+ annotations: updates
69
+ }, handle(config, async ({ project, environment, id, decision, retireVersion, policyOverride }) => {
70
+ assertProcessNotProduction('decision_update', environment, config);
71
+ if (Boolean(decision) === (retireVersion !== undefined))
72
+ throw new PlatformApiError("decision_update: 'decision' ya da 'retireVersion' — yalnız biri (istek gönderilmedi).", 400);
73
+ if (retireVersion !== undefined)
74
+ return dataOf(await platform.tenant('POST', project, `/bpm/decisions/${id}/versions/${retireVersion}/retire`, { environment }));
75
+ const findings = lintDecision(config, decision, policyOverride);
76
+ return withUnmappedMembers(attachFindings(dataOf(await platform.tenant('PUT', project, `/bpm/decisions/${id}`, { environment, body: { decision } })), findings), unmappedMembers('UpdateDecisionCommand', { decision }));
77
+ }));
78
+ server.registerTool('decision_patch', {
79
+ title: 'Karara patch uygula',
80
+ description: "Tam modeli bağlama almadan hedefli değişiklik: gateway güncel modeli okur (GET), seçicileri (/rules[id=x], /inputs[id=x]) çözer, yamayı yerelde uygular, DMN-001/002 denetiminden geçirir ve tam modeli taslağa yazar (PUT). Backend sürüm denetimi yok: okuma ile yazma arasında başka yazan olursa değişikliği ezilir. Yanıt { patchTargets, decision }.",
81
+ inputSchema: {
82
+ project: projectParam,
83
+ environment: environmentParam,
84
+ id: guid,
85
+ operations: patchOperationsParam.optional(),
86
+ ops: patchOperationsParam.optional().describe("'operations' ile aynı alan (eşanlamlı)"),
87
+ policyOverride: policyOverrideParam
88
+ },
89
+ annotations: updates
90
+ }, handle(config, async ({ project, environment, id, operations: givenOperations, ops, policyOverride }) => {
91
+ assertProcessNotProduction('decision_patch', environment, config);
92
+ const operations = microOps('decision_patch', ops, givenOperations);
93
+ const current = dataOf(await platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment }));
94
+ const model = structuredClone((current.decision ?? {}));
95
+ const resolved = resolvePatchOperations(model, operations, 'decision_get');
96
+ let patched;
97
+ try {
98
+ patched = fastJsonPatch.applyPatch(model, resolved.operations, true, false).newDocument;
99
+ }
100
+ catch (error) {
101
+ throw new PlatformApiError(`decision_patch: yama uygulanamadı — ${error instanceof Error ? error.message : String(error)} (istek gönderilmedi). Yolları decision_get çıktısına göre kurun.`, 400);
102
+ }
103
+ const findings = lintDecision(config, patched, policyOverride);
104
+ const saved = dataOf(await platform.tenant('PUT', project, `/bpm/decisions/${id}`, { environment, body: { decision: patched } }));
105
+ return withNormalization(attachFindings({ patchTargets: resolved.targets, decision: saved.decision ?? patched }, findings), resolved.notes);
106
+ }));
107
+ server.registerTool('decision_delete', {
108
+ title: 'Kararı sil',
109
+ description: "Kararı ve bütün sürümlerini siler (DELETE bpm/decisions/{id}). Bir süreç tanımı decisionSlug ile başvuruyorsa 422 ReferencedByProcess, başka karar requires ile başvuruyorsa 422 DecisionInvalid.",
110
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid },
111
+ annotations: destructive
112
+ }, handle(config, async ({ project, environment, id }) => {
113
+ assertProcessNotProduction('decision_delete', environment, config);
114
+ return platform.tenant('DELETE', project, `/bpm/decisions/${id}`, { environment });
115
+ }));
116
+ server.registerTool('decision_clone', {
117
+ title: 'Kararı klonla',
118
+ description: 'Kararın güncel modelinden yeni slug ile taslak kopya oluşturur (GET + POST bpm/decisions). variable verilmemişse slug\'dan türetildiği için üst kararlar yeni adı görür; requires başvuruları kopyalanır.',
119
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid, slug: z.string().min(1).max(100) },
120
+ annotations: writes
121
+ }, handle(config, async ({ project, environment, id, slug }) => {
122
+ assertProcessNotProduction('decision_clone', environment, config);
123
+ const current = dataOf(await platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment }));
124
+ const decision = { ...structuredClone((current.decision ?? {})), slug };
125
+ return dataOf(await platform.tenant('POST', project, '/bpm/decisions', { environment, body: { applicationId: current.applicationId ?? undefined, decision } }));
126
+ }));
127
+ server.registerTool('decision_preview', {
128
+ title: 'Kararı değerlendir (kuru)',
129
+ description: "Kararı verilen girdilerle YAN ETKİSİZ değerlendirir (POST bpm/decisions/{id}/evaluate; transaction açmaz, defter yazmaz — tablo tasarımını denemenin yolu, platform_guide('decision') §Deneme): version verilmezse taslak (yoksa aktif). DRD'deki alt kararlar (requires) önce değerlendirilir. Yanıt { value, outputs, matchedRules, decisions[] (her karar için inputs, value, matchedRules) }. unique'te birden çok kural eşleşirse 422 DecisionHitPolicyViolated (eşleşen kural kimlikleriyle); hiçbiri eşleşmezse defaultOutputEntry ya da null.",
130
+ inputSchema: {
131
+ project: projectParam,
132
+ environment: environmentParam,
133
+ id: guid,
134
+ inputs: z.record(z.unknown()).describe("girdi adları → değerler, ör. { tutar: 180000, kategori: 'makine' }; tarih '2026-09-17', süre 'P3D'"),
135
+ version: z.number().int().min(1).optional()
136
+ },
137
+ annotations: readOnly
138
+ }, handle(config, ({ project, environment, id, inputs, version }) => platform.tenant('POST', project, `/bpm/decisions/${id}/evaluate`, { environment, query: { version }, body: { inputs } })));
139
+ server.registerTool('decision_publish', {
140
+ title: 'Kararı yayınla',
141
+ description: "Taslağı aktif sürüm yapar (POST bpm/decisions/{id}/publish); önceki aktif sürüm retiring olur. requires içindeki her kararın aktif sürümü olmalı (422 DecisionUnknown) ve döngü olmamalı (422 DecisionInvalid). Gateway yayından önce taslağı DMN-001/002 ile denetler. production hedefi durur (BPM-001).",
142
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid, policyOverride: policyOverrideParam },
143
+ annotations: writes
144
+ }, handle(config, async ({ project, environment, id, policyOverride }) => {
145
+ assertProcessNotProduction('decision_publish', environment, config);
146
+ const current = dataOf(await platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment }));
147
+ const findings = lintDecision(config, (current.decision ?? {}), policyOverride);
148
+ return attachFindings(dataOf(await platform.tenant('POST', project, `/bpm/decisions/${id}/publish`, { environment })), findings);
149
+ }));
150
+ server.registerTool('decision_dmn_get', {
151
+ title: 'Kararı DMN 1.3 XML olarak dışa aktar',
152
+ description: "Kararı ve requires ile bağlı alt kararlarını DMN 1.3 XML'e çevirir (GET bpm/decisions/{id}/dmn; zeyrek: uzantısı kaynak ve kategori bilgisini taşır). version verilmezse taslak (yoksa aktif). Yanıt { decisionId, versionNumber, state, sizeBytes, xml }; 256 KB üstü için outPath verin.",
153
+ inputSchema: {
154
+ project: projectParam,
155
+ environment: environmentParam,
156
+ id: guid,
157
+ version: z.number().int().min(1).optional(),
158
+ outPath: z.string().min(1).optional().describe('verilirse XML bu yerel yola yazılır ve yanıt yalnız özet döner')
159
+ },
160
+ annotations: readOnly
161
+ }, handle(config, async ({ project, environment, id, version, outPath }) => {
162
+ const response = await platform.tenantWithHeaders('GET', project, `/bpm/decisions/${id}/dmn`, { environment, query: { version }, expectBinary: true });
163
+ const payload = response.body;
164
+ const xml = payload.bytes.toString('utf8').replace(/^\uFEFF/, '');
165
+ const summary = {
166
+ decisionId: id,
167
+ versionNumber: Number(response.headers['x-decision-version']) || null,
168
+ state: response.headers['x-decision-version-state'] ?? null,
169
+ sizeBytes: payload.bytes.byteLength
170
+ };
171
+ if (outPath)
172
+ return { ...summary, path: await writeLocalFile('decision_dmn_get', outPath, xml) };
173
+ const inline = { ...summary, xml };
174
+ assertInline('decision_dmn_get', config, inline);
175
+ return inline;
176
+ }));
177
+ server.registerTool('decision_dmn_update', {
178
+ title: 'DMN 1.3 XML içe aktar',
179
+ description: "DMN 1.3 XML'deki kararları içe aktarır (POST bpm/decisions/import-dmn): slug'ı (decision id) mevcut karar taslağına yazılır, yoksa yeni karar oluşur; DRD bilgi gereksinimleri requires olur. xml (≤ 256 KB) ya da filePath (≤ 5 MB) — biri. Camunda/Trisotech tablolarında desteklenmeyen FEEL işlevi değerlendirmede 422 ExpressionInvalid döner; içe aktardıktan sonra decision_preview ile deneyin. DTD/dış varlık içeren XML 400.",
180
+ inputSchema: {
181
+ project: projectParam,
182
+ environment: environmentParam,
183
+ applicationId: guid.optional(),
184
+ xml: z.string().min(1).max(maxInlineXmlBytes).optional(),
185
+ filePath: z.string().min(1).optional().describe('yerel .dmn dosyası')
186
+ },
187
+ annotations: updates
188
+ }, handle(config, async ({ project, environment, applicationId, xml, filePath }) => {
189
+ assertProcessNotProduction('decision_dmn_update', environment, config);
190
+ if (Boolean(xml) === Boolean(filePath))
191
+ throw new PlatformApiError("decision_dmn_update: 'xml' ya da 'filePath' — yalnız biri (istek gönderilmedi).", 400);
192
+ let content = xml ?? '';
193
+ if (filePath) {
194
+ try {
195
+ content = await readFile(resolve(filePath), 'utf8');
196
+ }
197
+ catch (error) {
198
+ throw new PlatformApiError(`decision_dmn_update: dosya okunamadı — ${resolve(filePath)} (${error instanceof Error ? error.message : String(error)}). Yol gateway sürecinin çalıştığı makineye göre çözülür (istek gönderilmedi).`, 400);
199
+ }
200
+ }
201
+ content = content.replace(/^/, '');
202
+ if (Buffer.byteLength(content, 'utf8') > maxDmnBytes)
203
+ throw new PlatformApiError(`decision_dmn_update: XML en çok ${maxDmnBytes} B (istek gönderilmedi).`, 413);
204
+ return platform.tenant('POST', project, '/bpm/decisions/import-dmn', { environment, body: { applicationId, xml: content } });
205
+ }));
206
+ }
@@ -9,7 +9,7 @@ export function registerDependencyTools(server, platform) {
9
9
  inputSchema: {
10
10
  project: projectParam,
11
11
  environment: environmentParam,
12
- module: z.string().describe('Modül adı: entity | field | microservice | workflow | query | view | dataTransferObject | global-function (fonksiyon, iki kaynak: onu çağıran flow/workflow listesi; flow düğümü sahibini hostModule/hostId/hostName, bağlandığı komponenti ve olayı componentName/eventName/eventTitle ile taşır) vb. (platform Module enum değeri)'),
12
+ module: z.string().describe('Modül adı: entity | field | microservice | workflow | query | view | dataTransferObject | process-definition (depends: tanımın başvurduğu entity/workflow/sayfa/DTO/rol/pozisyon/birim/takvim/karar/alt süreç; depended: onu alt süreç olarak çağıran tanımlar — entity ve workflow grafiği de kullanan tanımları gösterir, silmeleri 422 ReferencedByProcess) | global-function (fonksiyon, iki kaynak: onu çağıran flow/workflow listesi; flow düğümü sahibini hostModule/hostId/hostName, bağlandığı komponenti ve olayı componentName/eventName/eventTitle ile taşır) vb. (platform Module enum değeri)'),
13
13
  id: guid
14
14
  },
15
15
  annotations: readOnly
@@ -4,13 +4,13 @@ export function registerDeploymentTools(server, platform) {
4
4
  const config = platform.config;
5
5
  server.registerTool('deployment_start', {
6
6
  title: 'Deployment başlat',
7
- description: 'Projeyi kaynak environment\'tan hedef environment\'a deploy eder. Asenkron bir saga\'dır: sonuç bu yanıtta bitmez, deployment_status ile izleyin. Environment id\'lerini project_get çıktısından alın.',
7
+ description: 'Projeyi kaynak environment\'tan hedef environment\'a deploy eder. Asenkron bir saga\'dır: sonuç bu yanıtta bitmez, deployment_status ile izleyin. Environment id\'lerini project_get çıktısından alın. BPM: süreç tanımları ve iş takvimleri taşınır — hedefte farklı aktif model yeni sürüm olarak yayınlanır (production\'da gelişte aktif), hedefin uyarlaması korunur; uyarlama, örnek, görev ve defter taşınmaz; kaynakta olmayan tanım silinir, açık örneği varsa emekliye ayrılır.',
8
8
  inputSchema: { projectId: guid, sourceEnvironmentId: guid, targetEnvironmentId: guid },
9
9
  annotations: writes
10
10
  }, handle(config, ({ projectId, ...body }) => platform.org('POST', `/deployments/${projectId}/deploy`, { body })));
11
11
  server.registerTool('deployment_status', {
12
12
  title: 'Deployment durumu',
13
- description: "Projenin son deployment durumunu döner. 'projectId' ZORUNLUDUR (project_list/project_get'ten alın) — verilmezse çağrı MCP şema katmanında reddedilir, platforma hiç gitmez. Hiç deployment yapılmamış projede yanıt BOŞ gelir; o durumda tool 'hiç deployment kaydı yok' bilgisini açıkça döner, yani boş yanıtı 'tool çalışmadı' diye okumayın.",
13
+ description: "Projenin son deployment durumunu döner. 'projectId' ZORUNLUDUR (project_list/project_get'ten alın) — verilmezse çağrı MCP şema katmanında reddedilir, platforma hiç gitmez. Hiç deployment yapılmamış projede yanıt BOŞ gelir; o durumda tool 'hiç deployment kaydı yok' bilgisini açıkça döner, yani boş yanıtı 'tool çalışmadı' diye okumayın. Durum satırı modül başına ayrılmaz: süreç tanımları ve iş takvimleri sayfa ve workflow'lardan sonra aynı saga adımında aktarılır; hedefte çalışamayan (eksik workflow/entity/rol) tanım aktarımı DefinitionInvalid ile düşürür.",
14
14
  inputSchema: { projectId: guid },
15
15
  annotations: readOnly
16
16
  }, handle(config, async ({ projectId }) => {
@@ -1,13 +1,16 @@
1
1
  import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, boundEventOps, stripGatewayEventFields, staleSetterWarnings, normalizeSchemaOps, validationNote, componentDefaultsNote, replacePropNote, flexSizeWarnings, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, verticalGapWarnings, withNormalization, FLEX_LAYOUT_PROP_NAMES } from '../knowledge/normalize.js';
2
- import { opsParam, writeViewParam, outlineWriteResponse, unknownEventOps, collectTypes, simulateLayoutOps, removeNodeFromTree, planEventRemovals, planResizes, planPropTypes, assertOpBodies } from './schemaOps.js';
2
+ import { opsParam, writeViewParam, outlineWriteResponse, unknownEventOps, collectTypes, styleTargetTypesFrom, simulateLayoutOps, removeNodeFromTree, planEventRemovals, planResizes, planPropTypes, assertOpBodies, applySkeletonOps, reshapesSkeleton } from './schemaOps.js';
3
3
  import { guid, projectParam, environmentParam, updates, microOps } from './common.js';
4
4
  import { fetchHost, hostPath } from './screens.js';
5
5
  import { assertScreenWriteGuards, screenCatalogNotes } from './screenWrite.js';
6
6
  import { emptyWriteDiff, schemaOpDrops, withWriteDiff } from '../platform/writeDiff.js';
7
7
  import { fetchComponentEventNames } from './components.js';
8
8
  import { PlatformApiError } from '../platform/errors.js';
9
+ import { connectDataOpIssues, connectedPropKeys } from '../knowledge/connectDataDefinition.js';
9
10
  import { handle } from '../platform/responses.js';
10
11
  import { slotWarning } from './layouts.js';
12
+ import { applicationTypeField, resolveProfile } from '../knowledge/platform/resolve.js';
13
+ import { boundFlowSteps, layoutPatchWarnings, screenProfileWarnings } from './profileWrite.js';
11
14
  import { z } from 'zod';
12
15
  const HOSTS = {
13
16
  layout: {
@@ -58,8 +61,6 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
58
61
  const resizeOps = allOps.filter(entry => entry.op === 'resize_component');
59
62
  const propTypeOps = allOps.filter(entry => entry.op === 'set_prop_type');
60
63
  const opRecords = allOps.filter(entry => !['remove_event', 'resize_component', 'set_prop_type'].includes(String(entry.op)));
61
- const normalized = normalizeSchemaOps(opRecords);
62
- assertOpBodies(opRecords, propTypeOps);
63
64
  const record = await fetchHost(platform, host, project, environment, applicationId, id);
64
65
  // Platform ucu kaydın türüne bakmaz: sıradan bir komponentin id'si verilirse kataloğundaki
65
66
  // tanımın yanına bir şema yazılırdı.
@@ -68,6 +69,17 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
68
69
  }
69
70
  const nodes = (record[spec.tree] ?? []);
70
71
  const events = host === 'layout' ? record.events : undefined;
72
+ // Normalizasyon kayıttan SONRA koşar: stil anahtarı çevirisi hedefin komponent TİPİNE bakar
73
+ // (TB-129, table.style.th/td kebab-case kalır) ve tip yalnız okunan ağaçta var. Gövde hataları
74
+ // bu yüzden bir okuma sonrasında rapor edilir; karar hiç değişmez, yalnız sıra değişti.
75
+ const normalized = normalizeSchemaOps(opRecords, styleTargetTypesFrom(opRecords, nodes));
76
+ assertOpBodies(opRecords, propTypeOps);
77
+ // CD-005 layout ve widget host'unda da: bağlı prop'u (iç içe yol dahil) ezen yazma ve bağlı olmayan prop'ta
78
+ // remove_connect_data okunan ağaca bakarak reddedilir (gövde denetimi assertOpBodies'te koştu).
79
+ const connectedProps = connectedPropKeys(nodes);
80
+ const connectionIssues = opRecords.flatMap(entry => connectDataOpIssues(entry, connectedProps).map(issue => `${issue.code} — ${issue.message}`));
81
+ if (connectionIssues.length > 0)
82
+ throw new PlatformApiError(`Connect Data op gövdesi geçersiz (istek gönderilmedi): ${connectionIssues.join(' · ')}`, 400);
71
83
  if (opRecords.some(entry => entry.op === 'set_event' || entry.op === 'add_event')) {
72
84
  const bound = boundEventOps(nodes, opRecords);
73
85
  if (bound.length > 0)
@@ -85,7 +97,8 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
85
97
  if (deletedFlows.length > 0 && allowFlowDeletion !== true)
86
98
  throw new PlatformApiError(orphanedFlowMessage(deletedFlows), 400);
87
99
  const added = opRecords.filter(entry => entry.op === 'add_component').map(entry => entry.component);
88
- assertScreenWriteGuards(spec.kind, { schema: added });
100
+ const resolved = await resolveProfile(platform, applicationId);
101
+ assertScreenWriteGuards(spec.kind, { schema: added }, resolved.profile.platform);
89
102
  const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, added);
90
103
  const flowWarnings = opRecords.some(entry => entry.op === 'remove_component')
91
104
  ? [...orphanedFlowWarnings(nodes, events, opRecords), ...staleSetterWarnings(Array.isArray(record.flows) ? record.flows : [], opRecords, nodes)]
@@ -100,17 +113,28 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
100
113
  || (entry.op === 'replace_prop' && FLEX_LAYOUT_PROP_NAMES.has(String(entry.prop ?? ''))));
101
114
  const nested = simulatable ? nestedRepeaterNodes(simulated) : [];
102
115
  if (nested.length > 0)
103
- throw new PlatformApiError(nestedRepeaterMessage(nested), 400);
116
+ throw new PlatformApiError(nestedRepeaterMessage(nested, resolved.profile.platform), 400);
104
117
  const reshaped = simulatable || opRecords.some(entry => entry.op === 'remove_component');
118
+ const profileWarnings = await screenProfileWarnings(platform, resolved, project, environment, applicationId, {
119
+ kind: spec.kind,
120
+ ops: [...opRecords, ...propTypeOps],
121
+ savedNodes: nodes,
122
+ steps: await boundFlowSteps(platform, resolved, project, environment, host, applicationId, id, opRecords)
123
+ });
105
124
  const layoutWarnings = reshaped
106
125
  ? [
107
- ...verticalGapWarnings(simulated, spec.codes.gap, touched),
126
+ ...(resolved.profile.layout.blocksMeaningful ? verticalGapWarnings(simulated, spec.codes.gap, touched) : []),
108
127
  ...stringStyleWarning(stringStyleNodes(simulated)),
109
- ...inertFlexPropWarning(inertFlexPropNodes(simulated)),
128
+ ...(resolved.profile.layout.modes.has('grid') ? inertFlexPropWarning(inertFlexPropNodes(simulated)) : []),
110
129
  ...flexSizeWarnings(simulated, spec.codes.flexMismatch, spec.codes.flexInvalid),
111
130
  ...(host === 'layout' ? slotWarning(simulated) : [])
112
131
  ]
113
132
  : [];
133
+ if (host === 'layout' && reshapesSkeleton(opRecords)) {
134
+ const skeleton = structuredClone(simulated);
135
+ applySkeletonOps(skeleton, opRecords);
136
+ layoutWarnings.push(...layoutPatchWarnings(resolved, nodes, skeleton));
137
+ }
114
138
  const removedEvents = planEventRemovals(removeEventOps);
115
139
  const resized = resizeOps.length > 0 ? planResizes(nodes, resizeOps, spec.readTool) : { serverOps: [], applied: [], warnings: [] };
116
140
  const propTypes = propTypeOps.length > 0 ? planPropTypes(nodes, propTypeOps, spec.readTool) : { serverOps: [], applied: [] };
@@ -133,8 +157,9 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
133
157
  response.deletedFlows = deletedFlows;
134
158
  if (flowWarnings.length > 0)
135
159
  response.flowWarnings = flowWarnings;
136
- if (layoutWarnings.length > 0)
137
- response.layoutWarnings = layoutWarnings;
160
+ if (layoutWarnings.length > 0 || profileWarnings.length > 0)
161
+ response.layoutWarnings = [...layoutWarnings, ...profileWarnings];
162
+ Object.assign(response, applicationTypeField(resolved));
138
163
  const contentOps = opRecords.filter(entry => entry.op === 'add_component' || entry.op === 'replace_prop');
139
164
  let opDrops = emptyWriteDiff();
140
165
  if (contentOps.length > 0) {