384. The emoji face is an artifact an application opts into
Date: 2026-09-17
Status
Accepted. Closes docs/ARCHITECTURE.md §17.1’s “goldberry-emoji is not a
module, and core carries its attribution” — which that section called the only
obligation in the toolkit an application cannot discharge with a file.
Context
content-widgets.md’s table has always quarantined OpenMoji in an optional
artifact, and given the reason: CC BY-SA asks for attribution where the work
is seen. An about box, a credits screen, a help page — not a line in a notice
file inside a jar.
goldberry-core shipped the font anyway, because the emoji slot is part of
§6.1’s font chain and the chain lives in the text stack. So every application
that depended on Goldberry inherited a share-alike attribution obligation
whether or not it ever drew an emoji, and had no way to tell that it had.
§17.1 recorded the two as defensible and incompatible. They are not: the chain is a text-stack decision and the face is a packaging one, and nothing required them to live in the same artifact.
Decision
The face ships as goldberry-emoji; :core keeps the slot and loads the face
through a service.
assets.EmojiFontis a service interface in:core, whichusesit.goldberry-emojiprovidesit withOpenMojiFont, and declares the provider inMETA-INF/servicesas well, so it is found on the class path and on the module path alike.- A resource, not a service, was the obvious alternative and does not work: a resource in a named module is encapsulated, and opening a package to read one file is a wider hole than a provider.
BundledAssets.font(EMOJI)with no provider throwsMissingEmojiFontException, whose message names the artifact, the licence and what to do about it.BundledAssets.hasEmojiFont()is the cheaper question for an application that draws emoji when it can.OpenMojiFont.CREDITis the sentence to display, as a constant, so an application meets the obligation without transcribing it.:assetsprepares a selection now —--only=inter,jetbrains-mono,lucidefor:core,--only=openmojifor:emoji— and each asset task empties its directory first, because an incremental build otherwise keeps shipping a face the module has stopped fetching.PublishedModulesgains one line and the BOM, the umbrella and the POMs follow; the artifact is optional, likegoldberry-htmlandgoldberry-gpu.
Consequences
- An application that drew emoji before must now add a dependency. That is the change, and it is the point: the obligation is visible at the moment it is taken on. The failure says so in a sentence rather than as a missing resource.
:coreis 1.4 MB smaller, which is a side effect and not a reason.- The shaping test moved with the font: “emoji shape through the emoji face”
belongs to the artifact that ships the face, and
:coreasserts the absence — thathasEmojiFont()is false and that the message names the artifact. NOTICEandTHIRD-PARTY-NOTICES.mdsay which jar the font is in, and that an application adding it owes the credit.licenses/openmoji.txtstays where it is: the licence text is still disclosed by the repository whether or not a given build ships the font.- §6.2’s re-themed COLRv0 variant is unaffected and still not bundled. If it ever is, it is a derivative work and the statement of changes goes in the same two files.