LexLint whitepapersPaper 3 of 3

You already think about law

The license field is a legal declaration, and what your code does needs one beside it

Author
Sean McDermottCo-Founder and CEO, UnGovr
Date
Part
Why it matters

Legal information, not legal advice. This paper describes the law as written and dated; it does not apply it to any system. The notice in the footer says what that means.

Abstract

Every developer who fills in a license field makes a legal declaration. Licensing shows how that became routine without making anyone a lawyer: a shared vocabulary, a line in every file and a field in every package, then a path into the bills of materials buyers ask for. What code does under law has no such field, though a library's behavior travels into every jurisdiction its products reach, and each product's counsel rediscovers what it does. This paper retraces how licensing became a field, works one invented library and three products through the gap, and ends with what a repository's legal declaration must do.

1Introduction: you already do law

1.1 Features that are law

You already do law. Not the way a lawyer does: nobody reads a statute to add a cookie banner. You do it the way you do everything else, as a feature with a ticket, a default and a test. Here are eight of them.

What you buildThe law it answersWhere it binds
A license field in a package manifest, or a license picked on a repository's creation page Copyright: who may copy, change and share the code. In the United States, the Copyright Act, 17 U.S.C. 106 and 501; in the EU, the Software Directive Almost every jurisdiction, on terms that differ less than any other row's
A cookie banner The EU's rule on storing or reading information on a user's device, Article 5(3) of the ePrivacy Directive The EU's member states, each through its own national law
An unsubscribe link in a marketing email Commercial-email law, such as the United States' 15 U.S.C. 7704 Most jurisdictions, on different terms: the United States asks for a way out, while the EU and Canada ask for consent first, with exceptions
An accessibility pass on a checkout flow Accessibility law, such as the European Accessibility Act, Directive (EU) 2019/882 The EU, for the products and services the Act lists, e-commerce among them. Other jurisdictions keep lists of their own
An age gate on sign-up Children's privacy law, such as the Children's Online Privacy Protection Act (COPPA) The United States, for a service directed to children under 13, or one that knows it is collecting their personal information
A "Do Not Sell or Share" link California's right to opt out of the sale or sharing of personal information, in the California Consumer Privacy Act California, for a business over the statute's thresholds
An account-deletion endpoint The right to erasure, Article 17 of the General Data Protection Regulation The EU, and any service outside it that offers goods or services to people in the EU or monitors what they do there
An encryption export notice Export control on encryption, such as the United States' Export Administration Regulations Code exported from the United States. The EU and other jurisdictions keep control lists of their own

The third column is the one nobody asked you about. Each row binds in some jurisdictions and not others, and every team that shipped one of these decided which users get it. Ship the cookie banner to everyone and you apply the EU's rule to people it does not reach. Ship it only to the users you think it reaches and you have decided, in code, who those are. Either way the decision is a default, made without a legal reading, and it holds until someone changes it.

The claim in one line

The license field is a legal declaration, and developers learned to fill it in without becoming lawyers. What your code does under law needs the same kind of field next, and licensing has already walked most of the path.

1.2 Who should read this

Developers and the maintainers of libraries, frameworks and applications, first. Then the people who carry what a repository says downstream: package registries, the authors of the tools that build a software bill of materials, and the buyers who ask for one. Section 5 says what falls to each. The legal case for agentic software, in an attorney's terms, is the companion paper Whose law was that? This one makes a developer's case, and needs nothing from it.

1.3 Terms

Jurisdiction. A body of law together with the authorities and courts that apply it. LexLint keys every law to one jurisdiction at one of four levels: supranational (the EU), national, subnational (a US state, a province, a Land), or local (a city). In practice the law that binds software is made at the national and subnational levels, with the European Union above its member states. A small number of cities have software law of their own, which the law library lists by name.

Activity. Something code does that the law has a word for: sending a marketing message, recording a call, collecting a child's data, scraping a website. An activity is a fact about the code. Whether a law reaches it is a question about the jurisdictions it runs in.

Declaration. A statement a project makes about itself, in a form a tool can read. A license field is one.

2Background: how licensing became a field

Licensing is the one part of the law every developer handles, and it was not always a field. It became one in four steps, and each turned a legal fact into an engineering artifact without asking developers to read the law.

2.1 Known to matter, not tracked

A license was always law. It is the copyright holder's permission to copy, change and share the code, and without one the default is that you may do none of those. For most of open source's history it lived in prose: a comment header in whatever style its author liked, a file at the root, or nothing at all. Anyone who needed the answer (a company shipping the code, a buyer in an acquisition, a distribution packaging it) read for it again, and the next reader started from scratch.

The Linux kernel left a record of the cost. When its maintainers set out to label its files, the commit that began the work said that many source files in the tree were missing licensing information, "which makes it harder for compliance tools to determine the correct license."

2.2 A shared vocabulary

SPDX began in 2010 as a work group under the Linux Foundation, and its 1.0 specification followed in 2011. The specification carried, as an appendix, a table of standard short forms for licenses, and a document written to it named each package's license by its short form. That table grew into the SPDX License List, which today gives every license and exception on it a standard short identifier, a full name, the license text and a permanent URL.

The identifier is the step that mattered. Free text cannot be compared: "GPL v2", "GNU GPL version 2" and "the GPL, version 2 only" are three strings, and a tool has to guess whether they name one license. GPL-2.0-only is one string, and two tools that read it agree. Choosing a license still takes a decision. Recording it no longer takes a lawyer's prose.

2.3 A line in every file, a field in every package

On a commit to the Linux kernel began tagging its files. The analysis started from the 4.13 kernel, with 60,537 files assessed, in a spreadsheet that set the results of two independent scanners side by side. Where the scanners disagreed, a person inspected the file. Where the answer was still not clear, lawyers working with the Linux Foundation confirmed it, so that the developers did not have to, and a file with any question left was flagged for further research. The commit logs over 70 hours of that review. Its first patch added a one-line identifier to 11,139 files from the 60,537 assessed, outside the user-space API headers: those in which neither scanner had found any license information. A second patch tagged 930 user-space API headers that carried none, documentation files were excluded from tagging, and the commit said further patches would follow in the months after. It called the identifier "a legally binding shorthand, which can be used instead of the full boiler plate text." The kernel's licensing rules now require the precise identifier in all source files.

Package metadata took the same identifiers. npm's documentation for package.json tells authors to name the license by its SPDX identifier, or by an SPDX license expression when there are several. Python's PEP 639, now final, added a License-Expression field to the core metadata that describes every Python package. One license identifier, written three ways:

# a C file in the Linux kernel // SPDX-License-Identifier: GPL-2.0 # package.json, which npm reads "license": "(MIT OR Apache-2.0)" # pyproject.toml, under PEP 639 license = "MIT"

The field sits where a developer already is: the top of the file, the manifest, the root of the repository beside the LICENSE file. Nobody has to go looking for it, and neither does a tool.

2.4 Carried downstream, then expected

A field that stays in one repository helps one reader. The identifiers travel. The specification that carries the list is itself a format for describing a package and its files, each with its license as an identifier from the list, and a software bill of materials (SBOM) built from a product's packages carries the same strings to everyone who receives the product. In 2021 the specification was recognized as an international standard, ISO/IEC 5962:2021, by the SPDX project's own account.

By then the field was an expectation. The kernel requires it in every source file, the package managers ask for it, and buyers ask for the SBOM that collects it. The law has since begun to ask for the inventory, though not for the field. Under the EU's Cyber Resilience Act (from , in 13 months) a manufacturer of a product with digital elements will have to identify and document the vulnerabilities and components contained in it, including by drawing up a software bill of materials in a commonly used, machine-readable format covering at the very least the product's top-level dependencies (Annex I, Part II, point 1). That point names no license: the Regulation requires the bill of materials, and the license field stays a convention that travels in it.

What licensing did not ask

None of the four steps made developers into lawyers. Each turned a legal fact into a field: a vocabulary to fill it from, a fixed spot in every repository and package to put it, and a path downstream to whoever needs to read it. Developers make a legal declaration every time they start a project, and most never think of it as one.

3The problem: what your code does under law has no field

Licensing answered one legal question: who may copy, change and share this code. The table in section 1 raises others, about what the code does when it runs: whether it sends a marketing message, keeps a phone number, reads a cookie or decides something about a person. Those questions have no field. They split in two, and the split decides what a repository can say.

3.1 What the code does

Some of it is fixed when the code is written. A messaging library can send text messages; a crawler fetches other people's pages; a recorder captures a call. That is as much a fact about the code as its license is, and it belongs where the license is, at the root of the repository.

The fact comes in two forms, and the difference matters to everyone downstream. A library enables an activity: it sends a message only when a product calls it, to whomever the product names. An application performs it: it decides to send, and to whom. A library can also perform something itself, in every product it ships in, and that is usually a default: a log it keeps, a call home to its maintainers' servers, a cache it writes. A default is the part of a dependency with the widest blast radius, because every product that does not change it ships it.

What a repository cannot usefully say is which laws apply. A library does not know which jurisdictions its products will run in, so a list of laws in a library is a guess for every product that uses it, and wrong for most. The activity is the stable fact. The law is resolved later, by each product, from its own jurisdictions, the way a license identifier is turned into obligations by whoever ships the code.

3.2 Whose law reaches each act

The other half is not fixed until the code runs. Which jurisdictions' law reaches a message depends on who the parties are when it is sent: where the business sending it is established, where the person receiving it lives, where the provider carrying it is established. A repository cannot hold those facts, because they differ for every product and every message. They exist only at run time, and they have to pass from the system that knows them to the systems that act on them. The companion paper that makes this case for agentic software follows one agent's request through the software in its path, and finds that none of it carries the parties (Whose law was that?).

Two things sit between the halves, and a repository can say both. The first is the counterparties the code necessarily talks to. A library that can send text messages only through one provider's API brings that provider into every product built on it, and with it the jurisdiction the provider is established in. That is fixed when the code is written, so it can be declared beside the activity. The second belongs to a product, not a library: the jurisdictions the product means to operate in. Declared, checked, held describes that practice, in which counsel draws the boundary and the software is held to it. What no repository can state is where each party turns out to be when the code runs, and holding a product to its boundary needs that fact too.

3.3 Why this is harder than licensing

Licensing had two advantages that behavior lacks. A license is one grant, attached to the code, under a body of law that is broadly harmonized across countries, so one identifier means much the same thing in every jurisdiction a package reaches. What code does is governed by law that differs by jurisdiction, as the table's third column shows, and it attaches when the code runs, to the parties of each act.

So a field for behavior cannot carry an answer. It can carry the facts an answer is worked out from, which is all the license field ever carried: the identifier names a license, and the obligations are read from it downstream.

4Worked example: one library, three products

The example is invented. Its library, its products and their counsel are fictional, it analyzes no real software, and it is written to show which facts each reader needs, not to say what any product owes.

4.1 One library, three products

Quaybell is an open-source library for sending reminders by text message and email. It is popular because it is small: one function to send, one to schedule. Two facts about it are easy to miss from the outside. It sends text messages through one provider's API, the only one it supports, and that provider is established in the United States. And by default it keeps a delivery log, for 30 days, of each recipient's phone number and the text of each message, so that a failed send can be retried. Three products are built on it.

ProductWhat it does with QuaybellWhere it operates
PennantInvoicing for small businesses. Its collections agent chases late invoices by email and text message. It is the sample application of Declared, checked, heldIreland, the United Kingdom and the United States, among the jurisdictions its declaration names
PraxelleAppointment reminders for medical practices, by text messageGermany
Tiziu EntregasDelivery updates for online shops, by text messageBrazil

4.2 Without a declaration

Each product's counsel has to find out what Quaybell does before reading any law, and the only thing to read is the code. Three teams read it three times. Pennant's engineers know the provider, because they set up its account, and never notice the delivery log. Praxelle's find the log in a code review a year after launch. Tiziu Entregas runs a dependency scanner, which reports the library's license and nothing about what it does. Each reading is private, each is partial in a different way, and none of it reaches the other two teams.

The facts they missed are the ones the law turns on. A delivery log that keeps the text of a clinic reminder can say which practice a patient sees. Every message reaches a provider established in the United States. Both facts are fixed by Quaybell, and the products' own code shows the reader nothing of them.

4.3 With one

Now suppose Quaybell states, at the root of its repository beside its license, what it does, in words from a vocabulary every reader shares. The statement names activities and counterparties, and no law.

ActivityPerforms or enablesCounterparty
Sending text messagesEnables: it sends when a product calls it, to the recipients the product namesOne text-message provider, established in the United States
Sending emailEnables, in the same wayThe mail server the product configures
Keeping a log of each recipient's phone number and the message text, for 30 daysPerforms, by default, in every product that does not turn it offNone

Each product reads the same statement and resolves the law from its own jurisdictions.

ProductWhat it reads in the statementThe law its counsel reads for it
PennantRecipients' phone numbers and messages go to a provider in the United States, and a log of them is keptThe EU's rules on transfers of personal data out of the EU (General Data Protection Regulation, Chapter V)
PraxelleThe same, and the log keeps reminder text that can say which practice a patient seesThe same transfer rules as Germany applies them (Chapter V, from Germany), and the rules on special categories of personal data, health among them (General Data Protection Regulation, Article 9)
Tiziu EntregasRecipients' phone numbers and messages go to a provider in the United StatesBrazil's rules on international transfers (General Personal Data Protection Law, articles 33 to 36)

What each of those laws asks of each product is for that product's counsel. What changed is where the reading starts: one statement, made once by the people who wrote the code, instead of three partial readings of the code. And the default is visible before it ships. Praxelle can turn the delivery log off, or shorten it, before its first reminder goes out rather than a year after.

4.4 When a scan says something else

Praxelle's security team runs a scanner over its dependencies, and the scanner reports that Quaybell can record calls, because one of its own dependencies handles audio. Quaybell's statement says it sends text messages and email and keeps a log, and says nothing about calls.

The project's statement wins. Its maintainers wrote the code and know what it does; the scanner inferred from the outside, and so does every other reader. Praxelle can still decide what to do in its own product about a risk it suspects. What it does not do is replace what Quaybell says about Quaybell with its own inference, in its records or anyone else's.

A disagreement goes upstream. If Praxelle thinks the statement is wrong, it files an issue on Quaybell, where the statement lives. If the maintainers agree, they correct the statement, and the correction reaches Pennant and Tiziu Entregas with their next upgrade. If they do not, the statement stands, and every reader can see what is disputed. The statement can still be wrong (section 6 says so), but it is wrong in one public record, where it can be fixed once. The other way round, each reader acts on its own inference: three products hold three accounts of one library, none of them the maintainers', and a correction one of them makes reaches nobody else.

Licensing settled the same question the same way. The kernel's tags came out of the project's own review, scanners and lawyers included, and a file whose answer was unclear was flagged to be revisited in the project, not guessed at by each reader. Compliance tools read the tag rather than inferring again, and a tag that turns out wrong is corrected the way any other line of the kernel is, by a patch.

5What a repository's legal declaration must do

Each line below says what a declaration of what code does must do, whatever form it takes, and names the passage of this paper it comes from. No law requires such a declaration (section 6), and these lines are not read from any law. They come from the precedent in section 2, what made the license field work, applied to the facts in sections 3 and 4.

D1
Stated at the root of the repository, where the license is. Derives from 2.3.
D2
Drawn from a shared, open vocabulary of activities, never free text. Derives from 2.2.
D3
Says whether the code performs an activity or enables it for whoever uses it. Derives from 3.1.
D4
Names the counterparties the code necessarily talks to, since those pull in jurisdictions. Derives from 3.2.
D5
Names activities, never laws: the law is resolved where the product runs. Derives from 3.1, 3.2.
D6
Machine-readable, and carried with the package into a bill of materials. Derives from 2.4.
D7
The project's own statement wins over anyone's inference about it. Derives from 4.4.

5.1 Who does what

WhoWhat they can doRequirements
Maintainers of a library, framework or applicationState, at the root beside the license, what the code performs and what it enables, in words from a shared vocabulary, and the counterparties it cannot run without. Put a default that touches people's data in the statement, since every product inherits itD1, D2, D3, D4, D5
Package registriesGive the statement a field in package metadata, as the license has one, and show it on the package's pageD1, D6
Authors of tools that build a software bill of materialsCarry the statement with each component, as license identifiers are carried, and show a reader where the statement and a scan disagree rather than settling it silentlyD6, D7
Buyers who ask for a software bill of materialsAsk for the statement where you ask for the bill of materials today, and take a disagreement with it to the project that made itD6, D7

6Limitations

This paper does not say that any law requires a repository to declare what its code does. The argument is that licensing shows how a legal fact can become a field every developer fills in without legal training, and that what code does under law has no such field yet. Section 5 says what one would have to do.

The analogy has limits. A license is the author's grant, and it is true because the author says so. A statement of what code does is a statement of fact, and it can be wrong, which is why section 4.4 sends a disagreement back to the project. And a license works under law that is broadly harmonized, while the law that reaches what code does differs by jurisdiction (section 3.3), so a declaration carries facts and never an answer.

It does not say what any product owes. The example is invented, and its tables name the law each product's counsel would read, not a conclusion about it. The opening table names one example law per row, and its third column is a summary, not a statement of each law's reach.

The history in section 2 was read from each source's own pages on , and References lists them. ISO/IEC 5962:2021 is cited as the SPDX project states it. The requirements in section 5 are not LexLint's to own: they are offered for anyone to meet, by any means. The mechanisms that might meet them are kept apart from this argument on purpose, so that an objection to one of them is not an objection to the case (section 7 says where they are).

7Conclusion

You already think about law. You picked a license, typed its identifier into a manifest, and the tools downstream read it without asking you a question. That field took a vocabulary, a fixed spot in every repository and a path into the supply chain, and none of it asked a developer to read a statute. What your code does under law (the messages it sends, the data it keeps, the services it cannot run without) has nowhere to go yet, so every product that depends on it finds it out again. It needs the same kind of field, beside the license, and section 5 says what that field must do.

Where this goes next

How a declaration might meet the requirements in section 5 is a separate question, and nothing above depends on it. ACTIVITIES.md is LexLint's proposal for such a file: a project states, at the root of its repository, the activities its code performs or enables, drawn from an open registry, and the counterparties it cannot run without, with a table of the requirements in section 5 it meets and what it leaves to others. It can also be carried into a CycloneDX bill of materials. The other proposals are listed under Open proposals, and the paths by which each might become a standard are set out in Paths into standards.

References

Every law named in this paper that the law library carries, by the law library's own name for it, then the sources of the history in section 2.

  1. Copyright Act, exclusive rights and infringement, 17 U.S.C. ยงยง 106 and 501
  2. Directive 2009/24/EC on the legal protection of computer programs (Software Directive), Articles 1, 4, 5 and 6
  3. Children's Online Privacy Protection Act (COPPA)
  4. CCPA/CPRA Consumer Rights: Access, Deletion, Correction, and Opt-Out
  5. GDPR Articles 12-21, Data Subject Rights
  6. Cyber Resilience Act, Essential Requirements and Manufacturer Obligations
  7. GDPR Chapter V, Cross-Border Transfer Restrictions
  8. GDPR Chapter V, Cross-Border Transfer of Personal Data from Germany
  9. GDPR Article 9, Special Categories of Personal Data Including Biometric Data
  10. LGPD, international transfer of data
  11. The SPDX project: About, its timeline and its statement on ISO/IEC 5962:2021
  12. The SPDX project: Specification 1.0, Linux Foundation
  13. The SPDX project: License List
  14. The Linux kernel, commit b24413180f56, "License cleanup: add SPDX GPL-2.0 license identifier to files with no license",
  15. The Linux kernel documentation, Linux kernel licensing rules
  16. npm Docs, package.json
  17. PEP 639: Improving License Clarity with Better Package Metadata
  18. Regulation (EU) 2024/2847, the Cyber Resilience Act, official text, Annex I, Part II, point 1

About the author

Sean McDermott is Co-Founder and CEO of UnGovr, which publishes LexLint: a library of the law that reaches software, and a lint that reads a project against it. Corrections and comments are welcome at hello@ungovr.org.

Linux Foundation Associate Member Agentic AI Foundation Associate Member Open Secure AI Alliance UnGovr is an Associate Member of the Linux Foundation, of the Agentic AI Foundation and of the Open Secure AI Alliance. While UnGovr supports the mission of all three, none of them reviews, certifies or endorses LexLint, its findings, or this paper.
About this paperUpdated ShowHide

Sean McDermott, Co-Founder and CEO, UnGovr

Written by Sean McDermott (with AI assistance) using the LexLint law library, which supplied every legal instrument, status and date on these pages.

Every law named here links to its summary page on lexlint.io, translated to English (if needed) and restructured to a standard format for human and code use.

© 2026 UnGovr, publishing as LexLint. This paper, its text and its figures, is licensed under Creative Commons Attribution-NoDerivatives 4.0: cite it, quote it and share copies of it as it is, including commercially, with credit to LexLint (UnGovr). Do not adapt it, translate it or build another document from it without permission. Please contact LexLint at hello@ungovr.org to discuss other terms. Logos and wordmarks belong to their owners.

Law library as of .