@charlescms/astro 0.1.0

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +366 -0
  3. package/SECURITY.md +77 -0
  4. package/THIRD_PARTY_NOTICES.md +56 -0
  5. package/connector/worker.js +505 -0
  6. package/connector/wrangler.toml +15 -0
  7. package/package.json +92 -0
  8. package/scripts/check-licenses.js +45 -0
  9. package/scripts/check-package.js +62 -0
  10. package/scripts/setup.js +719 -0
  11. package/scripts/update-vendored-site.js +71 -0
  12. package/src/admin.astro +314 -0
  13. package/src/analyzer.js +639 -0
  14. package/src/asset-images.js +130 -0
  15. package/src/astro-frontmatter.js +17 -0
  16. package/src/boot.js +35 -0
  17. package/src/client.js +347 -0
  18. package/src/connector-client.js +185 -0
  19. package/src/content-bridge.js +162 -0
  20. package/src/content-panel.js +440 -0
  21. package/src/data-analyzer.js +304 -0
  22. package/src/edit-affordance.js +463 -0
  23. package/src/editor-styles.js +243 -0
  24. package/src/element-editor.js +355 -0
  25. package/src/fields.js +6 -0
  26. package/src/frontmatter.js +153 -0
  27. package/src/ids.js +20 -0
  28. package/src/index.js +681 -0
  29. package/src/js-ast.js +140 -0
  30. package/src/markdown-analyzer.js +95 -0
  31. package/src/media-preview.js +58 -0
  32. package/src/panel-manager.js +133 -0
  33. package/src/publishing.js +457 -0
  34. package/src/rich-text-editor.js +209 -0
  35. package/src/routes.js +21 -0
  36. package/src/runtime-controller.js +206 -0
  37. package/src/sanitize.js +150 -0
  38. package/src/section-editor.js +437 -0
  39. package/src/source-edit.js +310 -0
  40. package/src/source-map-runtime.js +184 -0
  41. package/src/staged-panel.js +145 -0
  42. package/src/toolbar.js +128 -0
  43. package/src/versions-panel.js +112 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright © 2026 Charles CMS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,366 @@
1
+ # @charlescms/astro
2
+
3
+ Static-first visual editing for Astro sites. Free and open source (MIT).
4
+
5
+ > ⚠️ **Early days (0.x).** CharlesCMS is young and under active development — some
6
+ > things may be rough or not work on every site yet. Source edits are byte-verified
7
+ > and conservative by design, but please **test on a branch first** and
8
+ > [report anything that breaks](https://github.com/Charles-CMS/astro/issues).
9
+ > APIs may change before 1.0.
10
+
11
+ ## Quickstart (≈2 minutes)
12
+
13
+ Requires Node.js 22.12 or newer and Astro 6.2.
14
+
15
+ Local preview needs no service account. To publish edits, you only need a GitHub
16
+ repository and a Cloudflare account; the connector is designed to fit within the
17
+ Cloudflare Workers free tier for typical small-site use.
18
+
19
+ ```bash
20
+ npm install @charlescms/astro
21
+ ```
22
+
23
+ Astro 6 currently permits an `esbuild` release affected by June 2026 security
24
+ advisories. Until Astro/Vite require the patched release themselves, pin it in
25
+ the consuming site's root `package.json`, reinstall, and verify with
26
+ `npm audit --omit=dev`:
27
+
28
+ ```json
29
+ {
30
+ "overrides": {
31
+ "esbuild": "^0.28.1"
32
+ }
33
+ }
34
+ ```
35
+
36
+ ```js
37
+ // astro.config.mjs
38
+ import { defineConfig } from "astro/config";
39
+ import charlesCMS from "@charlescms/astro";
40
+
41
+ export default defineConfig({ integrations: [charlesCMS()] });
42
+ ```
43
+
44
+ ```bash
45
+ npm run dev
46
+ ```
47
+
48
+ Open **`/cms`**, then click any text or image on the page to edit it. That's the
49
+ whole setup — no schema, no content models, no config.
50
+
51
+ Edits are a local preview until you connect the connector (below) — then
52
+ **Publish** commits them straight to your Git repo.
53
+
54
+ ## Publish your edits
55
+
56
+ To go live, deploy the connector — a small Cloudflare Worker that commits edits to
57
+ GitHub. One command walks you through it (GitHub repo, where you'll edit, Worker
58
+ name, branch, and an editor password):
59
+
60
+ ```bash
61
+ npx charlescms setup --deploy
62
+ ```
63
+
64
+ Then **connect the site to it once on `/cms`** — paste the connector URL and the
65
+ browser remembers it. No config editing needed.
66
+
67
+ > **Optional:** to skip even that form, bake the connection into `astro.config` so
68
+ > editors land straight on **Start editing**:
69
+ >
70
+ > ```js
71
+ > charlesCMS({
72
+ > connector: "https://<your-worker>.workers.dev",
73
+ > repo: "owner/name",
74
+ > branch: "main",
75
+ > })
76
+ > ```
77
+
78
+ Verify anytime:
79
+
80
+ ```bash
81
+ npx charlescms doctor https://<your-worker>.workers.dev
82
+ ```
83
+
84
+ No Wrangler install needed — `npx` fetches it. Prefer clicking or no CLI? See
85
+ [Manual setup](#manual-setup).
86
+
87
+ ### CLI reference
88
+
89
+ ```bash
90
+ npx charlescms setup [--deploy] [--open] # scaffold the connector (and deploy)
91
+ npx charlescms doctor [connector-url] # check files + a live connector verify
92
+ npx charlescms --help # all commands and options
93
+ npx charlescms --version
94
+ ```
95
+
96
+ `setup` detects your repository's default branch automatically, so edits target
97
+ the right branch (`main`, `master`, …) without you having to pick. `--open` opens
98
+ the GitHub App page for you; `--deploy` also stores the Worker secrets and runs
99
+ `wrangler deploy`.
100
+
101
+ ## Deploy your site
102
+
103
+ **Publish** commits to GitHub, so any host that rebuilds on push works — Cloudflare
104
+ Pages, Netlify, Vercel, GitHub Pages, or your own CI.
105
+
106
+ **Cloudflare keeps it simplest.** The connector already runs on Cloudflare Workers,
107
+ so hosting the site on **Cloudflare Pages** keeps everything on one account and the
108
+ same `wrangler` CLI. Connect the repo in the Cloudflare dashboard — build command
109
+ `npm run build`, output directory `dist` — or push straight from the CLI:
110
+
111
+ ```bash
112
+ npm run build
113
+ npx wrangler pages deploy dist
114
+ ```
115
+
116
+ Each **Publish** commits to GitHub; Pages rebuilds automatically. Edit → Publish →
117
+ live.
118
+
119
+ > The site is a standard static Astro build (`npm run build` → `dist/`), so any
120
+ > static host works — only the connector requires Cloudflare Workers. When you host
121
+ > elsewhere, add that site's URL to the connector's `ALLOWED_ORIGINS`.
122
+
123
+ ## Editor password
124
+
125
+ Protect a public editor with one password — the Worker secret `AUTH_SECRET`.
126
+ Editors enter it once on `/cms`.
127
+
128
+ - **Set / change:** in the assistant, `npx wrangler secret put AUTH_SECRET`, or the
129
+ Cloudflare dashboard (Settings → Variables and Secrets). Takes effect immediately.
130
+ - **Rotate:** replace it with `npx wrangler secret put AUTH_SECRET`.
131
+
132
+ The connector **fails closed**: with no `AUTH_SECRET` set it refuses every edit
133
+ (503), so a misconfigured deploy can never publish openly — always set one. The
134
+ secret is sent as a header over HTTPS and compared in constant time; GitHub
135
+ credentials stay in the Worker (never in the site or `localStorage`).
136
+
137
+ It's a single shared editor identity (no per-user audit; revoke by rotating). For
138
+ teams / per-user auth on higher-value sites, put the Worker behind **Cloudflare
139
+ Access**, or add **GitHub OAuth** in the `authorizeRequest()` hook
140
+ (`connector/worker.js`), plus a Cloudflare rate-limit rule on `/api/*`.
141
+
142
+ ## Add sections (optional)
143
+
144
+ By default the editor changes existing content in place. **Optionally**, let editors
145
+ insert whole new sections between developer-approved children. Mark the wrapper:
146
+
147
+ ```astro
148
+ <main
149
+ data-charlescms-sections
150
+ data-charlescms-section-class="prose section-shell"
151
+ data-charlescms-section-tools="header,paragraph,list,image,quote,delimiter"
152
+ >
153
+ <Hero />
154
+ <Features />
155
+ <Testimonials />
156
+ </main>
157
+ ```
158
+
159
+ That one attribute is the whole decision: sections can be inserted **exactly where
160
+ the developer placed the wrapper**, and nowhere else — pages without it never show
161
+ an insert control. The wrapper's direct children must be static markup (dynamic
162
+ `.map()` children are skipped).
163
+
164
+ - `data-charlescms-section-class` — class(es) every inserted section receives, so
165
+ new sections inherit the site's own spacing and look.
166
+ - `data-charlescms-section-tools` — which blocks editors may use
167
+ (`header,paragraph,list,image,quote,delimiter`).
168
+
169
+ Offer branded templates as static snippets in `src/charlescms/templates/`
170
+ (recommended — you own the markup and classes). Every `.html` or `.astro` file
171
+ there becomes a choice in the picker; the filename is the label
172
+ (`team-quote.html` → “Team Quote”):
173
+
174
+ ```html
175
+ <!-- src/charlescms/templates/newsletter.html -->
176
+ <h2 class="display-lg">Stay in the loop</h2>
177
+ <p>Occasional notes from the studio.</p>
178
+ <a class="button" href="/newsletter">Subscribe</a>
179
+ ```
180
+
181
+ Templates must be pure static markup: files containing scripts, frontmatter,
182
+ `{expressions}` or components are skipped with a dev-server warning (a section is
183
+ inserted verbatim as page content, so nothing dynamic can ride along).
184
+
185
+ **What the editor experiences:**
186
+
187
+ 1. **Add section here** appears before, between, and after the wrapper's sections.
188
+ 2. Clicking it offers your templates; choosing one stages the section as a live
189
+ draft on the page. Clicking the draft offers **Remove section** — nothing
190
+ touches the repository until **Publish**.
191
+ 3. Publish commits the section as sanitized, static Astro source (wrapped in a
192
+ durable `data-charlescms-block`). From then on it is ordinary page content:
193
+ its text and images are edited right on the page, like everything else, and
194
+ the whole section can be removed again at any time.
195
+
196
+ There is deliberately no free-form block builder: editors compose pages from
197
+ sections you designed, and edit content in one consistent way — on the page.
198
+
199
+ ## What it can edit
200
+
201
+ Everything visible is edited by clicking it on the page. **Page info** in the
202
+ toolbar holds the fields that render nowhere visible — the Google/browser-tab
203
+ title, the meta description, and other frontmatter.
204
+
205
+ - **Static text & headings**, and safe inline **rich text** (bold, italic, inline
206
+ code, links, line breaks)
207
+ - **Markdown** frontmatter and body — incl. Astro **Content Collections** (`.md`,
208
+ `.mdx`, and **JSON** `type: 'data'` collections)
209
+ - **Data rendered with `.map()`** — arrays of objects *and* positional tuples
210
+ (`[["Name","Desc","8"], …]`): names, descriptions, prices, list items
211
+ - **Config values** (`site.phone`, address, hours, …) and **component props**
212
+ (hero titles, section eyebrows) — clickable on the page, edited safely at source
213
+ - **Navigation menus** — labels edit; destinations stay locked
214
+ - **Links & downloads** — link text edits; PDFs/files replace in place
215
+ - **Images, video, audio, embeds, iframes** — upload, swap, bounded remove
216
+ - **New sections** (see above) and **versions / undo** via Git commits
217
+
218
+ Rich vs plain is decided by how your site renders a value: where it interprets
219
+ formatting (a Markdown body, `set:html`), you get full rich text; where it prints
220
+ raw text (`{value}`), it stays plain so formatting can never show as literal
221
+ characters. Pure logic — loops, conditions, computed expressions — is never
222
+ editable (that's code, not content); clicking such generated content shows a
223
+ calm "generated by the page, can't be edited here" hint instead of doing nothing.
224
+ Every write is verified against the exact source bytes and refused if the source
225
+ changed, so an edit can't silently corrupt surrounding code. Edited values are
226
+ escaped as content — including the `{`/`}` Astro reads as expressions — so typed
227
+ text stays text and can't be reinterpreted as code; a downstream `astro build`
228
+ remains the final check on any committed file.
229
+
230
+ CharlesCMS scans your source to know what's editable — automatically on save in
231
+ dev, at build time in production (rebuild to pick up new content). It works on any
232
+ Astro site, with or without a layout, alongside React/Svelte/Vue islands (those
233
+ files are never touched).
234
+
235
+ ## Options
236
+
237
+ ```js
238
+ charlesCMS({
239
+ // Connection (optional — bake in for one-click "Start editing"):
240
+ connector: "https://<your-worker>.workers.dev",
241
+ repo: "owner/name",
242
+ branch: "main",
243
+ sourceRoot: "website", // monorepos only
244
+
245
+ editablePaths: ["/demo", "/blog"], // limit where the editor activates
246
+ previewOnly: false, // true = local preview only, no publishing
247
+ adminPath: "/cms", // change the editor route
248
+ })
249
+ ```
250
+
251
+ Monorepos: `sourceRoot` is the app folder holding the Astro project, so
252
+ `src/pages/index.astro` commits as `website/src/pages/index.astro`.
253
+
254
+ ## Manual setup
255
+
256
+ Skip the assistant and set up the Worker by hand:
257
+
258
+ 1. Install + configure as in [Quickstart](#quickstart).
259
+
260
+ 2. Create the Worker:
261
+
262
+ ```bash
263
+ mkdir -p connector
264
+ cp node_modules/@charlescms/astro/connector/worker.js connector/worker.js
265
+ ```
266
+
267
+ ```toml
268
+ # connector/wrangler.toml
269
+ name = "<your-worker>"
270
+ main = "./worker.js"
271
+ compatibility_date = "2026-06-04"
272
+
273
+ [vars]
274
+ ALLOWED_ORIGINS = "https://www.yoursite.com" # comma-separated; add http://localhost:4321 for dev
275
+ ALLOWED_REPOS = "owner/name"
276
+ DEFAULT_BRANCH = "main"
277
+ ```
278
+
279
+ ```bash
280
+ cd connector && npx wrangler login
281
+ ```
282
+
283
+ 3. Store secrets (GitHub App with `contents: write` + `metadata: read`, installed on
284
+ the repo) and the editor password:
285
+
286
+ ```bash
287
+ npx wrangler secret put GITHUB_APP_ID
288
+ npx wrangler secret put GITHUB_PRIVATE_KEY
289
+ npx wrangler secret put AUTH_SECRET # required — the connector refuses to act without it
290
+ ```
291
+
292
+ 4. Deploy and verify:
293
+
294
+ ```bash
295
+ npx wrangler deploy
296
+ npx charlescms doctor https://<your-worker>.workers.dev
297
+ ```
298
+
299
+ ## Troubleshooting
300
+
301
+ `npx charlescms doctor <url>` maps each failure to a fix:
302
+
303
+ | Symptom | Likely cause | Fix |
304
+ | --- | --- | --- |
305
+ | `401` on publish or in `doctor` | Missing/wrong editor password | Use the value matching the Worker's `AUTH_SECRET` (or set it with `wrangler secret put AUTH_SECRET`) |
306
+ | `403` "not allowed" | Origin/repo not allow-listed | Fix `ALLOWED_ORIGINS` / `ALLOWED_REPOS` in `wrangler.toml`, redeploy |
307
+ | `403` from GitHub | App lacks access, or stale Worker | Install/grant the GitHub App, then `wrangler deploy` |
308
+ | `404` | GitHub App not installed on the repo | Install it (doctor prints the exact `github.com/apps/<app>/installations/new` link), or check the repo path |
309
+
310
+ ## How it works & safety
311
+
312
+ The editor ships as static HTML/JS, reads a build-time source map, and stages edits
313
+ as a live preview. Publish sends the exact source span to the Worker, which commits
314
+ to GitHub — credentials stay in the Worker, never in the site or `localStorage`.
315
+ Before each commit the file is re-read and the edit refused if the source changed;
316
+ rich text and section HTML are re-sanitized before the authenticated connector
317
+ writes the complete updated file.
318
+
319
+ ## Checks
320
+
321
+ ```bash
322
+ npm test
323
+ npm run test:coverage
324
+ npm run test:e2e
325
+ npm run build
326
+ ```
327
+
328
+ GitHub Actions runs the coverage and browser suites on Linux plus the packed
329
+ package smoke test on `ubuntu-latest`, `macos-latest`, and `windows-latest`.
330
+ Each job installs the tarball in a clean Astro project, runs the CLI setup,
331
+ builds, starts the dev server, and checks both `/` and `/cms`.
332
+
333
+ ## Runtime structure
334
+
335
+ The browser editor is split by responsibility:
336
+
337
+ - `src/client.js` is the composition root: shared state, module wiring, session
338
+ helpers, and the direct Tiptap imports required for reliable Vite
339
+ `file:` installs.
340
+ - `src/runtime-controller.js`, `src/source-map-runtime.js`, and
341
+ `src/edit-affordance.js` own startup, source-map binding, and click/hover
342
+ behavior.
343
+ - `src/element-editor.js`, `src/rich-text-editor.js`, and
344
+ `src/section-editor.js` own the three editing experiences.
345
+ - `src/publishing.js` owns staging, publishing, uploads, replacements, and
346
+ bounded media removal.
347
+ - `src/content-panel.js` owns the Page info (frontmatter/SEO) and data forms;
348
+ `src/content-bridge.js` maps rendered data to those deterministic forms.
349
+ - `src/panel-manager.js`, `src/toolbar.js`, `src/versions-panel.js`, and
350
+ `src/editor-styles.js` own the surrounding editor UI.
351
+ - `src/analyzer.js` handles Astro markup while `src/data-analyzer.js` handles
352
+ conservative JavaScript/TypeScript/JSON data collections. Both read source
353
+ through `src/js-ast.js`, a small layer over the Babel parser that locates
354
+ string literals at exact offsets (any nesting depth) without evaluating code.
355
+
356
+ All source writes remain byte-verified in the shared source-editing layer; the
357
+ DOM bridge only chooses which deterministic editor to open.
358
+
359
+ ## License
360
+
361
+ CharlesCMS is free and open source under the [MIT License](./LICENSE) — use it
362
+ for anything, including commercial work, no fees and no keys.
363
+ Third-party dependency licences are summarized in
364
+ [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
365
+
366
+ Everything self-hosts on your own Cloudflare and GitHub.
package/SECURITY.md ADDED
@@ -0,0 +1,77 @@
1
+ # Security
2
+
3
+ How CharlesCMS is built to be safe to install on a real site, what it deliberately
4
+ does and does **not** protect, and how to report a problem.
5
+
6
+ ## Reporting a vulnerability
7
+
8
+ Please do **not** open a public issue for security problems. Report them privately
9
+ through [GitHub's private vulnerability reporting form](https://github.com/Charles-CMS/astro/security/advisories/new).
10
+ Enable private vulnerability reporting in the repository settings before the
11
+ first public release.
12
+
13
+ ## Trust model in one paragraph
14
+
15
+ The published site is **100 % static** — none of the editor runs for visitors. The
16
+ editor boots only on the admin route (`/cms` by default) and only does anything once
17
+ an editor authenticates. All writes go through the **connector** (a Cloudflare
18
+ Worker you host), which is the only server-side component and the only thing holding
19
+ credentials.
20
+
21
+ ## Connector — the only component with secrets
22
+
23
+ - **GitHub App installation tokens**, not a personal access token: short-lived
24
+ (~1 h), scoped to the installed repo, cached in memory. The token is never sent to
25
+ the browser and never committed.
26
+ - **Editor auth**: a shared secret `AUTH_SECRET`, sent as the `x-charlescms-auth`
27
+ header and compared in **constant time** (both sides hashed to SHA-256, then a
28
+ branchless XOR) so neither length nor mismatch position leaks. **Fail-closed**:
29
+ with no `AUTH_SECRET` set, every action is refused (503) — a misconfigured deploy
30
+ can never publish openly.
31
+ - **Origin allow-list** and **repo allow-list** — requests from other origins or for
32
+ other repositories are rejected (403). The origin check is browser-facing CSRF
33
+ defense, not the access boundary: browsers always attach an `Origin` a malicious
34
+ site can't forge, but a non-browser client can omit it. Access is gated by
35
+ `AUTH_SECRET` (above) and the repo allow-list, which apply to every request.
36
+ - **Path traversal** is blocked everywhere (no `..`, no absolute paths).
37
+ - Source writes require an existing Git blob SHA and are limited to supported
38
+ files below a `src` directory. New binary files may only be created below
39
+ `public/uploads`; existing public assets require their current SHA.
40
+ - Recommended hardening before selling: a **Cloudflare rate-limit rule on `/api/*`**
41
+ to blunt password guessing; for multiple editors, put the Worker behind
42
+ **Cloudflare Access** and verify the access JWT instead of a single shared secret.
43
+
44
+ ## Source-edit safety and trust boundary
45
+
46
+ - Every edit is applied **byte-exact** against a build-time source map. Before
47
+ writing, the browser re-reads the file through the connector and **refuses** if
48
+ the recorded bytes no longer match (the source drifted).
49
+ - Rich text and Markdown are re-parsed and sanitized in the editor before the
50
+ complete updated source is sent to the connector.
51
+ - The connector restricts repository paths and requires GitHub's current blob SHA,
52
+ so stale writes and writes to workflows or other repository metadata are rejected.
53
+
54
+ The authenticated editor is still a trusted publisher. Anyone who obtains
55
+ `AUTH_SECRET`, or gains script execution in an authenticated editor tab, can submit
56
+ changes to allowed source files. Those files can contain executable Astro or
57
+ JavaScript code. Protect the secret, prevent untrusted scripts on the editor origin,
58
+ keep the GitHub App scoped to dedicated repositories, and use branch protection or
59
+ a review branch for higher-value sites. A downstream `astro build` detects syntax
60
+ errors; it is not a malware sandbox.
61
+
62
+ ## Supply-chain integrity (open, not obfuscated)
63
+
64
+ The package is **open source and shipped readable** — deliberately not
65
+ obfuscated. That lets anyone (or any scanner) audit exactly what runs, which matters
66
+ because the connector has write access to your repo. To prove the published npm
67
+ package is built from this public source and nothing was slipped in, releases are
68
+ published from CI with **[npm provenance](https://docs.npmjs.com/generating-provenance-statements)**
69
+ (`publishConfig.provenance`): a Sigstore-signed attestation linking the tarball to
70
+ the exact commit and build. Look for the **Provenance** badge on the npm page.
71
+
72
+ ## Development-only endpoints
73
+
74
+ In `astro dev` the integration exposes `/_charlescms/mirror-*` endpoints that write
75
+ uploaded media and just-published source back to the **local working tree only**, so
76
+ the dev preview stays in sync. They are restricted to the project directory (no
77
+ traversal, source-file types only) and **do not exist in a production build**.
@@ -0,0 +1,56 @@
1
+ # Third-party software
2
+
3
+ CharlesCMS depends on third-party software. The npm package does not bundle its
4
+ dependencies; npm installs them as separate packages with their own licence files.
5
+ An Astro production build may bundle browser-side portions of these packages.
6
+
7
+ ## Direct runtime dependencies
8
+
9
+ The following direct dependencies are licensed under the MIT License:
10
+
11
+ - `@astrojs/compiler`
12
+ - `@babel/parser`
13
+ - `@tiptap/core`
14
+ - `@tiptap/extension-bold`
15
+ - `@tiptap/extension-code`
16
+ - `@tiptap/extension-document`
17
+ - `@tiptap/extension-hard-break`
18
+ - `@tiptap/extension-italic`
19
+ - `@tiptap/extension-link`
20
+ - `@tiptap/extension-text`
21
+ - `@tiptap/pm`
22
+ - `js-yaml`
23
+ - `mdast-util-from-markdown`
24
+ - `mdast-util-gfm`
25
+ - `mdast-util-to-markdown`
26
+ - `mdast-util-to-string`
27
+ - `micromark-extension-gfm`
28
+ - `parse5`
29
+ - `vite`
30
+
31
+ Astro, the required peer dependency, is also MIT-licensed. Playwright, used only
32
+ for development tests, is Apache-2.0 licensed.
33
+
34
+ ## Transitive audit
35
+
36
+ The release audit found these licence families among installed production and
37
+ peer dependencies:
38
+
39
+ - MIT, ISC, BSD-2-Clause, BSD-3-Clause
40
+ - Apache-2.0, BlueOak-1.0.0
41
+ - CC0-1.0
42
+ - Python-2.0 (`argparse`)
43
+ - LGPL-3.0-or-later (the optional platform-specific `libvips` shared library
44
+ distributed for Sharp)
45
+
46
+ These licences permit commercial use, subject to their notice, attribution,
47
+ patent, source/relinking, and modification obligations. In particular, do not
48
+ statically incorporate or distribute a modified `libvips` build without reviewing
49
+ the LGPL requirements. Sharp's published platform packages use precompiled shared
50
+ libraries and carry their licence information in the installed package.
51
+
52
+ Full licence texts and copyright notices remain in each installed npm package.
53
+ JavaScript legal comments are preserved by esbuild when bundling by default.
54
+
55
+ Run `npm run check:licenses` and `npm sbom --omit=dev --sbom-format cyclonedx`
56
+ for every release. This inventory is a technical compliance aid, not legal advice.