Software licensing focusing on open source

Objectives

  • Principles of open source licensing

  • Difference between permissive and copyleft licenses

  • Regulations for AI-generated and AI-assisted code

  • Determine the software license for your project following EU regulation

  • Navigate the Joinup Licensing Assistant to select a compliant license

  • Understand the licensing distinction between container recipes and container images

Limitations and context of this lesson

This lesson is designed as practical educational material for researchers and research software engineers, not formal legal advice

  • Regional Focus: Guidance is grounded in EU statutory directives, European institutional frameworks and developers based in Europe with a global focus.

  • 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 references below and legal experts, especially if you have legal services at your host institute, could be of help:

Introduction: What is a Software License?

Under copyright law worldwide, software without an explicit license automatically defaults to All Rights Reserved: meaning nobody else has the legal right to run, modify, embed, or cite your code. A software license is a legal permission grant created by the author that overrides this statutory default, defining how downstream researchers can reuse your work.

In this lesson, we focus on open-source licenses to define both how we grant permissions for software we develop (outbound licensing) and how we safely comply with terms attached to code written by others (inbound reuse).

  • Open-source licenses fall into two main families:

    • Permissive (e.g., MIT, Apache-2.0, 0BSD): Do whatever you want, just keep crediti. Grants maximum reuse freedom, allowing anyone to modify, embed, or re-license your code in open or closed projects.

    • Copyleft/Reciprocal (e.g., GPL-3.0, EUPL-1.2): Share alike. Grants full freedom to run and modify, but mandates that any distributed derivative or combined work must also be released under matching copyleft terms. Often informally referred to as viral or infectious because its open-source requirements propagate across code boundaries (such as embedding snippets or static linking) into downstream projects. The diagram below unifies these license choices and their downstream rights:

%%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff' }}}%% flowchart TB subgraph box["How License Selection Governs Code Reuse"] A["<b>Your Research Codebase </b></><i>(Source code, container recipes, prompt templates)</i>"] -->|"No License Attached</>(Statutory Default)"| B["<b>All Rights Reserved</b></>❌ Zero permissions: Cannot run, modify, or share"] A -->|"Attach License</>(Explicit Permission Grant)"| C{"Select License"} C -->|"Goal: Maximum adoption & unrestricted reuse"| D["<b>Permissive License</b>"] C -->|"Goal: Ensure changes stay open-source (Reciprocity)"| E["<b>Copyleft License</b>"] C -->|"Goal: Proprietary control & restricted access"| F["<b>Closed Source / Restricted</b></>🚫 <i>Flavour not discussed in this lesson</i>"] D --> D1["Run & Modify? <b>Yes!</b>"] D --> D2["Embed in closed product? <b>Yes!</b>"] D --> D3["Must changes stay open? <b>No</b> (Optional)"] E --> E1["Run & Modify? <b>Yes!</b>"] E --> E2["Embed in closed product? <b>No!</b>"] E --> E3["Must changes stay open? <b>Yes!</b> (Mandatory)"] end classDef green fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; classDef red fill:#ffe3e3,stroke:#e03131,stroke-width:2px,color:#5c0000; classDef yellow fill:#fff9db,stroke:#f59f00,stroke-width:2px,color:#5c3c00; classDef white fill:#f8f9fa,stroke:#adb classDef dashed fill:#f8f9fa,stroke:#adb5bd,stroke-width:2px,stroke-dasharray: 5 5,color:#000000; classDef dashed_red fill:#ffe3e3,stroke:#adb5bd,stroke-width:2px,stroke-dasharray: 5 5,color:#000000; classDef defaultState fill:#ffe3e3,stroke:#e03131,stroke-width:2px,color:#5c0000; classDef box_fill fill:#ffffff,stroke:#adb5bd,stroke-width:1px; class D1,D2,D3,E1,E3 green; class E2 red; class D,E yellow; class F dashed; class B dashed_red; class A,C white; class box box_fill;

Scope of this Lesson: What Counts as Software?

Across international legal frameworks (such as 17 U.S.C. § 101 and WIPO-World Intellectual Property Organization model provisions), software is broadly defined as a set of instructions to be used directly or indirectly in a computer to bring about a certain result.

Because modern research software extends beyond simple Python scripts, this lesson applies copyright and licensing principles across six core research software assets:

  • Source Code: Original algorithms written from scratch or implemented from scientific papers.

  • Third-Party Integrations: Embedded permissive or copyleft code snippets and linked libraries (dynamically/statically).

  • Infrastructure as Code: Ansible playbooks,Terraform configurations,container Recipes (Dockerfile, Apptainer .def).

  • Container Images: Bundled binary filesystem snapshots (.sif files, OCI registry images).

  • AI-Assisted Code: Code generated, refactored, or assembled with human creative oversight.

  • AI Prompt Templates: Complex, engineered system prompts and structured frameworks meeting the threshold of human creative authorship.

Motivation: Debugging a License Compliance Failure

With the understanding of the difference between Permissive and Copyleft licenses, examine what happens when they collide inside an automated CI/CD pipeline:

%%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff' }}}%% flowchart TB subgraph box["CI/CD License Compliance Debugging Pipeline"] A[Paste snippet copyied from somewhere ] --> A2["<b>Build Trigger:</b>Push to my-code-base"] A2["<b>Build Trigger:</b> Push to my-code-base"] --> B["Run Compliance Scanner"] B --> C{"Check Inbound vs.</>Outbound Terms"} C -->|"Target License:Permissive</> but pasted snippet:Copyleft"| D["❌ <b>BUILD FAILURE</b><br/>Pasted copyleft snippet restricts MIT release"] D --> E{"Select Patch Option"} E -->|"Option A: Keep MIT & add comment '# Originally GPL'"| F["❌ <b>BUILD FAIL</b><br/>Comments do not override copyleft terms"] E -->|"Option B: Re-license repo to GPL-3.0 / EUPL-1.2"| G["✅ <b>BUILD PASS</b><br/>Your license matches the pasted copyleft snippet"] E -->|"Option C: Rewrite code from scratch to replace snippet"| H["✅ <b>BUILD PASS</b><br/>New code expression frees your target license"] E -->|"Option D: Delete LICENSE file to bypass scanner"| I["⚠️ <b>PASSED SCANNER (LEGAL TRAP!)</b><br/>Infringes third-party copyright & locks own code to All Rights Reserved"] P["<b>Permissive</b><br/>(MIT, Apache-2.0, 0BSD)</><i>'Do whatever you want, just keep credit'</i>"] CL["<b>Copyleft / Reciprocal</b><br/>(GPL-3.0, EUPL-1.2)</><i>'Must share changes under same terms'</i>"] end P -.->|"I want to use"| C CL -.->|"Pasted code snippet uses"| C classDef pass fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; classDef copyleft fill:#fff9db,stroke:#f59f00,stroke-width:2px,color:#5c3c00; classDef fail fill:#ffe3e3,stroke:#e03131,stroke-width:2px,color:#5c0000; classDef warning fill:#fff3bf,stroke:#f08c00,stroke-width:2px,color:#5c0000; classDef neutral fill:#f8f9fa,stroke:#495057,stroke-width:2px,color:#212529; classDef box_fill fill:#ffffff,stroke:#adb5bd,stroke-width:1px; class P,G,H pass; class CL copyleft; class D,F fail; class I warning; class A,B,C,E neutral; class box box_fill;

Limitations of AI-Assisted Licensing Advice

Modern software developers and RSEs routinely rely on AI coding assistants (ChatGPT, Claude, GitHub Copilot) to generate boilerplate, refactor functions, and answer project setup questions.

However, using these tools for legal or licensing guidance introduces a subtle risk of AI legal bias as AI models are overwhelmingly trained on US-centric web data and legal forum posts, their outputs default almost universally to US common law concepts such as Fair Use, Work Made for Hire, and Derivative Works.

In contrast, developers operating under EU statutory frameworks (such as Directive 2009/24/EC) face a different legal reality related to exceptions, author ownership, and code adaptations. Relying blindly on AI legal advice creates significant compliance blind spots, which is why this lesson equips you with a direct, EU-aligned framework for software licensing.

Standardizing In-File Declarations: SPDX Identifiers

Selecting a license is only half the battle; automated scanners and CI/CD pipelines need a machine-readable way to verify license compliance per file without parsing long legal texts.

Managed by the Linux Foundation, SPDX identifiers (Software Package Data Exchange) provide standardized short tags (e.g., MIT, Apache-2.0, GPL-3.0-only, EUPL-1.2) placed at the very top line of every source file:

# SPDX-License-Identifier: MIT
# Copyright (c) 2026 Author Name <author@institute.eu>

Throughout the exercise scenarios below, look for the In-File Identification (SPDX) callouts to see how these tags apply directly to Python scripts, container recipes, and engineered prompt templates.

License Selection Decision Matrix & Scenario Index

To help you navigate open-source compliance, the matrix below serves as an upfront quick-reference summary and interactive index for the core licensing scenarios encountered in research software engineering.

Joinup Licensing Assistant (JLA)

  • Our decision framework is grounded in the European Commission’s JLA, which evaluates software assets across six criteria categories:

    • Can (Permissions)

    • Must (Obligations)

    • Cannot (Restrictions)

    • Compatible** (Interoperability)

    • Law (Jurisdiction)

    • Support(Governance)

Use this index to preview the demonstrated path for each scenario, or click any module link to jump directly to its detailed exercise, legal analysis, and JLA selection instructions.

Scenario Module

Demonstrated Path / Focus

Compliant Target Licenses

1. Own Code

🟢 Permissive (Default Choice)

MIT, Apache-2.0, BSD-3-Clause

2. Implement an algorithm

🟡 Copyleft / Reciprocal

EUPL-1.2, GPL-3.0, AGPL-3.0

3. Embed Permissive

🟢 Permissive Focus (Copyleft Flexible)

MIT, Apache-2.0, EUPL-1.2, GPL-3.0

4. Embed Copyleft

🟡 Mandatory Copyleft

EUPL-1.2, GPL-3.0

5. Link GPL Library

🟡 Mandatory Copyleft

GPL-3.0, EUPL-1.2

6. Container Recipe

🟢 Permissive Focus

MIT, Apache-2.0, BSD-3-Clause

7. Built Image

⚠️ Multi-License Bundle

Governed by individual layer/binary terms

8. AI-Assisted Code

🟢 Permissive Focus (Author Choice)

MIT, Apache-2.0, EUPL-1.2, GPL-3.0

9. Prompt Chaining Architecture

🟢 Permissive Focus

MIT, Apache-2.0

Module 1: Clean Slate – Authoring Original Code & Algorithms

When writing original code or implementing published mathematical logic, you control 100% of your copyright.

Scenario 1: Authoring original code and algorithms

You wrote an original algorithm from scratch (in Python, C++, Rust, etc.). Your repository contains only your original source code and dependency specifications (requirements.txt, CMakeLists.txt, Cargo.toml).

  • Licensing Goal: You want maximum adoption and zero friction for commercial or academic reuse.

  • Legal Reality: External dependencies remain separate works. Because you have not bundled third-party code inside your repository, you hold full copyright over your original codebase.

  • 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).

Scenario 2: Implementing mathematical models with copyleft obligations

You developed a custom mathematical solver implementing algorithms from academic literature. You want to ensure that any downstream improvements, extensions, or modifications made by others remain open-source and are shared back with the scientific community.

  • Licensing Goal: You want to enforce reciprocity (share-alike), preventing third parties from incorporating your algorithm into proprietary, closed-source software without sharing their modifications.

  • Legal Reality: Mathematical concepts and formulas themselves are not copyrightable, but your specific code implementation is fully protected by copyright. Applying a copyleft license legally binds anyone who distributes modified versions of your implementation to release their source code under matching reciprocal terms.

  • JLA Selection Strategy: To enforce reciprocal sharing, you must mandate that downstream distributors disclose their modified source code (Disclose source) and license their derivative works under matching terms (Copyleft/Share a.).

Module 2: The Dependency Minefield – Inbound Code & Linking

Embedding third-party source code snippets or linking against strong copyleft libraries introduces legal boundaries that restrict your repository choices.

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).

Scenario 4: Embedding copyleft third-party code

You are building an software tool and copied a non-trivial code snippet from a third-party project licensed under a copyleft license (e.g., GPL-3.0 or EUPL-1.2) directly into one of your source files.

  • Licensing Goal: Comply with legal requirements imposed by the inbound copyleft code while ensuring your overall repository remains legally compliant.

  • Legal Reality: Copyleft licenses require that any work containing copyleft code must be shared under a compatible copyleft license as a whole. Embedding copyleft code directly into your repository creates a single combined work, making copyleft licensing mandatory for your entire project.

  • 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.).

Module 3: Dependency Linking & Packaging

When software incorporates external dependencies, whether by dynamic linking, static compiling, or bundling binaries into container images licensing obligations expand beyond your own written source code. This module covers how dependency boundaries, build automation scripts, and packaged container artifacts affect legal compliance under the Joinup Licensing Assistant (JLA) framework.

Scenario 5: Linking against a GPL-licensed library

You are developing an 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: Under mainstream copyright interpretation and the text of GPL-3.0, linking your code directly against a GPL library (whether statically or dynamically) creates a combined work. Consequently, the copyleft obligations of the external library extend to your entire repository.

  • 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.).

Scenario 6: Authoring container recipes and environment specifications

You are creating a Dockerfile, Conda environment.yml, or build recipe to automate the setup of your research environment. The recipe itself contains setup instructions, shell commands, and package lists.

  • Licensing Goal: You want maximum adoption and reuse of your build automation script so other researchers can freely adapt and build upon your workflow.

  • Legal Reality: Build recipes and configuration scripts are plain-text source code separate from the software binaries they download at execution time. You hold copyright over the unique build instructions you write in the Dockerfile.

  • 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.


Scenario 7: Distributing pre-built container images

You compiled and published a pre-built container image (e.g., pushing a compiled Docker image to Docker Hub, GitHub Container Registry, or an institutional registry) containing an OS layer, runtime binaries, dependencies, and your application code.

  • Licensing Goal: Safely distribute compiled container images without violating the license terms of any software layer or binary included inside the image.

  • Legal Reality: A compiled container image is a multi-license aggregate bundle. Distributing pre-built binaries triggers source-code distribution obligations for any copyleft software (e.g., Linux base packages, coreutils, GPL libraries) pre-installed inside the image layers.

  • 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.

Module 4: Emerging Workflows & AI

AI-assisted development tools and machine learning models introduce unique legal challenges regarding copyright ownership, training data memorization, and behavioral restrictions. This module addresses how to license projects built with AI code generation tools and how to package research software that bundles AI models, weights, and datasets alongside source code.


Scenario 8: 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.


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 open-source software licenses (MIT, GPL) are written specifically for source code and are legally ill-suited for datasets or neural network parameters. Under EU legal frameworks, datasets and model weights are governed by database rights (sui generis database protection) rather than traditional code copyright.

  • 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.

Best Practices: Attaching a License to Your Repository

Once you have selected a license using the JLA, you must officially attach it to your repository so automated scanners, package registries, and downstream researchers can verify your terms.

1. Adding the Root LICENSE File

Always place the full text of your chosen license in a plain-text file named LICENSE or LICENSE.txt at the root of your repository.

  • Exact Legal Text: Copy the standard text directly from spdx.org/licenses or choosealicense.com.

  • Copyright Header: Ensure you fill in the copyright year and copyright holder line at the top of the license text:

    Copyright (c) 2026 [Author Name or Institution Name]
    
  • Do Not Edit Terms: Never modify the legal wording of standard licenses (e.g., removing clauses from GPL or MIT). Custom license edits create non-standard legal texts that compliance scanners cannot parse, defaulting your repository back to restricted status.

2. Documenting License Status in README.md

Add a dedicated License section near the bottom of your repository’s README.md file, along with a machine-readable badge:

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

3. Automated Compliance with the REUSE Standard

For multi-asset research repositories containing code, data, container build recipes, and prompt templates, follow the FSFE REUSE Initiative standard:

  1. Include License Texts: Place full license files inside a LICENSES/ directory (e.g., LICENSES/MIT.txt, LICENSES/GPL-3.0-or-later.txt).

  2. Add In-File SPDX Headers: Label every source file, build script, and prompt file with SPDX tags.

  3. Verify Compliance: Run the automated REUSE linter in your CI/CD pipeline:

# Install and run REUSE compliance check
pip install reuse
reuse lint

When reuse lint passes, downstream researchers can automatically verify the legal status of every single asset in your codebase.

Summary: Resolving the Compliance Pipeline

When developing research software, license compliance is not an afterthought to debug at the end of a project, it is a proactive design choice. By using the Joinup Licensing Assistant (JLA) framework to align your repository license with your inbound dependencies from day one, your CI/CD pipeline passes cleanly on the first run.

The diagram below illustrates how selecting a compatible license upfront ensures your code passes automated compliance checks and results in a legally sound release:

%%{init: {'themeVariables': { 'edgeLabelBackground': '#faf5ff' }}}%% flowchart TB subgraph local["1. Local Authoring & Standardization"] A["<b>Inbound Reuse Trigger:</b><br/>User copies copyleft snippet <i>(Scenario 4)</i><br/>or links GPL library <i>(Scenario 5)</i>"] --> B["<b>JLA Selection Strategy:</b><br/>Select compatible copyleft license<br/><i>(GPL-3.0 / EUPL-1.2)</i>"] B --> C["<b>Standardize Local Codebase:</b><br/>1. Add <b>SPDX Headers</b> to all files <i>(Scenarios 1-9)</i><br/>2. Add root <code>LICENSE</code> file & README badge"] end subgraph cicd["2. Automated CI/CD & Verification"] C -->|"<b>Git Push</b> to Repository"| D["<b>Build Trigger: Run Compliance Scanner</b><br/><i>(Executes <code>reuse lint</code> in CI/CD)</i>"] D --> E{"<b>Verify Inbound vs.<br/>Outbound Terms</b>"} E -->|"SPDX Headers & License Match Confirmed!"| F["✅ <b>BUILD PASSES</b><br/>Compliance verified automatically"] F --> SUCCESS["🎉 <b>COMPLIANT OPEN-SOURCE RELEASE</b><br/>Legally sound, reproducible & ready for scientific reuse"] end classDef pass fill:#e6ffe6,stroke:#2b8a3e,stroke-width:2px,color:#1b4332; classDef neutral fill:#f8f9fa,stroke:#495057,stroke-width:2px,color:#212529; classDef box_fill fill:#ffffff,stroke:#adb5bd,stroke-width:1px; class F,SUCCESS pass; class A,B,C,D,E neutral; class local,cicd box_fill;

Scenario Mapping Across the Pipeline

  • Handling Inbound Copyleft (Scenario 4 & Scenario 5): When you copy non-trivial copyleft code snippets (e.g., CC BY-SA from Stack Overflow or GPL snippets) or link directly against a GPL library, your overall project becomes a combined work. Selecting a compatible copyleft license upfront (GPL-3.0 or EUPL-1.2) satisfies the reciprocal sharing terms and allows the pipeline scanner to pass without conflict.

  • Maintaining Permissive Defaults (Scenario 1 & Scenario 3): If you write original code or embed only permissively licensed snippets (MIT, Apache-2.0, BSD), selecting a permissive license (MIT or Apache-2.0) grants downstream users maximum adoption freedom while preserving your citation credit.

  • Packaging and Build Automation (Scenario 6 & 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 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: By adding machine-readable SPDX headers across every script, Dockerfile, and prompt template, running reuse lint in your pipeline confirms 100% legal clarity for the entire scientific community.