diff --git a/content/conf.py b/content/conf.py index 2f54faf..8c6395a 100644 --- a/content/conf.py +++ b/content/conf.py @@ -42,6 +42,7 @@ "sphinx_rtd_theme_ext_color_contrast", "sphinx_coderefinery_branding", "lesson_metadata", + "sphinxcontrib.mermaid", ] # Settings for myst_nb: diff --git a/content/index.rst b/content/index.rst index 4486a72..430a25f 100644 --- a/content/index.rst +++ b/content/index.rst @@ -40,7 +40,7 @@ navigating and deciding on licenses. :delim: ; 20 min ; :doc:`social-coding` - 30 min ; :doc:`software-licensing` + 45 min ; :doc:`software-licensing` 20 min ; :doc:`software-citation` 10 min ; :doc:`sharing-data` @@ -77,7 +77,8 @@ Who is the course for? .. toctree:: :maxdepth: 1 :caption: About - + + software-licensing-old.md All lessons CodeRefinery reusing diff --git a/content/software-licensing-old.md b/content/software-licensing-old.md new file mode 100644 index 0000000..3707f90 --- /dev/null +++ b/content/software-licensing-old.md @@ -0,0 +1,350 @@ +# OLD Software licensing + +```{objectives} +- Knowing about what derivative work is and whether we can share it. +- Get familiar with terminology around licensing. +- Practical advice for software licensing. +``` + + +## Copyright + +```{figure} img/tate.jpg +:alt: Photo of somebody taking a photo of an artwork that contains the text "WHO OWNS WHAT?" +:width: 50% +``` + +- **Trademark**: Protects a name/brand from impersonation. +- **Patent**: Protects a novel, non-obvious, technical invention. +- **Copyright**: Protects **creative expression**: software, writing, graphics, photos, certain datasets, this presentation. + Practically "forever" (lifetime of author + 70 years). + +Copyright controls whether and how we can distribute the original work or the **derivative work**. + + +## Derivative work: Sampling/remixing + +```{figure} img/ai/record-player.png +:alt: Generated image of a monk operating a record player +:width: 50% +``` +[Midjourney, CC-BY-NC 4.0] + +```{figure} img/ai/turntable.png +:alt: Generated image of a monk operating two record players +:width: 50% +``` +[Midjourney, CC-BY-NC 4.0] + +- Changing and distributing software is similar to changing and distributing + music +- You can do almost anything if you don't distribute it + +**Often we don't have the choice**: +- We are expected to publish software +- Sharing can be good insurance against being locked out + + +### Exercise: Derivative work + +````{discussion} Licensing-1: What constitutes derivative work? +This question 5 below can be used as a starting point and copied to the collaborative +document or form input for an online poll: + +```markdown +## Question 5: Which of these are derivative works? + +**Choose many**. Vote by adding an `o` character: + +- A. Download some code from a website and add on to it + - votes: + +- B. Download some code and use one of the functions in your code + - votes: + +- C. Changing code you got from somewhere + - votes: + +- D. Extending code you got from somewhere + - votes: + +- E. Completely rewriting code you got from somewhere + - votes: + +- F. Rewriting code to a different programming language + - votes: + +- G. Linking to libraries (static or dynamic), plug-ins, and drivers + - votes: + +- H. Clean room design (somebody explains you the code but you have never seen it) + - votes: + +- I. You read a paper, understand algorithm, write own code + - votes: +``` + +```{solution} +- Derivative work: A-F +- Not derivative work: G-I +- E and F: This depends on how you do it, see clean room design. +``` +```` + + +```{admonition} Plagiarism vs. Intellectual Property Rights = Research Ethics vs Law +*This insert can be skipped and left as reading exercise* + +In academic context it is important to consider also *plagiarism* and how it relates to copyright and more broadly Intellectual Property Rights ([a clear explanation at this page](https://scholarworks.duke.edu/copyright-advice/copyright-faq/copyright-and-plagiarism/)). Plagiarism is the practice of taking somebody else's ideas or work and claim them as your own: it is the **unacknowledged** use of another person's work. Intellectual Property Rights (IPRs) infringement instead is the **unauthorised** use of another's work. + +IPRs can be classified in two main groups ([WTO](https://www.wto.org/english/tratop_e/trips_e/intel1_e.htm)): i) Copyright and rights related to copyright (computer programs are here) and ii) Industrial properties like trademarks, and inventions (which may include specific technical implementations of systems or code) protected by patents. + +In research ethics, plagiarism is one of the three definition of research misconduct (along with *fabrication* and *falsification*, see ALLEA, [European Code of Conduct for Research Integrity](https://allea.org/wp-content/uploads/2023/06/European-Code-of-Conduct-Revised-Edition-2023.pdf)). Plagiarism is not illegal per se, but it can lead to serious consequences like the retraction of published work. One can engage in plagiarism, without necessarily breaking any IPR law (e.g. write a new book by reusing the plot of an old book that is not under copyright anymore). Copyright infringment instead is illegal and it can result in criminal charges (e.g. fines). Copyright however protects the particular expression of an idea or fact (for example, the specific source code of a program, but not the underlying algorithm itself). + +There is no pre-defined "number of lines of code", "seconds of a song", or "pixels of an image" that can clearly set the basis for plagiarism or IPR infringement. However in the context of research, it can be possible to use *Quotation Exception* (in EU, [ref](https://www.copyrightexceptions.eu/exceptions/info53d/)) and *Fair use* (in USA, [ref](https://en.wikipedia.org/wiki/Fair_use)). Fair use has become controversial recently as it is used as legal basis for training large language models based on scraped internet data ([See for example Henderson, P., Li, X., Jurafsky, D., Hashimoto, T., Lemley, M. A., & Liang, P. (2023). Foundation models and fair use. Journal of Machine Learning Research, 24(400), 1-79.](https://www.jmlr.org/papers/v24/23-0569.html)) +``` + +### Derivative work and containers + +Containers are a bit more tricky when it comes to licenses. + +- Distribution of container recipes: it's like distributing source code +- Distribution of container images: it can be considered like distributing a binary compiled software + +The latter case is a bit more nuanced and the interested reader should read more about "Mere Aggregation" at [GPL-FAQ](https://www.gnu.org/licenses/gpl-faq.html#MereAggregation). Briefly, if the container image just bundles separate programs that talk through normal system interfaces, it is an **aggregate** and each keeps its own license (like a CD-ROM with various packages). If the components are tightly integrated into one program (e.g. a pipeline with various parts that the container can run as a single program), the image may be treated as a **derivative work**, and stricter license obligations (e.g. GPL copyleft) can apply. + +--- + +## Taxonomy of software licenses + +```{figure} img/license-models.png +:alt: "European Union Public Licence (EUPL): guidelines July 2021" + +European Commission, Directorate-General for Informatics, Schmitz, P., European Union Public Licence (EUPL): guidelines July 2021, Publications Office, 2021, +``` + +Comments: +- Arrows represent compatibility (A -> B: B can reuse A) +- Proprietary/custom: Derivative work typically not possible (no arrow goes from proprietary to open) +- Permissive: Derivative work does not have to be shared +- Copyleft/reciprocal: Derivative work must be made available under the same license terms +- NC (non-commercial) and ND (non-derivative) exist for data licenses but not really for software licenses + +**Great resource for comparing software licenses**: [Joinup Licensing Assistant](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) +- Provides comments on licenses +- Easy to compare licenses ([example](https://joinup.ec.europa.eu/licence/compare/BSD-3-Clause;Apache-2.0)) +- [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) +- Not biased by some company agenda + +If you would like to learn more about licenses, check out our slide deck: ["Software licensing +and open source explained with +cakes"](https://cicero.xyz/v3/remark/0.14.0/github.com/coderefinery/social-coding/main/licensing-and-cakes.md/). + + +## Exercise: Licensing situations + +````{exercise} Licensing-2: Consider some common licensing situations +1. What is the StackOverflow license for code you copy and paste? +2. A journal requests that you release your software during publication. You have + copied a portion of the code from another package, which you have forgotten. + Can you satisfy the journal's request? +3. You want to fix a bug in a project someone else has released, but there is no license. What risks are there? +4. How would you ask someone to add a license? +5. You incorporate MIT, GPL, and BSD3 licensed code into your project. What possible licenses can you pick for your project? +6. You do the same as above but add in another license that looks strong copyleft. What possible licenses can you use now? +7. Do licenses apply if you don't distribute your code? Why or why not? +8. Which licenses are most/least attractive for companies with proprietary software? + +```{solution} +1. As indicated [here](https://stackoverflow.com/help/licensing), all publicly accessible user contributions are licensed under [Creative Commons Attribution-ShareAlike](https://creativecommons.org/licenses/by-sa/4.0/) license. See Stackoverflow [Terms of service](https://stackoverflow.com/legal/terms-of-service/public#licensing) for more detailed information. +2. "Standard" licensing rules apply. So in this case, you would need to remove the portion of code you have copied from another package before being able to release your software. +3. By default you are no authorized to use the content of a repository when there is no license. And derivative work is also not possible by default. Other risks: it may not be clear whether you can use and distribute (publish) the bugfixed code. For the repo owners it may not be clear whether they can use and distributed the bugfixed code. However, the authors may have forgotten to add a license so we suggest you to contact the authors (e.g. make an issue) and ask whether they are willing to add a license. +4. As mentionned in 3., the easiest is to fill an issue and explain the reasons why you would like to use this software (or update it). +5. Combining software with different licenses can be tricky and it is important to understand compatibilities (or lack of compatibilities) of the various licenses. GPL license is the most protective (BSD and MIT are quite permissive) so for the resulting combined software you could use a GPL license. However, re-licensing may not be necessary. +6. Derivative work would need to be shared under this strong copyleft license (e.g. AGPL or GPL), unless the components are only plugins or libraries. +7. If you keep your code for yourself, you may think you do not need a license. However, remember that in most companies/universities, your employer is "owning" your work and when you leave you may not be allowed to "distribute your code to your future self". So the best is always to add a license! +8. The least attractive licenses for companies with proprietary software are licenses where you would need to keep an open license when creating derivative work. For instance GPL and and AGPL. The most attractive licenses are permissive licenses where they can reuse, modify and relicense with no conditions. For instance MIT, BSD and Apache License. +``` +```` + + +## When should I add a license? + +**Choose a license early in the project, even before you publish it**. Later in +the project it may become complicated to change it. Agreeing on a software +license does not mean that you have to make it open immediately. You can also +follow the **"open core" approach**: You don't have to open source all your +work. Core can be open and on a public branch. Unpublished code can be on a +private repository. + +However, we recommend to **work as if the code is public even though it still +may be private** (thanks to E. Glerean for this great suggestion): This is to +avoid surprises about code in the history with incompatible license years later +when you decide to open the project. + + +## How to add a license if your work is derivative work + +Your code is derivative work if you have started from an existing code and +made changes to it or if you incorporated an existing code into your code. + +If your code is derivative work, then **you need to check the license of the +original code**. Depending on the license, your choices might be limited. In +this case we recommend to use these two resources: +- [Joinup Licensing Assistant - Find and compare software licenses](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) +- [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) + +If the original code does not have a license, you may not be able to distribute your +derivative code. You can try to contact the authors and ask them to clarify +the license of their code. + +Practical steps for **incorporating something small into your own project** with a license +that allows you to do so (as +an example incorporating a function or two from another project): +- Create a `LICENSES/` folder in your project and "put the unmodified license text + (i.e., the license text template without any copyright notices) in your + `LICENSES/` folder" (). This + way if you reuse code from multiple projects, you can keep there multiple + license files. +- **Put the code that you incorporate into a separate file or separate files**. This makes + it later easier to see what was incorporated, and what was written from scratch. + On top of the file(s) which you have incorporated into your project add (and + adapt) the following header ([more examples](https://reuse.software/faq/)): + ```python + # SPDX-FileCopyrightText: 2023 Jane Doe + # + # SPDX-License-Identifier: MIT + ``` + The [REUSE](https://reuse.software/) initiative was started by the [Free + Software Foundation Europe](https://fsfe.org/) to make licensing of software + projects easier. It is OK if you prefer to not follow this strict format but + the advantage of following it is that the + [reuse-tool](https://github.com/fsfe/reuse-tool) makes it then easy to verify + and update license headers if you have many files from different sources. +- If it does not make sense to have several files in your project (e.g. when incorporating + something into a notebook), then add a note/comment + about the license and where the code came from on top of the function. +- Although it is not dictated by the license but it can still be nice to + acknowledge the incorporated functions/code in your README/documentation and to cite + their work if you publish a paper about your code. +- Some licenses are more permissive (you can keep your changes private) but some licenses + require you to publish the changes (share-alike). + +Practical steps for making **changes to an existing project** with a license +that allows you to do so: +- If the project is on GitHub or GitLab or similar, first fork the project + (copy it into your user space where you can make changes). +- For the BSD and MIT licenses you are not obliged to state your changes but it can + still be helpful for others if you do. You can state your changes in the + header of the files you have modified. It can be helpful to state + bigger-picture changes in the README file of the project. +- Some licenses are more permissive (you can keep your changes private) but some licenses + require you to publish the changes (share-alike). + + +### If your work is not derivative work + +If you have started "from scratch", and not used any existing code, or +incorporated existing code into your code, then you may consider your code to +be not derivative work. + +Before you may choose a license, clarify the following points with, for +example, your supervisor, collaborators, or principal investigator: +- Does your work contract, grant, or collaboration agreement dictate a + specific license? +- Is there an intent to commercialize the code? +- When there is unknown or mixed ownership: If there are multiple persons or + organizations as owners of the code, all must agree to the license. + +**Do not invent your own license**. Choose one of the standard licenses, otherwise +compatibility is not clear: + - [Joinup Licensing Assistant - Find and compare software licenses](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) + - [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) + +Practical steps: +- Create a `LICENSES/` folder ([example](https://github.com/bast/runtest/tree/main/LICENSES)). +- Put the unmodified license text + (i.e., the license text template without any copyright notices) in plain + text format into the folder ([example](https://github.com/bast/runtest/tree/main/LICENSES)). Here are + the two above licenses in plain text: + [EUPL](https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/2020-03/EUPL-1.2%20EN.txt) + and [MIT](https://en.wikipedia.org/wiki/MIT_License#License_terms) (but the + latter contains a copyright notice which we rather want to have on top of + files). +- Add copyright and license information to each file following + which uses a standard format with + so-called [SPDX identifiers](https://spdx.org/licenses/). Example below + ([example](https://github.com/bast/runtest/blob/3b210d2e9bdbdc1903a1dab9da32e161d390092d/runtest/tuple_comparison.py#L1-L3)): + ```python + # SPDX-FileCopyrightText: 2023 Jane Doe + # + # SPDX-License-Identifier: EUPL-1.2 + ``` + The [REUSE](https://reuse.software/) initiative was started by the [Free + Software Foundation Europe](https://fsfe.org/) to make licensing of software + projects easier. It is OK if you prefer to not follow this strict format but + the advantage of following it is that the + [reuse-tool](https://github.com/fsfe/reuse-tool) makes it then easy to verify + and update license headers if you have many files from different sources. +- For really small projects with one or two files the above may seem excessive + and some projects choose to not have copyright information on top of their + files and they only have one `LICENSE` file and that is + OK for really small projects. + + + +```{admonition} Licensing code produced by generative AI systems + +With generative AI tools for coding such as GitHub copilot, Cursor, or even basic chat implementations (ChatGPT, Claude, Grok, ...) the responsibility fully lays on the person who is going to use (and publish) the generated code. You can never blame the autopilot or the company who invented it, only the driver (you!). + +There are various risks in using generative AI code (this is not a taxonomy). A few examples: + +- Risks for the derivative work: you think your code is doing what you asked, but you did not review it and your results are false +- Risks for the system in use: your generated code has software security issues, e.g. an import is a *typosquat* of an actual library (e.g. "microsoft" is spelled "rnicrosoft" and depending on the font you might totally miss it...) +- Risks related to licenses/IPR: you have generated code that is actually verbatim copy of fully copyrighted code, or code that requires a strict copyleft license. Plagiarism (ethics) also applies. + +If we focus on the last one, a recent paper ([ref](https://arxiv.org/html/2408.02487v1)) estimates that around 2% of AI generated code is "strikingly similar to existing open-source implementations". Generative AI tools are typically not able to provide an exact reference of where certain bits of generated code were copied from, so it is the responsibility of the researcher to verify that the produced code is citing and referencing the license of other published pieces of software. Possibly, future AI systems for code generation can be trained on code that share the same set of licenses (e.g. based only on MIT) to mitigate these risks. + +``` + +--- + + +## Great resources + +- [Research institution policies to support research software (compiled by the Research Software Alliance)](https://www.researchsoft.org/software-policies/) +- Guide from the Aalto University in Finland: ["Opening your Software at Aalto University"](https://www.aalto.fi/en/open-science-and-research/opening-your-software-at-aalto-university) +- [Draft: Research software licensing guide](https://research-software.uit.no/blog/2023-software-licensing-guide/) +- [Joinup Licensing Assistant - Find and compare software licenses](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) +- [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) +- [Social coding lesson material](https://coderefinery.github.io/social-coding/) by [CodeRefinery](https://coderefinery.org/) +- [Citation File Format (CFF)](https://citation-file-format.github.io/) +- [License Selector](https://ufal.github.io/public-license-selector/) +- [GitHub licensing guide](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository) +- [Choosing an open-source licence](https://www.software.ac.uk/resources/guides/choosing-open-source-licence) +- [Understanding Open Source and Free Software Licensing](http://www.oreilly.com/openbook/osfreesoft/) +- [Software Licenses in Plain English](https://tldrlegal.com) +- [Don's Bibliography of Ethical Source Reading and Resources](https://github.com/DEGoodmanWilson/Ethical-Resources) +- [Mikko Välimäki: The Rise of Open Source Licensing](http://lib.tkk.fi/Diss/2005/isbn9529187793/isbn9529187793.pdf) +- [Lawrence Rosen: Open Source Licensing](http://www.rosenlaw.com/oslbook.htm) +- [Aalto IPR Cheatsheet](https://users.aalto.fi/~darstr1/cheatsheets/ipr-cheatsheet.pdf) +- [Contributor License Agreements](https://jacobian.org/2009/sep/17/contributor-license-agreements/) +- [4OSS recommendations](https://softdev4research.github.io/recommendations/) +- [4OSS lesson](https://softdev4research.github.io/4OSS-lesson/) +- [Intellectual Property Rights (IPR), Licensing And Patents](http://oss-watch.ac.uk/resources/ipr) +- [Dispelling Open Source Confusion: An Introduction to Licenses](http://depth-first.com/articles/2006/12/29/dispelling-open-source-confusion-an-introduction-to-licenses/) +- (can send automatic pull request to your GitHub repo) +- +- +- Nadia Asparouhova (formerly Nadia Eghbal): "Working in Public: The Making and Maintenance of Open Source Software" (Stripe Press) +- [Open Source Guides](https://opensource.guide/) +- [The Architecture of Open Source Applications](http://aosabook.org) +- Christopher M. Kelty: ["Two Bits: The Cultural Significance of Free Software"](https://twobits.net/) (Duke University Press, 2008) +- [Open Source (Almost) Everything](http://tom.preston-werner.com/2011/11/22/open-source-everything.html) +- [99 ways to ruin an open source project](http://opensoul.org/99ways/) +- [Open Source Casebook](https://google.github.io/opencasebook/) + +```{keypoints} +- **You cannot ignore licensing**: default is "no one can make copies or + derivative works". +``` diff --git a/content/software-licensing.md b/content/software-licensing.md index 112a713..09686e2 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -1,350 +1,823 @@ -# Software licensing +# Software licensing focusing on open source ```{objectives} -- Knowing about what derivative work is and whether we can share it. -- Get familiar with terminology around licensing. -- Practical advice for software licensing. +- Principles of open source licensing +- Difference between permissive and copyleft licenses +- Regulations for AI-generated and AI-assisted code +- Determine the software license for your project following EU regulation +- Navigate the Joinup Licensing Assistant to select a compliant license +- Understand the licensing distinction between container recipes and container images ``` +```{discussion} Limitations and context of this lesson -## Copyright +This lesson is designed as practical educational material for researchers and research software engineers, **not formal legal advice**. -```{figure} img/tate.jpg -:alt: Photo of somebody taking a photo of an artwork that contains the text "WHO OWNS WHAT?" -:width: 50% +* EU directives set only minimum requirements in some areas: Member States implement them differently and may add national rules not covered here. For example, some Member States let university researchers retain ownership of the programs they write instead of applying the employer rule in Art. 2(3). +* Institutional Context: Employment contracts, grant agreements, and university policies heavily influence software ownership and licensing choices. +* This lesson covers only the general principles of open-source reuse, copyright scope, and software adaptation. + +If you need formal guidance, the references below can help — and so can legal experts, especially if your host institute has a legal services office: + +* [EUR Directive 2009/24/EC](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32009L0024) +* [Compendium of U.S. Copyright Office Practices (3rd Ed.) – Chapter 700, Section 721: Computer Programs](https://www.copyright.gov/comp3/) +* [Chinese Regulations on Computer Software Protection,(search:"计算机软件保护条例")](https://xzfg.moj.gov.cn/) +* [Joinup Licensing Assistant,JLA](https://interoperable-europe.ec.europa.eu/collection/eupl/solution/licensing-assistant/find-and-compare-software-licenses) +* [FSFE REUSE Initiative](https://reuse.software/) +* [Research Software Alliance Policy Directory](https://www.researchsoft.org/software-policies/) ``` -- **Trademark**: Protects a name/brand from impersonation. -- **Patent**: Protects a novel, non-obvious, technical invention. -- **Copyright**: Protects **creative expression**: software, writing, graphics, photos, certain datasets, this presentation. - Practically "forever" (lifetime of author + 70 years). -Copyright controls whether and how we can distribute the original work or the **derivative work**. +## Introduction: What is a Software License? + +Under copyright law worldwide, software without an explicit license defaults to **All Rights Reserved**: nobody else may run, copy, modify, distribute, or build on your code. A software license is how the copyright holder exercises their exclusive rights, granting others permission to reproduce, distribute, modify, and sometimes sublicense the work. + +Note that *author* and *copyright holder* may differ: under Art. 2(3), an employer exercises the economic rights in code written by an employee on the job, unless a contract says otherwise. The employee is still the author; the employer is who licenses it. This matters in practice, because the person choosing the license for a research project is often not the person who wrote the code. + +This lesson focuses on open-source licenses. If your employment terms and institutional policy allow you to open-source the code you write, we recommend doing so. It makes you a better citizen of the research community, since others can reuse, verify, and build on your work. It also protects **your future self**: code your employer owns and never licenses stays locked behind All Rights Reserved when you change jobs, whereas an open license grants everyone the right to reuse it, including you. + +Open-source licenses fall into three families, which differ in what they let downstream users do: + +```{mermaid} +%%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff', 'fontSize': '16px' }}}%% -## Derivative work: Sampling/remixing +flowchart TB -```{figure} img/ai/record-player.png -:alt: Generated image of a monk operating a record player -:width: 50% + A["Your code"] -->|"no license"| B["All Rights Reserved
Nobody may run,
copy or modify it"] + A -->|"attach a license"| C{"What do you want
downstream users
to be able to do?"} + + C --> D["Permissive
MIT, Apache-2.0
'Reuse freely, keep credit'
━━━━━━
Run & modify ✅
Closed product ✅
Must share changes ❌"] + C --> W["Weak Copyleft
LGPL, MPL-2.0
'Share alike, within a boundary'
━━━━━━
Run & modify ✅
Closed product ✅ cond.
Must share changes ✅ file/library only"] + C --> E["Copyleft
GPL-3.0, EUPL-1.2
'Share alike'
━━━━━━
Run & modify ✅
Closed product ❌
Must share changes ✅"] + + classDef green fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; + classDef amber fill:#fff3bf,stroke:#f08c00,stroke-width:2px,color:#5c3c00; + classDef yellow fill:#fff9db,stroke:#f59f00,stroke-width:2px,color:#5c3c00; + classDef dashed_red fill:#ffe3e3,stroke:#adb5bd,stroke-width:2px,stroke-dasharray: 5 5,color:#000000; + classDef white fill:#f8f9fa,stroke:#adb5bd,stroke-width:2px,color:#212529; + + class D green; + class W amber; + class E yellow; + class B dashed_red; + class A,C white; ``` -[Midjourney, CC-BY-NC 4.0] -```{figure} img/ai/turntable.png -:alt: Generated image of a monk operating two record players -:width: 50% +Three rules of thumb as an compliment to the diagram: + +* **Copyleft only applies when you share the code.** Running modified GPL code on your own machine or cluster creates no obligations. +* **"Weak" copyleft still has conditions.** For example, if you ship an LGPL library inside a closed product, you must still let users modify and debug that library. +* **Copyleft licenses often don't mix.** Code under two different copyleft licenses may not be combinable, so your choice today decides who can build on your work later. + +You will hear copyleft called *viral* or *infectious*. The slang is misleading: copyleft doesn't spread just because GPL code sits next to yours in a repository or container. It only applies when you build GPL code into your own, for example by copying in a snippet. And choosing copyleft is a legitimate project decision, not a sign that a license is harmful. + +This lesson covers both directions: choosing terms for software you write, and complying with terms attached to code written by others. The scenarios later work through each case. + +### Copyright Foundation: Expression vs. Ideas + +Under Directive 2009/24/EC, software is protected by copyright as a **literary work** (Art. 1(1)). But copyright protects only the **expression**, not the ideas beneath it: Art. 1(2) explicitly excludes "ideas and principles which underlie any element of a computer program, including those which underlie its interfaces." + +* **Protected**: your specific source code text, binaries, container recipes, prompt text, and preparatory design material. +* **Not protected**: mathematical algorithms, scientific models, programming logic, data structures, and interfaces. + +The CJEU confirmed this line in *SAS Institute v World Programming* (C-406/10): a program's functionality, its programming language, and its data file formats are ideas, not expression, and are therefore outside copyright. Someone may reimplement your algorithm from scratch; they may not copy your code. This is exactly why licenses exist — they set the terms for the expression, which is the only part copyright lets you control. + +### Scope of this Lesson: What Counts as *Software*? + +Across international frameworks (17 U.S.C. § 101 and WIPO model provisions), software is broadly defined as a set of statements or instructions used directly or indirectly in a computer to bring about a certain result. Research software goes well beyond Python scripts, so this lesson covers six asset types — find the ones matching your own project, since the scenarios later map onto them: + +* **Source Code** — original algorithms, or implementations of published methods. +* **Third-Party Integrations** — embedded snippets and linked libraries (static or dynamic). +* **Infrastructure as Code** — Ansible playbooks, Terraform configs, container recipes (`Dockerfile`, Apptainer `.def`). +* **Container Images** — built binary snapshots (`.sif` files, OCI registry images). +* **AI-Assisted Code** — generated or refactored with human oversight. +* **AI Prompt Templates** — engineered system prompts meeting the threshold of human authorship. + +## Motivation: Debugging a License Compliance Failure + +With the three license families in mind, examine what happens when they collide inside an automated CI/CD pipeline: + +```{mermaid} +%%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff' }}}%% +flowchart TB + + subgraph box["CI/CD License Compliance Debugging Pipeline"] + A["Paste a snippet copied from somewhere"] --> A2["Build Trigger: Push to my-code-base"] + A2 --> B["Run Compliance Scanner"] + B --> C{"Check Inbound vs.
Outbound Terms"} + + C -->|"Target license: Permissive
Pasted snippet: Copyleft"| D["❌ BUILD FAILURE · job #142
Pasted copyleft snippet blocks MIT release"] + + D --> E{"Select Patch Option"} + + E -->|"A: Keep MIT, add comment '# Originally GPL'"| F["❌ BUILD FAIL
Comments do not override license terms"] + E -->|"B: Re-license repo to GPL-3.0 / EUPL-1.2"| G["✅ BUILD PASS
Your license now matches the snippet"] + E -->|"C: Reimplement the functionality yourself"| H["✅ BUILD PASS
Your own expression, your own license"] + E -->|"D: Delete LICENSE file to silence the scanner"| I["⚠️ SCANNER PASSES — LEGAL TRAP
Still infringing, and your own code reverts to All Rights Reserved"] + + P["Permissive
MIT, Apache-2.0, 0BSD"] + WC["Weak Copyleft
LGPL, MPL-2.0, EPL-2.0"] + CL["Copyleft
GPL-3.0, EUPL-1.2"] + end + + P -.->|"What I want for my repo"| C + CL -.->|"What the pasted snippet uses"| C + WC -.->|"Would often have been fine"| C + + classDef pass fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; + classDef copyleft fill:#fff9db,stroke:#f59f00,stroke-width:2px,color:#5c3c00; + classDef amber fill:#fff3bf,stroke:#f08c00,stroke-width:2px,color:#5c3c00; + classDef fail fill:#ffe3e3,stroke:#e03131,stroke-width:2px,color:#5c0000; + classDef warning fill:#fff3bf,stroke:#f08c00,stroke-width:2px,color:#5c0000; + classDef neutral fill:#f8f9fa,stroke:#495057,stroke-width:2px,color:#212529; + classDef box_fill fill:#ffffff,stroke:#adb5bd,stroke-width:1px; + + class P,G,H pass; + class CL copyleft; + class WC amber; + class D,F fail; + class I warning; + class A,A2,B,C,E neutral; + class box box_fill; ``` -[Midjourney, CC-BY-NC 4.0] -- Changing and distributing software is similar to changing and distributing - music -- You can do almost anything if you don't distribute it +* Option D : deleting the `LICENSE` file makes the scanner quiet without changing anything legally. You are still distributing someone else's copyleft code without honouring its terms, and you have now stripped your own users of any permission to use your work. A green pipeline is not a compliance result. -**Often we don't have the choice**: -- We are expected to publish software -- Sharing can be good insurance against being locked out +* Option C works only if you genuinely reimplement the functionality without copying the original expression. As the idea/expression split above establishes, the algorithm is free to reuse — the specific code is not. Reading the original closely and retyping a close paraphrase is still copying. -### Exercise: Derivative work +## Limitations of AI-Assisted Licensing Advice -````{discussion} Licensing-1: What constitutes derivative work? -This question 5 below can be used as a starting point and copied to the collaborative -document or form input for an online poll: +Modern software developers and RSEs routinely rely on AI coding assistants +(ChatGPT, Claude, GitHub Copilot) to generate boilerplate, refactor functions, +and answer project setup questions. -```markdown -## Question 5: Which of these are derivative works? -**Choose many**. Vote by adding an `o` character: +However, using these tools for legal or licensing guidance introduces a subtle risk of **AI legal bias**. AI models are overwhelmingly trained on US-centric web data and legal forum posts, so their outputs default almost universally to **US common law concepts** such as *Fair Use*, *Work Made for Hire*, and *Derivative Works*. + +Developers working under EU statutory frameworks face a different legal reality around exceptions, ownership, and code adaptation. The clearest example is the term you will hear constantly: + +* **US law (17 U.S.C. § 101)** formally defines *"derivative work"*, and AI assistants reach for it to describe almost any code modification. +* **EU law (Directive 2009/24/EC, Art. 4(1)(b))** does not use that term at all. It grants exclusive rights over "the translation, adaptation, arrangement and any other alteration of a computer program" — governed collectively as an **adaptation**. +* **Licenses vary**: `EUPL-1.2` defines "Derivative Works" in its own text as a contractual term, and `GPL-2.0` used the phrase too. `GPL-3.0` deliberately dropped it in favour of "modify" and "a work based on the Program", because its drafters recognised the term means different things in different jurisdictions — the same problem you face when an AI assistant uses it. + +So when an AI assistant tells you a snippet creates a "derivative work", treat that as a prompt to check the actual question under EU law: is this a statutory **adaptation**, or a **combined work** across a technical boundary? The rest of this lesson gives you that EU-aligned framework. + +## Standardizing In-File Declarations: SPDX Identifiers + +Selecting a license is only half the job. Automated scanners and CI/CD pipelines need a machine-readable way to verify compliance per file without parsing legal text. + +Managed by the Linux Foundation, **SPDX identifiers** are standardized short tags (`MIT`, `Apache-2.0`, `GPL-3.0-only`, `EUPL-1.2`) placed at the top of every source file: + +```python +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name +``` + +Every scenario below shows the SPDX tagging for its asset type — Python scripts, container recipes, and prompt templates each have their own conventions. + +## License Selection Decision Matrix & Scenario Index + +Our decision framework is grounded in the European Commission's **[Joinup Licensing Assistant (JLA)](https://interoperable-europe.ec.europa.eu/collection/eupl/solution/licensing-assistant/find-and-compare-software-licenses)**, which sorts licenses across six criteria: **Can** (permissions), **Must** (obligations), **Cannot** (restrictions), **Compatible** (interoperability), **Law** (jurisdiction), and **Support** (governance). + +The scenarios below are independent. Find the row that matches what you are actually building, jump to it, and skip the rest. + +| If you are... | Scenario | Typical Outcome | Example Licenses | +| :--- | :--- | :--- | :--- | +| Writing everything yourself | [**1. Own code**](#scenario-1) | 🟢 Free choice | `MIT`, `Apache-2.0`, `BSD-3-Clause` | +| Implementing a published algorithm | [**2. Algorithm implementation**](#scenario-2) | 🟢 Free choice — copyleft if you want reciprocity | `EUPL-1.2`, `GPL-3.0`, `AGPL-3.0` | +| Pasting in a permissive snippet | [**3. Embed permissive**](#scenario-3) | 🟢 Stay permissive, keep notices | `MIT`, `Apache-2.0`, `EUPL-1.2`, `GPL-3.0` | +| Pasting in a copyleft snippet | [**4. Embed copyleft**](#scenario-4) | 🟡 Strong copyleft likely required | `EUPL-1.2`, `GPL-3.0` | +| Importing or linking a library | [**5. Link a library**](#scenario-5) | 🟡 Depends on which copyleft — see below | `GPL-3.0`, `EUPL-1.2`, or permissive if weak copyleft | +| Writing a Dockerfile or `.def` | [**6. Container recipe**](#scenario-6) | 🟢 Free choice | `MIT`, `Apache-2.0`, `BSD-3-Clause` | +| Publishing a built image | [**7. Built image**](#scenario-7) | ⚠️ Multi-license bundle | Governed by each layer's own terms | +| Using Copilot, ChatGPT or Claude | [**8. AI-assisted code**](#scenario-8) | 🟢 Free choice, verify for memorization | `MIT`, `Apache-2.0`, `EUPL-1.2`, `GPL-3.0` | +| Shipping prompts, weights or datasets | [**9. AI workflows & assets**](#scenario-9) | 🟢 Dual-license code vs. assets | `MIT` + `CC-BY-4.0` | + +This lesson covers nine scenarios; a typical session works through three or four. The rest are here for reference when your project changes. + +## Module 1: Clean Slate – Authoring Original Code & Algorithms + +When writing original code or implementing published algorithms, no third-party license constrains your choice — but who owns the code depends on your employment contract and national rules, so check your institution's policy first. + +(scenario-1)= +::::{exercise} Scenario 1: Authoring original code and algorithms +You wrote an original algorithm from scratch (in Python, C++, Rust, etc.). Your repository contains only your original source code and dependency specifications (`requirements.txt`, `CMakeLists.txt`, `Cargo.toml`). + +* **Licensing Goal**: You want **maximum adoption** and zero friction for commercial or academic reuse. +* **Legal Reality**: External dependencies remain separate works. Because you have not bundled third-party code inside your repository, no inbound license terms constrain your choice. +* **JLA Selection Strategy**: To ensure downstream users must acknowledge your original authorship while granting them maximum flexibility to incorporate your code into both open and proprietary software, you require citation credit (`Incl. Copyright`) without imposing share-alike conditions (leaving `Copyleft/Share a.` unselected). + +:::{solution} +**What to select in the JLA interface:** + +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright` +3. **Support Column**: Select `OSI approved` + +* **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` + +* **Permissive vs. Public Domain (EU Civil Law Nuance)**: Public domain dedications (e.g., `CC0`, `Unlicense`) attempt to give away all rights. However, under EU civil law, authors cannot legally give up their moral rights (*droit moral*). Selecting an explicit permissive license like `MIT` or `Apache-2.0` grants broad permissions globally, remains legally valid under European copyright law, and guarantees academic citation credit. + +* **Downstream Obligations**: Anyone who reuses, modifies, or integrates your code into their work must preserve your copyright notice and license text. They are not required to share their modifications or open-source their downstream projects. -- A. Download some code from a website and add on to it - - votes: +* **Allowed Inbound Snippets**: If you want to include small third-party code snippets in your files, you can freely embed code licensed under **permissive terms** (e.g., MIT, BSD, Apache-2.0, 0BSD) or public domain waivers (CC0) without affecting your permissive license. However, embedding copyleft snippets (e.g., GPL, EUPL) might trigger reciprocal obligations requiring you to re-license. Whether it does depends on which copyleft: weak copyleft (LGPL, MPL-2.0) often lets your surrounding code stay permissive, while strong copyleft generally does not. -- B. Download some code and use one of the functions in your code - - votes: +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your scripts: -- C. Changing code you got from somewhere - - votes: +```python +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name -- D. Extending code you got from somewhere - - votes: +import numpy as np +``` +::: +:::: + +(scenario-2)= +::::{exercise} Scenario 2: Choosing reciprocity for your own implementation +You developed a custom solver implementing algorithms from academic literature. You want any downstream improvements, extensions, or modifications to remain open-source and be shared back with the scientific community. + +* **Licensing Goal**: You want to enforce **reciprocity** (share-alike), preventing third parties from incorporating your implementation into proprietary software without sharing their modifications. +* **Legal Reality**: The published algorithm itself is an unprotected idea — anyone may implement it independently, as Scenario 1 and the *SAS* ruling establish. What copyright protects is *your* specific implementation. Nothing about implementing a published method forces a particular license; copyleft here is your deliberate choice to bind downstream distributors to matching terms. +* **JLA Selection Strategy**: To enforce reciprocal sharing, you must mandate that downstream distributors disclose their modified source code (`Disclose source`) and license their adaptations or combined works under matching terms (`Copyleft/Share a.`). + +:::{solution} +**What to select in the JLA interface:** -- E. Completely rewriting code you got from somewhere - - votes: +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright`, `Disclose source`, and `Copyleft/Share a.` +3. **Support Column**: Select `OSI approved` -- F. Rewriting code to a different programming language - - votes: +* **Example JLA Matches**: `EUPL-1.2`, `GPL-3.0`, `AGPL-3.0` -- G. Linking to libraries (static or dynamic), plug-ins, and drivers - - votes: +* **Copyleft Mechanics (EUPL vs. GPL Nuance)**: `GPL-3.0` is the standard global copyleft license, but `EUPL-1.2` is specifically tailored for European institutions. EUPL-1.2 is officially published in 23 EU language versions (each with equal legal validity), includes built-in compatibility clauses with GPL, and explicitly defaults to EU Member State jurisdiction and courts. +* **A caution before choosing strong copyleft**: reciprocity also limits who can combine with your code. Strong copyleft licenses are frequently incompatible with each other, so a future collaborator on a differently-licensed copyleft project may be unable to use your work at all. Scenario 5 covers this. +* **Downstream Obligations**: Anyone who distributes your code or a modified version of it must provide complete access to the corresponding source code under the same copyleft license and preserve your original copyright notices. -- H. Clean room design (somebody explains you the code but you have never seen it) - - votes: +* **Allowed Inbound Snippets**: You can freely embed code snippets licensed under **permissive terms** (e.g., MIT, Apache-2.0, BSD) or public domain waivers (CC0). You may also embed snippets from compatible copyleft code (e.g., EUPL, GPL). However, you cannot embed closed-source or proprietary code snippets. -- I. You read a paper, understand algorithm, write own code - - votes: +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your scripts: + +```python +# SPDX-License-Identifier: EUPL-1.2 +# Copyright (c) 2026 Author Name + +import numpy as np ``` +::: +:::: + +## Module 2: The Dependency Minefield – Inbound Code & Linking + +Embedding third-party snippets or linking against external libraries introduces boundaries that can constrain your license choice. How far those boundaries reach depends on which license the inbound code carries. + +(scenario-3)= +::::{exercise} Scenario 3: Embedding permissively licensed third-party code +You are building an RSE tool and copied a helper function or utility snippet from a third-party project licensed under a permissive license (e.g., MIT or Apache-2.0) directly into one of your source files. + +* **Licensing Goal**: You want to maintain a **permissive default** for your project while properly acknowledging and legally respecting the embedded third-party code. +* **Legal Reality**: Permissive licenses explicitly grant you permission to copy, modify, and embed their code into your repository. However, embedding permissive code does not make the original third-party copyright disappear, you must preserve the original copyright attribution and license terms for that specific snippet. +* **JLA Selection Strategy**: Because inbound permissive code gives you maximum licensing flexibility, your overall repository can remain permissively licensed. To reflect this, select citation obligations (`Incl. Copyright`) without imposing reciprocal sharing constraints (leaving `Copyleft/Share a.` unselected). + +:::{solution} +**What to select in the JLA interface:** + +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright` +3. **Support Column**: Select `OSI approved` + +* **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` + +* **Notice Preservation Nuance**: Permissive licenses are flexible, but they are not license-free. If you copy code from an Apache-2.0 or BSD-3-Clause project into your MIT-licensed repository, you must retain the original author's copyright statement and license identifier directly above the embedded code block. Your repository license covers *your* code. It does not relicense the embedded snippet — that code stays under its original license and its original copyright holder's terms. You are distributing one file containing two separately licensed contributions, which is why both notices must appear. -```{solution} -- Derivative work: A-F -- Not derivative work: G-I -- E and F: This depends on how you do it, see clean room design. +* **Downstream Obligations**: Downstream users receive your project under your primary permissive license (e.g., MIT), but they must preserve both your overall copyright notice and the specific third-party notices attached to embedded snippets. + +* **Allowed Inbound Snippets**: In addition to the embedded permissive snippet, you can freely embed other permissively licensed code (MIT, BSD, Apache-2.0) or public domain waivers (CC0).Embedding **strong** copyleft code (GPL, EUPL) generally requires re-licensing your repository to match. Weak copyleft (LGPL, MPL-2.0) applies at a narrower boundary and often does not + +* **In-File Identification (SPDX)**: Mark both your overall file license and the specific embedded snippet using SPDX comments: + +```python +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name + +# --- Embedded Third-Party Snippet --- +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 External Contributor +def fast_matrix_solver(matrix): + # Embedded algorithm implementation + return np.linalg.solve(matrix, np.eye(len(matrix))) +# --- End Embedded Snippet --- + +def main(): + pass ``` -```` +::: +:::: + +(scenario-4)= +::::{exercise} Scenario 4: Embedding copyleft third-party code +You are building a software tool and copied a non-trivial code snippet from a third-party project licensed under a copyleft license (e.g., GPL-3.0 or EUPL-1.2) directly into one of your source files. + +* **Licensing Goal**: Comply with legal requirements imposed by the inbound copyleft code while ensuring your overall repository remains legally compliant. +* **Legal Reality**: Copying a non-trivial copyleft snippet into your source files creates a single combined work, so copyleft licensing generally extends to your whole project. "Non-trivial" matters: a snippet too short or purely functional to qualify as the author's own intellectual creation (Art. 1(3)) may not carry copyright at all. There is no word count or line count that draws this line — if you are unsure, assume it is protected and either comply or reimplement. +* **JLA Selection Strategy**: Because the inbound copyleft code forces your repository to adopt reciprocal sharing terms, you must configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). +:::{solution} +**What to select in the JLA interface:** -```{admonition} Plagiarism vs. Intellectual Property Rights = Research Ethics vs Law -*This insert can be skipped and left as reading exercise* +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright`, `Disclose source`, and `Copyleft/Share a.` +3. **Support Column**: Select `OSI approved` -In academic context it is important to consider also *plagiarism* and how it relates to copyright and more broadly Intellectual Property Rights ([a clear explanation at this page](https://scholarworks.duke.edu/copyright-advice/copyright-faq/copyright-and-plagiarism/)). Plagiarism is the practice of taking somebody else's ideas or work and claim them as your own: it is the **unacknowledged** use of another person's work. Intellectual Property Rights (IPRs) infringement instead is the **unauthorised** use of another's work. +* **Example JLA Matches**: `GPL-3.0`, `EUPL-1.2` -IPRs can be classified in two main groups ([WTO](https://www.wto.org/english/tratop_e/trips_e/intel1_e.htm)): i) Copyright and rights related to copyright (computer programs are here) and ii) Industrial properties like trademarks, and inventions (which may include specific technical implementations of systems or code) protected by patents. +* **Copyleft Scope & EUPL Compatibility (Legal Nuance)**: Directly copying copyleft code into your source files extends the copyleft obligation to your entire codebase. If the embedded snippet is `EUPL-1.2`, its built-in compatibility provisions allow you to license your combined project under `GPL-3.0` if your project ecosystem requires it, resolving license conflicts without violating EUPL terms. -In research ethics, plagiarism is one of the three definition of research misconduct (along with *fabrication* and *falsification*, see ALLEA, [European Code of Conduct for Research Integrity](https://allea.org/wp-content/uploads/2023/06/European-Code-of-Conduct-Revised-Edition-2023.pdf)). Plagiarism is not illegal per se, but it can lead to serious consequences like the retraction of published work. One can engage in plagiarism, without necessarily breaking any IPR law (e.g. write a new book by reusing the plot of an old book that is not under copyright anymore). Copyright infringment instead is illegal and it can result in criminal charges (e.g. fines). Copyright however protects the particular expression of an idea or fact (for example, the specific source code of a program, but not the underlying algorithm itself). +* **Downstream Obligations**: Anyone who receives, modifies, or distributes your repository must receive full access to the source code under the same copyleft license terms (`GPL-3.0` or `EUPL-1.2`) and preserve all copyright notices. -There is no pre-defined "number of lines of code", "seconds of a song", or "pixels of an image" that can clearly set the basis for plagiarism or IPR infringement. However in the context of research, it can be possible to use *Quotation Exception* (in EU, [ref](https://www.copyrightexceptions.eu/exceptions/info53d/)) and *Fair use* (in USA, [ref](https://en.wikipedia.org/wiki/Fair_use)). Fair use has become controversial recently as it is used as legal basis for training large language models based on scraped internet data ([See for example Henderson, P., Li, X., Jurafsky, D., Hashimoto, T., Lemley, M. A., & Liang, P. (2023). Foundation models and fair use. Journal of Machine Learning Research, 24(400), 1-79.](https://www.jmlr.org/papers/v24/23-0569.html)) +* **Allowed Inbound Snippets**: Because your overall repository is now governed by a copyleft license, you can safely embed code from **permissive sources** (MIT, BSD, Apache-2.0, CC0) as well as **compatible copyleft sources**. You cannot embed proprietary, closed-source code or snippets from incompatible copyleft licenses. + +* **In-File Identification (SPDX)**: Mark your overall file license and clearly cite the embedded copyleft snippet using SPDX comments: + +```python +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2026 Author Name + +# --- Embedded Copyleft Snippet --- +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2023 External Researcher +def optimized_fft_filter(data_signal): + # Embedded copyleft algorithm implementation + return np.fft.fft(data_signal) +# --- End Embedded Snippet --- + +def main(): + pass ``` +::: +:::: + +## Module 3: Dependency Linking & Packaging + +When software incorporates external dependencies, whether by dynamic linking, static compiling, or bundling binaries into container images licensing obligations expand beyond your own written source code. This module covers how dependency boundaries, build automation scripts, and packaged container artifacts affect legal compliance under the Joinup Licensing Assistant (JLA) framework. + +(scenario-5)= +::::{exercise} Scenario 5: Linking against a GPL-licensed library +You are developing a software application that imports or links against an external software library licensed under GPL-3.0 (e.g., importing a GPL Python package or linking a C/C++ static/shared library). -### Derivative work and containers +* **Licensing Goal**: Ensure legal compliance while using copyleft libraries as core dependencies in your software project. +* **Legal Reality**: Whether linking creates a combined work is genuinely unsettled, and often has to be decided case by case. The FSF's position is that linking a GPL library — statically or dynamically — creates a combined work; some legal scholars and Commission EUPL guidance disagree, particularly for dynamic linking through a stable API. Most Member States have no case law on this, so no firm general rule can be stated. The guidance below follows the conservative, widely-adopted reading. +* **JLA Selection Strategy**: Because linking to a GPL library requires your distributed project to be released under matching reciprocal terms, you must configure JLA to mandate source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). -Containers are a bit more tricky when it comes to licenses. +:::{solution} +**What to select in the JLA interface:** -- Distribution of container recipes: it's like distributing source code -- Distribution of container images: it can be considered like distributing a binary compiled software +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright`, `Disclose source`, and `Copyleft/Share a.` +3. **Support Column**: Select `OSI approved` -The latter case is a bit more nuanced and the interested reader should read more about "Mere Aggregation" at [GPL-FAQ](https://www.gnu.org/licenses/gpl-faq.html#MereAggregation). Briefly, if the container image just bundles separate programs that talk through normal system interfaces, it is an **aggregate** and each keeps its own license (like a CD-ROM with various packages). If the components are tightly integrated into one program (e.g. a pipeline with various parts that the container can run as a single program), the image may be treated as a **derivative work**, and stricter license obligations (e.g. GPL copyleft) can apply. +* **Example JLA Matches**: `GPL-3.0`, `EUPL-1.2` + +* **Linking Boundaries & License Selection (Legal Nuance)**: + * **Why GPL forces copyleft**: Linking against a standard `GPL-3.0` library extends copyleft to your entire project. Your repository must adopt a compatible copyleft license (`GPL-3.0` or `EUPL-1.2`, which explicitly lists GPL-3.0 in its compatibility appendix). +* **Copyleft licenses are not compatible with each other**: two strong copyleft licenses can each demand that the combined work use *their* terms, which makes the combination undistributable. The classic trap is `GPL-2.0-only`: without the "or later" clause you cannot upgrade to GPL-3.0 to resolve a conflict, so GPL-2.0-only code cannot be combined with GPL-3.0 or Apache-2.0 code at all. Always check the exact SPDX identifier — `GPL-2.0-only` and `GPL-2.0-or-later` behave very differently. +* **Downstream Obligations**: Anyone to whom you **distribute** the application must receive full access to your source code under `GPL-3.0` (or `EUPL-1.2`), along with upstream copyright notices and the build scripts needed to recompile it. Running the software internally, without distributing it, creates no such obligation — though note that `AGPL-3.0` extends this to network use. + +* **Allowed Inbound Code & Dependencies**: Your project can import or include other **permissively licensed** packages (MIT, BSD, Apache-2.0) and public domain waivers (CC0). However, all code linked together in the final executable or runtime environment must satisfy GPL compatibility. + +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your main scripts: + +```python +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2026 Author Name + +import gpl_licensed_solver # External GPL dependency forces GPL/EUPL compliance + +def solve_system(data): + return gpl_licensed_solver.compute(data) +``` +::: +:::: + + +(scenario-6)= +::::{exercise} Scenario 6: Authoring container recipes and environment specifications +You are creating a `Dockerfile`, Conda `environment.yml`, or build recipe to automate the setup of your research environment. The recipe itself contains setup instructions, shell commands, and package lists. + +* **Licensing Goal**: You want **maximum adoption** and reuse of your build automation script so other researchers can freely adapt and build upon your workflow. +* **Legal Reality**: Build recipes and configuration scripts are plain-text source code, separate from the software binaries they download at build time. The build instructions you write are your expression — but note that a very short recipe (a `FROM` line plus two `RUN` commands) may be too trivial to meet the Art. 1(3) originality threshold and may not attract copyright at all. Longer, non-obvious recipes clearly do. +* **JLA Selection Strategy**: To allow anyone to reuse or adapt your container recipe without restrictions, you require citation credit (`Incl. Copyright`) while leaving reciprocal requirements (`Copyleft/Share a.`) unselected. + +:::{solution} +**What to select in the JLA interface:** + +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright` +3. **Support Column**: Select `OSI approved` + +* **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` + +* **Recipe vs. Image Nuance**: The license applied to a `Dockerfile` covers only the recipe instructions, not the software packages installed inside the container when `docker build` runs. A permissively licensed Dockerfile can install both permissive and copyleft packages without legal conflict. + +* **Downstream Obligations**: Anyone who reuses or adapts your build recipe must preserve your original copyright notice in the header of the recipe file. + +* **Allowed Inbound Snippets**: You can freely include build commands and code snippets from permissively licensed build scripts or public domain code. + +* **In-File Identification (SPDX)**: Place SPDX identifier comments at the top of your Dockerfile or recipe file: + +```dockerfile +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name + +FROM ubuntu:24.04 +RUN apt-get update && apt-get install -y python3 python3-pip +COPY solver.py /app/solver.py +``` +::: +:::: --- -## Taxonomy of software licenses +(scenario-7)= +::::{exercise} Scenario 7: Distributing pre-built container images +You compiled and published a pre-built container image (e.g., pushing a compiled Docker image to Docker Hub, GitHub Container Registry, or an institutional registry) containing an OS layer, runtime binaries, dependencies, and your application code. + +* **Licensing Goal**: Safely distribute compiled container images without violating the license terms of any software layer or binary included inside the image. +* **Legal Reality**: A compiled container image is a **multi-license aggregate bundle**, not a single combined work. Distributing pre-built binaries makes you a distributor of every package inside, so source-availability obligations apply to the copyleft components (Linux base packages, coreutils, GPL libraries). But those packages sitting in the same filesystem as your application do not make your application a derivative of them, this is mere aggregation. Your own code keeps whatever license you chose; you simply also carry distributor obligations for the copyleft software you are shipping alongside it. +* **JLA Selection Strategy**: Because a container image combines multiple distinct software components, JLA is used to evaluate constituent component obligations. When distributing compiled binaries containing copyleft layers, source disclosure requirements (`Disclose source`) must be fulfilled for those specific layers. + +:::{solution} +**What to select in the JLA interface:** + +1. **Can Column**: Select `Distribute` and `Commercial use` +2. **Must Column**: Select `Incl. Copyright` and `Disclose source` +3. **Support Column**: Select `OSI approved` + +* **JLA Outcome**: No single license applies. Use JLA per component to check each one's obligations, then record the aggregate in your image metadata. + +* **Multi-License Aggregation Nuance**: Applying a permissive license (like MIT) to your application code inside the container does not override or erase the GPL/LGPL obligations of base system packages installed in `/usr/lib` or `/usr/bin`. Distributing the built image binary makes you a distributor of all installed packages. + +* **Downstream Obligations**: You must ensure downstream users can obtain the corresponding source for the copyleft components you shipped. Publishing your `Dockerfile` documents the build but does not by itself satisfy this — the GPL asks for the source of the binaries actually distributed. In practice, most research images rely on unmodified upstream distribution packages, where pointing to the distributor's public source archives (as GPLv3 §6(d) permits) is the normal approach. If you modify or rebuild a copyleft component yourself, you must provide that source directly. + +* **Allowed Inbound Packages**: Before publishing an image binary, run automated compliance scanning tools (e.g., Syft, Trivy) to generate a Software Bill of Materials (SBOM) and verify that no non-redistributable or proprietary software is packaged inside. -```{figure} img/license-models.png -:alt: "European Union Public Licence (EUPL): guidelines July 2021" +* **In-File Identification (Metadata Annotations)**: Document the multi-license nature of the aggregate bundle using standard OCI (Open Container Initiative) image labels inside your Dockerfile: -European Commission, Directorate-General for Informatics, Schmitz, P., European Union Public Licence (EUPL): guidelines July 2021, Publications Office, 2021, +```dockerfile +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name + +FROM ubuntu:24.04 +LABEL org.opencontainers.image.authors="author@institute.eu" +# OCI Standard Image Annotations for Docker Hub Compliance +LABEL org.opencontainers.image.title="My Research Pipeline" +LABEL org.opencontainers.image.licenses="MIT AND GPL-3.0-or-later" +LABEL org.opencontainers.image.vendor="My Institute Name" +LABEL org.opencontainers.image.description="Includes Ubuntu 24.04 base layers (GPL/LGPL) and custom solver (MIT)" + +COPY solver.py /app/solver.py ``` +::: +:::: + +## Module 4: Emerging Workflows & AI + +AI-assisted development tools and machine learning models introduce unique legal challenges regarding copyright ownership, training data memorization, and behavioral restrictions. This module addresses how to license projects built with AI code generation tools and how to package research software that bundles AI models, weights, and datasets alongside source code. + +--- + +(scenario-8)= +::::{exercise} Scenario 8: AI-assisted code generation +You used AI tools (e.g., GitHub Copilot, ChatGPT, Claude) to write functions, unit tests, or documentation for your research software repository. + +* **Licensing Goal**: Retain clear ownership and apply a **permissive license** (`MIT` or `Apache-2.0`) to your repository without incurring hidden copyright infringement or copyleft obligations from code embedded during model training. +* **Legal Reality**: Unmodified AI-generated outputs lack human authorship and are generally not eligible for copyright protection under current EU and international legal standards. However, if an LLM reproduces a substantial copyrighted code snippet verbatim from its training data (memorization), that output snippet retains its original copyright and license obligations. +* **JLA Selection Strategy**: To ensure maximum adoption and academic reuse for your overall codebase, require citation credit (`Incl. Copyright`) while avoiding share-alike constraints (leaving `Copyleft/Share a.` unselected), supported by automated compliance checks. + +:::{solution} +**What to select in the JLA interface:** + +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright` +3. **Support Column**: Select `OSI approved` + +* **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` + +* **Marking AI-generated code**: Some projects and AI tool terms require contributors to disclose AI involvement — via a commit trailer, a PR checkbox, or an in-file comment. Even where it is optional, marking AI-assisted sections is increasingly recommended practice: it records provenance, signals to reviewers where extra scrutiny is warranted, and makes later authorship or infringement questions much easier to resolve. Check the contribution guidelines of any project you submit to. +* **Downstream Obligations**: Downstream users must preserve your copyright notice for the repository. They are free to reuse, modify, and integrate your code into commercial or open-source projects. + +* **Allowed Inbound Snippets**: You can include permissively licensed code, public domain code (CC0), and AI-generated snippets that have been verified against verbatim training data duplication. + +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your scripts: -Comments: -- Arrows represent compatibility (A -> B: B can reuse A) -- Proprietary/custom: Derivative work typically not possible (no arrow goes from proprietary to open) -- Permissive: Derivative work does not have to be shared -- Copyleft/reciprocal: Derivative work must be made available under the same license terms -- NC (non-commercial) and ND (non-derivative) exist for data licenses but not really for software licenses - -**Great resource for comparing software licenses**: [Joinup Licensing Assistant](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) -- Provides comments on licenses -- Easy to compare licenses ([example](https://joinup.ec.europa.eu/licence/compare/BSD-3-Clause;Apache-2.0)) -- [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) -- Not biased by some company agenda - -If you would like to learn more about licenses, check out our slide deck: ["Software licensing -and open source explained with -cakes"](https://cicero.xyz/v3/remark/0.14.0/github.com/coderefinery/social-coding/main/licensing-and-cakes.md/). - - -## Exercise: Licensing situations - -````{exercise} Licensing-2: Consider some common licensing situations -1. What is the StackOverflow license for code you copy and paste? -2. A journal requests that you release your software during publication. You have - copied a portion of the code from another package, which you have forgotten. - Can you satisfy the journal's request? -3. You want to fix a bug in a project someone else has released, but there is no license. What risks are there? -4. How would you ask someone to add a license? -5. You incorporate MIT, GPL, and BSD3 licensed code into your project. What possible licenses can you pick for your project? -6. You do the same as above but add in another license that looks strong copyleft. What possible licenses can you use now? -7. Do licenses apply if you don't distribute your code? Why or why not? -8. Which licenses are most/least attractive for companies with proprietary software? - -```{solution} -1. As indicated [here](https://stackoverflow.com/help/licensing), all publicly accessible user contributions are licensed under [Creative Commons Attribution-ShareAlike](https://creativecommons.org/licenses/by-sa/4.0/) license. See Stackoverflow [Terms of service](https://stackoverflow.com/legal/terms-of-service/public#licensing) for more detailed information. -2. "Standard" licensing rules apply. So in this case, you would need to remove the portion of code you have copied from another package before being able to release your software. -3. By default you are no authorized to use the content of a repository when there is no license. And derivative work is also not possible by default. Other risks: it may not be clear whether you can use and distribute (publish) the bugfixed code. For the repo owners it may not be clear whether they can use and distributed the bugfixed code. However, the authors may have forgotten to add a license so we suggest you to contact the authors (e.g. make an issue) and ask whether they are willing to add a license. -4. As mentionned in 3., the easiest is to fill an issue and explain the reasons why you would like to use this software (or update it). -5. Combining software with different licenses can be tricky and it is important to understand compatibilities (or lack of compatibilities) of the various licenses. GPL license is the most protective (BSD and MIT are quite permissive) so for the resulting combined software you could use a GPL license. However, re-licensing may not be necessary. -6. Derivative work would need to be shared under this strong copyleft license (e.g. AGPL or GPL), unless the components are only plugins or libraries. -7. If you keep your code for yourself, you may think you do not need a license. However, remember that in most companies/universities, your employer is "owning" your work and when you leave you may not be allowed to "distribute your code to your future self". So the best is always to add a license! -8. The least attractive licenses for companies with proprietary software are licenses where you would need to keep an open license when creating derivative work. For instance GPL and and AGPL. The most attractive licenses are permissive licenses where they can reuse, modify and relicense with no conditions. For instance MIT, BSD and Apache License. +```python +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name + +def filter_sensor_data(raw_readings: list[float]) -> list[float]: + """Cleans raw sensor data (written with AI assistance and human review).""" + return [reading for reading in raw_readings if reading > 0.0] ``` -```` - - -## When should I add a license? - -**Choose a license early in the project, even before you publish it**. Later in -the project it may become complicated to change it. Agreeing on a software -license does not mean that you have to make it open immediately. You can also -follow the **"open core" approach**: You don't have to open source all your -work. Core can be open and on a public branch. Unpublished code can be on a -private repository. - -However, we recommend to **work as if the code is public even though it still -may be private** (thanks to E. Glerean for this great suggestion): This is to -avoid surprises about code in the history with incompatible license years later -when you decide to open the project. - - -## How to add a license if your work is derivative work - -Your code is derivative work if you have started from an existing code and -made changes to it or if you incorporated an existing code into your code. - -If your code is derivative work, then **you need to check the license of the -original code**. Depending on the license, your choices might be limited. In -this case we recommend to use these two resources: -- [Joinup Licensing Assistant - Find and compare software licenses](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) -- [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) - -If the original code does not have a license, you may not be able to distribute your -derivative code. You can try to contact the authors and ask them to clarify -the license of their code. - -Practical steps for **incorporating something small into your own project** with a license -that allows you to do so (as -an example incorporating a function or two from another project): -- Create a `LICENSES/` folder in your project and "put the unmodified license text - (i.e., the license text template without any copyright notices) in your - `LICENSES/` folder" (). This - way if you reuse code from multiple projects, you can keep there multiple - license files. -- **Put the code that you incorporate into a separate file or separate files**. This makes - it later easier to see what was incorporated, and what was written from scratch. - On top of the file(s) which you have incorporated into your project add (and - adapt) the following header ([more examples](https://reuse.software/faq/)): - ```python - # SPDX-FileCopyrightText: 2023 Jane Doe - # - # SPDX-License-Identifier: MIT - ``` - The [REUSE](https://reuse.software/) initiative was started by the [Free - Software Foundation Europe](https://fsfe.org/) to make licensing of software - projects easier. It is OK if you prefer to not follow this strict format but - the advantage of following it is that the - [reuse-tool](https://github.com/fsfe/reuse-tool) makes it then easy to verify - and update license headers if you have many files from different sources. -- If it does not make sense to have several files in your project (e.g. when incorporating - something into a notebook), then add a note/comment - about the license and where the code came from on top of the function. -- Although it is not dictated by the license but it can still be nice to - acknowledge the incorporated functions/code in your README/documentation and to cite - their work if you publish a paper about your code. -- Some licenses are more permissive (you can keep your changes private) but some licenses - require you to publish the changes (share-alike). - -Practical steps for making **changes to an existing project** with a license -that allows you to do so: -- If the project is on GitHub or GitLab or similar, first fork the project - (copy it into your user space where you can make changes). -- For the BSD and MIT licenses you are not obliged to state your changes but it can - still be helpful for others if you do. You can state your changes in the - header of the files you have modified. It can be helpful to state - bigger-picture changes in the README file of the project. -- Some licenses are more permissive (you can keep your changes private) but some licenses - require you to publish the changes (share-alike). - - -### If your work is not derivative work - -If you have started "from scratch", and not used any existing code, or -incorporated existing code into your code, then you may consider your code to -be not derivative work. - -Before you may choose a license, clarify the following points with, for -example, your supervisor, collaborators, or principal investigator: -- Does your work contract, grant, or collaboration agreement dictate a - specific license? -- Is there an intent to commercialize the code? -- When there is unknown or mixed ownership: If there are multiple persons or - organizations as owners of the code, all must agree to the license. - -**Do not invent your own license**. Choose one of the standard licenses, otherwise -compatibility is not clear: - - [Joinup Licensing Assistant - Find and compare software licenses](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) - - [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) - -Practical steps: -- Create a `LICENSES/` folder ([example](https://github.com/bast/runtest/tree/main/LICENSES)). -- Put the unmodified license text - (i.e., the license text template without any copyright notices) in plain - text format into the folder ([example](https://github.com/bast/runtest/tree/main/LICENSES)). Here are - the two above licenses in plain text: - [EUPL](https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/2020-03/EUPL-1.2%20EN.txt) - and [MIT](https://en.wikipedia.org/wiki/MIT_License#License_terms) (but the - latter contains a copyright notice which we rather want to have on top of - files). -- Add copyright and license information to each file following - which uses a standard format with - so-called [SPDX identifiers](https://spdx.org/licenses/). Example below - ([example](https://github.com/bast/runtest/blob/3b210d2e9bdbdc1903a1dab9da32e161d390092d/runtest/tuple_comparison.py#L1-L3)): - ```python - # SPDX-FileCopyrightText: 2023 Jane Doe - # - # SPDX-License-Identifier: EUPL-1.2 +::: +:::: + +--- + +(scenario-9)= +::::{exercise} Scenario 9: Packaging AI workflows, datasets, and model weights +You are developing research software that includes source code alongside trained machine learning model weights (`.pt`, `.safetensors`) and benchmark datasets. + +* **Licensing Goal**: Apply a clear **dual-licensing strategy** that makes both the software source code and the non-code assets (data, weights) open and reusable under appropriate legal frameworks. +* **Legal Reality**: Standard software licenses (MIT, GPL) are written for source code and fit datasets and model parameters poorly. Datasets may attract the EU *sui generis* database right where there has been substantial investment in obtaining, verifying, or presenting their contents. Model weights are a harder case: they are neither code nor a database, and whether they attract any copyright protection in the EU is genuinely unsettled. Because of this uncertainty, applying an explicit license to weights is about setting clear terms for your users, not about relying on a settled legal right. +* **JLA Selection Strategy**: Use JLA to select an OSI-approved open-source license for the executable code component (`Incl. Copyright` selected), while using Creative Commons licenses (e.g., `CC-BY-4.0` or `CC0`) for the dataset and weight files. + +:::{solution} +**What to select in the JLA interface:** + +1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` +2. **Must Column**: Select `Incl. Copyright` +3. **Support Column**: Select `OSI approved` + +* **Example JLA Matches**: `MIT`, `Apache-2.0` (for the code component) + +* **Code vs. Data/Weights & OpenRAIL Nuance**: Avoid applying software licenses like GPL or MIT to raw datasets or model weights — their terms reference source code, object code, and linking, which leaves users guessing about what applies. Use **CC-BY-4.0** or **CC0** for non-code assets instead. Note also that behavioral licenses (such as OpenRAIL) impose usage restrictions (e.g., prohibiting specific harmful uses), so they do **not** qualify as OSI-approved open source and will not appear in standard JLA queries. + +* **Downstream Obligations**: Downstream users must cite your repository for the code (under your chosen software license) and give credit for the model weights and data under the corresponding Creative Commons license. + +* **Allowed Inbound Assets**: You may combine permissively licensed python code with CC-BY-4.0 datasets or open-weight models, provided the attribution files clearly separate code licenses from data/weight licenses. + +* **In-File Identification (SPDX / Dual-Licensing Structure)**: Document the dual-licensing scheme in your root repository structure and script headers: + +```python +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Author Name +# +# Note: Source code is licensed under MIT. +# Model weights in /models/ and datasets in /data/ are licensed under CC-BY-4.0. + +import torch + +def load_pipeline(): + model = torch.load("models/climate_weights.safetensors") + return model +``` +::: +:::: + + +## Best Practices: Attaching a License to Your Repository + +Once you have selected a license using the JLA, you must officially attach it to your repository so automated scanners, package registries, and downstream users can verify your terms. + + +### 1. Adding the Root `LICENSE` File + +Always place the full text of your chosen license in a plain-text file named `LICENSE` or `LICENSE.txt` at the root of your repository. + +* **Exact Legal Text**: Copy the standard text directly from [spdx.org/licenses](https://spdx.org/licenses/) or [choosealicense.com](https://choosealicense.com/). +* **Copyright Header**: Ensure you fill in the copyright year and copyright holder line at the top of the license text: + ```text + Copyright (c) 2026 [Author Name or Institution Name] ``` - The [REUSE](https://reuse.software/) initiative was started by the [Free - Software Foundation Europe](https://fsfe.org/) to make licensing of software - projects easier. It is OK if you prefer to not follow this strict format but - the advantage of following it is that the - [reuse-tool](https://github.com/fsfe/reuse-tool) makes it then easy to verify - and update license headers if you have many files from different sources. -- For really small projects with one or two files the above may seem excessive - and some projects choose to not have copyright information on top of their - files and they only have one `LICENSE` file and that is - OK for really small projects. +* **Do Not Edit Terms**: Never modify the legal wording of standard licenses (e.g., removing clauses from GPL or MIT). Edited texts are no longer the license they claim to be: compliance scanners cannot classify them, package registries may flag them, and downstream users have to get their own legal review before touching your code. If a standard license does not fit, pick a different standard license. +### 2. Documenting License Status in `README.md` +Add a dedicated **License** section near the bottom of your repository's `README.md` file, along with a machine-readable badge: -```{admonition} Licensing code produced by generative AI systems +```markdown +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +``` -With generative AI tools for coding such as GitHub copilot, Cursor, or even basic chat implementations (ChatGPT, Claude, Grok, ...) the responsibility fully lays on the person who is going to use (and publish) the generated code. You can never blame the autopilot or the company who invented it, only the driver (you!). -There are various risks in using generative AI code (this is not a taxonomy). A few examples: +### 3. Automated Compliance with the REUSE Standard -- Risks for the derivative work: you think your code is doing what you asked, but you did not review it and your results are false -- Risks for the system in use: your generated code has software security issues, e.g. an import is a *typosquat* of an actual library (e.g. "microsoft" is spelled "rnicrosoft" and depending on the font you might totally miss it...) -- Risks related to licenses/IPR: you have generated code that is actually verbatim copy of fully copyrighted code, or code that requires a strict copyleft license. Plagiarism (ethics) also applies. +For multi-asset research repositories containing code, data, container build recipes, and prompt templates, follow the [FSFE REUSE Initiative](https://reuse.software/) standard: -If we focus on the last one, a recent paper ([ref](https://arxiv.org/html/2408.02487v1)) estimates that around 2% of AI generated code is "strikingly similar to existing open-source implementations". Generative AI tools are typically not able to provide an exact reference of where certain bits of generated code were copied from, so it is the responsibility of the researcher to verify that the produced code is citing and referencing the license of other published pieces of software. Possibly, future AI systems for code generation can be trained on code that share the same set of licenses (e.g. based only on MIT) to mitigate these risks. +1. **Include License Texts**: Place full license files inside a `LICENSES/` directory (e.g., `LICENSES/MIT.txt`, `LICENSES/GPL-3.0-or-later.txt`). +2. **Add In-File SPDX Headers**: Label every source file, build script, and prompt file with SPDX tags. +3. **Verify Compliance**: Run the automated REUSE linter in your CI/CD pipeline: +```bash +# Install and run REUSE compliance check +pip install reuse +reuse lint ``` ---- +When `reuse lint` passes, every asset in your codebase carries a declared, machine-readable license that downstream users can check. + +## Summary: Resolving the Compliance Pipeline + +When developing research software, license compliance is not an afterthought to debug at the end of a project, it is a proactive design choice. By using the **Joinup Licensing Assistant (JLA)** framework to align your repository license with your inbound dependencies from day one, your pipeline is far less likely to fail on a license conflict late in the project. + +The diagram below illustrates how selecting a compatible license upfront ensures your code passes automated compliance checks and results in a legally sound release: + +```{mermaid} +%%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff', 'fontSize': '16px' }}}%% +flowchart TB + + subgraph local["① What you do differently now — before pushing"] + direction LR + A["Paste a snippet
copied from somewhere"] --> L["Identify its
license family"] --> S["Choose a compatible
license + add
SPDX headers"] + end + + subgraph ci["② The same pipeline as before"] + direction LR + T["Build Trigger:
Push to my-code-base"] --> B["Run Compliance
Scanner"] --> C{"Check Inbound vs.
Outbound Terms"} + end + + S --> T + C -->|"terms match"| P["✅ BUILD PASS · job #143
Compliant, reusable release"] + + classDef pass fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; + classDef neutral fill:#f8f9fa,stroke:#495057,stroke-width:2px,color:#212529; + classDef fix fill:#e7f5ff,stroke:#1c7ed6,stroke-width:2px,color:#0b3d6b; + classDef box_fill fill:#ffffff,stroke:#adb5bd,stroke-width:1px; + + class P pass; + class A,T,B,C neutral; + class L,S fix; + class local,ci box_fill; +``` + +Compare this with the failing pipeline at the start of the lesson: the pipeline itself is identical. Nothing about the scanner changed — the only difference is two decisions made before pushing. + +### Scenario Mapping Across the Pipeline + +* **Choosing Your Own Terms ([Scenario 1](#scenario-1), [Scenario 2](#scenario-2) & [Scenario 3](#scenario-3))**: When you write original code, implement a published algorithm, or embed only permissive snippets, no inbound license constrains you — the choice follows your goal. Pick permissive (`MIT`, `Apache-2.0`) for maximum adoption, or copyleft (`EUPL-1.2`, `GPL-3.0`) if you want downstream improvements shared back. Either way, preserve any third-party notices attached to code you embedded. +* **Handling Inbound Copyleft ([Scenario 4](#scenario-4) & [Scenario 5](#scenario-5))**: Copying a non-trivial copyleft snippet (e.g., CC BY-SA code from Stack Overflow, or a GPL fragment) creates a combined work. Linking against a copyleft library may do the same, depending on the license and the linking method. In both cases, selecting a compatible copyleft license upfront (`GPL-3.0` or `EUPL-1.2`) satisfies the reciprocal terms and lets the scanner pass — and checking the exact SPDX identifier first avoids the `GPL-2.0-only` incompatibility trap. +* **Packaging and Build Automation ([Scenario 6](#scenario-6) & [Scenario 7](#scenario-7))**: Keep plain-text build recipes (Dockerfiles) permissively licensed for maximum reuse, while annotating compiled container image binaries as multi-license aggregate bundles to satisfy embedded base-layer obligations. +* **AI Assets and Dual-Licensing ([Scenario 8](#scenario-8) & [Scenario 9](#scenario-9))**: Run code-similarity scanners to catch LLM training memorization before releasing AI-assisted code, and apply dual-licensing to separate executable software code (`MIT`) from non-code datasets and model weights (`CC-BY-4.0`). +* **Standardized Distribution**: Adding machine-readable **SPDX headers** across every script, Dockerfile, and prompt template lets `reuse lint` confirm that every asset has a declared, documented license. Note what this does and does not prove: the linter verifies that declarations exist and are well-formed, not that they are legally correct or mutually compatible. Automation makes your intent auditable — it does not replace the judgment calls in the scenarios above. + +## Glossary + +````{admonition} Glossary of terms (click to expand) +:class: dropdown + +```{glossary} +0BSD + Zero-Clause BSD, a permissive license so minimal it doesn't even require keeping the copyright notice. + +Adaptation + EU term (Art. 4(1)(b)) for translating, arranging, or altering a program; roughly the US *derivative work*. + +AGPL-3.0 + Strong copyleft that also requires sharing source when users interact with modified software over a network. + +All Rights Reserved + Default for unlicensed software: nobody but the copyright holder may run, copy, modify, or share it. + +Apache-2.0 + Permissive license like MIT, plus an explicit patent grant and a requirement to note changes you made. + +API + Application Programming Interface: the defined way one program calls another. The idea of an interface is not protected by copyright; the code implementing it is. + +Author + The person who created the program; not always the copyright holder. + +BSD-3-Clause + Permissive license like MIT, plus a clause forbidding use of the authors' names to promote derived products. + +CC BY-SA + Creative Commons share-alike license used for code posted on Stack Overflow; adaptations must carry the same terms, much like copyleft. + +CC-BY-4.0 + Creative Commons license allowing any reuse if the creator is credited; suited to data, documentation, and models rather than code. + +CC0 + Creative Commons tool waiving rights as far as the law allows, placing a work as close to the public domain as possible. + +CI/CD + Continuous Integration / Continuous Delivery: automated pipelines that build, test, and check code on every push, including license compliance checks. + +CJEU + Court of Justice of the European Union; its rulings interpret EU law for all Member States. + +Combined work + One work formed by merging separately licensed code, e.g. embedding a snippet or static linking. + +Compatibility + Whether two licenses allow their code to be combined and distributed together. + +Container image + A built binary snapshot (`.sif`, OCI image) bundling many packages under many licenses. + +Container recipe + The plain-text build instructions (`Dockerfile`, `.def`); source code in its own right. + +Copyleft + Licenses requiring distributed adaptations to use matching terms (GPL-3.0, EUPL-1.2). + +Copyright holder + Whoever holds the economic rights and can license the work: the author, employer, or assignee. + +Corresponding source + The full source and build scripts needed to rebuild the exact binaries you distributed. + +Derivative work + US term (17 U.S.C. § 101) for a work based on another; EU law says *adaptation*. + +Distribution + Giving copies to others outside your organisation; this is what triggers copyleft obligations. + +Dynamic linking + Loading a separate library at runtime; whether it creates a combined work is unsettled. + +Economic rights + Exclusive rights to copy, adapt, and distribute; often exercised by the employer (Art. 2(3)). + +EPL-2.0 + Eclipse Public License, a weak copyleft license applying at the file/module level. + +EUPL-1.2 + The European Commission's copyleft license, available in 23 EU languages. + +Expression vs. ideas + Copyright protects your code, not the underlying algorithms, functionality, or interfaces. + +FSF + Free Software Foundation, the US non-profit that publishes the GPL family of licenses. + +GPL + GNU General Public License, the most widely used strong copyleft license. `GPL-3.0` is the current version; `GPL-2.0` is still common. + +Inbound licensing + The licenses on others' code you bring into your project. + +JLA + Joinup Licensing Assistant, the Commission's tool for comparing licenses. + +LGPL + Weak copyleft for libraries; your app may use other terms if it allows modifying and debugging the library. + +LLM + Large Language Model, the technology behind AI assistants such as ChatGPT, Copilot, and Claude. + +Memorization + When an AI model reproduces training code verbatim; that code keeps its original license. + +Mere aggregation + Separate programs shipped side by side; copyleft does not spread between them. + +MIT + The most widely used permissive license: short, simple, and requires only that the copyright and license notice be kept. + +MPL-2.0 + Mozilla Public License, a weak copyleft license applying per file: modified MPL files stay MPL, new files can use any license. + +OCI + Open Container Initiative, the standard format for container images used by Docker, Podman, and registries. + +OpenRAIL + Behavioral licenses for AI models that forbid specific harmful uses; because they restrict use, they are not OSI open source. + +Originality threshold + A program is protected only if it is the author's own intellectual creation (Art. 1(3)). + +OSI + Open Source Initiative, the non-profit that approves licenses as meeting the Open Source Definition. + +Outbound licensing + The license you choose for your own project. + +Permissive + Licenses allowing any reuse if notices are kept (MIT, Apache-2.0, BSD). + +Reciprocity + The copyleft requirement to share adaptations under matching terms. + +REUSE + FSFE standard for per-file license declarations; `reuse lint` checks they exist, not that they are correct. + +RSE + Research Software Engineer: a professional who develops and maintains software used in research. + +SPDX identifier + Standard license tag in file headers, e.g. `MIT`, `GPL-3.0-or-later`. + +SPDX version suffixes + `-only` and `-or-later`: `GPL-2.0-only` cannot move to GPL-3.0; `GPL-2.0-or-later` can. + +Static linking + Copying library code into your binary at build time; generally creates a combined work. + +Sublicense + Passing on permissions under your own terms; allowed by MIT, generally not by copyleft. + +Sui generis database right + EU right protecting databases built with substantial investment; unclear for model weights. +Viral / infectious + Misleading slang for copyleft; it does not spread by mere contact. -## Great resources - -- [Research institution policies to support research software (compiled by the Research Software Alliance)](https://www.researchsoft.org/software-policies/) -- Guide from the Aalto University in Finland: ["Opening your Software at Aalto University"](https://www.aalto.fi/en/open-science-and-research/opening-your-software-at-aalto-university) -- [Draft: Research software licensing guide](https://research-software.uit.no/blog/2023-software-licensing-guide/) -- [Joinup Licensing Assistant - Find and compare software licenses](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses) -- [Joinup Licensing Assistant - Compatibility Checker](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-compatibility-checker) -- [Social coding lesson material](https://coderefinery.github.io/social-coding/) by [CodeRefinery](https://coderefinery.org/) -- [Citation File Format (CFF)](https://citation-file-format.github.io/) -- [License Selector](https://ufal.github.io/public-license-selector/) -- [GitHub licensing guide](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository) -- [Choosing an open-source licence](https://www.software.ac.uk/resources/guides/choosing-open-source-licence) -- [Understanding Open Source and Free Software Licensing](http://www.oreilly.com/openbook/osfreesoft/) -- [Software Licenses in Plain English](https://tldrlegal.com) -- [Don's Bibliography of Ethical Source Reading and Resources](https://github.com/DEGoodmanWilson/Ethical-Resources) -- [Mikko Välimäki: The Rise of Open Source Licensing](http://lib.tkk.fi/Diss/2005/isbn9529187793/isbn9529187793.pdf) -- [Lawrence Rosen: Open Source Licensing](http://www.rosenlaw.com/oslbook.htm) -- [Aalto IPR Cheatsheet](https://users.aalto.fi/~darstr1/cheatsheets/ipr-cheatsheet.pdf) -- [Contributor License Agreements](https://jacobian.org/2009/sep/17/contributor-license-agreements/) -- [4OSS recommendations](https://softdev4research.github.io/recommendations/) -- [4OSS lesson](https://softdev4research.github.io/4OSS-lesson/) -- [Intellectual Property Rights (IPR), Licensing And Patents](http://oss-watch.ac.uk/resources/ipr) -- [Dispelling Open Source Confusion: An Introduction to Licenses](http://depth-first.com/articles/2006/12/29/dispelling-open-source-confusion-an-introduction-to-licenses/) -- (can send automatic pull request to your GitHub repo) -- -- -- Nadia Asparouhova (formerly Nadia Eghbal): "Working in Public: The Making and Maintenance of Open Source Software" (Stripe Press) -- [Open Source Guides](https://opensource.guide/) -- [The Architecture of Open Source Applications](http://aosabook.org) -- Christopher M. Kelty: ["Two Bits: The Cultural Significance of Free Software"](https://twobits.net/) (Duke University Press, 2008) -- [Open Source (Almost) Everything](http://tom.preston-werner.com/2011/11/22/open-source-everything.html) -- [99 ways to ruin an open source project](http://opensoul.org/99ways/) -- [Open Source Casebook](https://google.github.io/opencasebook/) - -```{keypoints} -- **You cannot ignore licensing**: default is "no one can make copies or - derivative works". +Weak copyleft + Reciprocity limited to a file (MPL-2.0) or library (LGPL). ``` diff --git a/requirements.txt b/requirements.txt index 2a7e803..684c460 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ Sphinx sphinx_rtd_theme sphinx_rtd_theme_ext_color_contrast +sphinxcontrib-mermaid==0.7.1 myst_nb git+https://github.com/rkdarst/sphinx-copybutton.git@exclude-unselectable-3 sphinx-lesson