Skip to content

feat: add @launchdarkly/o11y as the shared browser foundation, publish highlight.run as a thin alias - #756

Open
Vadman97 wants to merge 3 commits into
mainfrom
vkorolik/launchdarkly-o11y-package
Open

feat: add @launchdarkly/o11y as the shared browser foundation, publish highlight.run as a thin alias#756
Vadman97 wants to merge 3 commits into
mainfrom
vkorolik/launchdarkly-o11y-package

Conversation

@Vadman97

@Vadman97 Vadman97 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduces @launchdarkly/o11y as the shared browser foundation that @launchdarkly/observability and @launchdarkly/session-replay are built on, and turns highlight.run into a thin compatibility wrapper over it so both names keep publishing (dual publishing).

Motivation (from a teammate's question): our own packages currently pull highlight.run in as a runtime dependency of @launchdarkly/observability / @launchdarkly/session-replay. Tooling that allow-lists by @launchdarkly/* (dependency quarantines, exclusions, namespace protection) can't express that today. After this change every runtime dependency in the LD browser SDK chain is under the @launchdarkly/* scope.

What changed

Source move (git rename, no code changes): sdk/highlight-run/**sdk/@launchdarkly/o11y/**. The package is renamed to @launchdarkly/o11y; build config, exports map (., ./observe, ./record, ./ld/observe, ./ld/record), UMD global (LD), tests, codegen, typedoc, and size-limit are all unchanged apart from two relative paths (tsconfig project reference, codegen.yml schema path).

highlight.run becomes a wrapper (sdk/highlight-run), exactly like the other two wrappers: export * from '@launchdarkly/o11y' (+ one file per subpath entry), bundled by vite into a self-contained package with the same 5 entry points and index.umd.js. Keeps its own CHANGELOG.md, version line (10.x), README (with a pointer note), and continues to publish via yarn publish:highlight. All in-repo consumers (@highlight-run/next, remix, node, react, e2e apps) keep importing highlight.run untouched.

Wrappers re-pointed: @launchdarkly/observability and @launchdarkly/session-replay now depend on and re-export from @launchdarkly/o11y instead of highlight.run.

Plumbing:

  • turbo.json: highlight.run#typegen@launchdarkly/o11y#typegen (the rrweb build ordering).
  • release-please-config.json + manifest: register sdk/@launchdarkly/o11y (node release type, same settings as siblings). Manifest seeded at 1.1.20 so it ships in lockstep with @launchdarkly/observability / @launchdarkly/session-replay; the node-workspace plugin then bumps the three wrappers whenever o11y changes, as it does for highlight.run today.
  • scripts/check-published-types.mjs: now packs and type-checks @launchdarkly/o11y (the package that owns the rolled-up .d.ts and whose runtime deps are all on npm). The wrappers use workspace: so npm pack can't test them, same as before.
  • Docs CI (publish-docs.yml, manual-publish-docs.yml): typedoc now runs from sdk/@launchdarkly/o11y; output path stays packages/@launchdarkly/observability so the docs URL doesn't move.
  • .gitignore, CLAUDE.md, analytics-taxonomy.md: path updates.
  • yarn.lock: workspace re-link only, no new third-party deps.

Things reviewers should know

  • ⚠️ First publish needs a human. @launchdarkly/o11y does not exist on npm yet, and publish-npm.sh uses npm OIDC trusted publishing, which requires the package to already exist with a trusted publisher configured. Before merging, an npm org admin needs to create the package and add launchdarkly/observability-sdk / turbo.yml as its trusted publisher (same setup as the other @launchdarkly/* packages). Otherwise the Publish @launchdarkly npm packages step on main will fail for o11y (the other packages are unaffected; the script exits on first failure so ordering matters — o11y sorts before observability).
  • Reported SDK version changes. src/version.ts reads its own package.json, so firstloadVersion / clientVersion on sessions moves from the highlight.run line (10.7.2) to the @launchdarkly line (1.1.20) for all three wrappers. The backend only stores these fields (InitializeSession → session row); nothing gates on them. This is arguably more correct: it's the version customers actually install.
  • Not changed on purpose: runtime string identifiers that still say highlight.run (LD SDK hook metadata name: 'highlight.run' / 'highlight.run/ld', error-frame and XHR self-filtering on 'highlight.run', console warning prefix). Renaming those affects telemetry/dashboards and deserves its own PR.
  • Bundle size of the wrappers is unchanged: they inline @launchdarkly/o11y exactly as they inlined highlight.run.

Verification

All run locally in a fresh worktree off main with a clean yarn install:

  • yarn dedupe --check
  • yarn turbo run build --filter 'highlight.run...' --filter @launchdarkly/observability --filter @launchdarkly/session-replay ✅ (15 tasks: rrweb deps → observability-shared → o11y typegen/build → the three wrappers)
  • yarn turbo run test --filter @launchdarkly/o11y ✅ — 26 test files, 491 tests; enforce-size 171.64 kB brotli (limit 256 kB)
  • node scripts/check-published-types.mjs ✅ — packed @launchdarkly/o11y installs into a clean consumer and type-checks with skipLibCheck: false under both bundler and node resolution
  • prettier --check on every changed file ✅
  • Output equivalence: highlight.run's dist/index.js and dist/index.umd.js export exactly the same named surface as @launchdarkly/o11y (GenerateSecureID, H, HighlightSegmentMiddleware, LDObserve, LDRecord, MetricCategory, Observe, Record, __testing, configureElectronHighlight); the UMD bundle evaluated in jsdom sets window.H (25 methods) and H.getRecordingState() returns NotRecording. UMD size 793 KB vs 794 KB for o11y. @launchdarkly/observability exports default, LDObserve; @launchdarkly/session-replay exports default, LDRecord, as before.
  • Every highlight.run .d.ts is a one-line export * from '@launchdarkly/o11y[/subpath]'; the two @launchdarkly/* wrappers' .d.ts re-export from @launchdarkly/o11y.

Not run here: the e2e apps (they import highlight.run, which is unchanged at the API level) and the actual npm publish (see the prerequisite above).

Follow-ups (not in this PR)

  • Decide whether @highlight-run/next / remix / node / react should also move to @launchdarkly/o11y, or stay on the highlight.run alias as the highlight-branded family.
  • Rename the 'highlight.run' runtime identifiers above once dashboards/queries are ready for it.
  • Eventually deprecate highlight.run on npm with a pointer to @launchdarkly/observability / @launchdarkly/session-replay.

Note

Overview
Introduces @launchdarkly/o11y as the shared browser implementation (session replay + observability) and repoints @launchdarkly/observability and @launchdarkly/session-replay to depend on and re-export it instead of highlight.run. highlight.run stays published as a thin bundled alias (export * from '@launchdarkly/o11y') so existing imports keep working.

Release and docs plumbing follow the new layout: turbo.yml publishes @launchdarkly/* before highlight.run (runtime dep on @launchdarkly/o11y), publish-npm.sh and root publish scripts use topological ordering, check-published-types.mjs validates @launchdarkly/o11y's rolled-up types, TypeDoc/docs CI targets sdk/@launchdarkly/o11y (still published to the observability docs path), and release-please registers the new package.

Reviewed by Cursor Bugbot for commit f3ce874. Bugbot is set up for automated code reviews on this repo. Configure here.

…h highlight.run as a thin alias

Move the browser SDK implementation from sdk/highlight-run to
sdk/@launchdarkly/o11y and publish it as @launchdarkly/o11y. highlight.run
becomes a thin wrapper that re-exports @launchdarkly/o11y (same five entry
points and UMD bundle), so it keeps publishing unchanged for existing users.
@launchdarkly/observability and @launchdarkly/session-replay now depend on
@launchdarkly/o11y instead of highlight.run, so the whole LaunchDarkly browser
SDK dependency chain lives under the @launchdarkly/* scope.

- turbo: highlight.run#typegen -> @launchdarkly/o11y#typegen
- release-please: register sdk/@launchdarkly/o11y (seeded at 1.1.20, lockstep
  with the wrappers)
- check-published-types: verify @launchdarkly/o11y (owns the rolled-up .d.ts)
- docs CI: typedoc from sdk/@launchdarkly/o11y, same output path
- .gitignore / CLAUDE.md / analytics-taxonomy.md path updates

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Vadman97
Vadman97 requested a review from a team as a code owner September 3, 2026 23:35
export default defineConfig({
envPrefix: ['REACT_APP_'],
server: {
host: '0.0.0.0',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High severity vulnerability may affect your project—review required:
Line 11 lists a dependency (vite) with a known High severity vulnerability.

ℹ️ Why this matters

Affected versions of vite and vite-plus are vulnerable to Exposure of Sensitive Information to an Unauthorized Actor / Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'). Vite's server.fs.deny blocklist—which protects sensitive files such as .env and certificate files from being served—can be bypassed on Windows using alternate path representations (NTFS Alternate Data Stream syntax like /.env::$DATA?raw, or 8.3 short filenames), allowing an attacker to read otherwise-denied files when the dev server is exposed to the network.

References: https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-38303, GHSA, CVE

To resolve this comment:
Check if you are running the Vite dev server or vite-plus on Windows.

  • If you're affected, upgrade this dependency to at least version 6.4.3 at yarn.lock.
  • If you're not affected, comment /fp we don't use this [condition]
💬 Ignore this finding

To ignore this, reply with:

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

You can view more details on this finding in the Semgrep AppSec Platform here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

/fp we don't use the vite dev server with this dependency. The flagged vite5 alias (vite 5.4.21) is a devDependency invoked only as vite build to produce the production bundle; the dev server (vite dev) runs on vite@^6.4.3, which is already the patched version. Builds run on ubuntu in CI and macOS locally, not Windows, so the server.fs.deny Windows path bypass is not reachable.

Context: this devDependency predates this PR (added in #603 as a "dual vite" setup) and only shows up here because sdk/highlight-run was renamed to sdk/@launchdarkly/o11y. Vite 5 has no patched release for this advisory (fix is 6.4.3+), so removing it means moving the o11y production build to vite 6, which currently fails on the inline worker bundle (cross-fetch CJS interop via graphql-request). That migration is a separate follow-up.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7b8136a. Configure here.

Comment thread sdk/highlight-run/package.json
Vadman97 and others added 2 commits September 8, 2026 17:46
…shes topologically

highlight.run now depends on @launchdarkly/o11y at runtime, but the Monorepo
workflow published highlight.run before the @launchdarkly/* OIDC step. After a
version bump, `npm install highlight.run` could fail until (or forever, if) the
o11y publish landed.

- turbo.yml: run the @launchdarkly/* publish first; a failure there stops the
  job before highlight.run is published.
- publish-npm.sh: sort workspaces topologically instead of relying on
  alphabetical order (o11y -> observability/session-replay -> observability-next).
- package.json: `--topological` on both `yarn workspaces foreach` publish
  scripts so highlight.run publishes before @highlight-run/node, next, remix.
- manual-publish.yml: document the ordering constraint for manual highlight
  publishes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings in #758 (WebKit/iPad performance hardening) and #759 (release
1.1.21 / 10.7.3). Conflict resolutions:

- .release-please-manifest.json: take main's bumps; seed
  sdk/@launchdarkly/o11y at 1.1.21 to stay in lockstep with
  @launchdarkly/observability and @launchdarkly/session-replay.
- sdk/@launchdarkly/o11y/package.json: version 1.1.20 -> 1.1.21 (same).
- sdk/highlight-run/package.json: take main's 10.7.3, keep the wrapper
  description.
- sdk/highlight-run/vite.config.ts: keep the wrapper config; port main's
  OTEL_DEDUPE resolve/dedupe change to sdk/@launchdarkly/o11y/vite.config.ts,
  which is now byte-identical to main's sdk/highlight-run/vite.config.ts.
- body-limits.test.ts: placed under the renamed sdk/@launchdarkly/o11y path.

All other #758 source changes were auto-applied onto the renamed o11y paths
(zero-diff renames against main). Verified: yarn dedupe --check, wrapper
builds, 27 o11y test files / 496 tests, size-limit 170.29 kB brotli.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Vadman97

Vadman97 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Two follow-up commits since the approvals:

e0e9367 – publish ordering (Bugbot finding). turbo.yml now publishes @launchdarkly/* (OIDC) before yarn publish:highlight, scripts/publish-npm.sh orders workspaces topologically instead of alphabetically, and both yarn workspaces foreach publish scripts use --topological (so highlight.run also precedes @highlight-run/node/next/remix). A failed @launchdarkly/o11y publish now fails the job before highlight.run is published against a missing version.

f3ce874 – merge of main. The PR had become conflicting after #758 (iPad hardening) and #759 (release 1.1.21 / 10.7.3), which blocked all pull_request workflows. Resolutions:

Re-verified locally: yarn dedupe --check, builds of highlight.run, @launchdarkly/observability, @launchdarkly/session-replay; o11y tests 27 files / 496 passed; size-limit 170.29 kB brotli (was 171.64 kB before the dedupe).

Semgrep's vite finding is answered inline as a false positive: the flagged vite5 alias is only used for vite build, the dev server runs on the patched vite@6.4.3, and vite 5 has no patched release. Moving the o11y build to vite 6 fails on the inline worker bundle (cross-fetch CJS interop), so that stays a separate follow-up.

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.

3 participants