Ana içeriğe atla

title: Mimari description: “Hook işleyicisinin, config yüklemesinin ve politika değerlendirmesinin dahili olarak nasıl çalıştığı” icon: sitemap

Bu belge failproofai’nin dahili olarak nasıl çalıştığını açıklar: hook sistemi aracı araç çağrılarını nasıl yakalar, yapılandırma nasıl yüklenir ve birleştirilir, politikalar nasıl değerlendirilir ve kontrol paneli aracı etkinliğini nasıl izler.

Genel Bakış

failproofai iki bağımsız alt sisteme sahiptir:
  1. Hook işleyicisi - Claude Code’un her aracı araç çağrısında çağırdığı hızlı bir CLI alt süreci. Politikaları değerlendirir ve bir karar döndürür.
  2. Aracı İzleyicisi (Kontrol Paneli) - Aracı oturumlarını izlemek ve politikaları yönetmek için Next.js web uygulaması.
Her iki alt sistem ~/.failproofai/ ve projenin .failproofai/ dizinindeki yapılandırma dosyalarını paylaşır, ancak ayrı süreçler olarak çalışır ve yalnızca dosya sistemi aracılığıyla iletişim kurar.

Hook işleyicisi

Claude Code ile Entegrasyon

failproofai policies --install komutunu çalıştırdığınızda, ~/.claude/settings.json dosyasına şu gibi girişler yazar:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "failproofai --hook PreToolUse"
          }
        ]
      }
    ],
    "PostToolUse": [ ... ]
  }
}
Claude Code daha sonra her araç çağrısından önce failproofai --hook PreToolUse komutunu bir alt süreç olarak çağırır ve stdin üzerinde bir JSON yükü iletir.

Yük biçimi

{
  "session_id": "abc123",
  "transcript_path": "/home/user/.claude/projects/myproject/sessions/abc123.jsonl",
  "cwd": "/home/user/myproject",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "sudo apt install nodejs" }
}
PostToolUse olayları için yük, araçın çıktısını içeren tool_result da içerir. İşleyici 1 MB stdin sınırını uygular. Bu sınırı aşan yükler atılır ve tüm politikalar örtük olarak izin verir.

Yanıt biçimi

Reddet (PreToolUse):
{
  "hookSpecificOutput": {
    "permissionDecision": "deny",
    "permissionDecisionReason": "Blocked by failproofai: sudo command blocked"
  }
}
Reddet (PostToolUse):
{
  "hookSpecificOutput": {
    "additionalContext": "Blocked by failproofai because: API key detected in output"
  }
}
Talimat (Stop hariç herhangi bir olay):
{
  "hookSpecificOutput": {
    "additionalContext": "Instruction from failproofai: Verify tests pass before committing."
  }
}
Stop olay talimatı:
  • Çıkış kodu: 2
  • Sebep stderr’e yazılmıştır (stdout değil)
İzin ver:
  • Çıkış kodu: 0
  • Boş stdout
İzin ver ve mesaj: allow(message) bir politikanın, işlem izin verildiğinde bile Claude’a bilgilendirici bağlam göndermesine izin verir. Hook işleyicisi aşağıdaki JSON’u stdout’a yazar (yapılandırma dosyası değil — bu, deny ve instruct yanıtlarının üstünde olduğu gibi hook işleyici sürecinin Claude Code’a yanıtıdır):
// Hook işleyici süreci tarafından stdout'a yazılmıştır
{
  "hookSpecificOutput": {
    "additionalContext": "All CI checks passed on branch 'feat/my-feature'."
  }
}
  • Çıkış kodu: 0 (işleme izin verildi)
  • Birden fazla politika ileti içeren allow döndürdüğünde, iletileri yeni satırlarla birleştirerek tek bir additionalContext dizesine katılırlar
  • Hiçbir politika ileti sağlamazsa, stdout boştur (öncekiyle aynı)

İşlem hattı

src/hooks/handler.ts tam işlem hattını uygular:
stdin JSON
  → yükü ayrıştır (maks 1 MB)
  → oturum metaverilerini çıkar (session_id, cwd, tool_name, tool_input, vb.)
  → readMergedHooksConfig(cwd)    ← proje + yerel + global yapılandırmayı birleştir
  → etkin yerleşik politikaları çözümlenen parametrelerle kayıt et
  → customPoliciesPath'ten özel politikaları yükle (ayarlandıysa)
  → özel politikaları politika kaydına kayıt et
  → tüm politikaları değerlendir (yerleşiklerin ardından özel olanlar)
      → ilk reddet kısa devresi
      → talimat kararları birikir
      → mesajlara izin verilir ve birikir
  → JSON kararını stdout'a yaz
  → olayı ~/.failproofai/hook-activity.jsonl'ye kalıcı hale getir
  → çık
Tüm işlem, LLM çağrıları olmayan tipik yükler için 100ms altında çalışır.

Yapılandırma Yükleme

src/hooks/hooks-config.ts üç kapsamlı config yükleme uygular.
[1] {cwd}/.failproofai/policies-config.json        ← proje  (en yüksek öncelik)
[2] {cwd}/.failproofai/policies-config.local.json  ← yerel
[3] ~/.failproofai/policies-config.json             ← global   (en düşük öncelik)
Birleştirme mantığı:
  • enabledPolicies - her üç dosya arasında tekilleştirilen birleşim
  • policyParams - politika başına anahtar, ilk dosya tamamen kazanır
  • customPoliciesPath - ilk dosya kazanır
  • llm - ilk dosya kazanır
Web kontrol paneli yalnızca global yapılandırma için readHooksConfig() kullanır çünkü bir proje cwd ile çağrılmaz.

Politika Değerlendirmesi

src/hooks/policy-evaluator.ts politikaları sırayla çalıştırır. Her politika için:
  1. Politikanın params şemasını ara (varsa).
  2. Birleştirilen yapılandırmadan policyParams[policy.name] oku.
  3. Kullanıcı tarafından sağlanan değerleri şema varsayılanları üzerine birleştirerek ctx.params üret.
  4. policy.fn(ctx) komutunu çözümlenen bağlamla çağır.
  5. Sonuç deny ise, hemen durdur ve bu kararı döndür.
  6. Sonuç instruct ise, mesajı biriktir ve devam et.
  7. Sonuç allow ise, sonraki politikaya devam et.
Tüm politikalar çalıştıktan sonra:
  • Herhangi bir deny döndürülürse, reddet yanıtını yayınla.
  • Herhangi bir instruct dönüşü toplanırsa, tüm mesajlarla birleştirilerek tek bir instruct yanıtı yayınla.
  • Aksi takdirde, izin yanıtını yayınla (boş stdout, çıkış 0).

Yerleşik Politikalar

src/hooks/builtin-policies.ts tüm 39 yerleşik politikayı BuiltinPolicyDefinition nesneleri olarak tanımlar:
interface BuiltinPolicyDefinition {
  name: string;
  description: string;
  fn: (ctx: PolicyContext) => PolicyResult;
  match: {
    events: HookEventType[];
    tools?: string[];
  };
  defaultEnabled: boolean;
  category: string;
  beta?: boolean;
  params?: PolicyParamsSchema;
}
params kabul eden politikalar her parametre için türler ve varsayılanlar içeren PolicyParamsSchema bildirir. Politika değerlendiricisi, fn çağrılmadan önce çözümlenen değerleri ctx.params öğesine enjekte eder. Politika işlevleri, varsayılanlar her zaman ilk olarak uygulandığı için ctx.params öğesini null kontrol yapmadan okur. Politikalar içindeki desen eşleştirmesi, ham dize eşleştirmesinden değil, ayrıştırılmış komut belirteçlerini (argv) kullanır. Bu, shell operatörü enjeksiyonu aracılığıyla bypass’ı önler (örneğin, sudo systemctl status * için bir desen, komuta ; rm -rf / eklenerek bypass edilemez).

Özel Politikalar

src/hooks/custom-hooks-registry.ts bir globalThis tabanlı kayıt defteri uygular:
const REGISTRY_KEY = "__failproofai_custom_hooks__";

export const customPolicies = {
  add(hook: CustomHook): void { ... }
};

export function getCustomHooks(): CustomHook[] { ... }
export function clearCustomHooks(): void { ... }  // testlerde kullanılır
src/hooks/custom-hooks-loader.ts kullanıcının politika dosyasını yükler:
  1. Yapılandırmadan customPoliciesPath öğesini oku; yoksa atla.
  2. Mutlak yola çöz; dosyanın var olduğunu kontrol et.
  3. Tüm from "failproofai" içe aktarımlarını gerçek dist yoluna yeniden yaz, böylece customPolicies aynı globalThis kaydına çözülür.
  4. ESM uyumluluğunu sağlamak için geçişli yerel içe aktarımları yinelemeli olarak yeniden yaz.
  5. Geçici .mjs dosyaları yaz ve giriş dosyasını import() et.
  6. Kayıtlı kancaları almak için getCustomHooks() çağır.
  7. finally bloğunda tüm geçici dosyaları temizle.
Herhangi bir hata (dosya bulunamadı, söz dizimi hatası, içe aktarma hatası) üzerinde, hata ~/.failproofai/hook.log dosyasına kaydedilir ve yükleyici boş bir dizi döndürür. Yerleşik politikalar etkilenmez. Özel politikalar tüm yerleşik politikalardan sonra değerlendirilir. Özel bir politika deny yine de başka özel politikaları kısa devre yapar (ancak bu noktada tüm yerleşikler zaten çalıştırılmıştır).

Etkinlik Günlüğü

Her hook olayından sonra, işleyici ~/.failproofai/hook-activity.jsonl dosyasına bir JSONL satırı ekler:
{
  "timestamp": "2026-04-06T12:34:56.789Z",
  "sessionId": "abc123",
  "eventType": "PreToolUse",
  "toolName": "Bash",
  "policyName": "block-sudo",
  "decision": "deny",
  "reason": "sudo command blocked by failproofai",
  "durationMs": 12
}
İzin vermeyen bir karar alan her politika için bir satır. İzin kararları günlüğe kaydedilmez (dosyayı küçük tutmak için).

Kontrol Paneli Mimarisi

Kontrol paneli, React Server Components ve Server Actions ile App Router kullanan bir Next.js 16 uygulamasıdır.
app/
  layout.tsx                  ← Kök düzen (tema, telemetri, gezinti)
  projects/page.tsx           ← Sunucu bileşeni: tüm Claude projelerini listele
  project/[name]/page.tsx     ← Sunucu bileşeni: bir projedeki oturumları listele
  project/[name]/session/
    [sessionId]/page.tsx      ← Sunucu bileşeni: oturum görüntüleyiciyi oluştur
  policies/page.tsx           ← İstemci bileşeni: politika yönetimi + etkinlik günlüğü
  actions/
    get-hooks-config.ts       ← Yapılandırmayı ve politika listesini oku
    update-hooks-config.ts    ← Politikayı aç/kapat
    update-policy-params.ts   ← Politika parametrelerini güncelle
    get-hook-activity.ts      ← Etkinlik günlüğünü sayfalandır/ara
    install-hooks-web.ts      ← Tarayıcıdan kancaları yükle/kaldır
  api/
    download/[project]/[session]/route.ts   ← CLI başına oturum dışa aktarımı (JSONL veya JSON)
Veri akışı:
  • Sayfa bileşenleri, proje/oturum verilerini dosya sisteminden doğrudan okumak için lib/projects.ts ve lib/log-entries.ts komutlarını çağırır (okumalar için API katmanı yok).
  • Politikalar sayfası, tüm mutasyonlar (değiştir, parametreleri güncelle, yükle/kaldır) için Server Actions kullanır.
  • Oturum görüntüleyicisi Claude’un JSONL transkript biçimini ayrıştırır ve iletilerin ve araç çağrılarının bir zaman çizelgesini oluşturur.
Temel tasarım kararları:
  • Veritabanı yok - tüm kalıcı durum düz dosyalardadır (~/.failproofai/, ~/.claude/projects/).
  • Mutasyonlar için Server Actions - CRUD işlemleri için REST API gerekli değildir.
  • Okuma sayfaları için React Server Components - daha hızlı ilk yükleme, veri getirme için istemci paketi yok.
  • İstemci bileşenleri yalnızca etkileşimin gerekli olduğu yerlerde (politika açma/kapatma, etkinlik arama, günlük görüntüleyicisi).

Dosya Düzeni

failproofai/
├── bin/
│   └── failproofai.mjs           # CLI yönlendiricisi (hook / dashboard / install / vb.)
├── src/hooks/
│   ├── handler.ts                # Hook olay işlem hattı
│   ├── builtin-policies.ts       # 39 politika tanımı
│   ├── policy-evaluator.ts       # Politika yürütme motoru
│   ├── policy-registry.ts        # Politika kaydı ve araması
│   ├── policy-types.ts           # TypeScript arayüzleri
│   ├── hooks-config.ts           # Çok kapsamlı yapılandırma yükleme
│   ├── custom-hooks-registry.ts  # globalThis tabanlı kanca kaydı
│   ├── custom-hooks-loader.ts    # Kullanıcı JS kancaları için ESM yükleyicisi
│   ├── manager.ts                # yükle / kaldır / listele işlemleri
│   ├── install-prompt.ts         # Etkileşimli politika seçim istemi
│   ├── hook-logger.ts            # hook.log dosyasına günlüğe kaydetme
│   ├── hook-activity-store.ts    # Etkinliği hook-activity.jsonl dosyasına kalıcı hale getir
│   └── llm-client.ts             # LLM API istemcisi (AI güçlü politikalar için)
├── app/                          # Next.js kontrol paneli (sayfalar + sunucu işlemleri)
├── lib/                          # Paylaşılan yardımcılar
│   ├── projects.ts               # Dosya sisteminden Claude projelerini numaralandır
│   ├── log-entries.ts            # Claude transkript JSONL biçimini ayrıştır
│   ├── paths.ts                  # Sistem yollarını çöz
│   └── ...
├── components/                   # Paylaşılan React UI bileşenleri
├── contexts/                     # React bağlam sağlayıcıları (tema, otomatik yenileme, telemetri)
├── examples/                     # Örnek özel kanca dosyaları
└── __tests__/                    # Birim ve E2E testleri