MemHub 第三方依赖许可证治理:THIRD_PARTY_NOTICES.md 的生成机制、内容解读与发布流水线

发布时间:2026/10/20 1:24:51
MemHub 第三方依赖许可证治理:THIRD_PARTY_NOTICES.md 的生成机制、内容解读与发布流水线
【免费下载链接】Hy-Memory项目地址https://gitcode.com/gh_mirrors/hy/Hy-Memory点击查看免费下载MemHub本仓库memhub/目录下的多端内存应用套件在发布时不仅交付功能代码还会随包附带一份合规清单THIRD_PARTY_NOTICES.md逐一记录自身许可证、打包进运行时的第三方依赖及其许可证文本。本文以 THIRD_PARTY_NOTICES.md 为线索完整解读这份文档的章节结构并深入其背后由 generate_sbom.py 实现的“从已安装依赖树自动生成、人工禁止手改”的 SBOM/声明体系说明它如何接入pnpm release:check、运行时打包与公开发布门禁。读完本文你将理解 MemHub 如何保证“声明与真正随包分发的内容永远一致”并掌握重新生成、校验与发布该文档的完整操作路径。一、文档定位一份“禁止手改”的运行时依赖声明文档开篇即给出三条关键事实MemHub 自身采用 Apache-2.0 许可参见仓库根目录的 LICENSE生成脚本会直接读取该文件内容来判断许可证见下文第五节它随包捆绑bundles了下述运行时依赖因此需要向再分发者完整交代这些第三方组件的归属文档是由python3 scripts/generate_sbom.py在 2026-10-17T13:52:48Z 从“已安装依赖树”生成的并明确标注“Do not edit by hand”禁止手工编辑。这最后一条是整份文档的设计核心它刻意不采用人工维护的依赖清单而是每次从真实的虚拟环境与包管理器锁文件中重新推导从而避免声明与实际随包内容“悄悄漂移”generate_sbom.py 的模块 docstring 原文即指出“Both artifacts are derived from what is actually installed rather than from a hand-maintained list, so they cannot quietly drift away from the shipped app.”。文档还预告了一个重要策略当前阶段不逐包复制许可证原文license 列在发布审查release review时才填充在此之前配套的 SBOM 对每个第三方包记录NOASSERTION不声明而不是靠猜。这与《第四部分NOASSERTION 策略》中源码的“拒绝猜测”逻辑完全对应。二、内容解读文档的四个核心章节1. hy-memory 2.0.4Apache-2.0腾讯 Tencent文档第一段声明主体是hy-memory 2.0.4许可证为 Apache-2.0并附完整许可证文本。其版权声明明确指出腾讯Tencent向社区提供 Hy-MemoryHy-Memory 在 Apache-2.0 之外不施加任何额外限制该声明仅指腾讯依据 Apache-2.0 公开发布的代码、参数与权重。从源码看这段文本不是写死的模板generate_sbom.py的hy_memory_notice()L56-L91会定位apps/core/.venv中已安装的hy_memory-2.0.4.dist-info从其中的METADATA读取 Name/Version/License-Expression并读取licenses/LICENSE文件得到版权行与正文任何一项缺失或不匹配例如版本不是 2.0.4、许可证不是 Apache-2.0都会抛出SbomError使生成失败fail closed。测试 test_generate_sbom.py 也专门验证了“从 dist-info 取声明”与“缺失 dist-info 必须拒绝”两个行为。2. MemTensor memmy-agentadaptedMIT文档第二段声明MemTensor memmy-agent的适配版本上游固定提交pinned commit为25acd5f29fc7df73b943713abe61f1b2f9839887许可证为 MIT版权归 MemTensor2026-present并附完整 MIT 许可证文本。随后文档明确划出适配边界Adaptation boundarypackages/host-bridge/src/memmy-adapter/claude-code/是 Memmy Claude 集成的源码级适配为符合 One Memory 的授权与存储契约而被大幅重写完整的上游/适配边界记录在该包的PROVENANCE.md中。且不随包分发任何 Memmy 品牌、图标、字体或吉祥物资产。对应仓库实现事实适配代码位于 memmy-adapter/claude-code/含target.ts、install-plan.ts、hook-template.ts、event-adapter.ts、runtime.ts、session-state.ts、recall-trigger.ts等模块上游许可原文保留在 LICENSE.memmy并由license.ts在候选安装中嵌入同一份声明详细的上游/适配逐模块对照表如把上游的“子串删除目录替换”改为“精确属主条目、预览指纹、冲突拒绝与可逆日志”记录在 PROVENANCE.md生成脚本通过MEMMY_PIN 25acd5f29fc7df73b943713abe61f1b2f9839887L37固定该提交并在 SPDX 中为它单独建立SPDXRef-Package-memmy-agent-derived条目声明 MIT、filesAnalyzed: True通过CONTAINS关系挂到主包下。3. JavaScript (npm) — 10 个包文档以“ecosystem — 数量”作为小节标题完整列出 10 个运行时 npm 依赖版本号精确锁定包名版本包名版本tanstack/react-query5.103.2axios1.20.0fflate0.8.3https-proxy-agent7.0.0lucide-react1.43.0proxy-from-env2.1.0react19.2.8react-dom19.2.8tar7.5.22three0.185.1从这组清单可以读出 MemHub 桌面端/Web 端的技术栈轮廓React 19 渲染层、tanstack/react-query 数据请求、three 用于三维可视化、axios https-proxy-agent 处理网络代理、tar 用于归档处理。生成侧对应javascript_packages()L112-L131它执行pnpm list --prod --depth 0 -r --json获取生产依赖并主动跳过link:前缀的 workspace 内部链接包因此不会把 Monorepo 自己的包误报成第三方。4. Python (PyPI) — 126 个包文档列出的 PyPI 运行时依赖共 126 个对应python_packages()L134-L161——它用uv pip list --python apps/core/.venv/bin/python --format json读取受管虚拟环境中的全部包并剔除one-memory与hy-memory两个自有包后按名称排序。按功能可归类如下版本均以文档原文为准向量检索与图数据库chromadb 1.5.9、kuzu 0.11.3对应 Hy-Memory 的向量存储与图存储后端机器学习/Embedding 运行时numpy、scipy、scikit-learn、onnxruntime 1.23.2、tokenizers 0.23.1、tiktoken 0.14.0、huggingface-hub 1.29.0、hf-xet 1.6.0、mmh3 5.3.0、joblib、threadpoolctl中文分词与检索jieba 0.42.1、rank-bm25 0.2.2、langdetect 1.0.9、regex 2026.8.31Web/API 服务层fastapi 0.141.1、starlette、uvicorn 0.52.4、uvloop、httpx、httpcore、h11、httptools、openai 2.54.0、websockets 17.1、websocket-client、aiohttp 3.14.3及其配套aiohappyeyeballs、aiosignal、multidict、yarl、frozenlist、propcache数据库驱动aiomysql 0.3.2、pymysql 1.2.3、pypika 0.51.1序列化/校验orjson、json-repair、protobuf 7.36.0、flatbuffers、pyyaml、pydantic 2.13.5、pydantic-core、pydantic-settings、jsonschema、referencing、rpds-py、attrs、six、annotated-types可观测性OpenTelemetryopentelemetry-api、opentelemetry-sdk、opentelemetry-proto、opentelemetry-exporter-otlp-proto-common、opentelemetry-exporter-otlp-proto-grpc、opentelemetry-semantic-conventions均为 1.44.0 / 0.65b0CLI/日志/工具click、typer、rich、coloredlogs、humanfriendly、pygments、markdown-it-py、python-dotenv、keyring、oauthlib、requests-oauthlib、kubernetes 36.0.3、distro、shellingham打包与分发pyinstaller 6.22.2、pyinstaller-hooks-contrib、altgraph、macholib、setuptools 84.0.0、build、pyproject-hooks测试与质量pytest 9.1.1、pytest-xdist 3.8.0、execnet、mypy 2.3.1、ruff 0.16.5、pluggy、iniconfig、pathspec其他工具链tenacity 9.1.4、tqdm、zstandard、pybase64、bcrypt 5.0.0、grpcio 1.83.1、googleapis-common-protos、requests 2.34.2、urllib3 2.7.0、certifi、charset-normalizer、idna、filelock、fsspec、importlib-resources、more-itertools、jaraco-*系列、narwhals、overrides、typing-extensions、typing-inspection、jiter、watchfiles、mpmath、sympy、durationpy、cloudpickle、anyio、sniffio等。完整的 126 项逐条清单请直接查看 THIRD_PARTY_NOTICES.md 原文。三、生成机制generate_sbom.py如何从“已安装依赖树”推导两份工件memhub/scripts/generate_sbom.py是整份声明的唯一事实来源一次运行同时产出两个文件main()SBOM.spdx.jsonSPDX-2.3 格式的软件物料清单THIRD_PARTY_NOTICES.md本文主题文档。生成流水线如下枚举 JS 生产依赖pnpm list --prod --depth 0 -r --json工作区根目录执行跳过link:workspace 内部包枚举 Python 依赖uv pip list --python apps/core/.venv/bin/python --format json剔除one-memory与hy-memory读取 hy-memory 的已安装 wheel从.venv的hy_memory-2.0.4.dist-info读METADATA与licenses/LICENSE不猜测许可证判定项目自身许可证project_license()L176-L190直接读取 LICENSE 文本若包含 “Apache License / Version 2.0, January 2004” 则判定 Apache-2.0若为 MIT 文本则判定 MIT否则报错——文档中“命名一个仓库并未携带的许可证是 SBOM 绝不能犯的错误”正是这段代码的注释拼装 SPDX每个第三方包获得SPDXRef-Package-{ecosystem}-{name}唯一 ID 与pkg:npm/...或pkg:pypi/...的 purl 外部引用主包通过DEPENDS_ON关系指向所有运行时依赖通过CONTAINS指向 memmy 适配模块两份工件都成功后才落盘若任一步失败先前的文件不会被覆盖避免给发布门禁留下“半更新”的 SBOM。重生成命令在memhub/目录下即 package.json 中定义的脚本package.jsonpnpm sbom # 等价于 apps/core/.venv/bin/python scripts/generate_sbom.py前置条件apps/core/.venv已通过uv sync建立、pnpm依赖已安装、Python 版本 ≥ 3.10脚本入口有显式版本守卫见 L12-L16。四、NOASSERTION 策略与项目级许可证的防猜机制THIRD_PARTY_NOTICES.md明言“per-package license texts are not reproduced here yet; the license column is filled in as part of release review, and the SBOM recordsNOASSERTIONuntil then rather than guessing.”对应的 SPDX 构建逻辑在 build_spdx() 中清晰分层MemHub 自身one-memorylicenseConcluded/licenseDeclared来自project_license()的真实读取结果copyrightText为NOASSERTION126 个 PyPI 10 个 npm 第三方包licenseConcluded、licenseDeclared、copyrightText一律NOASSERTION代码注释解释这是“解析每个上游许可证文本是独立、需审查的步骤在此处声明任何许可证都等于猜测”hy-memory许可证与版权来自已安装 wheel 的真实元数据Apache-2.0memmy 适配模块MIT 与版权来自固定提交与LICENSE.memmy。这套“宁可写 NOASSERTION 也不猜”的策略将许可证审查刻意保留在发布审查release review这个人工环节避免自动化工具在缺少证据时擅自给出错误的合规结论。五、发布流水线中的硬门禁没有声明文件就拒绝发布THIRD_PARTY_NOTICES.md不是装饰性文档它被发布检查、运行时打包、公开发布三个环节强制引用发布就绪检查pnpm release:checkverify_release_ready.py将LICENSE、NOTICE、THIRD_PARTY_NOTICES.md、SBOM.spdx.json四者列为REQUIRED_RELEASE_FILESL8-L13任一缺失即输出missing release file: ...并以非零码退出同时还会拒绝“许可证仍为 pending”的LICENSE-PENDING.md占位文件并检查 Core 的uv.lock不再依赖腾讯内部 Python 源防止内部依赖泄漏到公开包。运行时打包build_runtime_distribution.cjsL397-L412把SBOM.spdx.json、THIRD_PARTY_NOTICES.md直接复制进产物根目录并把LICENSE→licenses/LICENSE.one-memory、LICENSE.memmy→licenses/LICENSE.memmy、PROVENANCE.md→licenses/PROVENANCE.memmy.md一起随 Runtime 分发随后在必产物清单中逐一断言这些文件存在L429-L449。也就是说用户拿到的每个 Runtime 包里都物理携带这三份声明。公开发布清单build-release-assets.mjsL159-L179将SBOM.spdx.json作为role: sbomspdx-json、THIRD_PARTY_NOTICES.md作为role: noticesmarkdown的发布元数据工件登记计算 sha256 并对外公布文件缺失、为空或为符号链接都会抛出release_metadata_invalid。公开发布门禁二次校验verify_public_release_ready.pyL254-L267还会重新解析SBOM.spdx.jsonJSON 无法解析则记录sbom_invalid阻断项若包名集合中出现hy-memory-internal这类内部依赖则记录sbom_contains_internal_dependency阻断项——确保公开清单里绝不出现内部包名。README 官方指引仓库 README.md 的许可证一节同样指向 THIRD_PARTY_NOTICES.md 与 SBOM.spdx.json作为第三方归属与许可证的唯一权威出处。六、可复现性与测试保障THIRD_PARTY_NOTICES.md头部的生成时间戳2026-10-17T13:52:48Z默认取自datetime.now(timezone.utc)但生成脚本支持环境变量SOURCE_DATE_EPOCHL356-L369设置后将从该 Unix 秒数换算 UTC 时间从而支持可复现的发布构建reproducible build值为负数或非法时生成直接失败。对应测试test_source_date_epoch_drives_reproducible_release_timestamp验证了该行为test_generate_sbom.py。围绕生成器test_generate_sbom.py 提供四组回归测试test_hy_memory_notice_comes_from_the_installed_dist_info构造临时hy_memory-2.0.4.dist-info验证声明名称/版本/许可证/版权均来自其中真实元数据test_hy_memory_notice_refuses_missing_dist_infodist-info 缺失时必须抛SbomErrorfail closedtest_script_has_a_modern_python_guard_before_type_annotations保证 Python 3.10 版本守卫先于Path | None等新语法出现避免旧解释器在解析阶段就崩溃test_source_date_epoch_drives_reproducible_release_timestamp验证时间戳可复现路径。此外构建侧测试如 build_runtime_distribution.test.cjs断言打包产物必然包含SBOM.spdx.json与THIRD_PARTY_NOTICES.mdbuild-release-assets.test.mjs 验证发布清单中两份文件的 sha256 与内容一致性。七、对开发者与使用者的实践建议作为再分发者若你基于 MemHub 构建衍生发行版Apache-2.0 要求保留版权与归属声明。请沿用THIRD_PARTY_NOTICES.mdSBOM.spdx.jsonlicenses/目录的完整随包结构尤其不要遗漏LICENSE.memmy与PROVENANCE.memmy.md因为 memmy 适配模块的 MIT 归属与适配边界声明都在其中。作为 MemHub 维护者任何依赖变更后应运行pnpm sbom重新生成两份工件再执行pnpm release:check验证发布就绪生成前的uv sync与pnpm install是必要前置步骤因为脚本坚持从真实安装树而非手工清单推导。作为审查者第三方包的NOASSERTION条目应在发布审查时逐包填充许可证结论但禁止在填充前以猜测方式把NOASSERTION替换成具体许可证——这是生成器刻意保留的人工把关点。综上THIRD_PARTY_NOTICES.md 表面上是一份法务声明实质上是一套由 generate_sbom.py 驱动、被发布检查与打包脚本强制执行的“依赖归属可追溯”工程机制声明永远来自真实安装树未知信息宁可留白NOASSERTION也不猜测最终让随包分发的每一份许可证文本都有源码级出处可查。赞分享【免费下载链接】Hy-Memory项目地址https://gitcode.com/gh_mirrors/hy/Hy-Memory点击查看免费下载相关推荐libnvidia-container 第三方依赖与许可证合规全解析从 THIRD_PARTY_NOTICES.md 读懂构建系统的依赖管理libnvidia container 第三方依赖与许可证合规全解析从 THIRD_PARTY_NOTICES.md 读懂构建系统的依赖管理 本篇技术指南以容器运行时云原生openJiuwen 代码许可证治理指南贡献白名单、第三方依赖许可与特殊许可证评审机制openJiuwen 代码许可证治理指南贡献白名单、第三方依赖许可与特殊许可证评审机制 openJiuwen 社区遵循 Open Source Definit文档开源治理Blender 第三方许可证全景解读从依赖合规清单到 make license 自动化生成机制Blender 第三方许可证全景解读从依赖合规清单到 make license 自动化生成机制 本文以 release/license/license.md图形学3D渲染桌面应用音视频上一篇create-mf-app完全指南从安装到部署的完整流程下一篇从 PyTorch 到 MLXmoge-3-vitg-mlx-fp32 是如何用 mlx-vlm 转换的模型迁移实战详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考