diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 0ba09719d..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,37 +0,0 @@ -# 贡献说明 - -本仓库以个人使用为主,主要维护自定义规则并整合上游数据。提交规则时保持内容清晰、可生成即可,不设置复杂审批流程。 - -## 自定义规则 - -- 域名规则:`sources/custom/domain/*.list` -- IP 规则:`sources/custom/ip/*.list` -- 文件名使用小写字母、数字和连字符。 -- 规则类型和值保持规范格式,例如: - -```text -DOMAIN,api.example.com -DOMAIN-SUFFIX,example.com -IP-CIDR,192.0.2.0/24 -IP-CIDR6,2001:db8::/32 -``` - -不同文件可以有意重叠,以便分别绑定不同策略;同一文件内不应保留重复或被更宽规则覆盖的条目。使用首条命中的客户端时,细分规则应放在宽泛规则之前,例如先加载 `emby-cn`,再加载 `emby`。 - -## 修改与验证 - -日常修改可直接提交,也可通过 Pull Request 合并。建议至少运行: - -```bash -make validate -``` - -需要预览自定义文本产物时运行: - -```bash -make build-custom-text -``` - -涉及完整上游同步或二进制格式时,由 `main` 分支的发布工作流统一构建。不要提交 `.output/`、`.tmp/`、`.artifacts/`、`.bin/`、凭据或本机缓存。 - -新增上游时,在 `config/upstreams.json` 中填写来源和健康阈值,并按实际情况更新第三方来源说明。仓库代码使用 MIT 许可证;上游数据仍遵循各自条款。 diff --git a/README.md b/README.md index 033b937a7..1cbab666e 100644 --- a/README.md +++ b/README.md @@ -2,112 +2,70 @@

Sync Rules - Pull Request Validation Platforms - Repository code license

-本仓库用于个人维护自定义规则并整合上游数据,生成 Surge、Quantumult X、Egern、sing-box 与 mihomo 规则。`main` 保存源码、配置和工作流;可直接使用的文件位于对应平台分支。 +个人自用规则仓库:维护自定义规则,拉取并整合上游数据,自动生成多个客户端的规则文件。 -> [!IMPORTANT] -> 客户端不要引用 `main`。规则名称和区域分类沿用上游定义,不构成准确性、完整性或适用性保证。第三方内容不因格式转换而自动适用本仓库的 MIT 许可,详见 [`NOTICE`](NOTICE) 与 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。 +> 客户端不要引用 `main`,请使用对应的产物分支。 -## 获取产物 +## 产物 -分支 URL 格式: +| 客户端 | 分支 | 格式 | +| --- | --- | --- | +| Surge | [`surge`](https://github.com/KuGouGo/Rules/tree/surge) | `.list` | +| Quantumult X | [`quanx`](https://github.com/KuGouGo/Rules/tree/quanx) | `.list` | +| Egern | [`egern`](https://github.com/KuGouGo/Rules/tree/egern) | `.yaml` | +| sing-box | [`sing-box`](https://github.com/KuGouGo/Rules/tree/sing-box) | `.srs` | +| mihomo | [`mihomo`](https://github.com/KuGouGo/Rules/tree/mihomo) | `.mrs` | + +URL 格式: ```text -https://raw.githubusercontent.com/KuGouGo/Rules/{branch}/{type}/{name}.{extension} +https://raw.githubusercontent.com/KuGouGo/Rules/{branch}/{domain|ip}/{name}.{extension} ``` -| 客户端 | 分支 | domain / ip 扩展名 | 分支说明 | -| --- | --- | --- | --- | -| Surge | `surge` | `.list` | [查看产物](https://github.com/KuGouGo/Rules/tree/surge) | -| Quantumult X | `quanx` | `.list` | [查看产物](https://github.com/KuGouGo/Rules/tree/quanx) | -| Egern | `egern` | `.yaml` | [查看产物](https://github.com/KuGouGo/Rules/tree/egern) | -| sing-box | `sing-box` | `.srs` | [查看产物](https://github.com/KuGouGo/Rules/tree/sing-box) | -| mihomo | `mihomo` | `.mrs` | [查看产物](https://github.com/KuGouGo/Rules/tree/mihomo) | - 示例: ```text https://raw.githubusercontent.com/KuGouGo/Rules/surge/domain/cn.list https://raw.githubusercontent.com/KuGouGo/Rules/quanx/domain/emby-cn.list -https://raw.githubusercontent.com/KuGouGo/Rules/egern/ip/cn.yaml -https://raw.githubusercontent.com/KuGouGo/Rules/sing-box/domain/cn.srs +https://raw.githubusercontent.com/KuGouGo/Rules/sing-box/domain/fakeip-filter.srs https://raw.githubusercontent.com/KuGouGo/Rules/mihomo/ip/google.mrs ``` -各平台的接入方式和最小配置示例位于对应产物分支的 `README.md`。分支 URL 会随成功发布变化,不适合作为不可变版本标识;需要固定内容时,应将分支名替换为产物分支的提交 SHA。 - -## 规则说明 - -| 名称 | 类型 | 当前生成方式 | -| --- | --- | --- | -| `cn` | domain | v2fly/domain-list-community 的 `cn` 集合及其派生结果 | -| `cn` | ip | 配置的中国大陆 IP 上游经规范化、去重和 CIDR 合并后的结果 | -| `geolocation-cn` / `geolocation-!cn` | domain | 上游提供的区域集合名称与内容 | -| `google` / `telegram` | ip | 配置的服务地址源;Telegram 结果还合并配置的 ASN 前缀 | -| `emby-cn` / `emby` | domain | 本仓库维护的两个 Emby 规则集合 | -| `fakeip-filter` | domain | 本仓库维护的 Fake-IP 排除集合 | - -在按首条命中处理的客户端中,如果同时使用 `emby-cn` 和 `emby`,应先加载范围较窄的 `emby-cn`。规则文件会随上游增加、删除或改变;使用前应在目标分支确认文件存在并检查内容。 - -## 转换行为 +常用规则包括 `cn`、`geolocation-cn`、`geolocation-!cn`、`google`、`telegram`、`emby-cn`、`emby` 和 `fakeip-filter`。同时使用 `emby-cn` 与 `emby` 时,应先加载范围较小的 `emby-cn`。 -| 产物平台 | 精确域名 | 后缀 | 关键词 | 正则 | IP CIDR | -| --- | :---: | :---: | :---: | :---: | :---: | -| Surge | ✓ | ✓ | ✓ | — | ✓ | -| Quantumult X | ✓ | ✓ | ✓ | — | ✓ | -| Egern | ✓ | ✓ | ✓ | ✓ | ✓ | -| sing-box | ✓ | ✓ | ✓ | ✓ | ✓ | -| mihomo | ✓ | ✓ | — | — | ✓ | +## 添加自定义规则 -`✓` 表示当前转换器会保留并输出该类型,`—` 表示当前转换链会省略该类型;该表不判断客户端自身的全部能力。一个列表在目标平台没有可保留条目时,不发布空文件。 +- 域名规则:`sources/custom/domain/*.list` +- IP 规则:`sources/custom/ip/*.list` +- 文件名使用小写字母、数字和连字符。 -属性与区域名称沿用上游语义: +```text +DOMAIN,api.example.com +DOMAIN-SUFFIX,example.com +DOMAIN-KEYWORD,example +DOMAIN-REGEX,^(.+\.)?example\.com$ +IP-CIDR,192.0.2.0/24 +IP-CIDR6,2001:db8::/32 +``` -- `name@cn`、`name@!cn`、`name@ads` 是属性派生集合,`@!cn` 不是布尔取反。 -- `*-cn`、`*-!cn` 是区域列表名称;明显冗余的属性派生不会发布。 -- `official`、`registry`、`community` 是仓库配置中的来源分类,不代表质量、可信度或许可等级。 +不同文件可以按策略需要重叠;同一文件内不要保留重复或被更宽规则覆盖的条目。 -## 本地维护 +## 本地检查 -本地命令要求 Bash 5+、Python 3.11+、GNU Make 和 Git。macOS 可使用 Homebrew Bash 与 Python 运行检查和文本构建;需要下载 sing-box 或 mihomo 的二进制构建只支持 lock 文件声明的 Linux 平台。 +需要 Bash 5+、Python 3.11+、GNU Make 和 Git。 ```bash -make check -make validate -make build-custom-text -make preflight -make clean +make check # 日常快速检查 +make validate # 完整测试 +make build-custom-text # 预览自定义文本产物 +make clean # 清理生成文件 ``` -- `make check`:快速检查脚本语法、配置和自定义规则,适合日常改规则。 -- `make validate`:在快速检查基础上运行完整测试。 -- `make build-custom-text`:生成自定义文本产物,不下载二进制工具。 -- `make preflight`:执行 `make validate` 和自定义文本构建;不执行上游完整同步、二进制构建或发布。 -- `make clean`:删除生成产物和临时文件,保留已校验的工具缓存。 - -完整环境、构建事务和调试命令见 [开发指南](docs/DEVELOPMENT.md)。 - -## 仓库边界 - -- 长期分支只保留 `main` 与 `surge`、`quanx`、`egern`、`sing-box`、`mihomo` 五个产物分支。 -- 日常变更可直接提交,也可通过 Pull Request;PR 只运行基础校验,完整生成和发布由 `main` 工作流负责。 -- `main` 在构建相关路径变化、定时任务运行或人工触发时执行发布工作流;产物内容没有变化时不会创建新的产物分支提交。 -- 不启用自动依赖 PR;GitHub Actions 版本按需手工更新。 -- `fakeip-filter` 是本仓库维护的文本源,不下载第三方预编译文件。 -- 构建摘要、manifest 和 CI 通过都不是第三方许可证明。 -- 规则按现状提供。使用者需自行判断策略、顺序和更新带来的影响,并保留可回退版本。 - -## 文档 - -| 文档 | 内容 | -| --- | --- | -| [贡献指南](CONTRIBUTING.md) | 规则格式、来源要求和评审清单 | -| [开发指南](docs/DEVELOPMENT.md) | 环境、命令和开发流程 | -| [仓库结构](docs/STRUCTURE.md) | 同步、构建、manifest、守卫和发布架构 | -| [故障排查](docs/TROUBLESHOOTING.md) | 常见构建和产物问题 | -| [安全政策](SECURITY.md) | 安全问题报告范围与方式 | -| [第三方声明](THIRD_PARTY_NOTICES.md) | 上游来源和人工许可核对状态 | +更多维护命令见 [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md)。推送到 `main` 后,GitHub Actions 会自动构建并更新五个平台分支;每天也会定时同步一次上游。 + +## 声明 + +规则按现状提供,上游内容可能随时变化,请自行确认使用策略并保留回退版本。仓库代码使用 MIT License;第三方内容仍遵循各自条款,来源见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。 diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index e2534bfcd..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,41 +0,0 @@ -# 安全政策 - -本文件说明安全支持范围和私密报告方式。规则内容错误、许可核对和一般构建失败分别按质量或治理问题处理。 - -## 支持范围 - -仅当前 `main` 及当前自动化生成的五个本仓库维护的发布分支受支持。历史提交、第三方分叉、镜像、用户修改规则和非支持环境不在支持范围内。 - -可能导致凭据泄露、工作流或发布分支被接管、任意代码执行、供应链污染或绕过发布守卫的问题属于安全问题。规则误分流、上游失效、普通构建错误和许可状态未知通常不是安全漏洞,请使用普通 Issue 或 Pull Request,但不要公开敏感信息。 - -构建工具固定到 `config/tools-lock.json` 声明的 GitHub Release 资产,并校验归档与解包后二进制的 SHA-256;缓存还会复核来源 metadata、摘要和版本探针。该机制不等同于发布者签名,若发现资产替换、下载链路劫持或缓存投毒证据,请按安全问题私密报告。 - -## 私密报告 - -优先通过 [GitHub Security Advisory](https://github.com/KuGouGo/Rules/security/advisories/new) 私密报告。不要在公开 Issue、Pull Request、讨论区或规则文件中披露漏洞细节、令牌或可利用样例。若仓库未启用私密漏洞报告且没有可用的私密联系方式,可先提交一个不含漏洞细节的普通 Issue,请求维护者建立私密沟通渠道。 - -报告建议包含: - -- 受影响提交、脚本、工作流或发布分支; -- 最小复现步骤、利用条件和影响; -- 已采取或建议的缓解措施; -- 希望采用的披露时间表。 - -请勿在未获授权时访问他人数据、持久化控制、破坏发布分支或高频测试第三方服务。 - -## 响应与凭据处理 - -维护者会尽力确认和评估,但不承诺固定响应时限。完成缓解后将按实际影响决定是否发布公告及致谢。 - -仓库不应接收真实令牌、Cookie、私钥或账号信息。凭据进入提交或日志后应立即在提供方撤销或轮换;删除 Git 历史不能替代轮换。 - -## 文档导航 - -- [`README.md`](README.md):用户入口、平台示例和关键边界 -- [`CONTRIBUTING.md`](CONTRIBUTING.md):贡献规则与人工评审清单 -- [`docs/README.md`](docs/README.md):文档职责与阅读路径 -- [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md):环境、命令和开发流程 -- [`docs/STRUCTURE.md`](docs/STRUCTURE.md):构建、产物、守卫和发布结构 -- [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md):常见失败与定位步骤 -- [`SECURITY.md`](SECURITY.md):安全支持范围和私密报告 -- [`NOTICE`](NOTICE) / [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md):许可范围与第三方状态 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 8dab320d5..0c9f4f1d4 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -1,56 +1,20 @@ -# 第三方声明 - -本文件记录当前已知第三方输入及截至 **2026-07-15** 的人工核对状态。它不是自动生成清单,也不是法律意见。`trust` 只表示采集来源分类;公开可访问、官方托管、注册机构提供或 CI 成功都不等于获得复制、修改或再分发授权。 - -标准 MIT License 位于 [`LICENSE`](LICENSE),适用范围见 [`NOTICE`](NOTICE)。第三方材料不会因下载、规范化、合并、转换或编译而变为本仓库的 MIT 内容。 - -## 已确认的上游许可证 - -| 输入 | 来源 | 人工核对结果 | 说明 | -| --- | --- | --- | --- | -| `domain.dlc` | [v2fly/domain-list-community](https://github.com/v2fly/domain-list-community) | MIT License,`Copyright (c) 2018-2019 V2Ray` | 上游 [LICENSE](https://raw.githubusercontent.com/v2fly/domain-list-community/master/LICENSE) 明确声明;再分发时仍需保留其版权与许可声明。 | - -“已确认”只表示链接材料中存在明确许可证,不代表自动化验证了每次下载内容、上游全部依赖或具体使用方式。 - -## 许可或再分发权尚未确认 - -以下项目统一标记为“未知”。维护者必须在相关合并或发布前人工评审许可证、服务条款、数据来源和适用义务;脚本不会读取本表或据此自动阻断。 - -| 输入 | 来源 | 分类 | 人工核对状态 | -| --- | --- | --- | --- | -| `ip.cn-ipv46` | | `registry` | 未知;响应中未见明确数据许可证。 | -| `ip.loyalsoldier-geoip-cn`、`ip.loyalsoldier-geoip-private` | [Loyalsoldier/geoip](https://github.com/Loyalsoldier/geoip) `release` 分支 | `community` | 未知;`master` 的 CC BY-SA 4.0 不能自动证明 `release` 聚合产物及全部来源适用相同许可。 | -| `ip.cn-ipv46-apnic` | | `registry` | 未知;名称提及 APNIC 不等于已获 APNIC 再分发授权。 | -| `ip.google` | | `official` | 未知;响应中未见独立数据许可证。 | -| `ip.telegram` | | `official` | 未知;响应中未见独立数据许可证。 | -| `ip.cloudflare-ipv4`、`ip.cloudflare-ipv6` | | `official` | 未知;未确认独立数据许可证。 | -| `ip.aws`、`ip.cloudfront` | | `official` | 未知;两个解析器复用同一官方响应,未见独立数据许可证。 | -| `ip.fastly` | | `official` | 未知;响应中未见独立数据许可证。 | -| `ip.github` | | `official` | 未知;未确认 Meta API 数据的独立再分发许可证。 | -| `ip.apple` | (回退:) | `official` | 未知;未确认页面中网络范围数据的独立再分发许可证。 | -| `ip.ripe-stat` | | `registry` | 未知;未确认 API 响应和 ASN 查询所得前缀集合的再分发许可。 | - -`asn_groups.telegram`、`asn_groups.netflix`、`asn_groups.spotify` 和 `asn_groups.disney` 只是 RIPEstat 查询参数分组,不是独立许可声明;所得结果沿用 `ip.ripe-stat` 的“未知”状态。组织名称和商标归各自权利人所有。 - -## Fake-IP - -当前 `fakeip-filter` 是 KuGouGo 在 `sources/custom/domain/fakeip-filter.list` 维护的仓库源码,由自定义构建生成各平台文本产物以及 sing-box、mihomo 二进制产物;它不属于第三方输入,也不下载第三方预编译文件。 - -## 审计与评审边界 - -- `config/upstreams.json` 覆盖主上游规则网络输入;工具资产下载另由工具 lock 控制。当前没有 Fake-IP 网络输入或独立同步步骤。 -- `.output/upstream-summary.json` 只覆盖主同步记录,不覆盖本仓库自定义源(包括 `fakeip-filter`)、完整转换链或 HTTP 响应身份,因此不是完整来源追溯记录。 -- `.output/build-summary.json` 由成功构建事务在产物守卫后生成并受 manifest 摘要绑定;它只说明事务产物统计,不证明来源或授权。 -- 当前自动化不解析 `NOTICE` 或本文件,不验证第三方许可,也不会因“未知”状态自动失败。 -- 新增、更换或改变第三方输入时,应同步更新本文件并提供可核验依据;无法确认时保持“未知”,由维护者人工决定停止、替换、取得授权或满足适用义务后再发布。 - -## 文档导航 - -- [`README.md`](README.md):用户入口、平台示例和关键边界 -- [`CONTRIBUTING.md`](CONTRIBUTING.md):贡献规则与人工评审清单 -- [`docs/README.md`](docs/README.md):文档职责与阅读路径 -- [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md):环境、命令和开发流程 -- [`docs/STRUCTURE.md`](docs/STRUCTURE.md):构建、产物、守卫和发布结构 -- [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md):常见失败与定位步骤 -- [`SECURITY.md`](SECURITY.md):安全支持范围和私密报告 -- [`NOTICE`](NOTICE) / [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md):许可范围与第三方状态 +# 第三方来源 + +仓库代码使用 [MIT License](LICENSE)。下列上游数据仍遵循各自的许可证或服务条款,不因本仓库进行下载、合并或格式转换而变为 MIT 内容。 + +| 内容 | 来源 | +| --- | --- | +| 域名规则 | [v2fly/domain-list-community](https://github.com/v2fly/domain-list-community)(MIT) | +| 中国 IP | 、[Loyalsoldier/geoip](https://github.com/Loyalsoldier/geoip) | +| Google IP | | +| Telegram IP | | +| Cloudflare IP | | +| AWS / CloudFront IP | | +| Fastly IP | | +| GitHub IP | | +| Apple 网络范围 | | +| ASN 前缀 | [RIPEstat](https://stat.ripe.net/) | + +除 v2fly/domain-list-community 明确使用 MIT License 外,本仓库不对其他上游数据的再分发许可作保证。使用者应自行确认相关条款。 + +`fakeip-filter`、`emby`、`emby-cn` 和 `apple-apns` 的本地源位于 `sources/custom/`。当前完整上游配置以 [`config/upstreams.json`](config/upstreams.json) 为准。 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 708d229df..b025e1bda 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,89 +1,49 @@ -# 开发指南 - -本文件说明环境、命令和日常开发流程;构建内部结构见 [仓库结构](STRUCTURE.md)。 - -## 环境支持 - -CI 的受支持基准是 GitHub Actions `ubuntu-latest`、Bash 5+ 和 Python 3.11。本地验证与文本构建支持安装了 Bash 5+、Python 3.11+、GNU Make、Git、curl、tar、gzip、find 的 Linux、WSL 和 macOS;macOS 应使用 Homebrew Bash 与 Python,并确保 `/opt/homebrew/bin` 或 `/usr/local/bin` 位于系统路径之前。`make check-runtime` 会在构建前拒绝旧版 Bash 或 Python。 - -Homebrew 的版本化 Python 将通用的 `python3` 链接放在 `libexec/bin`。macOS 可用以下配置验证当前终端,而无需为本地系统增加二进制规则编译支持: - -```bash -export PATH="$(brew --prefix python@3.11)/libexec/bin:$(brew --prefix)/bin:$PATH" -make check-runtime -``` - -二进制工具下载逻辑仅支持 Linux 的 `amd64`、`arm64` 锁定资产。原生 Windows 在需要下载 sing-box/mihomo 时会被 `require_non_windows_shell` 明确拒绝;macOS 也没有对应 lock 平台。请使用 Linux、WSL 或 GitHub Actions 完成二进制构建。 - -完整构建只使用 `config/tools-lock.json` 固定的 sing-box 和 mihomo 版本、Linux 资产名、GitHub release asset SHA-256,以及从这些已校验官方归档独立提取的二进制 SHA-256;环境变量不能覆盖版本。下载归档在解包前校验摘要,解包后的程序也必须先匹配锁定摘要才会执行;缓存通过 provenance sidecar、锁定来源、二进制 SHA-256 和版本探针复核,二进制与 sidecar 成对替换,metadata 写入失败不会替换现有缓存。`tag_commit` 仅是记录/人工核对用 metadata,当前流程不认证 tag 与 commit 的关系。工作流缓存键包含锁文件摘要、两个版本和格式前缀。该机制是资产摘要锁定,不是发布者签名。 +# 维护说明 ## 常用命令 ```bash -make help -make check -make lint -make test -make validate -make build-custom-text -make build-custom -make preflight -make clean +make check # Shell、Python、配置和自定义规则检查 +make validate # 快速检查 + 全部测试 +make build-custom-text # 生成自定义文本产物 +make build-custom # 生成文本和二进制产物(Linux) +make clean # 清理临时文件和产物 ``` -- `make check` / `make lint`:快速检查 Shell、Python、配置和自定义规则。 -- `make validate`:快速检查后再运行完整测试。 -- `make check-runtime`:验证当前 `PATH` 解析到 Bash 5+ 和 Python 3.11+。 -- `make build-custom-text`:只生成自定义文本产物,不下载二进制编译器。 -- `make build-custom`:生成自定义文本和二进制产物。 -- `make preflight`:`make validate` 加文本自定义构建;不执行完整同步、产物守卫(artifact guard)或发布。 -- `build-artifacts-transaction.sh`:CI 的完整入口。它在 `.tmp/` 中以事务自有的 `RULES_ARTIFACT_ROOT` 组合上游同步或已发布分支恢复、自定义构建、守卫、摘要、manifest 生成与验证;调用方提供 `RULES_ARTIFACT_ROOT` 会被拒绝,测试或运维如需改变最终提升位置应使用 `RULES_LIVE_ARTIFACT_ROOT`。该 live root 必须与仓库 `.tmp/` 位于同一文件系统,跨设备目标会在构建前被拒绝;最终 backup、promotion 和 rollback 均使用不允许复制回退的严格目录 rename,因此检查后的设备变化也会以 EXDEV 失败。全部成功后才提升为 `.output/`(或该显式 live root)。backup 后收到 HUP、INT 或 TERM,以及 promotion rename 失败时,都会通过同一幂等回滚恢复旧目录;恢复本身失败时事务目录保留唯一备份以供人工处理。失败诊断写入非发布目录 `.artifacts/diagnostics/`,并记录 failure reason、promotion state、rollback status 与可用的 signal。`config/upstreams.json` 为每个源声明 parser、required/optional、原始字节、规范条目、地址族和 fallback policy;required 源在主 URL 与允许的回退均失败,或出现语义健康回归时阻断提升。每个 RIPE Stat ASN 响应和合并分组都使用 `ripe-stat` health policy,过小或无效响应会先写入诊断摘要再阻断事务。自定义恢复要求五个发布分支都存在且具有相同 generation/source 身份,并把分支 commit 写入 manifest restoration metadata;缺失或身份分裂时失败关闭,应执行 full 构建恢复发布 cohort。 -- `generate-artifact-manifest.sh`:完整构建事务的内部阶段,不是独立的日常构建入口。它要求当前 artifact root 已有 canonical 输入、摘要、来源记录和发布基线;按能力配置验证五个平台后才写入 schema v4 manifest。缺失或未验证的产物会阻断生成。CI 将 source SHA 绑定到实际 checkout 的 `github.sha`:PR 验证记录被测试的合并提交,正式发布记录 `main` 提交。 -- `verify-artifact-manifest.sh`:严格重算所选 artifact root 内的可发布文件集合、路径、大小和 SHA-256,并重新执行五平台 canonical 验证、核对发布基线、能力/lock 与可选 source SHA;发布 job 在恢复或安装锁定工具后强制执行同一验证。需要单独调试时,应先保留完整事务生成的 artifact root,不要手工拼装 manifest 参数。 +本地需要 Bash 5+、Python 3.11+、GNU Make 和 Git。二进制构建还需要 Linux;日常添加规则运行 `make check` 即可。 -五平台验证以 `.output/.canonical/{domain,ip}/` 为共同基准。Surge、Quantumult X、Egern 解析各自文本/YAML,`.srs` 使用固定的 `sing-box rule-set decompile` 读回 JSON,`.mrs` 使用固定的 `mihomo convert-ruleset mrs INPUT OUTPUT` 读回。每个平台先按能力矩阵过滤不支持的类型,再比较规范化语义集合:域名消除已被更宽后缀覆盖的冗余项,IP 合并为等价 CIDR 并集;值替换、范围扩大、范围丢失、缺少副本和没有 canonical 来源的额外文件都会失败。manifest 记录验证方法、原始计数、读回语义 SHA-256,以及规范输入的语义 SHA-256。 -- `make clean`:删除 `.tmp/`、`.output/`、`.artifacts/`、Python `__pycache__` 和未完成的 `.bin/*.new*`;保留已安装的 `.bin/sing-box`、`.bin/mihomo` 及 provenance sidecar。 +## 目录 -CI 设置 `REQUIRE_SHELLCHECK=1`,本地缺少 ShellCheck 时的跳过不代表 CI 会通过。 - -GitHub Actions 使用完整 commit SHA 固定版本,按需手工更新。 - -## 开发流程 - -1. 直接修改 `main` 或使用临时分支,不手工编辑生成目录。 -2. 修改自定义源、配置、实现或测试夹具。 -3. 日常规则变更运行 `make check`;修改生成逻辑时再运行 `make validate` 或适用的构建命令。 -4. 检查差异中没有 `.output/`、`.tmp/`、`.bin/`、凭据或无关格式化。 -5. 可直接提交到 `main`,也可通过 Pull Request 合并。PR 只运行基础校验;完整候选构建不再重复执行。 -6. `main` 的发布工作流按变更范围生成并更新五个平台分支。 - -## 自定义规则与名称 - -域名源位于 `sources/custom/domain/*.list`;可选 IP 源位于 `sources/custom/ip/*.list`,后者可不存在。文件名只使用小写字母、数字和连字符。 - -新增名称冲突检查仅针对相对基准提交新加入的自定义源,且 domain 与 ip 分开检查五个平台的当前 `.output/` 目标路径。它不是全仓库名称注册表,也不覆盖既有自定义源修改。 +```text +sources/custom/domain/ 自定义域名规则 +sources/custom/ip/ 自定义 IP 规则 +config/upstreams.json 上游地址和解析方式 +config/tools-lock.json sing-box / mihomo 工具版本 +scripts/ 同步、转换、校验和发布脚本 +templates/ 各产物分支 README 模板 +``` -自定义源会检查类型、值和同一文件内的重复/覆盖关系。不同文件允许有意重叠,以便绑定不同策略,不再维护逐条冲突审批清单。首条命中客户端应先加载细分规则,例如先加载 `emby-cn`,再加载 `emby`。 +不要手工修改 `.output/` 或五个平台产物分支。自定义规则或配置推送到 `main` 后,GitHub Actions 会自动生成并发布。 -## 摘要与许可评审 +## 添加规则 -主上游完整同步生成的 `upstream-summary.json` 记录健康检查后的状态、实际 URL、回退、原始与规范化输入的字节数、条目数和 SHA-256;DLC 另记录检出的 commit。它不包含本仓库维护的自定义源(包括 `sources/custom/domain/fakeip-filter.list`),也不覆盖完整转换链或 HTTP 响应身份,因此仍不是完整来源证明。`fakeip-filter` 与其他自定义规则共用同一构建入口,没有独立下载步骤。 +规则文件使用 `.list` 扩展名,文件名只使用小写字母、数字和连字符。 -`build-summary.json` 是成功构建事务的固有输出:产物守卫通过后、manifest 生成前,由 `build-artifacts-transaction.sh` 在事务 artifact root 中生成。manifest 同时记录摘要文件 SHA-256 与解析后的嵌入内容,发布前验证两者。工作流的 `Show summary` 步骤只负责显示成功输出,或在失败诊断场景中临时生成可读摘要,不定义成功产物。 +```text +DOMAIN,api.example.com +DOMAIN-SUFFIX,example.com +IP-CIDR,192.0.2.0/24 +``` -许可状态完全由维护者人工核验。自动化不解析许可文档,也不会根据“未知”状态自动阻断。 +不同文件允许重叠,以便绑定不同策略;同一文件内的重复、无效格式或被宽规则覆盖的条目会被检查拒绝。 -## 测试约定 +新增上游时修改 `config/upstreams.json`,并按实际情况更新根目录的 `THIRD_PARTY_NOTICES.md`。 -输出行为有意变化时,更新 `tests/fixtures/` 并新增或调整 `scripts/tests/test-*.sh`。测试运行器自动发现 `test-*.sh`。不要通过降低阈值、删除测试或跳过守卫掩盖异常。 +## 自动构建 -## 文档导航 +- PR:只运行快速检查。 +- `main`:检查、构建并发布五个平台分支。 +- 定时任务:每天同步一次上游。 +- 手动运行:Actions → Sync Rules,可选择 `auto`、`custom` 或 `full`。 -- [`README.md`](../README.md):用户入口、平台示例和关键边界 -- [`CONTRIBUTING.md`](../CONTRIBUTING.md):自定义规则格式与修改说明 -- [`docs/README.md`](README.md):文档职责与阅读路径 -- [`docs/DEVELOPMENT.md`](DEVELOPMENT.md):环境、命令和开发流程 -- [`docs/STRUCTURE.md`](STRUCTURE.md):构建、产物、守卫和发布结构 -- [`docs/TROUBLESHOOTING.md`](TROUBLESHOOTING.md):常见失败与定位步骤 -- [`SECURITY.md`](../SECURITY.md):安全支持范围和私密报告 -- [`NOTICE`](../NOTICE) / [`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md):许可范围与第三方状态 +构建失败时,先查看 Actions 日志中最早出现的错误。常见原因是规则格式错误、上游不可访问、上游条目数量异常或工具下载失败。 diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 8be4e47f3..000000000 --- a/docs/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# 文档索引 - -本目录保存实现与维护文档;根目录 `README.md` 仍是规则使用入口。 - -## 文档职责 - -- [开发指南](DEVELOPMENT.md):受支持环境、工具依赖、本地命令和开发流程。 -- [仓库结构](STRUCTURE.md):同步、构建、审计文件、守卫和发布分支的真实边界。 -- [故障排查](TROUBLESHOOTING.md):按症状定位构建、产物与客户端问题。 -- [贡献指南](../CONTRIBUTING.md):自定义规则格式和修改说明。 -- [`NOTICE`](../NOTICE) 与 [第三方声明](../THIRD_PARTY_NOTICES.md):MIT 适用范围和第三方核对状态。 -- [安全政策](../SECURITY.md):安全问题与普通质量问题的分界及私密报告渠道。 - -事实冲突时,以脚本、配置和工作流当前实现为准,并修正文档;许可结论只能由维护者基于可核验材料人工评审,不能从自动化结果推导。 - -## 文档导航 - -- [`README.md`](../README.md):用户入口、平台示例和关键边界 -- [`CONTRIBUTING.md`](../CONTRIBUTING.md):自定义规则格式与修改说明 -- [`docs/README.md`](README.md):文档职责与阅读路径 -- [`docs/DEVELOPMENT.md`](DEVELOPMENT.md):环境、命令和开发流程 -- [`docs/STRUCTURE.md`](STRUCTURE.md):构建、产物、守卫和发布结构 -- [`docs/TROUBLESHOOTING.md`](TROUBLESHOOTING.md):常见失败与定位步骤 -- [`SECURITY.md`](../SECURITY.md):安全支持范围和私密报告 -- [`NOTICE`](../NOTICE) / [`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md):许可范围与第三方状态 diff --git a/docs/STRUCTURE.md b/docs/STRUCTURE.md deleted file mode 100644 index 1b0025e84..000000000 --- a/docs/STRUCTURE.md +++ /dev/null @@ -1,84 +0,0 @@ -# 仓库结构 - -本文件描述同步、构建、守卫和发布实现,不承担客户端配置教程或许可结论。 - -## 顶层职责 - -| 路径 | 职责 | -| --- | --- | -| `sources/custom/` | 自有域名规则及可选 IP 规则 | -| `config/` | 上游端点、首批健康基线、平台能力、自定义规则精确冲突关系和二进制工具 lock | -| `scripts/commands/` | 同步、恢复、构建、守卫和发布入口 | -| `scripts/lib/` | 下载、工具缓存和渲染共享函数 | -| `scripts/tools/` | Python 解析、规范化、校验与摘要工具 | -| `scripts/tests/`、`tests/fixtures/` | 自动测试与稳定夹具 | -| `templates/branch-readmes/` | 发布分支 README 模板及随发布树携带的 v2fly MIT 充分通知 | -| `.output/` | 构建产物及部分审计摘要 | -| `.output/.canonical/` | 事务内保留的 domain/IP 规范编译输入,只用于跨平台语义校验,不进入发布分支 | -| `.tmp/` | 可清理临时工作区 | -| `.bin/` | 外部工具及版本缓存 | -| `.artifacts/` | 失败构建保留的诊断摘要;属于可清理的本地/CI 数据,不进入发布分支 | - -## 构建范围 - -完整范围依次同步主上游、写入 `.output/.canonical/`、构建自定义规则、执行产物守卫(artifact guard),再上传并发布。自定义范围从五个发布分支恢复同一发布 cohort;旧 cohort 没有 canonical 状态时先从 Egern 文本产物重建,再用本次自定义源覆盖相应规范输入并重建产物。工作流没有独立的 Fake-IP 同步步骤。 - -`fakeip-filter` 当前源为本仓库维护的 `sources/custom/domain/fakeip-filter.list`,由 `build-custom.sh` 与其他自定义规则一起生成五平台形式,不从网络下载预编译文件。`config/upstreams.json` 覆盖主上游网络输入;工具资产下载另由工具 lock 控制。 - -`main` 是唯一长期源码与发布源分支;日常修改可直接提交或使用临时分支。发布分支为 `surge`、`quanx`、`egern`、`sing-box`、`mihomo`,只允许生成的 `README.md`、`domain/`、`ip/` 及平台对应扩展名。各分支 `README.md` 由 `templates/branch-readmes/` 生成,并直接包含 v2fly/domain-list-community 的完整 MIT 版权与许可通知;因此发布树无需新增独立许可证文件。模板变更属于构建触发路径。 - -## 审计文件 - -- `.output/upstream-summary.json`:主同步在健康检查后记录名称、实际 URL、状态、回退、临时路径、原始与规范化内容的字节数、条目数和 SHA-256;DLC 另含检出的 commit。 -- `.output/domain/rule-manifest.json`:域名列表、区域集合和属性派生结构。 -- `.output/build-summary.json`:GitHub Actions 在产物守卫之后、规范发布清单之前扫描 `.output/` 生成。 -- `.output/.canonical/{domain,ip}/`:规范化、去重后的平台无关规则集合。它是五个平台语义验证的唯一比较基准;manifest 记录验证结果,但不会将该目录列为发布产物。 -- `.output/artifact-manifest.json`:schema v4 规范发布清单,包含 generation/build/source/build scope、完整发布基线(整体状态以及各分支 commit/generation/source)、能力与工具 lock 摘要、工具 provenance metadata、可用的上游/构建摘要,以及每个可发布 domain/ip 文件的平台、类型、扩展名、字节数、SHA-256 和可判定来源。JSON 键与产物按稳定顺序输出;generation/build id 由调用方提供,因此相同输入和 id 可复现相同内容。 -- `.tmp/**/normalize-tasks.json`:批处理任务描述,属于临时数据。 -- `.artifacts/diagnostics//`:失败事务保留的 `transaction-health.json` 及可用的构建/上游摘要;CI 日志只展示白名单内且大小受限的 JSON,完整诊断作为短期 Actions artifact 上传。 - -`verify-artifact-manifest.sh` 严格重算能力矩阵允许的完整文件集合、路径层级与安全性、非零大小、字节数和 SHA-256,并核对能力/lock 摘要及可选的预期 source SHA。Surge、Quantumult X、Egern、sing-box 和 Mihomo 都会按各自能力过滤规则类型,再与 `.output/.canonical/` 比较等价语义集合;域名后缀覆盖和 CIDR 并集合并允许编译器消除冗余,但值替换、扩大或丢失范围会失败。缺少任一应有平台副本、存在没有 canonical 来源的额外产物,或为只含该平台不支持规则的空集合生成文件,同样失败。清单同时记录读回方法、计数和语义 SHA-256。 - -发布作业下载后再次验证;`publish-branches.sh` 自身也必须先验证清单,拒绝缺失、额外、被修改或重放的产物。清单只作为流水线审计输入,不复制到发布分支。一次发布中五个分支提交携带共同 generation id 和 source SHA;任一平台 tree 改变时完整 cohort 原子推进并保留各分支父历史,全部 tree 不变时在重新读取远端 cohort 后整体跳过。自定义范围以最近一次一致发布 cohort 的 source 为累计比较基准,而不是只比较 `HEAD^`,因此连续的文档提交不会掩盖此前未发布的规则改动。候选 source/generation 不得早于远端基线;准备前、推送前和推送后均检查远端 `main`,五个产物 ref 使用带预期 SHA lease 的原子推送。Git 协议无法把未变化的 `main` ref 纳入同一次 compare-and-swap;若推送产物后发现 `main` 已前进,本次运行会明确失败,由当前 `main` 的排队运行继续推进。 - -`scripts/tools/artifact_origins.py` 是 `artifact-origins.json` 的唯一写入口:完整同步重置为 `generated-upstream`,发布分支恢复重置为 `restored-published-branch`,自定义构建只重标本次控制且实际存在的目标,并清除对应平台已经删除或降级省略的旧记录。 - -`config/domain-platform-capabilities.json` 是平台 branch、extension、format、rule mapping、empty policy、compiler 与 verifier 的唯一结构化来源。`scripts/tools/platform_capabilities.py` 严格加载并校验实现标识,同时向 Python 消费者提供查询对象、向 shell 消费者生成稳定的 tab-separated registry。IP 渲染、构建/守卫的安全循环、摘要和发布均查询该 registry;声明未知实现时构建会 fail closed。公开分支名仍由能力文件中的 `branch` 字段固定。 - -`upstream-summary.json` 不是完整来源追溯记录:它不覆盖自定义源(包括 `fakeip-filter`)、全部转换步骤或 HTTP 响应身份。上述文件也都不是许可证证明。 - -## 名称冲突检查 - -`build-custom.sh` 根据 `RULES_CONFLICT_BASE_SHA`(可用时)或 `HEAD^` 判断自定义源是否为新增。只有新增源会检查五个平台当前 `.output/` 中同类型目标是否已经存在:domain 只对 domain,ip 只对 ip。 - -因此该检查不覆盖既有自定义源修改、未出现在当前 `.output/` 的潜在未来上游名称,也不禁止 domain 与 ip 使用同一名称。它是防覆盖措施,不是全局命名守卫。 - -共享解析器先验证 canonical 类型和值,并检查同一自定义文件内的重复或覆盖关系。不同文件允许按策略需要有意重叠。`build-custom.sh` 在生成产物前运行该阶段。 - -## 产物守卫(artifact guard)范围 - -当前产物守卫(artifact guard)包括: - -- 五个平台 domain 和 ip 的最低文件数量; -- 五个平台冗余域名属性派生文件名; -- 基线分支可用且未命中特定兼容跳过条件时,Surge、Quantumult X、Egern 文本域名规则相对发布分支的下降检查; -- Surge 和 Quantumult X 文本 IP 的地址族及非 `private` 非公网 CIDR 检查; -- 两个平台部分内置 IP 集的总数与 IPv4/IPv6 最低值; -- Surge 上部分内置 IP 集相对基线的增长或删除检查。 - -artifact guard 本身不执行五平台 canonical 语义比较;该检查由随后生成和复验 manifest 的阶段执行,其中 `.srs` / `.mrs` 使用锁定工具真实读回。两者都不审查许可。发布脚本另行检查发布树、扩展名和本地产物完整性。 - -## 工具缓存与清理 - -sing-box 和 mihomo 只按 `config/tools-lock.json` 固定版本、tag commit 和 Linux `amd64` / `arm64` 资产下载到 `.bin/`。归档解包前必须匹配 lock 中的 SHA-256。每个缓存二进制都有原子替换的 provenance sidecar,记录 lock commit、资产与归档摘要、二进制摘要和版本探针;命中缓存时会重新核对 sidecar 的完整字段、二进制 SHA 和实时版本输出,不可信缓存会被重新下载替换。工作流缓存键以缓存格式版本开头,并包含两个工具版本、平台和 lock 摘要。该校验是 GitHub release asset digest 锁定,不是发布者签名。`make clean` 保留可信工具缓存,只移除未完成下载与 metadata 临时文件、生成产物、临时目录和 Python 缓存。 - -## 文档导航 - -- [`README.md`](../README.md):用户入口、平台示例和关键边界 -- [`CONTRIBUTING.md`](../CONTRIBUTING.md):自定义规则格式与修改说明 -- [`docs/README.md`](README.md):文档职责与阅读路径 -- [`docs/DEVELOPMENT.md`](DEVELOPMENT.md):环境、命令和开发流程 -- [`docs/STRUCTURE.md`](STRUCTURE.md):构建、产物、守卫和发布结构 -- [`docs/TROUBLESHOOTING.md`](TROUBLESHOOTING.md):常见失败与定位步骤 -- [`SECURITY.md`](../SECURITY.md):安全支持范围和私密报告 -- [`NOTICE`](../NOTICE) / [`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md):许可范围与第三方状态 diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md deleted file mode 100644 index 793f14976..000000000 --- a/docs/TROUBLESHOOTING.md +++ /dev/null @@ -1,86 +0,0 @@ -# 故障排查 - -先处理日志中最早的错误,并对照 [开发指南](DEVELOPMENT.md) 的环境边界。 - -## `make validate` 失败 - -- `shellcheck not found`:本地默认可跳过,CI 强制要求;安装后重试。 -- Python 编译失败:确认 `python3 --version` 为 3.11 或更高版本,再修复首个语法错误。 -- 配置失败:检查 HTTPS URL、正整数阈值、必需项和支持的枚举。 -- 自定义规则失败:处理非 canonical 类型/值、同文件内的 domain 精确项/后缀覆盖、IP 重复/包含、正则或 CIDR 规范问题。不同文件之间允许按策略需要重叠。 -- 测试失败:运行 `bash scripts/tests/test-*.sh` 中对应的脚本,再检查夹具是否应有意更新。 - -## `make check-runtime` 失败 - -本地命令要求 `PATH` 解析到 Bash 5+ 和 Python 3.11+。macOS 应优先使用 Homebrew 安装的版本;若 `python@3.11` 已安装但仍解析到系统 Python,把 `$(brew --prefix python@3.11)/libexec/bin` 放到 `PATH` 前部。分别运行 `bash --version`、`python3 --version` 和 `command -v bash python3`,确认没有落回系统旧版本。 - -若错误提示 `cross-device artifact promotion refused` 或 `cross-device rename refused`,应把 `RULES_LIVE_ARTIFACT_ROOT` 改到仓库所在文件系统。事务的预检与最终严格 rename 都不会通过跨设备复制模拟原子目录提升。若日志提示 `transaction recovery data preserved`,不要删除所示目录;其中的 `previous-output` 是自动恢复失败后保留的旧 live tree。 - -## 原生 Windows 构建失败 - -sing-box/mihomo 下载逻辑会在需要获取新工具时拒绝原生 Windows。请使用 WSL、Linux 或 GitHub Actions。Git Bash 不属于完整支持环境,不能因文本目标偶尔可运行而推断二进制构建受支持。 - -## 文本成功但二进制失败 - -`make build-custom-text` 不下载编译器。检查网络、GitHub Release 可用性、`amd64` / `arm64` 架构和 `.bin/` 缓存后运行: - -```bash -make build-custom -``` - -若日志报告 checksum mismatch,停止并核对 `config/tools-lock.json` 与官方 GitHub Release 资产,不要绕过校验。缓存命中还会检查 provenance sidecar、二进制 SHA-256 和版本探针;校验失败时会自动重新下载。该机制验证固定资产摘要,但不等同于发布者签名。 - -## `make clean` 后工具仍存在 - -这是预期行为。清理会删除 `.tmp/`、`.output/`、`.artifacts/`、Python 缓存及 `.bin/*.new*`,但保留已缓存的 sing-box、mihomo 和 provenance sidecar。若需要强制重新下载,应人工删除对应二进制及其 `.provenance.json`;不要提交 `.bin/`。 - -## 自定义名称冲突 - -冲突检查只针对相对基准新加入的自定义源,并在同一 domain/ip 类型内检查当前 `.output/` 的五平台目标。报错时重命名新增规则,不要删除恢复或同步得到的产物。 - -既有自定义源修改、domain 与 ip 同名、当前产物中尚不存在的未来上游名称不在同一检查范围内,仍需人工审查。 - -## `emby-cn` 未按预期命中 - -确认 `emby-cn` 位于 `emby` 之前,并绑定不同策略;反向加载会让宽泛规则先命中。 - -## 上游同步或条目异常 - -1. 对照 `config/upstreams.json` 检查主 URL、回退、解析器和阈值。 -2. 成功事务查看 `.output/upstream-summary.json`;失败事务查看 `.artifacts/diagnostics//` 中保留的 upstream/transaction health 报告。失败时 `.output/` 仍是事务开始前的完整树,不会包含部分下载、渲染或编译结果。 -3. 成功后查看 `.output/domain/rule-manifest.json` 定位属性派生。 -4. 对照基线和发布分支判断变化是否预期。 - -CI 的失败事务会把 `.artifacts/diagnostics/` 上传为保留 7 天的 diagnostics artifact。若日志被截断,优先下载对应 artifact;仅文档或治理文件的 PR 不运行外部上游同步。 - -该摘要不包括本仓库维护的自定义源(包括 `sources/custom/domain/fakeip-filter.list`),也没有完整转换链或 HTTP 响应身份,不能单独作为完整来源追溯记录或许可依据。`fakeip-filter` 应由 `build-custom.sh` 生成;若日志出现独立同步或预编译下载,应视为回归。 - -## 找不到 `build-summary.json` - -独立运行 `make build-custom*` 不生成它;请运行 `build-artifacts-transaction.sh`。成功事务会在产物守卫之后、manifest 之前生成并绑定该摘要。工作流的 `Show summary` 只显示成功输出,或在失败诊断时临时生成可读摘要;失败时 `.output/` 仍保留上一次成功事务。 - -## 产物守卫(artifact guard)阻断 - -检查最低文件数、冗余派生名、文本域名下降、Surge/Quantumult X 文本 IP 合法性和部分内置 IP 基线。随后 manifest 阶段会解析或真实读回五个平台产物,并与 `.output/.canonical/` 中的平台无关规范规则集合精确比较。只有在来源证据、测试和评审说明齐全时才调整阈值。 - -## 许可状态不明 - -自动化不会发现或阻断许可问题。停止相关内容的合并或发布,由维护者对照 `NOTICE`、`THIRD_PARTY_NOTICES.md`、上游许可证和条款人工评审。CI 通过不构成授权。 - -## 客户端问题 - -- 404:核对分支、domain/ip 类型、规则名和固定扩展名。 -- Quantumult X 策略不存在:用 `filter_remote` 的 `force-policy` 绑定本地策略。 -- mihomo 缺少 domain `.mrs`:只有关键词或正则的列表会因当前降级边界而不发布。 -- 内容未更新:检查发布分支提交、工作流状态和客户端缓存周期。 - -## 文档导航 - -- [`README.md`](../README.md):用户入口、平台示例和关键边界 -- [`CONTRIBUTING.md`](../CONTRIBUTING.md):自定义规则格式与修改说明 -- [`docs/README.md`](README.md):文档职责与阅读路径 -- [`docs/DEVELOPMENT.md`](DEVELOPMENT.md):环境、命令和开发流程 -- [`docs/STRUCTURE.md`](STRUCTURE.md):构建、产物、守卫和发布结构 -- [`docs/TROUBLESHOOTING.md`](TROUBLESHOOTING.md):常见失败与定位步骤 -- [`SECURITY.md`](../SECURITY.md):安全支持范围和私密报告 -- [`NOTICE`](../NOTICE) / [`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md):许可范围与第三方状态 diff --git a/scripts/commands/guard-artifacts.sh b/scripts/commands/guard-artifacts.sh index 86cc8a473..8588715d3 100755 --- a/scripts/commands/guard-artifacts.sh +++ b/scripts/commands/guard-artifacts.sh @@ -156,7 +156,7 @@ check_no_redundant_attr_filter_artifacts() { while IFS=$'\t' read -r platform _public _branch section _extension _format _empty _compiler _verifier; do [ "$section" = domain ] || continue check_no_redundant_attr_filter_artifacts_in_dir "$ARTIFACT_ROOT/domain/$platform" "domain/$platform" - done < <(capability_registry) + done <<< "$CAPABILITY_REGISTRY" } count_domain_rules_from_file() { @@ -538,7 +538,7 @@ main() { while IFS=$'\t' read -r platform _public _branch section extension _format _empty _compiler _verifier; do if [ "$section" = domain ]; then min_expected=1000; else min_expected=10; fi check_min_files "$ARTIFACT_ROOT/$section/$platform" "$ARTIFACT_ROOT/$section/$platform/*.${extension}" "$min_expected" - done < <(capability_registry) + done <<< "$CAPABILITY_REGISTRY" # Minimum 10 covers the guaranteed sources: # cn, private, google, telegram, cloudflare, cloudfront, aws, fastly, github, apple. # Streaming services (netflix, spotify, disney) are best-effort via RIPE NCC diff --git a/scripts/commands/publish-branches.sh b/scripts/commands/publish-branches.sh index e4cbfab6d..4d0416ccd 100755 --- a/scripts/commands/publish-branches.sh +++ b/scripts/commands/publish-branches.sh @@ -14,8 +14,7 @@ CAPABILITY_REGISTRY="$(python3 "$ROOT/scripts/tools/platform_capabilities.py" sh PUBLISH_BRANCH_NAMES=(surge quanx egern sing-box mihomo) ARTIFACT_SOURCE_SHA="${ARTIFACT_SOURCE_SHA:-}" "$ROOT/scripts/commands/verify-artifact-manifest.sh" -read -r MANIFEST_GENERATION_ID MANIFEST_SOURCE_SHA MANIFEST_BASELINE_STATUS MANIFEST_BASELINE_SOURCE < <( - python3 - <<'PY' "$MANIFEST_FILE" +manifest_identity="$(python3 - <<'PY' "$MANIFEST_FILE" import json, sys manifest = json.load(open(sys.argv[1], encoding="utf-8")) print( @@ -25,7 +24,8 @@ print( manifest["baseline"]["source_commit"] or "-", ) PY -) +)" +read -r MANIFEST_GENERATION_ID MANIFEST_SOURCE_SHA MANIFEST_BASELINE_STATUS MANIFEST_BASELINE_SOURCE <<< "$manifest_identity" refresh_and_validate_remote_baseline() { local metadata_file branch commit subject generation source @@ -221,7 +221,9 @@ has_allowed_extension() { assert_branch_layout() { local domain_extensions="$1" local ip_extensions="$2" - local file rel + local file rel file_list + file_list="$(mktemp)" + find domain ip -type f -print0 > "$file_list" [ -f "README.md" ] || { echo "missing publish file: README.md" >&2 @@ -246,7 +248,8 @@ assert_branch_layout() { fi echo "unexpected file in publish tree: $rel" >&2 exit 1 - done < <(find domain ip -type f -print0) + done < "$file_list" + rm -f "$file_list" } cleanup_tempdir() { diff --git a/scripts/commands/select-build-scope.sh b/scripts/commands/select-build-scope.sh index db8c36b3c..7eb78b8be 100755 --- a/scripts/commands/select-build-scope.sh +++ b/scripts/commands/select-build-scope.sh @@ -159,13 +159,13 @@ load_publication_baseline() { if [ "$baseline_loaded" -eq 1 ]; then return 0 fi + local baseline_values if [ -n "$BASELINE_INPUT_FILE" ]; then - read -r baseline_status baseline_generation baseline_source < <( - validate_and_write_baseline "$BASELINE_INPUT_FILE" "$BASELINE_FILE" - ) + baseline_values="$(validate_and_write_baseline "$BASELINE_INPUT_FILE" "$BASELINE_FILE")" else - read -r baseline_status baseline_generation baseline_source < <(resolve_remote_baseline) + baseline_values="$(resolve_remote_baseline)" fi + read -r baseline_status baseline_generation baseline_source <<< "$baseline_values" baseline_loaded=1 echo "Publication baseline: status $baseline_status, generation $baseline_generation, source $baseline_source" @@ -222,7 +222,7 @@ has_build_relevant_changes() { } has_only_non_build_changes() { - ! grep -Eqv '^(\.github/(CODEOWNERS$|ISSUE_TEMPLATE/|dependabot\.yml$|pull_request_template\.md$)|\.gitignore$|CONTRIBUTING\.md$|LICENSE$|NOTICE$|README\.md$|SECURITY\.md$|THIRD_PARTY_NOTICES\.md$|docs/)' + ! grep -Eqv '^(\.gitignore$|LICENSE$|NOTICE$|README\.md$|THIRD_PARTY_NOTICES\.md$|docs/)' } if [ "$EVENT_NAME" != "pull_request" ]; then diff --git a/scripts/lib/common.sh b/scripts/lib/common.sh index 4f3602562..1816fa2a6 100644 --- a/scripts/lib/common.sh +++ b/scripts/lib/common.sh @@ -199,8 +199,8 @@ tool_cache_is_trusted() { archive_sha="$(tool_lock_value "$tool" sha256 "$platform")" locked_binary_sha="$(tool_lock_value "$tool" binary_sha256 "$platform")" || return 1 - if ! IFS=$'\t' read -r binary_sha recorded_probe < <( - python3 - "$sidecar" "$tool" "$version" "$tag_commit" "$platform" "$asset" "$archive_sha" <<'PY' + local provenance_values + if ! provenance_values="$(python3 - "$sidecar" "$tool" "$version" "$tag_commit" "$platform" "$asset" "$archive_sha" <<'PY' import json import re import sys @@ -232,9 +232,10 @@ try: except (OSError, KeyError, TypeError, ValueError, json.JSONDecodeError): raise SystemExit(1) PY - ); then + )"; then return 1 fi + IFS=$'\t' read -r binary_sha recorded_probe <<< "$provenance_values" actual_sha="$(sha256_file "$binary")" [ "$actual_sha" = "$locked_binary_sha" ] || return 1