From 353d87d0ccacd7184a1d302e56e4b4fd134ee705 Mon Sep 17 00:00:00 2001 From: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Date: Wed, 26 Aug 2026 23:15:01 -0300 Subject: [PATCH] docs(legal): add pinned provider asset notices --- THIRD_PARTY_NOTICES.md | 221 +++++++++++++++ ...rovider-assets-third-party-notices.test.ts | 252 ++++++++++++++++++ 2 files changed, 473 insertions(+) create mode 100644 tests/unit/provider-assets-third-party-notices.test.ts diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 45fcfed7bd..773f351dca 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -24,3 +24,224 @@ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPO NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## LobeHub provider asset derivatives + +Six local provider SVGs contain geometry derived from fixed components in +`@lobehub/icons@5.10.0`. The source package is pinned as follows: + +- Tarball: + +- npm shasum: `add1baced073a60157d39c7820b8d5c1928a1054` +- npm integrity: + `sha512-CIpjkISCLRK7haDtSugGFd0o3odaJts8ewJOkUiEFtns3xvsqbl8i24eowBnjw+yMDQVQyNONlhqTD58YC6Ljg==` +- License file in the fixed tarball: `package/LICENSE` + +| Local derivative | Fixed tarball source | +| ------------------------------- | ----------------------------------------- | +| `public/providers/360ai.svg` | `package/es/Ai360/components/Color.js` | +| `public/providers/baichuan.svg` | `package/es/Baichuan/components/Color.js` | +| `public/providers/codex.svg` | `package/es/Codex/components/Color.js` | +| `public/providers/copilot.svg` | `package/es/Copilot/components/Color.js` | +| `public/providers/openclaw.svg` | `package/es/OpenClaw/components/Color.js` | +| `public/providers/stepfun.svg` | `package/es/Stepfun/components/Color.js` | + +The fixed tarball contains this license notice: + +MIT License + +Copyright (c) 2023 LobeHub + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +This package notice applies to the derived SVG geometry identified above. It does not grant rights +in any underlying brand name, logo, or trademark. + +## theSVG provider assets + +At release snapshot `091589089cd134a94df9f6cdab9ba562b2cefd18`, 65 local provider SVGs were +byte-exact matches for `public/icons//default.svg` in the theSVG repository at immutable +commit [`7870bc1c5f657d9accbb7f96cc457b8dd3363ee8`](https://github.com/GLINCKER/thesvg/tree/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8). +The fixed upstream evidence includes its +[`LICENSE`](https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/LICENSE), +[`LEGAL.md`](https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/LEGAL.md), +[`TRADEMARK.md`](https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/TRADEMARK.md), +[`LICENSING.md`](https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/LICENSING.md), +and +[`src/data/icons.json`](https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json). + +The byte match proves source provenance for the listed files. It does not prove that a registry +claim was authorized by each brand owner, and it does not relicense the logos or their underlying +brand marks. The theSVG source applies its MIT license to its codebase, tooling, and catalog; its +own legal documents separately reserve trademark rights to the respective owners. + +The fixed theSVG source contains this license notice: + +MIT License + +Copyright (c) 2025 thesvg.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Byte-exact file scope (65/65) + +- `public/providers/alibaba.svg` +- `public/providers/anthropic.svg` +- `public/providers/arcee.svg` +- `public/providers/assemblyai.svg` +- `public/providers/aws.svg` +- `public/providers/azure.svg` +- `public/providers/bailian.svg` +- `public/providers/baseten.svg` +- `public/providers/cerebras.svg` +- `public/providers/cline.svg` +- `public/providers/comfyui.svg` +- `public/providers/continue.svg` +- `public/providers/cursor.svg` +- `public/providers/deepgram.svg` +- `public/providers/deepinfra.svg` +- `public/providers/elevenlabs.svg` +- `public/providers/exa.svg` +- `public/providers/fal.svg` +- `public/providers/fireworks.svg` +- `public/providers/friendli.svg` +- `public/providers/gemini.svg` +- `public/providers/grok.svg` +- `public/providers/groq.svg` +- `public/providers/heroku.svg` +- `public/providers/huggingface.svg` +- `public/providers/hyperbolic.svg` +- `public/providers/ibm.svg` +- `public/providers/inference.svg` +- `public/providers/lambda.svg` +- `public/providers/longcat.svg` +- `public/providers/minimax.svg` +- `public/providers/mistral.svg` +- `public/providers/moonshot.svg` +- `public/providers/morph.svg` +- `public/providers/nebius.svg` +- `public/providers/novita.svg` +- `public/providers/nvidia.svg` +- `public/providers/ollama.svg` +- `public/providers/openai.svg` +- `public/providers/openrouter.svg` +- `public/providers/ovhcloud.svg` +- `public/providers/picoclaw.svg` +- `public/providers/poe.svg` +- `public/providers/pollinations.svg` +- `public/providers/qwen.svg` +- `public/providers/recraft.svg` +- `public/providers/replicate.svg` +- `public/providers/roocode.svg` +- `public/providers/runway.svg` +- `public/providers/sambanova.svg` +- `public/providers/searchapi.svg` +- `public/providers/suno.svg` +- `public/providers/tavily.svg` +- `public/providers/topazlabs.svg` +- `public/providers/trae.svg` +- `public/providers/udio.svg` +- `public/providers/upstage.svg` +- `public/providers/v0.svg` +- `public/providers/vercel.svg` +- `public/providers/vllm.svg` +- `public/providers/volcengine.svg` +- `public/providers/voyage.svg` +- `public/providers/windsurf.svg` +- `public/providers/xai.svg` +- `public/providers/zhipu.svg` + +### Upstream registry claims + +These are claims recorded by the fixed upstream registry. They have not been independently +verified against an authoritative license or brand-owner notice for every asset, so they are not +independent copyright or trademark clearance. + +| Upstream registry claim | Count | Clearance status | +| ----------------------- | ----: | --------------------------------------------------------------------- | +| MIT | 46 | Upstream claim only; original per-asset copyright notices remain HOLD | +| CC0-1.0 | 14 | Upstream claim only; not independently verified with each owner | +| Apache-2.0 | 1 | Upstream claim only; upstream NOTICE remains HOLD | +| brand-use | 2 | Brand terms, not open-source licenses; owner guidelines remain HOLD | +| Custom | 1 | Custom MiniMax claim; terms remain HOLD | +| MISSING | 1 | No matching registry claim for HuggingFace; license remains HOLD | + +#### MIT (46) + +`alibaba`, `arcee`, `assemblyai`, `aws`, `bailian`, `baseten`, `cerebras`, `comfyui`, +`deepinfra`, `exa`, `fal`, `fireworks`, `friendli`, `gemini`, `grok`, `groq`, `heroku`, +`hyperbolic`, `ibm`, `inference`, `lambda`, `longcat`, `mistral`, `moonshot`, `morph`, `nebius`, +`novita`, `openai`, `picoclaw`, `pollinations`, `qwen`, `recraft`, `roocode`, `runway`, +`sambanova`, `searchapi`, `tavily`, `topazlabs`, `trae`, `udio`, `upstage`, `vllm`, `volcengine`, +`voyage`, `xai`, `zhipu` + + +#### CC0-1.0 (14) + +`anthropic`, `cline`, `cursor`, `deepgram`, `elevenlabs`, `nvidia`, `ollama`, `openrouter`, `poe`, +`replicate`, `suno`, `v0`, `vercel`, `windsurf` + + +#### Apache-2.0 (1) + +`continue` + + +#### brand-use (2) + +`azure`, `ovhcloud` + + +#### Custom (1) + +`minimax` + + +#### MISSING (1) + +`huggingface` + + +The `continue` Apache-2.0 claim remains HOLD until its authoritative upstream NOTICE obligations +are verified. The `azure` and `ovhcloud` brand-use claims are not open-source licenses and remain +subject to owner guidelines. `minimax` remains HOLD under custom terms. `huggingface` remains HOLD +because its matching file has no entry or license claim in the fixed registry. + +### Trademark and affiliation disclaimer + +All brand names, logos, and trademarks are the property of their respective owners. OmniRoute uses +these assets nominatively to identify provider integrations. There is no affiliation, sponsorship, +or endorsement by the respective owners. Copyright provenance and source license claims do not +provide trademark clearance; users should follow each owner's official brand guidelines. diff --git a/tests/unit/provider-assets-third-party-notices.test.ts b/tests/unit/provider-assets-third-party-notices.test.ts new file mode 100644 index 0000000000..2ae5438083 --- /dev/null +++ b/tests/unit/provider-assets-third-party-notices.test.ts @@ -0,0 +1,252 @@ +import assert from "node:assert/strict"; +import { readFile } from "node:fs/promises"; +import test from "node:test"; + +const NOTICE_PATH = new URL("../../THIRD_PARTY_NOTICES.md", import.meta.url); +const notice = await readFile(NOTICE_PATH, "utf8"); + +const LOBEHUB_ASSETS = [ + ["360ai.svg", "package/es/Ai360/components/Color.js"], + ["baichuan.svg", "package/es/Baichuan/components/Color.js"], + ["codex.svg", "package/es/Codex/components/Color.js"], + ["copilot.svg", "package/es/Copilot/components/Color.js"], + ["openclaw.svg", "package/es/OpenClaw/components/Color.js"], + ["stepfun.svg", "package/es/Stepfun/components/Color.js"], +] as const; + +const THESVG_ASSETS = [ + "alibaba", + "anthropic", + "arcee", + "assemblyai", + "aws", + "azure", + "bailian", + "baseten", + "cerebras", + "cline", + "comfyui", + "continue", + "cursor", + "deepgram", + "deepinfra", + "elevenlabs", + "exa", + "fal", + "fireworks", + "friendli", + "gemini", + "grok", + "groq", + "heroku", + "huggingface", + "hyperbolic", + "ibm", + "inference", + "lambda", + "longcat", + "minimax", + "mistral", + "moonshot", + "morph", + "nebius", + "novita", + "nvidia", + "ollama", + "openai", + "openrouter", + "ovhcloud", + "picoclaw", + "poe", + "pollinations", + "qwen", + "recraft", + "replicate", + "roocode", + "runway", + "sambanova", + "searchapi", + "suno", + "tavily", + "topazlabs", + "trae", + "udio", + "upstage", + "v0", + "vercel", + "vllm", + "volcengine", + "voyage", + "windsurf", + "xai", + "zhipu", +] as const; + +const THESVG_CLAIMS = { + MIT: [ + "alibaba", + "arcee", + "assemblyai", + "aws", + "bailian", + "baseten", + "cerebras", + "comfyui", + "deepinfra", + "exa", + "fal", + "fireworks", + "friendli", + "gemini", + "grok", + "groq", + "heroku", + "hyperbolic", + "ibm", + "inference", + "lambda", + "longcat", + "mistral", + "moonshot", + "morph", + "nebius", + "novita", + "openai", + "picoclaw", + "pollinations", + "qwen", + "recraft", + "roocode", + "runway", + "sambanova", + "searchapi", + "tavily", + "topazlabs", + "trae", + "udio", + "upstage", + "vllm", + "volcengine", + "voyage", + "xai", + "zhipu", + ], + "CC0-1.0": [ + "anthropic", + "cline", + "cursor", + "deepgram", + "elevenlabs", + "nvidia", + "ollama", + "openrouter", + "poe", + "replicate", + "suno", + "v0", + "vercel", + "windsurf", + ], + "Apache-2.0": ["continue"], + "brand-use": ["azure", "ovhcloud"], + Custom: ["minimax"], + MISSING: ["huggingface"], +} as const; + +function section(start: string, end?: string): string { + const startIndex = notice.indexOf(start); + assert.notEqual(startIndex, -1, `missing notice section: ${start}`); + const endIndex = end ? notice.indexOf(end, startIndex + start.length) : notice.length; + assert.notEqual(endIndex, -1, `missing notice boundary: ${end}`); + return notice.slice(startIndex, endIndex); +} + +function backtickedValues(text: string): string[] { + return [...text.matchAll(/`([^`]+)`/g)].map((match) => match[1]); +} + +test("provider asset notice pins the complete LobeHub MIT source and six derivatives", () => { + const lobe = section("## LobeHub provider asset derivatives", "## theSVG provider assets"); + + assert.match(lobe, /@lobehub\/icons@5\.10\.0/); + assert.match(lobe, /https:\/\/registry\.npmjs\.org\/@lobehub\/icons\/-\/icons-5\.10\.0\.tgz/); + assert.match(lobe, /add1baced073a60157d39c7820b8d5c1928a1054/); + assert.match( + lobe, + /sha512-CIpjkISCLRK7haDtSugGFd0o3odaJts8ewJOkUiEFtns3xvsqbl8i24eowBnjw\+yMDQVQyNONlhqTD58YC6Ljg==/ + ); + assert.match(lobe, /Copyright \(c\) 2023 LobeHub/); + assert.match(lobe, /Permission is hereby granted, free of charge/); + assert.match(lobe, /THE SOFTWARE IS PROVIDED "AS IS"/); + + for (const [asset, source] of LOBEHUB_ASSETS) { + assert.match(lobe, new RegExp(`public/providers/${asset.replace(".", "\\.")}.*${source}`)); + } + + const localAssets = backtickedValues(lobe) + .filter((value) => value.startsWith("public/providers/")) + .map((value) => value.replace("public/providers/", "")); + assert.deepEqual( + localAssets, + LOBEHUB_ASSETS.map(([asset]) => asset) + ); +}); + +test("theSVG notice pins the byte-exact 65-file scope without relicensing brand marks", () => { + const thesvg = section("## theSVG provider assets"); + const scope = section("### Byte-exact file scope (65/65)", "### Upstream registry claims"); + + assert.match(thesvg, /GLINCKER\/thesvg/); + assert.match(thesvg, /7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/); + assert.match(thesvg, /public\/icons\/\/default\.svg/); + assert.match(thesvg, /Copyright \(c\) 2025 thesvg\.org/); + assert.match(thesvg, /Permission is hereby granted, free of charge/); + assert.match(thesvg, /THE SOFTWARE IS PROVIDED "AS IS"/); + assert.match(thesvg, /does not relicense/i); + assert.match(thesvg, /trademark clearance/i); + + const localAssets = backtickedValues(scope) + .filter((value) => value.startsWith("public/providers/")) + .map((value) => value.replace("public/providers/", "").replace(/\.svg$/, "")); + assert.equal(new Set(localAssets).size, 65); + assert.deepEqual(localAssets, [...THESVG_ASSETS]); + assert.doesNotMatch(thesvg, /all (?:65 )?(?:logos|assets) (?:are|as) MIT/i); + assert.doesNotMatch(thesvg, /logos (?:are|as) open[- ]source/i); +}); + +test("theSVG registry claims retain exact counts, group membership, and HOLD boundaries", () => { + const claims = section( + "### Upstream registry claims", + "### Trademark and affiliation disclaimer" + ); + const expectedCounts = new Map([ + ["MIT", 46], + ["CC0-1.0", 14], + ["Apache-2.0", 1], + ["brand-use", 2], + ["Custom", 1], + ["MISSING", 1], + ]); + + for (const [claim, expectedAssets] of Object.entries(THESVG_CLAIMS)) { + const rowPattern = new RegExp( + `\\|\\s*${claim.replace(".", "\\.")}\\s*\\|\\s*${expectedCounts.get(claim)}\\s*\\|` + ); + assert.match(claims, rowPattern); + const group = section(`#### ${claim} (${expectedAssets.length})`, ``); + assert.deepEqual(backtickedValues(group), [...expectedAssets]); + } + + assert.match(claims, /claims recorded by the fixed upstream registry/i); + assert.match(claims, /not independently verified/i); + assert.match(claims, /continue.*HOLD.*NOTICE/is); + assert.match(claims, /azure.*ovhcloud.*not open-source licenses/is); + assert.match(claims, /minimax.*HOLD/is); + assert.match(claims, /huggingface.*HOLD/is); + + const disclaimer = section("### Trademark and affiliation disclaimer"); + assert.match(disclaimer, /nominative/i); + assert.match(disclaimer, /no affiliation/i); + assert.match(disclaimer, /endorsement/i); + assert.match(disclaimer, /respective owners/i); +});