@r0kshan/cairn 1.0.0-RC13 → 1.0.0-RC14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,7 @@ Cairn is an [Elkjs (Eclipse Layout Kernel)](https://github.com/kieler/elkjs) bas
17
17
  - [Preview](#preview)
18
18
  - [Installation](#installation)
19
19
  - [Commands](#commands)
20
+ - [License](#license)
20
21
  - [More](#more)
21
22
 
22
23
  ## Why cairn?
@@ -83,26 +84,24 @@ Every image below is rendered by cairn CLI from a `.cairn` source in [`examples/
83
84
  <p align="center"><img src="examples/application-medium.svg" alt="Medium application view" width="760"></p>
84
85
  <p align="center"><img src="examples/application-large.svg" alt="Large application view" width="760"></p>
85
86
 
86
- #### System boundaries
87
-
88
- `system` is a C4 system boundary: it groups the applications, queues and
89
- datastores that belong to one system — the small example above uses one. The
90
- flow matrix names an endpoint's nearest container, so a module reads
91
- `Name (App)` and a queue sitting directly in the system reads `Name (System)`.
92
- From [`examples/application-system.cairn`](examples/application-system.cairn):
87
+ #### Technology logos
93
88
 
94
89
  ```cairn
95
- system ORDERS "Order platform" {
96
- application ORDER_APP "Order management" {
97
- module CAPTURE "Order\ncapture"
98
- module VALIDATE "Order\nvalidation"
99
- }
100
- queue EVENTS "Order event\nbus"
101
- datastore ORDER_DB "Order\nrepository"
90
+ application STOREFRONT "Storefront" { logo: nextdotjs
91
+ module WEB "Web client" { logo: react }
102
92
  }
93
+ queue EVENTS "Order events" { logo: apachekafka }
94
+ datastore ORDER_DB "Order store" { logo: postgresql }
95
+ module BILLING "Billing" { logo: "./logos/acme.svg" }
103
96
  ```
104
97
 
105
- <p align="center"><img src="examples/application-system.svg" alt="Application view with a system boundary" width="760"></p>
98
+ <p align="center"><img src="examples/application-tech-stack.svg" alt="Application view with technology logos" width="760"></p>
99
+
100
+ Six of the 37 built-in logos keep their own licence rather than simple-icons'
101
+ CC0-1.0. A diagram that draws one embeds that artwork, so the SVG carries an
102
+ attribution comment naming the mark, its source and its licence — keep it in
103
+ the file, and check that an SVG optimiser is not set to strip comments. The
104
+ other 31 add nothing. See [THIRD-PARTY-NOTICES.md](./THIRD-PARTY-NOTICES.md).
106
105
 
107
106
  ### Infrastructure view diagram examples from small to large
108
107
 
@@ -192,10 +191,6 @@ actor-group STAFF "Payment actors" {
192
191
  }
193
192
  ```
194
193
 
195
- Values need not be contiguous, and the hint never moves an element into another
196
- band. Where a declared order contradicts a flow, the order wins and the flow is
197
- drawn running backwards.
198
-
199
194
  <p align="center"><img src="examples/positioning.svg" alt="Element ordering, pinned sides and arrow glyphs" width="760"></p>
200
195
 
201
196
  More examples: [`examples/placement/`](examples/placement/) shows one shape four
@@ -259,6 +254,31 @@ Cairn comes with a collection of built-in themes. Choose the one that best fits
259
254
  </tr>
260
255
  </table>
261
256
 
257
+ Pick one from the command line with `--theme`, without editing the diagram:
258
+
259
+ ```sh
260
+ cairn build my-system.cairn --theme nord
261
+ cairn themes # list the built-in names
262
+ ```
263
+
264
+ #### Your own colours
265
+
266
+ `--theme` also takes a JSON file. It **extends a built-in and overrides only
267
+ what it names**, so a usable theme is a few lines rather than fifty colours:
268
+
269
+ ```json
270
+ {
271
+ "extends": "dark",
272
+ "dark": true,
273
+ "pal": { "bg": "#0d1117", "nStroke": "#58a6ff" },
274
+ "accentColors": { "blue": "#58a6ff", "blueF": "#0d2136" }
275
+ }
276
+ ```
277
+
278
+ ```sh
279
+ cairn build my-system.cairn --theme ./my-theme.json
280
+ ```
281
+
262
282
  ## Installation
263
283
 
264
284
  Prebuilt, self-contained binaries are published on every `v*` tag (no runtime needed). Pick your platform:
@@ -316,6 +336,7 @@ help: move this `block` inside a `layer`, `system` or `external`
316
336
 
317
337
  ```sh
318
338
  cairn build my-system.cairn -o my-system.svg # -o optional; defaults to the same name, .svg
339
+ cairn build my-system.cairn --theme nord # or --theme ./my-theme.json
319
340
  ```
320
341
 
321
342
  On validation errors nothing is written and the exit code is 1; warnings are printed but do not block.
@@ -336,6 +357,21 @@ cairn watch my-system.cairn
336
357
 
337
358
  Rebuilds the SVG on save. On a compile error the SVG becomes an error panel (codes, lines, help), so an open preview never shows a stale diagram. Watch observes only the file it was launched on — run one per file. Pair it with an editor that auto-refreshes an open SVG.
338
359
 
360
+ ### List the built-in logos
361
+
362
+ ```sh
363
+ cairn logos
364
+ ```
365
+
366
+ ```text
367
+ 37 built-in logos — use as `logo: <name>` on an element:
368
+
369
+ angular apache apachekafka apachespark django
370
+ ...
371
+ ```
372
+
373
+ Anything else: point at a file — `logo: "./logos/name.svg"`.
374
+
339
375
  ### Explain a diagnostic
340
376
 
341
377
  ```sh
@@ -347,13 +383,42 @@ E0240 — The infrastructure view requires every flow to carry its protocol (and
347
383
  relevant): the flow matrix is the primary output of this view. Add `(HTTPS/443)` after the label.
348
384
  ```
349
385
 
350
- ### Check your version
386
+ ### Check your version, and what it contains
351
387
 
352
388
  ```sh
353
389
  cairn version # or --version / -v
390
+ cairn version --licenses
354
391
  ```
355
392
 
356
- Released binaries (the ones from Homebrew, Scoop, or the GitHub Releases page) print the exact tag they were built from. Running from a clone via `npm run cairn` prints `package.json`'s version instead.
393
+ Released binaries (the ones from Homebrew, Scoop, or the GitHub Releases page) print the exact tag they were built from. Running from a clone via `npm run cairn` prints `package.json`'s version instead. The bare form prints one line and nothing else, so it stays safe to parse in a script.
394
+
395
+ `--licenses` adds the third-party notices for that exact build — elkjs under EPL-2.0, the Simple Icons artwork, and, for the released binaries only, the embedded Bun runtime and its LGPL-2.1 JavaScriptCore. It reads from inside the artifact, so it describes the copy you are running rather than whatever the repository says today.
396
+
397
+ That output is a convenience, not the licence itself. The full texts are installed with cairn: `share/doc/cairn/` for the curl installer and Homebrew, the app directory for Scoop, the package root for npm. [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md) is the long form, with per-icon attribution and the LGPL relink offer.
398
+
399
+ ## License
400
+
401
+ cairn is [Apache-2.0](LICENSE). Its shipped artifacts also *contain* third-party code Apache-2.0 does not cover: elkjs (EPL-2.0) inlined into every bundle and binary, a curated set of Simple Icons paths vendored into the logos, and — in the release binaries only — the Bun runtime, which statically links JavaScriptCore under the LGPL.
402
+
403
+ Full texts live in [`licenses/`](licenses/), their provenance in [`licenses/README.md`](licenses/README.md), and the long form in [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md).
404
+
405
+ ### What that means for you
406
+
407
+ Find your row. Most people are in the first one, and owe nothing.
408
+
409
+ | What you are doing | What you owe |
410
+ |---|---|
411
+ | **Sharing a diagram** | Nothing — unless it draws one of the six licensed logos below, and then cairn has already written the attribution into the SVG. Leave the comment in place. |
412
+ | **Depending on `@r0kshan/cairn`** from npm | Nothing. You distribute no copy of cairn; `npm install` fetches it with its notices intact. |
413
+ | **Bundling cairn** into your own artifact (webpack, Docker, Electron, single-file CLI) | Copy `LICENSE`, `THIRD-PARTY-NOTICES.md` and `licenses/` out of the installed package into your distribution. |
414
+ | **Redistributing a cairn binary** | The same three files — and every installer has already put them on disk beside it (`share/doc/cairn`, the app directory, or the package root, by channel). |
415
+
416
+ **Two things worth knowing:**
417
+
418
+ - **6 of the 37 built-in logos** — `angular`, `apache`, `apachekafka`, `apachespark`, `javascript`, `openjdk` — keep their own licence instead of the project-wide CC0-1.0. The other 31 ask for nothing.
419
+ - **Converting a diagram to PNG, or pasting it into a slide deck, drops the attribution comment.** The artwork is still there, so the attribution has to go somewhere you control: a caption, a credits slide, or `licenses/` shipped alongside. This is the one case cairn cannot handle for you.
420
+
421
+ Diagrams you produce are yours — cairn claims nothing in them. The brands drawn by the built-in logos remain their owners' trademarks.
357
422
 
358
423
  ## More
359
424
 
@@ -362,3 +427,4 @@ Released binaries (the ones from Homebrew, Scoop, or the GitHub Releases page) p
362
427
  - [`ARCHITECTURE.md`](documentation/ARCHITECTURE.md) — how the pipeline fits together, for contributors.
363
428
  - [`CONTRIBUTING.md`](CONTRIBUTING.md) — how to open a PR, and the gates it must pass.
364
429
  - [`documentation/`](documentation/) — architecture, invariants, DSL and internals.
430
+ - [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md) — third-party licence notices, with per-icon attribution.
@@ -4,8 +4,154 @@ cairn is Apache-2.0 (`LICENSE`). Its shipped artifacts — the npm tarball's
4
4
  `bin/cairn.mjs`, the release binaries, the playground bundles — additionally
5
5
  *contain* third-party code, so this notice travels with them.
6
6
 
7
- Build-only tools (esbuild, Bun, biome, typescript) are not listed: nothing of
8
- theirs is distributed.
7
+ Build-only tools (esbuild, biome, typescript) are not listed: nothing of theirs
8
+ is distributed. Bun is a different case — `bun build --compile` embeds its
9
+ runtime in every release binary — and has its own section below.
10
+
11
+ Where each artifact carries this notice:
12
+
13
+ | Artifact | How the notices travel |
14
+ |---|---|
15
+ | npm tarball | `files` ships `LICENSE`, this file and `licenses/`; both bundles also carry a `/*!` banner naming what they inline |
16
+ | release binaries | the texts ship as a `cairn-<version>-licenses.tar.gz` release asset, unpacked into `share/doc/cairn` by `packaging/install.sh`, into the formula's `doc` by the Homebrew tap, and into the app directory by the Scoop manifest — that is what carries the licences. `install.sh` is fail-closed in its own code: it verifies the bundle against the release checksums and installs nothing at all, binary included, if it cannot. Homebrew and Scoop are given the same checksums by `scripts/render-packaging.mjs` and abort on a mismatch through their own resource verification rather than through anything cairn does. `cairn version --licenses` additionally prints the short notice from inside the binary, so a copy separated from its directory still says what it contains |
17
+ | playground | `LICENSE`, this file and `licenses/` are served from the deployed site beside the bundle and linked from the page header; the bundle carries the same banner |
18
+
19
+ ## What this means for you
20
+
21
+ The rest of this file records what cairn owes and to whom. This section is the
22
+ other direction: what, if anything, *you* take on. It is a plain reading of the
23
+ licence texts in `licenses/`, not legal advice, and the summary below is not a
24
+ substitute for the terms themselves.
25
+
26
+ Three situations, in increasing order of what they ask of you.
27
+
28
+ ### You generate diagrams with cairn
29
+
30
+ Nothing. Using a tool is not redistributing it, and every obligation in this
31
+ file attaches to distributing copies. cairn claims nothing in the diagrams you
32
+ produce.
33
+
34
+ One thing worth knowing, because it is the only case where a third party's
35
+ terms reach your output: **a rendered SVG embeds the icon artwork it draws.**
36
+ 31 of the 37 built-in logos are CC0-1.0, which waives copyright and asks for
37
+ nothing. Six carry their own terms and ask for attribution:
38
+
39
+ | Logo | Licence |
40
+ |---|---|
41
+ | `angular` | CC-BY-4.0 |
42
+ | `apache`, `apachekafka`, `apachespark` | Apache-2.0 |
43
+ | `javascript` | MIT |
44
+ | `openjdk` | BSD-3-Clause |
45
+
46
+ A diagram that uses none of those six carries no third-party artwork with
47
+ conditions attached, and cairn writes nothing extra into it. One that does is a
48
+ redistribution of that artwork, so the SVG carries its own attribution: an XML
49
+ comment after the opening `<svg>` tag naming each licensed mark it drew, the
50
+ artwork's source, the rights-holder's copyright line where one is published,
51
+ and a URL for the licence text. Only the marks actually painted are named.
52
+
53
+ That comment also records that the artwork is **modified**, because it is:
54
+ simple-icons redrew each brand mark as a single monochrome path before cairn
55
+ vendored it, and cairn paints that path in the node's colour rather than the
56
+ mark's own. CC-BY-4.0 §3(a)(1)(B) asks that a modification be indicated and
57
+ previous ones retained; Apache-2.0 §4(b) asks that a changed file say so.
58
+
59
+ **Keep that comment in the file.** It is the attribution those four licences
60
+ ask for, and an exported SVG travels without the `licenses/` directory that
61
+ discharges this everywhere else. An optimiser set to strip comments — `svgo`
62
+ does by default — removes the only notice the diagram carries. The per-icon
63
+ table further down this file says the same thing at more length, for anyone
64
+ who has the repository rather than a lone SVG.
65
+
66
+ **When the diagram stops being an SVG, the comment stops travelling.** Pasted
67
+ into a slide deck, a wiki page or a PDF, or converted to PNG, it is gone — and
68
+ that is how most diagrams reach an audience. The artwork is still there, so the
69
+ attribution still has to be somewhere: a credits slide, a caption, a colophon,
70
+ or `licenses/` shipped alongside. The per-icon table further down this file is
71
+ the text to copy; `cairn version --licenses` prints a shorter pointer to it.
72
+ This is the one case cairn cannot do for you, because nothing of cairn's is
73
+ left in the artifact by then.
74
+
75
+ One limit worth stating: Apache-2.0 §4(a) asks that recipients be given "a copy
76
+ of the License", and a comment of that size in every diagram is not practical,
77
+ so the SVG links the text rather than embedding it. CC-BY-4.0 §3(a)(3) permits
78
+ a link outright; MIT and BSD-3-Clause get the holder's copyright line inline
79
+ where one exists. If you need a diagram to carry the texts themselves, ship
80
+ `licenses/` beside it.
81
+
82
+ Separately from copyright: the brands these logos depict are their owners'
83
+ trademarks. Drawing one in a diagram is not an endorsement, and cairn grants no
84
+ rights in the marks themselves.
85
+
86
+ ### You use cairn as an npm package
87
+
88
+ Two quite different cases, and which one you are in depends on how your own
89
+ thing is distributed.
90
+
91
+ **cairn as a dependency.** Your package declares `@r0kshan/cairn` in
92
+ `dependencies` and your users' `npm install` fetches it from the registry, with
93
+ `LICENSE`, this file and `licenses/` intact in `node_modules`. You are
94
+ distributing no copies of cairn, so nothing here attaches to you. Just don't
95
+ strip those files out of what you publish.
96
+
97
+ **cairn bundled into your artifact** — a webpack/rollup/esbuild bundle, a
98
+ Docker image, an Electron app, a single-file CLI. Now cairn's code, and the
99
+ elkjs inside it, are part of what you hand someone. You take on cairn's
100
+ Apache-2.0 (`LICENSE`), elkjs' EPL-2.0 (§3.2(b) wants a copy of the Agreement
101
+ with each copy of the program), and the per-icon attribution. In practice that
102
+ is copying `LICENSE`, this file and `licenses/` out of the installed package
103
+ into your own distribution.
104
+
105
+ `bin/cairn.mjs` and `dist/cairn.mjs` each begin with a `/*!` banner naming what
106
+ they contain, and most minifiers preserve `/*!` by default. **Check your
107
+ bundler's comment settings**: one configured to strip all comments removes the
108
+ only notice the code itself carries.
109
+
110
+ Note that the icon artwork is in the bundle whether or not you ever use a
111
+ `logo:` — the table is not tree-shaken. So for redistribution the six licensed
112
+ icons above apply regardless; it is only your *output* that depends on which
113
+ logos you actually draw.
114
+
115
+ **EPL-2.0 does not reach your code.** Its copyleft covers modifications to the
116
+ EPL'd work; cairn does not modify elkjs, and bundling is not modification. Your
117
+ own code stays under whatever licence you choose. This is why cairn elects
118
+ EPL-2.0 from elkjs' dual offer rather than GPL-3.0-or-later.
119
+
120
+ ### You redistribute cairn itself
121
+
122
+ Republishing the binaries, mirroring the release assets, or shipping a cairn
123
+ executable inside something else. This is the heavy case, and it is what most
124
+ of this file exists for: the binaries additionally embed the Bun runtime, which
125
+ statically links JavaScriptCore under the LGPL in part, along with everything
126
+ else in `licenses/bun-LICENSE.md`.
127
+
128
+ The short version is that the licence texts have to travel with the binary.
129
+ Every installer cairn publishes already puts them on disk for you, but not next
130
+ to the executable: the curl installer unpacks them into `share/doc/cairn`
131
+ beside the `bin/` it installs into, Homebrew stages them into the formula's
132
+ `doc` directory, and Scoop unpacks them into the app directory. Copying just
133
+ the binary out of an install therefore leaves the notices behind — take those
134
+ files with it.
135
+
136
+ If you are building your own, this is what has to travel with it:
137
+
138
+ | What | Where it is | Why |
139
+ |---|---|---|
140
+ | `LICENSE` | repo root | cairn's own Apache-2.0, §4(a) |
141
+ | `THIRD-PARTY-NOTICES.md` | repo root | this file — the per-icon attribution and the §6 offer |
142
+ | `licenses/elkjs-EPL-2.0.md` | `licenses/` | EPL-2.0 §3.2(b), a copy with each copy |
143
+ | `licenses/simple-icons-CC0-1.0.md` and the four icon texts | `licenses/` | the six marks that carry their own terms |
144
+ | `licenses/bun-LICENSE.md` and `licenses/LGPL-2.1.txt` | `licenses/` | the runtime the binary embeds |
145
+
146
+ Shipping the whole `licenses/` directory plus those two root files is the
147
+ simplest way to get all of it, and is what every installer above does.
148
+
149
+ Two things a copied directory does not give you. The LGPL-2.1 §6 offer names a
150
+ specific WebKit revision, a specific cairn tag and a specific build script — if
151
+ you build against a different Bun, that offer is wrong and you must restate it
152
+ for what you actually linked. And `cairn version --licenses` prints from inside
153
+ the binary, so a build of your own prints your build's notice, not this one.
154
+ Read the Bun and JavaScriptCore sections below before you ship.
9
155
 
10
156
  ## elkjs
11
157
 
@@ -17,8 +163,9 @@ copy of elkjs' own `LICENSE.md`, upstream at https://www.eclipse.org/legal/epl-2
17
163
 
18
164
  That copy is vendored rather than referenced because elkjs is a *devDependency*:
19
165
  the published package installs zero dependencies, so `node_modules/elkjs/` never
20
- reaches a consumer while the inlined code does. EPL-2.0 §3.1(b) requires the
21
- license to travel with the distributed form, so `files` ships it in the tarball.
166
+ reaches a consumer while the inlined code does. The inlined form is source
167
+ code, so EPL-2.0 §3.2(b) requires a copy of the Agreement with each copy of it,
168
+ and `files` ships that copy in the tarball.
22
169
 
23
170
  Per EPL-2.0 §3.1(a): the source code for elkjs is available under the EPL-2.0,
24
171
  and can be obtained from https://github.com/kieler/elkjs or from the published
@@ -29,9 +176,166 @@ ties it back to.
29
176
  cairn asserts no ownership over elkjs and does not relicense it. Apache-2.0
30
177
  covers cairn's own code only.
31
178
 
179
+ ## Bun
180
+
181
+ The release binaries are built with `bun build --compile`
182
+ (`scripts/build-binaries.sh`), which packages cairn's code **together with the
183
+ Bun runtime** into one executable. So unlike esbuild, biome and typescript, Bun
184
+ is not merely a build tool here: part of it is distributed in every binary
185
+ cairn publishes. The npm bundles and the playground are built with esbuild and
186
+ carry none of it, and `cairn version --licenses` says so per artifact — the binaries
187
+ print the Bun paragraph, the npm CLI does not.
188
+
189
+ **Version 1.4.0.** The release workflow pins `bun-version`
190
+ (`.github/workflows/release.yml`) rather than tracking `latest`, because a
191
+ notice that cannot name the runtime it shipped is not a notice. The same pin is
192
+ recorded in `src/notice.ts` as `BUN_VERSION`.
193
+
194
+ Bun itself is MIT. Its runtime statically links a long list of further
195
+ components with their own terms. Bun's own `LICENSE.md` is the authoritative
196
+ enumeration of them, and it is reproduced verbatim at
197
+ [`licenses/bun-LICENSE.md`](./licenses/bun-LICENSE.md) — fetched from the
198
+ `bun-v1.4.0` tag, so it enumerates the runtime cairn actually embeds rather
199
+ than whatever upstream `main` says today. That file, not this section, is the
200
+ notice for everything Bun links; it is shipped with every binary.
201
+
202
+ ### JavaScriptCore and the LGPL
203
+
204
+ The component that carries real obligations is JavaScriptCore, from WebKit,
205
+ which Bun links statically and which is under the GNU Lesser (originally
206
+ Library) General Public License for part of its source. Which version takes a
207
+ sentence to state, because the sources disagree in wording rather than in
208
+ substance: Bun's `LICENSE.md` labels it `LGPL-2`, while WebKit's own file
209
+ headers offer "version 2 of the License, or (at your option) any later
210
+ version". cairn takes that offer at **2.1** — that is the text shipped at
211
+ [`licenses/LGPL-2.1.txt`](./licenses/LGPL-2.1.txt), and the §6 offer below is
212
+ written against it. tinycc, also in Bun's list, is LGPL v2.1 outright.
213
+
214
+ LGPL-2.1 §6 permits distributing a work that statically links the library
215
+ provided the recipient can modify the library and relink. cairn discharges that
216
+ as follows, and everything named here is published:
217
+
218
+ - **The library's source.** JavaScriptCore as Bun links it is at
219
+ <https://github.com/oven-sh/webkit>, at revision
220
+ `0f966e81b78c84bb23213e391bc679c4ef83e56b` — the `WEBKIT_VERSION` pinned in
221
+ `scripts/build/deps/webkit.ts` at Bun's `bun-v1.4.0` tag, which is the Bun
222
+ the release workflow is pinned to. Naming the revision rather than the
223
+ repository is the point: "the version Bun happens to use" is not something a
224
+ recipient can check, and a relink has to start from the same source the
225
+ binary was built against. Bun's `LICENSE.md` gives the relink procedure
226
+ verbatim, and it is reproduced at `licenses/bun-LICENSE.md`.
227
+ - **cairn's own source, which is the rest of the work.** Apache-2.0, at
228
+ <https://github.com/R0kshan/cairn>, at the tag the binary was built from —
229
+ `cairn version` prints that tag, and the release carries a build-provenance
230
+ attestation tying the binary to that commit.
231
+ - **The build that combines them.** `scripts/build-binaries.sh`, in the same
232
+ repository, is the whole of it: one `bun build --compile` invocation against
233
+ a pinned Bun. Anyone who relinks a modified JavaScriptCore into Bun by
234
+ upstream's procedure can rerun that script and obtain an equivalent cairn
235
+ binary.
236
+
237
+ Requests for anything in this list that you cannot obtain from those URLs
238
+ should be opened as an issue on the cairn repository.
239
+
240
+ > **This is a good-faith implementation, not a legal opinion.** Static linking
241
+ > of LGPL-2.1 code is an area where reasonable lawyers differ, particularly on
242
+ > whether an offer of source-plus-build-script is equivalent to the "object
243
+ > format" §6 speaks of. The facts above are accurate and the materials are
244
+ > genuinely published; whether they are sufficient for a given jurisdiction or
245
+ > distribution is a question for counsel. If you need certainty without that
246
+ > question, the npm and playground artifacts contain no Bun and no LGPL code at
247
+ > all.
248
+
249
+ ## simple-icons
250
+
251
+ Version 16.29.0, CC0-1.0. Upstream: https://github.com/simple-icons/simple-icons
252
+
253
+ cairn's shipped artifacts and runtime do not depend on simple-icons; only
254
+ regenerating the logos does. A curated
255
+ subset of its icon *paths* — the ones behind `logo: <name>` — is vendored into
256
+ `src/logos.ts` by `scripts/update-logos.mjs`, which fetches the pinned version
257
+ with `npm pack` and writes the paths out as source. The full license text is in
258
+ [`licenses/simple-icons-CC0-1.0.md`](./licenses/simple-icons-CC0-1.0.md), a
259
+ verbatim copy of the project's own `LICENSE.md` at that version.
260
+
261
+ That version stamp is deliberate. The file records which licence governed the
262
+ paths cairn actually ships, so it is a historical fact rather than a mirror of
263
+ upstream: a later relicence there cannot make it wrong, and cannot oblige a
264
+ cairn release. CC0 is irrevocable, so paths vendored under it stay CC0 whatever
265
+ simple-icons does next.
266
+
267
+ **The project licence is not the whole story.** Simple Icons' `DISCLAIMER.md`
268
+ says individual icons may carry their own terms, and some of the ones cairn
269
+ vendors do. `scripts/update-logos.mjs` reads each icon's declared licence and
270
+ refuses anything cairn cannot pass on under its own Apache-2.0 — so such an icon
271
+ cannot reach `src/logos.ts` even if someone adds it to the curated list. The
272
+ reasons differ by licence, and are set out with the table below.
273
+
274
+ <!-- generated by scripts/update-logos.mjs — do not edit by hand -->
275
+
276
+ Most of the 37 vendored icons carry no licence of their own and are
277
+ covered by the project-wide CC0-1.0 above. These declare their own, which
278
+ applies to that icon's artwork instead:
279
+
280
+ | Icon | Licence | Full text | Artwork source |
281
+ | --- | --- | --- | --- |
282
+ | Angular (`angular`) | CC-BY-4.0 | [`CC-BY-4.0.txt`](./licenses/CC-BY-4.0.txt) | <https://angular.dev/press-kit> |
283
+ | Apache (`apache`) | Apache-2.0 | [`Apache-2.0.txt`](./licenses/Apache-2.0.txt) | <https://www.apache.org/foundation/press/kit> |
284
+ | Apache Kafka (`apachekafka`) | Apache-2.0 | [`Apache-2.0.txt`](./licenses/Apache-2.0.txt) | <https://apache.org/logos> |
285
+ | Apache Spark (`apachespark`) | Apache-2.0 | [`Apache-2.0.txt`](./licenses/Apache-2.0.txt) | <https://apache.org/logos> |
286
+ | JavaScript (`javascript`) | MIT | [`MIT-javascript-logo.js.txt`](./licenses/MIT-javascript-logo.js.txt) | <https://github.com/voodootikigod/logo.js/blob/1544bdeed6d618a6cfe4f0650d04ab8d9cfa76d9/js.svg> |
287
+ | OpenJDK (`openjdk`) | BSD-3-Clause | [`BSD-3-Clause.txt`](./licenses/BSD-3-Clause.txt) | <https://github.com/openjdk/duke/blob/master/vector/Agent.svg> |
288
+
289
+ Each permits commercial redistribution and asks for attribution, which this
290
+ table and the shipped licence texts are. **Attribution is to the artwork
291
+ source named above.** Where a rights-holder publishes no copyright line at
292
+ that source — as is the case for several of these marks — cairn identifies
293
+ the origin by that URL rather than assert a copyright holder it cannot
294
+ verify. `licenses/BSD-3-Clause.txt` is consequently the SPDX template, with
295
+ the `<year> <owner>` fields as upstream left them; see `licenses/README.md`.
296
+
297
+ Source notes:
298
+
299
+ - **OpenJDK (`openjdk`)** — simple-icons records <https://hg.openjdk.java.net/duke/duke/file/ca00f100dafc/vector/Agent.svg>, and that Mercurial host has been retired — it answers 403. The attribution above therefore names the live GitHub location of the same file, recorded in SOURCE_OVERRIDES rather than silently swapped. Checked 2026-09-04: that repository has no LICENSE file, the GitHub API reports no licence for it, and `vector/Agent.svg` carries no copyright notice of its own. So there is no upstream copyright line to reproduce, which is why `licenses/BSD-3-Clause.txt` keeps the SPDX `<year> <owner>` fields blank and attribution for this mark is to the source URL.
300
+
301
+ Three kinds of terms are refused by the generator instead, and never reach
302
+ `src/logos.ts`, for three different reasons:
303
+
304
+ - **NonCommercial** bars the commercial use cairn's own Apache-2.0 grants
305
+ downstream, so cairn would be promising a right it does not hold.
306
+ - **ShareAlike** does permit commercial use, but requires adaptations to carry
307
+ the same licence — an obligation cairn cannot discharge on behalf of whoever
308
+ embeds the mark in their own diagram.
309
+ - **A trademark policy** in place of a licence is not a copyright grant at all,
310
+ so there is no permission to copy the artwork to rely on.
311
+
312
+ <!-- end generated -->
313
+
314
+ CC0-1.0 waives copyright and imposes no attribution requirement, so for the
315
+ icons it covers this entry is a courtesy rather than an obligation. It is kept
316
+ because the paths reach users inside every shipped artifact, and a reader
317
+ deserves to know where the artwork came from. For the icons in the table above
318
+ it is not a courtesy: MIT, BSD-3-Clause, CC-BY-4.0 and Apache-2.0 each require
319
+ the attribution it carries.
320
+
321
+ **Trademarks are a separate matter from the license.** Simple Icons' own
322
+ `DISCLAIMER.md` is explicit that CC0 covers the project while individual icons
323
+ may carry their own terms, and that brand marks remain the property of their
324
+ owners. cairn redistributes the artwork only; it claims no rights in the brands
325
+ depicted, and using a logo in a diagram does not imply the brand endorses
326
+ anything. Anyone republishing a cairn diagram is responsible for their own use
327
+ of the marks it shows.
328
+
32
329
  ---
33
330
 
34
331
  If the set of inlined dependencies changes, update this file **and** `licenses/`
35
- in the same commit — a notice that names a license text the tarball doesn't carry
36
- is the failure mode this section exists to prevent. `files` in `package.json`
37
- ships both with the npm package.
332
+ **and** `src/notice.ts` in the same commit — a notice that names a license text
333
+ the tarball doesn't carry is the failure mode this section exists to prevent.
334
+ `files` in `package.json` ships them with the npm package.
335
+
336
+ `src/notice.ts` is the single source for the short form: the bundle banners
337
+ (`scripts/notice-banner.sh`) and `cairn version --licenses` both render from it,
338
+ so they cannot drift apart. `tests/notice.test.ts` fails the build if a checked-in
339
+ artifact's banner no longer matches. The long form — full texts, per-icon
340
+ attribution, the LGPL relink offer — is this file, and `licenses/README.md`
341
+ records where each text was fetched from.