Skip to content

chore(shared): replace telemetry postinstall with runtime notice#8549

Open
jacekradko wants to merge 3 commits into
mainfrom
jacek/sdk-84-remove-telemetry-postinstall-notice
Open

chore(shared): replace telemetry postinstall with runtime notice#8549
jacekradko wants to merge 3 commits into
mainfrom
jacek/sdk-84-remove-telemetry-postinstall-notice

Conversation

@jacekradko
Copy link
Copy Markdown
Member

@jacekradko jacekradko commented May 14, 2026

NOT READY FOR REVIEW YET!

Moves the one-time telemetry disclosure off the postinstall lifecycle script and into the TelemetryCollector itself. The same notice now fires at runtime the first time telemetry activates on a development instance, gated on CI, headless, and the existing opt-out signals. The Node persistence marker reuses the prior env-paths location so anyone who already saw the postinstall notice will not see it again. Drops the std-env dependency and removes install-time code from the published package, which addresses the supply-chain concern raised in #8540.

Resolves SDK-84.

Move the one-time telemetry disclosure off of npm lifecycle scripts and into the
TelemetryCollector itself. Surfacing it at runtime instead of install time keeps
@clerk/shared free of postinstall code, drops the std-env dependency, and only
shows the notice in environments where telemetry actually fires. The Node
persistence marker reuses the prior env-paths location, so users who already
saw the notice via postinstall will not see it again.

Resolves SDK-84.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 14, 2026

🦋 Changeset detected

Latest commit: 8d23466

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
@clerk/shared Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/chrome-extension Patch
@clerk/clerk-js Patch
@clerk/expo-passkeys Patch
@clerk/expo Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/hono Patch
@clerk/localizations Patch
@clerk/msw Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/react Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/ui Patch
@clerk/vue Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment May 14, 2026 7:36pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

📝 Walkthrough

Walkthrough

The patch removes the install-time postinstall telemetry-disclosure script and drops the std-env dependency from @clerk/shared, and narrows published files to dist. Telemetry disclosure is moved to runtime: a new synchronous maybeShowTelemetryNotice(options?) prints a one-time notice guarded by CI and headless checks, persists a seen marker to localStorage in browsers or a process-wide globalThis Symbol in Node, deduplicates within a process, and swallows errors. TelemetryCollector now invokes the notice at construction. Tests covering gating, persistence, dedupe, and error resilience were added; the removed postinstall.mjs file was deleted.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: moving telemetry disclosure from postinstall script to runtime notice.
Description check ✅ Passed The description is directly related to the changeset, explaining the motivation, implementation details, and issue resolution.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@brkalow
Copy link
Copy Markdown
Member

brkalow commented May 14, 2026

@jacekradko my hunch is that this is going to trigger more than desired in the browser, and we'll get requests to disable the warning altogether similar to what happened with the dev mode warning. How can we get ahead of that? 🤔

@clerk/ui re-bundles @clerk/shared with Rspack, which does not handle bare
`node:` URI imports even when they are only reachable on a Node runtime.
Route the dynamic imports through a `new Function('id', 'return import(id)')`
indirection so the module specifiers are no longer visible to static
analysis. Also apply prettier to the new spec file.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 14, 2026

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8549

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8549

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8549

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8549

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@8549

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8549

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8549

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8549

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8549

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8549

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8549

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8549

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8549

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8549

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8549

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8549

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8549

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8549

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8549

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8549

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8549

commit: 8d23466

Next.js Edge Runtime forbids `new Function`/`eval` even in unreachable code,
so the dynamic-import-evasion trick used to hide `node:` module specifiers
from webpack tripped the edge analyzer when @clerk/shared was reached through
@clerk/nextjs middleware. Replace the Node config-file persistence with a
`globalThis` Symbol flag (browser still uses localStorage). The notice now
shows at most once per process on Node and once per machine in the browser,
with no filesystem access and no dynamic-code APIs anywhere in the bundle.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/shared/src/telemetry/notice.ts`:
- Around line 66-75: hasSeen() currently returns early if
hasUsableLocalStorage() is true even when localStorage.getItem throws, so the
process-level dedupe (PROCESS_FLAG) never gets consulted; update hasSeen() to
attempt reading localStorage in a try/catch and on exception fall back to
returning the boolean value of (globalThis as Record<symbol,
unknown>)[PROCESS_FLAG] instead of false. Also adjust markSeen() so when writing
to localStorage throws it sets PROCESS_FLAG as the fallback; reference
STORAGE_KEY, PROCESS_FLAG, hasUsableLocalStorage(), hasSeen(), and markSeen()
when making these changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: f335de7c-4216-4858-aabd-2ebf30fd08e7

📥 Commits

Reviewing files that changed from the base of the PR and between 6592f97 and 8d23466.

📒 Files selected for processing (4)
  • .changeset/sdk-84-remove-telemetry-postinstall.md
  • packages/shared/src/__tests__/telemetry.notice.spec.ts
  • packages/shared/src/telemetry/collector.ts
  • packages/shared/src/telemetry/notice.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/sdk-84-remove-telemetry-postinstall.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/shared/src/telemetry/collector.ts
  • packages/shared/src/tests/telemetry.notice.spec.ts

Comment on lines +66 to +75
function hasSeen(): boolean {
if (hasUsableLocalStorage()) {
try {
return globalThis.localStorage.getItem(STORAGE_KEY) === '1';
} catch {
return false;
}
}
return Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG]);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Process-level dedupe is skipped when localStorage exists but cannot persist/read reliably.

On Line 66–72, hasSeen() returns from the localStorage branch and never checks PROCESS_FLAG. On Line 77–87, markSeen() sets PROCESS_FLAG as fallback, but that fallback is effectively ignored on later calls when localStorage is present. In restricted storage contexts, the notice can print repeatedly instead of once.

Suggested fix
 function hasSeen(): boolean {
+  if (Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG])) {
+    return true;
+  }
+
   if (hasUsableLocalStorage()) {
     try {
       return globalThis.localStorage.getItem(STORAGE_KEY) === '1';
     } catch {
       return false;
     }
   }
-  return Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG]);
+  return false;
 }
 
 function markSeen(): void {
+  // Always dedupe within the current process, regardless of storage state.
+  (globalThis as Record<symbol, unknown>)[PROCESS_FLAG] = true;
+
   if (hasUsableLocalStorage()) {
     try {
       globalThis.localStorage.setItem(STORAGE_KEY, '1');
-      return;
     } catch {
-      // fall through to the in-process flag
+      // ignore storage failures; in-process dedupe is already set
     }
   }
-  (globalThis as Record<symbol, unknown>)[PROCESS_FLAG] = true;
 }

Also applies to: 77-87

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/telemetry/notice.ts` around lines 66 - 75, hasSeen()
currently returns early if hasUsableLocalStorage() is true even when
localStorage.getItem throws, so the process-level dedupe (PROCESS_FLAG) never
gets consulted; update hasSeen() to attempt reading localStorage in a try/catch
and on exception fall back to returning the boolean value of (globalThis as
Record<symbol, unknown>)[PROCESS_FLAG] instead of false. Also adjust markSeen()
so when writing to localStorage throws it sets PROCESS_FLAG as the fallback;
reference STORAGE_KEY, PROCESS_FLAG, hasUsableLocalStorage(), hasSeen(), and
markSeen() when making these changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants