ADR-0129: An extension payload carries its licence inside it
- Status: Accepted
- Date: 2026-09-20
- Deciders: jka
- Decision: D122
Context
ADR-0128 licensed rio under MIT with a single LICENSE at the
repository root, on the reasoning that rio is copied wholesale: clone it, package it,
mirror it, and the licence arrives with every source file in the tree. That record
declined per-file headers for the same reason.
Extensions are the one part of rio for which that is false. An extension is fetched from
a repository over plain http (ADR-0039) and installed
file by file, and where the files land depends on the kind: a mode or syntax payload
is written into the user's ~/.config/rio/modes/ — a directory shared with every other
extension of that kind — a theme is handed to the core and kept in its theme store,
and only a provider gets a directory of its own. Nothing shipped beside a payload
travels with it, and for the shared directories nothing could: two extensions cannot both
install a file called LICENSE there.
So rio's own extensions, MIT in the tree from the moment ADR-0128 landed, arrived on a user's disk as files that could not say what they were — at exactly the point where the question gets asked, which is the second copy rather than the first.
ADR-0127 had already put the test in the right form for artwork: the question is not whether rio may use something, but whether everyone who receives it may pass it on. A payload is in the same position as the icon was, and more exposed, since being fetched by strangers is the ordinary way to obtain it.
Decision
Every payload rio's own extensions ship carries the full MIT notice — copyright line,
permission paragraph and warranty disclaimer — inside the comment block the file already
opens with. That is extensions/claude/*.tcl, extensions/openai/*.tcl,
extensions/emacs/emacs.tcl, extensions/vi/vi.tcl, and night-theme/night.theme in the
publishing repository. Their tests are not stamped: tests stay behind.
The notice is the full one and not a pointer. MIT asks for it to be included in all copies, and a file that travels alone is the case that requirement exists for; "MIT, see LICENSE" would send a reader to a file that is not there.
Theme files take # comments like any conf file
(ADR-0021), and
rio::theme::put validates by parsing and then stores the text verbatim, so the notice
reaches the user's theme store intact.
The publishing repository is a separate git repository and had no licence of its own; it
gets the same LICENSE. Its README states the terms and says plainly that another
publisher's extensions are theirs to license — a rio repository makes no claim about what
it serves, because the sources list is the trust list.
CONTRIBUTING states this to extension authors as a consequence of the format rather than as a house rule: nothing beside a payload arrives with it, so a licence has to be in the file. rio neither asks for one nor checks for one.
Alternatives considered
- Leaving it to the root
LICENSE. This is what ADR-0128 already did, and it is correct for everything that travels with the tree. It simply does not reach a file installed on its own. - A
LICENSEfile among an extension'sfiles. Defeated by where the files go: the sharedmodes/andsyntax/directories would have every extension'sLICENSEcolliding on one name, and a theme's payload is not written as a file at all. - A
licensekey inrio-extension.conf. The manifest is installed for a provider, and the install prompt could show the licence as consent is given. But it changes the manifest contract, it is advisory — nothing can verify a claim made in a.conf— and the notice in the payload is the part with legal work to do. Deferred, now for a reason rather than by omission. - An SPDX tag alone. Machine-readable and one line, but it identifies a licence without granting it, which is the wrong half for a file with no licence beside it.
Consequences
- An extension file that leaves rio — installed, copied out of a config directory, mailed on, pasted into someone else's repository — carries its terms with it.
- Payload files open with roughly twenty lines of notice before their description. That is the visible cost, and it is paid once per file.
- ADR-0128's refusal of file headers now has a stated boundary rather than being a flat rule: the licence lives with whatever unit actually travels — the repository for rio, the file for an extension. A future decision about some other separately-distributed artefact has the test to apply.
- Nothing enforces this. No test can read a licence off a payload, and rio must not start refusing extensions over what their comments say. It is held by review, as ADR-0127's artwork rule is.
- The publishing repository's
SHA256SUMScovers every served file, so stamping the payloads invalidates its signature. Re-hashing and re-signing is the ordinary publish step (SIGNING.md), not a new obligation — but it is required before the next upload.