@polishd/next 0.2.2-dev.0 → 0.2.2-dev.1
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/CHANGELOG.md +30 -0
- package/DATABASE.md +8 -1
- package/README.md +25 -0
- package/dist/client/dom.d.ts +23 -0
- package/dist/client/dom.d.ts.map +1 -0
- package/dist/client/dom.js +71 -0
- package/dist/client/dom.js.map +1 -0
- package/dist/client/init.d.ts.map +1 -1
- package/dist/client/init.js +3 -62
- package/dist/client/init.js.map +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +16 -10
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/telemetry-consent.d.ts +3 -0
- package/dist/dashboard/telemetry-consent.d.ts.map +1 -0
- package/dist/dashboard/telemetry-consent.js +20 -0
- package/dist/dashboard/telemetry-consent.js.map +1 -0
- package/dist/dashboard/telemetry.d.ts +21 -0
- package/dist/dashboard/telemetry.d.ts.map +1 -0
- package/dist/dashboard/telemetry.js +212 -0
- package/dist/dashboard/telemetry.js.map +1 -0
- package/dist/dashboard.css +20 -0
- package/dist/server/ingest.d.ts +20 -0
- package/dist/server/ingest.d.ts.map +1 -1
- package/dist/server/ingest.js +49 -0
- package/dist/server/ingest.js.map +1 -1
- package/dist/server/store.d.ts +6 -2
- package/dist/server/store.d.ts.map +1 -1
- package/dist/server/store.js +34 -13
- package/dist/server/store.js.map +1 -1
- package/dist/server/telemetry.d.ts +28 -0
- package/dist/server/telemetry.d.ts.map +1 -0
- package/dist/server/telemetry.js +83 -0
- package/dist/server/telemetry.js.map +1 -0
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/telemetry.d.ts +43 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +81 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Polishd — the dashboard's own telemetry: emitter + consent prompt.
|
|
5
|
+
*
|
|
6
|
+
* The dashboard is polishd's product surface, and it is exactly the traffic
|
|
7
|
+
* the package refuses to record for its hosts (the dashboard-path drop in
|
|
8
|
+
* ingest). This emitter is the separate, opt-in channel that records it —
|
|
9
|
+
* dashboard interactions only — and reports it to the polishd project's own
|
|
10
|
+
* `@polishd/next/telemetry` endpoint, so the dashboard is improved by the same
|
|
11
|
+
* signals it preaches.
|
|
12
|
+
*
|
|
13
|
+
* Everything about the transport differs from the host-site capture layer
|
|
14
|
+
* because the POST crosses origins:
|
|
15
|
+
*
|
|
16
|
+
* • Identity travels in the body — an anonymous session id minted here (the
|
|
17
|
+
* httpOnly session cookie never leaves its origin) plus the stable
|
|
18
|
+
* anonymous install id the server resolved from `polishd_meta`.
|
|
19
|
+
* • Batches are sent as `text/plain`, which keeps the request inside CORS's
|
|
20
|
+
* "simple" class — no preflight — and is the only shape `sendBeacon` can
|
|
21
|
+
* deliver cross-origin anyway. The receiving route parses the body as
|
|
22
|
+
* JSON regardless of the header.
|
|
23
|
+
* • Paths are namespaced under `/~polishd/<tab>` so the receiving database
|
|
24
|
+
* can never confuse dashboard telemetry with the receiving site's own
|
|
25
|
+
* first-party pages.
|
|
26
|
+
*
|
|
27
|
+
* What is captured: page views (tab switches), clicks (with the same
|
|
28
|
+
* rage/dead classification as the host capture layer, via the shared DOM
|
|
29
|
+
* helpers), one viewport sample per session, and session end. Nothing else —
|
|
30
|
+
* no scroll depth, no errors, no design scans, and never anything from the
|
|
31
|
+
* host site's own pages: capture suspends the moment the URL leaves the
|
|
32
|
+
* dashboard's mount path.
|
|
33
|
+
*/
|
|
34
|
+
import { useRouter } from "next/navigation";
|
|
35
|
+
import { useEffect, useState, useTransition } from "react";
|
|
36
|
+
import { componentOf, deviceCategory, hasTextSelection, isInteractive, labelOf, selectorOf, } from "../client/dom";
|
|
37
|
+
import { denyPolishdTelemetry, grantPolishdTelemetry } from "./telemetry-consent";
|
|
38
|
+
const PATH_PREFIX = "/~polishd";
|
|
39
|
+
const SESSION_KEY = "polishd_telemetry_session";
|
|
40
|
+
const FLUSH_INTERVAL_MS = 15_000;
|
|
41
|
+
const MAX_BATCH = 50;
|
|
42
|
+
const RAGE_COUNT = 3;
|
|
43
|
+
const RAGE_WINDOW_MS = 500;
|
|
44
|
+
/** The telemetry path for the tab currently in the URL. */
|
|
45
|
+
function telemetryPath() {
|
|
46
|
+
const tab = new URLSearchParams(location.search).get("tab");
|
|
47
|
+
return `${PATH_PREFIX}/${tab || "analytics"}`;
|
|
48
|
+
}
|
|
49
|
+
/** A session id that survives soft navigation but not the browser session. */
|
|
50
|
+
function sessionId() {
|
|
51
|
+
try {
|
|
52
|
+
const existing = sessionStorage.getItem(SESSION_KEY);
|
|
53
|
+
if (existing)
|
|
54
|
+
return existing;
|
|
55
|
+
const minted = crypto.randomUUID();
|
|
56
|
+
sessionStorage.setItem(SESSION_KEY, minted);
|
|
57
|
+
return minted;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Storage blocked — a per-page-load id is the honest fallback.
|
|
61
|
+
return crypto.randomUUID();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function start(endpoint, installId) {
|
|
65
|
+
const sid = sessionId();
|
|
66
|
+
// The route the dashboard is mounted at, learned from where we woke up.
|
|
67
|
+
// Capture is suspended whenever the URL wanders off it — the listeners
|
|
68
|
+
// below outlive the dashboard page, and host-site interactions must never
|
|
69
|
+
// leak into telemetry.
|
|
70
|
+
const mountPath = location.pathname;
|
|
71
|
+
const onDashboard = () => location.pathname === mountPath;
|
|
72
|
+
const queue = [];
|
|
73
|
+
let currentPath = telemetryPath();
|
|
74
|
+
const flush = (useBeacon = false) => {
|
|
75
|
+
if (queue.length === 0)
|
|
76
|
+
return;
|
|
77
|
+
const batch = queue.splice(0, queue.length);
|
|
78
|
+
const body = JSON.stringify({ installId, sessionId: sid, events: batch });
|
|
79
|
+
if (useBeacon && navigator.sendBeacon) {
|
|
80
|
+
const ok = navigator.sendBeacon(endpoint, new Blob([body], { type: "text/plain" }));
|
|
81
|
+
if (!ok)
|
|
82
|
+
queue.unshift(...batch);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
fetch(endpoint, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers: { "Content-Type": "text/plain" },
|
|
88
|
+
body,
|
|
89
|
+
keepalive: true,
|
|
90
|
+
}).catch(() => {
|
|
91
|
+
queue.unshift(...batch);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
const push = (e) => {
|
|
95
|
+
if (!onDashboard())
|
|
96
|
+
return;
|
|
97
|
+
queue.push({ ts: Date.now(), path: currentPath, ...e });
|
|
98
|
+
if (queue.length >= MAX_BATCH)
|
|
99
|
+
flush();
|
|
100
|
+
};
|
|
101
|
+
// ---- clicks (same classification as the host capture layer) --------------
|
|
102
|
+
let lastClick = { selector: "", time: 0, count: 0 };
|
|
103
|
+
document.addEventListener("click", (ev) => {
|
|
104
|
+
const target = ev.target;
|
|
105
|
+
if (!target || !onDashboard())
|
|
106
|
+
return;
|
|
107
|
+
const selector = selectorOf(target);
|
|
108
|
+
const component = componentOf(target);
|
|
109
|
+
const text = labelOf(target);
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
if (selector === lastClick.selector && now - lastClick.time < RAGE_WINDOW_MS) {
|
|
112
|
+
lastClick.count++;
|
|
113
|
+
lastClick.time = now;
|
|
114
|
+
if (lastClick.count === RAGE_COUNT) {
|
|
115
|
+
push({ type: "rage_click", selector, component, text });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
lastClick = { selector: selector ?? "", time: now, count: 1 };
|
|
120
|
+
}
|
|
121
|
+
if (!isInteractive(target)) {
|
|
122
|
+
if (hasTextSelection())
|
|
123
|
+
return;
|
|
124
|
+
push({ type: "dead_click", selector, component, text });
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
push({ type: "click", selector, component, text });
|
|
128
|
+
}
|
|
129
|
+
}, { capture: true, passive: true });
|
|
130
|
+
// ---- page views (tab switches ride on the History API) -------------------
|
|
131
|
+
const onNavigate = () => {
|
|
132
|
+
if (!onDashboard())
|
|
133
|
+
return;
|
|
134
|
+
const next = telemetryPath();
|
|
135
|
+
if (next === currentPath)
|
|
136
|
+
return;
|
|
137
|
+
currentPath = next;
|
|
138
|
+
push({ type: "page_view", path: currentPath });
|
|
139
|
+
};
|
|
140
|
+
const wrapHistory = (method) => {
|
|
141
|
+
const original = history[method];
|
|
142
|
+
history[method] = function (...args) {
|
|
143
|
+
const ret = original.apply(this, args);
|
|
144
|
+
onNavigate();
|
|
145
|
+
return ret;
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
wrapHistory("pushState");
|
|
149
|
+
wrapHistory("replaceState");
|
|
150
|
+
addEventListener("popstate", onNavigate);
|
|
151
|
+
// ---- lifecycle -----------------------------------------------------------
|
|
152
|
+
addEventListener("pagehide", () => {
|
|
153
|
+
push({ type: "session_end" });
|
|
154
|
+
flush(true);
|
|
155
|
+
});
|
|
156
|
+
addEventListener("visibilitychange", () => {
|
|
157
|
+
if (document.visibilityState === "hidden")
|
|
158
|
+
flush(true);
|
|
159
|
+
});
|
|
160
|
+
setInterval(() => flush(false), FLUSH_INTERVAL_MS);
|
|
161
|
+
const w = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
162
|
+
if (w > 0) {
|
|
163
|
+
push({ type: "viewport", value: w, text: deviceCategory(w) });
|
|
164
|
+
}
|
|
165
|
+
push({ type: "page_view", path: currentPath });
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Mounted by the dashboard page only when consent is granted. Renders nothing;
|
|
169
|
+
* starts the capture singleton once per page load (the listeners are global
|
|
170
|
+
* and deliberately never torn down — capture suspends off-dashboard instead).
|
|
171
|
+
*/
|
|
172
|
+
export function PolishdTelemetryEmitter({ endpoint, installId, }) {
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (window.__polishdTelemetryStarted)
|
|
175
|
+
return;
|
|
176
|
+
if (navigator.doNotTrack === "1")
|
|
177
|
+
return;
|
|
178
|
+
window.__polishdTelemetryStarted = true;
|
|
179
|
+
start(endpoint, installId);
|
|
180
|
+
}, [endpoint, installId]);
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The one-time opt-in prompt, shown while consent is "unset". Both buttons
|
|
185
|
+
* persist the decision through a guarded server action; "Share" refreshes the
|
|
186
|
+
* server render so the emitter mounts immediately rather than on next visit.
|
|
187
|
+
*/
|
|
188
|
+
export function PolishdTelemetryConsent() {
|
|
189
|
+
const router = useRouter();
|
|
190
|
+
const [dismissed, setDismissed] = useState(false);
|
|
191
|
+
const [pending, startTransition] = useTransition();
|
|
192
|
+
if (dismissed)
|
|
193
|
+
return null;
|
|
194
|
+
const decide = (granted) => startTransition(async () => {
|
|
195
|
+
try {
|
|
196
|
+
if (granted) {
|
|
197
|
+
await grantPolishdTelemetry();
|
|
198
|
+
router.refresh();
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
await denyPolishdTelemetry();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// Denied or store unavailable — the banner will be back next render;
|
|
206
|
+
// hiding it now keeps this visit usable either way.
|
|
207
|
+
}
|
|
208
|
+
setDismissed(true);
|
|
209
|
+
});
|
|
210
|
+
return (_jsxs("div", { role: "dialog", "aria-label": "Polishd telemetry consent", className: "fixed bottom-4 right-4 z-50 w-[340px] max-w-[calc(100vw-2rem)] rounded-xl border border-[#2e2e2e] bg-[#111] p-4 shadow-2xl", children: [_jsx("p", { className: "text-[13px] font-medium text-white", children: "Help improve polishd?" }), _jsxs("p", { className: "mt-1.5 text-[12px] leading-relaxed text-[#888]", children: ["Share anonymous usage of ", _jsx("span", { className: "text-[#aaa]", children: "this dashboard" }), " \u2014 clicks and tab views inside it, tied to a random install id. Never your site's analytics, never your visitors' data. Opt out any time with", " ", _jsx("code", { className: "font-mono text-[11px] text-[#aaa]", children: "POLISHD_TELEMETRY=off" }), "."] }), _jsxs("div", { className: "mt-3 flex gap-2", children: [_jsx("button", { type: "button", disabled: pending, onClick: () => decide(true), className: "rounded-lg bg-white px-3 py-1.5 text-[12px] font-medium text-black transition-opacity hover:opacity-90 disabled:opacity-50", children: "Share" }), _jsx("button", { type: "button", disabled: pending, onClick: () => decide(false), className: "rounded-lg border border-[#2e2e2e] px-3 py-1.5 text-[12px] text-[#888] transition-colors hover:text-white disabled:opacity-50", children: "No thanks" })] })] }));
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/dashboard/telemetry.tsx"],"names":[],"mappings":"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"}
|
package/dist/dashboard.css
CHANGED
|
@@ -298,10 +298,18 @@
|
|
|
298
298
|
right: 0;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
.polishd-root.polishd-root .right-4 {
|
|
302
|
+
right: calc(var(--spacing) * 4);
|
|
303
|
+
}
|
|
304
|
+
|
|
301
305
|
.polishd-root.polishd-root .bottom-0 {
|
|
302
306
|
bottom: 0;
|
|
303
307
|
}
|
|
304
308
|
|
|
309
|
+
.polishd-root.polishd-root .bottom-4 {
|
|
310
|
+
bottom: calc(var(--spacing) * 4);
|
|
311
|
+
}
|
|
312
|
+
|
|
305
313
|
.polishd-root.polishd-root .bottom-full {
|
|
306
314
|
bottom: 100%;
|
|
307
315
|
}
|
|
@@ -748,6 +756,10 @@
|
|
|
748
756
|
width: 92%;
|
|
749
757
|
}
|
|
750
758
|
|
|
759
|
+
.polishd-root.polishd-root .w-\[340px\] {
|
|
760
|
+
width: 340px;
|
|
761
|
+
}
|
|
762
|
+
|
|
751
763
|
.polishd-root.polishd-root .w-full {
|
|
752
764
|
width: 100%;
|
|
753
765
|
}
|
|
@@ -1157,6 +1169,10 @@
|
|
|
1157
1169
|
border-radius: var(--radius-sm);
|
|
1158
1170
|
}
|
|
1159
1171
|
|
|
1172
|
+
.polishd-root.polishd-root .rounded-xl {
|
|
1173
|
+
border-radius: var(--radius-xl);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1160
1176
|
.polishd-root.polishd-root .rounded-t-xl {
|
|
1161
1177
|
border-top-left-radius: var(--radius-xl);
|
|
1162
1178
|
border-top-right-radius: var(--radius-xl);
|
|
@@ -2341,6 +2357,10 @@
|
|
|
2341
2357
|
opacity: .4;
|
|
2342
2358
|
}
|
|
2343
2359
|
|
|
2360
|
+
.polishd-root.polishd-root .disabled\:opacity-50:disabled {
|
|
2361
|
+
opacity: .5;
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2344
2364
|
@media not all and (min-width: 40rem) {
|
|
2345
2365
|
.polishd-root.polishd-root .max-sm\:hidden {
|
|
2346
2366
|
display: none;
|
package/dist/server/ingest.d.ts
CHANGED
|
@@ -42,4 +42,24 @@ export declare function sessionIdFromCookie(cookieValue: string | undefined): st
|
|
|
42
42
|
* they do in the browser. It falls back to the defaults when omitted.
|
|
43
43
|
*/
|
|
44
44
|
export declare function ingest(body: unknown, cookieValue: string | undefined, config?: Partial<PolishdConfig>): Promise<IngestResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Ingest a telemetry batch from a *remote* polishd installation.
|
|
47
|
+
*
|
|
48
|
+
* This differs from first-party {@link ingest} in exactly three ways, each a
|
|
49
|
+
* consequence of the request crossing origins:
|
|
50
|
+
*
|
|
51
|
+
* 1. Identity travels in the body. The session cookie is httpOnly and
|
|
52
|
+
* first-party, so it never arrives here; the emitter mints an anonymous
|
|
53
|
+
* session id itself and sends it alongside a stable `installId`. Both are
|
|
54
|
+
* validated by shape only — there is nothing to verify them against, and
|
|
55
|
+
* the worst a forger achieves is polluting telemetry, same as any public
|
|
56
|
+
* ingest endpoint.
|
|
57
|
+
* 2. Every stored row is tagged with the `installId`, so one shared database
|
|
58
|
+
* can tell installations apart.
|
|
59
|
+
* 3. Dashboard paths are NOT dropped. Recording how the dashboard itself is
|
|
60
|
+
* used is the entire point of this channel; the emitter is expected to
|
|
61
|
+
* namespace its paths so they can't collide with the receiving site's own
|
|
62
|
+
* first-party events.
|
|
63
|
+
*/
|
|
64
|
+
export declare function ingestTelemetry(body: unknown, config?: Partial<PolishdConfig>): Promise<IngestResult>;
|
|
45
65
|
//# sourceMappingURL=ingest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAenB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AA+BD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAElF;AAkCD;;;;;;GAMG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CA4BvB"}
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAenB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AA+BD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAElF;AAkCD;;;;;;GAMG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CA4BvB;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,YAAY,CAAC,CAyBvB"}
|
package/dist/server/ingest.js
CHANGED
|
@@ -136,4 +136,53 @@ export async function ingest(body, cookieValue, config = {}) {
|
|
|
136
136
|
const stored = await insertEvents(sessionId, events);
|
|
137
137
|
return { ok: true, stored };
|
|
138
138
|
}
|
|
139
|
+
// ── Cross-install telemetry ingest ───────────────────────────────────────────
|
|
140
|
+
/**
|
|
141
|
+
* The shape both client-minted ids must satisfy. Loose enough for a UUID or a
|
|
142
|
+
* short hash, tight enough that the column can never hold markup, whitespace,
|
|
143
|
+
* or anything long enough to be a payload.
|
|
144
|
+
*/
|
|
145
|
+
const TELEMETRY_ID_RE = /^[A-Za-z0-9._-]{6,64}$/;
|
|
146
|
+
/**
|
|
147
|
+
* Ingest a telemetry batch from a *remote* polishd installation.
|
|
148
|
+
*
|
|
149
|
+
* This differs from first-party {@link ingest} in exactly three ways, each a
|
|
150
|
+
* consequence of the request crossing origins:
|
|
151
|
+
*
|
|
152
|
+
* 1. Identity travels in the body. The session cookie is httpOnly and
|
|
153
|
+
* first-party, so it never arrives here; the emitter mints an anonymous
|
|
154
|
+
* session id itself and sends it alongside a stable `installId`. Both are
|
|
155
|
+
* validated by shape only — there is nothing to verify them against, and
|
|
156
|
+
* the worst a forger achieves is polluting telemetry, same as any public
|
|
157
|
+
* ingest endpoint.
|
|
158
|
+
* 2. Every stored row is tagged with the `installId`, so one shared database
|
|
159
|
+
* can tell installations apart.
|
|
160
|
+
* 3. Dashboard paths are NOT dropped. Recording how the dashboard itself is
|
|
161
|
+
* used is the entire point of this channel; the emitter is expected to
|
|
162
|
+
* namespace its paths so they can't collide with the receiving site's own
|
|
163
|
+
* first-party events.
|
|
164
|
+
*/
|
|
165
|
+
export async function ingestTelemetry(body, config = {}) {
|
|
166
|
+
const cfg = { ...defaultPolishdConfig, ...config };
|
|
167
|
+
if (!cfg.enabled)
|
|
168
|
+
return { ok: true, stored: 0, reason: "disabled" };
|
|
169
|
+
const b = body;
|
|
170
|
+
const installId = typeof b?.installId === "string" && TELEMETRY_ID_RE.test(b.installId)
|
|
171
|
+
? b.installId
|
|
172
|
+
: null;
|
|
173
|
+
const sessionId = typeof b?.sessionId === "string" && TELEMETRY_ID_RE.test(b.sessionId)
|
|
174
|
+
? b.sessionId
|
|
175
|
+
: null;
|
|
176
|
+
if (!installId || !sessionId)
|
|
177
|
+
return { ok: false, stored: 0, reason: "bad_identity" };
|
|
178
|
+
const rawEvents = b?.events;
|
|
179
|
+
if (!Array.isArray(rawEvents))
|
|
180
|
+
return { ok: false, stored: 0, reason: "no_events" };
|
|
181
|
+
const events = rawEvents
|
|
182
|
+
.slice(0, MAX_EVENTS_PER_BATCH)
|
|
183
|
+
.map(sanitize)
|
|
184
|
+
.filter((e) => e !== null);
|
|
185
|
+
const stored = await insertEvents(sessionId, events, installId);
|
|
186
|
+
return { ok: true, stored };
|
|
187
|
+
}
|
|
139
188
|
//# sourceMappingURL=ingest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"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"}
|
package/dist/server/store.d.ts
CHANGED
|
@@ -6,8 +6,12 @@ import type { PolishdEvent, PolishdEventRow } from "../shared/types";
|
|
|
6
6
|
type Row = Record<string, unknown>;
|
|
7
7
|
/** True when events are actually being persisted (used by the dashboard). */
|
|
8
8
|
export declare function storeReady(): Promise<boolean>;
|
|
9
|
-
/**
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Persist a batch of events for one session. Silently drops if no store.
|
|
11
|
+
* `installId` is only ever set on the telemetry path — first-party ingest
|
|
12
|
+
* leaves it undefined and the column null.
|
|
13
|
+
*/
|
|
14
|
+
export declare function insertEvents(sessionId: string, events: PolishdEvent[], installId?: string): Promise<number>;
|
|
11
15
|
/**
|
|
12
16
|
* Run a portable read query, or return `[]` in no-op mode. Use `?` placeholders;
|
|
13
17
|
* each backend rewrites them to its own dialect. The aggregation layer (and the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErE;;;GAGG;AACH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErE;;;GAGG;AACH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAmTnC,6EAA6E;AAC7E,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAEnD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EAAE,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAY/E;AAQD,sEAAsE;AACtE,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIjE;AAED,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB1E;AAED,mEAAmE;AACnE,wBAAsB,OAAO,CAAC,KAAK,SAAO,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAGtE;AAmBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAW/D"}
|
package/dist/server/store.js
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { defaultPolishdConfig } from "../config";
|
|
22
22
|
/** The columns every backend inserts, in a fixed order, for one event. */
|
|
23
|
-
const INSERT_COLS = "session_id, type, ts, path, selector, component, text, value, meta, received_at";
|
|
23
|
+
const INSERT_COLS = "session_id, type, ts, path, selector, component, text, value, meta, received_at, install_id";
|
|
24
24
|
/** Turn one event into its positional values, matching `INSERT_COLS`. */
|
|
25
|
-
function eventValues(sessionId, e, now) {
|
|
25
|
+
function eventValues(sessionId, e, now, installId) {
|
|
26
26
|
return [
|
|
27
27
|
sessionId,
|
|
28
28
|
e.type,
|
|
@@ -34,6 +34,7 @@ function eventValues(sessionId, e, now) {
|
|
|
34
34
|
e.value ?? null,
|
|
35
35
|
e.meta ? JSON.stringify(e.meta) : null,
|
|
36
36
|
now,
|
|
37
|
+
installId ?? null,
|
|
37
38
|
];
|
|
38
39
|
}
|
|
39
40
|
// ── Legacy metadata migration ────────────────────────────────────────────────
|
|
@@ -93,7 +94,8 @@ async function openSqlite() {
|
|
|
93
94
|
text TEXT,
|
|
94
95
|
value REAL,
|
|
95
96
|
meta TEXT,
|
|
96
|
-
received_at INTEGER NOT NULL
|
|
97
|
+
received_at INTEGER NOT NULL,
|
|
98
|
+
install_id TEXT
|
|
97
99
|
);
|
|
98
100
|
CREATE INDEX IF NOT EXISTS idx_events_path ON events(path);
|
|
99
101
|
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
@@ -105,20 +107,30 @@ async function openSqlite() {
|
|
|
105
107
|
updated_at INTEGER NOT NULL
|
|
106
108
|
);
|
|
107
109
|
`);
|
|
110
|
+
// Databases created before install_id existed lack the column; SQLite has no
|
|
111
|
+
// ADD COLUMN IF NOT EXISTS, so the raise on an up-to-date table is the
|
|
112
|
+
// expected path. The index only lands once the column is guaranteed present.
|
|
113
|
+
try {
|
|
114
|
+
db.exec(`ALTER TABLE events ADD COLUMN install_id TEXT`);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Column already there — fresh table or already-migrated database.
|
|
118
|
+
}
|
|
119
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_events_install ON events(install_id)`);
|
|
108
120
|
migrateLegacyMeta((sql) => db.exec(sql), `INSERT OR IGNORE INTO polishd_meta (key, value, updated_at)
|
|
109
121
|
SELECT key, value, updated_at FROM buffd_meta`);
|
|
110
122
|
return {
|
|
111
|
-
async insert(sessionId, events) {
|
|
123
|
+
async insert(sessionId, events, installId) {
|
|
112
124
|
if (events.length === 0)
|
|
113
125
|
return 0;
|
|
114
126
|
const now = Date.now();
|
|
115
|
-
const stmt = db.prepare(`INSERT INTO events (${INSERT_COLS}) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
127
|
+
const stmt = db.prepare(`INSERT INTO events (${INSERT_COLS}) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
116
128
|
let written = 0;
|
|
117
129
|
// node:sqlite has no .transaction() helper; wrap manually for batch speed.
|
|
118
130
|
db.exec("BEGIN");
|
|
119
131
|
try {
|
|
120
132
|
for (const e of events) {
|
|
121
|
-
stmt.run(...eventValues(sessionId, e, now));
|
|
133
|
+
stmt.run(...eventValues(sessionId, e, now, installId));
|
|
122
134
|
written++;
|
|
123
135
|
}
|
|
124
136
|
db.exec("COMMIT");
|
|
@@ -176,11 +188,15 @@ function openPostgres(url) {
|
|
|
176
188
|
text TEXT,
|
|
177
189
|
value DOUBLE PRECISION,
|
|
178
190
|
meta JSONB,
|
|
179
|
-
received_at BIGINT NOT NULL
|
|
191
|
+
received_at BIGINT NOT NULL,
|
|
192
|
+
install_id TEXT
|
|
180
193
|
);
|
|
194
|
+
-- Migrates tables created before install_id existed; no-op otherwise.
|
|
195
|
+
ALTER TABLE events ADD COLUMN IF NOT EXISTS install_id TEXT;
|
|
181
196
|
CREATE INDEX IF NOT EXISTS idx_events_path ON events(path);
|
|
182
197
|
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
183
198
|
CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
|
|
199
|
+
CREATE INDEX IF NOT EXISTS idx_events_install ON events(install_id);
|
|
184
200
|
|
|
185
201
|
CREATE TABLE IF NOT EXISTS polishd_meta (
|
|
186
202
|
key TEXT PRIMARY KEY,
|
|
@@ -193,12 +209,12 @@ function openPostgres(url) {
|
|
|
193
209
|
ON CONFLICT (key) DO NOTHING`);
|
|
194
210
|
});
|
|
195
211
|
return {
|
|
196
|
-
async insert(sessionId, events) {
|
|
212
|
+
async insert(sessionId, events, installId) {
|
|
197
213
|
if (events.length === 0)
|
|
198
214
|
return 0;
|
|
199
215
|
await ready;
|
|
200
216
|
const now = Date.now();
|
|
201
|
-
const cols =
|
|
217
|
+
const cols = 11; // must match INSERT_COLS / eventValues
|
|
202
218
|
const params = [];
|
|
203
219
|
const tuples = [];
|
|
204
220
|
events.forEach((e, row) => {
|
|
@@ -206,7 +222,7 @@ function openPostgres(url) {
|
|
|
206
222
|
// meta is the 9th column (index 8) — cast its text param to jsonb.
|
|
207
223
|
const ph = Array.from({ length: cols }, (_, c) => c === 8 ? `$${base + c + 1}::jsonb` : `$${base + c + 1}`);
|
|
208
224
|
tuples.push(`(${ph.join(", ")})`);
|
|
209
|
-
params.push(...eventValues(sessionId, e, now));
|
|
225
|
+
params.push(...eventValues(sessionId, e, now, installId));
|
|
210
226
|
});
|
|
211
227
|
const res = await pool.query(`INSERT INTO events (${INSERT_COLS}) VALUES ${tuples.join(", ")}`, params);
|
|
212
228
|
return res.rowCount ?? 0;
|
|
@@ -261,13 +277,17 @@ async function getBackend() {
|
|
|
261
277
|
export async function storeReady() {
|
|
262
278
|
return (await getBackend()) !== null;
|
|
263
279
|
}
|
|
264
|
-
/**
|
|
265
|
-
|
|
280
|
+
/**
|
|
281
|
+
* Persist a batch of events for one session. Silently drops if no store.
|
|
282
|
+
* `installId` is only ever set on the telemetry path — first-party ingest
|
|
283
|
+
* leaves it undefined and the column null.
|
|
284
|
+
*/
|
|
285
|
+
export async function insertEvents(sessionId, events, installId) {
|
|
266
286
|
const b = await getBackend();
|
|
267
287
|
if (!b || events.length === 0)
|
|
268
288
|
return 0;
|
|
269
289
|
try {
|
|
270
|
-
return await b.insert(sessionId, events);
|
|
290
|
+
return await b.insert(sessionId, events, installId);
|
|
271
291
|
}
|
|
272
292
|
catch (err) {
|
|
273
293
|
console.warn("[polishd] insert failed, dropping batch:", err instanceof Error ? err.message : err);
|
|
@@ -335,6 +355,7 @@ function deserialize(row) {
|
|
|
335
355
|
value: row.value == null ? undefined : Number(row.value),
|
|
336
356
|
meta: parseMeta(row.meta),
|
|
337
357
|
received_at: Number(row.received_at),
|
|
358
|
+
install_id: row.install_id ?? undefined,
|
|
338
359
|
};
|
|
339
360
|
}
|
|
340
361
|
/**
|
package/dist/server/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAkBjD,0EAA0E;AAC1E,MAAM,WAAW,GACf,
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where telemetry lands: the polishd landing site's own installation. One
|
|
3
|
+
* constant on purpose — when the site moves to a real domain, this is the
|
|
4
|
+
* single line to change.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_TELEMETRY_ENDPOINT = "https://polishd-lac.vercel.app/api/polishd-telemetry";
|
|
7
|
+
export type PolishdTelemetryStatus =
|
|
8
|
+
/** Owner said yes; the emitter runs. */
|
|
9
|
+
"granted"
|
|
10
|
+
/** Owner said no; nothing runs, nothing asks again. */
|
|
11
|
+
| "denied"
|
|
12
|
+
/** Never asked — the dashboard shows the consent prompt. */
|
|
13
|
+
| "unset"
|
|
14
|
+
/** Env kill switch, or no writable store to keep consent in. */
|
|
15
|
+
| "disabled";
|
|
16
|
+
export interface PolishdTelemetryState {
|
|
17
|
+
status: PolishdTelemetryStatus;
|
|
18
|
+
/** Set only when status is "granted" — the emitter needs it, nobody else. */
|
|
19
|
+
installId: string | null;
|
|
20
|
+
endpoint: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function telemetryDisabledByEnv(): boolean;
|
|
23
|
+
export declare function resolveTelemetryEndpoint(): string;
|
|
24
|
+
/** Record the owner's decision. Overwrites any previous one. */
|
|
25
|
+
export declare function saveTelemetryConsent(granted: boolean): Promise<void>;
|
|
26
|
+
/** What the dashboard should do about telemetry on this render. */
|
|
27
|
+
export declare function loadPolishdTelemetryState(): Promise<PolishdTelemetryState>;
|
|
28
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/server/telemetry.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,yDACiB,CAAC;AAKzD,MAAM,MAAM,sBAAsB;AAChC,wCAAwC;AACtC,SAAS;AACX,uDAAuD;GACrD,QAAQ;AACV,4DAA4D;GAC1D,OAAO;AACT,gEAAgE;GAC9D,UAAU,CAAC;AAEf,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,6EAA6E;IAC7E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAGhD;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAcD,gEAAgE;AAChE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1E;AAED,mEAAmE;AACnE,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAuBhF"}
|