Skip to content

Latest commit

 

History

History
260 lines (210 loc) · 17.2 KB

LICENSES.md

File metadata and controls

260 lines (210 loc) · 17.2 KB

Licensing map

Hifth's own work is GPL-3.0-or-later (LICENSE). But the repository also carries data it did not write, under terms it cannot change, so a single blanket statement would be inaccurate. This file is the map: which terms cover which paths, and why.

SOURCES.md is the authority on every third-party source — its provenance, its verbatim license text, and where the notice ships. This file only says how those terms compose.

The buckets, by door

Something leaves this project through three doors, and "may this be distributed?" has a different answer at each — so the map is organised by door first and by path second. Each row says what goes out, through which door, under whose terms. The doors and what goes through each were measured in docs/design/what-we-distribute.md; the numbers below are its.

Through the repository — public, cloneable

The whole tree, every vendored input verbatim. This is the door the copyleft obligation is discharged at: the corresponding source for every derived tree below is here, and reachable.

Paths Terms Whose choice
apps/web/, packages/core/, packages/etl/ (scripts), scripts/, docs/, config GPL-3.0-or-later Ours
packages/etl/data/** — 17 vendored input files, 12.3 MB, verbatim Each source's own terms — not ours to relicense KFGQPC, QAC, quran-tajweed, Tanzil, Waqar144
apps/web/public/assets/** — the derived trees, checked in as built The site door's terms, below As below

Through the deployed site — public, fetched by browsers

Derived assets and the app bundle. No vendored input reaches a browser; what does is built from them, and some of it inherits their terms.

Paths Terms Whose choice
The app bundle, apps/web/dist/, about 120 KB gz GPL-3.0-or-later Ours
apps/web/public/assets/roots/** GPL-3.0 (inherited) The Quranic Arabic Corpus's
apps/web/public/assets/skins/** CC BY 4.0 (inherited) quran-tajweed's
apps/web/public/assets/adj/** free use with attribution (inherited) and CC BY (inherited) and Sadaqa-e-Jaria free use (inherited) Waqar144's and Tanzil's and MushafDatabase's
apps/web/public/assets/words/** GPL-3.0-or-later Ours — rectangles we measured
apps/web/public/assets/marks/** GPL-3.0-or-later Ours — rectangles we measured
apps/web/public/assets/letters/** GPL-3.0-or-later Ours — dividing lines we measured
apps/web/public/assets/manifest.json GPL-3.0-or-later, with one question open (below) Ours
apps/web/public/assets/pages/** KFGQPC's own terms — not ours to relicense KFGQPC

Through a store binary — no such door yet

Nothing goes through it. If one is opened it would carry the site door's contents wrapped in an installable, and that is where two clauses in the inherited grants bite that a static site never trips — the technological-measures clause of CC BY 4.0, and the GPL's conveying terms on a binary rather than a page. docs/design/track-b-native.md is the record for that door.

Until 2026-09-01 this file had one table, organised by path, which silently meant the site door: it said nothing about the repository, where every vendored corpus actually is and where the copyleft obligation is discharged, and nothing about a store. A reader got an answer to "may this be distributed?" without being told which distribution it answered for.

Why GPL for our code

Copyleft, chosen so improvements come back. The plain GPL rather than the AGPL, and the reasoning is specific to what Hifth is: a fully static, backend-free PWA hands the browser its entire JS bundle, so anyone deploying a modified Hifth is already conveying the code under §4–6 and owes their users the source. The AGPL's §13 exists to close the network-service hole — the case where the modified code runs on a server the user never receives — and Hifth has no server to hide behind. Taking the AGPL would add real adoption friction to cover a case the architecture does not have.

It also collapses a seam. The derived root shards are GPL-covered whatever we do (below), so licensing our code GPL makes "GPL, except the vendored upstream assets under their own terms" the whole story, instead of a code license and a data license in tension.

Why the root shards are GPL, and what that obliges

apps/web/public/assets/roots/** is generated by packages/etl/scripts/build-roots.mjs from the Quranic Arabic Corpus morphology. Under a strict reading — the one we design to — those shards are a derivative work of a GPL-licensed input, so they carry GPL terms forward. Two consequences we actually have to honor:

  1. Corresponding source must reach recipients. For the shards that means packages/etl/scripts/build-roots.mjs plus the pinned input at packages/etl/data/roots/quranic-corpus-morphology-0.4.txt. Both are in this repository — which discharges the obligation only once the repository is reachable by the people receiving the shards. See the deploy note below.
  2. The notice travels with the data. assets/roots/<edition>/NOTICE.txt is emitted beside the shards by the build, quoted verbatim from the source header so it cannot drift, and the app shows a visible credit and copyright line on the root lens.

The corpus's terms of use and the GPL contradict each other on modification (GPL §5 grants it; the terms say changing is not allowed). We satisfy both readings rather than picking one: the file is vendored verbatim and never edited, and the shards are derived from it at build time. docs/decisions/loop-5.md records the full analysis.

The app code does not read the corpus data at build time: every asset it touches is fetched by URL at runtime, and no source file imports or reads anything under packages/etl/data/. Our code is GPL because we chose it, not because the corpus required it.

That is a statement about one boundary, and it used to be written as though it covered all of them — "nothing here reaches our source by way of the data". It does not, because content can arrive by being typed, and once did: twelve verses were transcribed into a source file and shipped in the bundle for the life of a feature, having crossed no build step at all. gate:scripture now refuses running scripture anywhere in the tree, which is the check that sentence was quietly standing in for.

Why the adjacency shards have three parents, and not one

Since 2026-09-26 the corpus is no longer one of them. The spans, and the whole-verse twins, are now found in the print's own words — MushafDatabase's numbering, the same upstream the word boxes come from, released as Sadaqa-e-Jaria (free to use, derive and publish) — with each lone "and" glued onto the word after it, which is the one habit the corpus and the print differ on. Glued, the print keeps every span the corpus gave, on the same words, and the same 74 twin clusters; a test holds it to both. The builder no longer imports the corpus reader at all, so the notice check would fail the day it did. That was decision adjacency-span-source = D. The three parents are now Waqar144 (the pairings), Tanzil (the juz flag) and MushafDatabase (the spans and twins). What follows is how the corpus came to be a parent, kept because the way it arrived — as a feature, with no licence edit — is the lesson.

apps/web/public/assets/adj/** carried one upstream for most of this project's life, and the row above said so: the mutashabihat pairings are Waqar144's, free to use with attribution. That stopped being true when the shards started carrying spans — which words of an ayah a pairing actually shares — and nothing in a licence file moved, because nothing about the drift was a licence edit. It arrived as a feature.

build-adjacency.mjs imports sharedRuns from morphology.mjs, and that module reads the same GPL-licensed Quranic Arabic Corpus morphology the root shards are built from. Its result is written into every pairing it can answer for as span and toSpan. Today that is 2,544 of 3,002 edges across 114 shard files — not an edge case, the common case.

So under the same strict reading of derivative applied to the root shards above, the adjacency shards are a GPL derivative too, and one of their two parents was unnamed. Both were named then. The pairings remain Waqar144's and still owe attribution; the spans are the corpus's and carry GPL terms forward, with the same two consequences the root shards have.

A third parent was named on 2026-09-01, and it arrived the same way the second did — as a feature, through no licence edit. 510 of 3,002 edges carry a flag saying whether a pairing stays inside one juz, computed from the juz table in the shared core package; that table is derived from the Tanzil structural metadata (tanzil-quran-metadata in SOURCES.md, CC BY, attribution mandatory). No Tanzil byte ships — the flag is a boolean — but attribution is owed for what was derived, so the row and the notice name Tanzil too. What made this one harder to see than the second: gate:notices traces what a builder reads through its imports, and by its own header it does not follow imports into the core package, so a builder can reach a new upstream through core and the trace stays green. The declaration in the gate names Tanzil by hand for now; whether the trace should follow core is still open, in docs/design/what-we-depend-on.md ③.

The asymmetry worth keeping in mind: a static site discharges §4–6 by handing the browser the whole bundle, which is this file's own argument for plain GPL over AGPL. A wrapped store binary is the thing that has to be licensed, which is why this matters more to Track B than to the web build — see docs/design/track-b-native.md.

The notice travels with this data too, as of 2026-08-16. assets/adj/<edition>/NOTICE.txt is written by the build beside the shards, and it names both parents — the way to get a two-parent row wrong twice is to fix it once, and a notice that discharged the GPL half while dropping Waqar144's attribution would have been the same one-parent mistake wearing the other hat. Since 2026-09-01 it names all three; since 2026-09-26 the three are Waqar144, Tanzil and MushafDatabase, and the corpus's copyright block is no longer in it, because nothing of the corpus reaches these shards.

Nothing had noticed any of this, which is its own finding. gate:notices now traces what each builder actually reads, in imports rather than in prose, and fails the build when a shipped asset tree reads a vendored input that neither this table nor the tree's notice accounts for.

What this does not yet settle. Building that trace immediately surfaced one more candidate parent: every edge in every shard carries the page it lands on and the distance in pages to its pair, and those come from a table derived from the KFGQPC page corpus — bucketed in the row below under terms neither upstream here grants. Whether a table of which page an ayah falls on is expression that carries terms forward, or a fact about a printing, is a licensing question and not an engineering one. It is recorded rather than guessed, because naming a third parent without grounds would overstate what this app owes in a notice handed to every reader, and leaving it unnamed understates it if the answer runs the other way.

Why the word rectangles are ours

apps/web/public/assets/words/** is 604 files of geometry: for every word of the mus'haf, a rectangle on our page frame. It shipped for months in no row of the table above and under no heading in this file — not because anyone decided it needed none, but because nothing was reading the folder. gate:notices reads it now, and this is the row it asked for.

The rectangles were fitted from a second SVG print of the same mus'haf, set per word rather than per page (word-geometry-mushafdatabase in SOURCES.md). No byte of that print ships. 378 MB was read to write 2.2 MB of numbers, and the ink stays the print we already had. Its grant is a Sadaqa-e-Jaria one — use, copy, modify, publish, distribute and derive, commercially included, with no prior approval and no attribution obliged — so the tree inherits nothing that has to travel with it. The colophon credits it anyway, and SOURCES.md says in as many words that the credit is a courtesy so that a later reader does not mistake it for a condition, or mistake a condition for a courtesy.

Why the mark rectangles are ours too

apps/web/public/assets/marks/** is 604 files of the same kind of thing: for every diacritic mark of the mus'haf, a rectangle on our page frame, at the place and size the app draws it. It shipped undeclared for the same reason the word rectangles did — nothing read the folder until gate:notices did — and this is the row it asked for.

Each rectangle was measured from the KFGQPC hafs ligature drawing (hafs-kfqc in SOURCES.md): the placement search reads the print's own mark ink and records where the mark sits, four numbers to a mark. No byte of that artwork ships — a mark shard carries page numbers, indices and offsets, nothing that could redraw a glyph, and gate:scripture and gate:notext hold that line independently. The Complex's grant behind that print reserves commercial printing and leaves digital use — websites, software — free, obliging no attribution; Hifth prints nothing. The 892 marks the reader placed by hand are ours outright. So the tree inherits nothing that has to travel with it, and the colophon's credit to the Complex is the same courtesy the word row's is, not a condition.

Why the letter lines are ours too

apps/web/public/assets/letters/** says, for each word, where one letter ends and the next begins: a few dividing lines across the word, found in the ink of the same KFGQPC hafs ligature print the mark rectangles were measured from. To know how many letters to look for, the build reads the word's spelling from the Quranic Arabic Corpus; that spelling is used and dropped, and no letter of it ships, nor any byte of the print. What ships is lines on our page frame. So the tree carries the same terms as the marks: ours, with the Complex credited as a courtesy.

The manifest's one open question

apps/web/public/assets/manifest.json is ours, and it ships one thing that is under a question: the complete table of which page each of the 6,236 ayahs falls on, byte-identical to the vendored copy the pipeline reads. That is the same table, and the same question, as the "what this does not yet settle" note above — whether a page table is expression that carries its source's terms forward, or a fact about a printing. It reaches three shipped outputs, not one: the adjacency shards, every root-shard occurrence, and this file. The question is tracked with all three attached to it rather than answered here, for the reason given above: guessing either way misinforms every reader who opens the colophon.

The deploy trigger

Publishing the site is distribution. A static app hands the browser real copies of assets/roots/**; that is conveying under the GPL, not merely operating a service, and §13's network provision does not cover it. So from the first public deploy onward the corresponding source has to be reachable by anyone who loads the page.

Practically: do not publish the site while this repository is private. Either open the repository, or publish the ETL script and its pinned input alongside the deployment.

That trigger has since fired, and it is discharged. The site is published and the repository is public, so the corresponding source is reachable by anyone who loads the page: build-roots.mjs and build-adjacency.mjs are in it, along with the pinned quranic-corpus-morphology-0.4.txt both derive from. The app also offers the source explicitly rather than leaving a reader to find it — SOURCE_REPO in apps/web/src/provenance.ts, pinned to the commit the bundle was built from, and scripts/check-source-offer.mjs follows the link so a moved repository fails a check instead of quietly breaking the offer.

This paragraph said the opposite for a while after it stopped being true, which is the failure worth naming rather than just correcting: an obligation that triggers on an event — a first public deploy — is described in a file nobody edits on the day the event happens. If the repository is ever taken private again, or the site is ever served from somewhere that does not carry the source, this is the paragraph that has to change back.

What we do not license

The mushaf page artwork (assets/pages/**) is KFGQPC's, distributed under the Complex's own terms. Nothing in LICENSE grants rights to it.

It is not unmodified, which this paragraph used to claim. Three transforms are applied and each is declared, reproducible and asserted on every build — the artwork is minified at a fixed coordinate precision, and a short list of malformed shapes and identifiers is repaired. SOURCES.md names all three and says how many of each there are; the pipeline's own header is the authority on what they do. Nothing is hand-edited, which is the promise that was actually being made. The same holds for every vendored input under packages/etl/data/. When in doubt, the per-source entry in SOURCES.md governs — not this file, and not LICENSE.