Metadata-Version: 2.4
Name: cfgdrift
Version: 0.17.0
Summary: Semantic-level configuration drift detection system (JSON/TOML/INI parsed in C or pure Python, YAML via PyYAML)
Author-email: Zhiyu Dong <dongzhiyu0402@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/Dongzhiyu0402/cfgdrift
Project-URL: Repository, https://github.com/Dongzhiyu0402/cfgdrift
Project-URL: Documentation, https://dongzhiyu0402.github.io/cfgdrift/
Keywords: config,drift,detection,semantic,diff
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: C
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.1
Requires-Dist: PyYAML>=6.0
Requires-Dist: tomli>=2.0; python_version < "3.11"
Provides-Extra: web
Requires-Dist: fastapi>=0.110; extra == "web"
Requires-Dist: uvicorn>=0.27; extra == "web"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: fastapi>=0.110; extra == "dev"
Requires-Dist: uvicorn>=0.27; extra == "dev"
Requires-Dist: httpx>=0.24; extra == "dev"
Requires-Dist: httpx2>=2.0; python_version >= "3.10" and extra == "dev"
Dynamic: license-file

# cfgdrift — 语义级配置漂移检测系统

**简体中文** | [English](./README.en.md)

[![CI](https://img.shields.io/github/actions/workflow/status/Dongzhiyu0402/cfgdrift/ci.yml?branch=main&label=CI)](https://github.com/Dongzhiyu0402/cfgdrift/actions/workflows/ci.yml)
[![PyPI version](https://img.shields.io/pypi/v/cfgdrift.svg)](https://pypi.org/project/cfgdrift/)
[![PyPI downloads](https://img.shields.io/pypi/dm/cfgdrift.svg)](https://pypi.org/project/cfgdrift/)
[![License](https://img.shields.io/github/license/Dongzhiyu0402/cfgdrift.svg)](https://github.com/Dongzhiyu0402/cfgdrift/blob/main/LICENSE)
[![Python versions](https://img.shields.io/pypi/pyversions/cfgdrift.svg)](https://pypi.org/project/cfgdrift/)
[![Stars](https://img.shields.io/github/stars/Dongzhiyu0402/cfgdrift.svg?style=social&label=Stars)](https://github.com/Dongzhiyu0402/cfgdrift)

`cfgdrift` 是语义级（semantic-level）配置漂移检测工具：解析 JSON / YAML / TOML / INI 为结构化语义树，忽略注释 / 缩进 / 键序等格式噪音，只报告配置「含义」的真实变化。适合配置变更审计、安全合规检查、CI 门禁与日常运维巡检。

## ✨ 亮点

- **精准检测**：检出新增 / 删除 / 修改 / 类型变化 / **重排**五类漂移，按 CRITICAL / WARN / INFO 分级，误报趋近于零
- **闭环可操作**：采集 → 解析 → 基线 → 比对 → 报告一条命令打通；基线版本化 + 回滚，SQLite 历史可追溯
- **无人值守**：daemon 周期扫描，检出漂移触发 webhook / 邮件 / 脚本 / Slack / Teams / PagerDuty 六通道告警（规则级重试可配），支持开机自启（systemd / launchd / schtasks）
- **工程友好**：退出码 0/1/2 契约可直接接入 CI/CD；JSON / 单文件离线 HTML 报告；本地 Web 仪表盘
- **可扩展**：插件化解析器接口（entry point `cfgdrift.parsers` + 装饰器注册），支持任意自定义格式
- **随处可装**：C 核心解析 + 纯 Python 兜底，任意 Python 3.8+ 免编译器安装，跨平台

## 特性速览

| 能力 | 一句话说明 | 详见 |
|------|-----------|------|
| 语义 diff + 严重度 | 五类漂移 × CRITICAL/WARN/INFO | [语义 diff 与严重度](#语义-diff-与严重度) |
| 一致性约束 | 五类约束叠加 diff，升级 + 关联判定 | [一致性约束](#一致性约束与约束挖掘) |
| daemon + 告警 | 周期扫描、三通道、重试 / 静默 / 开机自启 | [daemon 与告警](#daemon-与告警) |
| 自愈闭环 | remediate 键级回滚 + 修复建议 hint | [自愈闭环](#自愈闭环remediate--hint) |
| Web 仪表盘 | 10 视图：时间线 / 环境对比 / 自愈审计… | [Web 仪表盘](#web-仪表盘10-视图) |
| corpus + kappa | git 历史挖掘 + 双人标注一致性 | [corpus 基准语料 + kappa](#corpus-基准语料--kappa) |
| 敏感脱敏 | 13 类敏感键五出口打码 | [敏感值脱敏](#敏感值脱敏) |
| 插件 | `--format` 自定义解析格式 | [自定义解析器插件](#自定义解析器插件) |
| 云/部署态采集 | `--source k8s` 采集 K8s ConfigMap（v0.14.0） | [云/部署态采集](#云部署态采集v0140) |
| 原生告警通道 | Slack / Teams / PagerDuty 原生通道（v0.15.0） | [原生告警通道](#原生告警通道v0150) |
| 列表重排检测 | LCS 序列匹配，纯重排报 INFO `reordered` 而非多处误报（v0.16.0） | [列表重排检测](#列表重排检测v0160) |
| Web 认证 | 可选 Bearer token 保护全部 `/api/*`，未配置时零噪音（v0.17.0） | [Web 认证](#web-认证v0170) |
| 双 wheel / C 加速 | 纯 Python 兜底 + CPython3.13 加速 | [安装](#安装) |

## 安装

```bash
pip install cfgdrift            # 通用安装（pip 自动选件）
pip install "cfgdrift[web]"     # 含 Web 仪表盘
pip install "cfgdrift[dev]"     # 含测试依赖
```

- Python 3.8+ 免编译器；C 扩展为可选加速器，未编译或安装失败自动降级纯 Python。
- 双 wheel 模型 / 本地构建配方 / 环境变量表 / 双模式一致性差异：见 [安装文档](./docs-site/installation.html)。

## 快速上手

```bash
cfgdrift init
cfgdrift scan ./config --save-as-baseline prod
# …修改配置…
cfgdrift diff ./config --baseline prod          # 退出码 1 = 有漂移
cfgdrift serve                                   # 打开 http://127.0.0.1:8080
```

## 云/部署态采集（v0.14.0）

`--source`（别名 `--adapter`）把采集来源从本地文件扩展为部署态真实配置。首发 `k8s` 采集器通过只读 `kubectl` 子进程（零 SDK 依赖）抓取 ConfigMap 的 `data` 条目，接入现有解析 / diff / 脱敏 / 约束 / hint 全链路：

```bash
cfgdrift baseline create prod --source k8s --namespace prod   # 存部署态基线
cfgdrift scan --source k8s --baseline prod                     # 比对部署态当前 vs 基线
cfgdrift daemon start --source k8s --baseline prod             # 周期巡检部署态漂移
```

- 过滤：`--namespace a,b`（逐命名空间采集）、`--label-selector app=gateway`（透传 `kubectl -l`）
- 来源标注：非 local 漂移项在终端 / `--json` / 告警 payload 均带 `source`（`k8s/<ns>/<name>/<key>` 伪路径，`line` 恒为 null）
- 降级清晰：kubectl 缺失 / 集群不可达 → 可读错误退出码 2；空结果 → 空报告退出码 0（D6 守卫防误报）
- 默认 `--source local` 行为与 v0.13.0 逐字节一致（零噪音契约）
- 扩展点：`COLLECTORS` 注册表挂一项即新增来源（AWS SSM 等后续版本）

## 原生告警通道（v0.15.0）

漂移告警从「webhook / 邮件 / 脚本」三通道升级为**六通道**——新增 **Slack**（Incoming Webhook）、**Microsoft Teams**（Workflow Webhook 卡片）与 **PagerDuty**（Events API v2）三个原生通道。每个通道一个专用渲染器 + 纯 HTTP POST 发送器（标准库 `urllib.request`，零新增依赖），**完全复用**既有 Channel 基类与调度链（规则级重试 / 10 分钟防抖 / 事件落库 / 审计全部白拿）：

```bash
cfgdrift alert add --name ops-slack --type slack --severity WARN \
    --webhook-url https://hooks.slack.com/services/T.../B.../xxx
cfgdrift alert add --name ops-teams --type teams --severity WARN \
    --webhook-url https://<tenant>.webhook.office.com/webhookb2/<token>/IncomingWebhook/<id>/<key>
cfgdrift alert add --name oncall --type pagerduty --severity CRITICAL \
    --routing-key "{env:CFGDRIFT_PD_ROUTING_KEY}"     # {env:VAR} 引用，明文不落盘
cfgdrift alert test --rule ops-slack                  # 连通性验证 exit 0/2
```

- **severity 统一映射**：CRITICAL → Slack/Teams `#e11d48`、PagerDuty `critical`；WARN → `#f59e0b` / `warning`；INFO → `#64748b` / `info`（`channels.py` 单点常量表，三渲染器共用）
- **凭据不落盘**：`webhook_url` / `routing_key` 支持 `{env:VAR}` 在发送时展开；错误消息只含 `scheme://host`，不回显 webhook token / routing key
- **零噪音**：不配置新通道时，CLI / 告警 payload / Web / daemon 行为与 v0.14.0 逐字节一致

## 列表重排检测（v0.16.0）

列表 diff 从「按索引逐位比较」升级为 **LCS 序列匹配**（标准库 `difflib`，零新增依赖）：元素按「类型 + 语义值」指纹配对，**内容不变仅位置变**的元素报 INFO 级 `reordered`，不再误报为多处 `modified`；真新增 / 真删除 / 真修改照常判定。

```bash
cfgdrift diff ./app.yaml --baseline prod          # 默认开启重排检测
cfgdrift diff ./app.yaml --baseline prod --no-reorder   # 恢复 v0.15.0 逐位行为
```

- **REORDERED 语义**：`[alice,bob,carol]` → `[carol,alice,bob]` = 3 条 `reordered`（INFO），**不计入退出码**（纯重排 exit 0，CI 友好）；混合场景 `[a,b,c,d]`→`[a,c,b,e]` = b/c 重排 + d 删除 + e 新增
- **可精确控制**：`change_type=reordered` 可用于 ignore 规则（静默）与 severity 规则（如把 ingress host 顺序提升为 WARN）
- **零噪音契约**：不含重排的 diff 与 v0.15.0 逐字节一致（`reordered` 计数 / `reorder` 详情仅非零时输出）；`--no-reorder` 下完全恢复 v0.15.0 行为
- **约束语义**：索引引用 = 位置引用，随重排移动（`hosts[2].port` 按新列表 index 2 评估）；内置 20 条约束均为 dict 路径，零改动
- corpus 迁移评估：`benchmark/corpus-v1/results/reorder_migration.md`（232 实例中 9 个重排实例、223 个非重排实例逐字节一致）

## 📚 文档站

| 主题 | 链接 |
|------|------|
| 首页 / 总览 | [docs-site/index.html](./docs-site/index.html) |
| 安装（双 wheel / 构建 / 环境变量 / 双模式差异） | [installation.html](./docs-site/installation.html) |
| 快速上手 | [quickstart.html](./docs-site/quickstart.html) |
| CLI 参考（完整命令清单） | [cli.html](./docs-site/cli.html) |
| Web 仪表盘 | [web-dashboard.html](./docs-site/web-dashboard.html) |
| 告警（三通道 / 重试 / 静默 / 趋势） | [alerting.html](./docs-site/alerting.html) |
| 一致性约束 | [constraints.html](./docs-site/constraints.html) |
| corpus 基准语料 | [corpus.html](./docs-site/corpus.html) |
| 自愈（remediate + hint） | [self-healing.html](./docs-site/self-healing.html) |
| 示例 gallery | [gallery.html](./docs-site/gallery.html) |
| 贡献指南 | [contributing.html](./docs-site/contributing.html) |
| FAQ | [faq.html](./docs-site/faq.html) |

## 核心特性（按用户价值，不按版本）

### 语义 diff 与严重度

- 检出新增 / 删除 / 修改 / 类型变化四类漂移，忽略注释 / 缩进 / 键序等格式噪音；快照结构 `{relpath: tree}`，文件级新增 = INFO、删除 = CRITICAL。
- 目录扫描约定：扩展名识别 `.json` / `.yaml|.yml` / `.toml` / `.ini|.cfg|.conf`，未知扩展名跳过并告警；单文件未知扩展名需显式 `--format`；列表 diff 按索引比较（不检测元素重排）。
- 数据目录默认 `~/.cfgdrift/`，可用 `CFGDRIFT_HOME` 或 `--store PATH` 覆盖。
- **退出码契约**：`0`=无漂移，`1`=检出漂移，`2`=错误——可直接接入 CI 门禁。
- 多环境基线对比：`compare ENV1 ENV2...`（头部展示 `compare A -> B (vX vs vY)`，支持 `environments.yaml` 映射）；`report --html` / `--json` / `--csv` 导出报告。

### 一致性约束与约束挖掘

- 在语义 diff 之上叠加约束检查层，**仅报告与本次漂移关联**的约束破坏（零噪音契约）。
- 五类约束：`range` / `enum` / `conditional_required` / `correlation` / `mutual_exclusion`；diff / scan / daemon 默认启用内置库（20 条，`--no-builtin` 关闭，`--constraints` 追加），`constraint add|list|remove|disable|enable` 管理用户规则。
- `constraint mine` 从历史扫描 / 语料挖掘候选（`mined_candidates.yaml`，`enabled: false` 不自动生效），人工确认后一键转正。

```bash
cfgdrift diff ./config --baseline prod --constraints extra.yaml
cfgdrift constraint mine --min-support 5 --source scans
```

### daemon 与告警

- 后台常驻周期扫描，检出漂移触发 webhook / 邮件 / 脚本 / Slack / Teams / PagerDuty 六通道告警；防抖去重 + 失败重试（规则级 `--retry-count` / `--retry-delay` 可配）。
- 开机自启：`daemon enable-autostart|disable-autostart|autostart-status`（systemd / launchd / schtasks，幂等语义，`--dry-run` 预览）。
- 规则级静默 `alert mute NAME --until <ISO>` + 事件 ack；daemon 健康可观测（`error_rate` 聚合）。

```bash
cfgdrift daemon enable-autostart --target /etc/nginx --baseline prod --interval 300
cfgdrift alert add --name nginx-webhook --type webhook --url http://x --retry-count 5
```

### 自愈闭环（remediate + hint）

- `cfgdrift remediate --baseline NAME [--apply]` 按 `<home>/remediate.yaml` 策略把漂移键**精确回滚**回基线值：只改写目标键文本区间，注释 / 缩进 / 键序 / 其它键逐字节保留；写前备份 + 原子写 + 写后校验；默认 dry-run 预览。
- `daemon start --remediate` 自动修复闭环；每次动作落 `remediation_log` 审计表（Web「自愈审计」视图）。
- G4 修复建议：每条 CRITICAL/WARN 漂移自动生成 `[hint]`（期望值 + 回滚命令 + 溯源）；`--no-hint` 一键恢复旧输出（零噪音）。

```bash
cfgdrift remediate --baseline prod            # dry-run 预览
cfgdrift remediate --baseline prod --apply    # 执行回滚
cfgdrift diff ./config --baseline prod --no-hint   # 关闭 hint
```

### Web 仪表盘（10 视图）

- `cfgdrift serve` 启动本地 Web 仪表盘（`127.0.0.1:8080`，需 `[web]` extra）。
- 10 视图：时间线（搜索 / 筛选 / 分页）、严重度分布（饼图点击联动）、环境对比、报告（含「导出 HTML」）、告警（规则管理 / 趋势图 / 事件 ack）、约束（生效列表 / 挖掘候选 / 违反）、corpus 统计、自愈审计等。

```bash
pip install "cfgdrift[web]"
cfgdrift serve
```

### Web 认证（v0.17.0）

把 dashboard 共享给团队时，用 **Bearer token** 给全部 `/api/*` 路由（含回滚 / 改规则 / 发告警等写操作）上锁——**不配置 token 时服务与 v0.16.0 逐字节一致**（零噪音，默认匿名）。

```bash
cfgdrift web token                 # 生成一个 URL-safe token（43 字符，一次一行）
cfgdrift serve --token <TOKEN>     # 启动时开启认证
CFGDRIFT_WEB_TOKEN=<TOKEN> cfgdrift serve   # 或走环境变量（CLI --token 优先）
```

- 认证开启后：`Authorization: Bearer <token>` 缺失 / 错误 / 缺 `Bearer ` 前缀 → `401` + `WWW-Authenticate: Bearer`（写操作零副作用）；对 token 的响应与 v0.16.0 逐字节一致。
- 前端行为：任一 `/api/*` 请求返回 401 → 弹登录层；登录成功写入 `localStorage`（key `cfgdrift_web_token`）并自动重渲染，刷新页面保持登录态。**未启用认证时前端不弹层、无探针请求**。
- 安全提示：绑到非回环地址（如 `0.0.0.0`）且未配置 token 时，启动会向 stderr 打印警告（仅提示，不拦截启动）。token 只回显「已启用/未启用」状态，从不打印 token 值。

### corpus 基准语料 + kappa

- `corpus init|fetch|export|validate` 从真实项目 git 历史挖掘配置变更对，标准化为 `instances.jsonl`（`local_path` 离线采集 / CI 安全）。
- `corpus annotate` 双人标注 + `corpus kappa`（Cohen's kappa + 混淆矩阵）+ `corpus stats`；`kappa --export` 导出论文附录。

### 敏感值脱敏

- 终端 / JSON 报告 / HTML 报告 / Web API / 告警 payload 五出口对 `password` / `token` / `secret` 等 13 类敏感键自动打码（`masking.yaml` 可定制；数据库始终保存原始值）。

### 自定义解析器插件

- `--format <plugin>` 支持自定义解析格式：插件返回原始树，由引擎统一归一化为语义树；可选 `build_line_map` 提供 `file:line` 行号。
- 方式 A 装饰器 `@register_plugin(...)` 进程内注册（import 即生效）；方式 B entry point `[project.entry-points."cfgdrift.parsers"]` pip 打包分发。
- 完整可运行示例（含 pytest 测试）：[`examples/mydsl-parser`](./examples/mydsl-parser)。

```bash
pip install -e examples/mydsl-parser
cfgdrift scan app.dsl --format mydsl        # 或按 .dsl 扩展名自动识别
```

### 双 wheel / C 加速

- 双 wheel 发布：纯 Python 通用 wheel（默认）+ CPython 3.13 C 加速平台 wheel + sdist；pip 标签优先级自动分流。
- 构建配方 / 环境变量表（`CFGDRIFT_BACKEND` / `CFGDRIFT_NO_C` 等）/ 双模式一致性差异明细：见 [installation.html](./docs-site/installation.html)。

## 示例 gallery

三段可复现 demo，一键跑通「基线 → 漂移 → 检出 → 修复建议 → 自愈」全流程：

| Demo | 场景 | 演示能力 | 一键复现 |
|------|------|----------|----------|
| nginx | 生产配置被人工改端口 | 插件解析器 + range 约束 + hint + 自愈回滚 | `bash docs/gallery/nginx/run.sh` |
| configmap | staging/prod 双 ConfigMap | 多环境对比 + correlation 约束 + 脱敏 | `bash docs/gallery/configmap/run.sh` |
| ci-gate | CI 配置漂移门禁 | 退出码契约 + JSON / HTML 报告 | `bash docs/gallery/ci-gate/run.sh` |

详见 [docs/gallery/README.md](./docs/gallery/README.md) 与 [gallery.html](./docs-site/gallery.html)。

## 贡献

欢迎提交 issue 与 PR。请先阅读 [贡献指南](./docs-site/contributing.html)。开发环境：`pip install "cfgdrift[dev]"`，测试用 `pytest`。

## FAQ

常见问题见 [文档站 FAQ](./docs-site/faq.html)。

## License

本项目采用 **MIT License**（详见根目录 [`LICENSE`](./LICENSE) 文件）。

MIT 许可允许你自由使用、修改与分发本项目（包括商业用途），只需保留原始版权声明与许可声明即可。

## 版本历史

各版本增量（v0.13.0 → v0.1.0）见 [docs/CHANGELOG.md](./docs/CHANGELOG.md)（英文版 [docs/CHANGELOG.en.md](./docs/CHANGELOG.en.md)）。
