Skip to main content

title: Mimari description: “Hook handler, config loading ve policy evaluation’ın dahili olarak nasıl çalıştığı” icon: sitemap

Bu belgede failproofai’nin dahili olarak nasıl çalıştığı açıklanmaktadır: hook sistemi agent tool çağrılarını nasıl kesiştirir, konfigürasyon nasıl yüklenir ve birleştirilir, politikalar nasıl değerlendirilir ve dashboard agent aktivitesini nasıl izler.

Genel Bakış

failproofai iki bağımsız alt sisteme sahiptir:
  1. Hook handler - Claude Code’un her agent tool çağrısında çağırdığı hızlı bir CLI alt işlemi. Politikaları değerlendirir ve bir karar döndürür.
  2. Agent Monitor (Dashboard) - Agent oturumlarını izlemek ve politikaları yönetmek için bir Next.js web uygulaması.
Her iki alt sistem ~/.failproofai/ ve projenin .failproofai/ dizinindeki konfigürasyon dosyalarını paylaşır, ancak ayrı işlemler olarak çalışırlar ve yalnızca dosya sistemi aracılığıyla iletişim kurarlar.

Hook handler

Claude Code ile Entegrasyon

failproofai policies --install komutunu çalıştırdığınızda, ~/.claude/settings.json dosyasına şu gibi girişler yazar:
Claude Code daha sonra her tool çağrısından önce failproofai --hook PreToolUse komutunu alt işlem olarak çağırır ve stdin üzerinden bir JSON payload’u geçer.

Payload formatı

PostToolUse olayları için payload ayrıca tool_result içerir ve bu da tool’un çıktısını içerir. Handler, 1 MB stdin limitini uygular. Bu limiti aşan payload’lar atılır ve tüm politikalar örtülü olarak izin verir.

Response formatı

Reddet (PreToolUse):
Reddet (PostToolUse):
Talimat (Stop hariç herhangi bir olay):
Stop olay talimatı:
  • Exit kodu: 2
  • Sebep stderr’e yazılır (stdout’a değil)
İzin Ver:
  • Exit kodu: 0
  • Boş stdout
İleti ile izin ver: allow(message) bir politikanın, işlem izin verildiği halde Claude’a bilgisel bağlam göndermesine olanak tanır. Hook handler, aşağıdaki JSON’u stdout’a yazar (bir config dosyasına değil — bu, deny ve instruct response’ları gibi hook handler’ın Claude Code’a cevabıdır):
  • Exit kodu: 0 (işlem izin verildi)
  • Birden fazla politika allow ve bir ileti döndürdüğünde, mesajları newline’larla birleştirerek tek bir additionalContext string’ine dönüştürülür
  • Hiçbir politika mesaj sağlamıyorsa, stdout boştur (önceki gibi)

İşlem hattı

src/hooks/handler.ts tam hattı uygular:
Tipik payload’lar için LLM çağrısı olmadığında tüm işlem 100ms altında çalışır.

Konfigürasyon yükleme

src/hooks/hooks-config.ts üç kapsamlı config yükleme uygular.
Birleştirme mantığı:
  • enabledPolicies - üç dosya arasında çoğaltılmamış birleşim
  • policyParams - politika başına anahtar, tanımlayan ilk dosya tamamen kazanır
  • customPoliciesPath - tanımlayan ilk dosya kazanır
  • llm - tanımlayan ilk dosya kazanır
Web dashboard okuma ve yazma için readHooksConfig() (yalnızca global) kullanır, çünkü proje cwd’si ile çağrılmaz.

Politika değerlendirilmesi

src/hooks/policy-evaluator.ts politikaları sırayla çalıştırır. Her politika için:
  1. Politikanın params şemasını bulun (eğer varsa).
  2. policyParams[policy.name]’ı birleştirilmiş config’ten okuyun.
  3. Kullanıcı tarafından sağlanan değerleri şema varsayılanları üzerinden birleştirerek ctx.params’ı üretin.
  4. Çözülmüş bağlamla policy.fn(ctx) çağırın.
  5. Sonuç deny ise, hemen durun ve bu kararı döndürün.
  6. Sonuç instruct ise, mesajı biriktirin ve devam edin.
  7. Sonuç allow ise, sonraki politikaya devam edin.
Tüm politikalar çalıştıktan sonra:
  • deny döndürüldüyse, deny response’unu yayınlayın.
  • instruct dönüşleri toplandıysa, tüm mesajları birleştirerek tek bir instruct response’u yayınlayın.
  • Aksi takdirde, allow response’unu yayınlayın (boş stdout, exit 0).

Builtin politikalar

src/hooks/builtin-policies.ts 39 builtin politikanın tümünü BuiltinPolicyDefinition nesneleri olarak tanımlar:
params kabul eden politikalar, her parametre için tür ve varsayılan değer içeren PolicyParamsSchema bildirirler. Politika değerlendiricisi fn çağrılmadan önce çözülmüş değerleri ctx.params’a enjekte eder. Politika işlevleri varsayılanlar önce her zaman uygulandığı için ctx.params’ı null kontrolü yapmadan okurlar. Politika içindeki desen eşleştirme, ham string eşleştirmesi değil, ayrıştırılmış komut token’larını (argv) kullanır. Bu, shell operatörü enjeksiyonu yoluyla bypass’ı önler (örneğin sudo systemctl status * deseni ; rm -rf / ekleyerek bypass edilemez).

Custom politikalar

src/hooks/custom-hooks-registry.ts globalThis destekli bir kayıt defteri uygular:
src/hooks/custom-hooks-loader.ts kullanıcının politika dosyasını yükler:
  1. Config’ten customPoliciesPath’i okuyun; yoksa atla.
  2. Mutlak path’e çözün; dosyanın var olup olmadığını kontrol edin.
  3. Tüm from "failproofai" import’larını gerçek dist path’ine yeniden yazın, böylece customPolicies aynı globalThis kaydına çözülür.
  4. ESM uyumluluğunu sağlamak için geçişli lokal import’ları özyinelemeli olarak yeniden yazın.
  5. Geçici .mjs dosyaları yazın ve giriş dosyasını import() edin.
  6. Kayıtlı hook’ları almak için getCustomHooks()’u çağırın.
  7. finally bloğunda tüm geçici dosyaları temizleyin.
Herhangi bir hata durumunda (dosya bulunamadı, syntax hatası, import hatası), hata ~/.failproofai/hook.log’a kaydedilir ve loader boş dizi döndürür. Builtin politikalar etkilenmez. Custom politikalar tüm builtin politikaların ardından değerlendirilir. Bir custom politika deny’si yine de başka custom politikaları kısa devre yapabilir (ancak tüm builtin’ler zaten bu noktada çalışmış olmuştur).

Aktivite günlüğü

Her hook olayından sonra, handler ~/.failproofai/hook-activity.jsonl’ye bir JSONL satırı ekler:
Allow olmayan karar veren her politika için bir satır. Allow kararları günlüğe kaydedilmez (dosyayı küçük tutmak için).

Dashboard mimarisi

Dashboard, App Router ile React Server Components ve Server Actions kullanan bir Next.js 16 uygulamasıdır.
Veri akışı:
  • Sayfa bileşenleri, dosya sisteminden doğrudan proje/oturum verilerini okumak için lib/projects.ts ve lib/log-entries.ts çağırırlar (okumalar için API katmanı yok).
  • Policies sayfası tüm mutasyonlar (aç/kapat, params güncelleme, yükle/kaldır) için Server Actions kullanır.
  • Oturum görüntüleyicisi Claude’un JSONL transkript formatını ayrıştırır ve mesaj ile tool çağrılarından oluşan bir zaman çizelgesi renderlar.
Anahtar tasarım kararları:
  • Veritabanı yok - tüm kalıcı durum düz dosyalarda (~/.failproofai/, ~/.claude/projects/).
  • Mutasyonlar için Server Actions - CRUD işlemleri için REST API’ye gerek yok.
  • Okuma sayfaları için React Server Components - daha hızlı ilk yükleme, veri getirme için istemci demeti yok.
  • Client bileşenleri yalnızca etkileşimin gerekli olduğu yerlerde (politika açma/kapama, aktivite arama, günlük görüntüleyici).

Dosya düzeni