作者署名头——逐文件 SPDX 许可行
使用规范的单行头部,以每种文件类型相应的注释语法,定义并强制执行逐文件的 SPDX 许可标识符标记。
面向下游贡献者的规范性参考。 本文档镜像项目规范的作者署名与文件头章节(规范 §0.5 + §4.6);它是随发布仓库一同提供的独立参考。架构理由记录于 ADR-0002。
1. 规范头部行
生态系统中每个适用文件都必须以单行规范 SPDX 许可标识符行开头,并采用其文件类型族的注释语法。该行是文件的机器可读许可标记;对于非豁免文件,其存在是不可协商的,其内容由单一事实来源治理,而非逐文件即兴编写。完整的版权法律文书在仓库根目录的 LICENSE 文件中只保留一份——它不会复制到每个源文件中。
1.1 信息内容(不变量)
规范内容正好是一行:
SPDX-License-Identifier: MIT— 按 FSFE 维护的 REUSE 规范定义的机器可读许可标记;可被 SPDX 工具链(reuse lint、scancode)、Linux 内核工具以及下游许可扫描器无歧义地解析。它不携带任何可视边框,也不携带逐文件的版权、网站、邮箱或 GitHub 行——逐文件溯源就是这一行 SPDX,这是有意为之的设计(见 §4)。
1.2 参考形式(# 注释族)
规范文本——此处以其 # 注释语法形式书写——其事实来源在 src/apothem/schemas/authorship-header.txt:
# SPDX-License-Identifier: MIT此文本是唯一权威来源。file-header 验证器(§7)针对此字节精确的固定样本运行。文件头行与此固定样本之间的任何漂移(在 §2 的语法替换之下)都是 CI 失败。
2. 逐文件类型变体(字节精确)
该行的信息内容是不变的;只有其注释语法随文件类型而变化。完整的逐文件类型变体表:
| 文件类型族 | 注释语法 | 变体渲染 |
|---|---|---|
# 族 — .sh、.bash、.zsh、.py、.rb、.pl、.ps1、.yml、.yaml、.toml、.cff、.gitignore、.gitattributes、.editorconfig、.shellcheckrc、.env.example、Makefile、Dockerfile、Procfile、CODEOWNERS、PKGBUILD,以及诸如 scripts/apothem 的无扩展名 shell 入口点 | # 行注释 | # SPDX-License-Identifier: MIT |
// 族 — .js、.jsx、.mjs、.cjs、.ts、.tsx、.go、.rs、.java、.kt、.swift、.c、.cc、.cpp、.h、.hpp、.cs、.scala、.dart、.jsonc | // 行注释 | // SPDX-License-Identifier: MIT |
块注释族 — .html、.htm、.md、.markdown、.xml、.vue(模板区域)、.php(模板区域) | <!-- ... --> | <!-- SPDX-License-Identifier: MIT --> |
MDX(.mdx) | {/* ... */}(JSX 表达式注释) | {/* SPDX-License-Identifier: MIT */} |
C 块族 — .css、.scss、.less、.sql(/* */) | /* ... */ | /* SPDX-License-Identifier: MIT */ |
; 族 — .ini、.cfg、部分 .lisp/.scm | ; 行注释 | ; SPDX-License-Identifier: MIT |
-- 族 — .sql、.lua、.hs、.elm、.ada | -- 行注释 | -- SPDX-License-Identifier: MIT |
| 锁文件 / 生成文件 / JSON | 无 / 不适用 | 豁免。 见 §3 例外清单。 |
Markdown 变体(规范渲染):
<!-- SPDX-License-Identifier: MIT -->HTML 注释(或 MDX {/* */})包装器以不可见方式渲染,因此渲染后的界面保持整洁,而源内许可标记在各文件类型间始终保持机器可读。
3. 例外清单(按类别豁免)
以下类别豁免于 SPDX 头部行。file-header 验证器的适用性检查对这些返回 not-applicable:
LICENSE— 它本身就是法律文书;携带权威版权行,license-author-consistency验证器会确认其存在。*.svg资源 — XML 注释对行注释标记而言脆弱,因此 SVG 溯源由资源 README 和生成的栅格输出承载。CHANGELOG.md— 格式受约束的发行说明文档;SPDX 行作为单条 HTML 注释出现在变更日志标题之上,而不是交织进格式中。- JSON 文件(
.json) — JSON 没有注释语法。当 JSON 配置需要署名时,放置一个同级<file>.NOTICE.md。 - 锁文件 —
package-lock.json、yarn.lock、pnpm-lock.yaml、Cargo.lock、Pipfile.lock、poetry.lock、go.sum等(机器管理)。 - 生成文件 — 任何带有
# Generated by ...或// Generated by ...标记的文件,或任何匹配.gitattributeslinguist-generated=true的文件。 - 供应(vendored)的第三方内容 —
vendor/、third_party/、node_modules/下的文件。它们携带上游自身的许可/声明;在上游署名之上注入我们的标记是许可违规。 .audit/文件 — 被 gitignore 的临时文件;超出发布树范围。- 计划文件(
<project-root>/.apothem/plans/**,以及旧的<project-root>/.plans/**) — 被 gitignore 的临时文件;溯源是计划的 frontmatter(见plans-discipline.md§3)。 - 空标记 —
.keep、.gitkeep等(语义上零字节)。 - 任何种类的二进制文件。
例外清单本身在 src/apothem/schemas/header-exceptions.txt 中被编码为正则/glob 列表,并作为验证器适用性检查的输入。修订需要一次结构化询问和一份新的 ADR。
4. 许可交互
SPDX 行以机器可读方式声明项目的许可;LICENSE 文件以权威方式声明它:
SPDX-License-Identifier: MIT— 按 REUSE 规范和 SPDX 标准的机器可读许可标记。自动化许可扫描器直接解析此行;SPDX 表达式语法与reuse lint、scancode-toolkit、FOSSology 和 Linux 内核许可工具交叉兼容。
- 仓库根目录的
LICENSE— 权威的法律文书,携带完整的 MIT 条款和版权持有人。它是版权声明的唯一所在;逐文件头部通过共享的 SPDX 标识符隐式引用它,而不是在每个文件中重述版权。
单行形式。 逐文件溯源就是这一行 SPDX;版权文书在根 LICENSE 中只保留一份。带边框的多行横幅框(版权、网站、邮箱、联系行包裹在一个划线框架中)被验证器拒绝:它们在每个文件中复制联系方式和版权元数据,却没有添加任何机器可读许可标记尚未向 REUSE/SPDX/SBOM 工具提供的东西。src/apothem/schemas/authorship-header.txt 处的字节精确固定样本携带单行形式;验证器针对此固定样本运行。
交叉引用。 LICENSE 文件(MIT)——在冲突情形下以法律文书为准。ADR-0006 记录横幅收窄批准理由。
5. 插入位置
- SPDX 行是文件的第一项内容,仅有一个例外:shebang 行(
#!/usr/bin/env bash、#!/usr/bin/env python3等),它始终保持在第 1 行;SPDX 行从第 2 行开始。 - 对于带有 YAML frontmatter 的 Markdown / MDX 文件,SPDX 注释位于最顶端,YAML frontmatter 随后,然后是 H1 和正文。渲染后的输出以一条不可见的注释开头,然后由工具解析 frontmatter,再之后是可见内容。
- 单个空行将 SPDX 行与下一项内容(frontmatter
---、shebang 的后继行、H1 等)分隔开。
6. 头部可见性策略
具体到 Markdown 文件,SPDX 行默认不可见——包裹在 <!-- ... -->(或 MDX 的 {/* */})中,仅在源中可见。这是 README、CONTRIBUTING、CLAUDE.md、受支持的harness指令文件、技能 SKILL.md、命令正文、output-styles 以及文档页的正确策略。可见渲染(SPDX 行作为输出顶部的纯文本或围栏块)对那些受益于即时可读溯源的独立参考文档是允许的;该策略按文件类别在 src/apothem/schemas/header-visibility.yaml 中设置(默认不可见),并允许在该行之后紧接一个文件作用域覆盖标记 <!-- header-visibility: visible -->。
7. 注入器——scripts/inject-header.{sh,py}
一个确定性 CLI,它:
- 接受一个或多个文件路径(或 glob)。
- 通过例外清单(§3)确定适用性。
- 检测现有头部状态(规范 / 畸形 / 缺失),剥离它发现的任何非规范横幅块,使重新运行具有幂等性。
- 按文件类型渲染正确的 SPDX 变体(§2)。
- 在正确位置插入(§5),尊重 shebang 和 frontmatter。
- 以三种模式运行:
fix-in-place(写入)、emit-patch(打印统一 diff)、check(在任何偏离时以非零退出——供 CI 使用)。 - 幂等:运行两次是无操作。
注入器由那些以预先插入的 SPDX 行来搭建新文件的 Make 目标(make headers-fix 和 make new-* 脚手架)以及处于 --fix 模式的预提交钩子调用。
8. 验证器——file-header(CI)
位于 src/apothem/conformity/file_header_grep.py。对于工作树中的每个文件,验证器查找其适用性(按 §3),若适用,则断言规范 SPDX 行存在于文件头部——位于所有其他内容之前,唯一允许的前置内容是 shebang(§5)。
由 src/apothem/schemas/authorship-header.txt 处的字节精确固定样本支撑。在 CI 摘要中报告逐文件 diff 和聚合覆盖率 %。在任何偏离时使构建失败。
9. 自我强制机制
该纪律必须在每一个未来会话和每一位未来贡献者中存续。强制性的强制执行界面:
src/apothem/schemas/authorship-header.txt— 字节精确的规范固定样本;唯一事实来源。scripts/inject-header.{sh,py}— 机械注入器(§7)。file-headerCI 验证器(§8)——在任何偏离时使构建失败。- 预提交钩子 — 在暂存文件上以
--fix运行验证器,接入注入器。 CLAUDE.md强制行为块 — 指示助手在创建适用文件时注入规范 SPDX 行。- 位于规范
.github/路径的受支持的harness指令文件 — 指示harness运行时在文件生成时做同样的事。 - PreToolUse 钩子 位于
src/apothem/hooks/messages/pretooluse-{write,edit}-header-guard.md— 拦截对适用路径的 Write/Edit 工具调用,使 SPDX 行在文件创建时注入,而不是稍后作为 CI 失败被发现。 - PR 模板复选框 — 面向贡献者的断言,确认每个新文件都携带规范 SPDX 行。
- 本文档(
site/content/docs/reference/authorship-header.mdx)——规范的、规范性的说明文。
另见
- ADR-0002 — 架构理由、所考虑的替代方案。
- ADR-0006 — 横幅收窄批准。
src/apothem/schemas/authorship-header.txt— 字节精确的规范固定样本。src/apothem/schemas/header-exceptions.txt— 例外清单(正则/glob 形式)。scripts/inject-header.py和scripts/inject-header.sh— 注入器。src/apothem/conformity/file_header_grep.py— 验证器。- 项目规范 §0.5 + §4.6 — 此处镜像的规范文本。