From fc3bc86c816cc6c6e6ac3c6c7f1c6008791c909e Mon Sep 17 00:00:00 2001 From: ManojDev Date: Mon, 3 Aug 2026 13:03:35 +0530 Subject: [PATCH 01/11] Fill the LICENSE copyright placeholder, add NOTICE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third in the series, after aistudio-server (31 July) and aistudio-app. LICENSE is already the complete Apache-2.0 text, so detection and scanning work — unlike aistudio-server finding 1. But the appendix still read: Copyright [yyyy] [name of copyright owner] the template text meant to be replaced. Same as aistudio-app. Inert legally, since the grant does not depend on the appendix, but it was the only place in the repository identifying the copyright holder and it identified nobody. NOTICE covers the copyright, the third-party software compiled into the binary, the trademark statement, and one section specific to this repo: the distinction between what the CLI DISTRIBUTES and what it merely INSTALLS on the operator's behalf. That distinction is worth writing down because it cuts in our favour. ai-studio-cli provisions NVIDIA drivers, the CUDA userspace, Docker or Podman and vLLM onto GPU nodes, but CoreSpan conveys none of it — the operator downloads it from the publisher onto their own machine. So the NVIDIA CUDA EULA question that is the largest open item for aistudio-server, where we do build and ship images containing CUDA, has no counterpart here. Absent a statement a reader could reasonably assume our Apache grant covers the drivers this tool installs. It does not. .gitattributes is scoped to the file types this change introduces rather than a blanket `* text=auto eol=lf`. Nine of the 33 tracked files carry CRLF in the working tree while committed as LF, including several .go files; a blanket rule would renormalise all of them the next time anyone touched them, producing a whole-file diff unrelated to whatever they were changing. That mixed state is worth fixing, as its own commit. --- .gitattributes | 27 ++++++++++++++++++++++ LICENSE | 2 +- NOTICE | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 NOTICE diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e6a8fe2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,27 @@ +# Line-ending rules. +# +# Scoped deliberately to the file types this change introduces, rather than a +# blanket `* text=auto eol=lf`. Nine of the 33 tracked files (LICENSE, several +# .go files, both existing workflows) currently carry CRLF; a blanket rule would +# renormalise all of them the next time anyone touched them, producing a +# whole-file diff at a moment unrelated to whatever they were actually changing. +# That mixed state is worth cleaning up, but as its own commit, not as a side +# effect of this one. + +# Shell scripts must be LF. CRLF gives `bad interpreter: /usr/bin/env bash^M`, +# which is a genuinely confusing way to fail. +*.sh text eol=lf + +# Generated compliance artifacts are written with LF. Without this, a +# contributor with core.autocrlf=true checks them out as CRLF and the freshness +# check reports them stale with a diff that looks empty. +NOTICE text eol=lf +THIRD-PARTY-*.md text eol=lf +*.css text eol=lf + +# Vendored assets — never normalise. These are embedded into the binary +# verbatim and any rewriting corrupts them. +*.woff2 binary +*.woff binary +*.png binary +ai-studio-cli/internal/benchui/ui/vendor/js/*.js -text diff --git a/LICENSE b/LICENSE index 261eeb9..d242001 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2026 CoreSpan AI Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..2d45142 --- /dev/null +++ b/NOTICE @@ -0,0 +1,63 @@ +AI Studio CLI (ai-studio-cli) +Copyright 2026 CoreSpan AI + +This product includes software developed at CoreSpan AI. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License in the LICENSE file distributed with this work, or at: + + http://www.apache.org/licenses/LICENSE-2.0 + +-------------------------------------------------------------------------------- +THIRD-PARTY SOFTWARE +-------------------------------------------------------------------------------- + +ai-studio-cli is distributed as a compiled Go binary. Go statically links its +dependencies, so a released binary contains compiled copies of every module in +its build graph — cobra, viper, pflag, fsnotify and the rest — together with +the web UI assets embedded via go:embed. + +Distributing the binary distributes all of that. Unlike an interpreted project, +there is no node_modules or site-packages beside the artifact for third-party +notices to live in: the binary is the whole distribution, so the notices are +compiled into it. + +Print them from any build: + + ai-studio-cli licenses + +The same text is published as an asset on every GitHub release, so it can be +read without running the binary. + +Sources of the embedded notices: + + * Go modules — generated by `make notices` (go-licenses over the real build + graph) into ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt + + * Web UI assets — ai-studio-cli/internal/benchui/ui/vendor/NOTICE + Inter and JetBrains Mono, SIL OFL-1.1 + Chart.js 4.4.7, MIT + +-------------------------------------------------------------------------------- +EXTERNAL SOFTWARE THIS TOOL INSTALLS OR RUNS +-------------------------------------------------------------------------------- + +Separately from what is compiled in, ai-studio-cli provisions and runs software +on GPU nodes: NVIDIA drivers and the CUDA userspace, Docker or Podman, vLLM, +nvbandwidth, and container images pulled at run time. + +CoreSpan does not distribute those. They are downloaded by the operator, from +their publishers, onto the operator's own machines, under those publishers' +terms — the NVIDIA driver and CUDA EULAs in particular. Nothing in this +repository's Apache-2.0 grant extends to them, and accepting their terms is +between the operator and the publisher. + +-------------------------------------------------------------------------------- +TRADEMARKS +-------------------------------------------------------------------------------- + +Apache License 2.0 Section 6 grants no trademark rights. "CoreSpan" and the +CoreSpan logo are trademarks of CoreSpan AI. All other product names, logos and +brands referenced in this repository are the property of their respective +owners and are used for identification purposes only. From 54e555e88143282401141c658089009c4389bab5 Mon Sep 17 00:00:00 2001 From: ManojDev Date: Mon, 3 Aug 2026 13:03:56 +0530 Subject: [PATCH 02/11] Serve bench UI fonts and Chart.js from the binary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings, both about assets compiled into the binary with go:embed. Google Fonts ------------ index.html loaded Inter and JetBrains Mono from fonts.googleapis.com. Same as aistudio-server finding 9, but worse here, and the irony is sharper: this UI is embedded in the binary precisely so it needs no external files — then phoned out for fonts on every page load. `ai-studio-cli bench-ui` runs ON GPU nodes, which are routinely air-gapped, and serves the dashboard on localhost. A CDN reference there does not degrade, it fails. The privacy half applies too: LG Muenchen I, 3 O 17493/20 (20 Jan 2022) held that disclosing a visitor's IP to Google via a font request is a GDPR breach absent consent. Here the disclosed IP is the operator's own machine. Chart.js -------- chart.umd.min.js was a 205 KB copy fetched from jsdelivr carrying only a banner: /*! Chart.js v4.4.7 ... Released under the MIT License */ A banner naming a licence is not the licence. MIT requires "the above copyright notice AND THIS PERMISSION NOTICE" to be included; the permission notice — the paragraph that actually grants the rights — was absent, and there was no LICENSE file anywhere near it. Provenance was a CDN rather than a registry, with jsdelivr's own "Do NOT use SRI with dynamically generated files" warning still in the header. Replaced with the npm chart.js@4.4.7 artifact, verified byte-identical to the vendored copy apart from that banner — so it is provably the same code from a canonical source — with LICENSE-chartjs.md beside it. Both handled by scripts/vendor-ui-assets.sh, which also writes vendor/NOTICE. Latin subset, only the four Inter and two JetBrains weights index.css actually references. Unlike aistudio-app, where the equivalent binaries are gitignored and fetched at setup, these are COMMITTED. `go build` cannot run npm and go:embed needs the files present at compile time — making a working build depend on a prior npm run would break `go install` for everyone. Verified: `//go:embed ui/*` recurses into vendor/fonts/ and vendor/js/, no vendored filename starts with . or _ (which embed would silently skip), and spaHandler's fs.Stat + http.FileServer resolves the nested vendor/ paths. --- ai-studio-cli/internal/benchui/ui/index.html | 24 ++- .../internal/benchui/ui/vendor/NOTICE | 31 ++++ .../internal/benchui/ui/vendor/fonts.css | 9 + .../ui/vendor/fonts/LICENSE-Inter-OFL.txt | 93 ++++++++++ .../fonts/LICENSE-JetBrainsMono-OFL.txt | 93 ++++++++++ .../vendor/fonts/inter-latin-400-normal.woff2 | Bin 0 -> 23664 bytes .../vendor/fonts/inter-latin-500-normal.woff2 | Bin 0 -> 24272 bytes .../vendor/fonts/inter-latin-600-normal.woff2 | Bin 0 -> 24452 bytes .../vendor/fonts/inter-latin-700-normal.woff2 | Bin 0 -> 24356 bytes .../jetbrains-mono-latin-400-normal.woff2 | Bin 0 -> 21168 bytes .../jetbrains-mono-latin-500-normal.woff2 | Bin 0 -> 21832 bytes .../benchui/ui/vendor/js/LICENSE-chartjs.md | 9 + .../js/chart.umd.js} | 6 - scripts/vendor-ui-assets.sh | 165 ++++++++++++++++++ 14 files changed, 418 insertions(+), 12 deletions(-) create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/NOTICE create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts.css create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-Inter-OFL.txt create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-JetBrainsMono-OFL.txt create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-400-normal.woff2 create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-500-normal.woff2 create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-600-normal.woff2 create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-700-normal.woff2 create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/fonts/jetbrains-mono-latin-500-normal.woff2 create mode 100644 ai-studio-cli/internal/benchui/ui/vendor/js/LICENSE-chartjs.md rename ai-studio-cli/internal/benchui/ui/{chart.umd.min.js => vendor/js/chart.umd.js} (99%) create mode 100644 scripts/vendor-ui-assets.sh diff --git a/ai-studio-cli/internal/benchui/ui/index.html b/ai-studio-cli/internal/benchui/ui/index.html index 4e81280..9ed100f 100644 --- a/ai-studio-cli/internal/benchui/ui/index.html +++ b/ai-studio-cli/internal/benchui/ui/index.html @@ -6,12 +6,24 @@ Benchmarks — AI Studio - - - - + + + diff --git a/ai-studio-cli/internal/benchui/ui/vendor/NOTICE b/ai-studio-cli/internal/benchui/ui/vendor/NOTICE new file mode 100644 index 0000000..f2f104a --- /dev/null +++ b/ai-studio-cli/internal/benchui/ui/vendor/NOTICE @@ -0,0 +1,31 @@ +Third-party assets embedded in the ai-studio-cli bench UI +========================================================= + +These files are compiled into the ai-studio-cli binary via //go:embed, so +their licence terms travel with every copy of the binary that is distributed. + +Regenerate with: ./scripts/vendor-ui-assets.sh + +Inter + Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) + SIL Open Font License 1.1 — fonts/LICENSE-Inter-OFL.txt + Packaged via @fontsource/inter@5.3.0 + +JetBrains Mono + Copyright 2020 The JetBrains Mono Project Authors + (https://github.com/JetBrains/JetBrainsMono) + SIL Open Font License 1.1 — fonts/LICENSE-JetBrainsMono-OFL.txt + Packaged via @fontsource/jetbrains-mono@5.3.0 + +Chart.js 4.4.7 + Copyright (c) 2014-2024 Chart.js Contributors + MIT — js/LICENSE-chartjs.md + +OFL-1.1 note: these fonts are redistributed unmodified, under their original +names, and are not sold on their own, which is what OFL section 2 requires. +If a font file is ever subsetted or renamed, re-read sections 3 and 4. + +MIT note: Chart.js previously lived here as a jsdelivr-fetched copy carrying +only a banner comment. A banner names the licence; it is not the licence. MIT +requires "the above copyright notice and this permission notice" to be included, +so the full text is now shipped in js/LICENSE-chartjs.md. diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts.css b/ai-studio-cli/internal/benchui/ui/vendor/fonts.css new file mode 100644 index 0000000..85f693a --- /dev/null +++ b/ai-studio-cli/internal/benchui/ui/vendor/fonts.css @@ -0,0 +1,9 @@ +/* Self-hosted web fonts. Generated by scripts/vendor-ui-assets.sh — do not edit. */ +/* Inter — SIL OFL-1.1 — see fonts/LICENSE-Inter-OFL.txt */ +@font-face{font-family:"Inter";font-style:normal;font-display:swap;font-weight:400;src:url("./fonts/inter-latin-400-normal.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;} +@font-face{font-family:"Inter";font-style:normal;font-display:swap;font-weight:500;src:url("./fonts/inter-latin-500-normal.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;} +@font-face{font-family:"Inter";font-style:normal;font-display:swap;font-weight:600;src:url("./fonts/inter-latin-600-normal.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;} +@font-face{font-family:"Inter";font-style:normal;font-display:swap;font-weight:700;src:url("./fonts/inter-latin-700-normal.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;} +/* JetBrains Mono — SIL OFL-1.1 — see fonts/LICENSE-JetBrainsMono-OFL.txt */ +@font-face{font-family:"JetBrains Mono";font-style:normal;font-display:swap;font-weight:400;src:url("./fonts/jetbrains-mono-latin-400-normal.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;} +@font-face{font-family:"JetBrains Mono";font-style:normal;font-display:swap;font-weight:500;src:url("./fonts/jetbrains-mono-latin-500-normal.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;} diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-Inter-OFL.txt b/ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-Inter-OFL.txt new file mode 100644 index 0000000..40589da --- /dev/null +++ b/ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-Inter-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) Inter-Italic[opsz,wght].ttf: Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-JetBrainsMono-OFL.txt b/ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-JetBrainsMono-OFL.txt new file mode 100644 index 0000000..8f7ed67 --- /dev/null +++ b/ai-studio-cli/internal/benchui/ui/vendor/fonts/LICENSE-JetBrainsMono-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) JetBrainsMono-Italic[wght].ttf: Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-400-normal.woff2 b/ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-400-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..f15b025d666269fb07daf0263e54231481e4289c GIT binary patch literal 23664 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 literal 0 HcmV?d00001 diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-500-normal.woff2 b/ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-500-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..54f0a595dd3c76344a980109e7517ed42416de93 GIT binary patch literal 24272 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 literal 0 HcmV?d00001 diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-700-normal.woff2 b/ai-studio-cli/internal/benchui/ui/vendor/fonts/inter-latin-700-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a68fb101cd9224aa7bb6ca80356b5132c40c6f3f GIT binary patch literal 24356 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 T=ND-DucNQ`tADQ-AuI&|D5jKI literal 0 HcmV?d00001 diff --git a/ai-studio-cli/internal/benchui/ui/vendor/fonts/jetbrains-mono-latin-500-normal.woff2 b/ai-studio-cli/internal/benchui/ui/vendor/fonts/jetbrains-mono-latin-500-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..be878e68fa71bc1f08894c0882d07adbe485ef99 GIT binary patch literal 21832 zcmV)CK*GOwPew8T0RR91098l;5C8xG0O8O80954w0RR9100000000000000000000 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 there is not a slow load — it is +# a dashboard that renders in fallback fonts on the exact machines +# this tool exists to benchmark. Embedding the UI in the binary and +# then having it phone out for fonts defeats the embedding. +# +# Privacy Requesting fonts from fonts.googleapis.com discloses the +# operator's IP to a third party. LG München I, 3 O 17493/20 +# (20 Jan 2022) held that to be a GDPR breach absent consent. +# +# Self-hosting the fonts creates an SIL OFL-1.1 obligation to ship the copyright +# and licence with them. Handled here: the LICENSE files are copied alongside +# the .woff2 files and summarised in vendor/NOTICE. +# +# WHY THESE BINARIES ARE COMMITTED +# +# Unlike aistudio-app, where the vendored assets are gitignored and fetched at +# setup time, these are committed. `go build` does not run npm, and `go:embed` +# requires the files to exist in the source tree at compile time. Anyone with a +# Go toolchain and a checkout must be able to produce a working binary. Making +# that depend on a prior npm run would break `go install`. +# +# Usage: +# ./scripts/vendor-ui-assets.sh # re-fetch and regenerate +# VENDOR_DEST=/tmp/check ./scripts/... # CI: regenerate elsewhere and diff +# +# Requires: npm +# ============================================================================= + +set -euo pipefail + +# Exact versions. A floating major would ship different .woff2 bytes and fail +# CI's reproducibility diff on an unrelated PR. +INTER_VERSION="5.3.0" +JETBRAINS_VERSION="5.3.0" + +# Must match the version the UI was written against. The previously vendored +# copy came from jsdelivr and was byte-identical to npm's dist/chart.umd.js for +# this version, plus a CDN banner. +CHARTJS_VERSION="4.4.7" + +# Weights actually referenced by index.css (--font-sans, --font-mono). +# Every extra weight is ~25 KB compiled into the binary for nothing. +INTER_WEIGHTS=(400 500 600 700) +JETBRAINS_WEIGHTS=(400 500) + +SUBSET="latin" + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +UI="$ROOT/ai-studio-cli/internal/benchui/ui" +DEST="${VENDOR_DEST:-$UI/vendor}" + +if ! command -v npm >/dev/null 2>&1; then + echo "ERROR: npm is required to vendor UI assets." >&2 + echo " These files are committed, so this is only needed when updating them." >&2 + exit 1 +fi + +WORK="$(mktemp -d)" +BUILD="$WORK/stage" +trap 'rm -rf "$WORK"' EXIT + +echo "Fetching packages ..." +cd "$WORK" +npm init -y >/dev/null 2>&1 +npm install --no-audit --no-fund --silent \ + "@fontsource/inter@${INTER_VERSION}" \ + "@fontsource/jetbrains-mono@${JETBRAINS_VERSION}" \ + "chart.js@${CHARTJS_VERSION}" + +MODULES="$WORK/node_modules" + +# Stage then swap, so a failure partway through cannot leave the embedded UI +# half-populated — `go:embed` would then compile a broken dashboard into the +# binary with no error. +mkdir -p "$BUILD/fonts" "$BUILD/js" + +echo "Copying fonts ..." +for w in "${INTER_WEIGHTS[@]}"; do + cp "$MODULES/@fontsource/inter/files/inter-${SUBSET}-${w}-normal.woff2" "$BUILD/fonts/" +done +for w in "${JETBRAINS_WEIGHTS[@]}"; do + cp "$MODULES/@fontsource/jetbrains-mono/files/jetbrains-mono-${SUBSET}-${w}-normal.woff2" "$BUILD/fonts/" +done + +echo "Copying licences ..." +cp "$MODULES/@fontsource/inter/LICENSE" "$BUILD/fonts/LICENSE-Inter-OFL.txt" +cp "$MODULES/@fontsource/jetbrains-mono/LICENSE" "$BUILD/fonts/LICENSE-JetBrainsMono-OFL.txt" +cp "$MODULES/chart.js/LICENSE.md" "$BUILD/js/LICENSE-chartjs.md" + +echo "Copying Chart.js ..." +# dist/chart.umd.js is already minified upstream; this is the same artifact the +# previous jsdelivr copy carried, minus the CDN banner. +cp "$MODULES/chart.js/dist/chart.umd.js" "$BUILD/js/chart.umd.js" + +RANGE='U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD' + +echo "Generating fonts.css ..." +{ + echo "/* Self-hosted web fonts. Generated by scripts/vendor-ui-assets.sh — do not edit. */" + echo "/* Inter — SIL OFL-1.1 — see fonts/LICENSE-Inter-OFL.txt */" + for w in "${INTER_WEIGHTS[@]}"; do + printf '@font-face{font-family:"Inter";font-style:normal;font-display:swap;font-weight:%s;src:url("./fonts/inter-%s-%s-normal.woff2") format("woff2");unicode-range:%s;}\n' \ + "$w" "$SUBSET" "$w" "$RANGE" + done + echo "/* JetBrains Mono — SIL OFL-1.1 — see fonts/LICENSE-JetBrainsMono-OFL.txt */" + for w in "${JETBRAINS_WEIGHTS[@]}"; do + printf '@font-face{font-family:"JetBrains Mono";font-style:normal;font-display:swap;font-weight:%s;src:url("./fonts/jetbrains-mono-%s-%s-normal.woff2") format("woff2");unicode-range:%s;}\n' \ + "$w" "$SUBSET" "$w" "$RANGE" + done +} > "$BUILD/fonts.css" + +echo "Writing NOTICE ..." +cat > "$BUILD/NOTICE" < Date: Mon, 3 Aug 2026 13:04:19 +0530 Subject: [PATCH 03/11] Compile third-party notices into the binary, add `licenses` command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the blocker, and the distribution model makes it the strictest of the three repos. `go build` links every module in the build graph into one executable, and releases publish that executable. The graph includes cobra (Apache-2.0), viper, pflag, fsnotify, afero, cast, mapstructure, go-toml, locafero, conc, gotenv, mousetrap, golang.org/x/{term,sys,text} and yaml.v3 — MIT, BSD-3 and Apache-2.0, all of which condition redistribution on carrying the copyright notice, with Apache-2.0 s4(d) additionally requiring any NOTICE file to be reproduced. Unlike an interpreted project there is no node_modules or site-packages beside the artifact for those notices to live in. The binary IS the distribution. If the notices are not inside it they are not accompanying anything, and they were not. So they go inside it — the same approach kubectl, docker and gh take: ai-studio-cli licenses # everything embedded in this binary ai-studio-cli licenses cobra # filter to one dependency internal/notices holds the text via go:embed, in its own package so that `go build` fails loudly if the file is deleted rather than silently producing an unattributed binary. scripts/generate-notices.sh runs go-licenses over the REAL build graph — only what is actually linked, not everything in go.sum, which also lists test and tooling modules that never reach a user. It appends the embedded UI's font and Chart.js notices, which go-licenses cannot see because they are not Go modules but are equally compiled in. This survives the case that matters: someone copies the binary to an isolated GPU node with no network and no checkout. The notices go too. NOT YET GENERATED ----------------- The committed THIRD-PARTY-NOTICES.txt is an explicit placeholder. The environment this was written in cannot reach proxy.golang.org, go.dev or GitHub, so the machinery is complete but has not been run: make notices && git commit One command with a Go toolchain and network. I deliberately did not hand-write the inventory — writing licence facts I could not verify into a compliance document is the failure mode that makes such documents worthless. Guards while the placeholder is present: `make compliance` fails, CI fails, and the release workflow refuses to publish. A released binary must never ship without its notices, and `licenses` reports the fault rather than printing an empty page that reads like "no dependencies". --- ai-studio-cli/cmd/licenses.go | 80 +++++++++ .../internal/notices/THIRD-PARTY-NOTICES.txt | 38 ++++ ai-studio-cli/internal/notices/notices.go | 38 ++++ scripts/generate-notices.sh | 166 ++++++++++++++++++ 4 files changed, 322 insertions(+) create mode 100644 ai-studio-cli/cmd/licenses.go create mode 100644 ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt create mode 100644 ai-studio-cli/internal/notices/notices.go create mode 100644 scripts/generate-notices.sh diff --git a/ai-studio-cli/cmd/licenses.go b/ai-studio-cli/cmd/licenses.go new file mode 100644 index 0000000..6dc8849 --- /dev/null +++ b/ai-studio-cli/cmd/licenses.go @@ -0,0 +1,80 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + + "github.com/corespan/ai-studio-cli/internal/notices" + "github.com/spf13/cobra" +) + +// A Go binary statically links every dependency. When we publish a release +// binary we are distributing compiled copies of cobra, viper, pflag and the +// rest — and MIT, BSD-3 and Apache-2.0 all condition redistribution on carrying +// the copyright notice. Unlike a Python or Node project, there is no +// site-packages or node_modules alongside the artifact for those notices to +// live in: the binary is the entire distribution. +// +// So the notices are compiled in too, and this command prints them. It is the +// same approach kubectl, docker and gh take, and it is the only one that +// survives someone copying the binary onto a machine with no network and no +// repository checkout. +var licensesCmd = &cobra.Command{ + Use: "licenses", + Short: "Print third-party licence notices for the software in this binary", + Long: `Print the licences of the open-source software compiled into this binary. + +A Go binary statically links its dependencies, so distributing ai-studio-cli +means distributing copies of that code. The notices below accompany it, as +those licences require. + +The embedded web UI's fonts and Chart.js are covered too — they are compiled in +via go:embed. + +CoreSpan AI's own source is Apache-2.0 and is not covered by these notices. +See https://github.com/corespan/aistudio-cli for the LICENSE and NOTICE files.`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + text := notices.Text() + + if strings.TrimSpace(text) == "" || notices.IsPlaceholder() { + // Better to say so than to print an empty page and let the user + // conclude there are no third-party dependencies. + fmt.Fprintln(os.Stderr, + "This binary was built without its licence notices generated.") + fmt.Fprintln(os.Stderr, + "That is a packaging fault — please report it at") + fmt.Fprintln(os.Stderr, + "https://github.com/corespan/aistudio-cli/issues") + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, + "Building from source? Run `make notices` before `go build`.") + return fmt.Errorf("licence notices not embedded in this build") + } + + // `licenses ` filters to one dependency. Handy when someone + // only needs to check a single package's terms. + if len(args) == 1 { + needle := strings.ToLower(args[0]) + var matched []string + for _, block := range strings.Split(text, "\n"+strings.Repeat("-", 72)+"\n") { + if strings.Contains(strings.ToLower(block), needle) { + matched = append(matched, strings.TrimSpace(block)) + } + } + if len(matched) == 0 { + return fmt.Errorf("no dependency matching %q is compiled into this binary", args[0]) + } + fmt.Println(strings.Join(matched, "\n\n"+strings.Repeat("-", 72)+"\n\n")) + return nil + } + + fmt.Println(text) + return nil + }, +} + +func init() { + rootCmd.AddCommand(licensesCmd) +} diff --git a/ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt b/ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt new file mode 100644 index 0000000..1f2927d --- /dev/null +++ b/ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt @@ -0,0 +1,38 @@ +NOTICES-NOT-GENERATED + +This is a placeholder. The real third-party licence inventory has not been +generated for this checkout yet. + +Generate it with: + + make notices + +That runs go-licenses over the actual module graph and overwrites this file +with the licence text of every dependency compiled into the binary. It needs a +Go toolchain and network access to proxy.golang.org. + +CI regenerates and verifies this file on every push, and release builds are +blocked while this marker is present — a released binary must never ship +without its notices. + +Why this file exists at all +--------------------------- + +A Go binary statically links its dependencies. Publishing a release binary +means distributing compiled copies of cobra, viper, pflag, fsnotify and the +rest, and MIT, BSD-3 and Apache-2.0 all condition redistribution on carrying +the copyright notice. There is no node_modules or site-packages next to the +artifact for those notices to live in — the binary is the whole distribution, +so the notices have to be inside it. + +`ai-studio-cli licenses` prints this file. + +Not covered here +---------------- + + * CoreSpan AI's own source — Apache-2.0, see LICENSE and NOTICE in the + repository root. + * The embedded web UI's fonts and Chart.js — see + internal/benchui/ui/vendor/NOTICE. Those are also compiled in via + go:embed and their notices are reproduced by `make notices` alongside the + Go module licences. diff --git a/ai-studio-cli/internal/notices/notices.go b/ai-studio-cli/internal/notices/notices.go new file mode 100644 index 0000000..1ad64cc --- /dev/null +++ b/ai-studio-cli/internal/notices/notices.go @@ -0,0 +1,38 @@ +// Package notices carries the third-party licence text compiled into the +// binary. +// +// The content of THIRD-PARTY-NOTICES.txt is generated by `make notices`, which +// runs go-licenses over the real module graph. It is committed rather than +// produced at build time because `go build` and `go install` must work from a +// plain checkout with no extra tooling — and because go:embed requires the file +// to exist in the source tree at compile time. +// +// Keeping it in its own package rather than in cmd/ means `go build` fails +// loudly if the file is ever deleted, instead of silently producing a binary +// that ships no attribution. +package notices + +import ( + _ "embed" + "strings" +) + +//go:embed THIRD-PARTY-NOTICES.txt +var embedded string + +// placeholderMarker appears in the committed stub and is removed by the +// generator. Its presence means a real inventory was never generated for this +// build, which the `licenses` command reports rather than printing an empty +// document that reads like "no dependencies". +const placeholderMarker = "NOTICES-NOT-GENERATED" + +// Text returns the embedded third-party licence notices. +func Text() string { + return embedded +} + +// IsPlaceholder reports whether this binary was built without a generated +// inventory. Release builds must never return true; CI enforces that. +func IsPlaceholder() bool { + return strings.Contains(embedded, placeholderMarker) +} diff --git a/scripts/generate-notices.sh b/scripts/generate-notices.sh new file mode 100644 index 0000000..ecae72a --- /dev/null +++ b/scripts/generate-notices.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash +# ============================================================================= +# Generate the third-party licence notices compiled into the binary +# ============================================================================= +# +# WHY +# +# A Go binary statically links every dependency. Publishing a release binary +# distributes compiled copies of cobra, viper, pflag, fsnotify and the rest. +# MIT, BSD-3 and Apache-2.0 all condition redistribution on carrying the +# copyright notice, and there is no node_modules or site-packages beside the +# artifact for those notices to live in — the binary IS the distribution. +# +# So the notices go inside it, via go:embed, and `ai-studio-cli licenses` +# prints them. Same approach as kubectl, docker and gh, and the only one that +# survives someone copying the binary to a machine with no network. +# +# Output: ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt (committed) +# +# Usage: +# ./scripts/generate-notices.sh # regenerate +# ./scripts/generate-notices.sh --check # CI: fail if stale +# +# Requires: Go toolchain and network access to proxy.golang.org. +# ============================================================================= + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +MODULE_DIR="$ROOT/ai-studio-cli" +OUT="$MODULE_DIR/internal/notices/THIRD-PARTY-NOTICES.txt" +UI_NOTICE="$MODULE_DIR/internal/benchui/ui/vendor/NOTICE" + +CHECK=0 +[ "${1:-}" = "--check" ] && CHECK=1 + +command -v go >/dev/null 2>&1 || { echo "ERROR: Go toolchain not found." >&2; exit 1; } + +# go-licenses resolves the real build graph — only what is actually linked into +# the binary, not everything in go.sum. That distinction matters: go.sum lists +# modules pulled in for tests and tooling that never reach a user. +if ! command -v go-licenses >/dev/null 2>&1; then + echo "Installing go-licenses ..." + go install github.com/google/go-licenses@latest + export PATH="$PATH:$(go env GOPATH)/bin" +fi + +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +cd "$MODULE_DIR" + +echo "Resolving licences for the linked module graph ..." +# save writes each dependency's licence file into a directory tree; csv gives +# the module -> licence mapping for the summary table. +go-licenses save ./... --save_path="$WORK/licences" --force 2>"$WORK/save.err" || { + echo "ERROR: go-licenses save failed:" >&2 + cat "$WORK/save.err" >&2 + exit 1 +} +go-licenses csv ./... > "$WORK/licences.csv" 2>"$WORK/csv.err" || { + echo "ERROR: go-licenses csv failed:" >&2 + cat "$WORK/csv.err" >&2 + exit 1 +} + +# Anything here is a decision, not routine attribution. Strong copyleft in a +# statically linked binary we hand to customers is a materially different +# question from MIT. +FLAG='GPL|AGPL|LGPL|MPL|SSPL|BUSL|CC-BY-NC|Commons-Clause|Unknown|unknown' + +{ + echo "ai-studio-cli — third-party licence notices" + printf '=%.0s' {1..72}; echo + echo + echo "This binary statically links the Go modules listed below, and embeds the" + echo "web UI assets noted at the end. Distributing the binary distributes copies" + echo "of all of it, so their licences are reproduced here in full." + echo + echo "CoreSpan AI's own source is Apache-2.0 and is NOT covered by these notices." + echo "See LICENSE and NOTICE at https://github.com/corespan/aistudio-cli" + echo + echo "Generated: $(date -u +%Y-%m-%d) by scripts/generate-notices.sh" + echo + printf -- '-%.0s' {1..72}; echo + echo + echo "SUMMARY" + echo + # Skip the CSV header if go-licenses emits one, and align for readability. + awk -F, 'NF>=3 && $1!="module" { printf " %-58s %s\n", $1, $3 }' "$WORK/licences.csv" | sort -u + echo + echo " Modules: $(awk -F, 'NF>=3 && $1!="module"' "$WORK/licences.csv" | wc -l)" + echo + + if awk -F, 'NF>=3' "$WORK/licences.csv" | grep -qE "$FLAG"; then + echo " REQUIRES REVIEW — copyleft or unresolved licences present:" + awk -F, 'NF>=3' "$WORK/licences.csv" | grep -E "$FLAG" | sed 's/^/ /' + echo + else + echo " No copyleft or unresolved licences. Attribution obligations only." + echo + fi + + printf -- '-%.0s' {1..72}; echo + echo + + # Full text of every licence file go-licenses collected. + find "$WORK/licences" -type f \( -iname 'LICENSE*' -o -iname 'LICENCE*' -o -iname 'COPYING*' -o -iname 'NOTICE*' \) \ + | sort \ + | while read -r f; do + module="${f#"$WORK/licences/"}" + module="$(dirname "$module")" + echo "$module" + echo + sed 's/^/ /' "$f" + echo + printf -- '-%.0s' {1..72}; echo + echo + done + + # The UI assets are embedded too, and go-licenses cannot see them — they are + # not Go modules. Append their notices so one command covers the whole binary. + if [ -f "$UI_NOTICE" ]; then + echo "EMBEDDED WEB UI ASSETS" + echo + sed 's/^/ /' "$UI_NOTICE" + echo + printf -- '-%.0s' {1..72}; echo + echo + for lf in "$MODULE_DIR"/internal/benchui/ui/vendor/fonts/LICENSE-*.txt \ + "$MODULE_DIR"/internal/benchui/ui/vendor/js/LICENSE-*.md; do + [ -f "$lf" ] || continue + echo "$(basename "$lf")" + echo + sed 's/^/ /' "$lf" + echo + printf -- '-%.0s' {1..72}; echo + echo + done + else + echo "WARNING: $UI_NOTICE not found — run ./scripts/vendor-ui-assets.sh" >&2 + fi +} | sed 's/[[:space:]]*$//' > "$WORK/notices.txt" + +if [ "$CHECK" -eq 1 ]; then + if [ ! -f "$OUT" ]; then + echo "ERROR: $OUT is missing. Run 'make notices'." >&2 + exit 1 + fi + # Ignore the Generated: date, which changes every run. + if ! diff <(grep -v '^Generated:' "$OUT") <(grep -v '^Generated:' "$WORK/notices.txt"); then + echo >&2 + echo "ERROR: embedded notices are out of date. Run 'make notices' and commit." >&2 + exit 1 + fi + echo "Embedded notices are up to date." + exit 0 +fi + +cp "$WORK/notices.txt" "$OUT" +echo "Wrote $OUT ($(wc -c < "$OUT") bytes)" +grep -q "NOTICES-NOT-GENERATED" "$OUT" && { + echo "ERROR: placeholder marker survived generation — this should not happen." >&2 + exit 1 +} +echo "Verify with: cd ai-studio-cli && go run . licenses | head" From b20279a314ce186d7b24072416eded977c9c4dce Mon Sep 17 00:00:00 2001 From: ManojDev Date: Mon, 3 Aug 2026 13:04:34 +0530 Subject: [PATCH 04/11] Pin and verify the install, gate releases on notices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The installer resolved releases/latest at run time, downloaded a tarball over curl, and `sudo mv`d the contents into /usr/local/bin. No checksum, no signature, no version pinning, no check that the tarball even contained the expected binary. It extracted into /tmp under fixed names, so concurrent runs clobbered each other and failures left files behind. This is aistudio-server finding 2, sharper on two counts. That installer at least pinned a tag; this one installed whatever was newest at that instant, so it could not be used in a reproducible provisioning flow — which is what this tool is for. And the payload goes into /usr/local/bin with root, not into a compose directory. install.sh now: - takes a version (`./install.sh v1.2.3`), defaulting to latest but resolving it once, printing it, and showing how to pin it - downloads and verifies SHA256SUMS; a mismatch aborts with a report link. Verifies a detached GPG signature when one is present - uses a private mktemp -d with a cleanup trap - confirms the tarball contains the binary before installing - skips sudo entirely when $INSTALL_DIR is writable, and says so when it does need it - uses `set -euo pipefail` rather than bare `set -e` The missing-checksum path warns rather than aborting only because existing releases predate SHA256SUMS. There is a comment marking where to make it fatal once every supported release publishes one. Verified the verification: with a synthetic SHA256SUMS, a matching tarball passes, and a filename that grep cannot find makes sha256sum -c exit 1 rather than silently succeeding on empty input — which was the failure mode I most suspected in this script. release.yml produces what the installer expects: refuses to build from a lightweight tag (no author, date or signature, and silently repointable), gates on `make compliance` and `make notices-check`, verifies the built binary prints real notices before publishing, and attaches SHA256SUMS plus the notices as their own asset so they can be read without running the binary. LICENSE, NOTICE and the notices also go inside the tarball. --- .github/workflows/release.yml | 104 +++++++++++++++++++++++++++++ install.sh | 119 +++++++++++++++++++++++++++++----- 2 files changed, 208 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..2b6200e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,104 @@ +name: Release + +# Publishes a release the installer can actually verify. +# +# The previous flow produced a tarball with no checksum, and install.sh +# downloaded whatever "latest" resolved to and `sudo mv`d it into +# /usr/local/bin unverified. This publishes SHA256SUMS alongside the binary, +# and attaches the third-party notices as their own asset so they can be read +# without running the binary. + +on: + push: + tags: ["v*"] + workflow_dispatch: + inputs: + tag: + description: "Tag to build (must already exist)" + required: true + +permissions: + contents: write + +env: + GO_VERSION: "1.25" + BINARY: ai-studio-cli + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag || github.ref }} + # Annotated tag metadata is needed to verify the tag is not + # lightweight — see the check below. + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: ai-studio-cli/go.sum + + - name: Tag must be annotated + run: | + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + type=$(git cat-file -t "$TAG" 2>/dev/null || echo missing) + if [ "$type" != "tag" ]; then + echo "::error::'$TAG' is a lightweight tag (type=$type)." + echo "Lightweight tags carry no author, date or signature, and can be" + echo "silently repointed. Re-cut it with: git tag -a -s $TAG -m ..." + exit 1 + fi + echo "$TAG is annotated." + + - name: Compliance gate + # A release binary must never ship without its notices. This is the + # one place where the placeholder is a hard stop rather than a warning. + run: | + make compliance + make notices-check + + - name: Build + run: make build + + - name: Verify the binary carries its notices + run: | + out=$(./${BINARY} licenses) + grep -q "NOTICES-NOT-GENERATED" <<<"$out" && { + echo "::error::refusing to release a binary embedding the placeholder." + exit 1 + } + echo "Notices embedded: $(grep -ci copyright <<<"$out") copyright lines." + + - name: Package + run: | + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + mkdir -p dist + # The tarball carries the notices and licence beside the binary, so + # they are present even for someone who never runs `licenses`. + cp LICENSE NOTICE ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt dist/ + cp "${BINARY}" dist/ + tar -czf "${TAG}.tar.gz" -C dist . + cp ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt . + + - name: Checksums + run: | + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + sha256sum "${TAG}.tar.gz" THIRD-PARTY-NOTICES.txt > SHA256SUMS + cat SHA256SUMS + + - name: Publish + env: + GH_TOKEN: ${{ github.token }} + run: | + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + gh release create "$TAG" \ + --title "ai-studio-cli $TAG" \ + --generate-notes \ + --verify-tag \ + "${TAG}.tar.gz" \ + THIRD-PARTY-NOTICES.txt \ + SHA256SUMS \ + || gh release upload "$TAG" \ + "${TAG}.tar.gz" THIRD-PARTY-NOTICES.txt SHA256SUMS --clobber diff --git a/install.sh b/install.sh index 07cf2b9..aac2cfa 100644 --- a/install.sh +++ b/install.sh @@ -1,23 +1,112 @@ #!/bin/bash -set -e +# ============================================================================= +# ai-studio-cli installer +# ============================================================================= +# +# Usage: +# ./install.sh # install the latest release +# ./install.sh v1.2.3 # install a specific version +# VERSION=v1.2.3 ./install.sh # same, via environment +# +# What changed and why +# -------------------- +# The previous version resolved "latest" at run time, downloaded a tarball over +# plain curl, and `sudo mv`d the contents into /usr/local/bin with no +# verification of any kind. Three separate problems: +# +# Unpinned Two people running the same command a week apart got different +# binaries, and neither could say which. A script that installs +# "whatever is newest" cannot be used in a reproducible +# provisioning flow, which is what this tool is for. +# +# Unverified No checksum, no signature. Anything that could tamper with the +# download — a compromised release asset, a proxy, a redirect — +# ended up as an unverified binary in /usr/local/bin, with sudo. +# +# Untidy Extracted into /tmp with fixed names, so two concurrent runs +# clobbered each other, and a failure left files behind. +# +# It now pins a version (defaulting to latest, resolved once and reported), +# verifies a published SHA256SUMS, uses a private temp directory, and says what +# it is installing before asking for privilege. +# ============================================================================= + +set -euo pipefail REPO="corespan/aistudio-cli" BINARY_NAME="ai-studio-cli" +INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" +VERSION="${1:-${VERSION:-}}" + +die() { echo "ERROR: $*" >&2; exit 1; } + +for cmd in curl tar sha256sum; do + command -v "$cmd" >/dev/null 2>&1 || die "'$cmd' is required but not installed." +done + +# ── Resolve the version ─────────────────────────────────────────────────────── +if [ -z "$VERSION" ]; then + echo "Resolving latest release..." + VERSION=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \ + | grep '"tag_name"' | head -1 | sed -E 's/.*"([^"]+)".*/\1/') + [ -n "$VERSION" ] || die "could not resolve the latest release tag." + echo "Latest release is ${VERSION}." + echo "For a reproducible install, pin it: ./install.sh ${VERSION}" + echo +fi + +BASE="https://github.com/${REPO}/releases/download/${VERSION}" +TARBALL="${VERSION}.tar.gz" +TMP="$(mktemp -d)" +trap 'rm -rf "$TMP"' EXIT + +echo "Downloading ${TARBALL} ..." +curl -fsSL "${BASE}/${TARBALL}" -o "${TMP}/${TARBALL}" \ + || die "download failed. Does release ${VERSION} exist?" + +# ── Verify ──────────────────────────────────────────────────────────────────── +# The missing-checksum branch is a warning only while older releases predate +# SHA256SUMS. Once every supported release publishes one, make it a hard +# failure — an unverifiable binary going into /usr/local/bin under sudo +# deserves to stop the install. +echo "Verifying checksum ..." +if curl -fsSL "${BASE}/SHA256SUMS" -o "${TMP}/SHA256SUMS" 2>/dev/null; then + ( cd "$TMP" && grep " ${TARBALL}\$" SHA256SUMS | sha256sum -c - ) \ + || die "CHECKSUM MISMATCH for ${TARBALL}. + +The download does not match the published checksum. Do not install it. +Report this at https://github.com/${REPO}/issues" + echo " Checksum OK." -# 1. Get the latest release tag -TAG=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | head -1 | sed -E 's/.*"([^"]+)".*/\1/') -echo "Latest release: ${TAG}" + if curl -fsSL "${BASE}/SHA256SUMS.asc" -o "${TMP}/SHA256SUMS.asc" 2>/dev/null; then + if command -v gpg >/dev/null 2>&1 \ + && gpg --verify "${TMP}/SHA256SUMS.asc" "${TMP}/SHA256SUMS" 2>/dev/null; then + echo " Signature OK." + else + echo " NOTE: signature present but not verified (signing key not in your keyring)." + fi + fi +else + echo " WARNING: no SHA256SUMS published for ${VERSION} — cannot verify this download." + echo " Continuing; this release predates checksum publishing." +fi -# 2. Download the tarball -TARBALL="${TAG}.tar.gz" -echo "Downloading ${TARBALL}..." -curl -fsSL "https://github.com/${REPO}/releases/download/${TAG}/${TARBALL}" -o "/tmp/${TARBALL}" +# ── Extract ─────────────────────────────────────────────────────────────────── +tar -xzf "${TMP}/${TARBALL}" -C "$TMP" +[ -f "${TMP}/${BINARY_NAME}" ] || die "the tarball does not contain ${BINARY_NAME}." +chmod +x "${TMP}/${BINARY_NAME}" -# 3. Extract and install -tar -xzf "/tmp/${TARBALL}" -C /tmp -chmod +x "/tmp/${BINARY_NAME}" -echo "Installing to /usr/local/bin/..." -sudo mv "/tmp/${BINARY_NAME}" "/usr/local/bin/${BINARY_NAME}" -rm -f "/tmp/${TARBALL}" +# ── Install ─────────────────────────────────────────────────────────────────── +echo +echo "Installing ${BINARY_NAME} ${VERSION} to ${INSTALL_DIR}/" +if [ -w "$INSTALL_DIR" ]; then + mv "${TMP}/${BINARY_NAME}" "${INSTALL_DIR}/${BINARY_NAME}" +else + echo " ${INSTALL_DIR} is not writable — using sudo." + sudo mv "${TMP}/${BINARY_NAME}" "${INSTALL_DIR}/${BINARY_NAME}" +fi -echo "Done. Run: ${BINARY_NAME} --help" +echo +echo "Done. Installed ${BINARY_NAME} ${VERSION}." +echo " Run: ${BINARY_NAME} --help" +echo " Licence notices: ${BINARY_NAME} licenses" From b9990286dd717bab41a778ef8541a314acb35ae2 Mon Sep 17 00:00:00 2001 From: ManojDev Date: Mon, 3 Aug 2026 13:04:53 +0530 Subject: [PATCH 05/11] Enforce the licence position in CI, document it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four jobs. Three verify files in the repository; the fourth builds the binary and checks the notices are inside the artifact a user receives, which is what the obligation actually is. files make compliance, plus a clean regeneration of the vendored UI assets diffed against the committed copies (they are committed, so nothing otherwise stops a hand edit), plus a check that every font fonts.css references exists — a weight added to the script's list must not ship as a CSS rule with no file behind it notices make notices-check — go-licenses over the real build graph build `ai-studio-cli licenses` prints 10+ notices including the OFL text and Chart.js; and `strings` on the compiled binary finds no fonts.googleapis.com, asserted against the artifact rather than the source vet go vet Makefile adds notices, notices-check, vendor-ui and compliance alongside the build targets, so the local loop matches CI without a push. Three bugs in my own first draft of the Makefile, found by running it: `grep -q X && (echo FAIL && exit 1) || echo ok` printed BOTH branches and did not fail the recipe — the || catches the subshell's own exit. Replaced with if/then/fi. The same swallowing pattern with `|| true` meant the LICENSE placeholder check could never fail. The CDN check grepped for bare hostnames and so flagged the comment in index.html that explains why the CDN links were removed. It now matches only real loading positions (src=/href=/url()/@import followed by an absolute URL). A check that fires on its own documentation is a check someone deletes. README gains a Licensing section. For a change whose purpose is making the licence position legible, the most-read file was silent on it. It also documents the installs-but-does-not-distribute boundary. docs/LICENCE-REVIEW-RESPONSE.md is the finding-by-finding write-up, including which of the server's ten findings do not apply and why. Two were already satisfied here: go.sum pins every module by cryptographic hash — a stronger guarantee than either other repo had — and there are no container images, so the CUDA EULA question does not arise. It closes with the pattern across all three repos: same obligation, three artifacts, three different places the notices had to go. "We have a LICENSE file" answers a different question from "does the attribution reach the person receiving the software". In all three the second answer was no. --- .github/workflows/compliance.yml | 158 +++++++++++++ Makefile | 97 ++++++++ README.md | 50 ++++ docs/LICENCE-REVIEW-RESPONSE.md | 378 +++++++++++++++++++++++++++++++ 4 files changed, 683 insertions(+) create mode 100644 .github/workflows/compliance.yml create mode 100644 Makefile create mode 100644 docs/LICENCE-REVIEW-RESPONSE.md diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml new file mode 100644 index 0000000..8bbebf1 --- /dev/null +++ b/.github/workflows/compliance.yml @@ -0,0 +1,158 @@ +name: Licence compliance + +# Makes the licence position self-enforcing. +# +# The distribution model here is the strictest of the three AI Studio repos. +# aistudio-server conveys container images; aistudio-app serves a JS bundle; +# this ships a compiled Go binary that STATICALLY LINKS every dependency. There +# is no node_modules or site-packages beside the artifact for notices to live +# in — the binary is the whole distribution, so the notices have to be inside +# it. These checks confirm they are. + +on: + push: + branches: [master, main] + pull_request: + schedule: + # Weekly. Upstream modules change licences occasionally and silently. + - cron: "0 6 * * 1" + workflow_dispatch: + +permissions: + contents: read + +env: + GO_VERSION: "1.25" + +jobs: + files: + name: Licence files and bench UI assets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Static compliance checks + # Same target as `make compliance` locally, so the feedback loop does + # not require a push. Covers LICENSE completeness and filled-in + # copyright, required files, that the embedded notices are not still + # the placeholder, no CDN references in the bench UI, and that the + # vendored fonts and Chart.js are present with their licences. + run: make compliance + + - name: Vendored UI assets match their declared versions + run: | + # These binaries are committed (go:embed needs them at compile time + # and `go build` cannot run npm), so nothing stops someone editing + # them by hand. Regenerate into a scratch dir and compare. + VENDOR_DEST=/tmp/vendor-check ./scripts/vendor-ui-assets.sh + if ! diff -r /tmp/vendor-check ai-studio-cli/internal/benchui/ui/vendor; then + echo "::error::vendored UI assets differ from a clean regeneration." + echo "Run ./scripts/vendor-ui-assets.sh and commit the result." + exit 1 + fi + echo "Vendored assets reproduce exactly." + + - name: Every font referenced by fonts.css exists + run: | + # Guards against a weight being added to the script's list and + # shipping as a CSS rule with no file behind it — which go:embed + # would happily compile into the binary. + cd ai-studio-cli/internal/benchui/ui/vendor + missing=0 + for url in $(grep -oE 'url\("\./[^"]+"\)' fonts.css | sed -E 's|url\("\./||; s|"\)||'); do + [ -f "$url" ] || { echo "::error::fonts.css references missing $url"; missing=1; } + done + exit $missing + + notices: + name: Embedded notices match the module graph + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: ai-studio-cli/go.sum + + - name: Regenerate and compare + # go-licenses walks the real build graph — only what is actually linked + # into the binary, not everything in go.sum. If this drifts, the binary + # is shipping attribution that no longer describes its contents. + run: make notices-check + + build: + name: Build and verify the binary carries its notices + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: ai-studio-cli/go.sum + + - run: make build + + - name: "`licenses` prints real notices" + # The check that actually matters. Everything else verifies files exist + # in a repository; this verifies the notices are inside the artifact a + # user receives, which is what the obligation is. + run: | + out=$(./ai-studio-cli licenses 2>&1) || { + echo "::error::\`ai-studio-cli licenses\` failed:" + echo "$out" + exit 1 + } + + if grep -q "NOTICES-NOT-GENERATED" <<<"$out"; then + echo "::error::the binary embeds the placeholder, not real notices. Run 'make notices'." + exit 1 + fi + + copyrights=$(grep -ci "copyright" <<<"$out" || true) + if [ "$copyrights" -lt 10 ]; then + echo "::error::only $copyrights copyright notices in the binary output — expected 10+." + exit 1 + fi + echo "$copyrights copyright notices embedded." + + # The go:embed'd UI assets are not Go modules, so go-licenses cannot + # see them. generate-notices.sh appends them; confirm it did. + grep -qi "SIL Open Font License" <<<"$out" || { + echo "::error::OFL-1.1 text missing, but Inter is embedded (OFL s2)." + exit 1 + } + grep -qi "chart.js" <<<"$out" || { + echo "::error::Chart.js attribution missing, but it is embedded (MIT)." + exit 1 + } + echo "Embedded UI asset notices present." + + - name: Bench UI serves no external assets + run: | + # Belt and braces against the Makefile check: assert the strings are + # absent from the compiled binary, not just from the source tree. + if strings ./ai-studio-cli | grep -qE 'fonts\.(googleapis|gstatic)\.com'; then + echo "::error::the compiled binary still references Google Fonts." + exit 1 + fi + echo "No Google Fonts references in the binary." + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: third-party-notices + path: ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt + if-no-files-found: warn + + vet: + name: go vet + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: ai-studio-cli/go.sum + - run: make vet diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cc8ea5a --- /dev/null +++ b/Makefile @@ -0,0 +1,97 @@ +MODULE_DIR := ai-studio-cli +BINARY := ai-studio-cli + +.PHONY: build run test fmt vet notices notices-check vendor-ui compliance clean + +# ── Build ──────────────────────────────────────────────────────────────────── + +build: + cd $(MODULE_DIR) && go build -o ../$(BINARY) . + @echo "Built ./$(BINARY)" + +run: + cd $(MODULE_DIR) && go run . + +test: + cd $(MODULE_DIR) && go test ./... + +fmt: + cd $(MODULE_DIR) && gofmt -w . + +vet: + cd $(MODULE_DIR) && go vet ./... + +# ── Licence compliance ─────────────────────────────────────────────────────── +# +# A Go binary statically links its dependencies, so shipping a release binary +# means distributing their code. The notices have to travel inside the binary — +# there is nothing else alongside it. See scripts/generate-notices.sh. + +notices: + ./scripts/generate-notices.sh + +notices-check: + ./scripts/generate-notices.sh --check + +vendor-ui: + @# Fonts and Chart.js for the embedded bench UI. Committed, not fetched at + @# build time: `go build` cannot run npm, and go:embed needs the files + @# present in the source tree. + ./scripts/vendor-ui-assets.sh + +compliance: + @echo "── LICENSE ─────────────────────────────────────────────────────────" + @test $$(wc -c < LICENSE) -ge 10000 \ + || (echo " FAIL: LICENSE is only $$(wc -c < LICENSE) bytes — not the full Apache-2.0 text" && exit 1) + @grep -aq "3. Grant of Patent License" LICENSE || (echo " FAIL: LICENSE missing section 3" && exit 1) + @# `grep && (echo; exit 1) || true` swallows the failure — the || catches the + @# subshell's own exit. Use if/then/fi so the recipe actually fails. + @if grep -aq "name of copyright owner" LICENSE; then \ + echo " FAIL — LICENSE still has the placeholder copyright line"; exit 1; \ + fi + @echo " ok — $$(wc -c < LICENSE) bytes, sections present, copyright filled in" + @echo "── Required files ──────────────────────────────────────────────────" + @for f in NOTICE $(MODULE_DIR)/internal/benchui/ui/vendor/NOTICE \ + $(MODULE_DIR)/internal/notices/THIRD-PARTY-NOTICES.txt; do \ + test -f $$f && echo " ok — $$f" || (echo " FAIL — missing $$f" && exit 1); \ + done + @echo "── Embedded notices are real ───────────────────────────────────────" + @# A binary shipping the placeholder ships no attribution at all. For a + @# statically linked artifact this is the check that matters most. + @if grep -q "NOTICES-NOT-GENERATED" $(MODULE_DIR)/internal/notices/THIRD-PARTY-NOTICES.txt; then \ + echo " FAIL — placeholder still embedded. Run 'make notices'."; exit 1; \ + fi + @echo " ok — generated notices are embedded" + @echo "── Bench UI makes no third-party requests ──────────────────────────" + @# CDN assets break on air-gapped GPU nodes — the target deployment — and + @# Google Fonts discloses the operator's IP. + @# + @# Matches only real loading positions (src=/href= followed by an absolute + @# URL), not any mention of a hostname. A bare hostname grep flags the + @# comment in index.html that explains why the CDN links were removed, which + @# is a good way to get the check deleted. + @if grep -rnE '(src|href)[[:space:]]*=[[:space:]]*["'"'"']https?://' \ + $(MODULE_DIR)/internal/benchui/ui/index.html \ + $(MODULE_DIR)/internal/benchui/ui/index.css \ + $(MODULE_DIR)/internal/benchui/ui/app.js 2>/dev/null; then \ + echo " FAIL — bench UI loads an asset from an absolute URL (see above)"; exit 1; \ + fi + @# CSS url() and @import, which have no src=/href= prefix. + @if grep -rnE '(url\(|@import)[[:space:]]*["'"'"']?https?://' \ + $(MODULE_DIR)/internal/benchui/ui/index.css 2>/dev/null; then \ + echo " FAIL — bench UI CSS loads from an absolute URL (see above)"; exit 1; \ + fi + @echo " ok — no third-party asset references" + @echo "── Vendored UI assets present ──────────────────────────────────────" + @test $$(ls $(MODULE_DIR)/internal/benchui/ui/vendor/fonts/*.woff2 2>/dev/null | wc -l) -eq 6 \ + || (echo " FAIL — expected 6 vendored fonts; run 'make vendor-ui'" && exit 1) + @test -f $(MODULE_DIR)/internal/benchui/ui/vendor/js/chart.umd.js \ + || (echo " FAIL — Chart.js missing; run 'make vendor-ui'" && exit 1) + @echo " ok — fonts and Chart.js vendored with their licences" + @echo "" + @echo "Compliance checks passed." + @echo "Not covered here (needs network + Go): 'make notices-check'." + +clean: + rm -f $(BINARY) + cd $(MODULE_DIR) && go clean diff --git a/README.md b/README.md index 613c588..3d4c54f 100644 --- a/README.md +++ b/README.md @@ -295,3 +295,53 @@ The dashboard provides: - **Sudo Password**: The tool will securely prompt for your sudo password interactively during setup. --- + +--- + +## Licensing + +CoreSpan AI's source in this repository is licensed **Apache-2.0** — see +[`LICENSE`](LICENSE) and [`NOTICE`](NOTICE). + +Apache-2.0 Section 6 grants no trademark rights. "CoreSpan" and the CoreSpan +logo are trademarks of CoreSpan AI. + +### Third-party attribution + +Go statically links its dependencies, so a released `ai-studio-cli` binary +contains compiled copies of every module it builds against, plus the web UI +assets embedded via `go:embed`. Distributing the binary distributes all of it, +and MIT, BSD-3 and Apache-2.0 all require the copyright notice to travel with a +distributed copy. + +Unlike an interpreted project there is no `node_modules` or `site-packages` +beside the artifact for those notices to live in — the binary is the whole +distribution — so they are compiled into it: + +```bash +ai-studio-cli licenses # everything embedded in this binary +ai-studio-cli licenses cobra # filter to one dependency +``` + +The same text is published as a release asset, so it can be read without +running the binary. + +### What this tool installs but does not distribute + +`ai-studio-cli` provisions NVIDIA drivers, the CUDA userspace, Docker or Podman, +vLLM and container images onto GPU nodes. CoreSpan does not distribute those — +they are downloaded by you, from their publishers, onto your machines, under +their terms. The NVIDIA driver and CUDA EULAs in particular are between you and +NVIDIA. Nothing in our Apache-2.0 grant extends to them. + +### Verifying it yourself + +```bash +make compliance # licence files, embedded notices, no CDN refs in the UI +make notices-check # embedded notices match the real module graph (needs Go) +make notices # regenerate them after a dependency change +make vendor-ui # re-vendor the bench UI fonts and Chart.js +``` + +CI runs all of these plus a build that asserts `ai-studio-cli licenses` prints +real notices. See [`.github/workflows/compliance.yml`](.github/workflows/compliance.yml). diff --git a/docs/LICENCE-REVIEW-RESPONSE.md b/docs/LICENCE-REVIEW-RESPONSE.md new file mode 100644 index 0000000..c2c1a62 --- /dev/null +++ b/docs/LICENCE-REVIEW-RESPONSE.md @@ -0,0 +1,378 @@ +# Licence review — corespan/aistudio-cli + +**Repo:** `corespan/aistudio-cli` +**Reviewed:** 2 August 2026 +**Author:** ManojDev +**Context:** third in the series, after the 31 July review of `aistudio-server` +and the 2 August audit of `aistudio-app`. + +--- + +## Summary + +Seven findings. Two blockers, two high, two medium, one low. + +**This is the strictest distribution model of the three.** `aistudio-server` +conveys container images and the review had to argue about whether we ship +prebuilt artifacts. `aistudio-app` serves a JS bundle. This ships a **compiled +Go binary that statically links every dependency**. + +That distinction is the whole story. There is no `node_modules`, no +`site-packages`, no image layer beside the artifact for third-party notices to +live in. The binary *is* the distribution. If the notices are not inside it, +they are not accompanying anything — and they were not. + +| | Count | Findings | +| --- | --- | --- | +| ✅ Fixed | 5 | C1, C2, C3, C4, C5 | +| 🟡 Fixed, needs one local command | 1 | C1 (generation step) | +| 🔵 Open — product decision | 1 | C7 | + +**One thing needs you.** The sandbox this work was done in cannot reach +`proxy.golang.org`, `go.dev` or GitHub — only the npm registry. So I could +build all the machinery for the Go module inventory, but not run it. Everything +else is complete and verified. + +```bash +cd aistudio-cli && make notices && git add -A && git commit +``` + +That is a single command with a Go toolchain and network. I deliberately did +**not** hand-write the inventory: I know roughly what cobra and viper are +licensed under, but writing licence facts I could not verify into a compliance +document is precisely the failure mode that makes such documents worthless. +The committed file is an explicit placeholder, and both `make compliance` and +CI fail while it is present. + +--- + +## C1. A statically linked binary that carries no attribution + +**Blocker · Licence · largest exposure** + +**Technical.** `go build` links every module in the build graph into a single +executable. Releases publish that executable. The graph includes cobra +(Apache-2.0), viper, pflag, fsnotify, afero, cast, mapstructure, go-toml, +locafero, conc, gotenv, mousetrap, `golang.org/x/{term,sys,text}` and +`yaml.v3` — a mix of MIT, BSD-3 and Apache-2.0, all of which condition +redistribution on carrying the copyright notice. Apache-2.0 §4(d) additionally +requires reproducing any NOTICE file. + +There was no inventory, no notices, and no way for a recipient of the binary to +discover what was in it. + +**Plain.** When you hand someone the `ai-studio-cli` binary you are handing +them a dozen other projects' code, welded into one file. Their licences all say +the same easy thing: keep our name on it. Nothing did. + +**Fix.** The idiomatic Go answer, and the one kubectl, docker and gh all use — +compile the notices in and add a subcommand: + +``` +ai-studio-cli licenses # everything embedded in this binary +ai-studio-cli licenses cobra # filter to one dependency +``` + +- `internal/notices` holds the text, embedded with `go:embed`. Its own package, + so `go build` fails loudly if the file is deleted rather than silently + producing an unattributed binary. +- `scripts/generate-notices.sh` runs `go-licenses` over the **real build + graph** — only what is actually linked, not everything in `go.sum`, which + also lists test and tooling modules that never reach a user. +- The script appends the embedded web UI's notices too. Those are not Go + modules, so `go-licenses` cannot see them, but they are equally compiled in. +- The release workflow publishes the same text as a release asset, so it can be + read without running the binary, and puts `LICENSE`, `NOTICE` and the notices + inside the tarball alongside the executable. + +This survives the case that matters: someone copies the binary onto an isolated +GPU node with no network and no checkout. The notices go with it. + +**What is left.** `make notices` has not been run — see the summary above. The +placeholder is committed, `make compliance` fails on it, CI fails on it, and +the release workflow refuses to publish while it is present. That last one is +the important guard: a released binary must never ship without notices. + +--- + +## C2. Bench UI loads fonts from Google + +**High · Privacy + Function** + +**Technical.** `internal/benchui/ui/index.html` loaded Inter and JetBrains Mono +from `fonts.googleapis.com`. Same finding as `aistudio-server` #9, but the +consequence is worse here and the irony is sharper: this UI is compiled into the +binary with `go:embed` specifically so it needs no external files — and then +phoned out for fonts on every page load. + +`ai-studio-cli bench-ui` runs **on GPU nodes**, which are routinely air-gapped, +and serves the dashboard on localhost. The CDN reference does not degrade there, +it simply fails. + +The privacy half also applies: LG München I, 3 O 17493/20 (20 Jan 2022) held +that disclosing a visitor's IP to Google via a font request is a GDPR breach +absent consent. Here the disclosed IP is the operator's own machine. + +**Plain.** You embedded the dashboard into the binary so it would work +anywhere, then had it download fonts from Google — which fails on exactly the +isolated machines this tool is built for. + +**Fix.** `scripts/vendor-ui-assets.sh` fetches Inter and JetBrains Mono from +npm, copies their OFL-1.1 licence texts alongside, generates the `@font-face` +CSS, and writes `vendor/NOTICE`. Latin subset, only the four Inter and two +JetBrains weights `index.css` actually references. + +Unlike `aistudio-app`, these binaries **are committed**. `go build` cannot run +npm and `go:embed` needs the files present at compile time — making a working +build depend on a prior npm run would break `go install` for everyone. + +CI regenerates into a scratch directory and diffs, so a hand-edited asset is +caught, and asserts the compiled binary contains no `fonts.googleapis.com` +string. + +--- + +## C3. Vendored Chart.js with a banner instead of a licence + +**High · Licence** + +**Technical.** `internal/benchui/ui/chart.umd.min.js` was a 205 KB copy fetched +from jsdelivr, carrying only: + +``` +/*! + * Chart.js v4.4.7 ... (c) 2024 Chart.js Contributors + * Released under the MIT License + */ +``` + +A banner naming a licence is not the licence. MIT requires *"the above +copyright notice **and this permission notice**"* to be included; the +permission notice — the paragraph granting the rights — was absent. There was +no `LICENSE` file anywhere near it. + +Provenance was also a CDN rather than a package registry, with jsdelivr's own +"Do NOT use SRI with dynamically generated files" warning still embedded in the +header. + +**Plain.** The copy of Chart.js in your repo says "MIT" at the top but doesn't +include the actual licence, which is what MIT asks you to include. + +**Fix.** Replaced with the npm `chart.js@4.4.7` artifact — verified +byte-identical to the vendored copy apart from the jsdelivr banner, so this is +provably the same code from a canonical source — with `LICENSE-chartjs.md` +beside it and an entry in `vendor/NOTICE`. + +--- + +## C4. install.sh: unpinned, unverified, `sudo mv` + +**Blocker · Supply chain** + +**Technical.** The installer resolved `releases/latest` at run time, downloaded +a tarball over curl, and `sudo mv`d the contents into `/usr/local/bin`. No +checksum, no signature, no version pinning, no verification that the tarball +even contained the expected binary. It extracted into `/tmp` under fixed names, +so concurrent runs clobbered each other and failures left files behind. + +This is `aistudio-server` finding 2, but sharper on two counts. That installer +at least pinned a tag; this one installed *whatever is newest at this instant*, +so it could not be used in a reproducible provisioning flow — which is what +this tool is for. And the payload here goes into `/usr/local/bin` with sudo, +rather than into a docker-compose directory. + +**Plain.** `curl | sudo` with nothing checked. Anything that could interfere +with the download — a compromised release asset, a proxy, a bad redirect — +resulted in an unverified binary being installed with root privileges. And two +people running the same command a week apart got different software with no way +to tell. + +**Fix.** + +- Accepts a version: `./install.sh v1.2.3`. Defaults to latest, but resolves it + once, prints it, and tells you how to pin it. +- Downloads and verifies `SHA256SUMS`; a mismatch aborts with a report link. + Checks a detached GPG signature when present. +- Private `mktemp -d` with a cleanup trap. +- Confirms the tarball actually contains the binary before installing. +- Skips sudo entirely when `$INSTALL_DIR` is writable, and says so when it does + need it. +- `set -euo pipefail` instead of bare `set -e`. + +The missing-checksum path is a warning rather than a hard failure only because +existing releases predate `SHA256SUMS`. Once every supported release publishes +one, make it fatal — there is a comment in the script marking the spot. + +`.github/workflows/release.yml` now produces what the installer expects: +refuses to build from a lightweight tag, gates on compliance, verifies the +built binary prints real notices before publishing, and attaches +`SHA256SUMS` plus the notices as assets. + +--- + +## C5. LICENSE copyright placeholder never filled in + +**Medium · Licence** + +**Technical.** `LICENSE` is the complete Apache-2.0 text (11,558 bytes), so +detection and scanning work — unlike `aistudio-server` finding 1. But the +appendix still read `Copyright [yyyy] [name of copyright owner]`, the template +text meant to be replaced. Identical to `aistudio-app` finding A2. + +The file is CRLF-encoded, which is why the obvious `sed` fixes elsewhere in this +series did not apply; the replacement preserves the existing line endings rather +than reformatting the licence text and burying the one-line change in a +whole-file diff. + +**Fix.** `Copyright 2026 CoreSpan AI`. `NOTICE` added, covering the copyright, +the embedded third-party software, the trademark statement, and — specific to +this repo — a section distinguishing what the CLI *distributes* from what it +merely *installs on your behalf*. See C6. + +`make compliance` fails if the placeholder returns. + +--- + +## C6. No statement distinguishing distributed from installed software + +**Medium · Licence · specific to this repo** + +**Technical.** `ai-studio-cli` provisions NVIDIA drivers and the CUDA userspace, +Docker or Podman, vLLM, and pulls container images at run time +(`internal/provision/assets/driversInstallation.sh`, +`installVllmDeps.sh`, `cmd/vllm.go`). Nothing said whose terms govern that. + +The distinction matters and cuts in our favour, which is exactly why it should +be written down. CoreSpan does not convey any of it: the operator downloads it, +from the publisher, onto their own machine. The NVIDIA CUDA EULA question that +is the largest open item for `aistudio-server` — where we *do* build and +distribute images containing CUDA — **does not arise here**, because this tool +only automates the operator fetching it themselves. + +Absent a statement, a reader could reasonably assume our Apache-2.0 grant +extends to the drivers the tool installs. It does not, and neither does any +warranty. + +**Fix.** A dedicated section in `NOTICE` and in the README's Licensing section, +stating plainly what is distributed, what is merely installed, and that +accepting the NVIDIA terms is between the operator and NVIDIA. + +--- + +## C7. "AI Studio" name collision + +**Low · Branding — unchanged across all three repos** + +Same as `aistudio-server` #10 and `aistudio-app` A6. Apache-2.0 §6 grants no +trademark rights; "AI Studio" collides with Google AI Studio and Azure AI +Studio. + +One consideration this repo adds: the binary name `ai-studio-cli` is what +appears in `/usr/local/bin`, in shell history, in provisioning scripts and in +customer runbooks. Of the three surfaces, this is the one with the most +inertia — renaming a deployed CLI means every operator's muscle memory and +every automation script that references it. If a rename is coming, it is +cheapest here first, not last. + +Trademark statement added to `NOTICE`. Clearance search still the suggested +next step. + +--- + +## What did not apply + +| Server finding | Status here | +| --- | --- | +| 1 — LICENSE not the Apache text | Not applicable; text is complete (C5 is the placeholder only). | +| 3 — "open source" vs private gate | Not applicable. No gated registry; the CLI pulls public images and public drivers. | +| 5 — model licences | Not applicable directly. The CLI runs vLLM against models the operator supplies; C6 covers the general statement. | +| 6 — container image inventory | **Does not arise.** We build no images here. The CUDA EULA question that blocks aistudio-server has no counterpart. | +| 7 — unpinned dependencies | **Already satisfied.** `go.sum` pins every module by cryptographic hash — a stronger guarantee than either of the other two repos had. `go.mod` also pins the toolchain at 1.25.0. Nothing to fix. | +| 8 — repo dependency inventory | Superseded by C1, which is the same obligation but harder, because the artifact is a linked binary rather than a source tree the user builds. | + +--- + +## What CI now enforces + +| Check | Catches | +| --- | --- | +| LICENSE complete, no placeholder copyright | C5 recurring | +| NOTICE, vendor NOTICE, embedded notices present | C1, C2, C3 | +| Embedded notices are not the placeholder | C1 — a binary shipping no attribution | +| `make notices-check` — notices match the real module graph | C1 drifting after a dependency change | +| **Built binary**: `licenses` prints 10+ notices, incl. OFL and Chart.js | C1, C2, C3 — the check that actually matters | +| **Compiled binary** contains no `fonts.googleapis.com` string | C2, asserted against the artifact not the source | +| No `src=`/`href=`/`url()` absolute URLs in the bench UI | C2 creeping back | +| Vendored assets reproduce from a clean run | Hand-edited binaries | +| Every font `fonts.css` references exists | A weight shipping as a rule with no file | +| Release: tag must be annotated; compliance gate before publish | C4 | + +The two build-output checks are the substantive ones. Everything else confirms +files exist in a repository; only those confirm the notices are inside the +artifact a user receives. + +--- + +## Open items + +| # | Item | Owner | +| --- | --- | --- | +| C1 | Run `make notices` and commit — one command, needs Go + network | Engineering | +| C4 | Cut a release through the new workflow so `SHA256SUMS` exists; then make the missing-checksum branch fatal in install.sh | Engineering | +| C4 | Generate a CoreSpan signing key and sign `SHA256SUMS` | Engineering | +| C7 | Trademark clearance on "AI Studio" — cheapest to rename here first | Product + Counsel | +| — | Mixed line endings: 9 of 33 tracked files are CRLF, including `.go` files, which `gofmt` will fight. Worth one normalisation commit of its own. | Engineering | + +--- + +## Files added or changed + +**Added** + +``` +NOTICE Copyright, embedded software, installed-vs-distributed, trademarks +.gitattributes Scoped LF rules; binary assets protected +Makefile build/test/vet plus notices, vendor-ui, compliance +docs/LICENCE-REVIEW-RESPONSE.md This document +.github/workflows/compliance.yml CI enforcement +.github/workflows/release.yml Signed, checksummed, notice-gated releases +scripts/generate-notices.sh go-licenses over the real build graph +scripts/vendor-ui-assets.sh Fonts + Chart.js with licences +ai-studio-cli/cmd/licenses.go `ai-studio-cli licenses` +ai-studio-cli/internal/notices/notices.go go:embed carrier +ai-studio-cli/internal/notices/THIRD-PARTY-NOTICES.txt Placeholder — run `make notices` +ai-studio-cli/internal/benchui/ui/vendor/ Fonts, Chart.js, licences, NOTICE +``` + +**Changed** + +``` +LICENSE Copyright placeholder → CoreSpan AI (CRLF preserved) +README.md Licensing section +install.sh Version pinning, checksum + signature, private tmp, no blind sudo +ai-studio-cli/internal/benchui/ui/index.html Google Fonts + local chart.umd.min.js → vendor/ +``` + +**Removed** + +``` +ai-studio-cli/internal/benchui/ui/chart.umd.min.js jsdelivr copy, replaced by vendor/js/chart.umd.js + licence +``` + +--- + +## Across the three repos + +Same underlying obligation, three different answers, because the artifact +differs each time: + +| | Artifact | Where notices must live | +| --- | --- | --- | +| `aistudio-server` | Container images + source | SBOM per image; `THIRD-PARTY-NOTICES.md` in repo | +| `aistudio-app` | JS bundle served to browsers | `third-party-licences.txt` served with the app, linked from the footer | +| `aistudio-cli` | Statically linked binary | Compiled into the binary; `ai-studio-cli licenses` | + +The recurring lesson is that "we have a LICENSE file" answers a different +question from "does the attribution reach the person receiving the software". +In all three cases the second answer was no, and in all three the fix was to +put the notices where the artifact goes rather than where the source lives. From 6dce841c1f3627ff925ee4a58fbb1cdbc07d292f Mon Sep 17 00:00:00 2001 From: ManojDev Date: Mon, 3 Aug 2026 13:05:16 +0530 Subject: [PATCH 06/11] Mark shell scripts executable in the index This repo has core.fileMode=false, so chmod +x in a working tree never reaches the index and everything commits as 100644. A CI runner then checks the scripts out non-executable and `./scripts/generate-notices.sh` dies with exit 126, "found but not executable". That is exactly how the aistudio-server branch failed its first CI run, so setting the bit up front here rather than discovering it again. The Makefile and both workflows invoke these as `./scripts/...`, and install.sh is documented as `./install.sh`, so all three need it. internal/provision/assets/*.sh are deliberately left 100644: they are payloads copied to remote nodes and invoked as `bash