one.manifest.json: alan başvurusu
Her Devoplus One uygulamasının kökündeki beyan dosyası. Sözleşme platformun manifest şemasıdır (platform deposunda
packages/manifest/src/schema.ts, zod şeması +validateManifest). Bu belge o şemadan çıkarılmıştır; ikisi çelişirse şema esastır.
Doğrulamayı one-ci validate <uygulama dizini> yapar (validateManifest + giriş dosyasının varlığı); geçmeyen sürüm yüklenmez. İskelet üretici (create-devoplus-one-app) ürettiği manifest'i aynı doğrulayıcıdan geçirir.
Alanlar
one.manifest.json
├── schemaVersion 1 (sabit)
├── app
│ ├── slug küçük harf/rakam, tek tire, harfle başlar, ≤ 24 (SLUG_RE, SLUG_MAX)
│ ├── name { tr: 1-120 karakter (kırpılır), en?: 1-120 }
│ ├── version x.y.z (önek/etiket yok)
│ ├── description? { tr, en? }; name ile aynı kural
│ └── owner.email e-posta (uydurulmaz)
├── entry uygulamanın giriş dosyası, ^[\w./-]+\.(ts|js|mjs)$
├── scopes string[] ≤ 32, varsayılan []; her öğe <modül>.<read|write|manage|execute> ya da ai.use (SCOPE_RE)
├── services varsayılan {}; alt alanların varsayılanları uygulanır
│ ├── database bool, varsayılan true; kurulum başına veritabanı (`env.DB`)
│ ├── files bool, varsayılan false; kurulum başına dosya deposu (`env.FILES`)
│ ├── cache bool, varsayılan false; kurulum başına önbellek (`env.CACHE`)
│ ├── (eski adlar) KALDIRILDI; yazılırsa yeni adını söyleyen hatayla reddedilir
│ ├── email, sms, push, orgSchema bool, varsayılan false; yalnız beyandır, one-ci bunları bir kaynağa çevirmez
│ └── dexa? { queryKeys?: string[], commandKeys?: string[] }; en az biri, aşağıda
├── menu
│ ├── title { tr, en? }
│ ├── icon? ≤ 64; PrimeIcons sınıfı (`pi pi-box`), aşağıda
│ └── group? ≤ 64
├── permission
│ ├── code One.<Ad>.<Ad> (PERMISSION_CODE_RE)
│ └── name { tr, en? }
├── permissions [{ code, name: { tr, en? } }]; uygulama içi ek izinler, varsayılan [], aşağıda
├── navigation [{ path, label: { tr, en? }, permission? }] ≤ 12, varsayılan []; Portal'ın çizdiği sekmeler (sekme izniyle), aşağıda
├── actingSessions "read" | "write", varsayılan "read"; Vekalet / Yerine Görüntüle oturumunda yazma
├── devicePermissions ("camera" | "microphone" | "geolocation")[], tekil, varsayılan []; Permissions-Policy
├── agent? Devoplus yapay zekasının çağırabileceği araçlar, `strict`, aşağıda
│ ├── summary { tr: 1-1000, en? }; uygulamanın yapay zekaya kısa tanıtımı
│ └── tools ≤ 20, varsayılan []; [{ name, title, description, readOnly, permission?, input }]
├── exports? [{ name, version, description, permission?, request, response }]; uygulamalar arası okuma, veren taraf, aşağıda
├── imports? [{ app, export, version, reason }]; uygulamalar arası okuma, alan taraf, aşağıda
├── widgets? [{ name, version, title, kind, size, permission?, refreshSeconds?, params?, path? }]; Portal pano widget'ları, aşağıda
├── jobs? zamanlanmış görev ve kuyruk, `strict`; en az bir zamanlama ya da kuyruk, aşağıda
│ ├── schedules [{ name, cron, timeZone?, description? }] ≤ 10, varsayılan []
│ ├── queues [{ name, maxRetries?, description? }] ≤ 10, varsayılan []
│ └── services? arka plan işinin uygulama kimliğiyle çağıracağı servisler, aşağıda
├── sdkVersion? uygulamanın derlendiği SDK sürümü (SemVer, ön sürüm eki dahil); ELLE YAZILMAZ, aşağıda
├── limits? dispatch'in çağrı başına sınırı; platform tavanını aşamaz
│ ├── cpuMs? tam sayı 1-1000
│ └── subRequests? tam sayı 1-200
└── observability? Event Logger kalıcılığı, `strict`
└── headSamplingRate? 0 < oran ≤ 1, varsayılan 1 (her istek). Olay günlüğü platform tarafından HER ZAMAN açılır;
kapatmak bilerek mümkün değildir (`enabled` gibi bilinmeyen alan reddedilir)Kök nesne katıdır (strict): bilinmeyen bir kök alan reddedilir, uydurulmuş bir alan sessizce yutulmaz.
scopes
Biçim devoplus-auth scope kataloğuyla aynıdır; modül adının katalogda olup olmadığını manifest de one-ci de denetlemez; o kapı devoplus-auth client kaydındadır ve belirteç istemci kaydı ∩ oturum scope'unu taşır. Manifest scopes beyan ve biçim denetimi içindir, çalışma anında okunmaz. Kullanıcı kimliği (sub) scope'suz gelir.
ai.use: Devoplus yapay zekasını kullanma (SDK completeAi, uç One/services/ai). Dört eylem kalıbının dışındaki TEK addır; SCOPE_RE onu ayrıca tanır (genel bir .use eylemi açılmaz, hr.use reddedilir). Kullanıcının süreli onayına bağlı DEĞİLDİR.
agent: Devoplus yapay zekasının araçları
Devoplus yapay zekası (Devoplus ajanı) uygulamanın verisine ve işlemlerine yalnız burada beyan edilen araçlarla, kullanıcının kimliğiyle ulaşır: Devoplus kurulumu, uygulama iznini ve aracın beyanını doğrular, platform kapısına imzalı çağrı yapar, kapı isteği uygulamaya POST /__one/agent/<ad> olarak verir; SDK handleAgentRequest karşılar. Araç beyan eden uygulama AGENT_GUIDE.md taşımak ZORUNDADIR (aşağıda).
| Kural | Değer | Hata yolu |
|---|---|---|
| Ad | ^[a-z][a-z0-9-]{1,39}$ (AGENT_TOOL_NAME_RE; SDK ve dispatch ile birebir), tekil | agent.tools.<i>.name |
| Adet | en çok 20 (AGENT_TOOLS_MAX) | agent.tools |
title, description | { tr, en? }; başlık 1-200, açıklama 1-1000 karakter | öğenin yolu |
readOnly | zorunlu boolean; false = değiştirir; yapay zeka kullanıcıdan onay ister, Vekalet / Yerine Görüntüle oturumunda kapalı | agent.tools.<i>.readOnly |
permission | isteğe bağlı; uygulamanın ad alanında VE manifest'te beyanlı (permission.code ya da permissions[]) | agent.tools.<i>.permission |
input | JSON Schema ALT KÜMESİ (aşağıda), JSON hali ≤ 8 KiB, derinlik ≤ 8 | agent.tools.<i>.input.<şema yolu> |
| Öğe ve bölüm | strict (bilinmeyen alan reddedilir) | öğenin yolu |
input alt kümesi (AGENT_INPUT_KEYWORDS): type, properties, required, enum, minimum, maximum, minLength, maxLength, items ve description. Kök "type": "object" olmak zorundadır; her düğümde type yazılır (object, string, number, integer, boolean, array; tip dizisi yok); anahtar-tip uyumu denetlenir (minLength yalnız metinde, minimum yalnız sayıda, items yalnız dizide ve orada zorunlu); required yalnız tanımlı alanları sayar; alan adı ^[A-Za-z_][A-Za-z0-9_]{0,63}$, nesnede ≤ 50 alan; enum 1-100 tekil öğe ve düğümün tipinde; description ≤ 500. Alt küme dışı anahtar (pattern, format, $ref, oneOf, additionalProperties vb.) REDDEDİLİR. Sessizce yok sayılsaydı geliştirici denetlendiğini sanırdı. ⚠️ Nesneler çalışma anında kapalıdır: şemada olmayan alan SDK'da reddedilir (additionalProperties: false örtük).
Ajan rehberi: agent.tools boş değilse AGENT_GUIDE.md zorunludur: one-ci validate|plan|deploy dosyayı, dört başlığı (## Uygulama ne yapar, ## Veri, ## Araçlar, ## Örnek istekler), her araç adının rehberde geçtiğini, en az 400 karakteri ve 256 KiB tavanını denetler; eksikse yayın DURUR. agent yoksa ya da araç listesi boşsa yayın durmaz, "Devoplus yapay zekası bu uygulamaya erişemez" uyarısı yazılır. SDK manifest bölümünü /.well-known/one-agent.json, rehberi /.well-known/one-agent.md adresinden sunar (agentManifestResponse).
exports ve imports: uygulamalar arası okuma
Bir uygulama verisinin bir bölümünü adlandırılmış ve sürümlü okuma uçlarıyla başka uygulamalara açabilir (exports); başka bir uygulama bu uçlardan birine ihtiyacını gerekçesiyle beyan eder (imports). Paylaşım yalnız aynı portalda, alan uygulamanın kurulumunda şirket yöneticisinin onayıyla ve yalnız okuma olarak çalışır.
⚠️ Durum: beyan, doğrulama, veren tarafın işleyicisi (SDK defineExports ve handleExportRequest, U5-2), alan uygulamanın çağrısı (SDK readAppExport) ve dispatch ile çıkış katmanının çağrı yolu (U5-3) bu depodadır. Platformun öteki tarafı (backend servis ucu, onay kaydı, aşağıdaki yayın kuralları ve Devoplus Console onay ekranı; U5-4) yazılıyor. O tarafı yayına alınana kadar bu alanlar hiçbir çağrı açmaz.
| Kural | Değer | Hata yolu |
|---|---|---|
exports[].name | ^[a-z][a-z0-9-]{0,39}$ (EXPORT_NAME_RE); adres yoluna kodlanmadan yazılır (/__one/exports/<name>/v<version>) | exports.<i>.name |
exports[].version | tam sayı, 1-999999 (1.0 gibi bir yazım da 1 sayılır; yola v1 olarak yazılır) | exports.<i>.version |
| Ad + sürüm | tekil; aynı ad farklı sürümlerle birlikte sunulabilir (geçiş süresi) | exports.<i>.version |
exports[].description | { tr: 1-1000, en? }, katı; kırpılmaz, yalnız boşluk olamaz; onay penceresinde yöneticiye gösterilir | exports.<i>.description |
exports[].permission | isteğe bağlı; çağıran kullanıcıda aranan izin; uygulamanın ad alanında VE manifest'te beyanlı | exports.<i>.permission |
exports[].request, response | sözleşme şeması (aşağıda) | exports.<i>.request.<şema yolu> |
imports[].app | veren uygulamanın kısa adı (SLUG_RE, ≤ 24); kendi kısa adı olamaz | imports.<i>.app |
imports[].export, version | dışa açım adı ve sürümü (aynı biçim) | imports.<i>.export |
| Uygulama + dışa açım | tek sürüm beyan edilir; sürümü beyan seçer (readAppExport sürüm almaz, ONE_IMPORTS'tan okur) | imports.<i>.export |
imports[].reason | { tr: 1-1000, en? }, katı; kırpılmaz, yalnız boşluk olamaz; neden gerektiği, onay penceresinde gösterilir | imports.<i>.reason |
| Öğeler | strict (bilinmeyen alan reddedilir) | öğenin yolu |
| Adet | exports beyanları yayında tek bir değişkenle betiğe taşınır (ONE_EXPORTS: her ad ve sürüm için sözleşme özeti ve izin); değişken en çok 5000 bayttır (yaklaşık 25-35 beyan, ad ve izin uzunluğuna göre). Aşan liste doğrulamada durur. imports aynı biçimde ONE_IMPORTS ile taşınır (her uygulama + dışa açım için sürüm; en çok 5000 bayt, yaklaşık 60 beyan) | exports, imports |
Sözleşme şeması: ajan araç girdisiyle aynı alt küme (yukarıda agent: anahtarlar, tipler, kapalı nesneler, derinlik ≤ 8, nesnede ≤ 50 alan, JSON hali ≤ 8 KiB) ve buna ek olarak maxItems: her dizide zorunlu, 0 ile 1000 arası tam sayı. Kök "type": "object" olmak zorundadır. Aynı doğrulayıcı kullanılır (boundedSchemaProblems; sözleşme profili CONTRACT_SCHEMA_PROFILE), ajan profili değişmedi: maxItems araç girdisinde yine reddedilir. Yanıt gövdesi en çok 256 KB, istek gövdesi en çok 16 KB'tır (çalışma anında uygulanır).
Sözleşme özeti (contractDigest): onay kaydı sözleşmenin özetine bağlıdır. Özet; description, permission (yoksa açıkça null), request ve response alanlarının RFC 8785 kanonik JSON'unun UTF-8 baytları üzerinden SHA-256'dır (küçük harfli onaltılık). name ve version özete girmez, onay kaydı onları ayrıca taşır. Yanıta alan eklemek, izni değiştirmek ya da açıklamayı değiştirmek özeti değiştirir; aynı sürümde bu değişiklik yayında reddedilir ve yeni bir version ister (aşağıdaki yayın kuralları). Gerekçe de aynı biçimle ayrı bir özete bağlıdır (reasonDigest). Onay yalnız şu üç durumda yeniden istenir: alan uygulama yeni bir sürüme geçtiğinde, alan uygulama gerekçeyi (imports[].reason) değiştirdiğinde ve geri alma onaydakinden farklı bir sözleşmeyi geri getirdiğinde. Doğrulama özetin kapsadığı alanları değiştirmez (kırpma yok, bilinmeyen anahtar reddedilir); bu yüzden özet ham manifestte ve doğrulanmış manifestte aynıdır. Özetin çeviremeyeceği değer (ör. eşi olmayan vekil karakter) doğrulamada yola bağlı hatayla reddedilir. Özeti YALNIZ packages/manifest/src/contract.ts hesaplar; altın test vektörleri (RFC 8785 örnekleri, FIPS 180-2 vektörleri, Türkçe metin, büyük sayı) çıktıyı kilitler. Backend aynı özeti kendi kaydı için ayrıca hesaplar; iki uygulama aynı altın vektörlerle kilitlidir.
Yayın kuralları: platform yayını ve terfiyi, hat başlamadan önce yayınlanacak koddaki manifestle denetler. Kural ihlalinde yayın 409 ile durur ve hat başlamaz:
| Kural | Hata |
|---|---|
Aynı name + version'ın sözleşmesi (açıklama, izin, istek ya da yanıt şeması) değiştirilemez; en küçük değişiklik de yeni bir version ister | ONE-APP-E-163 |
| Aynı portalda onaylı olarak okunan bir sürüm kaldırılamaz: önce alan uygulama yeni sürüme geçip onay alır, eski sürüm o süre boyunca birlikte sunulur | ONE-APP-E-162 (alan uygulamayı adlandırır) |
Manifest yayınlanacak commit'te yoksa, başka uygulamaya aitse ya da exports / imports geçersizse | ONE-APP-E-164 |
Geri almada bu denetim yapılmaz: geri alınan sürümün beyanları geçerli olur. Sözleşmesi değişen onay yeniden onay ister, kalkan sürümü okuyan uygulama onu okuyamaz.
services.dexa: DEXA (ERP) sorguları ve işlemleri
Uygulama ERP'ye yalnız önceden tanımlı QueryStore anahtarlarıyla erişir. İki liste vardır ve en az biri verilir (boş services.dexa: {} reddedilir):
queryKeys: okuma sorguları (uçOne/services/dexa/query, scopedexa.read); SDKqueryDexa.commandKeys: ERP'ye YAZAN işlemler (uçOne/services/dexa/command, scopedexa.write); SDKrunDexaCommand(zorunluIdempotency-Key). Ayrıntı: SDK başvurusu (/docs/sdk).
| Kural | Değer | Hata yolu |
|---|---|---|
| Öğe biçimi (iki liste) | ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ (DEXA_QUERY_KEY_RE; harf duyarlı; SDK DEXA_KEY_RE ile birebir, SDK testi kilitler) | services.dexa.queryKeys.<i>, services.dexa.commandKeys.<i> |
| Adet | queryKeys en az 1, en çok 64 (DEXA_QUERY_KEYS_MAX); commandKeys en az 1, en çok 32 (DEXA_COMMAND_KEYS_MAX; backend kayıt defteri tavanıyla aynı) | listenin yolu |
| Tekillik | aynı anahtar bir listede iki kez yazılamaz (harf duyarlı: A ile a ayrıdır) | yinelenen öğenin yolu |
| En az bir liste | services.dexa varsa queryKeys ya da commandKeys olmalı | services.dexa |
| Çapraz denetim | queryKeys varsa scopes içinde dexa.read olmalı; commandKeys varsa dexa.write olmalı | scopes |
| Çapraz denetim | scopes içinde dexa.read varsa queryKeys olmalı; dexa.write varsa commandKeys olmalı | services.dexa |
⛔ İki liste de bir beyandır: çalışma anında okunmaz ve bir anahtarı açmaz. Hangi anahtarın çalışabileceğinin tek kaynağı platform kayıt defteridir. Anahtarları Devoplus Console'da uygulamanın kaydına yönetici ekler (dexaQueryKeys / dexaCommandKeys); kayıtta olmayan sorgu anahtarı backend'den 403 ONE-APP-E-024, işlem anahtarı 403 ONE-APP-E-030 alır. Bir işlem anahtarı ayrıca koddaki ERP komut kataloğunda One uygulamalarına açık olmalıdır (bugün böyle bir girdi yoktur; açmak bir backend kod değişikliğidir). Anahtar adı uydurulmaz; QueryStore tanımından alınır.
Çapraz denetimin gerekçesi: scope'suz beyan edilen anahtar listesi hiç çalışmaz (belirteç 403 ONE-APP-E-017 alır), listesiz beyan edilen dexa.read/dexa.write ise uygulamaya kullanmadığı bir ERP okuma ya da yazma yetkisi taşıtır. İskelet üretici --scopes dexa.read ve --scopes dexa.write kabul etmez (anahtar uyduramaz); scope ve anahtarlar iskelet üretildikten sonra elle eklenir.
widgets: Portal pano widget'ları
Uygulama, Portal ana sayfasındaki panolara eklenebilen widget'lar beyan eder. Uygulama bir portala kurulunca widget'ları o portalın pano tasarımcısında görünür; kaldırılınca düşer. İki tür vardır:
- Veri widget'ı (
stat,list,chart,table): uygulama sabit biçimli veri döner, Portal kendi bileşenleriyle çizer. Tarayıcı uygulamanın adresine istek atmaz; veriyi Devoplus ister. - Sayfa widget'ı (
page): uygulamanınpathyolundaki küçük sayfası panoda çerçeve içinde açılır.
⚠️ Durum: beyan ve doğrulama (packages/manifest/src/widgets.ts) ile veri widget'ının uygulama tarafındaki işleyicisi (SDK defineWidgets ve handleWidgetRequest) hazırdır. Devoplus katalog kaydı ve pano tasarımcısı yazılıyor; o taraf yayına alınana kadar bu alan hiçbir widget göstermez.
| Alan | Kural |
|---|---|
name | Küçük harfle başlar, küçük harf/rakam/-, 1-40 karakter (dışa açım adıyla aynı kural). Adres yoluna olduğu gibi yazılır. |
version | Başında sıfır olmayan pozitif tam sayı, en çok 999999. Aynı ad birden çok sürümle sunulabilir; aynı ad + sürüm iki kez yazılamaz. |
title | { tr, en? }, en çok 200 karakter. Tasarımcı kataloğunda ve widget başlığında görünür. |
kind | stat, list, chart, table ya da page. |
size | { w, h }: panoya eklenirken başlangıç boyutu (sütun ve satır), ikisi de 2-12 arası tam sayı (pano 12 sütundur). |
permission? | Widget'ı görmek için gereken izin; uygulamanın ad alanında ve permission.code ya da permissions içinde beyan edilmiş olmalı. |
refreshSeconds? | 0 (yalnız açılışta yüklenir) ya da 60-3600 saniye. |
params? | Tasarımcıda seçilecek ayarların şeması (aşağıda). Yoksa widget'ın ayarı yoktur. |
path? | Yalnız page türünde ve orada zorunlu: / ile başlar, en az bir bölüm taşır; yalnız küçük harf, rakam, - ve /. Kök yol (/), sorgu (?), #, % ve . kabul edilmez. Yol menüde (navigation) yer alamaz ve iki farklı sayfa widget'ı aynı yolu paylaşamaz. |
Ayar şeması (params): exports sözleşme şemasıyla aynı sınırlı biçimdir (kök "type": "object", her dizide maxItems zorunlu, derinlik ≤ 8, nesnede ≤ 50 alan, JSON hali ≤ 8 KiB) ve buna ek olarak her alanda title zorunludur: { "tr": "...", "en": "..." } (TR zorunlu, EN isteğe bağlı, en çok 200 karakter). Tasarımcı formu alan etiketini buradan çizer. title yalnız widget ayar şemasında tanınır; araç girdisi ve dışa açım şeması onu reddeder.
"widgets": [
{
"name": "low-stock",
"version": 1,
"title": { "tr": "Azalan stok", "en": "Low stock" },
"kind": "table",
"size": { "w": 6, "h": 4 },
"permission": "One.Stock.Read",
"refreshSeconds": 300,
"params": {
"type": "object",
"properties": { "branch": { "type": "string", "maxLength": 20, "title": { "tr": "Şube", "en": "Branch" } } },
"required": ["branch"]
}
},
{ "name": "summary", "version": 1, "title": { "tr": "Özet" }, "kind": "page", "size": { "w": 4, "h": 3 }, "path": "/widget/ozet" }
]Widget sözleşmesi (widgetContractDigest): kind, params şeması, permission (yoksa null) ve path (yoksa null) alanlarının dışa açımla aynı kanonik biçimdeki SHA-256 özeti. title, size ve refreshSeconds özete girmez: değişmeleri panoya eklenmiş widget'ı bozmaz. Pano kaydı widget'ı adı ve sürümüyle tutar; aynı sürümde sözleşmeyi kırıcı biçimde değiştirmek (türü, yolu değiştirmek, ayara zorunlu alan eklemek, alan türünü değiştirmek) yeni bir version ister.
menu.icon: menü simgesi
Portal menüsünde uygulamanın yanında çizilen simge (geliştirici kararı 25.10.2026). Değer bir PrimeIcons sınıfıdır: pi pi- öneki ve simgenin adı (pi pi-box, pi pi-flag, pi pi-wrench). İzinli liste PrimeIcons 7.0.0'ın tamamıdır (314 simge; packages/manifest/src/menuIcons.ts).
- Backend simgeyi her yayın isteğinde yayımlanan kodun manifestinden alır. Simge değişikliği bir sonraki yayında menüye geçer; menü kullanıcı başına 10 dakika önbelleklidir.
- Alan yoksa menüde varsayılan simge (
pi pi-box) çizilir. - Listede olmayan değer (eski Feather adı
box, büyük harf, fazladan boşluk ya da ikinci sınıf) reddedilmez: menüde varsayılan simge çizilir; one-ci arayüz kapısı ve kaynak yüklemesi uyarı yazar. - "Devoplus One Uygulamalarım" öğesinin simgesi sabittir (
pi pi-th-large).
Mobil bildirim: push.execute
scopes içinde push.execute (SDK sendPush, uç One/services/push; ⚠️ geliştirici onayı bekliyor). E-posta/SMS scope'ları gibi bir servis listesi ya da çapraz denetimi yoktur; services.push bayrağı bugün hiçbir kaynağa çevrilmez (aşağıdaki sınırlar).
permissions: uygulama içi ek izinler
Uygulama içinde rol gerekiyorsa (ör. yalnız onaylayanlar onaylasın) ek izin kodu beyan edilir. Portal yöneticisi bu kodu Yetki Yönetimi'nde kullanıcı gruplarına atar; grup üyeliği org düğümlerinden (şirket, departman, ünvan, pozisyon, iş yeri, çalışan türü) sunucuda çözülür. Dispatch kullanıcının yalnız bu uygulamanın ad alanındaki izinlerini X-One-Permissions ile iletir; SDK hasPermission(ctx, kod) / requirePermission(ctx, kod) okur (portal yöneticisi her izne sahip sayılır; bu, platformun yönetici baypasıdır).
| Kural | Değer | Hata yolu |
|---|---|---|
| Kod biçimi | PERMISSION_CODE_RE | permissions.<i>.code |
| Ad alanı | permission.code ile aynı önek: One.Hello.Use için One.Hello. (permissionNamespace) | permissions.<i>.code |
| Tekillik | ana koddan ve birbirinden farklı | permissions.<i>.code |
| Adet | en çok 16 (EXTRA_PERMISSIONS_MAX; backend OneNaming.AdditionalPermissionMaxCount ile aynı) | permissions |
| Öğe | strict (bilinmeyen alan reddedilir) | öğenin yolu |
⛔ permissions bir beyandır: kodu kataloğa ekleyen şey platform kayıt defteridir (Devoplus Console'da uygulamanın kaydına aynı kodlar girilir; backend additionalPermissions). Kayıtta olmayan kod hiçbir gruba atanamaz ve hasPermission yalnız portal yöneticisinde true döner. Ad alanı uygulamalar arasında tekildir (backend 409 ONE-APP-E-028).
navigation, actingSessions, devicePermissions
navigation: uygulama sol menü çizmez; görünümler burada beyan edilir ve Portal iframe'in üstünde sekme olarak çizer. Portal adresi /One/<kısa ad>/<yol> olur ve iframe aynı yola gider; uygulamanın sunucusu bu yolların hepsinde sayfayı döndürür. SDK navigationFromManifest(manifest) listeyi sayfa betiğine gömer, köprü one:navigation ile Portal'a bildirir.
| Kural | Değer | Hata yolu |
|---|---|---|
| Yol | / ya da / ile ayrılmış parçalar; parça harf/rakam/-/_ ile başlar, . içerebilir (NAVIGATION_PATH_RE); sorgu, #, .., // YOK; ≤ 200 karakter. SDK ROUTE_PATH_RE ile birebir (SDK testi kilitler) | navigation.<i>.path |
| Etiket | { tr, en? } (1-120) | navigation.<i>.label.tr |
| Tekillik | aynı yol iki kez yazılamaz | navigation.<i>.path |
| Adet | en çok 12 (NAVIGATION_MAX_ITEMS) | navigation |
İzin (permission, isteğe bağlı) | One.<Uygulama>.<Eylem>; uygulamanın ad alanında ve permission.code ya da permissions[] içinde beyan edilmiş olmalı (araç izniyle aynı kural). Verilirse sekme yalnız bu izni taşıyana ve yöneticiye görünür: köprü sekmeyi oturumdaki kişinin izinleri one.setNavigationAccess ile bildirilene kadar menüye koymaz, izin kodu Portal'a gitmez. Yalnız görünürlüktür; veri sunucu ucunda ayrıca korunur | navigation.<i>.permission |
| Öğe | strict | öğenin yolu |
actingSessions: read (varsayılan): Vekalet ya da Yerine Görüntüle oturumunda dispatch GET/HEAD dışındaki isteği 403 ONE-DSP-E-009 ile reddeder (backend genel kuralı: okuma açık, yazma kapalı). write: bu oturumlarda da yazılır; kim adına kimin yazdığı SDK ctx.user.sub + ctx.actor.sub ile kaydedilmelidir. Değer kurulum kaydına (one-ci deploy) yazılır, dispatch oradan okur, çalışma anında uygulama değiştiremez. Backend beyanı outbound'un eklediği X-One-Acting-Writes başlığından tanır (yalnız platform anahtarı eşleşirse); write beyanı Devoplus API'nin genel uçlarını açar, ama ERP komutu, e-posta, SMS ve mobil bildirim bu oturumlarda yine KAPALIDIR. Denetim kaydı (recordAudit) her iki değerde de yazılır ve vekili ayrıca tutar.
devicePermissions: dispatch her yanıta Permissions-Policy: camera=(), microphone=(), geolocation=() ekler; beyan edilen özellik (self) olur. ⛔ Alan adı permissions DEĞİLDİR: o ad uygulama içi izin kodlarına aittir. iframe'de özellik ayrıca Portal'ın iframe allow niteliğine bağlıdır.
jobs: zamanlanmış görev ve kuyruk
Uygulama işi beyan eder ve işleyicisini yazar (SDK defineJobs + handleJobRequest); işi platform tetikler. Zamanlama vadesi gelince, kuyruk ise uygulama enqueue(ad, gövde, { delaySeconds }) ile ileti bırakınca çalışır. Platform işleyiciyi POST /__one/jobs/<schedule|queue>/<ad> ile çağırır; bu yol internetten kapalıdır.
| Kural | Değer | Hata yolu |
|---|---|---|
| Ad | ^[a-z][a-z0-9-]{1,39}$ (JOB_NAME_RE; SDK ile birebir), tür içinde tekil | jobs.schedules.<i>.name, jobs.queues.<i>.name |
cron | 5 alan: dakika saat ayın-günü ay haftanın-günü. Öğe *, n, a-b, */s, a-b/s ya da a/s olur, öğeler virgülle listelenir; ay adları jan ile dec arası, gün adları sun ile sat arası; haftanın günü 0-7 (0 ve 7 pazar). ?, L, W, # ve saniye alanı YOK. Ayın günü ile haftanın günü ikisi de kısıtlıysa biri tutması yeter. En sık aralık dakikada bir | jobs.schedules.<i>.cron |
timeZone | IANA adı (Europe/Istanbul, UTC vb.), varsayılan Europe/Istanbul; kanonik yazıma çevrilir (europe/istanbul değeri Europe/Istanbul olur). Sayısal uzaklık (+03:00) kabul edilmez | jobs.schedules.<i>.timeZone |
maxRetries | 0-10 tam sayı, varsayılan 3; işleyici 5xx döndürür ya da zaman aşımına uğrarsa kaç kez yeniden denenir. Zamanlama için alan yoktur: 3 kez | jobs.queues.<i>.maxRetries |
description | 1-200 karakter, isteğe bağlı; yalnız beyandır (platforma gitmez) | öğenin yolu |
| Adet | en çok 10 zamanlama + 10 kuyruk; ikisi de boşsa jobs yazılmaz | jobs.schedules, jobs.queues, jobs |
services | isteğe bağlı; yalnız mail.execute, sms.execute, push.execute, dexa.read, ai.use (JOB_SERVICE_SCOPES), tekil; her biri scopes içinde de beyanlı. dexa.write ve diğer her scope reddedilir. Beyan istektir: servis kurulumda portal yöneticisi onaylamadıkça açılmaz. one-ci kurulum kaydına jobServices olarak yazar | jobs.services.<i> |
| Öğe | strict (bilinmeyen alan reddedilir) | öğenin yolu |
Çalışma kuralları (ayrıntı /docs/jobs.md): kuyruk iletisi gövdesi JSON ≤ 64 KiB, gecikme 0-86.400 sn; beyan edilmemiş kuyruk adına ileti bırakılamaz. Kuyruk işi iletiyi bırakan kullanıcının kimliğini bilgi olarak taşır, zamanlanmış iş kullanıcısız koşar; ikisinde de Devoplus servisleri uygulamanın kimliğiyle ve yalnız services + kurulum onayıyla çağrılır. İşleyici 2xx dönerse iş tamamdır; 4xx kalıcı hatadır (yeniden denenmez); 5xx ya da zaman aşımı geri çekilmeyle yeniden denenir. Aynı iş birden çok kez gelebilir; job.id her denemede aynıdır.
sdkVersion: SDK sürümü beyanı
Uygulamanın derlendiği SDK sürümü (ör. 0.3.0-next.12; v öneki ve + ile başlayan derleme üstverisi yok). Elle yazılmaz: SDK 0.3.0 ve sonrasında iskelet üretici (create-devoplus-one-app) ve npx one upgrade yazar; daha eski SDK'lı uygulamada alan boş kalır ve bu yalnız uyarıdır. Yayın kapısı (one-ci validate) beyanı uygulamanın kurulu SDK sürümüyle (kilit dosyası ya da node_modules) karşılaştırır:
| Durum | Sonuç | Kural |
|---|---|---|
| Beyan kurulu sürüme eşit | geçer | yok |
| Beyan kurulu sürümden farklı | yayın durur | ONE-RULE-007 |
| Beyan yok, kurulu SDK 0.3.0 ön sürümleri ya da sonrası | yayın durur | ONE-RULE-008 |
| Beyan yok, kurulu SDK daha eski ya da okunamıyor | uyarı, yayın sürer | ONE-RULE-008 |
| Beyan var ama kurulu sürüm kesin okunamıyor (kilit dosyası yok) | uyarı, yayın sürer | yok |
Beyan yoksa sürüm defterine ve kurulum kaydına legacy yazılır; legacy her sürümden küçük sayılır. Alan yalnız yayın kapısı ve gösterim içindir: çalışma anında platform davranışı bu alandan seçilmez. Kural metinleri ve düzeltme yönergesi platform kuralları kataloğundadır (packages/rules/catalog.json); one-ci validate uyguladığı katalog revizyonunu ve uymayan her kuralın tam metnini yazar.
Bilinen sınırlar
- Katılık kök nesnede,
services'te,navigationöğelerindeagent(bölüm + araç öğeleri),exportsveimportsöğelerinde vejobs(öğeler dahil) içindedir (services: { aiGateway: true }artık reddedilir). Diğer alt nesnelerde (app,services.dexa,menu,permission,limits) bilinmeyen alan reddedilmez, sessizce atılır (ölçüldü 15.10.2026). services.email,sms,pushveorgSchemabugün bu depoda hiçbir kaynağa çevrilmez (okundu 15.10.2026:one-ci planyalnızdatabase,filesvecacheokur). E-posta/SMS'i açan şey scope'tur (mail.execute/sms.execute).