chat-archive-guard README

The project's README from github.com/MaxHu-xuan/chat-archive-guard. As one markdown file: README.md.

ChatArchiveGuard(聊天归档守护)

CI

中文:中文说明 | 中文技术参考 | 中文项目资料

English: English overview | English technical reference | Project information

中文说明

准备保存、迁移、共享或分析聊天导出时,可以先让 ChatArchiveGuard(聊天归档守护)在 自己的电脑上做一次只读检查:

扫描器只读取你指定的文件或目录,不修改原文件,也不上传数据。使用 --summary-only 时, 报告只保留真实状态、数量和类别,不包含文件名或命中值。默认报告仍会显示相对文件名,方便 本地定位问题。运行时没有网络客户端、遥测或自动更新功能。

它是一道面向交付或迁移前检查的审计门禁,不是聊天归档阅读器、导入器、搜索器,也不能 证明消息业务完整或来源真实。

先看一分钟合成演示,或比较三个相关工具。

用户价值

一次扫描可以回答三个实际问题:

  1. 支持的文件中是否出现常见密钥、凭证或个人信息形态;
  2. JSON、JSONL 和 SQLite 等内容是否能按预期读取,SQLite 快检是否通过;
  3. 本次符合检查范围的内容是否全部完成扫描,是否有链接、读取错误或资源上限留下盲区。

这里的聊天归档完整性指文件格式、SQLite 结构和本次扫描覆盖状态。它不等于消息完整性, 也不能证明归档没有丢消息、来源真实或文件从未被篡改。

三个项目怎么选

你的问题 选择
分享或迁移聊天导出前,本地检查疑似秘密、个人信息形态、格式、SQLite 与扫描盲区 ChatArchiveGuard(聊天归档守护),当前项目
确认最终 PPTX 及随附验收证据仍匹配结构检查后生成的 HMAC 签名收据 ArtifactProof(PPTX 交付物验真)
重启后核对卡住任务、超时与待投递状态,不把未知结果猜成成功 TaskStateGuard(任务状态守护)

三个工具解决的是不同问题,可以单独使用;ChatArchiveGuard 不负责 PPTX 验真或任务状态修复。

适用场景

完整性检查

ChatArchiveGuard 会按文件类型执行不同检查:

轮转日志会作为独立文件处理。只有最终扩展名属于支持范围的文件,例如 history.1.log, 才会进入文本扫描;history.log.1 和压缩后的 .gz 文件不会被自动识别为文本。工具不会 拼接轮转序列,也不会判断时间段是否连续。

隐私与安全

默认报告中的相对文件名仍是元数据。使用 --summary-only 后,JSON 和文本输出都会省略 全部发现明细与相对文件名,只保留真实状态、扫描计数和类别汇总,适合 CI 或分享 脱敏报告。无论使用哪种报告模式,退出码和 finding_count 都不会被改写。

摘要模式不会建立用户或渠道隔离。类别计数仍然汇总整个扫描根目录,因此调用者应先把根 目录限制在自己有权检查的单个数据集,不要用一个跨用户目录生成共享摘要。

快速开始

需要 Python 3.11 或更高版本。安装已发布版本时,建议先创建隔离环境,再从 PyPI 安装, 避免影响系统 Python。

macOS 或 Linux:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install chat-archive-guard
chat-archive-guard /path/to/archive
chat-archive-guard /path/to/archive --json --summary-only

Windows PowerShell 使用 Python Launcher 和不同的路径写法:

py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install chat-archive-guard
.\.venv\Scripts\python.exe -m chat_archive_guard C:\path\to\archive
.\.venv\Scripts\python.exe -m chat_archive_guard C:\path\to\archive --json --summary-only

同时查看退出码和 ok、complete、truncated。只有没有发现项、扫描完整且未截断时, ok 才会是 true。

如果正在审核尚未发布的候选版本,或希望从源码安装,请先进入你已核对的源码仓库根目录 (即包含 pyproject.toml 的目录)。在已经创建并激活的 macOS 或 Linux 隔离环境中运行:

python -m pip install .

Windows PowerShell 使用已经创建的同一个隔离环境:

.\.venv\Scripts\python.exe -m pip install .

如需从 wheel 离线安装,请从同一个 GitHub Release 页面下载 SHA256SUMS 和 chat_archive_guard-0.1.0-py3-none-any.whl,并把两个文件放在同一目录。 SHA-256 核对只能确认 wheel 与该清单一致,不能替代对发布来源的核对。

macOS 或 Linux 先运行:

wheel="chat_archive_guard-0.1.0-py3-none-any.whl"
if command -v sha256sum >/dev/null 2>&1; then
  awk -v name="$wheel" '$2 == name { print }' SHA256SUMS | sha256sum -c -
else
  awk -v name="$wheel" '$2 == name { print }' SHA256SUMS | shasum -a 256 -c -
fi

只有在输出 chat_archive_guard-0.1.0-py3-none-any.whl: OK 后,才在已经激活的隔离环境中安装:

python -m pip install --no-index --no-deps ./chat_archive_guard-0.1.0-py3-none-any.whl

Windows PowerShell 先核对同一目录中的文件:

$wheel = "chat_archive_guard-0.1.0-py3-none-any.whl"
$rows = @(Get-Content .\SHA256SUMS | Where-Object {
    $_ -match ("^[0-9a-f]{64}  " + [regex]::Escape($wheel) + "$")
})
if ($rows.Count -ne 1) { throw "Expected exactly one checksum row" }
$expected = ($rows[0] -split "  ", 2)[0]
$actual = (Get-FileHash -Algorithm SHA256 ".\$wheel").Hash.ToLowerInvariant()
if ($actual -ne $expected) { throw "SHA-256 verification failed" }
"SHA-256 OK: $wheel"

只有核对成功后才安装:

.\.venv\Scripts\python.exe -m pip install --no-index --no-deps .\chat_archive_guard-0.1.0-py3-none-any.whl

未安装时,macOS 和 Linux 可以从你已核对的源码仓库根目录运行:

PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python3 -m chat_archive_guard /path/to/archive --json

Windows PowerShell 使用不同的环境变量语法:

$env:PYTHONDONTWRITEBYTECODE = "1"
$env:PYTHONPATH = "src"
py -3 -m chat_archive_guard C:\path\to\archive --json

可重复合成演示

仓库附带的生成器只创建两份固定的虚构数据:一份 JSONL 和一份 SQLite。它不会读取现有 文件,也不会覆盖已有目录。演示中的测试标记都明确写着永不有效,只用于证明检查器确实能 发现问题,不是可用凭据,也不来自任何真实对话。

macOS 或 Linux(在仓库根目录执行):

demo_parent="$(mktemp -d)"
demo_parent="$(cd "$demo_parent" && pwd -P)"
demo_dir="$demo_parent/chat-archive-guard-demo"
PYTHONDONTWRITEBYTECODE=1 python3 scripts/generate_demo.py "$demo_dir"
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python3 -m chat_archive_guard "$demo_dir" --summary-only

实测输出如下:

synthetic demo: PASS files=2
FAIL files_seen=2 files_scanned=2 finding_count=3 complete=true truncated=false details_omitted=true findings_omitted=true
category=format.invalid_jsonl count=1
category=secret.assignment count=1
category=secret.provider_key count=1

Windows PowerShell(在仓库根目录执行):

$demoDir = Join-Path ([System.IO.Path]::GetTempPath()) ("chat-archive-guard-demo-" + [guid]::NewGuid())
$env:PYTHONDONTWRITEBYTECODE = "1"
$env:PYTHONPATH = "src"
py -3 scripts/generate_demo.py $demoDir
py -3 -m chat_archive_guard $demoDir --summary-only

Windows 的文本检查结果相同,但标准 Python 会按安全边界拒绝直接检查 SQLite,因此输出为:

synthetic demo: PASS files=2
FAIL files_seen=2 files_scanned=1 finding_count=3 complete=false truncated=true details_omitted=true findings_omitted=true
category=format.invalid_jsonl count=1
category=secret.assignment count=1
category=sqlite.sidecar_unsafe count=1

两组扫描命令的退出码都会按设计返回 1,因为演示数据故意包含三个发现项。这表示门禁 发现了问题,不表示生成器或扫描器运行失败。演示结束后可以删除刚创建的唯一临时目录。

看懂结果

内容 含义
退出码 0 没有发现项,并且符合范围的内容完成扫描
退出码 1 发现问题,或有符合范围的内容未能完整检查
退出码 2 扫描路径或参数无效
files_seen 遍历到的常规文件数量,包括不支持内容检查的文件
files_scanned 已进入受支持内容检查阶段的文件数量
finding_count 所有类别的真实发现总数,包括摘要模式省略的明细
complete 符合当前检查范围的内容是否全部完成检查
truncated 是否因限制、读取失败或安全拒绝留下未检查内容
findings 默认报告中的相对路径、固定类别和数量,不含命中值
details_omitted、findings_omitted 摘要模式明确表示明细和文件名已省略

下面是默认 JSON 模式扫描一个合成无效文件后的完整结果。 format.invalid_json 表示 JSON 格式错误:

{
  "schema_version": 1,
  "ok": false,
  "complete": true,
  "truncated": false,
  "root": ".",
  "summary": {
    "files_seen": 1,
    "files_scanned": 1,
    "finding_count": 1,
    "categories": {"format.invalid_json": 1}
  },
  "findings": [
    {"path": "broken.json", "category": "format.invalid_json", "count": 1}
  ]
}

complete=true 只表示符合当前范围的内容完成检查,不代表聊天记录在业务上完整,也不代表 工具能证明文件中不存在任何敏感信息。

平台差异

能力 Linux macOS Windows
文本、JSON、JSONL 检查 支持 支持 支持
SQLite、WAL、SHM 检查 提供 O_NOFOLLOW 时支持 提供 O_NOFOLLOW 时支持 标准 Python 下安全拒绝
文件权限检查 POSIX 权限位 POSIX 权限位 不推断或审计 ACL
链接防护 拒绝或跳过符号链接 拒绝或跳过符号链接 拒绝或跳过重解析点及类似入口

Windows 标准库 Python 没有本项目安全边界要求的原子 no-follow 打开能力。遇到 SQLite 时, 工具会返回 sqlite.sidecar_unsafe,并设置 complete=false、truncated=true,不会降低保护 等级后继续读取。

使用局限

内容检查覆盖 .txt、.md、.log、.csv、.tsv、.yaml、.yml、.json、 .jsonl 和 .ndjson。.db、.sqlite、.sqlite3 以及带 SQLite 文件头的文件会按 SQLite 处理。

压缩包、加密文件、专有格式、附件、图片、音频和其他二进制内容不在检查范围内。这些常规 文件仍计入 files_seen,并在 POSIX 系统上接受权限检查,但不计入 files_scanned。

工具不会验证消息完整性(message completeness)、来源归属(source attribution)、导出 时间范围、参与者身份或平台签名。它也不是聊天阅读器、备份恢复工具、杀毒软件、OCR 工具、 取证工具或完整的数据防泄漏系统。匹配结果只是风险提示,可能存在误报和漏报。

常见问题

会上传聊天数据吗?

不会。安装后的扫描器只读取本地路径,没有网络客户端或遥测。常规安装可能访问包索引; 需要完全离线时,请按前述步骤从同一个 GitHub Release 下载 wheel 和 SHA256SUMS, 核对后再使用 --no-index --no-deps 安装。

能检查所有聊天导出吗?

不能。工具只检查支持的文本、JSON、JSONL 和 SQLite 内容,不要求文件来自特定应用。 压缩、加密、专有格式和附件内容不受支持。

能验证消息完整性和来源归属吗?

不能。工具可以报告文件格式、SQLite 快检和扫描覆盖状态,但无法知道平台是否漏导、记录 是否被删除,也不能认证某条消息来自哪个平台、账户或设备。需要这类结论时,应另外保存并 核对原始来源、耐久记录、可读归档、记录计数、时间范围、导出签名或可信来源回执,并对 轮转来源的归属冲突采用安全拒绝策略。本项目不建立或修复这些跨层关系。

如何处理轮转日志(rotated logs)?

把需要检查的未压缩日志放在同一扫描根目录下,并确保最终扩展名是 .log。每份文件会独立 扫描,但工具不会还原轮转顺序、去重或证明时间覆盖连续。压缩日志需要先在受控目录中安全 解包,解包能力不属于本项目。工具也不会根据文件名推断日志属于哪个用户、渠道或来源。

没有发现项就代表绝对安全吗?

不代表。完整且无发现的结果只说明已检查内容没有触发当前规则。未知模式、不支持的格式、 语义重识别和检测器漏报仍然可能存在。

可以在 CI 中使用吗?

可以,但 CI 必须有权读取输入。建议使用 --json --summary-only 读取真实状态与类别汇总, 避免在构建日志中暴露相对文件名。不要把真实聊天内容上传为公开构建产物。本项目自己的 CI 只使用运行时生成的合成数据。

中文技术参考

工作原理

  1. 工具只遍历指定文件或目录。扫描根路径的链接型入口会被拒绝,目录内的链接会被报告但 不会跟随。
  2. 文本检测器只累计类别数量,不保留命中值。JSON 和 JSONL 同时接受格式校验。
  3. 在支持原子 no-follow 打开的系统上,SQLite 主文件和现有 WAL、SHM 会复制到权限为 0700 的临时目录和权限为 0600 的临时文件。工具重新校验来源身份和 SHA-256, 只让 SQLite 打开私有副本,再在内存备份上运行 PRAGMA quick_check(1) 和内容检查。
  4. FTS 虚拟表内容只检查一次,FTS 影子表不会重复计数。来源发生并发变化、读取失败或达到 限制时,结果会明确标为不完整。

扫描器只使用 Python 标准库。完整边界和残余风险见 THREAT_MODEL.md。

检查类别

资源限制

参数 默认值 最大值
--max-file-mib 16 MiB 256 MiB
--max-sqlite-rows 100,000 1,000,000
--max-sqlite-value-kib 1,024 KiB 16,384 KiB
--max-files 10,000 100,000
--max-findings 10,000 100,000

达到文件数、发现数、字节、行数或值大小限制时,结果会出现对应发现项,并设置 complete=false、truncated=true。有限扫描不会因为未检查内容暂时没有命中而返回健康 结果。

中文项目资料

ChatArchiveGuard 采用 Apache License 2.0,详见 LICENSE 和 PROVENANCE.md。

参与贡献时请只使用合成数据。支持、安全、贡献规范与项目记录见 SUPPORT.md、 SECURITY.md、 CONTRIBUTING.md、 CODE_OF_CONDUCT.md、 CHANGELOG.md、 RELEASE_NOTES.md 和 RELEASING.md。

需要帮助、报告安全问题或参与贡献时,请按对应文档操作。版本记录、发布说明和维护者发布 流程分别列出,方便使用者与贡献者直接找到所需内容。

English overview

Before you store, migrate, share, or analyze a chat export, run ChatArchiveGuard locally to:

The scanner reads only the file or directory you choose. It does not modify the source or upload data. With --summary-only, the report keeps real status, counts, and categories while omitting filenames and matched values. Default reports retain relative filenames for local troubleshooting. The runtime has no network client, telemetry, or automatic update check.

It is a pre-delivery or pre-migration audit gate, not a chat archive reader, importer, search tool, or proof of message completeness or source authenticity.

Try the one-minute synthetic demo, or compare the three related tools.

User value

One scan answers three practical questions:

  1. Do supported files contain common secret, credential, or personal-data patterns?
  2. Can JSON, JSONL,

chat-archive-guard (MaxHu-xuan/chat-archive-guard)

Searching Database…

What is this?ChatArchiveGuard is a local, read-only CLI auditor you run on an AI chat export before sharing, migrating, or archiving it. It flags likely secrets and personal-data patterns, finds malformed UTF-8/JSON/JSONL, checks SQLite integrity, and reports scan coverage gaps.
Is this a chat reader or importer?No. It is strictly a pre-delivery audit gate that scans files and prints a report; it does not read, import, search, or reconstruct chat archives.
How do I get it running?Create an isolated virtual environment with Python 3.11 or newer, then install the published package from PyPI (or install from source/wheel for offline use), and run the scanner against a file or directory.
Does it need any libraries besides Python itself?No extra dependencies are required; the scanner runs entirely on the Python standard library at runtime.
Can it prove my chat export is complete or untampered?No. It can only report file format validity, SQLite integrity-check results, and scan coverage — it cannot verify message completeness, source authenticity, export time ranges, or participant identity, and matches can be false positives or false negatives.
Does SQLite scanning work the same on Windows as on macOS and Linux?No. On Windows, standard Python lacks the atomic no-follow file open the tool requires, so SQLite/WAL/SHM checks are safely refused and reported as incomplete, while Linux and macOS support full SQLite checking.
Does any of my chat data get uploaded anywhere?No. The scanner only reads the local file or directory you point it at, has no network client or telemetry, and never modifies the source.
What do the exit codes mean?Exit code 0 means no findings and full scan coverage; exit code 1 means findings were reported or coverage was incomplete; exit code 2 means an invalid scan path or argument.
What does --summary-only change in the report?It strips relative filenames and matched values from the output, keeping only real status, counts, and category totals — useful for sharing a redacted report or logging it in CI.
Can I run it inside a CI pipeline?Yes, as long as CI can read the input files. The project recommends --json --summary-only to avoid leaking filenames into build logs, and its own CI only scans synthetic demo data.
How are rotated log files handled?Each rotated file with a supported final extension like .log is scanned as an independent file; the tool does not merge rotation order, deduplicate entries, or prove the time range is continuous.
Creator
MaxHu-xuan
Size
0.1 MB
Stars
858
Age
1mo
Commits · 90 Days