From b4badeaedcc09148a24015b08782222754a86625 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:08:53 +0200 Subject: [PATCH 01/14] Remove old lessons --- content/software-licensing-old.md | 350 ------------------------------ 1 file changed, 350 deletions(-) delete mode 100644 content/software-licensing-old.md diff --git a/content/software-licensing-old.md b/content/software-licensing-old.md deleted file mode 100644 index 3707f90..0000000 --- a/content/software-licensing-old.md +++ /dev/null @@ -1,350 +0,0 @@ -# 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". -``` From fc5cd5882279be819519d7f2acc4ba64ce51fc1e Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:29:05 +0200 Subject: [PATCH 02/14] fix spdf --- content/index.rst | 1 - content/software-licensing.md | 25 +++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/content/index.rst b/content/index.rst index 430a25f..72f4a9d 100644 --- a/content/index.rst +++ b/content/index.rst @@ -78,7 +78,6 @@ Who is the course for? :maxdepth: 1 :caption: About - software-licensing-old.md All lessons CodeRefinery reusing diff --git a/content/software-licensing.md b/content/software-licensing.md index 96dc0de..7faade8 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -178,19 +178,26 @@ Developers working under EU statutory frameworks face a different legal reality 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: +Managed by the Linux Foundation, **SPDX** provides standardized short identifiers for licenses (`MIT`, `Apache-2.0`, `GPL-3.0-only`, `EUPL-1.2`). The [REUSE specification](https://reuse.software/), maintained by the FSFE, builds on SPDX to define how every file should declare its copyright and license. Each file starts with two tags: ```python +# SPDX-FileCopyrightText: 2026 Author Name # SPDX-License-Identifier: MIT -# Copyright (c) 2026 Author Name ``` +* **`SPDX-FileCopyrightText`** names the copyright holder and year. This may be your institution rather than you personally; check your institution's policy. +* **`SPDX-License-Identifier`** names the license, using the exact SPDX identifier. Watch the suffix: `GPL-3.0-only` and `GPL-3.0-or-later` behave differently, so choose deliberately. + +The tags only *point to* a license, so the full license text must also be in your repository. REUSE places one text file per license in a `LICENSES/` folder (e.g., `LICENSES/MIT.txt`). Running `reuse lint` then checks that every file carries both tags and that every license it names has its text present. + 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). @@ -322,8 +329,8 @@ When writing original code or implementing published algorithms, no third-party 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). +* **Legal Reality**: External dependencies remain separate works. Because you only list them and have not bundled third-party code inside your repository, no inbound license terms constrain your choice. This changes if you ship dependencies together with your code, for example in an executable or container image (see [Scenario 5](#scenario-5) and [Scenario 7](#scenario-7)). +* **JLA Selection Strategy**: To ensure downstream users must keep your copyright notice while granting them maximum flexibility to incorporate your code into both open and proprietary software, you require `Incl. Copyright` without imposing share-alike conditions (leaving `Copyleft/Share a.` unselected). :::{solution} **What to select in the JLA interface:** @@ -334,17 +341,19 @@ You wrote an original algorithm from scratch (in Python, C++, Rust, etc.). Your * **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. +* **Permissive vs. Public Domain (EU Civil Law Nuance)**: Public domain dedications (e.g., `CC0`, `Unlicense`) attempt to give away all rights. In many EU countries, authors cannot fully waive their rights, especially moral rights such as being named as the author. CC0 handles this with a fallback license, which makes it a good choice for data, but it explicitly grants no patent rights and is not OSI approved, so it is less suited to code. An explicit permissive license like `MIT` or `Apache-2.0` is valid across Europe and is the clearer choice for software. + +* **Credit vs. Citation**: Permissive licenses require users to keep your copyright notice in the code. They do not require anyone to cite you in a publication. For academic citation, add a `CITATION.cff` file to your repository. * **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. -* **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. +* **Allowed Inbound Snippets**: You can freely embed small third-party code snippets licensed under **permissive terms** (e.g., MIT, BSD, Apache-2.0, 0BSD), keeping their notices, without affecting your permissive license. Copying copyleft code into your files is different: strong copyleft (e.g., GPL, EUPL) generally requires re-licensing your project, and pasted weak copyleft code does not stay contained either. Pasted MPL-2.0 code makes that file MPL-covered, and pasted LGPL code is treated like GPL. Weak copyleft only lets your code stay permissive when you use it as a separate file or library (see [Scenario 4](#scenario-4)). -* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your scripts: +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX tags directly at the top of your scripts, following the [REUSE specification](https://reuse.software/): ```python +# SPDX-FileCopyrightText: 2026 Author Name # SPDX-License-Identifier: MIT -# Copyright (c) 2026 Author Name import numpy as np ``` From 7f4c362fb906c1b8e53d885774e44e94a12bb7e7 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:30:37 +0200 Subject: [PATCH 03/14] fix spdf scenario 2 --- content/software-licensing.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 7faade8..0da18d4 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -360,6 +360,7 @@ 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. @@ -377,17 +378,19 @@ You developed a custom solver implementing algorithms from academic literature. * **Example JLA Matches**: `EUPL-1.2`, `GPL-3.0`, `AGPL-3.0` -* **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. +* **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) and sets the applicable law and courts by reference to the licensor's EU Member State. Its compatibility clause works in one direction only: EUPL code can be combined into a GPL project and distributed under GPL, but GPL code cannot be re-licensed under EUPL. +* **AGPL and network use**: `AGPL-3.0` adds one rule to GPL-3.0: if you modify the software and let people use it over a network (for example a web portal or API), you must offer them the source code, even if you never distribute copies. Consider it if your group runs research software as an online service. +* **The trade-offs of strong copyleft**: Reciprocity comes at a cost. Some companies and projects avoid copyleft code entirely, so you may reach fewer users than with a permissive license. Strong copyleft licenses are also 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](#scenario-5) covers this). Neither choice is better: Scenario 1 optimizes for reach, this scenario for keeping improvements open. +* **Choose deliberately, early**: Changing your license later is only possible if you hold all the rights. Once others have contributed code, you need every contributor's agreement to re-license. +* **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. Running modified code internally, without distributing it, creates no obligation (except under AGPL for network use). -* **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. +* **Allowed Inbound Snippets**: You can freely embed code snippets licensed under **permissive terms** (e.g., MIT, Apache-2.0, BSD), keeping their notices, or public domain waivers (CC0). Copyleft snippets must be compatible with *your* license, and compatibility is directional: a **GPL** project can take EUPL or GPL snippets, but a GPL snippet in an **EUPL** project would require the combined work to be distributed under GPL. When in doubt, only embed copyleft code under the same license as your project. You cannot embed closed-source or proprietary code snippets. -* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your scripts: +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX tags directly at the top of your scripts, following the [REUSE specification](https://reuse.software/). If you choose GPL, use `GPL-3.0-only` or `GPL-3.0-or-later` rather than plain `GPL-3.0`, since the two behave differently when a new GPL version is released: ```python +# SPDX-FileCopyrightText: 2026 Author Name # SPDX-License-Identifier: EUPL-1.2 -# Copyright (c) 2026 Author Name import numpy as np ``` From a7488245763cc7e889fc0f7e8f3b4918a614db72 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:32:13 +0200 Subject: [PATCH 04/14] fix spdf scenario 3 --- content/software-licensing.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 0da18d4..710734d 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -401,13 +401,14 @@ import numpy as np 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). +* **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 notice 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, require that notices are kept (`Incl. Copyright`) without imposing reciprocal sharing constraints (leaving `Copyleft/Share a.` unselected). :::{solution} **What to select in the JLA interface:** @@ -418,25 +419,31 @@ You are building an RSE tool and copied a helper function or utility snippet fro * **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. +* **Notice Preservation Nuance**: Permissive licenses are flexible, but they are not license-free. 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. + +* **What "keeping the notice" requires**: Keep the original copyright line *and* the license text. An SPDX identifier only points to a license, so the full text must also be in your repository, typically as one file per license in a `LICENSES/` folder (e.g., `LICENSES/Apache-2.0.txt`). Apache-2.0 adds two small requirements: if you modified the snippet, state that you changed it, and if the original project has a `NOTICE` file, carry its relevant content along. + +* **Check the source before copying**: Confirm the license in the original project's own `LICENSE` file, not in a blog post or second-hand claim. A project with no license file is *All Rights Reserved*, so its code cannot be copied. Note that **Stack Overflow content is licensed CC BY-SA**, a share-alike license, not a permissive one, so non-trivial Stack Overflow snippets belong in [Scenario 4](#scenario-4). * **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 +* **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 does not stay contained when pasted either: pasted MPL-2.0 code makes that file MPL-covered, and pasted LGPL code is treated like GPL. Weak copyleft only lets your code stay permissive when used as a separate file or library. -* **In-File Identification (SPDX)**: Mark both your overall file license and the specific embedded snippet using SPDX comments: +* **In-File Identification (SPDX)**: Mark your file's own license at the top, and mark the embedded snippet with the REUSE snippet tags so its boundaries are machine-readable: ```python +# SPDX-FileCopyrightText: 2026 Author Name # SPDX-License-Identifier: MIT -# Copyright (c) 2026 Author Name -# --- Embedded Third-Party Snippet --- +import numpy as np + +# SPDX-SnippetBegin +# SPDX-SnippetCopyrightText: 2024 External Contributor # 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 --- +# SPDX-SnippetEnd def main(): pass @@ -444,6 +451,7 @@ def main(): ::: :::: + (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. From a7cac720dda0068d6f13c65de9b9e8f1f791f23e Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:36:02 +0200 Subject: [PATCH 05/14] fix spdf scenario 4 --- content/software-licensing.md | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 710734d..8ae0e7c 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -451,14 +451,13 @@ def main(): ::: :::: - (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. +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. This is the situation behind the failed build (job #142) in the [Motivation](#motivation-debugging-a-license-compliance-failure) section. * **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.`). +* **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. Moving the snippet into a separate file of the same program does not change this. "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**: If you keep the snippet, your repository must adopt reciprocal sharing terms, so configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). :::{solution} **What to select in the JLA interface:** @@ -469,25 +468,31 @@ You are building a software tool and copied a non-trivial code snippet from a th * **Example JLA Matches**: `GPL-3.0`, `EUPL-1.2` -* **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. +* **Match the snippet's license**: JLA lists both, but you do not get to choose freely. Your project must take a license compatible with the snippet: a **GPL** snippet means GPL, because GPL code cannot be re-licensed under EUPL. An **EUPL-1.2** snippet can go either way: its compatibility clause allows the combined project to be distributed under `GPL-3.0` if your ecosystem requires it. + +* **Re-licensing is not the only fix**: Re-licensing your project is only possible if you hold the rights, so check with co-authors and your institution first. The alternatives are to reimplement the functionality yourself (a genuine rewrite, not a close paraphrase), to find a permissively licensed alternative, or to ask the snippet's copyright holder for permission to use it under your license, in writing. + +* **Stack Overflow snippets**: Stack Overflow content is licensed **CC BY-SA** (version 2.5, 3.0, or 4.0 depending on when it was posted), a share-alike license. Credit non-trivial snippets with a link to the answer and the author's name. Creative Commons considers CC BY-SA 4.0 compatible with `GPL-3.0` in one direction, so such snippets can go into a GPL-3.0 project, but not into an MIT project. -* **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. +* **Downstream Obligations**: Anyone to whom you distribute your repository must receive full access to the source code under the same copyleft license terms and preserve all copyright notices. Running the code internally, without distributing it, creates no obligation. -* **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. +* **Allowed Inbound Snippets**: Because your overall repository is now governed by a copyleft license, you can safely embed code from **permissive sources** (MIT, BSD, CC0), keeping their notices, as well as **compatible copyleft sources**. Note that `Apache-2.0` is compatible with GPL-3.0 but not with GPL-2.0. 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: +* **In-File Identification (SPDX)**: Mark your file's own license at the top, and mark the embedded copyleft snippet with the REUSE snippet tags so the original author remains credited: ```python +# SPDX-FileCopyrightText: 2026 Author Name # SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (c) 2026 Author Name -# --- Embedded Copyleft Snippet --- +import numpy as np + +# SPDX-SnippetBegin +# SPDX-SnippetCopyrightText: 2023 External Researcher # 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 --- +# SPDX-SnippetEnd def main(): pass @@ -495,6 +500,7 @@ def main(): ::: :::: + ## 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. From 465c2115fa6ef2ca88426fbd399c3243cbcc1de3 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:43:34 +0200 Subject: [PATCH 06/14] fix spdf scenario 5 --- content/software-licensing.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 8ae0e7c..b802680 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -108,6 +108,7 @@ Across international frameworks (17 U.S.C. § 101 and WIPO model provisions), so * **AI-Assisted Code** — generated or refactored with human oversight. * **AI Prompt Templates** — engineered system prompts meeting the threshold of human authorship. +(motivation)= ## 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: @@ -453,7 +454,7 @@ def main(): (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. This is the situation behind the failed build (job #142) in the [Motivation](#motivation-debugging-a-license-compliance-failure) section. +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. This is the situation behind the failed build (job #142) in the [Motivation](#motivation) section. * **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. Moving the snippet into a separate file of the same program does not change this. "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. From 4d478388d8197fbb2f1b91250e5ba7fab3458fb0 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:44:34 +0200 Subject: [PATCH 07/14] fix spdf scenario 5 --- content/software-licensing.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index b802680..efa7b49 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -512,7 +512,7 @@ You are developing a software application that imports or links against an exter * **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.`). +* **JLA Selection Strategy**: Under the conservative reading, linking to a GPL library means the combined program you distribute must be released under matching reciprocal terms, so configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). :::{solution} **What to select in the JLA interface:** @@ -523,20 +523,31 @@ You are developing a software application that imports or links against an exter * **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. +* **The safe default, not settled law**: On the conservative reading, your own files must be under a **GPL-compatible** license (GPL itself, or permissive licenses such as MIT or BSD), and the combined program you distribute is under GPL. `EUPL-1.2` also works for your own files through its compatibility clause, but the combined program then goes out under GPL anyway. -* **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. +* **What you ship matters**: *Static linking* copies the library's code into your binary, so you always distribute it. With *dynamic linking* (including a Python `import`), the library stays a separate file. If you publish only your own source and users install the GPL library themselves, the risk is much lower, although the FSF would still expect your code to be GPL-compatible. If you **bundle** the library, in an executable, a container image, or a compiled binary, GPL clearly applies to what you ship. -* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your main scripts: +* **Alternatives if you want to stay permissive**: + * Find a permissively licensed alternative library. + * Use an **LGPL** library instead: with dynamic linking, your own code can stay permissive, provided you keep its notices and do not restrict users from modifying the library or reverse engineering to debug those modifications. + * Use an **EUPL-1.2** library through dynamic linking: Commission guidance says this does not make your program a derivative work (guidance, not case law). Static linking or copying EUPL code is treated as a combined work. + * Call a GPL tool as a **separate program** (e.g., via the command line) rather than importing it. This is generally treated as two programs communicating, not a combined work. + +* **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-compatible terms, 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, such as a web application built on an AGPL library. + +* **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; for example, `Apache-2.0` is compatible with GPL-3.0 but not with GPL-2.0. + +* **Check your dependencies**: Tools such as `pip-licenses` (Python) list the license of every installed package. Most package ecosystems have an equivalent. Run one once per project. + +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX tags directly at the top of your main scripts: ```python +# SPDX-FileCopyrightText: 2026 Author Name # SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (c) 2026 Author Name -import gpl_licensed_solver # External GPL dependency forces GPL/EUPL compliance +import gpl_licensed_solver # External GPL dependency: conservative reading requires GPL compatibility def solve_system(data): return gpl_licensed_solver.compute(data) From 9a1783dbdecbcbe57b4ae9bea73abf1a31d38d51 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:45:52 +0200 Subject: [PATCH 08/14] fix spdf scenario 6 --- content/software-licensing.md | 51 +++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index efa7b49..b57d857 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -556,44 +556,55 @@ def solve_system(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. +(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). -* **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. +* **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**: Under the conservative reading, linking to a GPL library means the combined program you distribute must be released under matching reciprocal terms, so configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). :::{solution} **What to select in the JLA interface:** 1. **Can Column**: Select `Distribute`, `Modify/merge`, and `Commercial use` -2. **Must Column**: Select `Incl. Copyright` +2. **Must Column**: Select `Incl. Copyright`, `Disclose source`, and `Copyleft/Share a.` 3. **Support Column**: Select `OSI approved` -* **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` +* **Example JLA Matches**: `GPL-3.0`, `EUPL-1.2` -* **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. +* **The safe default, not settled law**: On the conservative reading, your own files must be under a **GPL-compatible** license (GPL itself, or permissive licenses such as MIT or BSD), and the combined program you distribute is under GPL. `EUPL-1.2` also works for your own files through its compatibility clause, but the combined program then goes out under GPL anyway. -* **Downstream Obligations**: Anyone who reuses or adapts your build recipe must preserve your original copyright notice in the header of the recipe file. +* **What you ship matters**: *Static linking* copies the library's code into your binary, so you always distribute it. With *dynamic linking* (including a Python `import`), the library stays a separate file. If you publish only your own source and users install the GPL library themselves, the risk is much lower, although the FSF would still expect your code to be GPL-compatible. If you **bundle** the library, in an executable, a container image, or a compiled binary, GPL clearly applies to what you ship. -* **Allowed Inbound Snippets**: You can freely include build commands and code snippets from permissively licensed build scripts or public domain code. +* **Alternatives if you want to stay permissive**: + * Find a permissively licensed alternative library. + * Use an **LGPL** library instead: with dynamic linking, your own code can stay permissive, provided you keep its notices and do not restrict users from modifying the library or reverse engineering to debug those modifications. + * Use an **EUPL-1.2** library through dynamic linking: Commission guidance says this does not make your program a derivative work (guidance, not case law). Static linking or copying EUPL code is treated as a combined work. + * Call a GPL tool as a **separate program** (e.g., via the command line) rather than importing it. This is generally treated as two programs communicating, not a combined work. -* **In-File Identification (SPDX)**: Place SPDX identifier comments at the top of your Dockerfile or recipe file: +* **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. -```dockerfile -# SPDX-License-Identifier: MIT -# Copyright (c) 2026 Author Name +* **Downstream Obligations**: Anyone to whom you **distribute** the application must receive full access to your source code under GPL-compatible terms, 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, such as a web application built on an AGPL library. -FROM ubuntu:24.04 -RUN apt-get update && apt-get install -y python3 python3-pip -COPY solver.py /app/solver.py +* **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; for example, `Apache-2.0` is compatible with GPL-3.0 but not with GPL-2.0. + +* **Check your dependencies**: Tools such as `pip-licenses` (Python) list the license of every installed package. Most package ecosystems have an equivalent. Run one once per project. + +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX tags directly at the top of your main scripts: + +```python +# SPDX-FileCopyrightText: 2026 Author Name +# SPDX-License-Identifier: GPL-3.0-or-later + +import gpl_licensed_solver # External GPL dependency: conservative reading requires GPL compatibility + +def solve_system(data): + return gpl_licensed_solver.compute(data) ``` ::: :::: ---- - (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. From 5cec5efc4e41c59bae4691df6038dc0958d0d6d0 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:46:47 +0200 Subject: [PATCH 09/14] fix spdf scenario 7 --- content/software-licensing.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index b57d857..6713baf 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -607,10 +607,10 @@ def solve_system(data): (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. +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, or sharing an Apptainer `.sif` file) 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. +* **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} @@ -622,22 +622,29 @@ You compiled and published a pre-built container image (e.g., pushing a compiled * **JLA Outcome**: No single license applies. Use JLA per component to check each one's obligations, then record the aggregate in your image metadata. +* **Aggregation covers independent programs only**: Mere aggregation applies to programs that simply live side by side in the image, such as your application next to `bash` or `coreutils`. If your application actually imports or links a GPL library inside the image, that relationship is a linking question, covered by [Scenario 5](#scenario-5). + * **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. +* **What counts as distribution**: Pushing an image to a public registry, or sharing an image or `.sif` file with people outside your organisation, is distribution. Keeping an image in a private registry used only within your own organisation is generally not. If you are unsure, treat it as distribution. + +* **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, and pointing to the distributor's public source archives is common practice. The exact rules differ between GPL versions, however, and many distribution packages are GPL-2.0, so for images on public registries the safest option is to keep the relevant source available yourself. If you modify or rebuild a copyleft component yourself, you must provide that source directly. + +* **Watch for non-redistributable software**: The bigger risk in an image is often proprietary software you are not allowed to redistribute at all, such as parts of NVIDIA CUDA, Intel's math libraries, MATLAB runtimes, or commercial solvers. Their redistribution terms are set by each vendor's license, so check them before publishing. -* **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. +* **Generate a Software Bill of Materials (SBOM)**: Before publishing an image, use tools such as Syft or Trivy to list every package inside it, with versions and licenses. This SBOM is the complete record of what you distribute, and it shows whether any non-redistributable software is included. Consider publishing it alongside the image. -* **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: +* **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. The `licenses` label is a summary: a base image contains many more licenses than it lists, so the SBOM remains the complete record. ```dockerfile +# SPDX-FileCopyrightText: 2026 Author Name # 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 +# OCI standard image annotations, displayed by registries and tools LABEL org.opencontainers.image.title="My Research Pipeline" +# Summary only; see the published SBOM for the full list of licenses 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)" @@ -647,6 +654,7 @@ 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. From 541fe6f0aa66cec6f3fb4efb879afb0482f526aa Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:51:07 +0200 Subject: [PATCH 10/14] fix spdf scenario 8 --- content/software-licensing.md | 73 +++++++++++++++++------------------ 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 6713baf..764cca4 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -556,51 +556,40 @@ def solve_system(data): :::: -(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). +(scenario-6)= +::::{exercise} Scenario 6: Authoring container recipes and environment specifications +You are creating a `Dockerfile`, Apptainer `.def` file, 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**: 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**: Under the conservative reading, linking to a GPL library means the combined program you distribute must be released under matching reciprocal terms, so configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). +* **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. The same applies to a plain list of package names in an `environment.yml`. Longer, non-obvious recipes clearly do attract copyright. +* **JLA Selection Strategy**: To allow anyone to reuse or adapt your container recipe without restrictions, require that your copyright notice is kept (`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`, `Disclose source`, and `Copyleft/Share a.` +2. **Must Column**: Select `Incl. Copyright` 3. **Support Column**: Select `OSI approved` -* **Example JLA Matches**: `GPL-3.0`, `EUPL-1.2` - -* **The safe default, not settled law**: On the conservative reading, your own files must be under a **GPL-compatible** license (GPL itself, or permissive licenses such as MIT or BSD), and the combined program you distribute is under GPL. `EUPL-1.2` also works for your own files through its compatibility clause, but the combined program then goes out under GPL anyway. +* **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` -* **What you ship matters**: *Static linking* copies the library's code into your binary, so you always distribute it. With *dynamic linking* (including a Python `import`), the library stays a separate file. If you publish only your own source and users install the GPL library themselves, the risk is much lower, although the FSF would still expect your code to be GPL-compatible. If you **bundle** the library, in an executable, a container image, or a compiled binary, GPL clearly applies to what you ship. +* **License short recipes anyway**: Even if a recipe may fall below the originality threshold, a two-line SPDX header removes any doubt for people who want to reuse it, and tools such as `reuse lint` expect every file to be marked. For very small configuration files, some projects use `CC0-1.0`. -* **Alternatives if you want to stay permissive**: - * Find a permissively licensed alternative library. - * Use an **LGPL** library instead: with dynamic linking, your own code can stay permissive, provided you keep its notices and do not restrict users from modifying the library or reverse engineering to debug those modifications. - * Use an **EUPL-1.2** library through dynamic linking: Commission guidance says this does not make your program a derivative work (guidance, not case law). Static linking or copying EUPL code is treated as a combined work. - * Call a GPL tool as a **separate program** (e.g., via the command line) rather than importing it. This is generally treated as two programs communicating, not a combined work. +* **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. Writing `apt-get install` for a GPL package, or `FROM ubuntu`, names the software without copying it. A permissively licensed Dockerfile can therefore install both permissive and copyleft packages without legal conflict. This applies to the **recipe only**: once you build and publish the resulting image, you are distributing every package inside it (see [Scenario 7](#scenario-7)). -* **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 who reuses or adapts your build recipe must preserve your original copyright notice and license text. Keeping the recipe in your repository alongside the `LICENSES/` folder covers this. -* **Downstream Obligations**: Anyone to whom you **distribute** the application must receive full access to your source code under GPL-compatible terms, 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, such as a web application built on an AGPL library. +* **Allowed Inbound Snippets**: Copying build steps from other people's recipes follows the same rules as source code. Steps from permissively licensed recipes or public domain code can be included freely, keeping their notices ([Scenario 3](#scenario-3)). A non-trivial block from a copyleft project's recipe falls under [Scenario 4](#scenario-4). In practice, most build commands are short and generic, so this rarely applies. -* **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; for example, `Apache-2.0` is compatible with GPL-3.0 but not with GPL-2.0. +* **In-File Identification (SPDX)**: Place SPDX tags as comments at the top of your Dockerfile or recipe file: -* **Check your dependencies**: Tools such as `pip-licenses` (Python) list the license of every installed package. Most package ecosystems have an equivalent. Run one once per project. - -* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX tags directly at the top of your main scripts: - -```python +```dockerfile # SPDX-FileCopyrightText: 2026 Author Name -# SPDX-License-Identifier: GPL-3.0-or-later - -import gpl_licensed_solver # External GPL dependency: conservative reading requires GPL compatibility +# SPDX-License-Identifier: MIT -def solve_system(data): - return gpl_licensed_solver.compute(data) +FROM ubuntu:24.04 +RUN apt-get update && apt-get install -y python3 python3-pip +COPY solver.py /app/solver.py ``` ::: :::: @@ -651,6 +640,7 @@ LABEL org.opencontainers.image.description="Includes Ubuntu 24.04 base layers (G COPY solver.py /app/solver.py ``` + ::: :::: @@ -659,15 +649,14 @@ COPY solver.py /app/solver.py 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. +* **Licensing Goal**: Apply a **permissive license** (`MIT` or `Apache-2.0`) to your repository with confidence, without incurring hidden copyright infringement or copyleft obligations from code the AI model reproduced from its training data. +* **Legal Reality**: Unmodified AI-generated outputs lack human authorship and are generally not eligible for copyright protection under current EU and international legal standards. Most real code, however, is a mix of human and AI contribution: you prompt, select, edit, and integrate. Where the line falls between AI output and your own work is unsettled and varies between Member States; there is no percentage or line-count threshold. The more you design, choose, edit, and integrate, the stronger your claim that the result is your work. Separately, 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 that your copyright notice is kept (`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:** @@ -678,16 +667,26 @@ You used AI tools (e.g., GitHub Copilot, ChatGPT, Claude) to write functions, un * **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` +* **License your repository as normal**: Your license covers everything you authored. Any purely AI-generated parts that are not protected by copyright are free to use anyway, so the license does no harm there. Many AI tools' terms state that the output belongs to you as far as any rights exist, but a contract cannot create copyright that the law does not grant. + +* **Checking for memorized code**: Memorization is uncommon for everyday code, but it does happen, especially for well-known code that appears many times in training data. Practical checks: + * Be most careful with **long, distinctive functions** and implementations of well-known algorithms. Short boilerplate and unit tests are low risk. + * If you use GitHub Copilot, check whether the setting that **blocks suggestions matching public code** is enabled for your account or organisation. + * If a suggestion looks suspiciously polished, **search for a distinctive line** of it on GitHub. If it appears in a copyleft project, treat it as that project's code ([Scenario 4](#scenario-4)). + * **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. + +* **Use AI to write code, not to decide licensing**: As noted in the section on the limitations of AI-assisted licensing advice, AI assistants tend to apply US legal concepts. Check licensing questions against the actual license text. + * **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. +* **Allowed Inbound Snippets**: You can include permissively licensed code, public domain code (CC0), and AI-generated snippets that you have checked for verbatim reproduction of training data, as described above. -* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX identifier comments directly at the top of your scripts: +* **In-File Identification (SPDX)**: Apply standard machine-readable SPDX tags directly at the top of your scripts, and mark AI-assisted code where it appears: ```python +# SPDX-FileCopyrightText: 2026 Author Name # 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).""" @@ -696,8 +695,6 @@ def filter_sensor_data(raw_readings: list[float]) -> list[float]: ::: :::: ---- - (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. From ccb9ebc12f1a984719c329b95443f6f8ad7d1233 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 10:52:04 +0200 Subject: [PATCH 11/14] fix spdf scenario 9 --- content/software-licensing.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 764cca4..d75ab71 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -695,13 +695,15 @@ def filter_sensor_data(raw_readings: list[float]) -> list[float]: ::: :::: + + (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. +* **Licensing Goal**: Apply a clear licensing structure, with **different licenses for different parts** of the repository, 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 the numerical values learned during training, 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-1.0`) for the dataset and weight files. :::{solution} **What to select in the JLA interface:** @@ -712,26 +714,32 @@ You are developing research software that includes source code alongside trained * **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. +* **Code vs. Data/Weights**: 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-1.0** for non-code assets instead. CC-BY-4.0 requires credit; CC0-1.0 requires nothing, which makes it easier for data that others will combine with many other datasets. Note that this pattern is sometimes called "dual-licensing", but that term usually means offering the *same* work under two licenses. + +* **You can only license what is yours**: If your dataset contains material you did not create, such as scraped text, images, or other people's data, your license covers only your own contribution; the original content keeps its own rights. If your dataset contains personal data, data protection rules apply regardless of the license. + +* **Open weights are not always open source**: If you fine-tuned an existing model, its license still applies to what you built on it. Many models published with open weights come with their own licenses restricting, for example, commercial use or certain applications. Check the base model's license before fine-tuning and publishing. -* **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. +* **Behavioral licenses (OpenRAIL)**: Licenses such as OpenRAIL impose usage restrictions (e.g., prohibiting specific harmful uses). This can be a reasonable choice, but it means they do **not** qualify as OSI-approved open source and will not appear in standard JLA queries. -* **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. +* **Downstream Obligations**: Downstream users must keep your copyright notice and license text for the code (under your chosen software license) and give credit for the model weights and data as the corresponding Creative Commons license requires. For academic citation, add a `CITATION.cff` file to your repository. -* **In-File Identification (SPDX / Dual-Licensing Structure)**: Document the dual-licensing scheme in your root repository structure and script headers: +* **Allowed Inbound Assets**: You may combine permissively licensed Python code with CC-BY-4.0 datasets, provided the attribution files clearly separate code licenses from data/weight licenses. Models published with open weights can be included only under the terms of their own licenses (see above). + +* **In-File Identification (SPDX / Licensing Structure)**: Binary files such as weights and datasets cannot contain comments, so REUSE marks them with a companion `.license` file next to each one (e.g., `climate_weights.safetensors.license`) or with a single `REUSE.toml` file covering whole folders. State in your README which license covers which folder, and fill in the license fields on platforms such as Zenodo or Hugging Face. In your code, document the structure in the header: ```python +# SPDX-FileCopyrightText: 2026 Author Name # 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 +from safetensors.torch import load_file def load_pipeline(): - model = torch.load("models/climate_weights.safetensors") - return model + weights = load_file("models/climate_weights.safetensors") + return weights ``` ::: :::: From 264f211e365398ca936856ff4609304d4674cca7 Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 11:02:17 +0200 Subject: [PATCH 12/14] formating --- content/software-licensing.md | 70 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index d75ab71..67a01b9 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -17,7 +17,7 @@ This lesson is designed as practical educational material for researchers and re * 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: +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/) @@ -81,7 +81,7 @@ Under Directive 2009/24/EC, software is protected by copyright as a **literary w * **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. +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. ````{admonition} Plagiarism vs. Intellectual Property Rights = Research Ethics vs. Law :class: dropdown @@ -99,14 +99,14 @@ There is no pre-defined "number of lines of code", "seconds of a song", or "pixe ### 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: +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. +* **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)= ## Motivation: Debugging a License Compliance Failure @@ -127,9 +127,9 @@ flowchart TB 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 -->|"B: Re-license repo to match the snippet"| 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"] + 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"] @@ -138,7 +138,7 @@ flowchart TB P -.->|"What I want for my repo"| C CL -.->|"What the pasted snippet uses"| C - WC -.->|"Would often have been fine"| C + WC -.->|"Fine only as a separate library"| C classDef pass fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; classDef copyleft fill:#fff9db,stroke:#f59f00,stroke-width:2px,color:#5c3c00; @@ -159,7 +159,7 @@ flowchart TB * 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. -* 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. +* 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. ## Limitations of AI-Assisted Licensing Advice @@ -174,8 +174,8 @@ However, using these tools for legal or licensing guidance introduces a subtle r 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. +* **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. @@ -196,7 +196,7 @@ Managed by the Linux Foundation, **SPDX** provides standardized short identifier The tags only *point to* a license, so the full license text must also be in your repository. REUSE places one text file per license in a `LICENSES/` folder (e.g., `LICENSES/MIT.txt`). Running `reuse lint` then checks that every file carries both tags and that every license it names has its text present. -Every scenario below shows the SPDX tagging for its asset type — Python scripts, container recipes, and prompt templates each have their own conventions. +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 @@ -217,10 +217,10 @@ table.wrap-table td, table.wrap-table th { white-space: normal !important; } | 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` | +| 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 | +| 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` | @@ -323,7 +323,7 @@ Copyright does not use a numerical threshold such as 5, 10, or 20 lines. The imp ## 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. +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 @@ -367,7 +367,7 @@ import numpy as np 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. +* **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} @@ -420,7 +420,7 @@ You are building an RSE tool and copied a helper function or utility snippet fro * **Example JLA Matches**: `MIT`, `Apache-2.0`, `BSD-3-Clause` -* **Notice Preservation Nuance**: Permissive licenses are flexible, but they are not license-free. 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. +* **Notice Preservation Nuance**: Permissive licenses are flexible, but they are not license-free. 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. * **What "keeping the notice" requires**: Keep the original copyright line *and* the license text. An SPDX identifier only points to a license, so the full text must also be in your repository, typically as one file per license in a `LICENSES/` folder (e.g., `LICENSES/Apache-2.0.txt`). Apache-2.0 adds two small requirements: if you modified the snippet, state that you changed it, and if the original project has a `NOTICE` file, carry its relevant content along. @@ -457,7 +457,7 @@ def main(): 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. This is the situation behind the failed build (job #142) in the [Motivation](#motivation) section. * **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. Moving the snippet into a separate file of the same program does not change this. "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. +* **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. Moving the snippet into a separate file of the same program does not change this. "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**: If you keep the snippet, your repository must adopt reciprocal sharing terms, so configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). :::{solution} @@ -511,7 +511,7 @@ When software incorporates external dependencies, whether by dynamic linking, st 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). * **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. +* **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**: Under the conservative reading, linking to a GPL library means the combined program you distribute must be released under matching reciprocal terms, so configure JLA to require source code disclosure (`Disclose source`) and reciprocal licensing (`Copyleft/Share a.`). :::{solution} @@ -533,9 +533,9 @@ You are developing a software application that imports or links against an exter * Use an **EUPL-1.2** library through dynamic linking: Commission guidance says this does not make your program a derivative work (guidance, not case law). Static linking or copying EUPL code is treated as a combined work. * Call a GPL tool as a **separate program** (e.g., via the command line) rather than importing it. This is generally treated as two programs communicating, not a combined work. -* **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. +* **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-compatible terms, 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, such as a web application built on an AGPL library. +* **Downstream Obligations**: Anyone to whom you **distribute** the application must receive full access to your source code under GPL-compatible terms, 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, such as a web application built on an AGPL library. * **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; for example, `Apache-2.0` is compatible with GPL-3.0 but not with GPL-2.0. @@ -561,7 +561,7 @@ def solve_system(data): You are creating a `Dockerfile`, Apptainer `.def` file, 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. The same applies to a plain list of package names in an `environment.yml`. Longer, non-obvious recipes clearly do attract copyright. +* **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. The same applies to a plain list of package names in an `environment.yml`. Longer, non-obvious recipes clearly do attract copyright. * **JLA Selection Strategy**: To allow anyone to reuse or adapt your container recipe without restrictions, require that your copyright notice is kept (`Incl. Copyright`) while leaving reciprocal requirements (`Copyleft/Share a.`) unselected. :::{solution} @@ -617,7 +617,7 @@ You compiled and published a pre-built container image (e.g., pushing a compiled * **What counts as distribution**: Pushing an image to a public registry, or sharing an image or `.sif` file with people outside your organisation, is distribution. Keeping an image in a private registry used only within your own organisation is generally not. If you are unsure, treat it as distribution. -* **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, and pointing to the distributor's public source archives is common practice. The exact rules differ between GPL versions, however, and many distribution packages are GPL-2.0, so for images on public registries the safest option is to keep the relevant source available yourself. If you modify or rebuild a copyleft component yourself, you must provide that source directly. +* **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, and pointing to the distributor's public source archives is common practice. The exact rules differ between GPL versions, however, and many distribution packages are GPL-2.0, so for images on public registries the safest option is to keep the relevant source available yourself. If you modify or rebuild a copyleft component yourself, you must provide that source directly. * **Watch for non-redistributable software**: The bigger risk in an image is often proprietary software you are not allowed to redistribute at all, such as parts of NVIDIA CUDA, Intel's math libraries, MATLAB runtimes, or commercial solvers. Their redistribution terms are set by each vendor's license, so check them before publishing. @@ -674,7 +674,7 @@ You used AI tools (e.g., GitHub Copilot, ChatGPT, Claude) to write functions, un * If you use GitHub Copilot, check whether the setting that **blocks suggestions matching public code** is enabled for your account or organisation. * If a suggestion looks suspiciously polished, **search for a distinctive line** of it on GitHub. If it appears in a copyleft project, treat it as that project's code ([Scenario 4](#scenario-4)). -* **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. +* **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. * **Use AI to write code, not to decide licensing**: As noted in the section on the limitations of AI-assisted licensing advice, AI assistants tend to apply US legal concepts. Check licensing questions against the actual license text. @@ -714,7 +714,7 @@ You are developing research software that includes source code alongside trained * **Example JLA Matches**: `MIT`, `Apache-2.0` (for the code component) -* **Code vs. Data/Weights**: 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-1.0** for non-code assets instead. CC-BY-4.0 requires credit; CC0-1.0 requires nothing, which makes it easier for data that others will combine with many other datasets. Note that this pattern is sometimes called "dual-licensing", but that term usually means offering the *same* work under two licenses. +* **Code vs. Data/Weights**: 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-1.0** for non-code assets instead. CC-BY-4.0 requires credit; CC0-1.0 requires nothing, which makes it easier for data that others will combine with many other datasets. Note that this pattern is sometimes called "dual-licensing", but that term usually means offering the *same* work under two licenses. * **You can only license what is yours**: If your dataset contains material you did not create, such as scraped text, images, or other people's data, your license covers only your own contribution; the original content keeps its own rights. If your dataset contains personal data, data protection rules apply regardless of the license. @@ -800,7 +800,7 @@ The diagram below illustrates how selecting a compatible license upfront ensures %%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff', 'fontSize': '16px' }}}%% flowchart TB - subgraph local["① What you do differently now — before pushing"] + 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 @@ -824,15 +824,15 @@ flowchart TB 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. +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. +* **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. +* **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 @@ -998,4 +998,6 @@ Viral / infectious Weak copyleft Reciprocity limited to a file (MPL-2.0) or library (LGPL). + ``` +```` From 868eff1cf4165927185c8e3a79d1b84ae1d89dcd Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 11:12:46 +0200 Subject: [PATCH 13/14] Add a page end --- content/software-licensing.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/software-licensing.md b/content/software-licensing.md index 67a01b9..20c0f18 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -1001,3 +1001,5 @@ Weak copyleft ``` ```` + +End. From 0450f19ace21eef06ade3508e394da30192c3bff Mon Sep 17 00:00:00 2001 From: Sabry Razick Date: Tue, 29 Sep 2026 11:13:30 +0200 Subject: [PATCH 14/14] Add a remove page end --- content/software-licensing.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/software-licensing.md b/content/software-licensing.md index 20c0f18..953cee2 100644 --- a/content/software-licensing.md +++ b/content/software-licensing.md @@ -1002,4 +1002,3 @@ Weak copyleft ``` ```` -End.