You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -85,7 +85,7 @@ Two separate Node.js processes:
85
85
**Scanners (`src/adapters/`):**
86
86
-`semgrep.js` — runs `semgrep scan --config auto --json`; exit code 1 = findings found (not an error); maps ERROR→high, WARNING→medium, INFO→low
87
87
-`trufflehog.js` — runs `trufflehog filesystem --json --no-update`; exit code 183 = secrets found (not an error); batched at 200 files to stay under ARG_MAX; all findings are severity `high`
88
-
-`claude.js` — calls the Anthropic API to detect malicious intent; **disabled by default**, opt in per repo; skips binary files; caps files at 50 KB; batches at 100 KB per API call; errors are caught and logged without failing the scan. Supports two modes (configured per-repo in `repos.json`):
88
+
-`claude.js` — calls the Anthropic API to detect malicious intent; **disabled by default**, opt in per repo; skips binary files; caps files at 50 KB; batches at 100 KB per API call; errors are caught and logged without failing the scan. Supports two modes (configured per-repo in `config/layne.json`):
89
89
-**Prompt mode** (default): single `messages.create` call with a system prompt; use `claude.prompt` to override
90
90
-**Skill mode**: uses the Anthropic [API Skills beta](https://platform.claude.com/docs/en/build-with-claude/skills-guide) — adds a `code_execution` tool + an uploaded skill to each batch call, enabling runtime decoding, registry lookups, and richer static analysis; set `claude.skill: { id, version }` to enable; handles `pause_turn` continuations automatically (up to 10 turns per batch)
Copy file name to clipboardExpand all lines: docs/configuration.md
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -107,7 +107,9 @@ Uses the [Anthropic API Skills beta](https://platform.claude.com/docs/en/build-w
107
107
|`id`| string | — | Skill ID from the Anthropic Skills API (format: `skill_01...`) |
108
108
|`version`| string |`"latest"`| Skill version to use. Pin to a timestamp for reproducible behaviour |
109
109
110
-
> **Beta — expect breaking changes.** API Skills are in active development. The beta headers (`skills-2025-10-02`, `code-execution-2025-08-25`) may be superseded by Anthropic; when that happens, Layne will need to be updated to use the new headers before skill mode works again. Skill IDs (`skill_01...`) are opaque, tied to your Anthropic account, and are not portable — if Anthropic changes the Skills API in a way that invalidates existing uploads, you will need to re-upload your skill and update the `id` in `repos.json`. Skills are not ZDR-eligible. Use `claude-sonnet-4-6` or above — smaller models may not make effective use of code execution.
110
+
> **Beta — expect breaking changes.** API Skills are in active development. The beta headers (`skills-2025-10-02`, `code-execution-2025-08-25`) may be superseded by Anthropic; when that happens, Layne will need to be updated to use the new headers before skill mode works again. Skill IDs (`skill_01...`) are opaque, tied to your Anthropic account, and are not portable — if Anthropic changes the Skills API in a way that invalidates existing uploads, you will need to re-upload your skill and update the `id` in `config/layne.json`.
111
+
>
112
+
> **Skills are not ZDR-eligible.** ZDR (Zero Data Retention) is an Anthropic compliance feature that guarantees prompts and outputs are not retained after the API call. Skills require data retention to function, so they cannot be used with ZDR-enabled Anthropic organizations. Use `claude-sonnet-4-6` or above — smaller models may not make effective use of code execution.
111
113
112
114
**Uploading a skill:** Skills are managed outside of Layne. To upload one:
113
115
```python
@@ -483,7 +485,7 @@ Sends a POST request to a Rocket.Chat incoming webhook URL.
483
485
|`webhookUrl`| string | yes | Webhook URL, or an env var reference like `"$ROCKETCHAT_WEBHOOK_URL"`|
484
486
|`template`| string | no | Custom message template (see below). Omit for the default format |
485
487
486
-
**`webhookUrl` — keeping secrets out of `repos.json`:**
488
+
**`webhookUrl` — keeping secrets out of `config/layne.json`:**
487
489
488
490
If the value starts with `$`, Layne treats the rest as an environment variable name and reads it at runtime. This way your webhook URL never needs to be committed to the repository.
489
491
@@ -540,7 +542,7 @@ Sends a POST request to a Slack incoming webhook URL.
540
542
541
543
Create a Slack app, enable Incoming Webhooks, and add a webhook for your channel. Copy the resulting `https://hooks.slack.com/services/...` URL.
542
544
543
-
**`webhookUrl` — keeping secrets out of `repos.json`:**
545
+
**`webhookUrl` — keeping secrets out of `config/layne.json`:**
544
546
545
547
Same `$ENV_VAR` resolution as Rocket.Chat — if the value starts with `$`, Layne reads it from the environment at runtime.
| `file` | `string` | Path relative to the repo root (strip `workspacePath +'/'`) |
69
69
| `line` | `number` | Line number for the annotation (use `1` if unavailable) |
70
-
| `severity` | `'critical' \|'high' \|'medium' \|'low'` | Controls annotation styling in the GitHub UI |
70
+
| `severity` | `'critical' \|'high' \|'medium' \|'low' \|'info'` | Controls annotation styling and whether the check fails |
71
71
| `message` | `string` | Body text of the inline annotation |
72
72
| `ruleId` | `string` | Stable identifier used to deduplicate or suppress findings |
73
73
| `tool` | `string` | Name shown in the check run summary |
@@ -110,56 +110,77 @@ Pin the version so builds are reproducible. Pass `--build-arg MYTOOL_VERSION=x.y
110
110
111
111
---
112
112
113
-
## Adding a New Notification Provider
113
+
## How Findings Become GitHub Annotations
114
114
115
-
Notifications are **modular**: each provider is an independent file in `src/notifiers/`. Adding a new provider (e.g. PagerDuty) requires three steps and no changes to core scan logic.
115
+
Adapters return findings — they don't call the reporter directly. Understanding this flow helps when debugging or adding new scanners:
Create `src/notifiers/pagerduty.js` exporting a `notify` function. The function must **never throw** — catch all errors internally so a notification failure never affects the scan result.
143
+
**What the dispatcher does:**
120
144
121
-
```js
122
-
// src/notifiers/pagerduty.js
145
+
1. Runs all scanners in parallel via `Promise.all`
The overall Check Run conclusion determines whether GitHub shows a green check or red ✗:
168
+
169
+
| Condition | Conclusion |
170
+
|---|---|
171
+
| One or more `critical` / `high` findings | `failure` |
172
+
| No blocking findings | `success` |
173
+
174
+
When branch protection requires the Layne check, `failure` blocks the PR from merging.
160
175
161
-
The notifier key (`pagerduty`) is what operators use in `config/layne.json` under `notifications`.
176
+
### Annotation summary
177
+
178
+
The reporter generates a human-readable summary line shown in the Check Run header:
179
+
180
+
```
181
+
Found 3issue(s):0 critical, 1 high, 1 medium, 1 low.
182
+
```
162
183
163
-
### 3. Write tests
184
+
### Annotation chunking
164
185
165
-
Create `src/__tests__/notifiers/pagerduty.test.js` following the same pattern as the Rocket.Chat or Slack test files. Use `vi.stubGlobal('fetch', vi.fn())`to mock HTTP calls.
186
+
GitHub's API limits Check Runs to 50 annotations per request. The reporter batches automatically — adapters don't need to worry about this limit. The worker posts chunked requests to GitHub, with the final request setting `status: completed`.
For how findings are converted to GitHub annotations and how severities affect PR status, see [Extending Layne — How Findings Become GitHub Annotations](extending.md#how-findings-become-github-annotations).
Copy file name to clipboardExpand all lines: docs/security-architecture.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,7 +41,7 @@ Used only when a repo has `claude.enabled: true`. The key is passed directly to
41
41
42
42
### Notification webhook URLs (`webhookUrl`)
43
43
44
-
Rocket.Chat webhook URLs can be stored as environment variable references (e.g. `"$ROCKETCHAT_WEBHOOK_URL"`) in `repos.json` rather than as plaintext values. Layne resolves them at runtime from `process.env`. This keeps secrets out of the repository.
44
+
Rocket.Chat webhook URLs can be stored as environment variable references (e.g. `"$ROCKETCHAT_WEBHOOK_URL"`) in `config/layne.json` rather than as plaintext values. Layne resolves them at runtime from `process.env`. This keeps secrets out of the repository.
0 commit comments