cursedbelt-server 4.5.0 → 4.6.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.
@@ -15,4 +15,4 @@
15
15
  * and drags no peer.
16
16
  */
17
17
  export { type InjectedScript, foreignScriptSources, scriptsRefusedByCsp, } from "./injectedScripts";
18
- export { WEB_ANALYTICS_BEACON_ORIGIN, WEB_ANALYTICS_BEACON_SRC, WEB_ANALYTICS_SITE_TAG, WEB_ANALYTICS_SITE_TOKEN, WEB_ANALYTICS_TAG, htmlCarriesWebAnalytics, webAnalyticsTag, } from "./webAnalytics";
18
+ export { WEB_ANALYTICS_BEACON_ORIGIN, WEB_ANALYTICS_BEACON_SRC, WEB_ANALYTICS_PUBLIC_HOST, WEB_ANALYTICS_SITE_TAG, WEB_ANALYTICS_SITE_TOKEN, WEB_ANALYTICS_TAG, htmlCarriesWebAnalytics, webAnalyticsBootstrap, webAnalyticsTag, } from "./webAnalytics";
@@ -15,4 +15,4 @@
15
15
  * and drags no peer.
16
16
  */
17
17
  export { foreignScriptSources, scriptsRefusedByCsp, } from "./injectedScripts";
18
- export { WEB_ANALYTICS_BEACON_ORIGIN, WEB_ANALYTICS_BEACON_SRC, WEB_ANALYTICS_SITE_TAG, WEB_ANALYTICS_SITE_TOKEN, WEB_ANALYTICS_TAG, htmlCarriesWebAnalytics, webAnalyticsTag, } from "./webAnalytics";
18
+ export { WEB_ANALYTICS_BEACON_ORIGIN, WEB_ANALYTICS_BEACON_SRC, WEB_ANALYTICS_PUBLIC_HOST, WEB_ANALYTICS_SITE_TAG, WEB_ANALYTICS_SITE_TOKEN, WEB_ANALYTICS_TAG, htmlCarriesWebAnalytics, webAnalyticsBootstrap, webAnalyticsTag, } from "./webAnalytics";
@@ -62,6 +62,43 @@ export declare const WEB_ANALYTICS_SITE_TOKEN = "bd88d63678b64bc89f9702f48846bc8
62
62
  export declare function webAnalyticsTag(token?: string): string;
63
63
  /** The fleet's tag, for the one site this generation serves. */
64
64
  export declare const WEB_ANALYTICS_TAG: string;
65
+ /** The zone. A page served from anywhere else must not load the beacon — see below. */
66
+ export declare const WEB_ANALYTICS_PUBLIC_HOST = "cursedalchemy.com";
67
+ /**
68
+ * What a static shell actually pastes: the tag, behind a HOSTNAME GUARD.
69
+ *
70
+ * ## 🔴 Why the bare snippet cannot go in an `index.html`
71
+ *
72
+ * Measured 2026-09-18, the first time the eight shells carried it. The beacon posts its
73
+ * pageview to `https://cloudflareinsights.com/cdn-cgi/rum`, and Cloudflare answers that
74
+ * preflight with `Access-Control-Allow-Origin: http://127.0.0.1` — no port. So on every LOCAL
75
+ * page load the browser prints:
76
+ *
77
+ * > Access to XMLHttpRequest at 'https://cloudflareinsights.com/cdn-cgi/rum' from origin
78
+ * > 'http://127.0.0.1:57845' has been blocked by CORS policy … Failed to load resource
79
+ *
80
+ * Under Automatic Setup this never happened: the injection is done by the EDGE, so it existed
81
+ * only on the zone and a developer never saw it. Pasting the raw snippet into the source moves
82
+ * it to every `bun run dev` and every browser test — `apps/music` lost 5 route-render checks and
83
+ * `apps/desk` lost 24, both asserting the console is empty, and the owner's own local console
84
+ * would have gained a red line on every page.
85
+ *
86
+ * That is the exact cost he asked to be rid of, one environment over. So the guard: the beacon
87
+ * is appended only when the page is being served from {@link WEB_ANALYTICS_PUBLIC_HOST}, which
88
+ * is the only place it can report anyway.
89
+ *
90
+ * ## Why an inline script rather than a build-time injection
91
+ *
92
+ * A Vite plugin would mean ten `vite.config.ts` edits and a frontend build depending on a
93
+ * server package — and it would not even work: `apps/desk`'s browser suite runs against a
94
+ * production `dist` served from `127.0.0.1`, so a production-only injection is still a console
95
+ * error there. The hostname is the honest discriminator, not the build mode.
96
+ *
97
+ * 🔴 It needs inline script to be permitted on the page. Every shell that carries it already
98
+ * ships one; `apps/vault` does not, serves `script-src 'self'`, and is exempt from the beacon
99
+ * for that reason — see `tools/check-web-analytics.ts`.
100
+ */
101
+ export declare function webAnalyticsBootstrap(token?: string): string;
65
102
  /**
66
103
  * Does `html` carry the beacon for this site?
67
104
  *
@@ -67,6 +67,56 @@ export function webAnalyticsTag(token = WEB_ANALYTICS_SITE_TOKEN) {
67
67
  }
68
68
  /** The fleet's tag, for the one site this generation serves. */
69
69
  export const WEB_ANALYTICS_TAG = webAnalyticsTag();
70
+ /** The zone. A page served from anywhere else must not load the beacon — see below. */
71
+ export const WEB_ANALYTICS_PUBLIC_HOST = "cursedalchemy.com";
72
+ /**
73
+ * What a static shell actually pastes: the tag, behind a HOSTNAME GUARD.
74
+ *
75
+ * ## 🔴 Why the bare snippet cannot go in an `index.html`
76
+ *
77
+ * Measured 2026-09-18, the first time the eight shells carried it. The beacon posts its
78
+ * pageview to `https://cloudflareinsights.com/cdn-cgi/rum`, and Cloudflare answers that
79
+ * preflight with `Access-Control-Allow-Origin: http://127.0.0.1` — no port. So on every LOCAL
80
+ * page load the browser prints:
81
+ *
82
+ * > Access to XMLHttpRequest at 'https://cloudflareinsights.com/cdn-cgi/rum' from origin
83
+ * > 'http://127.0.0.1:57845' has been blocked by CORS policy … Failed to load resource
84
+ *
85
+ * Under Automatic Setup this never happened: the injection is done by the EDGE, so it existed
86
+ * only on the zone and a developer never saw it. Pasting the raw snippet into the source moves
87
+ * it to every `bun run dev` and every browser test — `apps/music` lost 5 route-render checks and
88
+ * `apps/desk` lost 24, both asserting the console is empty, and the owner's own local console
89
+ * would have gained a red line on every page.
90
+ *
91
+ * That is the exact cost he asked to be rid of, one environment over. So the guard: the beacon
92
+ * is appended only when the page is being served from {@link WEB_ANALYTICS_PUBLIC_HOST}, which
93
+ * is the only place it can report anyway.
94
+ *
95
+ * ## Why an inline script rather than a build-time injection
96
+ *
97
+ * A Vite plugin would mean ten `vite.config.ts` edits and a frontend build depending on a
98
+ * server package — and it would not even work: `apps/desk`'s browser suite runs against a
99
+ * production `dist` served from `127.0.0.1`, so a production-only injection is still a console
100
+ * error there. The hostname is the honest discriminator, not the build mode.
101
+ *
102
+ * 🔴 It needs inline script to be permitted on the page. Every shell that carries it already
103
+ * ships one; `apps/vault` does not, serves `script-src 'self'`, and is exempt from the beacon
104
+ * for that reason — see `tools/check-web-analytics.ts`.
105
+ */
106
+ export function webAnalyticsBootstrap(token = WEB_ANALYTICS_SITE_TOKEN) {
107
+ return [
108
+ "<script>",
109
+ `\tvar host = location.hostname;`,
110
+ `\tif (host === "${WEB_ANALYTICS_PUBLIC_HOST}" || host.endsWith(".${WEB_ANALYTICS_PUBLIC_HOST}")) {`,
111
+ `\t\tvar beacon = document.createElement("script");`,
112
+ `\t\tbeacon.type = "module";`,
113
+ `\t\tbeacon.src = "${WEB_ANALYTICS_BEACON_SRC}";`,
114
+ `\t\tbeacon.setAttribute("data-cf-beacon", '{"token": "${token}"}');`,
115
+ `\t\tdocument.head.appendChild(beacon);`,
116
+ "\t}",
117
+ "</script>",
118
+ ].join("\n");
119
+ }
70
120
  /**
71
121
  * Does `html` carry the beacon for this site?
72
122
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt-server",
3
- "version": "4.5.0",
3
+ "version": "4.6.0",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "The app-facing Bun/Hono server tier of the cursedbelt split \u2014 storage, sharing, activity, guard, sync. React-free; cursedbelt-core below it.",
@@ -22,9 +22,11 @@ export {
22
22
  export {
23
23
  WEB_ANALYTICS_BEACON_ORIGIN,
24
24
  WEB_ANALYTICS_BEACON_SRC,
25
+ WEB_ANALYTICS_PUBLIC_HOST,
25
26
  WEB_ANALYTICS_SITE_TAG,
26
27
  WEB_ANALYTICS_SITE_TOKEN,
27
28
  WEB_ANALYTICS_TAG,
28
29
  htmlCarriesWebAnalytics,
30
+ webAnalyticsBootstrap,
29
31
  webAnalyticsTag,
30
32
  } from "./webAnalytics";
@@ -6,6 +6,7 @@ import {
6
6
  WEB_ANALYTICS_SITE_TOKEN,
7
7
  WEB_ANALYTICS_TAG,
8
8
  htmlCarriesWebAnalytics,
9
+ webAnalyticsBootstrap,
9
10
  webAnalyticsTag,
10
11
  } from "./webAnalytics";
11
12
 
@@ -44,7 +45,69 @@ describe("the fleet's beacon", () => {
44
45
  });
45
46
  });
46
47
 
48
+ /**
49
+ * 🔴 The guard is EXECUTED, not read. It is eight lines of hand-written browser JavaScript
50
+ * that nothing else runs before production, and the whole reason it exists is a failure that
51
+ * only shows up at a particular hostname — so a test that merely asserted the string contains
52
+ * "cursedalchemy.com" would pass on a guard with the condition inverted.
53
+ */
54
+ function runBootstrap(hostname: string): { appended: string[]; attrs: Record<string, string> } {
55
+ const body = /<script>([\s\S]*)<\/script>/.exec(webAnalyticsBootstrap())?.[1] ?? "";
56
+ expect(body.trim().length).toBeGreaterThan(0);
57
+ const appended: string[] = [];
58
+ const attrs: Record<string, string> = {};
59
+ const fakeDocument = {
60
+ createElement: () => ({
61
+ type: "",
62
+ src: "",
63
+ setAttribute(name: string, value: string) {
64
+ attrs[name] = value;
65
+ },
66
+ }),
67
+ head: {
68
+ appendChild(el: { src: string }) {
69
+ appended.push(el.src);
70
+ },
71
+ },
72
+ };
73
+ new Function("location", "document", body)({ hostname }, fakeDocument);
74
+ return { appended, attrs };
75
+ }
76
+
77
+ describe("the hostname guard", () => {
78
+ test("appends the beacon on the zone, and on every satellite of it", () => {
79
+ for (const host of ["cursedalchemy.com", "collections.cursedalchemy.com", "vault.cursedalchemy.com"]) {
80
+ const { appended, attrs } = runBootstrap(host);
81
+ expect(appended, `${host} should load the beacon`).toEqual([WEB_ANALYTICS_BEACON_SRC]);
82
+ expect(attrs["data-cf-beacon"]).toBe(`{"token": "${WEB_ANALYTICS_SITE_TOKEN}"}`);
83
+ }
84
+ });
85
+
86
+ /**
87
+ * 🔴 The failure this guard was added for, 2026-09-18. The beacon POSTs to
88
+ * `cloudflareinsights.com/cdn-cgi/rum`, which answers the preflight with
89
+ * `Access-Control-Allow-Origin: http://127.0.0.1` — no port — so a local page load prints a
90
+ * CORS error. `apps/music` lost 5 route-render checks to it and `apps/desk` lost 24, both
91
+ * asserting an empty console, and the owner's own `bun run dev` would have shown it too.
92
+ */
93
+ test("loads NOTHING on localhost, 127.0.0.1 or a bare host", () => {
94
+ for (const host of ["localhost", "127.0.0.1", "::1", "app.test", ""]) {
95
+ expect(runBootstrap(host).appended, `${host} must not load the beacon`).toEqual([]);
96
+ }
97
+ });
98
+
99
+ test("a lookalike domain does not get the beacon either", () => {
100
+ // `endsWith` alone would admit this, which is why the guard tests for the dot.
101
+ expect(runBootstrap("evilcursedalchemy.com").appended).toEqual([]);
102
+ });
103
+ });
104
+
47
105
  describe("htmlCarriesWebAnalytics", () => {
106
+ test("true for the bootstrap block a shell actually pastes", () => {
107
+ expect(htmlCarriesWebAnalytics(webAnalyticsBootstrap())).toBe(true);
108
+ expect(htmlCarriesWebAnalytics(webAnalyticsBootstrap("0".repeat(32)))).toBe(false);
109
+ });
110
+
48
111
  test("true for the tag as authored, and for a re-wrapped copy of it", () => {
49
112
  expect(htmlCarriesWebAnalytics(`<head>${WEB_ANALYTICS_TAG}</head>`)).toBe(true);
50
113
  // A formatter is allowed to break the attributes across lines; the check must survive it.
@@ -76,6 +76,58 @@ export function webAnalyticsTag(token: string = WEB_ANALYTICS_SITE_TOKEN): strin
76
76
  /** The fleet's tag, for the one site this generation serves. */
77
77
  export const WEB_ANALYTICS_TAG = webAnalyticsTag();
78
78
 
79
+ /** The zone. A page served from anywhere else must not load the beacon — see below. */
80
+ export const WEB_ANALYTICS_PUBLIC_HOST = "cursedalchemy.com";
81
+
82
+ /**
83
+ * What a static shell actually pastes: the tag, behind a HOSTNAME GUARD.
84
+ *
85
+ * ## 🔴 Why the bare snippet cannot go in an `index.html`
86
+ *
87
+ * Measured 2026-09-18, the first time the eight shells carried it. The beacon posts its
88
+ * pageview to `https://cloudflareinsights.com/cdn-cgi/rum`, and Cloudflare answers that
89
+ * preflight with `Access-Control-Allow-Origin: http://127.0.0.1` — no port. So on every LOCAL
90
+ * page load the browser prints:
91
+ *
92
+ * > Access to XMLHttpRequest at 'https://cloudflareinsights.com/cdn-cgi/rum' from origin
93
+ * > 'http://127.0.0.1:57845' has been blocked by CORS policy … Failed to load resource
94
+ *
95
+ * Under Automatic Setup this never happened: the injection is done by the EDGE, so it existed
96
+ * only on the zone and a developer never saw it. Pasting the raw snippet into the source moves
97
+ * it to every `bun run dev` and every browser test — `apps/music` lost 5 route-render checks and
98
+ * `apps/desk` lost 24, both asserting the console is empty, and the owner's own local console
99
+ * would have gained a red line on every page.
100
+ *
101
+ * That is the exact cost he asked to be rid of, one environment over. So the guard: the beacon
102
+ * is appended only when the page is being served from {@link WEB_ANALYTICS_PUBLIC_HOST}, which
103
+ * is the only place it can report anyway.
104
+ *
105
+ * ## Why an inline script rather than a build-time injection
106
+ *
107
+ * A Vite plugin would mean ten `vite.config.ts` edits and a frontend build depending on a
108
+ * server package — and it would not even work: `apps/desk`'s browser suite runs against a
109
+ * production `dist` served from `127.0.0.1`, so a production-only injection is still a console
110
+ * error there. The hostname is the honest discriminator, not the build mode.
111
+ *
112
+ * 🔴 It needs inline script to be permitted on the page. Every shell that carries it already
113
+ * ships one; `apps/vault` does not, serves `script-src 'self'`, and is exempt from the beacon
114
+ * for that reason — see `tools/check-web-analytics.ts`.
115
+ */
116
+ export function webAnalyticsBootstrap(token: string = WEB_ANALYTICS_SITE_TOKEN): string {
117
+ return [
118
+ "<script>",
119
+ `\tvar host = location.hostname;`,
120
+ `\tif (host === "${WEB_ANALYTICS_PUBLIC_HOST}" || host.endsWith(".${WEB_ANALYTICS_PUBLIC_HOST}")) {`,
121
+ `\t\tvar beacon = document.createElement("script");`,
122
+ `\t\tbeacon.type = "module";`,
123
+ `\t\tbeacon.src = "${WEB_ANALYTICS_BEACON_SRC}";`,
124
+ `\t\tbeacon.setAttribute("data-cf-beacon", '{"token": "${token}"}');`,
125
+ `\t\tdocument.head.appendChild(beacon);`,
126
+ "\t}",
127
+ "</script>",
128
+ ].join("\n");
129
+ }
130
+
79
131
  /**
80
132
  * Does `html` carry the beacon for this site?
81
133
  *