मुख्य सामग्री पर जाएं

title: आर्किटेक्चर description: “हुक हैंडलर, कॉन्फ़िग लोडिंग, और पॉलिसी मूल्यांकन आंतरिक रूप से कैसे काम करते हैं” icon: sitemap

यह दस्तावेज़ failproofai कैसे आंतरिक रूप से काम करता है, यह समझाता है: कैसे हुक सिस्टम एजेंट टूल कॉल को इंटरसेप्ट करता है, कॉन्फ़िग कैसे लोड और मर्ज होता है, पॉलिसीज़ का मूल्यांकन कैसे होता है, और डैशबोर्ड एजेंट गतिविधि की निगरानी कैसे करता है।

सारांश

failproofai के दो स्वतंत्र सबसिस्टम हैं:
  1. हुक हैंडलर - एक तेज़ CLI सबप्रोसेस जो Claude Code हर एजेंट टूल कॉल पर आमंत्रित करता है। पॉलिसीज़ का मूल्यांकन करता है और एक निर्णय देता है।
  2. एजेंट मॉनिटर (डैशबोर्ड) - एजेंट सेशन की निगरानी और पॉलिसीज़ प्रबंधन के लिए एक Next.js वेब एप्लिकेशन।
दोनों सबसिस्टम ~/.failproofai/ और प्रोजेक्ट की .failproofai/ डायरेक्टरी में कॉन्फ़िग फ़ाइलें साझा करते हैं, लेकिन ये अलग प्रक्रियाओं के रूप में चलते हैं और केवल फ़ाइलसिस्टम के माध्यम से संचार करते हैं।

हुक हैंडलर

Claude Code के साथ एकीकरण

जब आप failproofai policies --install चलाते हैं, तो यह ~/.claude/settings.json में इस तरह की प्रविष्टियां लिखता है:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "failproofai --hook PreToolUse"
          }
        ]
      }
    ],
    "PostToolUse": [ ... ]
  }
}
Claude Code फिर प्रत्येक टूल कॉल से पहले failproofai --hook PreToolUse को एक सबप्रोसेस के रूप में आमंत्रित करता है, stdin पर एक JSON पेलोड पास करता है।

पेलोड फॉर्मेट

{
  "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 भी होता है। हैंडलर 1 MB stdin लिमिट को लागू करता है। इससे अधिक पेलोड को डिस्कार्ड कर दिया जाता है और सभी पॉलिसीज़ निहितार्थ से अनुमति देती हैं।

प्रतिक्रिया फॉर्मेट

अस्वीकार करें (PreToolUse):
{
  "hookSpecificOutput": {
    "permissionDecision": "deny",
    "permissionDecisionReason": "Blocked by failproofai: sudo command blocked"
  }
}
अस्वीकार करें (PostToolUse):
{
  "hookSpecificOutput": {
    "additionalContext": "Blocked by failproofai because: API key detected in output"
  }
}
निर्देशित करें (Stop को छोड़कर कोई भी इवेंट):
{
  "hookSpecificOutput": {
    "additionalContext": "Instruction from failproofai: Verify tests pass before committing."
  }
}
Stop इवेंट निर्देशित करें:
  • Exit कोड: 2
  • कारण stderr (stdout नहीं) में लिखा गया है
अनुमति दें:
  • Exit कोड: 0
  • खाली stdout
संदेश के साथ अनुमति दें: allow(message) एक पॉलिसी को Claude को सूचनात्मक संदर्भ भेजने देता है भले ही ऑपरेशन की अनुमति हो। हुक हैंडलर निम्नलिखित JSON को stdout में लिखता है (कॉन्फ़िग फ़ाइल में नहीं — यह Claude Code को हैंडलर की प्रतिक्रिया है, अस्वीकार करें और निर्देशित करें प्रतिक्रिया की तरह):
// हुक हैंडलर प्रक्रिया द्वारा stdout में लिखा गया
{
  "hookSpecificOutput": {
    "additionalContext": "All CI checks passed on branch 'feat/my-feature'."
  }
}
  • Exit कोड: 0 (ऑपरेशन की अनुमति है)
  • जब कई पॉलिसीज़ संदेश के साथ allow देते हैं, तो उनके संदेश नई पंक्तियों के साथ एक एकल additionalContext स्ट्रिंग में जुड़ते हैं
  • यदि कोई पॉलिसी संदेश प्रदान नहीं करती है, तो stdout खाली है (पहले की तरह)

प्रोसेसिंग पाइपलाइन

src/hooks/handler.ts पूरी पाइपलाइन को लागू करता है:
stdin JSON
  → पेलोड को पार्स करें (अधिकतम 1 MB)
  → सेशन मेटाडेटा निकालें (session_id, cwd, tool_name, tool_input, आदि)
  → readMergedHooksConfig(cwd)    ← प्रोजेक्ट + स्थानीय + वैश्विक कॉन्फ़िग को मर्ज करता है
  → सक्षम बिल्ट-इन पॉलिसीज़ को हल किए गए पैरामीटर के साथ पंजीकृत करें
  → customPoliciesPath से कस्टम पॉलिसीज़ लोड करें (यदि सेट किया गया है)
  → पॉलिसी रजिस्ट्री में कस्टम पॉलिसीज़ पंजीकृत करें
  → सभी पॉलिसीज़ का मूल्यांकन करें (पहले बिल्ट-इन, फिर कस्टम)
      → पहला अस्वीकार छोटा-परिपथ करता है
      → निर्देशित निर्णय जमा होते हैं
      → संदेश की अनुमति जमा होती है
  → JSON निर्णय stdout में लिखें
  → इवेंट को ~/.failproofai/hook-activity.jsonl में सहेजें
  → बाहर निकलें
LLM कॉल के बिना विशिष्ट पेलोड के लिए पूरी प्रक्रिया 100ms में चलती है।

कॉन्फ़िग लोडिंग

src/hooks/hooks-config.ts तीन-स्कोप कॉन्फ़िग लोडिंग को लागू करता है।
[1] {cwd}/.failproofai/policies-config.json        ← प्रोजेक्ट  (सर्वोच्च प्राथमिकता)
[2] {cwd}/.failproofai/policies-config.local.json  ← स्थानीय
[3] ~/.failproofai/policies-config.json             ← वैश्विक   (निम्नतम प्राथमिकता)
मर्ज लॉजिक:
  • enabledPolicies - सभी तीनों फ़ाइलों में डिडुप्लिकेटेड यूनियन
  • policyParams - प्रति-पॉलिसी कुंजी, पहली फ़ाइल जो इसे परिभाषित करती है पूरी तरह जीतती है
  • customPoliciesPath - पहली फ़ाइल जो इसे परिभाषित करती है जीतती है
  • llm - पहली फ़ाइल जो इसे परिभाषित करती है जीतती है
वेब डैशबोर्ड पढ़ने और लिखने के लिए readHooksConfig() (केवल वैश्विक) का उपयोग करता है, क्योंकि यह प्रोजेक्ट 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 लौटाया गया था, तो अस्वीकार प्रतिक्रिया जारी करें।
  • यदि कोई instruct रिटर्न एकत्र किए गए थे, तो सभी संदेशों को जुड़ा हुआ एक एकल निर्देशित प्रतिक्रिया जारी करें।
  • अन्यथा, अनुमति प्रतिक्रिया जारी करें (खाली stdout, exit 0)।

बिल्ट-इन पॉलिसीज़

src/hooks/builtin-policies.ts सभी 26 बिल्ट-इन पॉलिसीज़ को BuiltinPolicyDefinition ऑब्जेक्ट के रूप में परिभाषित करता है:
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 घोषित करती हैं। पॉलिसी मूल्यांकन fn को कॉल करने से पहले हल किए गए मानों को ctx.params में इंजेक्ट करता है। पॉलिसी फ़ंक्शन ctx.params को पढ़ते हैं बिना null-गार्डिंग के क्योंकि डिफ़ॉल्ट हमेशा पहले लागू किए जाते हैं। पॉलिसीज़ के अंदर पैटर्न मिलान कच्ची स्ट्रिंग मिलान के बजाय पार्स किए गए कमांड टोकन (argv) का उपयोग करता है। यह शेल ऑपरेटर इंजेक्शन के माध्यम से बाईपास को रोकता है (उदाहरण के लिए sudo systemctl status * के लिए एक पैटर्न ; rm -rf / को कमांड में जोड़ने से बाईपास नहीं किया जा सकता)।

कस्टम पॉलिसीज़

src/hooks/custom-hooks-registry.ts एक globalThis-समर्थित रजिस्ट्री को लागू करता है:
const REGISTRY_KEY = "__failproofai_custom_hooks__";

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

export function getCustomHooks(): CustomHook[] { ... }
export function clearCustomHooks(): void { ... }  // परीक्षण में उपयोग किया जाता है
src/hooks/custom-hooks-loader.ts उपयोगकर्ता की पॉलिसी फ़ाइल लोड करता है:
  1. कॉन्फ़िग से customPoliciesPath पढ़ें; अगर अनुपस्थित हो तो छोड़ें।
  2. निरपेक्ष पथ के लिए हल करें; फ़ाइल का अस्तित्व जांचें।
  3. सभी from "failproofai" आयातों को वास्तविक dist पाथ में फिर से लिखें ताकि customPolicies उसी globalThis रजिस्ट्री में हल हो।
  4. ESM संगतता सुनिश्चित करने के लिए संक्रमणीय स्थानीय आयातों को पुनरावर्ती रूप से फिर से लिखें।
  5. अस्थायी .mjs फ़ाइलें लिखें और प्रविष्टि फ़ाइल को import() करें।
  6. पंजीकृत हुक को पुनः प्राप्त करने के लिए getCustomHooks() को कॉल करें।
  7. finally ब्लॉक में सभी अस्थायी फ़ाइलें साफ करें।
किसी भी त्रुटि पर (फ़ाइल नहीं मिली, सिंटैक्स त्रुटि, आयात विफल), त्रुटि को ~/.failproofai/hook.log में लॉग किया जाता है और लोडर एक खाली सरणी लौटाता है। बिल्ट-इन पॉलिसीज़ प्रभावित नहीं होती हैं। कस्टम पॉलिसीज़ सभी बिल्ट-इन पॉलिसीज़ के बाद मूल्यांकन किए जाते हैं। एक कस्टम पॉलिसी deny अभी भी आगे की कस्टम पॉलिसीज़ को छोटा-परिपथ करता है (लेकिन उस बिंदु पर सभी बिल्ट-इन पहले से ही चल चुकी हैं)।

गतिविधि लॉगिंग

प्रत्येक हुक इवेंट के बाद, हैंडलर ~/.failproofai/hook-activity.jsonl में एक JSONL लाइन जोड़ता है:
{
  "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
}
गैर-अनुमति निर्णय लेने वाली प्रत्येक पॉलिसी के लिए एक पंक्ति। अनुमति निर्णय लॉग नहीं किए जाते हैं (फ़ाइल को छोटा रखने के लिए)।

डैशबोर्ड आर्किटेक्चर

डैशबोर्ड एक Next.js 16 एप्लिकेशन है जो App Router को React Server Components और Server Actions के साथ उपयोग करता है।
app/
  layout.tsx                  ← रूट लेआउट (थीम, टेलीमेट्री, नेव)
  projects/page.tsx           ← सर्वर घटक: सभी Claude प्रोजेक्ट्स सूचीबद्ध करें
  project/[name]/page.tsx     ← सर्वर घटक: प्रोजेक्ट में सेशन सूचीबद्ध करें
  project/[name]/session/
    [sessionId]/page.tsx      ← सर्वर घटक: सेशन दर्शक प्रदान करें
  policies/page.tsx           ← क्लाइंट घटक: पॉलिसी प्रबंधन + गतिविधि लॉग
  actions/
    get-hooks-config.ts       ← कॉन्फ़िग + पॉलिसी सूची पढ़ें
    update-hooks-config.ts    ← पॉलिसी को चालू/बंद करें
    update-policy-params.ts   ← पॉलिसी पैरामीटर अपडेट करें
    get-hook-activity.ts      ← गतिविधि लॉग को पेजिनेट/खोजें
    install-hooks-web.ts      ← ब्राउज़र से हुक इंस्टॉल/निकालें
  api/
    download/[project]/[session]/route.ts   ← सेशन को ZIP/JSONL के रूप में निर्यात करें
डेटा फ्लो:
  • पृष्ठ घटक lib/projects.ts और lib/log-entries.ts को कॉल करते हैं ताकि सीधे फ़ाइलसिस्टम से प्रोजेक्ट/सेशन डेटा पढ़ा जा सके (पढ़ने के लिए कोई API परत नहीं)।
  • पॉलिसीज़ पृष्ठ सभी उत्परिवर्तन के लिए Server Actions का उपयोग करता है (टॉगल, पैरामीटर अपडेट, इंस्टॉल/निकालें)।
  • सेशन दर्शक Claude के JSONL ट्रांसक्रिप्ट फॉर्मेट को पार्स करता है और संदेश और टूल कॉल की एक समय सूची प्रदान करता है।
मुख्य डिज़ाइन निर्णय:
  • कोई डेटाबेस नहीं - सभी स्थायी स्थिति सादा फ़ाइलों में है (~/.failproofai/, ~/.claude/projects/)।
  • उत्परिवर्तन के लिए Server Actions - CRUD संचालन के लिए कोई REST API की आवश्यकता नहीं।
  • पढ़ने वाले पृष्ठों के लिए React Server Components - तेजी से प्रारंभिक लोड, डेटा फेचिंग के लिए कोई क्लाइंट बंडल नहीं।
  • क्लाइंट घटक केवल जहां इंटरएक्टिविटी आवश्यक है (पॉलिसी टॉगल, गतिविधि खोज, लॉग दर्शक)।

फ़ाइल लेआउट

failproofai/
├── bin/
│   └── failproofai.mjs           # CLI राउटर (हुक / डैशबोर्ड / इंस्टॉल / आदि)
├── src/hooks/
│   ├── handler.ts                # हुक इवेंट पाइपलाइन
│   ├── builtin-policies.ts       # 26 पॉलिसी परिभाषाएं
│   ├── policy-evaluator.ts       # पॉलिसी निष्पादन इंजन
│   ├── policy-registry.ts        # पॉलिसी पंजीकरण और लुकअप
│   ├── policy-types.ts           # TypeScript इंटरफेस
│   ├── hooks-config.ts           # बहु-स्कोप कॉन्फ़िग लोडिंग
│   ├── custom-hooks-registry.ts  # globalThis-समर्थित हुक रजिस्ट्री
│   ├── custom-hooks-loader.ts    # उपयोगकर्ता JS हुक के लिए ESM लोडर
│   ├── manager.ts                # इंस्टॉल / निकालें / सूची संचालन
│   ├── install-prompt.ts         # इंटरएक्टिव पॉलिसी चयन प्रॉम्प्ट
│   ├── hook-logger.ts            # hook.log में लॉगिंग
│   ├── hook-activity-store.ts    # hook-activity.jsonl में गतिविधि सहेजें
│   └── llm-client.ts             # LLM API क्लाइंट (AI-संचालित पॉलिसीज़ के लिए)
├── app/                          # Next.js डैशबोर्ड (पृष्ठ + सर्वर क्रियाएं)
├── lib/                          # साझा उपयोगिताएं
│   ├── projects.ts               # फ़ाइलसिस्टम से Claude प्रोजेक्ट्स की गणना करें
│   ├── log-entries.ts            # Claude ट्रांसक्रिप्ट JSONL फॉर्मेट पार्स करें
│   ├── paths.ts                  # सिस्टम पाथ हल करें
│   └── ...
├── components/                   # साझा React UI घटक
├── contexts/                     # React संदर्भ प्रदाता (थीम, ऑटो-रिफ्रेश, टेलीमेट्री)
├── examples/                     # उदाहरण कस्टम हुक फ़ाइलें
└── __tests__/                    # इकाई और E2E परीक्षण