> ## Documentation Index
> Fetch the complete documentation index at: https://exosphere-auto-translate-docs-20260626-1023.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

title: ארכיטקטורה
description: "כיצד מטפל ה-hook, טעינת התצורה והערכת המדיניות פועלות בפנים"
icon: sitemap
-------------

מסמך זה מסביר כיצד failproofai פועל בפנים: כיצד מערכת ה-hook מיירטת קריאות כלי סוכן, כיצד תצורה נטענת ומתמזגת, כיצד מדיניות מוערכת, וכיצד לוח הבקרה מעקב אחר פעילות סוכן.

***

## סקירה כללית

ל-failproofai שתי תת-מערכות עצמאיות:

1. **מטפל ה-hook** - תהליך CLI מהיר שClaude Code משדר בכל קריאת כלי סוכן. מעריך מדיניות והחזר החלטה.
2. **Agent Monitor (Dashboard)** - יישום אינטרנט Next.js לניטור הפעלות סוכן וניהול מדיניות.

שתי תת-המערכות חולקות קבצי תצורה בתיקיות `~/.failproofai/` ו-`.failproofai/` של הפרויקט, אך הן פועלות כתהליכים נפרדים ותקשרות רק דרך מערכת הקבצים.

***

## מטפל ה-hook

### שילוב עם Claude Code

כאשר אתה מריץ `failproofai policies --install`, הוא כותב רשומות כמו זו ל-`~/.claude/settings.json`:

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

Claude Code לאחר מכן משדר את `failproofai --hook PreToolUse` כתהליך משנה לפני כל קריאת כלי, תוך העברת מטען JSON על stdin.

### פורמט מטען

```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`, המטען מכיל גם `tool_result` עם פלט הכלי.

המטפל אוכף מגבלת stdin של 1 MB. מטענים החוצים זאת מושלכים והכל מדיניות מרומז כן.

### פורמט תגובה

**Deny (PreToolUse):**

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

**Deny (PostToolUse):**

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

**Instruct (כל אירוע מלבד Stop):**

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

**Stop event instruct:**

* קוד יציאה: `2`
* סיבה כתובה ל-stderr (לא stdout)

**Allow:**

* קוד יציאה: `0`
* stdout ריק

**Allow עם הודעה:**

`allow(message)` מאפשר למדיניות לשלוח הקשר מידע חזרה ל-Claude גם כאשר הפעולה מותרת. מטפל ה-hook כותב את ה-JSON הבא ל-**stdout** (לא קובץ תצורה — זהו התגובה של מטפל ה-hook ל-Claude Code, בדיוק כמו תגובות deny ו-instruct לעיל):

```json theme={null}
// Written to stdout by the hook handler process
{
  "hookSpecificOutput": {
    "additionalContext": "All CI checks passed on branch 'feat/my-feature'."
  }
}
```

* קוד יציאה: `0` (הפעולה מותרת)
* כאשר מדיניות מרובות מחזירות `allow` עם הודעה, ההודעות שלהן מחוברות בשורות חדשות ל-`additionalContext` בודד
* אם אין מדיניות המספקת הודעה, stdout ריק (כמו קודם)

### צינור עיבוד

`src/hooks/handler.ts` מיישם את כל הצינור:

```text theme={null}
stdin JSON
  → parse payload (max 1 MB)
  → extract session metadata (session_id, cwd, tool_name, tool_input, etc.)
  → readMergedHooksConfig(cwd)    ← merges project + local + global config
  → register enabled builtin policies with resolved params
  → load custom policies from customPoliciesPath (if set)
  → register custom policies into policy registry
  → evaluate all policies (builtins first, then custom)
      → first deny short-circuits
      → instruct decisions accumulate
      → allow messages accumulate
  → write JSON decision to stdout
  → persist event to ~/.failproofai/hook-activity.jsonl
  → exit
```

כל התהליך רץ תחת 100ms עבור מטענים טיפוסיים ללא קריאות LLM.

***

## טעינת תצורה

`src/hooks/hooks-config.ts` מיישם טעינת תצורה בתחום שלוש-שלבי.

```text theme={null}
[1] {cwd}/.failproofai/policies-config.json        ← project  (highest priority)
[2] {cwd}/.failproofai/policies-config.local.json  ← local
[3] ~/.failproofai/policies-config.json             ← global   (lowest priority)
```

לוגיקת מיזוג:

* `enabledPolicies` - union מפושט בכל שלוש הקבצים
* `policyParams` - לכל-מדיניות מפתח, הקובץ הראשון המגדיר אותו מנצח לחלוטין
* `customPoliciesPath` - הקובץ הראשון המגדיר אותו מנצח
* `llm` - הקובץ הראשון המגדיר אותו מנצח

לוח הבקרה של האינטרנט משתמש ב-`readHooksConfig()` (global בלבד) לקריאה וכתיבה, מכיוון שהוא לא משודר עם cwd של פרויקט.

***

## הערכת מדיניות

`src/hooks/policy-evaluator.ts` מריץ מדיניות לפי הסדר.

לכל מדיניות:

1. חפש את סכמת `params` של המדיניות (אם יש לה).
2. קרא `policyParams[policy.name]` מתוך התצורה המתמזגת.
3. מזג ערכים שסופקו על ידי משתמש על ברירות מחדל של סכמה כדי להפיק `ctx.params`.
4. קרא `policy.fn(ctx)` עם ההקשר שנפתר.
5. אם התוצאה היא `deny`, עצור מיד והחזר החלטה זו.
6. אם התוצאה היא `instruct`, צבור את ההודעה והמשך.
7. אם התוצאה היא `allow`, המשך למדיניות הבאה.

לאחר שכל המדיניות רצה:

* אם הוחזר `deny` כלשהו, פלוט את תגובת ה-deny.
* אם הוחזר `instruct` כלשהו, פלוט תגובת instruct בודדת עם כל ההודעות מחוברות.
* אחרת, פלוט תגובת allow (stdout ריק, exit 0).

***

## מדיניות מובנית

`src/hooks/builtin-policies.ts` מגדיר את כל 39 המדיניות המובנית כאובייקטי `BuiltinPolicyDefinition`:

```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` מכריזה על `PolicyParamsSchema` עם סוגים וברירות מחדל לכל פרמטר. מעריך המדיניות מוזרק ערכים שנפתרו ל-`ctx.params` לפני קריאה ל-`fn`. פונקציות מדיניות קוראות `ctx.params` ללא הגנת null כי ברירות מחדל תמיד מיושמות קודם.

התאמת דפוס בתוך מדיניות משתמשת בעטוקנים של פקודה מנותחים (argv), לא התאמת מחרוזת גולמית. זה מונע עוקף דרך הזרקת אופרטור shell (למשל דפוס עבור `sudo systemctl status *` לא יכול להיות bypassed על ידי הוספת `; rm -rf /` לפקודה).

***

## מדיניות מותאמת אישית

`src/hooks/custom-hooks-registry.ts` מיישם רישום מבוסס `globalThis`:

```typescript theme={null}
const REGISTRY_KEY = "__failproofai_custom_hooks__";

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

export function getCustomHooks(): CustomHook[] { ... }
export function clearCustomHooks(): void { ... }  // used in tests
```

`src/hooks/custom-hooks-loader.ts` טוען את קובץ המדיניות של המשתמש:

1. קרא `customPoliciesPath` מתצורה; דלג אם כןנעדר.
2. פתור לנתיב מוחלט; בדוק שהקובץ קיים.
3. שכתב את כל ייבואי `from "failproofai"` לנתיב dist בפועל כדי ש-`customPolicies` יפתור לאותו רישום `globalThis`.
4. שכתב רקורסיבי ייבואים מקומיים חולפים כדי להבטיח תאימות ESM.
5. כתוב קבצי `.mjs` זמניים ו-`import()` קובץ הערך.
6. קרא `getCustomHooks()` כדי לאחזר hooks שנרשמו.
7. נקה את כל הקבצים הזמניים בבלוק `finally`.

בכל שגיאה (קובץ לא נמצא, שגיאת תחביר, כישלון ייבוא), השגיאה מתועדת ל-`~/.failproofai/hook.log` והמטען מחזיר מערך ריק. מדיניות מובנית אינה מושפעת.

מדיניות מותאמת אישית מוערכת לאחר כל המדיניות המובנית. ה-deny של מדיניות מותאמת אישית עדיין מפסיק מדיניות מותאמות אישיות נוספות (אבל כל המובנויות כבר רצו בנקודה זו).

***

## רישום פעילות

לאחר כל אירוע hook, המטפל מוסיף שורת JSONL ל-`~/.failproofai/hook-activity.jsonl`:

```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. החלטות allow אינן מתועדות (כדי לשמור את הקובץ קטן).

***

## ארכיטקטורה לוח הבקרה

לוח הבקרה הוא יישום **Next.js 16** תוך שימוש ב-App Router עם React Server Components ו-Server Actions.

```text theme={null}
app/
  layout.tsx                  ← Root layout (theme, telemetry, nav)
  projects/page.tsx           ← Server component: list all Claude projects
  project/[name]/page.tsx     ← Server component: list sessions in a project
  project/[name]/session/
    [sessionId]/page.tsx      ← Server component: render session viewer
  policies/page.tsx           ← Client component: policy management + activity log
  actions/
    get-hooks-config.ts       ← Read config + policy list
    update-hooks-config.ts    ← Toggle policy on/off
    update-policy-params.ts   ← Update policy parameters
    get-hook-activity.ts      ← Paginate/search activity log
    install-hooks-web.ts      ← Install/remove hooks from the browser
  api/
    download/[project]/[session]/route.ts   ← Per-CLI session export (JSONL or JSON)
```

**זרימת נתונים:**

* רכיבי עמוד קוראים `lib/projects.ts` ו-`lib/log-entries.ts` כדי לקרוא נתוני פרויקט/session ישירות מהמערכת קבצים (אין שכבת API לקריאה).
* עמוד המדיניות משתמש ב-Server Actions לכל התמורות (toggle, עדכון params, התקנה/הסרה).
* מסמך ה-session מנתח את פורמט התמלול JSONL של Claude ומעבד ציר זמן של הודעות וקריאות כלי.

**החלטות עיצוב מפתח:**

* אין מסד נתונים - כל מצב קבוע נמצא בקבצים רגילים (`~/.failproofai/`, `~/.claude/projects/`).
* Server Actions למוטציות - אין צורך בAPI REST עבור פעולות CRUD.
* React Server Components לעמודי קריאה - קריאה ראשונית מהירה יותר, אין חבילת לקוח עבור הביאת נתונים.
* רכיבי לקוח רק שם צריך אינטראקטיביות (toggles מדיניות, חיפוש פעילות, צופה יומן).

***

## פריסת קובץ

```text theme={null}
failproofai/
├── bin/
│   └── failproofai.mjs           # CLI router (hook / dashboard / install / etc.)
├── src/hooks/
│   ├── handler.ts                # Hook event pipeline
│   ├── builtin-policies.ts       # 39 policy definitions
│   ├── policy-evaluator.ts       # Policy execution engine
│   ├── policy-registry.ts        # Policy registration and lookup
│   ├── policy-types.ts           # TypeScript interfaces
│   ├── hooks-config.ts           # Multi-scope config loading
│   ├── custom-hooks-registry.ts  # globalThis-backed hook registry
│   ├── custom-hooks-loader.ts    # ESM loader for user JS hooks
│   ├── manager.ts                # install / remove / list operations
│   ├── install-prompt.ts         # Interactive policy selection prompt
│   ├── hook-logger.ts            # Logging to hook.log
│   ├── hook-activity-store.ts    # Persist activity to hook-activity.jsonl
│   └── llm-client.ts             # LLM API client (for AI-powered policies)
├── app/                          # Next.js dashboard (pages + server actions)
├── lib/                          # Shared utilities
│   ├── projects.ts               # Enumerate Claude projects from filesystem
│   ├── log-entries.ts            # Parse Claude transcript JSONL format
│   ├── paths.ts                  # Resolve system paths
│   └── ...
├── components/                   # Shared React UI components
├── contexts/                     # React context providers (theme, auto-refresh, telemetry)
├── examples/                     # Example custom hook files
└── __tests__/                    # Unit and E2E tests
```
