Tecof, uygulamanızın kurulum başına veri saklamasını sağlayan üç katman sunar. Bu katmanlarla birçok uygulama kendi veritabanına ihtiyaç duymadan, örneğin Vercel üzerinde durumsuz (stateless) çalışabilir.
| Katman | Ne için | Boyut | Kaldırmada |
|---|---|---|---|
| Ayarlar | Sır olmayan yapılandırma (JSON) | ≤ 64 KB | Silinir |
| Vault (sırlar) | API anahtarı, parola, token | Değer ≤ 8 KB, en fazla 50 anahtar | Silinir |
| Metafield'lar | Sipariş, ürün, müşteri ya da mağazaya bağlı uygulama verisi | Değer ≤ 16 KB | Panelde gizlenir, 30 gün sonra temizlenir |
Ayarlar ve sırlar kapsam istemez; kurulumun kendisi yetkidir.
Ayarlar#
Kurulum başına tek bir JSON nesnesi.
| Metot | Uç | Açıklama |
|---|---|---|
GET | /api/v1/app/settings | { settings, updatedAt } |
PUT | /api/v1/app/settings | { settings, merge?: boolean }; ≤ 64 KB → { settings, updatedAt } |
const api = tecof.client(installationId);
const { settings } = await api.settings.get();
await api.settings.set({ invoiceMode: "issued", seriesPrefix: "ABC" }, { merge: true });merge: true gönderilen anahtarları mevcut nesneyle birleştirir; merge olmadan nesne tamamen değiştirilir. Panelin yerel ayar formu da aynı ayar nesnesine yazar (birleştirerek; formda olmayan anahtarlar korunur). API'den yapılan yazmalar app.settings.updated olayı üretmez.
Vault (Sırlar)#
Üçüncü taraf API anahtarları ve parolalar için. Değerler Tecof'ta şifreli tutulur ve yalnız uygulamanızın kurulum token'ıyla okunabilir.
| Metot | Uç | Yanıt |
|---|---|---|
GET | /api/v1/app/secrets | [{ key, updatedAt, lastReadAt, length }] — değer yok |
GET | /api/v1/app/secrets/:key | { key, value, updatedAt } |
PUT | /api/v1/app/secrets/:key | Gövde { value } → { key, updatedAt } |
DELETE | /api/v1/app/secrets/:key | Siler |
await api.secrets.set("isbasiPassword", passwordFromForm);
const { value: password } = await api.secrets.get("isbasiPassword"); // okuma lastReadAt'i damgalar
const list = await api.secrets.list(); // yalnız anahtar adları ve meta
await api.secrets.delete("isbasiPassword");Kurallar
| Kural | Değer |
|---|---|
| Anahtar biçimi | ^[a-zA-Z][a-zA-Z0-9_.-]{0,63}$ |
| Anahtar sayısı | En fazla 50 |
| Değer | UTF-8 metin, en fazla 8 KB |
Şifreleme tasarımı#
Vault, sızıntı durumunda bile şifreli metnin başka bir yerde kullanılamamasını hedefler:
| Katman | Tasarım |
|---|---|
| Algoritma | AES-256-GCM (kimlik doğrulamalı şifreleme; değiştirilmiş şifreli metin çözülemez) |
| Kurulum başına anahtar | Veri anahtarı her kurulum için ayrı türetilir: HKDF-SHA256(ana anahtar, salt = kurulum kimliği, info = tecof-app-vault/v1) |
| AAD bağlama | Ek doğrulanmış veri = uygulama kimliği | kurulum kimliği | anahtar adı. Şifreli metin başka bir kuruluma, başka bir uygulamaya ya da başka bir anahtar adına kopyalanırsa çözülmez |
| Anahtar sürümü | Her kayıt hangi ana anahtarla şifrelendiğini (keyId) saklar; Tecof ana anahtarları döndürürken kayıtları yeniden şifreler |
| İstemci sırrı | Uygulamanızın istemci sırrı (tcfs_…) da aynı ana anahtarlarla, kendi bağlamına bağlanarak saklanır |
Garantiler
- Değerler panel API'sine, istek günlüklerine, webhook yüklerine ve hata mesajlarına hiçbir zaman çıkmaz. Panel yalnız "ayarlı / ayarlı değil" bilgisini ve güncelleme zamanını görür.
- Okuma
lastReadAtalanını damgalar; liste ucuyla hangi sırrın ne zaman okunduğunu izleyebilirsiniz. - Uygulama kaldırıldığında kurulumun sırları anında silinir.
Kendi tarafınızda: sırrı yalnız ihtiyaç anında okuyun, günlüğe yazmayın, istemci (tarayıcı) koduna göndermeyin.
Yerel Ayar Formu#
tecof.app.json içine settings şeması eklerseniz panel, uygulama sayfasında bir "Ayarlar" sekmesi gösterir. Böylece ayar ekranı için arayüz yazmanız gerekmez; arka plan (headless) uygulamalar için de idealdir.
{
"settings": [
{ "key": "username", "label": { "tr": "Kullanıcı adı", "en": "Username" }, "type": "text", "required": true },
{ "key": "password", "label": { "tr": "Parola", "en": "Password" }, "type": "secret", "required": true },
{ "key": "autoInvoice", "label": { "tr": "Ödenen siparişleri otomatik faturala", "en": "Auto-invoice paid orders" }, "type": "boolean" },
{ "key": "invoiceMode", "label": { "tr": "Fatura tipi", "en": "Invoice mode" }, "type": "select",
"help": { "tr": "Kesilmiş fatura doğrudan alıcıya gider", "en": "Issued invoices are sent to the buyer" },
"options": [
{ "value": "draft", "label": { "tr": "Taslak", "en": "Draft" } },
{ "value": "issued", "label": { "tr": "Kesilmiş", "en": "Issued" } }
] },
{ "key": "note", "label": { "tr": "Fatura notu", "en": "Invoice note" }, "type": "textarea" }
]
}| Alan | Açıklama |
|---|---|
key | Ayar anahtarı |
label | { tr, en } |
type | text, number, boolean, select, textarea, secret |
required | İsteğe bağlı |
options | select için zorunlu: [{ value, label: { tr, en } }] |
help | İsteğe bağlı yardım metni, { tr, en } |
En fazla 30 alan tanımlanabilir.
Panel tarafı#
| Metot | Uç | Davranış |
|---|---|---|
GET | /api/merchant/apps/installations/:id/settings | { schema, values }; secret alanlar değer yerine { set: boolean, updatedAt } döner |
PUT | /api/merchant/apps/installations/:id/settings | { values }; sır olmayanlar ayar nesnesine birleştirilerek (formda olmayan anahtarlar korunur), secret olanlar Vault'a yazılır |
secretalan için boş string = değiştirme;null= sil.- Kayıttan sonra uygulamanıza
app.settings.updatedwebhook'u gelir:data = { keys: [...], secretKeys: [...] }. Değer taşımaz. Olay yalnız bu panel kaydında üretilir. - Uygulamanın kendi yazdığı anahtarlar (ör.
billing) form kaydında silinmez; yalnız formdaki anahtarla aynı adı taşıyorsa üzerine yazılır.
Uygulama tarafı#
Formdaki sır olmayan değerler ayarlarda, secret değerler Vault'ta aynı key ile durur:
const api = tecof.client(installationId);
const { settings } = await api.settings.get();
const username = settings.username as string;
const { value: password } = await api.secrets.get("password");app.settings.updated geldiğinde önbelleğinizdeki değerleri geçersiz kılın ya da bağlantıyı test edin (ör. üçüncü taraf API'ye giriş deneyip sonucu metafield veya ayarlarla bildirin).
Metafield'lar#
Metafield, bir kaynağa (sipariş, ürün, müşteri, mağaza) bağlı uygulama verisidir. Örneğin fatura uygulaması siparişe fatura numarasını, kargo uygulaması takip bağlantısını yazar. Metafield'lar panelde gösterilebilir ve başka uygulamalarla paylaşılabilir.
| Metot | Uç | Açıklama |
|---|---|---|
GET | /api/v1/metafields?ownerType=order&ownerId=…[&namespace=isbasi] | Listeleme |
PUT | /api/v1/metafields | Yazma (owner + namespace + key tekildir; aynı anahtar güncellenir) → { id, namespace, ownerType, ownerId, key, type, value, visibility, panel, own, updatedAt } |
DELETE | /api/v1/metafields/:id | Silme |
Alanlar#
| Alan | Değerler |
|---|---|
ownerType | order, product, customer, merchant |
ownerId | Kaynağın kimliği. ownerType: "merchant" için yok sayılır (kayıt kurulumun mağazasına bağlanır) |
namespace | Uygulamanızın slug'ı — sunucu atar, gövdede gönderilmez |
key | Anahtar; owner + namespace + key tekildir |
type | string, number, boolean, json, url |
value | En fazla 16 KB |
visibility | private (yalnız uygulamanız) ya da shared (aynı mağazadaki diğer uygulamalar okuyabilir) |
panel | { label: { tr, en }, show: true } → panelde gösterilir |
Kapsam#
Okuma ve yazma, kaynağın okuma kapsamını ister:
ownerType | Gerekli kapsam |
|---|---|
order | orders:read |
product | products:read |
customer | customers:read |
merchant | Kapsam gerekmez |
Panelde gösterim#
panel.show: true olan metafield'lar ilgili detay sayfasındaki "Uygulamalar" kartında label ile listelenir; url tipi tıklanabilir bağlantı olarak gösterilir. Panel bu kartı GET /api/merchant/apps/metafields?ownerType=order&ownerId=… ile doldurur.
await api.metafields.set({
ownerType: "order",
ownerId: orderId,
key: "invoiceNumber",
type: "string",
value: "ABC2026000000123",
visibility: "shared",
panel: { label: { tr: "İşbaşı fatura no", en: "İşbaşı invoice no" }, show: true },
});
await api.metafields.set({
ownerType: "order",
ownerId: orderId,
key: "invoiceUrl",
type: "url",
value: "https://ornek-fatura-portali.example/fatura/ABC2026000000123",
visibility: "private",
panel: { label: { tr: "Faturayı görüntüle", en: "View invoice" }, show: true },
});
const mine = await api.metafields.list({ ownerType: "order", ownerId: orderId, namespace: "isbasi" });Kaldırmada#
Uygulama kaldırıldığında panelde görünen metafield'lar gizlenir; veri 30 gün sonra temizlik işinde silinir.
Paylaşılan metafield'ların uygulamalar arası kullanımı için bkz. Uygulamalar Arası İletişim.