failproofai 0.0.5 → 0.0.6-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.failproofai/policies/review-policies.mjs +112 -0
- package/.next/standalone/.failproofai/policies/workflow-policies.mjs +2 -1
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g72weg._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__092s1ta._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09icjsf._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g.lg8b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h..k-e._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0okos0k._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0a~g15g._.js → [root-of-the-server]__0rh.18_._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w6l33k._.js +6 -6
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qn95h3._.js → [root-of-the-server]__0~kmh8w._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11pa2ra._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12t-wym._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/static/chunks/{0sme4lkv.tgn-.js → 01b~z8f1ws0rk.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0lgbwkfqmnsmc.js → 03rz6ykw-a2xi.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17manv47o-~wp.js → 08t08igdql9yt.js} +1 -1
- package/.next/standalone/.next/static/chunks/09_k80d~cq2wg.js +4 -0
- package/.next/standalone/.next/static/chunks/{0ksdlt_1hucdm.js → 0bvhsa6zva2o..js} +1 -1
- package/.next/standalone/.next/static/chunks/{09ikntpt2-o9b.js → 0gbf4cphy8ksq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0yumumfzx_f27.js → 0v.yd0kg_ld3r.js} +1 -1
- package/.next/standalone/.next/static/chunks/{13juklu.vksks.js → 0wlyoif4_kj_t.js} +1 -1
- package/.next/standalone/.next/static/chunks/{09e7drilkf1sn.js → 12simlrcfk3g2.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0em7tspi4kylh.js → 12~yi9oj8av8p.js} +2 -2
- package/.next/standalone/.next/static/chunks/{turbopack-0r26pc8h0y_-e.js → turbopack-0o7k.hakttp4k.js} +1 -1
- package/.next/standalone/CHANGELOG.md +13 -0
- package/.next/standalone/README.md +2 -2
- package/.next/standalone/bun.lock +43 -85
- package/.next/standalone/dist/cli.mjs +107 -3
- package/.next/standalone/docs/ar/architecture.mdx +65 -64
- package/.next/standalone/docs/ar/configuration.mdx +42 -42
- package/.next/standalone/docs/ar/custom-policies.mdx +62 -64
- package/.next/standalone/docs/built-in-policies.mdx +37 -0
- package/.next/standalone/docs/custom-policies.mdx +1 -1
- package/.next/standalone/docs/de/architecture.mdx +92 -92
- package/.next/standalone/docs/de/configuration.mdx +34 -34
- package/.next/standalone/docs/de/custom-policies.mdx +49 -50
- package/.next/standalone/docs/es/architecture.mdx +72 -72
- package/.next/standalone/docs/es/configuration.mdx +25 -25
- package/.next/standalone/docs/es/custom-policies.mdx +48 -49
- package/.next/standalone/docs/examples.mdx +54 -0
- package/.next/standalone/docs/fr/architecture.mdx +53 -53
- package/.next/standalone/docs/fr/configuration.mdx +25 -25
- package/.next/standalone/docs/fr/custom-policies.mdx +42 -43
- package/.next/standalone/docs/getting-started.mdx +52 -0
- package/.next/standalone/docs/he/architecture.mdx +66 -66
- package/.next/standalone/docs/he/configuration.mdx +53 -52
- package/.next/standalone/docs/he/custom-policies.mdx +72 -73
- package/.next/standalone/docs/hi/architecture.mdx +106 -106
- package/.next/standalone/docs/hi/configuration.mdx +39 -39
- package/.next/standalone/docs/hi/custom-policies.mdx +75 -76
- package/.next/standalone/docs/i18n/README.ar.md +66 -66
- package/.next/standalone/docs/i18n/README.de.md +38 -38
- package/.next/standalone/docs/i18n/README.es.md +38 -38
- package/.next/standalone/docs/i18n/README.fr.md +42 -42
- package/.next/standalone/docs/i18n/README.he.md +67 -67
- package/.next/standalone/docs/i18n/README.hi.md +70 -70
- package/.next/standalone/docs/i18n/README.it.md +62 -62
- package/.next/standalone/docs/i18n/README.ja.md +54 -54
- package/.next/standalone/docs/i18n/README.ko.md +58 -58
- package/.next/standalone/docs/i18n/README.pt-br.md +43 -43
- package/.next/standalone/docs/i18n/README.ru.md +69 -69
- package/.next/standalone/docs/i18n/README.tr.md +76 -76
- package/.next/standalone/docs/i18n/README.vi.md +70 -70
- package/.next/standalone/docs/i18n/README.zh.md +52 -52
- package/.next/standalone/docs/it/architecture.mdx +54 -53
- package/.next/standalone/docs/it/configuration.mdx +44 -45
- package/.next/standalone/docs/it/custom-policies.mdx +76 -78
- package/.next/standalone/docs/ja/architecture.mdx +93 -93
- package/.next/standalone/docs/ja/configuration.mdx +47 -47
- package/.next/standalone/docs/ja/custom-policies.mdx +62 -63
- package/.next/standalone/docs/ko/architecture.mdx +66 -66
- package/.next/standalone/docs/ko/configuration.mdx +35 -35
- package/.next/standalone/docs/ko/custom-policies.mdx +71 -72
- package/.next/standalone/docs/pt-br/architecture.mdx +55 -55
- package/.next/standalone/docs/pt-br/configuration.mdx +35 -35
- package/.next/standalone/docs/pt-br/custom-policies.mdx +60 -61
- package/.next/standalone/docs/ru/architecture.mdx +59 -60
- package/.next/standalone/docs/ru/configuration.mdx +52 -53
- package/.next/standalone/docs/ru/custom-policies.mdx +68 -69
- package/.next/standalone/docs/tr/architecture.mdx +124 -124
- package/.next/standalone/docs/tr/configuration.mdx +45 -46
- package/.next/standalone/docs/tr/custom-policies.mdx +75 -75
- package/.next/standalone/docs/vi/architecture.mdx +65 -64
- package/.next/standalone/docs/vi/configuration.mdx +41 -41
- package/.next/standalone/docs/vi/custom-policies.mdx +68 -69
- package/.next/standalone/docs/zh/architecture.mdx +67 -67
- package/.next/standalone/docs/zh/configuration.mdx +34 -34
- package/.next/standalone/docs/zh/custom-policies.mdx +53 -54
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +7 -7
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/config-schema.js +10 -2
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/render.js +27 -20
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +15 -15
- package/.next/standalone/package.json +2 -2
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/src/hooks/builtin-policies.ts +131 -0
- package/README.md +2 -2
- package/dist/cli.mjs +107 -3
- package/package.json +2 -2
- package/src/hooks/builtin-policies.ts +131 -0
- package/.next/standalone/.next/static/chunks/0_yayar~bpphd.js +0 -4
- /package/.next/standalone/.next/static/{hYQM6iCWnF1W5XDpsIRhV → CkmOT-ZvDN-sVULinGVKT}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{hYQM6iCWnF1W5XDpsIRhV → CkmOT-ZvDN-sVULinGVKT}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{hYQM6iCWnF1W5XDpsIRhV → CkmOT-ZvDN-sVULinGVKT}/_ssgManifest.js +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
2
|
---
|
|
4
3
|
title: Архитектура
|
|
5
|
-
description: "Как работают обработчик
|
|
4
|
+
description: "Как работают обработчик хуков, загрузка конфига и оценка политик"
|
|
6
5
|
icon: sitemap
|
|
7
6
|
---
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
Этот документ объясняет, как работает failproofai изнутри: как система хуков перехватывает вызовы инструментов агента, как загружается и объединяется конфигурация, как оцениваются политики и как панель мониторинга отслеживает активность агента.
|
|
10
9
|
|
|
11
10
|
---
|
|
12
11
|
|
|
@@ -14,18 +13,18 @@ icon: sitemap
|
|
|
14
13
|
|
|
15
14
|
failproofai состоит из двух независимых подсистем:
|
|
16
15
|
|
|
17
|
-
1.
|
|
18
|
-
2. **Agent Monitor (Dashboard)** — веб-приложение Next.js для мониторинга
|
|
16
|
+
1. **Hook handler** — быстрый CLI подпроцесс, который Claude Code вызывает при каждом вызове инструмента агента. Оценивает политики и возвращает решение.
|
|
17
|
+
2. **Agent Monitor (Dashboard)** — веб-приложение Next.js для мониторинга сессий агента и управления политиками.
|
|
19
18
|
|
|
20
|
-
Обе подсистемы совместно используют файлы конфигурации в `~/.failproofai/` и в директории `.failproofai
|
|
19
|
+
Обе подсистемы совместно используют файлы конфигурации в `~/.failproofai/` и в директории проекта `.failproofai/`, но работают как отдельные процессы и взаимодействуют только через файловую систему.
|
|
21
20
|
|
|
22
21
|
---
|
|
23
22
|
|
|
24
|
-
##
|
|
23
|
+
## Hook handler
|
|
25
24
|
|
|
26
25
|
### Интеграция с Claude Code
|
|
27
26
|
|
|
28
|
-
Когда вы запускаете `failproofai policies --install`, в `~/.claude/settings.json
|
|
27
|
+
Когда вы запускаете `failproofai policies --install`, он записывает записи подобно этой в `~/.claude/settings.json`:
|
|
29
28
|
|
|
30
29
|
```json
|
|
31
30
|
{
|
|
@@ -46,7 +45,7 @@ failproofai состоит из двух независимых подсисте
|
|
|
46
45
|
}
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
Claude Code затем вызывает `failproofai --hook PreToolUse` как подпроцесс перед каждым вызовом инструмента, передавая JSON-полезную нагрузку на stdin.
|
|
50
49
|
|
|
51
50
|
### Формат полезной нагрузки
|
|
52
51
|
|
|
@@ -62,13 +61,13 @@ failproofai состоит из двух независимых подсисте
|
|
|
62
61
|
}
|
|
63
62
|
```
|
|
64
63
|
|
|
65
|
-
Для событий `PostToolUse` полезная нагрузка также содержит `tool_result` с
|
|
64
|
+
Для событий `PostToolUse` полезная нагрузка также содержит `tool_result` с результатом работы инструмента.
|
|
66
65
|
|
|
67
|
-
Обработчик устанавливает
|
|
66
|
+
Обработчик устанавливает лимит stdin в 1 МБ. Полезные нагрузки, превышающие этот лимит, отбрасываются и все политики неявно разрешают операцию.
|
|
68
67
|
|
|
69
68
|
### Формат ответа
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
**Deny (PreToolUse):**
|
|
72
71
|
```json
|
|
73
72
|
{
|
|
74
73
|
"hookSpecificOutput": {
|
|
@@ -78,7 +77,7 @@ failproofai состоит из двух независимых подсисте
|
|
|
78
77
|
}
|
|
79
78
|
```
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
**Deny (PostToolUse):**
|
|
82
81
|
```json
|
|
83
82
|
{
|
|
84
83
|
"hookSpecificOutput": {
|
|
@@ -87,7 +86,7 @@ failproofai состоит из двух независимых подсисте
|
|
|
87
86
|
}
|
|
88
87
|
```
|
|
89
88
|
|
|
90
|
-
|
|
89
|
+
**Instruct (любое событие, кроме Stop):**
|
|
91
90
|
```json
|
|
92
91
|
{
|
|
93
92
|
"hookSpecificOutput": {
|
|
@@ -96,20 +95,20 @@ failproofai состоит из двух независимых подсисте
|
|
|
96
95
|
}
|
|
97
96
|
```
|
|
98
97
|
|
|
99
|
-
|
|
98
|
+
**Instruct для события Stop:**
|
|
100
99
|
- Код выхода: `2`
|
|
101
|
-
- Причина
|
|
100
|
+
- Причина выводится в stderr (не в stdout)
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
**Allow:**
|
|
104
103
|
- Код выхода: `0`
|
|
105
104
|
- Пустой stdout
|
|
106
105
|
|
|
107
|
-
|
|
106
|
+
**Allow с сообщением:**
|
|
108
107
|
|
|
109
|
-
`allow(message)` позволяет политике
|
|
108
|
+
`allow(message)` позволяет политике отправлять информационный контекст обратно в Claude даже когда операция разрешена. Обработчик хуков записывает следующий JSON в **stdout** (не в файл конфига — это ответ обработчика для Claude Code, как и ответы deny и instruct выше):
|
|
110
109
|
|
|
111
110
|
```json
|
|
112
|
-
//
|
|
111
|
+
// Написано в stdout процессом обработчика хуков
|
|
113
112
|
{
|
|
114
113
|
"hookSpecificOutput": {
|
|
115
114
|
"additionalContext": "All CI checks passed on branch 'feat/my-feature'."
|
|
@@ -117,8 +116,8 @@ failproofai состоит из двух независимых подсисте
|
|
|
117
116
|
}
|
|
118
117
|
```
|
|
119
118
|
- Код выхода: `0` (операция разрешена)
|
|
120
|
-
- Когда несколько политик возвращают `allow` с сообщением, их сообщения объединяются с
|
|
121
|
-
- Если ни одна политика не предоставляет сообщение, stdout
|
|
119
|
+
- Когда несколько политик возвращают `allow` с сообщением, их сообщения объединяются с переводами строк в один string `additionalContext`
|
|
120
|
+
- Если ни одна политика не предоставляет сообщение, stdout пуст (как и раньше)
|
|
122
121
|
|
|
123
122
|
### Конвейер обработки
|
|
124
123
|
|
|
@@ -147,7 +146,7 @@ stdin JSON
|
|
|
147
146
|
|
|
148
147
|
## Загрузка конфигурации
|
|
149
148
|
|
|
150
|
-
`src/hooks/hooks-config.ts` реализует загрузку конфигурации
|
|
149
|
+
`src/hooks/hooks-config.ts` реализует загрузку конфигурации в трёх областях.
|
|
151
150
|
|
|
152
151
|
```text
|
|
153
152
|
[1] {cwd}/.failproofai/policies-config.json ← project (highest priority)
|
|
@@ -156,12 +155,12 @@ stdin JSON
|
|
|
156
155
|
```
|
|
157
156
|
|
|
158
157
|
Логика объединения:
|
|
159
|
-
- `enabledPolicies` — объединение всех
|
|
160
|
-
- `policyParams` —
|
|
161
|
-
- `customPoliciesPath` — первый файл, который его определяет,
|
|
162
|
-
- `llm` — первый файл, который его определяет,
|
|
158
|
+
- `enabledPolicies` — дедублицированное объединение всех трёх файлов
|
|
159
|
+
- `policyParams` — по ключу политики, первый файл, который его определяет, получает полный приоритет
|
|
160
|
+
- `customPoliciesPath` — первый файл, который его определяет, получает приоритет
|
|
161
|
+
- `llm` — первый файл, который его определяет, получает приоритет
|
|
163
162
|
|
|
164
|
-
Веб-панель
|
|
163
|
+
Веб-панель использует `readHooksConfig()` (только глобальный) для чтения и записи, поскольку она вызывается без cwd проекта.
|
|
165
164
|
|
|
166
165
|
---
|
|
167
166
|
|
|
@@ -171,18 +170,18 @@ stdin JSON
|
|
|
171
170
|
|
|
172
171
|
Для каждой политики:
|
|
173
172
|
|
|
174
|
-
1.
|
|
175
|
-
2.
|
|
176
|
-
3.
|
|
177
|
-
4.
|
|
178
|
-
5. Если результат
|
|
179
|
-
6. Если результат
|
|
180
|
-
7. Если результат
|
|
173
|
+
1. Поиск схемы `params` политики (если она есть).
|
|
174
|
+
2. Чтение `policyParams[policy.name]` из объединённой конфигурации.
|
|
175
|
+
3. Объединение предоставленных пользователем значений со значениями по умолчанию из схемы для создания `ctx.params`.
|
|
176
|
+
4. Вызов `policy.fn(ctx)` с разрешённым контекстом.
|
|
177
|
+
5. Если результат `deny`, остановиться немедленно и вернуть это решение.
|
|
178
|
+
6. Если результат `instruct`, накопить сообщение и продолжить.
|
|
179
|
+
7. Если результат `allow`, перейти к следующей политике.
|
|
181
180
|
|
|
182
|
-
После
|
|
183
|
-
- Если
|
|
184
|
-
- Если были собраны
|
|
185
|
-
- В противном случае
|
|
181
|
+
После выполнения всех политик:
|
|
182
|
+
- Если была возвращена какая-либо `deny`, вывести ответ deny.
|
|
183
|
+
- Если были собраны какие-либо `instruct`, вывести один ответ instruct со всеми объединёнными сообщениями.
|
|
184
|
+
- В противном случае вывести ответ allow (пустой stdout, выход 0).
|
|
186
185
|
|
|
187
186
|
---
|
|
188
187
|
|
|
@@ -206,15 +205,15 @@ interface BuiltinPolicyDefinition {
|
|
|
206
205
|
}
|
|
207
206
|
```
|
|
208
207
|
|
|
209
|
-
Политики, которые принимают `params`, объявляют `PolicyParamsSchema` с типами и значениями по умолчанию для каждого параметра. Оценщик политик
|
|
208
|
+
Политики, которые принимают `params`, объявляют `PolicyParamsSchema` с типами и значениями по умолчанию для каждого параметра. Оценщик политик внедряет разрешённые значения в `ctx.params` перед вызовом `fn`. Функции политик читают `ctx.params` без проверки на null, поскольку значения по умолчанию всегда применяются в первую очередь.
|
|
210
209
|
|
|
211
|
-
Сопоставление шаблонов внутри политик использует разобранные токены
|
|
210
|
+
Сопоставление шаблонов внутри политик использует разобранные токены команды (argv), а не простое совпадение строк. Это предотвращает обход с помощью инъекции оператора оболочки (например, шаблон для `sudo systemctl status *` не может быть обойден путём добавления `; rm -rf /` к команде).
|
|
212
211
|
|
|
213
212
|
---
|
|
214
213
|
|
|
215
214
|
## Пользовательские политики
|
|
216
215
|
|
|
217
|
-
`src/hooks/custom-hooks-registry.ts` реализует
|
|
216
|
+
`src/hooks/custom-hooks-registry.ts` реализует реестр, поддерживаемый `globalThis`:
|
|
218
217
|
|
|
219
218
|
```typescript
|
|
220
219
|
const REGISTRY_KEY = "__failproofai_custom_hooks__";
|
|
@@ -229,17 +228,17 @@ export function clearCustomHooks(): void { ... } // used in tests
|
|
|
229
228
|
|
|
230
229
|
`src/hooks/custom-hooks-loader.ts` загружает файл политики пользователя:
|
|
231
230
|
|
|
232
|
-
1.
|
|
233
|
-
2.
|
|
234
|
-
3.
|
|
235
|
-
4.
|
|
236
|
-
5.
|
|
237
|
-
6.
|
|
238
|
-
7.
|
|
231
|
+
1. Чтение `customPoliciesPath` из конфигурации; пропуск, если отсутствует.
|
|
232
|
+
2. Разрешение в абсолютный путь; проверка существования файла.
|
|
233
|
+
3. Переписывание всех импортов `from "failproofai"` на фактический путь dist, чтобы `customPolicies` разрешался в одинаковый реестр `globalThis`.
|
|
234
|
+
4. Рекурсивное переписывание переходных локальных импортов для обеспечения совместимости ESM.
|
|
235
|
+
5. Запись временных файлов `.mjs` и `import()` файла входа.
|
|
236
|
+
6. Вызов `getCustomHooks()` для получения зарегистрированных хуков.
|
|
237
|
+
7. Очистка всех временных файлов в блоке `finally`.
|
|
239
238
|
|
|
240
239
|
При любой ошибке (файл не найден, синтаксическая ошибка, ошибка импорта) ошибка регистрируется в `~/.failproofai/hook.log` и загрузчик возвращает пустой массив. Встроенные политики не затрагиваются.
|
|
241
240
|
|
|
242
|
-
Пользовательские политики оцениваются после всех встроенных политик. `deny`
|
|
241
|
+
Пользовательские политики оцениваются после всех встроенных политик. Пользовательская политика `deny` по-прежнему прерывает дальнейшие пользовательские политики (но к тому моменту все встроенные уже выполнены).
|
|
243
242
|
|
|
244
243
|
---
|
|
245
244
|
|
|
@@ -260,13 +259,13 @@ export function clearCustomHooks(): void { ... } // used in tests
|
|
|
260
259
|
}
|
|
261
260
|
```
|
|
262
261
|
|
|
263
|
-
|
|
262
|
+
По одной строке на каждую политику, которая приняла решение, отличное от allow. Решения allow не регистрируются (чтобы держать файл в разумном размере).
|
|
264
263
|
|
|
265
264
|
---
|
|
266
265
|
|
|
267
|
-
## Архитектура панели
|
|
266
|
+
## Архитектура панели
|
|
268
267
|
|
|
269
|
-
Панель
|
|
268
|
+
Панель — это приложение **Next.js 16** с использованием App Router, React Server Components и Server Actions.
|
|
270
269
|
|
|
271
270
|
```text
|
|
272
271
|
app/
|
|
@@ -288,16 +287,16 @@ app/
|
|
|
288
287
|
|
|
289
288
|
**Поток данных:**
|
|
290
289
|
|
|
291
|
-
- Компоненты страниц вызывают `lib/projects.ts` и `lib/log-entries.ts` для чтения данных
|
|
292
|
-
- Страница Policies использует Server Actions для всех
|
|
293
|
-
- Просмотрщик
|
|
290
|
+
- Компоненты страниц вызывают `lib/projects.ts` и `lib/log-entries.ts` для чтения данных проекта/сессии непосредственно из файловой системы (без слоя API для чтения).
|
|
291
|
+
- Страница Policies использует Server Actions для всех изменений (переключение, обновление параметров, установка/удаление).
|
|
292
|
+
- Просмотрщик сессии анализирует формат JSONL транскрипта Claude и отображает временную шкалу сообщений и вызовов инструментов.
|
|
294
293
|
|
|
295
294
|
**Ключевые решения проектирования:**
|
|
296
295
|
|
|
297
|
-
- Нет базы данных —
|
|
298
|
-
- Server Actions для
|
|
299
|
-
- React Server Components для страниц чтения — более быстрая начальная загрузка,
|
|
300
|
-
- Клиентские компоненты только
|
|
296
|
+
- Нет базы данных — всё постоянное состояние хранится в простых файлах (`~/.failproofai/`, `~/.claude/projects/`).
|
|
297
|
+
- Server Actions для изменений — REST API не требуется для CRUD операций.
|
|
298
|
+
- React Server Components для страниц чтения — более быстрая начальная загрузка, без клиентского пакета для получения данных.
|
|
299
|
+
- Клиентские компоненты только где требуется интерактивность (переключение политик, поиск по активности, просмотр логов).
|
|
301
300
|
|
|
302
301
|
---
|
|
303
302
|
|
|
@@ -1,58 +1,57 @@
|
|
|
1
1
|
---
|
|
2
|
-
---
|
|
3
2
|
title: Конфигурация
|
|
4
|
-
description: "Формат файла конфигурации,
|
|
3
|
+
description: "Формат файла конфигурации, система трёх областей и правила слияния"
|
|
5
4
|
icon: gear
|
|
6
5
|
---
|
|
7
6
|
|
|
8
|
-
failproofai использует JSON
|
|
7
|
+
failproofai использует JSON-файлы конфигурации для управления активными политиками, их поведением и местом загрузки пользовательских политик. Конфигурация разработана так, чтобы её было легко делиться с командой — достаточно добавить её в репозиторий, и каждый разработчик получит одинаковую защиту агента.
|
|
9
8
|
|
|
10
9
|
---
|
|
11
10
|
|
|
12
|
-
##
|
|
11
|
+
## Области конфигурации
|
|
13
12
|
|
|
14
|
-
Существует три
|
|
13
|
+
Существует три области конфигурации, оцениваемые в порядке приоритета:
|
|
15
14
|
|
|
16
|
-
|
|
|
17
|
-
|
|
18
|
-
| **project** | `.failproofai/policies-config.json` |
|
|
19
|
-
| **local** | `.failproofai/policies-config.local.json` | Личные переопределения
|
|
20
|
-
| **global** | `~/.failproofai/policies-config.json` |
|
|
15
|
+
| Область | Путь к файлу | Назначение |
|
|
16
|
+
|---------|--------------|-----------|
|
|
17
|
+
| **project** | `.failproofai/policies-config.json` | Параметры репозитория, коммитятся в контроль версий |
|
|
18
|
+
| **local** | `.failproofai/policies-config.local.json` | Личные переопределения для конкретного репозитория, в .gitignore |
|
|
19
|
+
| **global** | `~/.failproofai/policies-config.json` | Параметры уровня пользователя для всех проектов |
|
|
21
20
|
|
|
22
|
-
Когда failproofai получает событие
|
|
21
|
+
Когда failproofai получает событие хука, он загружает и объединяет все три файла, которые существуют для текущей рабочей директории.
|
|
23
22
|
|
|
24
23
|
### Правила слияния
|
|
25
24
|
|
|
26
|
-
**`enabledPolicies`** — объединение всех трёх
|
|
25
|
+
**`enabledPolicies`** — объединение всех трёх областей. Политика, активированная на любом уровне, становится активной.
|
|
27
26
|
|
|
28
27
|
```text
|
|
29
28
|
project: ["block-sudo"]
|
|
30
29
|
local: ["block-rm-rf"]
|
|
31
30
|
global: ["block-sudo", "sanitize-api-keys"]
|
|
32
31
|
|
|
33
|
-
resolved: ["block-sudo", "block-rm-rf", "sanitize-api-keys"] ← объединение
|
|
32
|
+
resolved: ["block-sudo", "block-rm-rf", "sanitize-api-keys"] ← дедублицированное объединение
|
|
34
33
|
```
|
|
35
34
|
|
|
36
|
-
**`policyParams`** —
|
|
35
|
+
**`policyParams`** — первая область, которая определяет параметры для данной политики, побеждает полностью. Глубокого слияния значений внутри параметров политики не происходит.
|
|
37
36
|
|
|
38
37
|
```text
|
|
39
38
|
project: block-sudo → { allowPatterns: ["sudo apt-get update"] }
|
|
40
39
|
global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
|
|
41
40
|
|
|
42
|
-
resolved: { allowPatterns: ["sudo apt-get update"] } ←
|
|
41
|
+
resolved: { allowPatterns: ["sudo apt-get update"] } ← project побеждает, global игнорируется
|
|
43
42
|
```
|
|
44
43
|
|
|
45
44
|
```text
|
|
46
|
-
project: (нет
|
|
47
|
-
local: (нет
|
|
45
|
+
project: (нет входа block-sudo)
|
|
46
|
+
local: (нет входа block-sudo)
|
|
48
47
|
global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
|
|
49
48
|
|
|
50
49
|
resolved: { allowPatterns: ["sudo systemctl status"] } ← переходит на global
|
|
51
50
|
```
|
|
52
51
|
|
|
53
|
-
**`customPoliciesPath`** —
|
|
52
|
+
**`customPoliciesPath`** — первая область, которая определяет его, побеждает.
|
|
54
53
|
|
|
55
|
-
**`llm`** —
|
|
54
|
+
**`llm`** — первая область, которая определяет его, побеждает.
|
|
56
55
|
|
|
57
56
|
---
|
|
58
57
|
|
|
@@ -97,85 +96,85 @@ resolved: { allowPatterns: ["sudo systemctl status"] } ← переходит
|
|
|
97
96
|
|
|
98
97
|
---
|
|
99
98
|
|
|
100
|
-
##
|
|
99
|
+
## Справочник полей
|
|
101
100
|
|
|
102
101
|
### `enabledPolicies`
|
|
103
102
|
|
|
104
103
|
Тип: `string[]`
|
|
105
104
|
|
|
106
|
-
Список имён политик для активации. Имена должны точно совпадать с идентификаторами политик, показываемыми
|
|
105
|
+
Список имён политик для активации. Имена должны точно совпадать с идентификаторами политик, показываемыми `failproofai policies`. Полный список смотрите в разделе [Встроенные политики](/ru/built-in-policies).
|
|
107
106
|
|
|
108
|
-
Политики, отсутствующие в `enabledPolicies`, неактивны, даже если
|
|
107
|
+
Политики, отсутствующие в `enabledPolicies`, неактивны, даже если они имеют записи в `policyParams`.
|
|
109
108
|
|
|
110
109
|
### `policyParams`
|
|
111
110
|
|
|
112
111
|
Тип: `Record<string, Record<string, unknown>>`
|
|
113
112
|
|
|
114
|
-
Переопределения параметров для
|
|
113
|
+
Переопределения параметров для отдельных политик. Внешний ключ — это имя политики; внутренние ключи специфичны для политики. Каждая политика описывает свои доступные параметры в разделе [Встроенные политики](/ru/built-in-policies).
|
|
115
114
|
|
|
116
|
-
Если политика имеет параметры, но вы их не указали, используются встроенные значения по
|
|
115
|
+
Если политика имеет параметры, но вы их не указали, используются встроенные значения по умолчанию. Пользователи, которые вообще не настраивают `policyParams`, получат идентичное поведение предыдущим версиям.
|
|
117
116
|
|
|
118
|
-
Неизвестные ключи
|
|
117
|
+
Неизвестные ключи внутри блока параметров политики молча игнорируются при срабатывании хука, но флагируются как предупреждения при запуске `failproofai policies`.
|
|
119
118
|
|
|
120
|
-
#### `hint` (
|
|
119
|
+
#### `hint` (сквозной)
|
|
121
120
|
|
|
122
121
|
Тип: `string` (опционально)
|
|
123
122
|
|
|
124
|
-
Сообщение, добавляемое к причине, когда политика возвращает `deny` или `instruct`. Используйте его, чтобы дать Claude
|
|
123
|
+
Сообщение, добавляемое к причине, когда политика возвращает `deny` или `instruct`. Используйте его, чтобы дать Claude действенное руководство без изменения самой политики.
|
|
125
124
|
|
|
126
|
-
Работает с любым типом
|
|
125
|
+
Работает с любым типом политик — встроенными, пользовательскими (`custom/`), соглашениями проекта (`.failproofai-project/`) или соглашениями пользователя (`.failproofai-user/`).
|
|
127
126
|
|
|
128
127
|
```json
|
|
129
128
|
{
|
|
130
129
|
"policyParams": {
|
|
131
130
|
"block-force-push": {
|
|
132
|
-
"hint": "Попробуйте создать
|
|
131
|
+
"hint": "Попробуйте создать новую ветку вместо этого."
|
|
133
132
|
},
|
|
134
133
|
"block-sudo": {
|
|
135
134
|
"allowPatterns": ["sudo apt-get"],
|
|
136
135
|
"hint": "Используйте apt-get напрямую без sudo."
|
|
137
136
|
},
|
|
138
137
|
"custom/my-policy": {
|
|
139
|
-
"hint": "Сначала
|
|
138
|
+
"hint": "Сначала получите одобрение у пользователя."
|
|
140
139
|
}
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
```
|
|
144
143
|
|
|
145
|
-
Когда `block-force-push`
|
|
144
|
+
Когда `block-force-push` отклоняет, Claude видит: *"Force-pushing заблокирован. Попробуйте создать новую ветку вместо этого."*
|
|
146
145
|
|
|
147
|
-
Значения, не являющиеся строками, и пустые строки молча игнорируются. Если `hint` не
|
|
146
|
+
Значения, не являющиеся строками, и пустые строки молча игнорируются. Если `hint` не задан, поведение не меняется (обратная совместимость).
|
|
148
147
|
|
|
149
148
|
### `customPoliciesPath`
|
|
150
149
|
|
|
151
150
|
Тип: `string` (абсолютный путь)
|
|
152
151
|
|
|
153
|
-
Путь к JavaScript
|
|
152
|
+
Путь к JavaScript-файлу, содержащему пользовательские политики хука. Этот параметр устанавливается автоматически командой `failproofai policies --install --custom <path>` (путь разрешается к абсолютному перед сохранением).
|
|
154
153
|
|
|
155
|
-
Файл загружается заново при каждом
|
|
154
|
+
Файл загружается заново при каждом срабатывании хука — кэширования нет. Подробности разработки смотрите в разделе [Пользовательские политики](/ru/custom-policies).
|
|
156
155
|
|
|
157
|
-
### Политики на основе
|
|
156
|
+
### Политики на основе соглашений
|
|
158
157
|
|
|
159
|
-
В дополнение к явному `customPoliciesPath
|
|
158
|
+
В дополнение к явному `customPoliciesPath` failproofai автоматически обнаруживает и загружает файлы политик из директорий `.failproofai/policies/`:
|
|
160
159
|
|
|
161
|
-
| Уровень | Директория |
|
|
162
|
-
|
|
163
|
-
|
|
|
164
|
-
|
|
|
160
|
+
| Уровень | Директория | Область |
|
|
161
|
+
|---------|-----------|---------|
|
|
162
|
+
| Проект | `.failproofai/policies/` | Совместное использование с командой через контроль версий |
|
|
163
|
+
| Пользователь | `~/.failproofai/policies/` | Личные, применяются ко всем проектам |
|
|
165
164
|
|
|
166
|
-
**Соответствие файлов:** Загружаются только файлы, соответствующие
|
|
165
|
+
**Соответствие файлов:** Загружаются только файлы, соответствующие шаблону `*policies.{js,mjs,ts}` (например `security-policies.mjs`, `workflow-policies.js`). Другие файлы в директории игнорируются.
|
|
167
166
|
|
|
168
|
-
**Конфигурация не требуется:** Политики на основе
|
|
167
|
+
**Конфигурация не требуется:** Политики на основе соглашений не требуют записей в `policies-config.json`. Просто поместите файлы в директорию, и они будут загружены при следующем срабатывании хука.
|
|
169
168
|
|
|
170
|
-
|
|
169
|
+
**Объединённая загрузка:** Сканируются обе директории соглашений — проекта и пользователя. Все подходящие файлы с обоих уровней загружаются (в отличие от `customPoliciesPath`, который использует первый-побеждает).
|
|
171
170
|
|
|
172
|
-
|
|
171
|
+
Подробности и примеры смотрите в разделе [Пользовательские политики](/ru/custom-policies).
|
|
173
172
|
|
|
174
173
|
### `llm`
|
|
175
174
|
|
|
176
175
|
Тип: `object` (опционально)
|
|
177
176
|
|
|
178
|
-
Конфигурация LLM
|
|
177
|
+
Конфигурация LLM-клиента для политик, которые выполняют вызовы AI. Не требуется для большинства конфигураций.
|
|
179
178
|
|
|
180
179
|
```json
|
|
181
180
|
{
|
|
@@ -188,20 +187,20 @@ resolved: { allowPatterns: ["sudo systemctl status"] } ← переходит
|
|
|
188
187
|
|
|
189
188
|
---
|
|
190
189
|
|
|
191
|
-
## Управление конфигурацией
|
|
190
|
+
## Управление конфигурацией из CLI
|
|
192
191
|
|
|
193
|
-
Команды `policies --install` и `policies --uninstall` записывают в `settings.json` Claude Code (точки входа
|
|
192
|
+
Команды `policies --install` и `policies --uninstall` записывают в `settings.json` Claude Code (точки входа хука), а `policies-config.json` — это файл, которым вы управляете напрямую. Это два разных файла:
|
|
194
193
|
|
|
195
|
-
- **`settings.json`** —
|
|
196
|
-
- **`policies-config.json`** —
|
|
194
|
+
- **`settings.json`** — говорит Claude Code вызывать `failproofai --hook <event>` при каждом использовании инструмента
|
|
195
|
+
- **`policies-config.json`** — говорит failproofai, какие политики оценивать и с какими параметрами
|
|
197
196
|
|
|
198
|
-
Вы можете редактировать `policies-config.json` напрямую в
|
|
197
|
+
Вы можете редактировать `policies-config.json` напрямую в любой момент; изменения вступают в силу сразу же при следующем срабатывании хука без необходимости перезагрузки.
|
|
199
198
|
|
|
200
199
|
---
|
|
201
200
|
|
|
202
|
-
## Пример: конфигурация
|
|
201
|
+
## Пример: конфигурация уровня проекта с командными параметрами по умолчанию
|
|
203
202
|
|
|
204
|
-
|
|
203
|
+
Добавьте `.failproofai/policies-config.json` в свой репозиторий:
|
|
205
204
|
|
|
206
205
|
```json
|
|
207
206
|
{
|
|
@@ -220,4 +219,4 @@ resolved: { allowPatterns: ["sudo systemctl status"] } ← переходит
|
|
|
220
219
|
}
|
|
221
220
|
```
|
|
222
221
|
|
|
223
|
-
|
|
222
|
+
Затем каждый разработчик может создать `.failproofai/policies-config.local.json` (в .gitignore) для личных переопределений без влияния на коллег.
|