> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rule settings

> Disable rules you don't care about — globally for your account, or per repository.

Some Pipefort rules don't apply to every team. A research-only org might
intentionally skip `BEST-PRAC-2: Job timeout not configured`. A monorepo team
might want `CICD-SEC-1: Default branch does not require signed commits` muted
on prototype repos but enforced elsewhere.

The **Rule settings** page lets you turn any individual rule on or off, with
two layers:

* **Global** (per user) — applies to every repository you scan.
* **Per-repository override** — a specific repo bucks the global value
  (tri-state: inherit, enabled, or disabled).

<Note>
  Changes affect **future scans only**. Existing findings are never modified or
  deleted retroactively. After a toggle, the SPA shows a banner with a one-click
  "Re-scan" button.
</Note>

## Global toggles

Open **Rule settings** in the left sidebar (route: `/rules`). Each rule is a
row with:

* Severity badge and title (matching the rule's docs page).
* One-line description.
* Direct link to the full rule docs.
* A toggle.

Rules are grouped into two sections:

* **Workflow checks** — the 8 rules applied to `.github/workflows/*.yml`.
* **Repository configuration checks** — the 17 rules applied to GitHub-side
  settings (branch protection, Actions permissions, secret scanning, …).

Toggling a rule off disables it for every repo you scan. The change persists
to a `rule_settings` row in Postgres with `repository_id = NULL`.

## Per-repository overrides

On any repository detail page (`/repositories/:id`), the **Rule overrides**
card lets you override the global value for that repo:

* **Inherit** — the global setting wins for this repo (no row written).
* **Enabled** — force-enable the rule for this repo, even if it's globally
  disabled.
* **Disabled** — force-disable the rule for this repo.

Switching back to **Inherit** deletes the override row.

By default the card only shows rules that already have an override. Click
**Show all rules** to see every rule alongside its inherited value (rendered
as muted "Inheriting global: enabled/disabled" text).

## How filtering happens

Filtering runs **at scan time, before persistence**. When the API resolves a
scan, it loads `(global, override)` rows for `(user, repo)`, merges them
(override wins), and drops findings whose rule is disabled — before writing
to the `findings` table or the `scans.counts` rollup. As a result:

* Severity tiles, trend charts, and the per-repo finding list are all
  consistent — they read the same filtered `findings` rows.
* Old scans are unaffected. A finding logged before you disabled a rule stays
  in your scan history.

This composes with the existing `--ruleset` choice (`all` vs `owasp`): the
per-rule filter runs first, then the ruleset filter. You can disable a
`CICD-SEC-*` rule globally and still pick `owasp` — the rule stays disabled.

## What if a new rule ships?

New rules are default-enabled for every user. There's no row in
`rule_settings` for them yet, so the lookup yields "enabled". Open
`/rules` to disable any you don't want.

## Caveats

* Rule IDs are stable. The doc slugs under `/rules/<id>` are the canonical
  identifiers and are unlikely to change.
* This is a **web-app-only feature**. The CLI still uses `--ruleset all|owasp`
  for filtering — per-user preferences depend on the database (see
  [CLAUDE.md's web-only exception](/architecture)).
* `SYSTEM` / `INFO` notices (parse errors, "settings audit skipped" notices,
  rule-settings load failures) are never toggleable — they always pass.

## Related

<CardGroup cols={2}>
  <Card title="Rules overview" icon="list" href="/rules/overview">
    The full catalog of checks across both surfaces.
  </Card>

  <Card title="API reference" icon="code" href="/webapp/api-reference">
    Programmatic access to the rule-settings endpoints.
  </Card>
</CardGroup>
