Building an Accounting API That Survives an Audit
A practical guide to the security and audit controls a financial API needs before Dutch businesses trust it with their books.
Bir ödeme yazma işlemine 200 OK döndüren bir muhasebe API'si, size neredeyse hiçbir şey söylememiş demektir. Bu yanıt; defteri kebirin (ledger) kaydı işlediğini, eylemi gerçekleştireenin bunu yapmaya yetkili olduğunu, tutarın doğrulamadan geçtiğini veya yetkili birinin bunu onayladığını doğrulamaz. Vergi dairesinin kayıtların yeniden oluşturulabilmesini ve yedi yıl boyunca saklanmasını beklediği Hollanda'daki işletmeler için "istek başarılı oldu" ile "defterler doğru" arasındaki bu boşluk, denetimlerin başarısız olduğu noktadır.
Denetime hazır olmak (audit-ready), bir sertifika değil, operasyonel bir tasarım hedefidir. Bu, API'nin eksiksiz bir zincir koruduğu anlamına gelir: kimliği doğrulanmış aktörden yetkilendirilmiş eyleme, doğrulanmış durum değişikliğinden onaya, defteri kebir sonucundan kurcalamaya karşı korumalı kanıta kadar. Aşağıdaki her şey, kimlik doğrulamanın ve TLS'nin bu durumu kurtaracağını varsaymak yerine, bu zinciri bilinçli olarak inşa etmekle ilgilidir.
Bir muhasebe API'sini "denetime hazır" kılan şey nedir
Bir işlemi yeniden oluşturan bir denetçi, belirli bir soru dizisini yanıtlamaya ihtiyaç duyar. Bunu kim başlattı? Yetkileri var mıydı? Değişiklik muhasebe doğrulamasından geçti mi? Bunu kim onayladı? Defteri kebir ne kaydetti? Bu kayıt, sonradan iz bırakmadan değiştirilebilir mi?
API'niz kendi günlüklerinden ve veri modelinden bu altı sorunun tümünü yanıtlayamıyorsa, kodu ne kadar temiz görünürse görsün denetime hazır değildir. Çoğu API ilk soruyu iyi, geri kalanını ise kötü yönetir.
Bu boşluğu kapatan kontroller birkaç gruba ayrılır: açık muhasebe durumu, katmanlı yetkilendirme, kapsamlı kimlik doğrulama, yinelenmeyen (idempotent) yazma işlemleri, sunucu tarafında doğrulama, görevler ayrılığı (segregation of duties) ve kurcalamaya karşı korumalı günlük kaydı. Bunlar birbirini destekler. Zayıf bir yetkilendirme, güçlü bir denetim günlüğünü zayıflatır; çünkü artık günlüğe kaydedilen aktörün söz konusu eylemi gerçekleştirmeye hakkı olduğundan emin olamazsınız.
Uç noktaları (endpoint) modellemeden önce muhasebe durumlarını modelleyin
En yaygın tasarım hatası, her finansal kaydı create, read, update, delete (oluşturma, okuma, güncelleme, silme) işlemlerine sahip, özgürce düzenlenebilir bir nesne olarak ele almaktır. Muhasebe bu şekilde çalışmaz ve bir denetçi, deftere işlenmiş (posted) bir yevmiye kaydının sessizce üzerine yazılabildiğini hemen fark eder.
Finansal açıdan önemli her kaynağın açık bir durum makinesine (state machine) ihtiyacı vardır. Bir yevmiye kaydı veya ödeme tipik olarak şu aşamalardan geçer:
draft → submitted → approved → posted → settled
Düzeltmeler bu yolu geri sarmaz. Yanlış olan deftere işlenmiş bir kayıt, bağlantılı bir ters kayıt (reversal) veya denkleştirici bir düzeltme alır. Orijinal kayıt olduğu gibi kalır.
İşinize yarayacak bir kural seti:
- Taslaklar yetkili kullanıcılar tarafından düzenlenebilir.
- Gönderilen kayıtlar yalnızca izin verilen roller tarafından düzenlenebilir veya taslağa geri döndürülebilir.
- Onaylanan kayıtlar, kontrollü bir değişiklik ve yeni bir onay gerektirir.
- Deftere işlenen kayıtların üzerine yazılamaz veya bu kayıtlar silinemez, yalnızca tersine çevrilebilir veya düzeltilebilir.
- Kapanmış dönem değişiklikleri; üst düzey yetkilendirme, belirtilen bir gerekçe ve bir denetim olayı gerektirir.
Deftere işlenmiş bir kaydı düzenlemeye çalışmak gibi yasadışı bir geçiş denemesi, kararlı (stable) bir hata döndürmeli ve yine de bir denetim kaydı yazmalıdır. Başarısız deneme de bir kanıttır.
Değişmez (immutable) çift taraflı defteri kebir tam da burada değer kazanır. Nordlet'in defteri kebir bileşeni, her işlemin taahhüt (commit) anında bir veritabanı tetikleyicisiyle dengesi sağlanan, dengeli ve kalıcı bir kayıt olarak düşmesini sağlayacak şekilde tasarlanmıştır; düzeltmeler yeniden yazmak yerine ters kayıtlar aracılığıyla gerçekleşir. Bu kısıtlama geliştirme sırasında kısıtlayıcı gibi hissedilir, ancak denetim sırasında muhasebecinizin güvendiği şeye dönüşür.
Yalnızca kimlik doğrulamakla kalmayın, her isteği yetkilendirin
Kimlik doğrulama (authentication), arayanın kim olduğunu kanıtlar. Bu arayanın belirli bir faturaya, yevmiyeye veya tüzel kişiliğe dokunup dokunamayacağı hakkında hiçbir şey söylemez. OWASP API Güvenliği Projesi, eksik kontroller nedeniyle kiracılar arası (cross-tenant) erişimi kolaylaştıran nesne düzeyinde yetkilendirme açıklarını (broken object-level authorization) risk listesinin başına koymaktadır.
Finansal bir API'ye gelen her istek, yalnızca bir belirteçle (token) değil, bir dizi faktörün kombinasyonuna karşı yetkilendirilmelidir:
- kimliği doğrulanmış aktör
- istemci uygulaması veya servis hesabı
- kiracı (tenant)
- tüzel kişilik
- kaynak kimliği (resource ID)
- istenen işlem
- mevcut kaynak durumu
- tutar veya işlem eşiği
Pratikte iki kural diğerlerinden daha önemlidir. İlk olarak, kiracı ve kullanıcı bağlamını kimliği doğrulanmış kimlikten türetin ve bununla çelişen hiçbir istemci kaynaklı kiracı veya rol iddiasını (claim) kabul etmeyin. Bir arayan, asla hangi şirket adına hareket ettiğini kendi iddia edebilmelidir. İkinci olarak, varsayılan olarak reddet (deny-by-default) yaklaşımını kullanın. Hiçbir politika açıkça bir eyleme izin vermiyorsa, eylem başarısız olur.
Her iki yönü de test edin. Bir kiracının diğer kiracının verilerine eriştiği yatay erişim ile normal bir kullanıcının onay, deftere işleme veya dışa aktarma işlevlerine eriştiği dikey erişim. İkisi de yaygındır ve muhasebe verilerinde felakete yol açar.
Nordlet'in tek bir hesap altında birden fazla şirket genelinde sahip (owner), yönetici (admin), muhasebeci (accountant), müdür (manager), geliştirici (developer) ve görüntüleyici (viewer) rolleri içeren rol modeli, bu ayrımı bir temenni olmaktan çıkarıp uygulanabilir kılmak için vardır. Taslak fatura oluşturabilen bir geliştirici rolü, ödemeleri serbest bırakabilme yetkisine sahip olmamalıdır.
Belirteçleri CRUD fiillerine değil, iş yeteneklerine göre kapsamlandırın
Temsili (delegated) erişim için, yeniden kullanılabilir şifreler veya geniş statik API anahtarları yerine güncel OAuth 2.0 güvenlik kılavuzunu kullanın. RFC 9700, mevcut En İyi Uygulama (Best Current Practice) standardıdır ve istemciler ile yetkilendirme sunucuları için net gereksinimler belirler: doğrulanmış yönlendirme URI'leri, geçerli olduğu durumlarda PKCE, ihraççı ve hedef kitle (audience) kontrolleri, kısa erişim belirteci ömürleri ve iptal mekanizmalı yenileme belirteci (refresh-token) rotasyonu.
Kapsamlandırma (scoping) kararı, muhasebeye özel düşünce yapısının kendini gösterdiği yerdir. read ve write gibi genel kapsamlar, görevler ayrılığı için neredeyse işe yaramaz. Kapsamlar yeteneklerle eşleşmelidir:
journal:createvejournal:approveayrı kapsamlardır.- Ödeme talimatı oluşturmak, onu serbest bırakma izni vermez.
- Dışa aktarma izni okuma izninden farklıdır, çünkü toplu dışa aktarma bir veri sızıntısı yoludur.
Belirli bir ürünün bu ölçekte nerede durtuğunu net bir şekilde belirleyin. Nordlet'in API anahtarları, her eylemde kontrol edilen sales:read ve sales:write gibi modül başına kapsamlar taşır; bu, modülleri ve okuma/yazma işlemlerini ayırır ancak oluşturma ile onaylama işlemlerini ayırmaz; bu daha hassas ayrım bölünmesine bugün ihtiyacınız varsa, çağrıdan önce kendi hizmetinizde bunu uygulayın.
Yüksek değerli işlemler için FAPI 2.0 Güvenlik Profili'nin geçerli olup olmadığını değerlendirmeye değer. Hassas finansal verileri koruyan API'ler için tasarlanmıştır ve temel OAuth'a göre daha güçlü garantiler sunar. Çoğu KOBİ muhasebe entegrasyonunun tam profile ihtiyacı olmayacaktır, ancak ödeme bırakma ve banka bağlantı akışları bunu düşünmek için doğru yerlerdir.
Nordlet'in tek kullanımlık e-posta bağlantıları aracılığıyla şifresiz oturum açma (passwordless sign-in) özelliği, insan kullanıcılar için yeniden kullanılabilir şifre sorununu ortadan kaldırır. Bu da döndürülecek, sızdırılacak veya oltalama (phishing) saldırısına uğrayacak bir kimlik bilgisinin daha azalması demektir.
Finansal yazma işlemlerini yinelenemez (idempotent) yapın
Ağlar istek sırasında kesilebilir. Bir istemci ödeme talimatı gönderir, yanıt gelmeden bağlantı kopar ve istemci yeniden deneme (retry) yapar. Koruma olmadan, artık iki ödemeniz olur.
Yinelenmeme anahtarları (idempotency keys) bunu çözer. İstemci her yazma işleminde benzersiz bir anahtar gönderir; sunucu anahtarı ve sonucunu kaydeder. Aynı anahtarla yapılan bir yeniden deneme, ikinci bir giriş oluşturmak yerine orijinal sonucu döndürür. Nordlet, her mutating (değiştiren) çağrıda bir Idempotency-Key üst bilgisini (header) kabul eder, aynı yük (payload) ile yapılan yeniden denemede saklanan yanıtı yeniden oynatır ve değiştirilmiş bir yük ile aynı anahtarı reddeder. Bu özelliği atlayan herhangi bir muhasebe API'si, birisinin elle çözmesi gereken mükerrer defteri kebir kayıtları üretmeye mahkumdur.
Bunu sunucu tarafı doğrulamayla eşleştirin. Borçların alacaklara eşit olduğunu, KDV oranının ülke ve dönem için geçerli olduğunu veya bir hesabın var olduğunu kontrol etmek için asla istemciye güvenmeyin. Doğrulama sunucuda, durum geçişinden önce çalışır ve reddedilen bir yazma işlemi kararlı bir hata ile bir denetim kaydı üretir.
Kurcalamaya karşı korumalı denetim izleri ve Hollanda saklama kuralları
Denetim günlüğü kanıt katmanıdır ve sıradan iş verilerinden farklı gereksinimlere sahiptir. Yetkilendirme kararını, politika sürümünü, aktörü, nesneyi, işlemi, önceki ve yeni durumu ve neden kodunu (reason code), asla sırları veya tam ödeme kimlik bilgilerini kaydetmeden kaydetmelidir.
Kritik özellik, kurcalamaya karşı korumalı (tamper-evident) olmasıdır. Bir yönetici denetim kayıtlarını sessizce düzenleyebilir veya silebilirse, günlüğün hiçbir kanıt değeri yoktur. Yalnızca ekleme yapılabilen depolama (append-only storage), kriptografik zincirleme veya bir kez yazılıp tekrar yazılamayan saklama (write-once retention) yöntemleri bunların tümünü ele alır. Buradaki mesele, yapılan bir değişikliğin tespit edilebilir olmasıdır.
Saklama (retention), ticari kayıt silme işlemlerinden ayrı bir politikayı hak eder. Hollanda'da idari kayıtlar için genel saklama süresi yedi yıldır ve gayrimenkullere ilişkin kayıtlar için bu süre on yıla çıkar. Sıradan veri silme ve GDPR silme iş akışlarınız, yasal bir saklama kuralının hâlâ kapsadığı kayıtları veya denetim kanıtlarını yok edemez. Yasal saklama (legal hold), arşivleme ve silme kurallarını denetim kanıtları için bağımsız olarak tanımlayın ve bunları faaliyet gösterdiğiniz yargı bölgeleriyle eşleştirin.
Dönem kilitleme (period locking), bunu muhasebe katmanında destekler. Bir ay kapatıldıktan sonra, içindeki kayıtlar üst düzey yetkilendirme ve günlüğe kaydedilmiş bir gerekçe olmaksızın değiştirilemez. Nordlet, kapalı ayların kapalı kalmasını sağlamak için dönem kilitlemeyi zorunlu kılar; kilitli bir döneme ait tarihe sahip herhangi bir deftere işleme girişimini API üzerinden bile reddeder; bu, Hollandalı bir denetçinin ilk kontrol ettiği şeylerden biridir.
Uç noktaları güvence altına alın: webhook'lar, dışa aktarmalar ve entegrasyonlar
Çekirdek API genellikle sistemin en iyi korunan kısmıdır. Uç noktalar veri sızdırır.
Webhook'lar sahte istek riski (forged-request risk) taşır. sale_invoice.paid gibi bir olay, alıcının sizden geldiğini doğrulayabilmesi için imzalanmalıdır ve alıcılar teslimatı en az bir kez (at-least-once) olarak ele almalı, tekilleştirme (deduplication) için olay kimliğini (event ID) kullanmalıdır. Nordlet, her webhook teslimini ham gövde (raw body) üzerinde bir HMAC imzasıyla imzalar ve başarısız teslimatları üstel artışla (exponential backoff) yeniden dener; böylece alıcı, tam olarak bir kez teslimat (exactly-once delivery) varsaymak yerine imzayı doğrulamalı ve olay kimliğine göre tekilleştirme yapmalıdır.
Dışa aktarmalar (exports) toplu veri sızıntısı yoludur. XLSX, PDF veya JSON formatındaki rapor dışa aktarmaları, tek bir işlemde büyük hacimli finansal verileri çeker; bu nedenle kendi izinlerine, oran sınırlamalarına (rate limits) ve denetim günlüklerine ihtiyaç duyarlar. Kullandığınız üçüncü taraf entegrasyonları güvenilmeyen girdi olarak ele alınmalı ve doğrudan istemci isteklerini doğruladığınız şekilde doğrulanmalıdır.
Hollanda muhasebe API'si için denetime hazır olma kontrol listesi
Bir entegrasyonun denetime hazır olduğunu iddia etmeden önce şunları kullanın:
- Her finansal kaynakta açık durum makinesi; deftere işlenmiş kayıtların üzerine yazılamaz
- Her istekte nesne ve tüzel kişilik düzeyinde yetkilendirme, varsayılan olarak reddetme
- İstemci iddialarından değil, belirteçten türetilen kiracı ve rol bağlamı
- RFC 9700'e göre OAuth 2.0; yetenek tabanlı kapsamlar; ayrı oluşturma ve onaylama rolleri
- Yalnızca belgelenmiş değil, rollerde zorunlu kılınan görevler ayrılığı
- Tüm finansal yazma işlemlerinde yinelenmeme anahtarları (idempotency keys)
- Durum geçişlerinden önce sunucu tarafında muhasebe ve KDV doğrulaması
- Neden kodları içeren, yalnızca ekleme yapılabilen, kurcalamaya karşı korumalı denetim günlüğü
- Hollanda dönemleriyle eşleştirilmiş saklama ve yasal saklama kuralları (yedi yıl, mülk için on yıl)
- Kapatılan aylarda dönem kilitleme
- Tekilleştirme özellikli imzalı webhook'lar; kapsamlandırılmış, oran sınırlamalı, günlüğe kaydedilmiş dışa aktarmalar
İlk olarak ne inşa ederdik
Yarın Hollanda merkezli bir platforma muhasebe entegre edecek olsaydık, tek bir iş uç noktası yazmadan önce durum modeline ve nesne düzeyinde yetkilendirmeye başlardık. Bu iki karar, sonraki her şeyi kısıtlar ve defteri kebir kayıtlarını düzenlenebilir satırlar olarak ele alan bir sisteme bunları sonradan uyarlamak son derece zordur. Yinelenmeme ve denetim günlüğü sıradakilerdir; çünkü bunları erken eklemek ucuz, veriler akmaya başladıktan sonra eklemek ise pahalıdır.
Geri kalanlar (kapsamlandırılmış belirteçler, imzalı webhook'lar, dönem kilitleme) temel sağlamsa daha kolay bir şekilde takip eder. Bunların tümü, hiçbir şey üretim verilerine dokunmadan önce bir sandbox şirketi üzerinde test edilebilir.
FAQ
Denetime hazır bir API, işletmenin mevzuata uygun olduğu anlamına mı gelir?
Hayır ve bu konuda net olmakta fayda var. Denetime hazır olmak, sistemin bir tasarım özelliğidir: defteri kebir, kontroller ve kanıt zinciri, bir denetimin başarılı olabileceği şekilde inşa edilmiştir. Belirli bir vergi, muhasebe veya güvenlik çerçevesine uygunluk (compliance), bu kontrolleri belirli bir standartla eşleştiren ayrı bir değerlendirmedir. İyi inşa edilmiş bir API uyumluluk çalışmasını kolaylaştırır, ancak onun yerini almaz.
Hollanda'da muhasebe kayıtlarının ne kadar süreyle saklanması gerekir?
Genel yükümlülük idari kayıtlar için yedi yıldır ve gayrimenkullere bağlı kayıtlar için on yıla kadar uzar. Sıradan silme iş akışlarınızın geçersiz kılamayacağı saklama ve yasal saklama kuralları oluşturun.
Finansal bir entegrasyon için statik bir API anahtarı yeterli midir?
Dar kapsamlı sunucudan sunucuya otomasyon için işe yarayabilir, ancak yeniden kullanılabilir statik anahtarların döndürülmesi zordur ve sızdırıldığında tehlikelidir. Temsili erişim ve insan odaklı herhangi bir akış için, kısa ömürlü, yetenek kapsamlı belirteçlere sahip OAuth 2.0 daha güçlü bir seçenektir.
Yinelenmeme (idempotency) özellikle muhasebe için neden bu kadar önemlidir?
Çoğu sistemde mükerrer bir yazma işlemi can sıkıntısıdır, ancak muhasebede mükerrer bir yazma işlemi, birinin bulup tersine çevirmesi gereken defterlerdeki yanlış bir sayıdır. Yinelenmeme anahtarları, yeniden denemeleri riskli değil güvenli hale getirir.
İleri okumalar
- Güncel API risk kategorileri için OWASP API Güvenliği Projesi
- Temsili erişim gereksinimleri için RFC 9700: OAuth 2.0 Güvenliği En İyi Uygulaması
- Hollanda'daki vergi tablosunun pratikte nasıl göründüğü hakkında Hollanda'daki geliştiriciler için gerçek zamanlı AB KDV'si
- Kapsamlar, yinelenmeme, hatalar ve webhook imzalama için API kuralları