diff --git a/.gitignore b/.gitignore index e1a0ecd..40c46f2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,13 @@ .roughcollie.toml testcases/c2j/ogagila/ +testcases/c2j/ogagila-web/ # 本地产物 / 工具会话数据(不应入库) .sisyphus/ testcases/a.csv +testcases/audit_manifest.csv +testcases/VERIFICATION.md # 本地验证配置(每人本机路径不同,各自维护) testcases/c2j_ogagila.toml diff --git a/.roughcollie.toml.example b/.roughcollie.toml.example index af759c2..77cd2f9 100644 --- a/.roughcollie.toml.example +++ b/.roughcollie.toml.example @@ -32,12 +32,20 @@ project_type = "gaussdb-sql" baseline = "main" git_repo = "." database = "gaussdb-prod" +# exclude: glob 模式相对于 git_repo,匹配的文件不进入审核管道 +exclude = [ + "**/test/**", # 测试目录 + "**/migrations/**", # 数据库迁移脚本 +] [projects.payment-service] project_type = "java" baseline = "dev" git_repo = "." database = "gaussdb-prod" +exclude = [ + "**/entity/**", # JPA 实体类(纯 POJO,无 SQL 注入面) +] # === 全局配置 === diff --git a/Cargo.lock b/Cargo.lock index 8447ed0..3d08091 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -767,7 +767,7 @@ dependencies = [ [[package]] name = "cr-audit-complexity" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-core", "ogsql-complexity", @@ -775,7 +775,7 @@ dependencies = [ [[package]] name = "cr-audit-explain" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-core", "ogexplain-core", @@ -784,7 +784,7 @@ dependencies = [ [[package]] name = "cr-audit-impact" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-core", "serde", @@ -797,7 +797,7 @@ dependencies = [ [[package]] name = "cr-audit-static" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-core", "dirs 5.0.1", @@ -815,7 +815,7 @@ dependencies = [ [[package]] name = "cr-cli" -version = "0.2.6" +version = "0.2.8" dependencies = [ "clap", "cr-audit-complexity", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "cr-config" -version = "0.2.6" +version = "0.2.8" dependencies = [ "csv", "serde", @@ -851,7 +851,7 @@ dependencies = [ [[package]] name = "cr-core" -version = "0.2.6" +version = "0.2.8" dependencies = [ "async-trait", "regex", @@ -863,7 +863,7 @@ dependencies = [ [[package]] name = "cr-db" -version = "0.2.6" +version = "0.2.8" dependencies = [ "async-trait", "cr-core", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "cr-git" -version = "0.2.6" +version = "0.2.8" dependencies = [ "ignore", "tempfile", @@ -887,7 +887,7 @@ dependencies = [ [[package]] name = "cr-mcp-server" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-audit-complexity", "cr-audit-static", @@ -903,7 +903,7 @@ dependencies = [ [[package]] name = "cr-plugin" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-core", "libc", @@ -914,7 +914,7 @@ dependencies = [ [[package]] name = "cr-report" -version = "0.2.6" +version = "0.2.8" dependencies = [ "cr-core", "serde", @@ -924,7 +924,7 @@ dependencies = [ [[package]] name = "cr-server" -version = "0.2.6" +version = "0.2.8" dependencies = [ "axum", "chrono", @@ -2511,7 +2511,7 @@ dependencies = [ [[package]] name = "ogexplain-core" -version = "0.2.6" +version = "0.2.8" dependencies = [ "insta", "ogsql-parser", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "ogsql-complexity" -version = "0.2.6" +version = "0.2.8" dependencies = [ "insta", "ogsql-parser", diff --git a/Cargo.toml b/Cargo.toml index 65ec9d6..b0aecfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ members = [ edition = "2021" rust-version = "1.75" license = "MIT OR Apache-2.0" -version = "0.2.6" +version = "0.2.8" [workspace.dependencies] # 内部 crate 间依赖 diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7e4bc16..3088669 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -126,6 +126,85 @@ format = "markdown" # markdown / json / sarif path = "./audit-report.md" exit_code_on_critical = 1 # Critical 时退出码非 0 exit_code_on_warning = 0 # Warning 时退出码 0(仅报告) + +[output.filter] +# 可选:按 rule_id / severity / category 保留或筛除审核结果(详见下方说明) +severity = "includes:critical,warning" +rule_id = "excludes:COMPLEX-*" +category = "excludes:parse-error" +``` + +### 文件排除与结果过滤 + +CodeRoughcollie 提供两个独立层次的过滤机制,作用阶段和效果不同: + +#### 项目级文件排除 `[projects.*].exclude` + +在文件进入审核管道**之前**按 glob 模式排除。模式相对于项目的 `git_repo` 目录。 + +```toml +[projects.my-sql-project] +git_repo = "." +project_type = "gaussdb-sql" +exclude = [ + "**/test/**", # 排除测试目录 + "**/*_test.sql", # 排除测试 SQL + "**/migrations/**", # 排除数据库迁移脚本 +] +``` + +不同 CLI 模式下被排除文件的处理方式: + +| 模式 | 被排除文件的处理 | +|------|-----------------| +| `--baseline`(默认) | 静默丢弃,不出现在报告中 | +| `--dir` | 静默丢弃,不出现在报告中 | +| `--files` | 标记为 ⏭️ Ignored,在报告中列出但不审核 | +| `--manifest` | 标记为 ⏭️ Ignored,在报告中列出但不审核 | + +> `--files` 和 `--manifest` 模式下保留可见性是因为用户显式指定了这些文件,需要告知"你指定了它,但配置排除了它"。 + +#### 审核结果过滤 `[output.filter]` + +在审核完成**之后**、报告输出之前,对 Finding 做保留或筛除。规则照跑、文件照扫,只决定哪些结果出现在最终报告里。 + +三个维度,彼此是 AND 关系: + +| 字段 | 说明 | 通配符 | 合法值示例 | +|------|------|:---:|---------| +| `rule_id` | 按规则 ID 过滤 | `*` | `excludes:SCAN-001,TYPE-*` | +| `severity` | 按严重度过滤 | — | `includes:critical,warning` | +| `category` | 按诊断分类过滤 | — | `excludes:parse-error` | + +每个字段格式为 `{mode}:{value1},{value2},...`: + +- `includes` — 白名单:仅保留匹配项 +- `excludes` — 黑名单:排除匹配项 + +`severity` 取值:`critical` / `warning` / `info` + +`category` 取值(kebab-case): + +| 分类 | 说明 | 对应规则前缀 | +|------|------|-------------| +| `scan-efficiency` | 扫描效率 | SCAN-* | +| `join-strategy` | 连接策略 | JOIN-* | +| `memory-usage` | 内存使用 | MEM-* | +| `sort-efficiency` | 排序效率 | SORT-* | +| `type-mismatch` | 类型不匹配 | TYPE-* | +| `subquery-structure` | 子查询结构 | SUBQ-* / REW-* | +| `parse-error` | 词法/语法错误 | PARSE-* / VAL-SYNTAX-* | +| `validation-semantic` | 语义校验 | VAL-PKG-* / VAL-PL-* | +| `general` | 通用 | GEN-* / ANTI-* / AGG-* | + +#### 过滤层次总结 + +``` +文件发现 审核管道 报告输出 + │ │ │ + ▼ ▼ ▼ +[projects.*].exclude → 规则匹配 → [output.filter] → 最终报告 + 排除整个文件 产出 Finding 筛除部分 Finding ``` ## 命令行接口