Sırların Gidecek Bir Yeri Yok — Vault'un Doğuşu · Vault Serisi 1/3
Bir akşam bir test kullanıcısına imzalı bir APK göndermem gerekti. WhatsApp dosyayı bozdu, e-posta 25 MB'de durdu, sonunda WeTransfer'a yükleyip linki Slack'e attım. Link kimsenin elinde ne kadar kalacaktı, kim indirmişti, indirildikten sonra nasıl iptal edecektim — hiçbirinin cevabı yoktu. O an düşündüm: hassas bir dosyayı koyabileceğim, kontrolün bende kaldığı bir yer neden yok?
Bu, Vault'u yazmaya nasıl başladığımın hikâyesi. Üç yazılık bir serinin birincisi. Burada kod yok; bir rahatsızlığın nasıl bir karara, bir kararın nasıl bir altyapıya dönüştüğü var.
Bir dosyayı nereye koyarsın?
Hikâye sıkıcı derecede sıradan. Bir test kullanıcısına imzalı bir APK göndermem gerekiyordu. Önce WhatsApp — dosyayı "belge" diye yolladım, karşı taraf "açılmıyor" dedi, çünkü sıkıştırmış. E-posta denedim, 25 MB sınırına takıldım. Sonunda klasik çözüm: WeTransfer'a yükle, linki kopyala, Slack'e yapıştır.
Link gitti, dosya indirildi, iş halloldu. Ama o gece aklımda bir soru kaldı:
- O link şu an kimin elinde?
- Kaç kere indirildi?
- Yarın "bu build'i geri çek" desem, linki nasıl iptal ederim?
- WeTransfer o dosyayı diskinde şifreli mi tutuyor, ne kadar tutuyor?
Hiçbirinin cevabı bende değildi. Bir sırrı —çünkü imzalı bir build, bir sırdır— kontrolüm dışındaki bir kanaldan, kontrolüm dışındaki bir sunucuya bırakmıştım. Ve bu, o hafta yaptığım onuncu şeydi. Bir .env dosyası, bir müşteri raporu, bir veritabanı yedeği, bir API anahtarı seti... Hepsi aynı yolculuğu yapıyordu: yanlış kanaldan, yanlış yere.
"Sır" dediğimiz şeyin tuhaf hayatı
Bir saniye durup düşününce, hassas dosyaların aslında hiçbir aracın birinci sınıf vatandaşı olmadığını fark ettim.
- E-posta metin için tasarlandı, eki sonradan ekledi.
- Slack/WhatsApp anlık mesajlaşma için var, dosya orada bir yan ürün.
- WeTransfer/Dropbox link için var ama "link bir sır" gerçeğini umursamıyor — link sızarsa dosya sızar.
- S3 presigned URL daha yakın ama ham bir yapı taşı; üstüne kimlik, yetki, denetim, iptal politikası yazman gerekiyor.
Hiçbiri şu basit cümleyi merkezine almıyordu: "Bu dosya bir sır ve onun nereye, ne kadar süreyle, kaç kez gideceğine ben karar vermeliyim."
İlk içgüdü tabii "bir tane daha mı yazacaksın, hazır araç kullan" demek. Ama soruyu tersinden sorunca cevap netleşti: hazır araçların hiçbiri bana kontrolü vermiyordu. Bana bir kolaylık veriyorlardı, karşılığında sahipliği alıyorlardı. Sır söz konusu olduğunda bu takas yanlış.
Neden hazır bir servis değil?
Üç şeyi aynı anda istiyordum ve piyasadaki hiçbir araç üçünü birden, benim sahipliğimde sunmuyordu:
- Diskte şifreli dursun. Sunucu çalınsa, disk imajı sızsa bile dosyalar anlaşılmaz olsun. Şifreleme anahtarı bende olsun, sağlayıcıda değil.
- Kim, neye, hangi rolle erişiyor — ben belirleyeyim. Proje bazlı. Bir kişi A projesinin dosyalarını görsün, B'yi görmesin.
- Her şey iz bıraksın, her şey geri alınabilsin. Kim ne indirdi, link ne zaman açıldı, hangi dosya ne zaman silindi — hepsi kayıtlı. Ve bir link, istediğim an ölsün.
Bu üçü bir araya geldiğinde, ortaya çıkan şey bir "dosya yükleme aracı" değil. Ortaya çıkan şey bir güven sınırı: içinde sırların yaşadığı, dışarıyla yalnızca benim koyduğum kurallarla konuşan kapalı bir alan. Self-hosted olmasının tek sebebi inat değil — güven sınırının sahibi benim olmam gerekiyordu.
Üç sütun: şifreli, yetkili, izlenebilir
Vault'u yazmaya oturduğumda elimde bir özellik listesi yoktu. Üç sütun vardı:
- Şifreli → Dosya MinIO'ya (S3 uyumlu depolama) yazılmadan önce AES-256-GCM ile şifrelensin. Anahtar yoksa düz yazılsın ama anahtar varsa hiçbir bayt çıplak diske düşmesin.
- Yetkili → Kullanıcılar, projeler, roller. Bir dosya bir projeye ait; bir kullanıcı bir projeye bir rolle bağlı. Erişim bu üçgenden doğsun.
- İzlenebilir → Her anlamlı eylem bir denetim kaydı bıraksın. Her paylaşım linki sonlu olsun — süreyle, indirme sayısıyla, ya da benim bir komutumla.
İlginç olan şu: bu üç sütunu bir kez kabul ettiğimde, sonraki kararların çoğu kendiliğinden yerine oturdu. "Dosya silince ne olur?" → şifreli nesne ve denetim kaydı ne olur, onu düşün. "Aynı isimli dosya tekrar yüklenirse?" → yetki aynı, ama sürüm yeni olmalı. "Link süresi dolunca?" → dosya gerçekten gitmeli mi, yoksa sadece link mi ölmeli? Her soru üç sütundan birine yaslanıyordu.
"Paylaşım" bir özellik değil, bir altyapı
Burada vurgulamak istediğim bir nokta var, çünkü atlanması kolay. Çoğu kişi dosya paylaşımını bir özellik gibi düşünür — bir uygulamanın köşesine eklenen "paylaş" düğmesi. Bense onu bir altyapı katmanı olarak görmeye başladım.
Analojisi şu: 20 yıl önce her uygulama kendi kullanıcı tablosunu, kendi oturum yönetimini kendi içinde, kötü kurardı. Sonra "kimlik" ayrı bir katman olarak kabul edildi. Bugün hassas dosya paylaşımı da aynı yerde: her ekip bunu kendi içinde, e-posta ve WeTransfer yamalarıyla, izsiz ve geri alınamaz biçimde yapıyor. Vault'un yapmaya çalıştığı şey, bu katmanı dışarı çıkarmak — bir sırrın güvenli biçimde yer değiştirmesini, her uygulamanın yeniden icat etmek zorunda kalmadığı ortak bir altyapıya dönüştürmek.
Bu zihinsel model bir kez oturduğunda, Vault artık "benim dosya kasam" değil. CLI'dan da, web arayüzünden de, bir AI ajanının çağırdığı bir araçtan da erişilebilen ortak bir kapı. İnsan da makine de aynı sınırdan geçiyor, aynı kurallara tabi.
Tek cümlelik manifesto
Vault'a başlarken kendime bir cümle kurdum, hâlâ orada duruyor ve hâlâ beni kötü kararlardan koruyor:
"Vault, bir sırrın kontrollü biçimde yer değiştirebildiği yerdir."
Bu cümlede dört kelime taşıyıcı:
- Sır → sıradan dosya değil; korunmaya değer bir şey. Şifreleme buradan geliyor.
- Kontrollü → kim, ne kadar, kaç kez. Yetki ve denetim buradan geliyor.
- Yer değiştirebildiği → durağan bir arşiv değil; paylaşılan, indirilen, akan bir şey. Streaming ve paylaşım linkleri buradan geliyor.
- Yer → tek bir sınır, sahibi belli. Self-hosted oluşu buradan geliyor.
Bir özellik eklemek istediğimde bu cümleye danıştım. "Bu, bir sırrın kontrollü yer değiştirmesine hizmet ediyor mu?" Etmiyorsa eklemedim. Bu kadar basit bir filtrenin ne kadar çok gereksiz işten kurtardığını anlatamam.
Sen de aynı yolculuğu mu yaptırıyorsun?
Buraya kadar okuduysan, muhtemelen senin de bir imzalı build'in, bir müşteri raporun, bir kimlik bilgisi setin geçen hafta yanlış bir kanaldan geçti. Bunun çözümü illa kendi Vault'unu yazmak olmak zorunda değil. Ama bir yere oturup şunu sormaya değer:
"Gönderdiğim sırlar üzerindeki kontrol kimde — bende mi, kullandığım kanalda mı?"
Cevap "kanalda" ise, farkında olmadan sahipliği devretmişsin demektir. Cevap "bende" olmasını istiyorsan, o zaman muhtemelen senin de bir güven sınırına ihtiyacın var.
Sonraki yazıda Vault'un çekirdeğine ineceğiz: neden egzotik bir yığın yerine yalnızca Go, PostgreSQL ve MinIO seçtiğim; 600 MB'lık bir dosyanın RAM'e hiç düşmeden nasıl aktığı; ve AES-256-GCM şifrelemesinin bir dosyayı 64 KB'lık parçalara bölerken aslında neyi koruduğu.
Ama bu yazıyı şu cümleyle bitirmek istiyorum, çünkü Vault'un ruhunu en iyi o özetliyor: bir sır, gideceği yere senin koyduğun kurallarla gitmeli — ya da hiç gitmemeli.