@bookedsolid/rea 0.1.0
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/LICENSE +21 -0
- package/README.md +339 -0
- package/SECURITY.md +104 -0
- package/THREAT_MODEL.md +245 -0
- package/agents/accessibility-engineer.md +101 -0
- package/agents/backend-engineer.md +126 -0
- package/agents/code-reviewer.md +144 -0
- package/agents/codex-adversarial.md +107 -0
- package/agents/frontend-specialist.md +84 -0
- package/agents/qa-engineer.md +138 -0
- package/agents/rea-orchestrator.md +101 -0
- package/agents/security-engineer.md +108 -0
- package/agents/technical-writer.md +140 -0
- package/agents/typescript-specialist.md +111 -0
- package/commands/codex-review.md +104 -0
- package/commands/freeze.md +81 -0
- package/commands/halt-check.md +120 -0
- package/commands/rea.md +52 -0
- package/commands/review.md +79 -0
- package/dist/cli/check.d.ts +1 -0
- package/dist/cli/check.js +66 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.js +93 -0
- package/dist/cli/freeze.d.ts +8 -0
- package/dist/cli/freeze.js +61 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +65 -0
- package/dist/cli/init.d.ts +6 -0
- package/dist/cli/init.js +237 -0
- package/dist/cli/serve.d.ts +1 -0
- package/dist/cli/serve.js +19 -0
- package/dist/cli/utils.d.ts +23 -0
- package/dist/cli/utils.js +51 -0
- package/dist/config/tier-map.d.ts +11 -0
- package/dist/config/tier-map.js +108 -0
- package/dist/config/types.d.ts +24 -0
- package/dist/config/types.js +1 -0
- package/dist/gateway/circuit-breaker.d.ts +43 -0
- package/dist/gateway/circuit-breaker.js +86 -0
- package/dist/gateway/middleware/audit-types.d.ts +16 -0
- package/dist/gateway/middleware/audit-types.js +1 -0
- package/dist/gateway/middleware/audit.d.ts +12 -0
- package/dist/gateway/middleware/audit.js +98 -0
- package/dist/gateway/middleware/blocked-paths.d.ts +12 -0
- package/dist/gateway/middleware/blocked-paths.js +117 -0
- package/dist/gateway/middleware/chain.d.ts +28 -0
- package/dist/gateway/middleware/chain.js +40 -0
- package/dist/gateway/middleware/circuit-breaker.d.ts +11 -0
- package/dist/gateway/middleware/circuit-breaker.js +43 -0
- package/dist/gateway/middleware/injection.d.ts +22 -0
- package/dist/gateway/middleware/injection.js +128 -0
- package/dist/gateway/middleware/kill-switch.d.ts +10 -0
- package/dist/gateway/middleware/kill-switch.js +58 -0
- package/dist/gateway/middleware/policy.d.ts +12 -0
- package/dist/gateway/middleware/policy.js +70 -0
- package/dist/gateway/middleware/rate-limit.d.ts +12 -0
- package/dist/gateway/middleware/rate-limit.js +31 -0
- package/dist/gateway/middleware/redact.d.ts +16 -0
- package/dist/gateway/middleware/redact.js +128 -0
- package/dist/gateway/middleware/result-size-cap.d.ts +13 -0
- package/dist/gateway/middleware/result-size-cap.js +48 -0
- package/dist/gateway/middleware/session.d.ts +10 -0
- package/dist/gateway/middleware/session.js +18 -0
- package/dist/gateway/middleware/tier.d.ts +6 -0
- package/dist/gateway/middleware/tier.js +10 -0
- package/dist/gateway/rate-limiter.d.ts +36 -0
- package/dist/gateway/rate-limiter.js +75 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/policy/loader.d.ts +80 -0
- package/dist/policy/loader.js +146 -0
- package/dist/policy/types.d.ts +34 -0
- package/dist/policy/types.js +19 -0
- package/hooks/_lib/common.sh +105 -0
- package/hooks/_lib/halt-check.sh +39 -0
- package/hooks/_lib/policy-read.sh +79 -0
- package/hooks/architecture-review-gate.sh +84 -0
- package/hooks/attribution-advisory.sh +126 -0
- package/hooks/blocked-paths-enforcer.sh +176 -0
- package/hooks/changeset-security-gate.sh +143 -0
- package/hooks/commit-review-gate.sh +166 -0
- package/hooks/dangerous-bash-interceptor.sh +362 -0
- package/hooks/dependency-audit-gate.sh +118 -0
- package/hooks/env-file-protection.sh +110 -0
- package/hooks/pr-issue-link-gate.sh +65 -0
- package/hooks/push-review-gate.sh +120 -0
- package/hooks/secret-scanner.sh +229 -0
- package/hooks/security-disclosure-gate.sh +146 -0
- package/hooks/settings-protection.sh +147 -0
- package/package.json +93 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Booked Solid Technology (Clarity House LLC)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# REA
|
|
2
|
+
|
|
3
|
+
**Agentic governance layer for Claude Code — policy enforcement, hook-based safety gates, audit logging, and Codex-integrated adversarial review.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@bookedsolid/rea)
|
|
6
|
+
[](https://github.com/bookedsolidtech/rea/actions)
|
|
7
|
+
[](https://docs.npmjs.com/generating-provenance-statements)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
[](https://developercertificate.org/)
|
|
10
|
+
[](https://nodejs.org/)
|
|
11
|
+
|
|
12
|
+
> Status: 0.0.x, pre-release. Badges are placeholders until the first publish.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx @bookedsolid/rea init
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The `init` command is an interactive wizard. It detects your project, writes
|
|
23
|
+
`.rea/policy.yaml`, copies hooks and slash commands into `.claude/`, wires
|
|
24
|
+
`.mcp.json` to run `rea serve` as a governance gateway, installs a
|
|
25
|
+
`.husky/commit-msg` hook, and appends a managed fragment to `CLAUDE.md`.
|
|
26
|
+
|
|
27
|
+
Node 22+ and pnpm 9+ required.
|
|
28
|
+
|
|
29
|
+
## What REA is
|
|
30
|
+
|
|
31
|
+
REA is a governance layer for Claude Code. It is a single npm package that
|
|
32
|
+
ships four things:
|
|
33
|
+
|
|
34
|
+
1. A **hook layer** — 11 shell scripts wired into Claude Code's `PreToolUse`
|
|
35
|
+
and `PostToolUse` events. Hooks enforce secret scanning, dangerous-command
|
|
36
|
+
interception, blocked-path protection, settings protection, attribution
|
|
37
|
+
rejection, and commit/push review gates.
|
|
38
|
+
2. A **gateway layer** — an MCP server (`rea serve`) that proxies downstream
|
|
39
|
+
MCP servers through a middleware chain. Every tool call — native or
|
|
40
|
+
proxied — is classified, policy-checked, redacted, audited, and
|
|
41
|
+
size-capped before it executes.
|
|
42
|
+
3. A **policy runtime** — `.rea/policy.yaml` with strict zod-validated
|
|
43
|
+
schema. Defines autonomy level, a hard ceiling (`max_autonomy_level`),
|
|
44
|
+
blocked paths, attribution rules, context protection, and optional
|
|
45
|
+
Discord notification webhook.
|
|
46
|
+
4. A **kill switch** — `.rea/HALT` is a single file. If it exists, every
|
|
47
|
+
tool call is denied at the middleware and hook layers. Use
|
|
48
|
+
`rea freeze --reason "..."` to create it and `rea unfreeze --reason "..."`
|
|
49
|
+
to remove it.
|
|
50
|
+
|
|
51
|
+
REA is one tool that does one thing: gate and audit agentic tool calls
|
|
52
|
+
against operator-defined policy. That is the whole product.
|
|
53
|
+
|
|
54
|
+
## What REA is NOT
|
|
55
|
+
|
|
56
|
+
These are non-goals. PRs adding any of these will be closed with a pointer
|
|
57
|
+
to build a separate package that composes with REA.
|
|
58
|
+
|
|
59
|
+
- **Not a project manager.** No task CRUD, no GitHub issue sync, no board
|
|
60
|
+
scaffolding. No `task_create`, `task_update`, `repo_scaffold`.
|
|
61
|
+
- **Not an Obsidian integration.** No vault journaling, no note creation,
|
|
62
|
+
no precompact summaries, no pre/post-compact Obsidian hooks.
|
|
63
|
+
- **Not an account manager.** No `rea account add/list/env/rotate/remove`.
|
|
64
|
+
No Keychain, no OAuth, no multi-tenant token vault. Env vars only.
|
|
65
|
+
- **Not a Discord bot.** No Discord MCP tools. A Discord webhook URL in
|
|
66
|
+
`policy.yaml` is the maximum surface area — one outbound POST, opt-in.
|
|
67
|
+
- **Not a daemon supervisor.** `rea serve` is started by Claude Code via
|
|
68
|
+
`.mcp.json`. Claude Code owns the lifecycle. There is no `rea start`,
|
|
69
|
+
no `rea stop`, no pid file, no systemd unit.
|
|
70
|
+
- **Not a hosted service.** There is no REA Cloud, no SaaS tier, no
|
|
71
|
+
multi-token workstreams, no workload isolation platform.
|
|
72
|
+
- **Not a 70-agent roster.** 10 curated agents ship in the package. Four
|
|
73
|
+
profiles layer additional specialists on top. No kitchen sink.
|
|
74
|
+
|
|
75
|
+
The non-goals are the product. Every "but what if we just added X" belongs
|
|
76
|
+
in a separate package.
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
### 1. Write a policy
|
|
81
|
+
|
|
82
|
+
`.rea/policy.yaml`:
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
version: "1"
|
|
86
|
+
profile: "bst-internal"
|
|
87
|
+
autonomy_level: L1
|
|
88
|
+
max_autonomy_level: L2
|
|
89
|
+
promotion_requires_human_approval: true
|
|
90
|
+
blocked_paths:
|
|
91
|
+
- ".env"
|
|
92
|
+
- ".env.*"
|
|
93
|
+
- "secrets/**"
|
|
94
|
+
block_ai_attribution: true
|
|
95
|
+
context_protection:
|
|
96
|
+
delegate_to_subagent:
|
|
97
|
+
- "pnpm run preflight"
|
|
98
|
+
- "pnpm run test"
|
|
99
|
+
- "pnpm run build"
|
|
100
|
+
max_bash_output_lines: 100
|
|
101
|
+
notification_channel: "" # optional Discord webhook
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`autonomy_level` can be raised up to `max_autonomy_level` and no further.
|
|
105
|
+
The loader rejects the file at parse time if `autonomy_level` exceeds the
|
|
106
|
+
ceiling. The ceiling is set by the human operator and never by an agent.
|
|
107
|
+
|
|
108
|
+
### 2. Freeze when you need to stop everything
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
rea freeze --reason "incident triage; investigate unexpected .env write"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`rea freeze` writes `.rea/HALT`. Every subsequent tool call is denied
|
|
115
|
+
until an operator runs:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
rea unfreeze --reason "false alarm — resolved"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Both calls produce audit entries. The middleware never clears HALT on
|
|
122
|
+
its own.
|
|
123
|
+
|
|
124
|
+
### 3. Verify the install
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
rea doctor
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`rea doctor` checks hook coverage, policy parse, husky commit-msg hook
|
|
131
|
+
install, `.mcp.json` gateway wiring, Codex plugin availability, and the
|
|
132
|
+
integrity of the audit hash chain. It returns a pass/fail summary with
|
|
133
|
+
specific remediation hints.
|
|
134
|
+
|
|
135
|
+
## Architecture
|
|
136
|
+
|
|
137
|
+
### Middleware chain
|
|
138
|
+
|
|
139
|
+
Every native MCP tool call AND every proxied downstream call flows through
|
|
140
|
+
one chain. The order matters — each layer fails closed.
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
tool call
|
|
144
|
+
│
|
|
145
|
+
▼
|
|
146
|
+
┌───────────────────────────────────────────────────┐
|
|
147
|
+
│ audit.enter — hash-chained record start │
|
|
148
|
+
│ kill-switch — deny if .rea/HALT exists │
|
|
149
|
+
│ tier — read/write/destructive class │
|
|
150
|
+
│ policy — autonomy gate (L0–L3) │
|
|
151
|
+
│ blocked-paths — .rea/ + operator paths │
|
|
152
|
+
│ rate-limit — token bucket per server │
|
|
153
|
+
│ circuit-breaker — trip on downstream failure │
|
|
154
|
+
│ redact (args) — secrets in arguments │
|
|
155
|
+
│ injection — prompt-injection heuristics │
|
|
156
|
+
│ │
|
|
157
|
+
│ ==== EXECUTE ==== │
|
|
158
|
+
│ │
|
|
159
|
+
│ redact (result) — secrets in result │
|
|
160
|
+
│ result-size-cap — bounded response │
|
|
161
|
+
│ audit.exit — hash-chained record close │
|
|
162
|
+
└───────────────────────────────────────────────────┘
|
|
163
|
+
│
|
|
164
|
+
▼
|
|
165
|
+
result
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`.rea/` is hardcoded as an always-blocked path. It cannot be unblocked
|
|
169
|
+
from policy. Policy is re-read on every invocation — any edit to
|
|
170
|
+
`policy.yaml` takes effect on the next tool call.
|
|
171
|
+
|
|
172
|
+
### Hook layer
|
|
173
|
+
|
|
174
|
+
Hooks are shell scripts wired into `.claude/settings.json`. They run at
|
|
175
|
+
Claude Code tool-invocation time, independently of the gateway. Both
|
|
176
|
+
layers fail closed. Bypassing one does not disable the other.
|
|
177
|
+
|
|
178
|
+
Every hook sources `hooks/_lib/halt-check.sh` and `hooks/_lib/policy-read.sh`
|
|
179
|
+
at the top of the script. Every hook uses `set -euo pipefail`.
|
|
180
|
+
|
|
181
|
+
### Slash commands
|
|
182
|
+
|
|
183
|
+
Five commands ship in the package and are copied into `.claude/commands/`
|
|
184
|
+
during `rea init`.
|
|
185
|
+
|
|
186
|
+
### Agent roster
|
|
187
|
+
|
|
188
|
+
Ten curated agents ship in the package: `rea-orchestrator`, `code-reviewer`,
|
|
189
|
+
`codex-adversarial`, `security-engineer`, `accessibility-engineer`,
|
|
190
|
+
`typescript-specialist`, `frontend-specialist`, `backend-engineer`,
|
|
191
|
+
`qa-engineer`, `technical-writer`. Four profiles
|
|
192
|
+
(`client-engagement`, `bst-internal`, `lit-wc`, `open-source`) layer
|
|
193
|
+
additional specialists on top.
|
|
194
|
+
|
|
195
|
+
The orchestrator is the single entry point for non-trivial tasks. The
|
|
196
|
+
CLAUDE.md template installed by `rea init` instructs the host agent:
|
|
197
|
+
_"For any non-trivial task, delegate to the `rea-orchestrator` agent
|
|
198
|
+
FIRST."_
|
|
199
|
+
|
|
200
|
+
## The Plan / Build / Review loop
|
|
201
|
+
|
|
202
|
+
Codex is a first-class part of REA. It is not a bolt-on. The BST
|
|
203
|
+
engineering process bakes adversarial review into the default flow, and
|
|
204
|
+
REA ships it out of the box.
|
|
205
|
+
|
|
206
|
+
| Phase | Primary model | Codex role | Governance |
|
|
207
|
+
| --- | --- | --- | --- |
|
|
208
|
+
| Plan | Claude Opus | — | Full middleware chain |
|
|
209
|
+
| Pre-implementation review | — | `/codex review` — review the PLAN before code | Audited |
|
|
210
|
+
| Build | Claude Opus | — | Full middleware chain |
|
|
211
|
+
| Adversarial review | — | `/codex adversarial-review` on the diff (independent perspective) | Audited, redacted, kill-switched |
|
|
212
|
+
| Pre-merge gate | — | `/codex adversarial-review` re-run; recorded in audit.jsonl | Required status check (recommended) |
|
|
213
|
+
|
|
214
|
+
Three things make this work:
|
|
215
|
+
|
|
216
|
+
1. The **`codex-adversarial` agent** in the curated roster wraps
|
|
217
|
+
`/codex adversarial-review`. The orchestrator delegates to it after
|
|
218
|
+
any non-trivial change.
|
|
219
|
+
2. The **`/codex-review` slash command** is one of the five shipped
|
|
220
|
+
commands. It produces an audit entry including the request summary,
|
|
221
|
+
response summary, and pass/fail signal.
|
|
222
|
+
3. The **`push-review-gate.sh` hook** checks for a recent `/codex-review`
|
|
223
|
+
audit entry on the current branch and warns (does not block) if none
|
|
224
|
+
is present.
|
|
225
|
+
|
|
226
|
+
Codex responses are treated as untrusted input. They flow through the
|
|
227
|
+
`redact` and `injection` middleware on return — same treatment as any
|
|
228
|
+
other downstream tool result. Codex never receives `.rea/policy.yaml`
|
|
229
|
+
content in its prompts; Codex reviews diffs, not policy.
|
|
230
|
+
|
|
231
|
+
If Codex is not installed, `rea doctor` warns with a one-line install
|
|
232
|
+
hint. REA does not require Codex to function, but the default workflow
|
|
233
|
+
assumes it.
|
|
234
|
+
|
|
235
|
+
## Hooks
|
|
236
|
+
|
|
237
|
+
Eleven hooks, down from reagent's 26. Each does one thing.
|
|
238
|
+
|
|
239
|
+
| Hook | Event | One-line purpose |
|
|
240
|
+
| --- | --- | --- |
|
|
241
|
+
| `dangerous-bash-interceptor` | PreToolUse: Bash | Block categories of destructive shell commands |
|
|
242
|
+
| `env-file-protection` | PreToolUse: Bash | Block reads of `.env*` files |
|
|
243
|
+
| `dependency-audit-gate` | PreToolUse: Bash | Run `npm audit`; block on high/critical |
|
|
244
|
+
| `commit-review-gate` | PreToolUse: Bash | Intercept `git commit`; require review on non-trivial diffs |
|
|
245
|
+
| `push-review-gate` | PreToolUse: Bash | Intercept `git push`; warn if no recent `/codex-review` |
|
|
246
|
+
| `attribution-advisory` | PreToolUse: Bash | Block commits containing AI attribution markers |
|
|
247
|
+
| `secret-scanner` | PreToolUse: Write\|Edit | Scan file writes for credential patterns |
|
|
248
|
+
| `settings-protection` | PreToolUse: Write\|Edit | Block agent writes to `.claude/settings.json` |
|
|
249
|
+
| `blocked-paths-enforcer` | PreToolUse: Write\|Edit | Enforce `blocked_paths` from policy |
|
|
250
|
+
| `changeset-security-gate` | PreToolUse: Write\|Edit | Require changeset entry on security-relevant changes |
|
|
251
|
+
| `architecture-review-gate` | PostToolUse: Write\|Edit | Flag edits crossing architectural boundaries |
|
|
252
|
+
|
|
253
|
+
A twelfth hook, `security-disclosure-gate`, intercepts `gh issue create`
|
|
254
|
+
commands containing security-sensitive keywords and redirects to private
|
|
255
|
+
disclosure. It is installed as part of the Bash PreToolUse set.
|
|
256
|
+
|
|
257
|
+
## Slash commands
|
|
258
|
+
|
|
259
|
+
| Command | Purpose |
|
|
260
|
+
| --- | --- |
|
|
261
|
+
| `/rea` | Session status — autonomy level, HALT state, last audit entries, next action |
|
|
262
|
+
| `/review` | Invoke the `code-reviewer` agent on current changes |
|
|
263
|
+
| `/codex-review` | Invoke the `codex-adversarial` agent → `/codex adversarial-review` |
|
|
264
|
+
| `/freeze` | Prompt for a reason and write `.rea/HALT` |
|
|
265
|
+
| `/halt-check` | Verify every middleware and hook respects HALT |
|
|
266
|
+
|
|
267
|
+
## Policy file reference
|
|
268
|
+
|
|
269
|
+
`.rea/policy.yaml` fields. The schema is zod-strict — unknown fields are
|
|
270
|
+
rejected, not ignored.
|
|
271
|
+
|
|
272
|
+
| Field | Type | Purpose |
|
|
273
|
+
| --- | --- | --- |
|
|
274
|
+
| `version` | string, `"1"` | Schema version; only `"1"` accepted in 0.1.x |
|
|
275
|
+
| `profile` | string | Profile name from `profiles/` (e.g. `bst-internal`) |
|
|
276
|
+
| `autonomy_level` | `L0`\|`L1`\|`L2`\|`L3` | Current autonomy. `L0` = read-only; `L3` = full tool access |
|
|
277
|
+
| `max_autonomy_level` | `L0`\|`L1`\|`L2`\|`L3` | Hard ceiling. `autonomy_level` cannot exceed this |
|
|
278
|
+
| `promotion_requires_human_approval` | boolean | Require operator confirmation to raise autonomy. Default `true` |
|
|
279
|
+
| `blocked_paths` | string[] | Glob patterns. `.rea/` is always blocked regardless of this list |
|
|
280
|
+
| `block_ai_attribution` | boolean | Enforce no-AI-attribution in commits and PR bodies |
|
|
281
|
+
| `context_protection.delegate_to_subagent` | string[] | Commands that must run in a subagent context to preserve the parent's context window |
|
|
282
|
+
| `context_protection.max_bash_output_lines` | number | Truncate long bash output at this line count |
|
|
283
|
+
| `notification_channel` | string | Optional Discord webhook URL. Empty string = no notifications |
|
|
284
|
+
|
|
285
|
+
`autonomy_level > max_autonomy_level` is rejected at parse time. Setting
|
|
286
|
+
`promotion_requires_human_approval: false` requires the CLI flag
|
|
287
|
+
`--i-understand-the-risks`.
|
|
288
|
+
|
|
289
|
+
## Migration from `@bookedsolid/reagent`
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
npx @bookedsolid/rea init --from-reagent
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
`--from-reagent`:
|
|
296
|
+
|
|
297
|
+
- Reads `.reagent/policy.yaml` and translates field-for-field into
|
|
298
|
+
`.rea/policy.yaml`. Field names are identical, so the translation is a
|
|
299
|
+
rename.
|
|
300
|
+
- Moves `.reagent/audit.jsonl` to `.rea/audit.jsonl` and verifies the
|
|
301
|
+
hash chain.
|
|
302
|
+
- Un-wires dropped hooks (Obsidian, PM-layer, account) from
|
|
303
|
+
`.claude/settings.json`.
|
|
304
|
+
- Replaces `reagent` slash commands and agents with the REA equivalents.
|
|
305
|
+
- Leaves `.reagent/` in place; you delete it manually after verifying
|
|
306
|
+
`rea doctor` passes and a dogfood run completes.
|
|
307
|
+
|
|
308
|
+
Reagent will be deprecated via `npm deprecate` within seven days of
|
|
309
|
+
REA 0.1.0. The deprecation notice points users here.
|
|
310
|
+
|
|
311
|
+
## Security
|
|
312
|
+
|
|
313
|
+
- [SECURITY.md](./SECURITY.md) — disclosure policy, supported versions,
|
|
314
|
+
and scope. Do not report vulnerabilities via public GitHub issues.
|
|
315
|
+
- [THREAT_MODEL.md](./THREAT_MODEL.md) — attack surface, mitigations,
|
|
316
|
+
residual risks. This is the contract REA holds itself to.
|
|
317
|
+
|
|
318
|
+
Short version: gateway and hook layers operate independently. Both fail
|
|
319
|
+
closed. `.rea/` is always blocked. Audit is hash-chained. Policy is
|
|
320
|
+
re-read on every invocation. npm publish uses OIDC provenance, not
|
|
321
|
+
long-lived tokens.
|
|
322
|
+
|
|
323
|
+
## Contributing
|
|
324
|
+
|
|
325
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md). Short version:
|
|
326
|
+
|
|
327
|
+
- DCO sign-off required on every commit (`git commit -s`). CI rejects
|
|
328
|
+
unsigned commits.
|
|
329
|
+
- No AI attribution in commit messages, PR bodies, or code. The
|
|
330
|
+
commit-msg hook enforces this.
|
|
331
|
+
- Conventional commits, TypeScript strict, ESLint zero-warnings,
|
|
332
|
+
Prettier, vitest.
|
|
333
|
+
- Security-sensitive paths (`src/gateway/middleware/**`, `src/policy/**`,
|
|
334
|
+
`hooks/**`, `.github/workflows/**`) require explicit maintainer
|
|
335
|
+
review and a threat-model update in the same PR.
|
|
336
|
+
|
|
337
|
+
## License
|
|
338
|
+
|
|
339
|
+
[MIT](./LICENSE)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| ------- | --------- |
|
|
7
|
+
| 0.1.x | Yes |
|
|
8
|
+
| < 0.1 | No (pre-release) |
|
|
9
|
+
|
|
10
|
+
## Reporting a Vulnerability
|
|
11
|
+
|
|
12
|
+
**Do not open a public GitHub issue for security vulnerabilities.**
|
|
13
|
+
|
|
14
|
+
Public issues expose vulnerabilities to attackers before users can patch. We follow coordinated disclosure — vulnerabilities are disclosed publicly only after a patch is released.
|
|
15
|
+
|
|
16
|
+
> Note: REA enforces this policy automatically. The `security-disclosure-gate` hook intercepts `gh issue create` commands containing security-sensitive keywords and blocks them with instructions to use private disclosure instead.
|
|
17
|
+
|
|
18
|
+
### Private Disclosure (preferred)
|
|
19
|
+
|
|
20
|
+
Email **security@bookedsolid.tech** with the details below. This is monitored and treated as confidential.
|
|
21
|
+
|
|
22
|
+
Alternatively, use [GitHub Security Advisories](https://github.com/bookedsolidtech/rea/security/advisories/new) to report privately. This creates a private discussion thread visible only to maintainers.
|
|
23
|
+
|
|
24
|
+
### What to include
|
|
25
|
+
|
|
26
|
+
- Description of the vulnerability and affected component
|
|
27
|
+
- Steps to reproduce (minimal PoC if possible)
|
|
28
|
+
- Potential impact and attack scenario
|
|
29
|
+
- Your suggested fix (optional but appreciated)
|
|
30
|
+
|
|
31
|
+
### Response timeline
|
|
32
|
+
|
|
33
|
+
| Step | Target |
|
|
34
|
+
| ------------------------- | ------------------------------------- |
|
|
35
|
+
| Acknowledgement | Within 72 hours |
|
|
36
|
+
| Patch for critical issues | Within 7 days of confirmed report |
|
|
37
|
+
| Public disclosure | Within 90 days, or sooner if patched |
|
|
38
|
+
|
|
39
|
+
## Scope
|
|
40
|
+
|
|
41
|
+
The following components are **in scope**:
|
|
42
|
+
|
|
43
|
+
- **Hook scripts** — all `.sh` files in `hooks/` and consumer-installed `.claude/hooks/`. REA ships shell scripts that execute on every Claude Code tool call with the full permissions of the user running Claude Code. Vulnerabilities in these scripts are treated as critical, equivalent to arbitrary code execution in the developer's environment.
|
|
44
|
+
- **CLI commands** — `rea init`, `rea freeze`, `rea unfreeze`, `rea serve`, `rea check`, `rea doctor`, and related entry points in `src/cli/`
|
|
45
|
+
- **MCP server and middleware chain** — policy enforcement, tier classification, blocked-path enforcement, secret redaction, audit logging, kill-switch, and injection detection layers
|
|
46
|
+
- **Policy loader** — `.rea/policy.yaml` parsing and schema validation; autonomy-ceiling enforcement
|
|
47
|
+
- **Prompt injection** — via proxied tool descriptions, tool names, or tool results
|
|
48
|
+
- **Tool name collision / shadowing** — native tool override via malicious downstream server config
|
|
49
|
+
- **Secret redaction gaps** — credential patterns not caught, encoding-based bypasses
|
|
50
|
+
- **Audit chain tampering** — hash chain bypass, log suppression techniques
|
|
51
|
+
- **Shell hook injection** — techniques to inject arbitrary commands through hook input parsing
|
|
52
|
+
- **HALT kill-switch bypass** — race conditions, symlink attacks, TOCTOU on `.rea/HALT`
|
|
53
|
+
- **Codex plugin integration** — review-gate bypass, audit entry suppression on Codex invocations
|
|
54
|
+
|
|
55
|
+
**Out of scope:**
|
|
56
|
+
|
|
57
|
+
- Vulnerabilities in Claude Code itself — report those to Anthropic
|
|
58
|
+
- Vulnerabilities in the Codex plugin itself — report those to OpenAI
|
|
59
|
+
- Bugs in the MCP protocol implementation — report those to the MCP maintainers or Anthropic
|
|
60
|
+
- Vulnerabilities in downstream MCP servers proxied through `.rea/registry.yaml` — report those to the respective project maintainers
|
|
61
|
+
- Social engineering
|
|
62
|
+
- Denial of service via resource exhaustion (unless it bypasses a security control)
|
|
63
|
+
- Issues requiring physical access to the machine
|
|
64
|
+
|
|
65
|
+
## Coordinated Disclosure
|
|
66
|
+
|
|
67
|
+
Once a patch is ready:
|
|
68
|
+
|
|
69
|
+
1. We release the patched version to npm
|
|
70
|
+
2. We publish a GitHub Security Advisory with full technical details
|
|
71
|
+
3. We credit the reporter (unless they prefer anonymity)
|
|
72
|
+
|
|
73
|
+
We ask reporters to wait for our patch before publishing their own writeup. Critical issues are patched within 7 days; other issues within a reasonable timeline based on complexity.
|
|
74
|
+
|
|
75
|
+
## Security Architecture
|
|
76
|
+
|
|
77
|
+
REA's security model is defense-in-depth across two independent layers:
|
|
78
|
+
|
|
79
|
+
**Gateway layer** (runtime, `rea serve`):
|
|
80
|
+
|
|
81
|
+
- Governance middleware chain — every tool call is audited, classified, and policy-checked
|
|
82
|
+
- Secret redaction on arguments (pre-execution) and results (post-execution)
|
|
83
|
+
- HALT kill switch — a single `.rea/HALT` file immediately blocks all tool calls
|
|
84
|
+
- Blocked path enforcement — `.rea/` and operator-defined paths are always protected
|
|
85
|
+
|
|
86
|
+
**Hook layer** (development-time, Claude Code hooks):
|
|
87
|
+
|
|
88
|
+
- 11 Claude Code hooks enforce security at the point of tool invocation
|
|
89
|
+
- `security-disclosure-gate` blocks public issue creation for security topics
|
|
90
|
+
- `settings-protection` prevents agents from modifying their own safety rails
|
|
91
|
+
- `dangerous-bash-interceptor` blocks categories of destructive shell commands
|
|
92
|
+
|
|
93
|
+
Both layers operate independently — compromising one does not disable the other.
|
|
94
|
+
|
|
95
|
+
## Security Design Notes
|
|
96
|
+
|
|
97
|
+
- No telemetry or network calls from the CLI or gateway (gateway only connects to operator-configured downstream servers)
|
|
98
|
+
- No `eval`, `Function()`, or dynamic `require` on policy-driven input
|
|
99
|
+
- Policy parsing is strict zod schema — unknown fields rejected, not ignored
|
|
100
|
+
- Path traversal protection on profile loading (regex + path containment check)
|
|
101
|
+
- CI publish pipeline includes gitleaks secret scanning, npm provenance attestation via OIDC, SBOM generation, and payload validation
|
|
102
|
+
- All shell hooks use `set -euo pipefail` with explicit variable quoting
|
|
103
|
+
- Commits are signed and DCO-signed-off; `main` branch protection requires passing checks and review
|
|
104
|
+
- npm publish uses OIDC provenance; no long-lived NPM tokens in CI
|