@cosmicdrift/kumiko-headless 0.146.2 → 0.146.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-headless",
|
|
3
|
-
"version": "0.146.
|
|
3
|
+
"version": "0.146.3",
|
|
4
4
|
"description": "Headless UI logic for Kumiko — Dispatcher contract, Form-Controller, View-Model, Nav-Resolver. Plattform- und React-frei; jeder Renderer (renderer, renderer-web, renderer-native, …) komponiert darauf.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-framework": "0.146.
|
|
39
|
+
"@cosmicdrift/kumiko-framework": "0.146.3",
|
|
40
40
|
"zod": "^4.4.3"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { APEX_LIGHTBOX_SCRIPT, APEX_LIGHTBOX_SCRIPT_CSP_HASH } from "../lightbox";
|
|
4
|
+
|
|
5
|
+
function scriptBody(html: string): string {
|
|
6
|
+
const match = html.match(/^<script>(?<body>[\s\S]*)<\/script>$/);
|
|
7
|
+
const body = match?.groups?.["body"];
|
|
8
|
+
if (body === undefined) {
|
|
9
|
+
throw new Error("APEX_LIGHTBOX_SCRIPT isn't a single <script>...</script> string");
|
|
10
|
+
}
|
|
11
|
+
return body;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe("APEX_LIGHTBOX_SCRIPT_CSP_HASH", () => {
|
|
15
|
+
test("matches the actual script content byte-for-byte", () => {
|
|
16
|
+
const body = scriptBody(APEX_LIGHTBOX_SCRIPT);
|
|
17
|
+
const hash = `sha256-${createHash("sha256").update(body).digest("base64")}`;
|
|
18
|
+
expect(hash).toBe(APEX_LIGHTBOX_SCRIPT_CSP_HASH);
|
|
19
|
+
});
|
|
20
|
+
});
|
package/src/apex/lightbox.ts
CHANGED
|
@@ -6,8 +6,10 @@ export const APEX_LIGHTBOX_HTML = `<dialog id="apex-lightbox" class="apex-lightb
|
|
|
6
6
|
<img class="apex-lightbox__img" alt="" />
|
|
7
7
|
</dialog>`;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Split from APEX_LIGHTBOX_SCRIPT so APEX_LIGHTBOX_SCRIPT_CSP_HASH hashes
|
|
10
|
+
// exactly the bytes the browser executes — CSP's script-src hash-source
|
|
11
|
+
// covers the content between <script> and </script>, nothing more/less.
|
|
12
|
+
const APEX_LIGHTBOX_SCRIPT_BODY = `
|
|
11
13
|
(function () {
|
|
12
14
|
var dlg = document.getElementById("apex-lightbox");
|
|
13
15
|
if (!dlg) return;
|
|
@@ -38,4 +40,17 @@ export const APEX_LIGHTBOX_SCRIPT = `<script>
|
|
|
38
40
|
close();
|
|
39
41
|
});
|
|
40
42
|
})();
|
|
41
|
-
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
/** ponytail: one delegated listener; no-op when no .shot-frame on the page. */
|
|
46
|
+
export const APEX_LIGHTBOX_SCRIPT = `<script>${APEX_LIGHTBOX_SCRIPT_BODY}</script>`;
|
|
47
|
+
|
|
48
|
+
// Apps that enforce `script-src 'self'` without `'unsafe-inline'`/nonce (the
|
|
49
|
+
// apex renderer has no per-request nonce hook — its output is often
|
|
50
|
+
// pre-rendered to static HTML at build time, where a nonce can't work
|
|
51
|
+
// anyway) need a hash-source instead. Add this to your CSP's script-src,
|
|
52
|
+
// e.g. `script-src 'self' 'sha256-...'` (value = this constant).
|
|
53
|
+
// lightbox.test.ts asserts this matches APEX_LIGHTBOX_SCRIPT_BODY byte-for-
|
|
54
|
+
// byte, so an edit to the script that doesn't update the hash fails CI
|
|
55
|
+
// instead of silently breaking every strict-CSP consumer's lightbox.
|
|
56
|
+
export const APEX_LIGHTBOX_SCRIPT_CSP_HASH = "sha256-f+hHLpDuQsjmtFZCjdM13D9NaMTCyOKaawAhfLf/X9o=";
|