Skip to content
Back to skills

Bl Capabilities

ASecurity

**Always load at session start.** This file is the curator's enforcement reference for every verb, tier, gate, and schema constraint that the `bl` wrapper exposes. Read this before proposing any step or tier classification to the operator. Reference source: `src/bl.d/` part files. Schema source: `schemas/step.json`, `schemas/ledger-event.json`. Gate behavior source: `DESIGN.md §6`. Read order: load `/skills/foundations.md` (ir-playbook lifecycle rules) alongside this file. They are complement...

  • 14 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 26, 2026
toolsrustshellbashapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add rfxn/blacklight --skill bl-capabilities --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bl Capabilities?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Bl Capabilities
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rfxn-bl-capabilities/badge)](https://www.skillsdirectory.com/skills/rfxn-bl-capabilities)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# bl-capabilities — Wrapper Capability Map

**Always load at session start.** This file is the curator's enforcement reference
for every verb, tier, gate, and schema constraint that the `bl` wrapper exposes.
Read this before proposing any step or tier classification to the operator.

Reference source: `src/bl.d/` part files. Schema source: `schemas/step.json`,
`schemas/ledger-event.json`. Gate behavior source: `DESIGN.md §6`.

Read order: load `/skills/foundations.md` (ir-playbook lifecycle rules) alongside
this file. They are complementary — this file covers the wrapper surface; foundations
covers the case reasoning rules.

---

## 1. Verb index

Nine verbs. Every curator-prescribed step must use one of the `verb` enum values in
`schemas/step.json`. The wrapper's `90-main.sh` routes dispatches these verbs.

| Verb | Sub-verbs / flags | Primary purpose |
|---|---|---|
| `observe` | file, log_apache, log_modsec, log_journal, cron, proc, htaccess, fs_mtime_cluster, fs_mtime_since, firewall, sigs | Read-only evidence extraction; no host mutation |
| `consult` | (new, continue, show, log, list) | Manage curator session lifecycle |
| `run` | `--batch`, `--yes`, `--yes-auto-tier`, `--unsafe` | Execute a pending step by step_id |
| `defend` | modsec, modsec_remove, firewall, sig | Apply or remove a defensive artifact |
| `clean` | htaccess, cron, proc, file | Remediate a malicious or suspicious artifact |
| `case` | new, show, log, list, close, reopen | Case lifecycle management |
| `setup` | --sync, --reset, --gc, --eval, --check, --install-hook lmd, --import-from-lmd | Workspace bootstrap + agent provisioning |
| `flush` | outbox, (target) | Drain the outbox queue |
| `trigger` | lmd | Open a case from a hook-fired event source |

---

## 2. Action tiers

Every step carries an `action_tier` field (`auto`, `suggested`, `destructive`).
The wrapper enforces gate behavior from this field plus the verb class — tier trust
does not come from the agent alone.

| Tier | Gate behavior | Can run unattended? |
|---|---|---|
| **read-only** | Auto-execute; no confirm; standard ledger entry | Yes |
| **auto** (reversible, low-risk) | Auto-execute + operator notify (Slack/stdout) + 15-min veto window | Yes, unless verb=defend.modsec (see §4) |
| **suggested** (reversible, high-impact) | Operator reviews diff + explicit `bl run --yes` required | No (queued, notify dispatched) |
| **destructive** | Diff shown or capture-then-kill; explicit `--yes` per-operation; no batch confirm; backup before apply | No (queued, notify dispatched) |
| **unknown** | Deny by default; operator must invoke `bl run <step-id> --unsafe --yes` | No |

**Non-obvious rule — verb class overrides tier:** `defend.modsec` is always
`suggested` regardless of what the agent writes in `action_tier`. The wrapper
enforces `apachectl configtest` pre-flight before any `defend.modsec` apply.
The agent cannot bypass this by writing `action_tier: auto`.

---

## 3. Schema-enumerated verb forms (step.json)

The `verb` field in `bl-case/pending/<step-id>.json` must be one of these values
exactly. Unknown values route to the `unknown` tier and are denied.

```
observe.file              observe.log_apache         observe.log_modsec
observe.log_journal       observe.cron               observe.proc
observe.htaccess          observe.fs_mtime_cluster   observe.fs_mtime_since
observe.firewall          observe.sigs
defend.modsec             defend.modsec_remove       defend.firewall          defend.sig
clean.htaccess            clean.cron                 clean.proc               clean.file
case.close                case.reopen
trigger.lmd               setup.install_hook         setup.import_from_lmd
```

**Authoring discipline:** the verb string in the step must match the schema
enum exactly (dot separator; no spaces; lowercase). A mismatch causes
`schema_reject` in the ledger and the step is not executed.

---

## 4. Unattended-mode policy (M14 G5)

When `BL_UNATTENDED_FLAG=1` or `unattended_mode="1"` in `blacklight.conf`,
the wrapper applies the following tier policy:

| Tier | Unattended behavior |
|---|---|
| read-only | Auto-execute (same as interactive) |
| auto | Auto-execute iff `verb != defend.modsec` |
| auto + defend.modsec | **Queue, do not execute.** Notify dispatched. |
| suggested | Queue + notify operator. Step waits for `bl run --yes`. |
| destructive | Queue + notify operator. Step waits for `bl run --yes`. |
| unknown | Deny. No queue. Ledger entry `unknown_tier_deny`. |

`bl trigger lmd` sets `BL_UNATTENDED_FLAG=1` when invoked from the
`/etc/blacklight/hooks/bl-lmd-hook` adapter. All cases opened via the LMD
hook are unattended by design — the curator must not emit `defend.modsec` or
`destructive` steps expecting immediate execution.

---

## 5. Exit codes

| Code | Constant | Meaning |
|---|---|---|
| 0 | `BL_EX_OK` | Success |
| 64 | `BL_EX_USAGE` | Bad arguments / unknown verb |
| 65 | `BL_EX_PREFLIGHT_FAIL` | Preflight check failed (jq/curl/key missing; mktemp fail) |
| 66 | `BL_EX_WORKSPACE_NOT_SEEDED` | `bl setup --sync` has not been run |
| 67 | `BL_EX_SCHEMA_VALIDATION_FAIL` | Step or result failed JSON schema validation |
| 68 | `BL_EX_TIER_GATE_DENIED` | Operator declined a prompted step |
| 69 | `BL_EX_UPSTREAM_ERROR` | API exhausted 5xx retries |
| 70 | `BL_EX_RATE_LIMITED` | API exhausted 429 retries |
| 71 | `BL_EX_CONFLICT` | Case allocator collision after retries; fence collision |
| 72 | `BL_EX_NOT_FOUND` | Referenced step_id or resource not found |

**Non-obvious:** exit code 68 (`BL_EX_TIER_GATE_DENIED`) fires when the
*operator* declines a prompted step, not when the tier gate prevents
execution from an automated caller. When `BL_UNATTENDED_FLAG=1` and a
destructive step is queued rather than executed, the return code is still
`0` (step queued successfully). The operator's subsequent `bl run --yes`
or decline produces 68 on decline.

---

## 6. Ledger event kinds (ledger-event.json)

The `kind` field in ledger events must match the schema enum. Key events:

**Case lifecycle:** `case_opened`, `case_attached`, `case_closed`, `case_reopened`

**Gate events:** `schema_reject`, `unknown_tier_deny`, `preflight_fail`,
`operator_decline`, `fence_collision_deny`, `result_schema_reject`

**Step execution:** `step_run`, `clean_apply`, `clean_undo`, `clean_unquarantine`,
`defend_applied`, `defend_rollback`, `defend_refused`, `defend_sig_rejected`

**Outbox:** `outbox_drain`, `outbox_retry`, `outbox_quarantine`, `backpressure_reject`

**Trigger + notify:** `lmd_hook_received`, `trigger_dedup_attached`, `lmd_hit_degraded`,
`notify_dispatched`, `notify_failed`

**cPanel Stage 4:** `cpanel_lockin_invoked`, `cpanel_lockin_failed`,
`cpanel_lockin_rolled_back`

---

## 7. Consult dedup / fingerprint contract

`bl consult --dedup yes --fingerprint <hex16> --dedup-window-hours <N>` prevents
duplicate case opening within the dedup window. The fingerprint must be 16
lowercase hex characters.

For LMD-triggered cases, the fingerprint is:
```
sha256("<scanid>|<sorted-sigs>|<sorted-paths>")[:16]
```

Two bl trigger lmd calls with identical fingerprints within the dedup window
produce `trigger_dedup_attached` in the ledger and return the existing case_id
rather than opening a new case. This is expected behavior — the curator should
continue the existing case, not start fresh.

---

## 8. Setup verb surface

`bl setup` bypasses `bl_preflight` — it carries its own checks (ANTHROPIC_API_KEY,
curl, jq, state-dir). It does not require an existing agent session to run.

| Sub-command | What it does |
|---|---|
| `--sync` | Provision agent + upload Skills + seed Files (idempotent) |
| `--reset [--force]` | Delete agent + Skills + workspace Files |
| `--gc` | Delete Files marked `files_pending_deletion` |
| `--eval [--promote]` | Live promotion eval against the 50-case fixture set |
| `--check` | Print `state.json` snapshot |
| `--install-hook lmd` | Install bl-lmd-hook adapter; write `conf.maldet` post_scan_hook stanza |
| `--import-from-lmd` | Import existing LMD quarantine/session data as bootstrap evidence |

`setup.install_hook` and `setup.import_from_lmd` are schema-enumerated verb
forms (step.json) — they can be prescribed by the agent in a pending step.

---

## 9. What bl explicitly cannot do

The following actions are outside bl's verb surface. Curator must not propose them.

- **Execute arbitrary shell commands.** The only execution path is a named
  `bl run <step-id>` with a step whose verb maps to a known schema enum. There
  is no `exec`, `shell`, `bash`, or `script` verb. Unknown verbs route to the
  `unknown` tier and are denied unless the operator explicitly passes `--unsafe --yes`.

- **Re-implement defensive primitives.** `bl` directs `apachectl`, `apf`, `csf`,
  `iptables`, `nftables`, `maldet`, `clamscan`, `yara` — it does not replace them.
  If a primitive is absent, the relevant defend verb will fail pre-flight; bl does
  not install primitives as a side effect.

- **Quarantine LMD hits a second time.** LMD runs its own quarantine at scan time.
  When a case is opened via `bl trigger lmd`, LMD has already isolated the flagged
  files. `bl` does not re-quarantine them. See
  `/skills/lmd-triggers/quarantine-vs-cleanup.md` for the discipline.

- **Access non-case memory stores.** The wrapper can read and write `bl-case/`
  (the `read_write` memory store). It cannot directly read the Skills or corpus
  Files — those are mounted by the Anthropic session layer, not accessible to the
  wrapper at the bash level.

- **Mutate running sessions.** The curator's session is the Managed Agent session.
  `bl` sends messages to the session and reads responses. It cannot modify session
  metadata, skill bindings, or file resources via the wrapper's verb surface.

- **Delete evidence files.** Evidence bundles uploaded via the Files API are
  permanent during a case's active lifecycle. `bl setup --gc` deletes files marked
  `files_pending_deletion` only — it does not accept arbitrary file_ids.

---

## §5 Pointers

- `/skills/foundations.md` — ir-playbook lifecycle and adversarial-content rules
- `/skills/prescribing-defensive-payloads-corpus.md` — payload authoring grammar
- `/skills/curating-cases-corpus.md` — case lifecycle state machine

Files in this skill

  • SKILL.md10.1 KB
  • description.txt986 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.