> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

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:

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "failproofai --hook PreToolUse"
          }
        ]
      }
    ],
    "PostToolUse": [ ... ]
  }
}
```

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ı

```json theme={null}
{
  "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 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):**

```json theme={null}
{
  "hookSpecificOutput": {
    "permissionDecision": "deny",
    "permissionDecisionReason": "Blocked by failproofai: sudo command blocked"
  }
}
```

**Reddet (PostToolUse):**

```json theme={null}
{
  "hookSpecificOutput": {
    "additionalContext": "Blocked by failproofai because: API key detected in output"
  }
}
```

**Talimat (Stop hariç herhangi bir olay):**

```json theme={null}
{
  "hookSpecificOutput": {
    "additionalContext": "Instruction from failproofai: Verify tests pass before committing."
  }
}
```

**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):

```json theme={null}
// Hook handler işlemi tarafından stdout'a yazıldı
{
  "hookSpecificOutput": {
    "additionalContext": "All CI checks passed on branch 'feat/my-feature'."
  }
}
```

* 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:

```text theme={null}
stdin JSON
  → payload'ı ayrıştır (maksimum 1 MB)
  → oturum metadata'sını çıkart (session_id, cwd, tool_name, tool_input, vb.)
  → readMergedHooksConfig(cwd)    ← proje + lokal + global config'i birleştirir
  → etkin builtin politikaları çözülmüş parametrelerle kayıt et
  → customPoliciesPath'ten custom politikaları yükle (ayarlanmışsa)
  → custom politikaları politika kaydına kayıt et
  → tüm politikaları değerlendir (builtin'ler önce, sonra custom'lar)
      → ilk deny hemen durdurur
      → instruct kararları birikir
      → allow mesajları birikir
  → karar JSON'unu stdout'a yaz
  → olayı ~/.failproofai/hook-activity.jsonl'ye kaydet
  → çık
```

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.

```text theme={null}
[1] {cwd}/.failproofai/policies-config.json        ← proje  (en yüksek öncelik)
[2] {cwd}/.failproofai/policies-config.local.json  ← lokal
[3] ~/.failproofai/policies-config.json             ← global (en düşük öncelik)
```

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:

```typescript theme={null}
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ü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:

```typescript theme={null}
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. 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:

```json theme={null}
{
  "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
}
```

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.

```text theme={null}
app/
  layout.tsx                  ← Root layout (tema, telemetri, nav)
  projects/page.tsx           ← Server component: tüm Claude projelerini listele
  project/[name]/page.tsx     ← Server component: bir projedeki oturumları listele
  project/[name]/session/
    [sessionId]/page.tsx      ← Server component: oturum görüntüleyiciyi renderla
  policies/page.tsx           ← Client component: politika yönetimi + aktivite günlüğü
  actions/
    get-hooks-config.ts       ← Config + politika listesini oku
    update-hooks-config.ts    ← Politikayı aç/kapat
    update-policy-params.ts   ← Politika parametrelerini güncelle
    get-hook-activity.ts      ← Aktivite günlüğünü sayfalandır/ara
    install-hooks-web.ts      ← Hook'ları tarayıcıdan yükle/kaldır
  api/
    download/[project]/[session]/route.ts   ← CLI başına oturum dışa aktar (JSONL veya JSON)
```

**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

```text theme={null}
failproofai/
├── bin/
│   └── failproofai.mjs           # CLI yönlendiricisi (hook / dashboard / install / vb.)
├── src/hooks/
│   ├── handler.ts                # Hook olay 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ı config yükleme
│   ├── custom-hooks-registry.ts  # globalThis destekli hook kaydı
│   ├── custom-hooks-loader.ts    # Kullanıcı JS hook'ları için ESM yükleyicisi
│   ├── manager.ts                # yükle / kaldır / listele işlemleri
│   ├── install-prompt.ts         # Etkileşimli politika seçimi istemi
│   ├── hook-logger.ts            # hook.log'a günlükleme
│   ├── hook-activity-store.ts    # Aktiviteyi hook-activity.jsonl'ye kaydet
│   └── llm-client.ts             # LLM API istemcisi (AI destekli politikalar için)
├── app/                          # Next.js dashboard (sayfalar + server actions)
├── lib/                          # Paylaşılan yardımcılar
│   ├── projects.ts               # Dosya sisteminden Claude projelerini numaralandır
│   ├── log-entries.ts            # Claude transkript JSONL formatını ayrıştır
│   ├── paths.ts                  # Sistem path'lerini çözümle
│   └── ...
├── components/                   # Paylaşılan React UI bileşenleri
├── contexts/                     # React bağlam sağlayıcıları (tema, auto-refresh, telemetri)
├── examples/                     # Örnek custom hook dosyaları
└── __tests__/                    # Birim ve E2E testleri
```
