@appaflytech/zeyrek-ai-mcp 0.0.37 → 0.0.40

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 (37) hide show
  1. package/dist/knowledge/componentCatalog.js +389 -149
  2. package/dist/knowledge/componentEvents.js +16 -8
  3. package/dist/knowledge/connectDataBind.js +10 -2
  4. package/dist/knowledge/expressionPrelude.js +1 -0
  5. package/dist/knowledge/mobileComponentCatalog.js +16 -4
  6. package/dist/knowledge/mobileComponentEvents.js +21 -1
  7. package/dist/knowledge/mobileStore.js +75 -0
  8. package/dist/knowledge/normalize.js +22 -5
  9. package/dist/knowledge/platform/mobile.js +1 -1
  10. package/dist/knowledge/platform/mobileRules.js +1 -1
  11. package/dist/knowledge/platform/web.js +1 -1
  12. package/dist/knowledge/rules.js +79 -2
  13. package/dist/knowledge/styleResolve.js +27 -7
  14. package/dist/knowledge/styleResolveNative.js +4 -2
  15. package/dist/knowledge/themeResolve.js +1 -1
  16. package/dist/knowledge/themeSchema.js +2 -1
  17. package/dist/observability/trace.js +7 -2
  18. package/dist/platform/secrets.js +50 -2
  19. package/dist/resources/guides/component.md +1 -1
  20. package/dist/resources/guides/merge.md +5 -4
  21. package/dist/resources/guides/microservice.md +1 -1
  22. package/dist/resources/guides/middleware.md +1 -1
  23. package/dist/resources/guides/mobile-publish.md +24 -0
  24. package/dist/resources/guides/mobile.md +22 -6
  25. package/dist/resources/guides/page.md +14 -7
  26. package/dist/resources/guides/theme.md +1 -0
  27. package/dist/resources/schema-fingerprint.json +3 -3
  28. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +2 -1
  29. package/dist/resources/schemas/OrganizationProjectDto.json +8 -0
  30. package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +59 -0
  31. package/dist/tools/applications.js +6 -3
  32. package/dist/tools/common.js +9 -5
  33. package/dist/tools/environments.js +1 -1
  34. package/dist/tools/flows.js +5 -1
  35. package/dist/tools/mobileStore.js +21 -5
  36. package/dist/tools/pages.js +3 -3
  37. package/package.json +1 -1
@@ -61,12 +61,12 @@ export const pagingParams = {
61
61
  isDescending: z.boolean().optional()
62
62
  };
63
63
  /**
64
- * Dal adı kuralı: `Environment` ctor'unun aynası, gerçek koruma backend'dedir. Ad yalnız
65
- * `environment_create`'i değil, `page_screenshot`'ın `/branch/{env}` şeridini de ilgilendirdiği
66
- * için tek yerde durur — iki kopya birbirinden ayrılırsa gateway kabul ettiği bir adı
67
- * görüntüleyemez hâle gelir.
64
+ * Dal adı kuralı: `Environment` ctor'unun birebir aynası (`/` ve `-` serbest, 3-31 karakter),
65
+ * gerçek koruma backend'dedir. Ad yalnız `environment_create`'i değil, `page_screenshot`'ın
66
+ * `/branch/{slug}` şeridini de ilgilendirdiği için tek yerde durur — iki kopya birbirinden
67
+ * ayrılırsa gateway kabul ettiği bir adı görüntüleyemez hâle gelir.
68
68
  */
69
- export const branchNamePattern = /^[a-z][a-z0-9_]{2,30}$/;
69
+ export const branchNamePattern = /^(?=.{3,31}$)[a-z][a-z0-9_-]*(\/[a-z0-9][a-z0-9_-]*)*$/;
70
70
  const reservedEnvironmentNames = new Set(['development', 'production', 'public', 'information_schema', 'dev', 'view', 'api', 'files', 'hubs']);
71
71
  /** Sabit ortamlar, url sözcükleri ve postgres şemaları: dal adı olamazlar */
72
72
  export function isReservedEnvironmentName(name) {
@@ -76,6 +76,10 @@ export function isReservedEnvironmentName(name) {
76
76
  export function isBranchName(name) {
77
77
  return branchNamePattern.test(name) && !isReservedEnvironmentName(name);
78
78
  }
79
+ /** Dalın adres parçası: her `/` → `-` (backend `Environment.Slug`); `feature/x` → `feature-x` */
80
+ export function branchSlug(name) {
81
+ return name.replace(/\//g, '-');
82
+ }
79
83
  export const readOnly = { readOnlyHint: true, openWorldHint: false };
80
84
  export const writes = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
81
85
  export const updates = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
@@ -4,7 +4,7 @@ import { handle } from '../platform/responses.js';
4
4
  import { z } from 'zod';
5
5
  /** Aggregate kuralının aynası (`Environment` ctor); gerçek koruma backend'dedir. Kural `common.ts`'te. */
6
6
  const branchName = z.string().regex(branchNamePattern)
7
- .describe("Dal adı: küçük harfle başlar, yalnız küçük harf/rakam/alt çizgi, 3-31 karakter. Bu ad PG şema adı olur.");
7
+ .describe("Dal adı: küçük harfle başlar; küçük harf/rakam/alt çizgi/tire ve '/' ile ayrılmış parçalar (ör. feature/odeme), 3-31 karakter. Bu ad PG şema adı olur ve değişmez; adres parçası (slug) '/' yerine '-' taşır.");
8
8
  function assertBranchName(name) {
9
9
  if (isReservedEnvironmentName(name)) {
10
10
  throw new PlatformApiError(`environment_create: '${name}' rezerve bir şema adı — dal adı olarak kullanılamaz. Başka bir ad seçin.`, 400);
@@ -515,10 +515,14 @@ export function registerFlowTools(server, platform) {
515
515
  };
516
516
  const authored = { steps: steps ?? [], errorSteps: errorSteps ?? [] };
517
517
  const normalized = [...normalizeFlowSteps(authored.steps), ...normalizeFlowSteps(authored.errorSteps)];
518
+ // Kurallar yalnız GÖNDERİLEN adımlara bakar (kayıtlı gövdeyi suçlamamak için); stepId
519
+ // benzersizliği ise birleşik akışta ölçülür: yalnız steps verilip kayıtlı errorSteps'le
520
+ // çakışan kimlik de platformda 500 verir.
518
521
  const findings = steps || errorSteps
519
522
  ? [
520
523
  ...enforcePolicy(evaluatePolicy(config, policyRules, 'flow', authored, { operation: 'update' }, policyOverride)),
521
- ...enforcePolicy(config.policyMode === 'off' ? [] : applyPolicyMode(config, connectedSetterFindings(authored.steps, authored.errorSteps, hostNodes(hostRecord)), policyOverride))
524
+ ...enforcePolicy(config.policyMode === 'off' ? [] : applyPolicyMode(config, connectedSetterFindings(authored.steps, authored.errorSteps, hostNodes(hostRecord)), policyOverride)),
525
+ ...enforcePolicy(evaluatePolicy(config, policyRules, 'flow', flow, { operation: 'update' }, policyOverride).filter(finding => finding.ruleId === 'FLOW-027'))
522
526
  ]
523
527
  : [];
524
528
  const parameterWarnings = [
@@ -7,7 +7,7 @@ import { PlatformApiError } from '../platform/errors.js';
7
7
  import { handle } from '../platform/responses.js';
8
8
  import { attachFindings, enforcePolicy, evaluatePolicy } from '../knowledge/policy.js';
9
9
  import { policyRules } from '../knowledge/rules.js';
10
- import { ASSET_KINDS, BUILD_ASSET_KINDS, DECLARATION_KEYS, DEVICE_CLASSES, MAX_ASSET_BYTES, ORIENTATIONS, RELEASE_STATUSES, SCREENSHOT_CAPTURE_DEVICES, SPLASH_RESIZE_MODES, USER_INTERFACE_STYLES, assetSlotProblem, changedStoreFields, mergeStoreSettings, permissionLaunchShellWarnings, permissionStoreBuildWarnings } from '../knowledge/mobileStore.js';
10
+ import { ASSET_KINDS, BUILD_ASSET_KINDS, DECLARATION_KEYS, DEVICE_CLASSES, MAX_ASSET_BYTES, ORIENTATIONS, RELEASE_STATUSES, SCREENSHOT_CAPTURE_DEVICES, SPLASH_RESIZE_MODES, USER_INTERFACE_STYLES, adsStoreWarnings, trackingDeclarationWarnings, assetSlotProblem, changedStoreFields, mergeStoreSettings, permissionLaunchShellWarnings, permissionStoreBuildWarnings } from '../knowledge/mobileStore.js';
11
11
  /**
12
12
  * Mobil mağaza yayınının ajan yolu (`plans/mobil-magaza-yayini` g-11, `plans/mobil-yayin-mcp` g-01):
13
13
  * gizli olmayan mağaza ayarı, mağaza görselleri, beyanlar ve derleme işi. Gizli bilgi (Apple/Google
@@ -70,7 +70,21 @@ const settingsPatch = z.object({
70
70
  phone: z.string().optional(),
71
71
  email: z.string().optional(),
72
72
  notes: z.string().optional()
73
- }).strict().optional().describe('App Review iletişim bilgisi. Demo hesabı parolası burada YOK — gizli bilgidir, Studio › Yayın › Hesaplar')
73
+ }).strict().optional().describe('App Review iletişim bilgisi. Demo hesabı parolası burada YOK — gizli bilgidir, Studio › Yayın › Hesaplar'),
74
+ ads: z.object({
75
+ enabled: z.boolean().optional(),
76
+ iosAppId: z.string().nullable().optional().describe('AdMob iOS uygulama kimliği: ca-app-pub-<16 hane>~<10 hane>'),
77
+ androidAppId: z.string().nullable().optional().describe('AdMob Android uygulama kimliği: ca-app-pub-<16 hane>~<10 hane>'),
78
+ testMode: z.boolean().optional().describe('true (varsayılan): Google test reklamları; yayınlanacak derlemeden önce kapatın'),
79
+ consentForm: z.boolean().optional().describe('true (varsayılan): AdMob UMP rıza formu reklamlardan önce sorulur'),
80
+ appOpenUnit: z.string().nullable().optional().describe('Açılış reklamı: format appOpen olan bir yerleşimin adı'),
81
+ units: z.array(z.object({
82
+ name: z.string().describe('Yerleşim adı ^[a-z][A-Za-z0-9]{0,39}$ — adBanner.unit ve ad-show.value bunu anar'),
83
+ format: z.string().describe('banner | interstitial | rewarded | rewardedInterstitial | appOpen'),
84
+ ios: z.string().nullable().optional().describe('iOS reklam birimi: ca-app-pub-<16 hane>/<10 hane>'),
85
+ android: z.string().nullable().optional().describe('Android reklam birimi: ca-app-pub-<16 hane>/<10 hane>')
86
+ }).strict()).optional().describe('Adlı reklam yerleşimleri (≤ 40); liste bütün olarak yazılır')
87
+ }).strict().optional().describe('Reklamlar (kök ADR 0012): açıkken izleme izni (tracking) derlemeye girer; manifest kabuk 0.4.0 ister')
74
88
  }).strict();
75
89
  /** Backend bir çağrıda en çok bu kadar satır döner (`MobileBuildService.LogPageLimit`); dolu sayfa = devamı var */
76
90
  const LOG_PAGE_LIMIT = 2000;
@@ -98,6 +112,7 @@ const assetSummary = (asset) => ({
98
112
  * liste döner (sıralama ve silme id ister). İçerik (bayt, url) hiç dönmez.
99
113
  */
100
114
  function storeSummary(store, detailAssets = false) {
115
+ const adsWarnings = adsStoreWarnings(isObject(store.settings) ? store.settings : {});
101
116
  const assets = Array.isArray(store.assets) ? store.assets.filter(isObject) : [];
102
117
  const slots = new Map();
103
118
  for (const asset of assets)
@@ -111,7 +126,8 @@ function storeSummary(store, detailAssets = false) {
111
126
  updatedAt: store.updatedAt,
112
127
  updatedBy: store.updatedBy,
113
128
  assets: detailAssets ? assets.map(assetSummary) : Object.fromEntries(slots),
114
- declarations: Object.fromEntries(Object.entries(declarations).map(([key, value]) => [key, isObject(value) && value.checked === true]))
129
+ declarations: Object.fromEntries(Object.entries(declarations).map(([key, value]) => [key, isObject(value) && value.checked === true])),
130
+ ...(adsWarnings.length > 0 ? { adsWarnings } : {})
115
131
  };
116
132
  }
117
133
  const list = (payload) => {
@@ -139,7 +155,7 @@ async function readDetail(platform, appId, section, scope) {
139
155
  });
140
156
  const counts = !(devices instanceof PlatformApiError) && isObject(devices.byPermission) ? devices.byPermission : {};
141
157
  const entries = Array.isArray(view.permissions) ? view.permissions.filter(isObject) : [];
142
- const warnings = [...permissionStoreBuildWarnings(entries, String(view.environment)), ...permissionLaunchShellWarnings(entries, view.shell)];
158
+ const warnings = [...permissionStoreBuildWarnings(entries, String(view.environment)), ...permissionLaunchShellWarnings(entries, view.shell), ...trackingDeclarationWarnings(entries)];
143
159
  return {
144
160
  permissions: {
145
161
  catalogVersion: view.catalogVersion,
@@ -310,7 +326,7 @@ export function registerMobileStoreTools(server, platform) {
310
326
  const config = platform.config;
311
327
  server.registerTool('mobile_store_get', {
312
328
  title: 'Mobil mağaza ayarını oku',
313
- description: "Mobil uygulamanın gizli olmayan mağaza ayarını döner (GET mobile-store/{appId}): kimlik (bundleIdentifier, androidPackage, scheme), sürüm ve sayaçlar, görünüm, izin metinleri, kipleri ve açılışta sorulanlar (permissions, permissionModes, launchPermissions), listing (dil başına mağaza metni), urls, apple, play, review; lockedFields (ilk derlemeden sonra değişmeyen alanlar), görsel yuvası başına sayı (assets: 'screenshot/tr/iphone69': 3) ve beyanlar (declarations: anahtar → işaretli mi). Kayıt hiç yazılmamışsa persisted:false ve VARSAYILANLAR döner (kaydedilmez). manifest:true derlemeye gidecek manifesti de ekler (manifest-preview; sayaçlar SIRADAKİ numara); üretilemiyorsa manifestError alan adıyla döner. detail ayrıntı bölümleri ekler: 'assets' görselleri id'li liste olarak döner (mobile_asset_update / mobile_asset_delete id ister), 'signing' uygulamanın kimlik bilgilerini (signing.app: iOS profili, Android keystore, harita anahtarı, demo hesabı) ve organizasyonun Apple/Google hesaplarını + sertifikalarını (signing.accounts), 'runners' çevrimiçi runner'ları, 'audit' son 20 gizli bilgi olayını (subject: hangi tür, kim, ne zaman, hangi iş), 'permissions' izin görünümünü (permissions.permissions[]: uygulamanın isteyebileceği her izin için mode, text/defaultText, usage — izni kullanan sayfa·bileşen ya da akış adımı (setter ile yazılan tetikleyici prop dahil), ilk 20 yer + usageCount, çağrının environment'ından; usageReadable false ise o ortam okunamamıştır ve boş usage 'kullanılmıyor' demek değildir —, build — mağaza derlemesi taşıyor mu ve neden; HER ZAMAN production'dan: build.usageCount production'daki kullanım, build.staticUsageCount onun yazılı (ifadesiz) kısmı —, devices — aktif cihazların izin durumu sayıları; missingFromStoreBuilds — o izni taşımayan son mağaza derlemeleri; shell.carriesPermissions false ise kipler ve kabuğun henüz taşımadığı izinler bir sonraki kabuk sürümüyle etkili olur; shell.carriesLaunchPermissions false ise açılışta sorulan izinler (askOnLaunch) o kabukta sorulmaz — permissionWarnings söyler). Gizli DEĞER hiçbir bölümde yoktur — yalnız tür, maskeli id ve meta (ekip, son kullanma); bir bölüm okunamazsa (uç hatası) <bölüm>Error döner, çağrı düşmez. Gizli bilgiyi EKLEMEK/DEĞİŞTİRMEK MCP'den yapılmaz — Studio › Yayın › Hesaplar.",
329
+ description: "Mobil uygulamanın gizli olmayan mağaza ayarını döner (GET mobile-store/{appId}): kimlik (bundleIdentifier, androidPackage, scheme), sürüm ve sayaçlar, görünüm, izin metinleri, kipleri ve açılışta sorulanlar (permissions, permissionModes, launchPermissions), listing (dil başına mağaza metni), urls, apple, play, review; lockedFields (ilk derlemeden sonra değişmeyen alanlar), görsel yuvası başına sayı (assets: 'screenshot/tr/iphone69': 3) ve beyanlar (declarations: anahtar → işaretli mi); settings.ads reklam ayarıdır (kök ADR 0012: enabled, App ID'ler, testMode, consentForm, appOpenUnit, units[] = adBanner.unit ve ad-show.value'nun andığı yerleşimler) ve reklam açıkken adsWarnings döner (MOB-026: test kipi, platformda birimsiz yerleşim, konsol beyanları). Kayıt hiç yazılmamışsa persisted:false ve VARSAYILANLAR döner (kaydedilmez). manifest:true derlemeye gidecek manifesti de ekler (manifest-preview; sayaçlar SIRADAKİ numara); üretilemiyorsa manifestError alan adıyla döner. detail ayrıntı bölümleri ekler: 'assets' görselleri id'li liste olarak döner (mobile_asset_update / mobile_asset_delete id ister), 'signing' uygulamanın kimlik bilgilerini (signing.app: iOS profili, Android keystore, harita anahtarı, demo hesabı) ve organizasyonun Apple/Google hesaplarını + sertifikalarını (signing.accounts), 'runners' çevrimiçi runner'ları, 'audit' son 20 gizli bilgi olayını (subject: hangi tür, kim, ne zaman, hangi iş), 'permissions' izin görünümünü (permissions.permissions[]: uygulamanın isteyebileceği her izin için mode, text/defaultText, usage — izni kullanan sayfa·bileşen ya da akış adımı (setter ile yazılan tetikleyici prop dahil), ilk 20 yer + usageCount, çağrının environment'ından; usageReadable false ise o ortam okunamamıştır ve boş usage 'kullanılmıyor' demek değildir —, build — mağaza derlemesi taşıyor mu ve neden; HER ZAMAN production'dan: build.usageCount production'daki kullanım, build.staticUsageCount onun yazılı (ifadesiz) kısmı —, devices — aktif cihazların izin durumu sayıları; missingFromStoreBuilds — o izni taşımayan son mağaza derlemeleri; shell.carriesPermissions false ise kipler ve kabuğun henüz taşımadığı izinler bir sonraki kabuk sürümüyle etkili olur; shell.carriesLaunchPermissions false ise açılışta sorulan izinler (askOnLaunch) o kabukta sorulmaz — permissionWarnings söyler). Gizli DEĞER hiçbir bölümde yoktur — yalnız tür, maskeli id ve meta (ekip, son kullanma); bir bölüm okunamazsa (uç hatası) <bölüm>Error döner, çağrı düşmez. Gizli bilgiyi EKLEMEK/DEĞİŞTİRMEK MCP'den yapılmaz — Studio › Yayın › Hesaplar.",
314
330
  inputSchema: {
315
331
  applicationId,
316
332
  manifest: z.boolean().optional().describe('true: derleme manifestinin önizlemesini de ekler'),
@@ -1,4 +1,4 @@
1
- import { guid, projectParam, environmentParam, pagingParams, asUserIdParam, readOnly, writes, updates, destructive, microOps, isBranchName } from './common.js';
1
+ import { guid, projectParam, environmentParam, pagingParams, asUserIdParam, readOnly, writes, updates, destructive, microOps, isBranchName, branchSlug } from './common.js';
2
2
  import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, boundEventOps, stripGatewayEventFields, staleSetterWarnings, lostSetterTargets, fillComponentNames, componentNameNote, normalizeComponentDefaults, normalizeSchemaOps, schemaOpValidationErrors, codePropTemplateErrors, addComponentIdErrors, missingBlocksNodes, assertAddComponentIds, assertComponentBlocks, validationNote, componentDefaultsNote, replacePropNote, ensurePageContainer, retargetRootAdds, rootAddsNote, flexSizeWarnings, spacingLayerWarnings, reorderSchemaBlocks, reorderNote, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, FLEX_LAYOUT_PROP_NAMES, resetPageContainerPosition, pageContainerPositionWarning, verticalGapWarnings, flexIndexOrder, flexIndexOrderNote, withNormalization, parseVariableEntries, PAGE_CONTAINER_ELEMENT_ID } from '../knowledge/normalize.js';
3
3
  import { functionSignature } from '../knowledge/functionGuards.js';
4
4
  import { attachFindings } from '../knowledge/policy.js';
@@ -340,9 +340,9 @@ export function registerPageTools(server, platform, injectedScreenshotter, injec
340
340
  ? 'dev'
341
341
  : resolvedEnvironment === 'production'
342
342
  ? 'view'
343
- : isBranchName(resolvedEnvironment) ? `branch/${resolvedEnvironment}` : undefined;
343
+ : isBranchName(resolvedEnvironment) ? `branch/${branchSlug(resolvedEnvironment)}` : undefined;
344
344
  if (!lane) {
345
- throw new PlatformApiError(`page_screenshot '${resolvedEnvironment}' ortamını görüntüleyemez: bu ad ne sabit bir ortam ne de geçerli bir dal adı. Sabitler 'development' (/dev) ve 'production' (/view); dal adı bir harfle başlar, yalnız küçük harf/rakam/alt çizgi taşır (3-31 karakter) ve rezerve olamaz ('public', 'api', 'pg_*' gibi). Projedeki dalları environment_list ile görün.`);
345
+ throw new PlatformApiError(`page_screenshot '${resolvedEnvironment}' ortamını görüntüleyemez: bu ad ne sabit bir ortam ne de geçerli bir dal adı. Sabitler 'development' (/dev) ve 'production' (/view); dal adı bir harfle başlar, küçük harf/rakam/alt çizgi/tire ve '/' ile ayrılmış parçalar taşır (3-31 karakter, ör. feature/odeme) ve rezerve olamaz ('public', 'api', 'pg_*' gibi). Dal şeridi adın '/' yerine '-' taşıyan hâliyle (slug) kurulur. Projedeki dalları environment_list ile görün.`);
346
346
  }
347
347
  const projectSlug = platform.resolveProject(project);
348
348
  const languageChoice = language === undefined ? undefined : normalizeLanguageCode(language, 'language');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appaflytech/zeyrek-ai-mcp",
3
- "version": "0.0.37",
3
+ "version": "0.0.40",
4
4
  "type": "module",
5
5
  "description": "Zeyrek (NgApps) platform APIs as MCP tools — data, logic and Studio design surface in one gateway",
6
6
  "license": "UNLICENSED",