@rafinery/cli 0.11.0 → 0.12.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/bin/rafa.mjs +10 -0
- package/blueprint/.claude/agents/atlas.md +2 -2
- package/blueprint/.claude/agents/bloom.md +3 -2
- package/blueprint/.claude/commands/rafa.md +1 -1
- package/blueprint/.claude/rafa/contract.md +10 -4
- package/blueprint/.claude/skills/rafa-build/SKILL.md +5 -1
- package/blueprint/.claude/skills/rafa-improve/SKILL.md +17 -6
- package/blueprint/.claude/skills/rafa-okf/SKILL.md +1 -1
- package/blueprint/.claude/skills/rafa-plan/SKILL.md +14 -1
- package/blueprint/.claude/skills/rafa-scan/SKILL.md +9 -1
- package/blueprint/.claude/skills/rafa-security/SKILL.md +96 -0
- package/lib/audit/core.mjs +488 -0
- package/lib/audit.mjs +279 -0
- package/lib/blueprint.mjs +1 -0
- package/lib/distiller/doctrine.mjs +4 -4
- package/lib/doctor.mjs +16 -0
- package/lib/gate/compile.mjs +17 -13
- package/lib/init.mjs +3 -2
- package/lib/manifest.mjs +2 -1
- package/lib/mcp-client.mjs +3 -2
- package/lib/working-set.mjs +3 -2
- package/package.json +1 -1
- package/skills-bundle/skills-manifest.json +1 -1
package/bin/rafa.mjs
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
// rafa distill --headless CI merge-to-main distillation (org's own LLM key)
|
|
19
19
|
// rafa ci-setup write the reconcile workflow (fold + distill on PR merge)
|
|
20
20
|
// rafa leverage inspect your agent toolbox → proactive tips
|
|
21
|
+
// rafa audit [--json] self-contained security engine: dep CVEs (OSV) ·
|
|
22
|
+
// secrets (built-in ruleset) · SAST (semgrep if present)
|
|
21
23
|
// rafa benchmark reproduce the brain-vs-cold token proof on THIS repo (measured)
|
|
22
24
|
// rafa migrate bring structured files (plans/config) up to the current schema
|
|
23
25
|
//
|
|
@@ -53,6 +55,7 @@ const COMMANDS = [
|
|
|
53
55
|
"distill",
|
|
54
56
|
"ci-setup",
|
|
55
57
|
"leverage",
|
|
58
|
+
"audit",
|
|
56
59
|
"benchmark",
|
|
57
60
|
"manifest",
|
|
58
61
|
"review",
|
|
@@ -140,6 +143,13 @@ Commands:
|
|
|
140
143
|
PR merge) and name the CI secrets to configure.
|
|
141
144
|
leverage Inspect your agent toolbox (permissions, skills, MCP) and print
|
|
142
145
|
prioritized tips for getting more out of it. Advisory — changes nothing.
|
|
146
|
+
audit Self-contained security engine (rafa.audit/v1): dependency CVEs via
|
|
147
|
+
the built-in lockfile parser + OSV.dev (pnpm audit merged in),
|
|
148
|
+
secrets via the built-in ruleset (tracked files only, .env* never
|
|
149
|
+
opened, fingerprints never bytes), SAST via semgrep IF present —
|
|
150
|
+
tiers that can't run say so honestly. --json emits the envelope;
|
|
151
|
+
writes .rafa/improve/security-audit.{json,md} when .rafa exists.
|
|
152
|
+
Exit: 0 clean · 1 findings · 2 engine error. Installs nothing.
|
|
143
153
|
benchmark Reproduce the brain-vs-cold token-efficiency proof on THIS repo: cut
|
|
144
154
|
two isolated worktrees (A=cold, B=brain), run the same task fixture,
|
|
145
155
|
count harness tokens, emit a MEASURED benchmark.json. --dry-run
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: atlas
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.1.0
|
|
4
4
|
model: opus # authoring is correctness-critical — a hallucinated note poisons the brain; best model, never cheap
|
|
5
5
|
groundTruth: code-at-sha
|
|
6
6
|
description: >-
|
|
@@ -15,7 +15,7 @@ color: blue
|
|
|
15
15
|
duties:
|
|
16
16
|
- "scan :: .claude/skills/rafa-scan/SKILL.md :: comprehensive breadth-first cited brain · verify-citations exits 0 · coverage honest (thin/gap stated, never hidden)"
|
|
17
17
|
- "repair :: .claude/skills/rafa-scan/SKILL.md :: every blocker + major in checklist.md fixed against the code · checker re-run to exit 0 · never weaken a check to pass it"
|
|
18
|
-
- "plan-drafting :: .claude/skills/rafa-plan/SKILL.md :: recall-grounded decomposition (coverage → search → notes) · blast radius named · contract §7 files · every child carries a Done-check"
|
|
18
|
+
- "plan-drafting :: .claude/skills/rafa-plan/SKILL.md :: recall-grounded decomposition (coverage → search → notes) · blast radius named · contract §7 files · every child carries a Done-check · the security audit runs BEFORE approval and its picture is presented to the dev verbatim (§3b — totals + blast-radius criticals; clean said out loud, never silence)"
|
|
19
19
|
- "build-execution :: .claude/skills/rafa-build/SKILL.md :: implement per recalled knowledge · TDD-DEFAULT when the tdd skill + a harness are present (the Done-check is a failing test FIRST at the plan-named seam; red→green evidence in the return) · UI tasks run the installed design skills per SOP (brain conventions win) · read session-facts FIRST and bank new expensive verifications (rafa facts add) · never hand-edit brain files around the gate · return what changed, cited"
|
|
20
20
|
- "scoped-refresh :: .claude/skills/rafa-scan/SKILL.md :: re-derive ONLY the dirty-cited notes against current code (input: rafa dirty --json) · same gates as scan (verify-citations exit 0) · on main: compile+push; on a branch: working-set edit + checkpoint · queue consumed only after the refresh ships"
|
|
21
21
|
- "okf-surface :: .claude/skills/rafa-okf/SKILL.md :: authored files pass rafa okf check as written — body links are markdown (never wikilinks); emit-owned sections untouched"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bloom
|
|
3
|
-
version: 0.
|
|
3
|
+
version: 0.10.0
|
|
4
4
|
model: opus # a false flag mutes the whole ledger — best model, never cheap
|
|
5
5
|
groundTruth: code-trend
|
|
6
6
|
description: >-
|
|
@@ -15,7 +15,8 @@ color: green
|
|
|
15
15
|
duties:
|
|
16
16
|
- "improve-pass :: .claude/skills/rafa-improve/SKILL.md :: cited · prioritized P0–P3 · the architecture lens applies the deletion-test/depth method with its vocabulary (Confidence-lined candidates, first-slice-or-backlog, never big-bang) · leverage-ranked · cite-checked (unresolved dropped) · ledger + debt trend regenerated"
|
|
17
17
|
- "plan-pull :: .claude/skills/rafa-plan/SKILL.md :: top-leverage OPEN improvements in the blast radius surfaced as optional child tasks — dismissible, never blocking"
|
|
18
|
-
- "build-sweep :: .claude/skills/rafa-build/SKILL.md :: newly spotted → ledger files · fixed-in-passing → status fixed · at most ONE opt-in nudge per task"
|
|
18
|
+
- "build-sweep :: .claude/skills/rafa-build/SKILL.md :: newly spotted → ledger files · fixed-in-passing → status fixed · at most ONE opt-in nudge per task · the cheap dependency tier of `rafa audit` re-runs so a mid-build lockfile change is caught"
|
|
19
|
+
- "security-profile :: .claude/skills/rafa-security/SKILL.md :: `rafa audit --json` is the engine (never LLM-pretended) · findings → category:security rows with the MECHANICAL priority map (critical→P0…dev-only→P3, annotate reachability, never downgrade) · P0 security rows are the ONE class that may surface outside the blast radius (dismissible, never blocking)"
|
|
19
20
|
- "staleness-watch :: .claude/skills/rafa-improve/SKILL.md :: median open-item age stays minimal — every sweep re-validates or closes aged items; no improvement ages silently"
|
|
20
21
|
- "okf-surface :: .claude/skills/rafa-okf/SKILL.md :: improvements/ledger pass rafa okf check as written · found: authored so timestamps are authored truth"
|
|
21
22
|
---
|
|
@@ -232,7 +232,7 @@ explicitly typed; an ACCEPTED boundary offer counts as the explicit invocation.
|
|
|
232
232
|
|---|---|---|
|
|
233
233
|
| `plan <intent>` | trio decomposition — atlas drafts brain-grounded contract §7 files (Done-checks), bloom pulls blast-radius improvements, prism validates the plan; approval → compile → `push_plan` + `set_active_plan` | [rafa-plan](../skills/rafa-plan/SKILL.md) |
|
|
234
234
|
| `build` | execute the active plan per item (in `blocked_by` order): atlas recalls+implements → prism gates `status: done` on the `## Done-check` → bloom sweeps the ledger → update file + journals → checkpoint (push_plan/log_decision/`rafa checkpoint`); final verify + clear `active.md` when all children done | [rafa-build](../skills/rafa-build/SKILL.md) |
|
|
235
|
-
| `improve` | spawn bloom → cited, prioritized P0–P3 ledger in `.rafa/improve/`; surface only the top few high-leverage items, never nag | [rafa-improve](../skills/rafa-improve/SKILL.md) |
|
|
235
|
+
| `improve` | spawn bloom → cited, prioritized P0–P3 ledger in `.rafa/improve/`; surface only the top few high-leverage items, never nag. Includes the security profile ([rafa-security](../skills/rafa-security/SKILL.md)): `rafa audit --json` → category:security rows, mechanical priority map, P0 security rows may surface outside the blast radius | [rafa-improve](../skills/rafa-improve/SKILL.md) |
|
|
236
236
|
| `scan [--brain-only]` | the full pass know → verify → improve → push — atlas maps → gate-1 checker → prism validates → iterate (max 3) → improve → push on approval → founding-scan coach offer. `--brain-only` stops after validation. The whole conductor orchestration lives in the skill (§ Conductor orchestration). | [rafa-scan](../skills/rafa-scan/SKILL.md) |
|
|
237
237
|
| `init` | first run: ensure `.rafa/active.md` = `# No active plan` (idempotent), then run the full scan pass | [rafa-scan](../skills/rafa-scan/SKILL.md) |
|
|
238
238
|
| `distill [<branch>]` | reconcile a merged branch's working set into the org brain — prism validates each file vs merged MAIN, atlas authors survivors through verify-citations · compile · push, refutes with cites, flags `needs-adjudication`. Offer-driven at bootstrap; CI runs it headlessly. | [rafa-distill](../skills/rafa-distill/SKILL.md) |
|
|
@@ -197,7 +197,8 @@ JSON. This is the exact shape the platform binds to.
|
|
|
197
197
|
{
|
|
198
198
|
"id": "dead-model-options-google-crewai",
|
|
199
199
|
"priority": "P1", // P0 | P1 | P2 | P3
|
|
200
|
-
"
|
|
200
|
+
"category": "product", // security|correctness|performance|architecture|product|ops
|
|
201
|
+
"lens": "product", // transitional mirror of category (pre-2026-07-26 name) — dropped with the backfill arc
|
|
201
202
|
"status": "open", // open | backlog | fixed | wontfix
|
|
202
203
|
"title": "…",
|
|
203
204
|
"summary": "…",
|
|
@@ -278,7 +279,7 @@ value).
|
|
|
278
279
|
schemaVersion: 1
|
|
279
280
|
id: dead-model-options-google-crewai # required · == filename stem
|
|
280
281
|
priority: P1 # required · P0 | P1 | P2 | P3
|
|
281
|
-
|
|
282
|
+
category: product # required · security|correctness|performance|architecture|product|ops
|
|
282
283
|
status: open # required · open | backlog | fixed | wontfix
|
|
283
284
|
title: Two of the four model options are dead and fail silently # required
|
|
284
285
|
summary: google_genai and crewai route to unwired agents # required
|
|
@@ -295,6 +296,11 @@ found: 2026-07-02 # optional · ISO date
|
|
|
295
296
|
Note: `title`, `summary`, `fix` are now **required frontmatter** — previously scraped
|
|
296
297
|
from prose. That scraping is gone; these are authored values.
|
|
297
298
|
|
|
299
|
+
`category` is the canonical field name (2026-07-26). The pre-rename name `lens`
|
|
300
|
+
is accepted as a **deprecated alias** by the compile gate (`category ?? lens`,
|
|
301
|
+
same enum); the manifest carries both keys during the transition. New files
|
|
302
|
+
author `category:` only.
|
|
303
|
+
|
|
298
304
|
---
|
|
299
305
|
|
|
300
306
|
## 4. Health file — `brain/checklist.md`
|
|
@@ -529,9 +535,9 @@ i.e. the default branch's instance).
|
|
|
529
535
|
|
|
530
536
|
**Search = deterministic lexical retrieval; the server retrieves, the agent decides.**
|
|
531
537
|
Fields searched per type — rule/playbook: `title, summary, domain, type` ·
|
|
532
|
-
improvement: `title, summary,
|
|
538
|
+
improvement: `title, summary, category, blast_radius` · plan: `title, plan, parent`.
|
|
533
539
|
Score = Σ over matched case-folded query tokens of field weight (`title` 3 ·
|
|
534
|
-
`domain`/`
|
|
540
|
+
`domain`/`category`/`blast_radius`/`type`/`plan`/`parent` 2 · `summary` 1); tie-break
|
|
535
541
|
score desc then id asc; fields a type lacks are omitted, never defaulted. Candidates
|
|
536
542
|
carry `matchKind: "lexical"` (`"semantic"` reserved).
|
|
537
543
|
|
|
@@ -43,7 +43,11 @@ platform MCP (one read path — the same surface any third-party agent uses).
|
|
|
43
43
|
[rafa-commit](../rafa-commit/SKILL.md) format — `[<task-id>] <type>:
|
|
44
44
|
<subject>` (the id join-key; intent records + the branch manifest lift it
|
|
45
45
|
into per-note provenance)** → prism validates vs `## Done-check` →
|
|
46
|
-
bloom sweeps (push new / close fixed / nudge
|
|
46
|
+
bloom sweeps (push new / close fixed / nudge; **when THIS task changed a
|
|
47
|
+
lockfile/manifest, re-run the cheap dependency tier — `rafa audit --json` —
|
|
48
|
+
and report the delta to the dev in one transparent line: new/cleared
|
|
49
|
+
findings, never silence**; a new critical → a `category: security` P0 row
|
|
50
|
+
surfaced now) → update the child file's `status`
|
|
47
51
|
**and append a dated entry to the child's `## Log`** (body links: markdown,
|
|
48
52
|
per [rafa-okf](../rafa-okf/SKILL.md)) — what was done, what was
|
|
49
53
|
decided, what surprised (body prose: displayed verbatim on the platform, never
|
|
@@ -50,7 +50,7 @@ Invoke via `/rafa improve`. The brain (#1) must exist — bloom *uses* it as the
|
|
|
50
50
|
## Output (to `.rafa/improve/`)
|
|
51
51
|
|
|
52
52
|
- `improvements/<id>.md` — one file per improvement (cited, prioritized, status-tracked).
|
|
53
|
-
- `ledger.md` — generated index: counts by priority/
|
|
53
|
+
- `ledger.md` — generated index: counts by priority/category/status + the **health/debt trend**.
|
|
54
54
|
Its **frontmatter carries the machine-read `open` · `debt_score` · `by_priority`** (per
|
|
55
55
|
[`.claude/rafa/contract.md`](../../rafa/contract.md) §5) — the platform reads *that*, never the body tables,
|
|
56
56
|
and `rafa compile` cross-checks `open`/`by_priority` against the actual improvement rows.
|
|
@@ -65,7 +65,7 @@ platform shows them; nothing is scraped from prose). Example *illustrative — f
|
|
|
65
65
|
schemaVersion: 1
|
|
66
66
|
id: rsc-route-level-use-client # required · kebab = filename stem
|
|
67
67
|
priority: P1 # required · P0|P1|P2|P3
|
|
68
|
-
|
|
68
|
+
category: architecture # required · security|correctness|performance|architecture|product|ops (pre-2026-07-26 name `lens` is a deprecated alias)
|
|
69
69
|
status: open # required · open|backlog|fixed|wontfix
|
|
70
70
|
title: Route-level "use client" silently disables RSC # required
|
|
71
71
|
summary: A route-level directive kills RSC down the whole subtree; no gate catches it # required
|
|
@@ -109,9 +109,15 @@ convention — see [RSC client boundary](/brain/rules/rsc-client-boundary.md)).
|
|
|
109
109
|
ledger speaks the repo's own language).
|
|
110
110
|
- **The big-bang guard is sovereign** (directive 1): a `Strong` candidate lands as its first
|
|
111
111
|
10-minute slice or a P2 backlog item — never a grand refactor plan.
|
|
112
|
-
3. **
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
3. **The security profile.** Run `npx @rafinery/cli audit --json` — the SELF-CONTAINED
|
|
113
|
+
engine (dep CVEs via the built-in OSV client + pnpm audit; secrets via the built-in
|
|
114
|
+
ruleset; SAST via semgrep only if present — a tier that didn't run says `ran:false`).
|
|
115
|
+
Then follow [rafa-security](../rafa-security/SKILL.md): findings → `category: security`
|
|
116
|
+
rows with the MECHANICAL priority map (critical→P0 · high→P1 · moderate→P2 ·
|
|
117
|
+
low/dev-only→P3), reachability annotated from the brain's domain map but never
|
|
118
|
+
downgraded, same-fix CVEs grouped into one row. The LLM pass (authz per route,
|
|
119
|
+
webhook verification, input validation) is observational only — never present it
|
|
120
|
+
as an authoritative audit.
|
|
115
121
|
4. **Write improvements.** One file per improvement, cited (`file:line :: token`), prioritized,
|
|
116
122
|
leverage-ranked. **Reconcile** against the existing ledger: dedup; **auto-close** improvements
|
|
117
123
|
whose code is now clean (`status: fixed`); **preserve** the dev's prior triage
|
|
@@ -119,7 +125,7 @@ convention — see [RSC client boundary](/brain/rules/rsc-client-boundary.md)).
|
|
|
119
125
|
5. **Cite-check (the fidelity gate).** Run
|
|
120
126
|
`npx @rafinery/cli verify-citations --root=.rafa/improve --dirs=improvements`. Every cite
|
|
121
127
|
must resolve; **drop or fix any that don't** — a hallucinated improvement is the cardinal sin.
|
|
122
|
-
6. **Ledger + trend.** Regenerate `ledger.md`: counts by priority/
|
|
128
|
+
6. **Ledger + trend.** Regenerate `ledger.md`: counts by priority/category/status + a **debt
|
|
123
129
|
score** (weighted open improvements) and its trend vs the last run — the compounding made
|
|
124
130
|
visible. Write the machine-read **frontmatter** `open` · `debt_score` · `by_priority`
|
|
125
131
|
([contract §5](../../rafa/contract.md)) — the platform reads that.
|
|
@@ -167,6 +173,11 @@ in that area and nudge once — *"2 P1s here, one's a 10-min fix — take it whi
|
|
|
167
173
|
ranked by leverage, **dismissible, never blocking.** Not built here; this capability produces
|
|
168
174
|
the ledger the nudge will read.
|
|
169
175
|
|
|
176
|
+
**The one exception to blast-radius scoping: `category: security` P0s.** A critical
|
|
177
|
+
CVE lives in no file the dev is touching, so a P0 security row may surface at
|
|
178
|
+
plan/build boundaries regardless of region — one line, dismissible, never blocking,
|
|
179
|
+
never re-nagged in the same session.
|
|
180
|
+
|
|
170
181
|
---
|
|
171
182
|
|
|
172
183
|
## Anti-patterns (each is a way bloom gets muted)
|
|
@@ -50,7 +50,7 @@ Conformance is our distribution wedge; verification stays the moat.
|
|
|
50
50
|
| Agent | Files | What OKF-native means for you |
|
|
51
51
|
|---|---|---|
|
|
52
52
|
| **atlas** | `brain/rules/` · `brain/playbooks/` · `brain/coverage.md` | author `type` (§2 enum) + `title` + `summary` as ever; body cross-links as markdown links; optionally author `description`/`tags` — emit derives them from `summary`/`domain` if you don't |
|
|
53
|
-
| **bloom** | `improve/improvements/` · `improve/ledger.md` | same; your files gain `type: Improvement` + `tags: [
|
|
53
|
+
| **bloom** | `improve/improvements/` · `improve/ledger.md` | same; your files gain `type: Improvement` + `tags: [category, priority]` at emit — author `found:` so timestamps are yours, not git's |
|
|
54
54
|
| **prism** | `brain/checklist.md` | verdict frontmatter as ever (emit stamps `type: Health Report` + a derived description); at validation, treat the checker's LINKS warns as a worklist — dangling links are claims of future knowledge |
|
|
55
55
|
| **sage** | `.claude/rafa/learnings/` | learnings are OKF concepts too: frontmatter + `type: Learning` + markdown links; outside the bundle but under the same protocol |
|
|
56
56
|
| **conductor / plan·build** | `plans/**` · `brain/log.md` | plan items gain `type` from `kind` at emit (per-epic `plans/index.md`); journals + bodies use markdown links; `log.md` stays the reserved trail |
|
|
@@ -23,7 +23,9 @@ Planning is a choreography, not one agent (spec: knowledge-mcp-build-agent):
|
|
|
23
23
|
the tools; the dev never asks for it. Repo not platform-connected (no `rafinery`
|
|
24
24
|
MCP in the session)? Fall back to reading `.rafa/brain/` files directly — same
|
|
25
25
|
knowledge, just unserved.*
|
|
26
|
-
- **bloom pulls** — `list_improvements` in the blast radius
|
|
26
|
+
- **bloom pulls** — `list_improvements` in the blast radius (PLUS any open
|
|
27
|
+
`category: security` P0 regardless of region — the one class that travels;
|
|
28
|
+
one line, dismissible, never blocking); surface the
|
|
27
29
|
top-leverage open items as optional *"while-you're-here"* child tasks
|
|
28
30
|
(leverage-ranked, dismissible, never blocking). **Any improvement the plan
|
|
29
31
|
ADOPTS (as a task or the plan's very subject) is hydrated NOW** —
|
|
@@ -100,6 +102,17 @@ Planning is a choreography, not one agent (spec: knowledge-mcp-build-agent):
|
|
|
100
102
|
the pivotal choices are logged as DECISIONS at approval (`log_decision`:
|
|
101
103
|
context · options · decision · rationale; actor = the dev for their calls).
|
|
102
104
|
3. **Ledger pull** (bloom) → optional leverage tasks in the blast radius.
|
|
105
|
+
3b. **Security transparency** (2026-07-26 r2 — "security is not an aftermath").
|
|
106
|
+
Run `npx @rafinery/cli audit --json` (seconds; reuse a same-session
|
|
107
|
+
`security-audit.json` if fresh) and present the picture TO THE DEV, verbatim
|
|
108
|
+
and unburied, before the plan is approved: one line of severity totals +
|
|
109
|
+
which tiers ran, then any critical/high finding whose package or file sits
|
|
110
|
+
in THIS plan's blast radius (per [rafa-security](../rafa-security/SKILL.md)'s
|
|
111
|
+
reachability method). A blast-radius critical/high → propose it as a plan
|
|
112
|
+
child task (the fix rides the work); open `category: security` P0s surface
|
|
113
|
+
regardless of region. Transparent means: the dev sees the counts even when
|
|
114
|
+
everything is clean — "dependency tier clean at <sha>" is one honest line,
|
|
115
|
+
never silence.
|
|
103
116
|
4. **Leverage-match** — recommend existing skills/tools/MCP that fit the tasks;
|
|
104
117
|
never plan to hand-roll what a capability already does.
|
|
105
118
|
5. **prism plan-validation** → REJECT/fix loop until clean.
|
|
@@ -201,6 +201,13 @@ retrieval index. Bodies read like a senior engineer explaining that one concept
|
|
|
201
201
|
6. **Flow tracing** [LLM, cited] — from each entry point, hop-by-hop to termination
|
|
202
202
|
(render / DB write / response) → `flow` playbooks. Add `how-to` playbooks for the
|
|
203
203
|
recurring "add X" procedures these flows imply.
|
|
204
|
+
**One `security-posture` playbook is required** (2026-07-26): the repo's trust
|
|
205
|
+
boundaries (what's server-exposed vs build-time), auth chokepoints (where
|
|
206
|
+
authz is enforced — cited), and the secret-handling convention (where env
|
|
207
|
+
names are read; names only, per the step-4 guardrail). This is durable
|
|
208
|
+
KNOWLEDGE, not findings — it grounds bloom's security profile
|
|
209
|
+
([rafa-security](../rafa-security/SKILL.md)): reachability annotations on
|
|
210
|
+
CVE rows come FROM this note's map.
|
|
204
211
|
|
|
205
212
|
7. **Verification & synthesis** — apply the 100× filter (a note earns a file only if it
|
|
206
213
|
answers a work-time question AND eliminates a recurring tax), then write the notes. Run
|
|
@@ -255,7 +262,8 @@ pipeline; **`--brain-only`** stops after the brain is validated (step 5 PASS)
|
|
|
255
262
|
do **not** improve or push (never improve/push an unvalidated brain).
|
|
256
263
|
6. **Improve** *(skip if `--brain-only`)* — run the improve pass ([rafa-improve](../rafa-improve/SKILL.md)):
|
|
257
264
|
spawn `bloom` → `.rafa/improve/`. It reads the *validated* brain as its index, so it only
|
|
258
|
-
runs after PASS.
|
|
265
|
+
runs after PASS. The security profile rides this step ([rafa-security](../rafa-security/SKILL.md):
|
|
266
|
+
`rafa audit --json` → category:security rows) — every scan carries it; no separate command.
|
|
259
267
|
7. **Prove it — the measured benchmark** *(skip if `--brain-only`; skip if
|
|
260
268
|
`.rafa/benchmark.json` already carries `measured: true` for this repo)* —
|
|
261
269
|
the proof engine is WORKFLOW-WOVEN, never a dev-typed command (owner
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rafa-security
|
|
3
|
+
description: "rafa SOP — the security profile: run the self-contained `rafa audit` engine (dep CVEs via OSV · secrets · SAST if present), brain-ground reachability, author category:security improvements with the mechanical priority map, emit the profile. Loaded by bloom/the conductor at profiling moments (scan's improve pass, build-time sweep) — NEVER a dev-typed verb."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# security — the profile (woven, never a command)
|
|
7
|
+
|
|
8
|
+
rafa's security posture is **woven into the loop, not a chore**: the dev never
|
|
9
|
+
types a security command. Owner doctrine (2026-07-26 r2): *"security is not an
|
|
10
|
+
aftermath — it is an integral part of the development cycle."* The engine
|
|
11
|
+
fires at every moment of that cycle:
|
|
12
|
+
|
|
13
|
+
- **plan** — the audit runs before approval and its picture is presented to
|
|
14
|
+
the dev verbatim (rafa-plan §3b): totals + blast-radius criticals; clean is
|
|
15
|
+
said out loud, never implied by silence.
|
|
16
|
+
- **build** — a task that touches the lockfile re-runs the cheap dep tier and
|
|
17
|
+
reports the delta in one line (rafa-build §2).
|
|
18
|
+
- **improve / scan** — the full three-tier profile (this SOP's procedure below).
|
|
19
|
+
- **every merge** — branch→branch merges get a platform-side dep audit at fold
|
|
20
|
+
time; canonical merges get the reconcile graph's security lane. Both mint
|
|
21
|
+
Security-tab rows — freshness at every level, not just prod.
|
|
22
|
+
|
|
23
|
+
Findings land as ordinary contract §3 improvements with `category: security`;
|
|
24
|
+
the platform's Security tab reads the merge-level rows.
|
|
25
|
+
|
|
26
|
+
## The engine — deterministic first, always
|
|
27
|
+
|
|
28
|
+
Run **`npx @rafinery/cli audit --json`** and parse the `rafa.audit/v1`
|
|
29
|
+
envelope. The engine is SELF-CONTAINED — it needs no installs, ever:
|
|
30
|
+
|
|
31
|
+
- **dependency** — built-in pnpm-lock parser + the OSV.dev advisory API,
|
|
32
|
+
merged with `pnpm audit`; per finding: package · GHSA/CVE + aliases ·
|
|
33
|
+
severity + CVSS · direct-vs-transitive chain · fixed-in · dev-only flag.
|
|
34
|
+
- **secrets** — built-in curated ruleset over tracked files (`.env*` never
|
|
35
|
+
opened; fingerprints, never secret bytes). gitleaks enhances if present.
|
|
36
|
+
- **sast** — semgrep if installed (pinned `p/security-audit`), otherwise the
|
|
37
|
+
envelope says `ran:false` with the reason. semgrep/gitleaks are OPTIONAL
|
|
38
|
+
enhancers; mention their value once when relevant (`rafa doctor` shows
|
|
39
|
+
install hints) — installing is always the dev's own consented choice.
|
|
40
|
+
**Never LLM-pretend a tier that did not run** — `tiers.<t>.ran` is the truth.
|
|
41
|
+
|
|
42
|
+
## Findings → improvements (the mechanical part)
|
|
43
|
+
|
|
44
|
+
One §3 improvement file per finding worth a row (group same-package CVEs into
|
|
45
|
+
one row when they share the fix — one lockfile bump = one improvement).
|
|
46
|
+
Required frontmatter as ever (`title` · `summary` · `fix` · `leverage` ·
|
|
47
|
+
`cites`), plus:
|
|
48
|
+
|
|
49
|
+
- `category: security` — always.
|
|
50
|
+
- **Priority maps mechanically, never by vibe**: critical → P0 · high → P1 ·
|
|
51
|
+
moderate → P2 · low or dev-only (`dev:true`) → P3. The LLM may ANNOTATE
|
|
52
|
+
(see below) but **never downgrades** a mapped priority.
|
|
53
|
+
- `fix:` carries the concrete path: the upgrade target (`fixedIn`), whether the
|
|
54
|
+
dep is direct (bump it) or transitive (dedupe/overrides/parent-bump), the
|
|
55
|
+
secret's rotation step. Comprehensive detail (chain, refs, CVSS) rides the
|
|
56
|
+
body — machine-sourced from the envelope, never re-guessed.
|
|
57
|
+
- Dependency-tier rows cite the lockfile/manifest line that pins the package;
|
|
58
|
+
secret/sast rows cite the `file:line` from the finding.
|
|
59
|
+
|
|
60
|
+
**Reconcile like any improvement**: dedupe against existing rows by the stable
|
|
61
|
+
finding id (in the body); auto-close rows whose finding vanished from a fresh
|
|
62
|
+
audit (`status: fixed` — the lockfile bump landed); preserve the dev's triage
|
|
63
|
+
(backlog/wontfix stay).
|
|
64
|
+
|
|
65
|
+
## Brain-ground the reachability (the judgment part)
|
|
66
|
+
|
|
67
|
+
The brain's domain map is what raw scanners lack. For each dependency finding,
|
|
68
|
+
answer from the brain — *is this package on a server-exposed path?* (API
|
|
69
|
+
routes, webhook handlers, auth boundary) — and write the answer into the body
|
|
70
|
+
as an annotation: `Reachability: server-exposed via <domain> — see
|
|
71
|
+
[<note>](/brain/...)` or `Reachability: build-time only`. Cited, observational,
|
|
72
|
+
and **priority-neutral** — it informs the dev's triage, it never overrides the
|
|
73
|
+
mechanical map.
|
|
74
|
+
|
|
75
|
+
The wider observational pass (authz per route, webhook verification, input
|
|
76
|
+
validation against the brain's contracts) belongs to the improve SOP's
|
|
77
|
+
security lens — cited `file:line`, labeled observational, never presented as
|
|
78
|
+
SAST output.
|
|
79
|
+
|
|
80
|
+
## The P0 exception — the one row that travels
|
|
81
|
+
|
|
82
|
+
Improvement nudges are blast-radius-scoped — EXCEPT `category: security` P0s:
|
|
83
|
+
a critical CVE lives in no file the dev is touching, so a P0 security row may
|
|
84
|
+
surface at plan/build boundaries regardless of region. Still one line, still
|
|
85
|
+
dismissible, never blocking, never re-nagged in the same session.
|
|
86
|
+
|
|
87
|
+
## Anti-patterns
|
|
88
|
+
|
|
89
|
+
- Running the engine and PARAPHRASING its output into rows without the
|
|
90
|
+
envelope's fields — the detail is machine-sourced or it doesn't ship.
|
|
91
|
+
- Downgrading a mapped priority because it "seems fine" — annotate, never
|
|
92
|
+
downgrade.
|
|
93
|
+
- A wall of per-CVE rows for one package — group by shared fix.
|
|
94
|
+
- Presenting the observational pass as scanner output.
|
|
95
|
+
- Asking the dev to install semgrep/gitleaks more than once — the doctor
|
|
96
|
+
carries the hint; a decline stands.
|