brainclaw 1.9.0 → 1.10.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/README.md +631 -499
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +18 -1
- package/dist/commands/code-map.js +129 -0
- package/dist/commands/codev.js +7 -0
- package/dist/commands/harvest.js +1 -1
- package/dist/commands/hooks.js +73 -73
- package/dist/commands/init.js +1 -1
- package/dist/commands/install-hooks.js +78 -78
- package/dist/commands/mcp-read-handlers.js +57 -14
- package/dist/commands/mcp.js +200 -13
- package/dist/commands/run-profile.js +3 -2
- package/dist/commands/switch.js +125 -93
- package/dist/commands/version.js +1 -1
- package/dist/core/agent-capability.js +19 -4
- package/dist/core/agent-files.js +131 -119
- package/dist/core/code-map/backend.js +123 -0
- package/dist/core/code-map/core.js +81 -0
- package/dist/core/code-map/drafts.js +2 -0
- package/dist/core/code-map/extractor.js +29 -0
- package/dist/core/code-map/finalizer.js +191 -0
- package/dist/core/code-map/freshness.js +108 -0
- package/dist/core/code-map/ids.js +0 -0
- package/dist/core/code-map/importable.js +35 -0
- package/dist/core/code-map/indexes.js +197 -0
- package/dist/core/code-map/lang/java/imports.scm +17 -0
- package/dist/core/code-map/lang/java/index.js +254 -0
- package/dist/core/code-map/lang/java/tags.scm +48 -0
- package/dist/core/code-map/lang/php/imports.scm +21 -0
- package/dist/core/code-map/lang/php/index.js +251 -0
- package/dist/core/code-map/lang/php/tags.scm +44 -0
- package/dist/core/code-map/lang/provider.js +9 -0
- package/dist/core/code-map/lang/providers.js +24 -0
- package/dist/core/code-map/lang/python/imports.scm +90 -0
- package/dist/core/code-map/lang/python/index.js +364 -0
- package/dist/core/code-map/lang/python/tags.scm +81 -0
- package/dist/core/code-map/lang/query-runtime.js +374 -0
- package/dist/core/code-map/lang/registry.js +125 -0
- package/dist/core/code-map/lang/typescript/imports.scm +90 -0
- package/dist/core/code-map/lang/typescript/index.js +306 -0
- package/dist/core/code-map/lang/typescript/tags.js.scm +106 -0
- package/dist/core/code-map/lang/typescript/tags.scm +151 -0
- package/dist/core/code-map/lock.js +210 -0
- package/dist/core/code-map/materialized.js +51 -0
- package/dist/core/code-map/memory-reader.js +59 -0
- package/dist/core/code-map/paths.js +53 -0
- package/dist/core/code-map/query.js +568 -0
- package/dist/core/code-map/refresh.js +0 -0
- package/dist/core/code-map/resolve.js +177 -0
- package/dist/core/code-map/store.js +206 -0
- package/dist/core/code-map/types.js +288 -0
- package/dist/core/code-map/vocabulary.js +57 -0
- package/dist/core/code-map/wasm-loader.js +294 -0
- package/dist/core/code-map/work-section.js +206 -0
- package/dist/core/codev-prompts.js +38 -38
- package/dist/core/codev-rounds.js +4 -0
- package/dist/core/default-profiles/doctor.yaml +11 -11
- package/dist/core/default-profiles/janitor.yaml +11 -11
- package/dist/core/default-profiles/onboarder.yaml +11 -11
- package/dist/core/default-profiles/reviewer.yaml +13 -13
- package/dist/core/dispatcher.js +1 -1
- package/dist/core/entity-operations.js +29 -3
- package/dist/core/execution-adapters.js +11 -10
- package/dist/core/execution-profile.js +58 -0
- package/dist/core/execution.js +1 -1
- package/dist/core/facade-schema.js +9 -0
- package/dist/core/instruction-templates.js +2 -0
- package/dist/core/loops/verbs.js +0 -1
- package/dist/core/mcp-command-resolution.js +3 -1
- package/dist/core/messaging.js +2 -2
- package/dist/core/protocol-skills.js +164 -164
- package/dist/core/runtime-signals.js +1 -1
- package/dist/core/search.js +19 -2
- package/dist/core/security-guard.js +207 -207
- package/dist/core/spawn-check.js +16 -2
- package/dist/core/staleness.js +1 -1
- package/dist/core/store-resolution.js +67 -11
- package/dist/core/worktree.js +18 -18
- package/dist/facts.js +9 -5
- package/dist/facts.json +8 -4
- package/dist/vendor/web-tree-sitter/tree-sitter.js +3980 -0
- package/dist/vendor/web-tree-sitter/tree-sitter.wasm +0 -0
- package/dist/wasm/tree-sitter-java.wasm +0 -0
- package/dist/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/wasm/tree-sitter-php.wasm +0 -0
- package/dist/wasm/tree-sitter-python.wasm +0 -0
- package/dist/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/wasm/tree-sitter.wasm +0 -0
- package/docs/PROTOCOL.md +1 -1
- package/docs/adapters/openclaw.md +43 -43
- package/docs/architecture/project-refs.md +328 -328
- package/docs/cli.md +2131 -2093
- package/docs/code-map.md +198 -0
- package/docs/concepts/coordination.md +52 -52
- package/docs/concepts/coordinator-runbook.md +129 -129
- package/docs/concepts/dispatch-lifecycle.md +245 -245
- package/docs/concepts/event-log-store.md +928 -928
- package/docs/concepts/ideation-loop.md +317 -317
- package/docs/concepts/loop-engine.md +520 -511
- package/docs/concepts/mcp-governance.md +268 -268
- package/docs/concepts/memory.md +84 -84
- package/docs/concepts/multi-agent-workflows.md +167 -167
- package/docs/concepts/observer-protocol.md +361 -361
- package/docs/concepts/plans-and-claims.md +217 -217
- package/docs/concepts/project-md-convention.md +35 -35
- package/docs/concepts/runtime-notes.md +38 -38
- package/docs/concepts/troubleshooting.md +254 -254
- package/docs/concepts/workspace-bootstrapping.md +142 -142
- package/docs/context-format-changelog.md +35 -35
- package/docs/context-format.md +48 -48
- package/docs/index.md +65 -65
- package/docs/integrations/agents.md +158 -158
- package/docs/integrations/claude-code.md +23 -23
- package/docs/integrations/cline.md +77 -77
- package/docs/integrations/continue.md +55 -55
- package/docs/integrations/copilot.md +68 -68
- package/docs/integrations/cursor.md +23 -23
- package/docs/integrations/kilocode.md +72 -72
- package/docs/integrations/mcp.md +385 -378
- package/docs/integrations/mistral-vibe.md +122 -122
- package/docs/integrations/openclaw.md +92 -92
- package/docs/integrations/opencode.md +84 -84
- package/docs/integrations/overview.md +115 -115
- package/docs/integrations/roo.md +71 -71
- package/docs/integrations/windsurf.md +77 -77
- package/docs/mcp-schema-changelog.md +364 -356
- package/docs/playbooks/integration/index.md +121 -121
- package/docs/playbooks/orchestration.md +37 -0
- package/docs/playbooks/productivity/index.md +99 -99
- package/docs/playbooks/team/index.md +117 -117
- package/docs/product/agent-first-model.md +184 -184
- package/docs/product/entity-model-audit.md +462 -462
- package/docs/product/positioning.md +86 -86
- package/docs/quickstart-existing-project.md +107 -107
- package/docs/quickstart.md +183 -183
- package/docs/release-maintenance.md +79 -79
- package/docs/reputation.md +52 -52
- package/docs/review.md +45 -45
- package/docs/security.md +212 -212
- package/docs/server-operations.md +118 -118
- package/docs/storage.md +106 -106
- package/package.json +86 -66
- package/docs/concepts/event-log-store-critique-A.md +0 -333
- package/docs/concepts/event-log-store-critique-B.md +0 -353
- package/docs/concepts/event-log-store-phase0-measurements.md +0 -58
- package/docs/concepts/event-log-store-proposal-A.md +0 -365
- package/docs/concepts/event-log-store-proposal-B.md +0 -404
- package/docs/concepts/identity-model-proposal.md +0 -371
package/docs/review.md
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
# Review and Reflection
|
|
2
|
-
|
|
3
|
-
brainclaw includes a reflective layer so not every observation has to become canonical memory immediately.
|
|
4
|
-
|
|
5
|
-
## Why this exists
|
|
6
|
-
|
|
7
|
-
Some facts are:
|
|
8
|
-
|
|
9
|
-
- durable and worth keeping
|
|
10
|
-
- useful but still uncertain
|
|
11
|
-
- too local or too temporary to promote immediately
|
|
12
|
-
|
|
13
|
-
A review layer helps filter and promote the right items.
|
|
14
|
-
|
|
15
|
-
## Typical flow
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
runtime-note → reflect-runtime-note → review candidate → accept / reject
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
1. capture a runtime note (`brainclaw runtime-note`)
|
|
22
|
-
2. reflect it into a candidate when useful (`brainclaw reflect-runtime-note`)
|
|
23
|
-
3. review the candidate (`brainclaw review`)
|
|
24
|
-
4. accept or reject it (`brainclaw accept` / `brainclaw reject`)
|
|
25
|
-
|
|
26
|
-
For MCP-capable agents, `brainclaw runtime-note` maps to `bclaw_write_note`.
|
|
27
|
-
|
|
28
|
-
## Star and use signals
|
|
29
|
-
|
|
30
|
-
Before formal review, candidates can accumulate signals:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
brainclaw star-candidate cnd_001 --by copilot # passive interest
|
|
34
|
-
brainclaw use-candidate cnd_001 --by copilot --context "auth rollout" # active reuse
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
`review --prioritized` uses these signals (along with freshness and semantic relevance) to surface the most important candidates.
|
|
38
|
-
|
|
39
|
-
## curator role
|
|
40
|
-
|
|
41
|
-
The `curator` trust level has direct promote access. Other roles create candidates for review.
|
|
42
|
-
|
|
43
|
-
## Why this is valuable
|
|
44
|
-
|
|
45
|
-
This keeps canonical memory cleaner while still preserving useful observations long enough to evaluate them.
|
|
1
|
+
# Review and Reflection
|
|
2
|
+
|
|
3
|
+
brainclaw includes a reflective layer so not every observation has to become canonical memory immediately.
|
|
4
|
+
|
|
5
|
+
## Why this exists
|
|
6
|
+
|
|
7
|
+
Some facts are:
|
|
8
|
+
|
|
9
|
+
- durable and worth keeping
|
|
10
|
+
- useful but still uncertain
|
|
11
|
+
- too local or too temporary to promote immediately
|
|
12
|
+
|
|
13
|
+
A review layer helps filter and promote the right items.
|
|
14
|
+
|
|
15
|
+
## Typical flow
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
runtime-note → reflect-runtime-note → review candidate → accept / reject
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
1. capture a runtime note (`brainclaw runtime-note`)
|
|
22
|
+
2. reflect it into a candidate when useful (`brainclaw reflect-runtime-note`)
|
|
23
|
+
3. review the candidate (`brainclaw review`)
|
|
24
|
+
4. accept or reject it (`brainclaw accept` / `brainclaw reject`)
|
|
25
|
+
|
|
26
|
+
For MCP-capable agents, `brainclaw runtime-note` maps to `bclaw_write_note`.
|
|
27
|
+
|
|
28
|
+
## Star and use signals
|
|
29
|
+
|
|
30
|
+
Before formal review, candidates can accumulate signals:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
brainclaw star-candidate cnd_001 --by copilot # passive interest
|
|
34
|
+
brainclaw use-candidate cnd_001 --by copilot --context "auth rollout" # active reuse
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`review --prioritized` uses these signals (along with freshness and semantic relevance) to surface the most important candidates.
|
|
38
|
+
|
|
39
|
+
## curator role
|
|
40
|
+
|
|
41
|
+
The `curator` trust level has direct promote access. Other roles create candidates for review.
|
|
42
|
+
|
|
43
|
+
## Why this is valuable
|
|
44
|
+
|
|
45
|
+
This keeps canonical memory cleaner while still preserving useful observations long enough to evaluate them.
|
package/docs/security.md
CHANGED
|
@@ -1,212 +1,212 @@
|
|
|
1
|
-
# Security
|
|
2
|
-
|
|
3
|
-
brainclaw is designed to be safe by default.
|
|
4
|
-
|
|
5
|
-
## Security model
|
|
6
|
-
|
|
7
|
-
### No network access by default
|
|
8
|
-
The CLI does not need to call external services to function. The optional
|
|
9
|
-
supply-chain gate (see below) is the one feature that talks to a remote
|
|
10
|
-
service, and it is off until explicitly enabled.
|
|
11
|
-
|
|
12
|
-
### No telemetry
|
|
13
|
-
brainclaw does not collect or send usage data.
|
|
14
|
-
|
|
15
|
-
### No secret management
|
|
16
|
-
brainclaw is not a vault and should not be treated like one.
|
|
17
|
-
|
|
18
|
-
### Plain-text visibility
|
|
19
|
-
The storage model is intentionally inspectable.
|
|
20
|
-
That makes review easier, but it also means users must be careful about what they write and commit.
|
|
21
|
-
|
|
22
|
-
## Built-in safety behaviors
|
|
23
|
-
|
|
24
|
-
### Content scanning (scanText)
|
|
25
|
-
|
|
26
|
-
Whenever content is added to `.brainclaw/` brainclaw scans the text in three
|
|
27
|
-
layers:
|
|
28
|
-
|
|
29
|
-
1. **User-configured regex patterns** from `redaction.patterns`. The
|
|
30
|
-
defaults catch words like `api_key`, `secret`, `token`, `password`.
|
|
31
|
-
2. **Structural detectors** for well-known token shapes — GitHub PATs
|
|
32
|
-
(`ghp_`, `gho_`, `github_pat_…`), AWS access keys (`AKIA…`/`ASIA…`),
|
|
33
|
-
Google API keys (`AIza…`), Slack tokens and webhooks, Stripe
|
|
34
|
-
`sk_live_/sk_test_` keys, JWTs, PEM-encoded private keys, and URLs
|
|
35
|
-
with embedded `user:password@host` credentials.
|
|
36
|
-
3. **Entropy detector** that flags high-Shannon-entropy substrings near
|
|
37
|
-
a secret keyword (api_key/token/secret/password/auth/...). This
|
|
38
|
-
catches custom-shaped keys the structural list does not enumerate.
|
|
39
|
-
|
|
40
|
-
In `security.mode: warn` matches surface as warnings; in
|
|
41
|
-
`security.strict_redaction: true` (or `security.mode: strict`) the same
|
|
42
|
-
matches block the write.
|
|
43
|
-
|
|
44
|
-
### Sensitive paths
|
|
45
|
-
|
|
46
|
-
When `security.block_sensitive_paths: true` (default), content that
|
|
47
|
-
references paths like `.env`, `secrets/`, `.git/`, or `node_modules/`
|
|
48
|
-
emits a warning.
|
|
49
|
-
|
|
50
|
-
### Configuration
|
|
51
|
-
|
|
52
|
-
```yaml
|
|
53
|
-
security:
|
|
54
|
-
mode: warn # 'warn' or 'strict' — affects redaction scanning
|
|
55
|
-
strict_redaction: false # if true, blocks entries with sensitive content
|
|
56
|
-
block_sensitive_paths: true
|
|
57
|
-
token_detection:
|
|
58
|
-
enabled: true # turn off all structural + entropy detection
|
|
59
|
-
entropy:
|
|
60
|
-
enabled: true
|
|
61
|
-
min_length: 32 # minimum substring length to consider
|
|
62
|
-
min_entropy: 4.0 # minimum Shannon entropy (bits/char)
|
|
63
|
-
detectors: # per-detector override map; explicit false disables a detector
|
|
64
|
-
aws_access_key: true
|
|
65
|
-
jwt: true
|
|
66
|
-
|
|
67
|
-
redaction:
|
|
68
|
-
enabled: true
|
|
69
|
-
patterns:
|
|
70
|
-
- '(?i)api[_-]?key'
|
|
71
|
-
- '(?i)secret'
|
|
72
|
-
- '(?i)token'
|
|
73
|
-
- '(?i)password'
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Supply-chain pre-install gate
|
|
77
|
-
|
|
78
|
-
`brainclaw setup-security` enables a preinstall gate that intercepts
|
|
79
|
-
`npm`/`pnpm`/`yarn`/`pip`/`pip3` install commands and asks Socket.dev's
|
|
80
|
-
scoring service whether the requested packages are risky.
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
brainclaw setup-security --mode advisory # default — warn-only
|
|
84
|
-
brainclaw setup-security --mode enforced # block risky installs
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Advisory vs enforced
|
|
88
|
-
|
|
89
|
-
The mode determines what happens when the gate decides a package is
|
|
90
|
-
risky:
|
|
91
|
-
|
|
92
|
-
- **advisory** — verdicts are surfaced (printed warning, security trap
|
|
93
|
-
created) but the install is *not* aborted.
|
|
94
|
-
- **enforced** — a `block` verdict aborts the install with a non-zero
|
|
95
|
-
exit code.
|
|
96
|
-
|
|
97
|
-
The mode is read from `security.preinstall.mode` and can be overridden
|
|
98
|
-
per call with `brainclaw check-security --mode <advisory|enforced>`.
|
|
99
|
-
|
|
100
|
-
### Exit codes
|
|
101
|
-
|
|
102
|
-
`brainclaw check-security` emits exit codes that already encode the mode
|
|
103
|
-
decision, so wrapper scripts are mode-agnostic:
|
|
104
|
-
|
|
105
|
-
| Exit | Meaning |
|
|
106
|
-
|------|------------------------------------------------------------|
|
|
107
|
-
| 0 | pass — no risky packages |
|
|
108
|
-
| 1 | warn — advisory-mode block, or warn-threshold verdict |
|
|
109
|
-
| 2 | block — enforced-mode block; the wrapper aborts the install|
|
|
110
|
-
|
|
111
|
-
The wrapper scripts (`<.brainclaw/security/bin>/npm`, `pnpm`, `yarn`,
|
|
112
|
-
`pip`, `pip3` and their `.ps1` counterparts) call the CLI and react
|
|
113
|
-
purely to the exit code, so flipping advisory↔enforced is a config
|
|
114
|
-
change — no regeneration required.
|
|
115
|
-
|
|
116
|
-
### Composite scoring
|
|
117
|
-
|
|
118
|
-
Each package gets five sub-scores from Socket (supply-chain,
|
|
119
|
-
vulnerability, quality, maintenance, license) on a 0–100 scale. The
|
|
120
|
-
gate combines them into a single composite using configurable weights:
|
|
121
|
-
|
|
122
|
-
```yaml
|
|
123
|
-
security:
|
|
124
|
-
preinstall:
|
|
125
|
-
weights:
|
|
126
|
-
supply_chain: 0.35
|
|
127
|
-
vulnerability: 0.30
|
|
128
|
-
quality: 0.15
|
|
129
|
-
maintenance: 0.15
|
|
130
|
-
license: 0.05
|
|
131
|
-
thresholds:
|
|
132
|
-
composite_pass: 70 # composite >= 70 → pass
|
|
133
|
-
composite_warn: 50 # composite >= 50 but < 70 → warn; below → block
|
|
134
|
-
supply_chain_block: 30 # hard block when supply_chain < 30
|
|
135
|
-
vulnerability_block: 20 # hard block when vulnerability < 20
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Weights are normalized to sum to 1.0 automatically — a config like
|
|
139
|
-
`{ supply_chain: 1, vulnerability: 1 }` is rescaled rather than
|
|
140
|
-
producing composites above 100. Thresholds are clamped to `[0,100]`
|
|
141
|
-
and `composite_warn` is capped at `composite_pass` so the verdict
|
|
142
|
-
function stays monotonic.
|
|
143
|
-
|
|
144
|
-
### Allowlist / denylist
|
|
145
|
-
|
|
146
|
-
```yaml
|
|
147
|
-
security:
|
|
148
|
-
preinstall:
|
|
149
|
-
allowlist:
|
|
150
|
-
- npm:internal-pkg # ecosystem-scoped
|
|
151
|
-
- npm:axios@1.14.0 # exact version pin
|
|
152
|
-
- lodash # bare name — any ecosystem, any version
|
|
153
|
-
denylist:
|
|
154
|
-
- npm:axios@1.14.1 # known-compromised version
|
|
155
|
-
- pypi:bad-pkg
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Matching is exact on each component. Bare names match by package name
|
|
159
|
-
only; an `ecosystem:` prefix scopes the match to that ecosystem;
|
|
160
|
-
appending `@version` (or `==version` for pip-style) requires an exact
|
|
161
|
-
version. The wildcard `@*` matches any version (useful for explicit
|
|
162
|
-
"any version" entries).
|
|
163
|
-
|
|
164
|
-
This is a hard tightening from the MVP: previously `denylist: ['lodash']`
|
|
165
|
-
matched any package whose purl contained the substring `lodash`, so
|
|
166
|
-
`react-lodash` was silently blocked. The new matcher requires exact
|
|
167
|
-
package-name equality.
|
|
168
|
-
|
|
169
|
-
### Package extraction sources
|
|
170
|
-
|
|
171
|
-
`check-security` can pull the list of packages from three places, which
|
|
172
|
-
may be combined:
|
|
173
|
-
|
|
174
|
-
- `--packages axios,express@1.2.3` — comma-separated specs
|
|
175
|
-
- `--requirements requirements.txt` — pip-style requirements file;
|
|
176
|
-
recursive `-r` includes, env markers, and extras are handled
|
|
177
|
-
- `--lockfile package-lock.json` — npm package-lock (v1, v2, v3);
|
|
178
|
-
scans top-level direct deps and devDeps
|
|
179
|
-
|
|
180
|
-
The wrappers auto-translate `npm install -r foo.txt` → `--requirements`,
|
|
181
|
-
skip filesystem paths and URL specs that aren't registry packages
|
|
182
|
-
(`./local-pkg`, `git+https://…`, `*.tgz`, `*.whl`), and handle the
|
|
183
|
-
common npm/pip flag conventions.
|
|
184
|
-
|
|
185
|
-
### Offline / fetch-error fallback
|
|
186
|
-
|
|
187
|
-
When the Socket call fails (network down, service unreachable), the
|
|
188
|
-
gate uses `security.preinstall.fallback_on_error`:
|
|
189
|
-
|
|
190
|
-
- `block` — fail closed regardless of mode
|
|
191
|
-
- `warn` — surface a warning, continue with whatever cached scores
|
|
192
|
-
exist; if no cache exists the gate exits with code 1
|
|
193
|
-
- `pass` — silent fall-through (the install proceeds)
|
|
194
|
-
|
|
195
|
-
Cached scores have a TTL of `cache_ttl_hours` (default 24) and live
|
|
196
|
-
in `.brainclaw/security/cache.json`.
|
|
197
|
-
|
|
198
|
-
## Recommended stance
|
|
199
|
-
|
|
200
|
-
- do not store secrets — even with detection, the safer move is to never
|
|
201
|
-
write them
|
|
202
|
-
- review what gets committed
|
|
203
|
-
- keep machine-local observations machine-local when appropriate
|
|
204
|
-
- use stricter redaction settings in sensitive environments
|
|
205
|
-
- run `setup-security --mode advisory` first; flip to `enforced` once
|
|
206
|
-
the team has gotten used to the verdicts
|
|
207
|
-
|
|
208
|
-
## Important nuance
|
|
209
|
-
|
|
210
|
-
brainclaw reduces hidden behavior, but it does not remove the need for
|
|
211
|
-
operational discipline. It warns; the team still decides what belongs
|
|
212
|
-
in shared memory.
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
brainclaw is designed to be safe by default.
|
|
4
|
+
|
|
5
|
+
## Security model
|
|
6
|
+
|
|
7
|
+
### No network access by default
|
|
8
|
+
The CLI does not need to call external services to function. The optional
|
|
9
|
+
supply-chain gate (see below) is the one feature that talks to a remote
|
|
10
|
+
service, and it is off until explicitly enabled.
|
|
11
|
+
|
|
12
|
+
### No telemetry
|
|
13
|
+
brainclaw does not collect or send usage data.
|
|
14
|
+
|
|
15
|
+
### No secret management
|
|
16
|
+
brainclaw is not a vault and should not be treated like one.
|
|
17
|
+
|
|
18
|
+
### Plain-text visibility
|
|
19
|
+
The storage model is intentionally inspectable.
|
|
20
|
+
That makes review easier, but it also means users must be careful about what they write and commit.
|
|
21
|
+
|
|
22
|
+
## Built-in safety behaviors
|
|
23
|
+
|
|
24
|
+
### Content scanning (scanText)
|
|
25
|
+
|
|
26
|
+
Whenever content is added to `.brainclaw/` brainclaw scans the text in three
|
|
27
|
+
layers:
|
|
28
|
+
|
|
29
|
+
1. **User-configured regex patterns** from `redaction.patterns`. The
|
|
30
|
+
defaults catch words like `api_key`, `secret`, `token`, `password`.
|
|
31
|
+
2. **Structural detectors** for well-known token shapes — GitHub PATs
|
|
32
|
+
(`ghp_`, `gho_`, `github_pat_…`), AWS access keys (`AKIA…`/`ASIA…`),
|
|
33
|
+
Google API keys (`AIza…`), Slack tokens and webhooks, Stripe
|
|
34
|
+
`sk_live_/sk_test_` keys, JWTs, PEM-encoded private keys, and URLs
|
|
35
|
+
with embedded `user:password@host` credentials.
|
|
36
|
+
3. **Entropy detector** that flags high-Shannon-entropy substrings near
|
|
37
|
+
a secret keyword (api_key/token/secret/password/auth/...). This
|
|
38
|
+
catches custom-shaped keys the structural list does not enumerate.
|
|
39
|
+
|
|
40
|
+
In `security.mode: warn` matches surface as warnings; in
|
|
41
|
+
`security.strict_redaction: true` (or `security.mode: strict`) the same
|
|
42
|
+
matches block the write.
|
|
43
|
+
|
|
44
|
+
### Sensitive paths
|
|
45
|
+
|
|
46
|
+
When `security.block_sensitive_paths: true` (default), content that
|
|
47
|
+
references paths like `.env`, `secrets/`, `.git/`, or `node_modules/`
|
|
48
|
+
emits a warning.
|
|
49
|
+
|
|
50
|
+
### Configuration
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
security:
|
|
54
|
+
mode: warn # 'warn' or 'strict' — affects redaction scanning
|
|
55
|
+
strict_redaction: false # if true, blocks entries with sensitive content
|
|
56
|
+
block_sensitive_paths: true
|
|
57
|
+
token_detection:
|
|
58
|
+
enabled: true # turn off all structural + entropy detection
|
|
59
|
+
entropy:
|
|
60
|
+
enabled: true
|
|
61
|
+
min_length: 32 # minimum substring length to consider
|
|
62
|
+
min_entropy: 4.0 # minimum Shannon entropy (bits/char)
|
|
63
|
+
detectors: # per-detector override map; explicit false disables a detector
|
|
64
|
+
aws_access_key: true
|
|
65
|
+
jwt: true
|
|
66
|
+
|
|
67
|
+
redaction:
|
|
68
|
+
enabled: true
|
|
69
|
+
patterns:
|
|
70
|
+
- '(?i)api[_-]?key'
|
|
71
|
+
- '(?i)secret'
|
|
72
|
+
- '(?i)token'
|
|
73
|
+
- '(?i)password'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Supply-chain pre-install gate
|
|
77
|
+
|
|
78
|
+
`brainclaw setup-security` enables a preinstall gate that intercepts
|
|
79
|
+
`npm`/`pnpm`/`yarn`/`pip`/`pip3` install commands and asks Socket.dev's
|
|
80
|
+
scoring service whether the requested packages are risky.
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
brainclaw setup-security --mode advisory # default — warn-only
|
|
84
|
+
brainclaw setup-security --mode enforced # block risky installs
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Advisory vs enforced
|
|
88
|
+
|
|
89
|
+
The mode determines what happens when the gate decides a package is
|
|
90
|
+
risky:
|
|
91
|
+
|
|
92
|
+
- **advisory** — verdicts are surfaced (printed warning, security trap
|
|
93
|
+
created) but the install is *not* aborted.
|
|
94
|
+
- **enforced** — a `block` verdict aborts the install with a non-zero
|
|
95
|
+
exit code.
|
|
96
|
+
|
|
97
|
+
The mode is read from `security.preinstall.mode` and can be overridden
|
|
98
|
+
per call with `brainclaw check-security --mode <advisory|enforced>`.
|
|
99
|
+
|
|
100
|
+
### Exit codes
|
|
101
|
+
|
|
102
|
+
`brainclaw check-security` emits exit codes that already encode the mode
|
|
103
|
+
decision, so wrapper scripts are mode-agnostic:
|
|
104
|
+
|
|
105
|
+
| Exit | Meaning |
|
|
106
|
+
|------|------------------------------------------------------------|
|
|
107
|
+
| 0 | pass — no risky packages |
|
|
108
|
+
| 1 | warn — advisory-mode block, or warn-threshold verdict |
|
|
109
|
+
| 2 | block — enforced-mode block; the wrapper aborts the install|
|
|
110
|
+
|
|
111
|
+
The wrapper scripts (`<.brainclaw/security/bin>/npm`, `pnpm`, `yarn`,
|
|
112
|
+
`pip`, `pip3` and their `.ps1` counterparts) call the CLI and react
|
|
113
|
+
purely to the exit code, so flipping advisory↔enforced is a config
|
|
114
|
+
change — no regeneration required.
|
|
115
|
+
|
|
116
|
+
### Composite scoring
|
|
117
|
+
|
|
118
|
+
Each package gets five sub-scores from Socket (supply-chain,
|
|
119
|
+
vulnerability, quality, maintenance, license) on a 0–100 scale. The
|
|
120
|
+
gate combines them into a single composite using configurable weights:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
security:
|
|
124
|
+
preinstall:
|
|
125
|
+
weights:
|
|
126
|
+
supply_chain: 0.35
|
|
127
|
+
vulnerability: 0.30
|
|
128
|
+
quality: 0.15
|
|
129
|
+
maintenance: 0.15
|
|
130
|
+
license: 0.05
|
|
131
|
+
thresholds:
|
|
132
|
+
composite_pass: 70 # composite >= 70 → pass
|
|
133
|
+
composite_warn: 50 # composite >= 50 but < 70 → warn; below → block
|
|
134
|
+
supply_chain_block: 30 # hard block when supply_chain < 30
|
|
135
|
+
vulnerability_block: 20 # hard block when vulnerability < 20
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Weights are normalized to sum to 1.0 automatically — a config like
|
|
139
|
+
`{ supply_chain: 1, vulnerability: 1 }` is rescaled rather than
|
|
140
|
+
producing composites above 100. Thresholds are clamped to `[0,100]`
|
|
141
|
+
and `composite_warn` is capped at `composite_pass` so the verdict
|
|
142
|
+
function stays monotonic.
|
|
143
|
+
|
|
144
|
+
### Allowlist / denylist
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
security:
|
|
148
|
+
preinstall:
|
|
149
|
+
allowlist:
|
|
150
|
+
- npm:internal-pkg # ecosystem-scoped
|
|
151
|
+
- npm:axios@1.14.0 # exact version pin
|
|
152
|
+
- lodash # bare name — any ecosystem, any version
|
|
153
|
+
denylist:
|
|
154
|
+
- npm:axios@1.14.1 # known-compromised version
|
|
155
|
+
- pypi:bad-pkg
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Matching is exact on each component. Bare names match by package name
|
|
159
|
+
only; an `ecosystem:` prefix scopes the match to that ecosystem;
|
|
160
|
+
appending `@version` (or `==version` for pip-style) requires an exact
|
|
161
|
+
version. The wildcard `@*` matches any version (useful for explicit
|
|
162
|
+
"any version" entries).
|
|
163
|
+
|
|
164
|
+
This is a hard tightening from the MVP: previously `denylist: ['lodash']`
|
|
165
|
+
matched any package whose purl contained the substring `lodash`, so
|
|
166
|
+
`react-lodash` was silently blocked. The new matcher requires exact
|
|
167
|
+
package-name equality.
|
|
168
|
+
|
|
169
|
+
### Package extraction sources
|
|
170
|
+
|
|
171
|
+
`check-security` can pull the list of packages from three places, which
|
|
172
|
+
may be combined:
|
|
173
|
+
|
|
174
|
+
- `--packages axios,express@1.2.3` — comma-separated specs
|
|
175
|
+
- `--requirements requirements.txt` — pip-style requirements file;
|
|
176
|
+
recursive `-r` includes, env markers, and extras are handled
|
|
177
|
+
- `--lockfile package-lock.json` — npm package-lock (v1, v2, v3);
|
|
178
|
+
scans top-level direct deps and devDeps
|
|
179
|
+
|
|
180
|
+
The wrappers auto-translate `npm install -r foo.txt` → `--requirements`,
|
|
181
|
+
skip filesystem paths and URL specs that aren't registry packages
|
|
182
|
+
(`./local-pkg`, `git+https://…`, `*.tgz`, `*.whl`), and handle the
|
|
183
|
+
common npm/pip flag conventions.
|
|
184
|
+
|
|
185
|
+
### Offline / fetch-error fallback
|
|
186
|
+
|
|
187
|
+
When the Socket call fails (network down, service unreachable), the
|
|
188
|
+
gate uses `security.preinstall.fallback_on_error`:
|
|
189
|
+
|
|
190
|
+
- `block` — fail closed regardless of mode
|
|
191
|
+
- `warn` — surface a warning, continue with whatever cached scores
|
|
192
|
+
exist; if no cache exists the gate exits with code 1
|
|
193
|
+
- `pass` — silent fall-through (the install proceeds)
|
|
194
|
+
|
|
195
|
+
Cached scores have a TTL of `cache_ttl_hours` (default 24) and live
|
|
196
|
+
in `.brainclaw/security/cache.json`.
|
|
197
|
+
|
|
198
|
+
## Recommended stance
|
|
199
|
+
|
|
200
|
+
- do not store secrets — even with detection, the safer move is to never
|
|
201
|
+
write them
|
|
202
|
+
- review what gets committed
|
|
203
|
+
- keep machine-local observations machine-local when appropriate
|
|
204
|
+
- use stricter redaction settings in sensitive environments
|
|
205
|
+
- run `setup-security --mode advisory` first; flip to `enforced` once
|
|
206
|
+
the team has gotten used to the verdicts
|
|
207
|
+
|
|
208
|
+
## Important nuance
|
|
209
|
+
|
|
210
|
+
brainclaw reduces hidden behavior, but it does not remove the need for
|
|
211
|
+
operational discipline. It warns; the team still decides what belongs
|
|
212
|
+
in shared memory.
|