fix: gh-2517 change for fixing next edge runtime build error for crypto module#2564
fix: gh-2517 change for fixing next edge runtime build error for crypto module#2564
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2564 +/- ##
==========================================
+ Coverage 89.97% 90.06% +0.09%
==========================================
Files 62 63 +1
Lines 7543 7603 +60
Branches 1604 1608 +4
==========================================
+ Hits 6787 6848 +61
+ Misses 744 743 -1
Partials 12 12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Current logic will break some customer builds if DPoP config is wrong (we have had cases where custoemr builds failed if validation failed due to the way their build system handles errors). This change will allow builds to pass and isntead runtime errors to be thrown. |
| // String concatenation at runtime makes the import path impossible to statically analyze | ||
| // This is bundler-agnostic and works with webpack, Turbopack, Vite, esbuild, Rollup, etc. | ||
| const cryptoModule = "cry" + "pto"; |
There was a problem hiding this comment.
const cryptoModule = "cry" + "pto";
Why statically load this module when we are already dynamically importing dpopUtils.ts?
I think a simple import { createPrivateKey } from "node:crypto" should achieve the same, without the edge cases that this can bring.
This is bundler-agnostic and works with webpack, Turbopack, Vite, esbuild, Rollup, etc.
Are we sure that future changes to bundlers related to static analysis will not break this? Bundler choice and version is not in control of the SDK.
There was a problem hiding this comment.
Have we taken any action on this?
There was a problem hiding this comment.
Dynamic import alone did not solve this issue :
Bundlers perform static analysis on all reachable files during build time, independent of dynamic imports.
// auth-client.ts
await import("../utils/dpopUtils.js"); // Dynamic import
// dpopUtils.ts
import { createPrivateKey } from "crypto"; // Static importBuild process:
- Bundler scans dpopUtils.ts during static analysis
- Detects crypto import, attempts to bundle crypto module
- Edge Runtime build fails (crypto not available)
- The await import() only controls when the pre-bundled module loads, not whether its dependencies get bundled.
Why node:crypto Doesn't Solve This
await import("node:crypto"); // Still a static string
Bundlers detect the string literal "node:crypto" during static analysis and attempt module resolution. The node: prefix doesn't prevent this.
const cryptoModule = "cry" + "pto";
await import(cryptoModule); // Path unknown to bundler
Static analysis cannot predict runtime string operations. Bundler sees import(variable) with unknown value and skips bundling.
Bundler Compatibility
Works across all JavaScript bundlers
No bundler can trace computed string values without runtime execution. This is not a workaround and is widely accepted.
Verified:
Internal testing confirmed Edge Runtime builds failed with static crypto imports and succeeded with runtime-constructed paths.
There was a problem hiding this comment.
Requesting to run this by @nandan-bhat once, to get consensus.
tusharpandey13
left a comment
There was a problem hiding this comment.
Please take a look at these comments, thanks.
Yes, it is. But this is intentional and better because: Error still gets caught - just at the right time (when DPoP is used) The trade-off is: Loss: Build-time config validation |
…y() params & auth-client dpop test improvements
|
Hi @tusharpandey13, Additional Fix: Critical DPoP Bug Problem
The Solution Impact:
|
d498c40 to
3753fbb
Compare
a003f1b to
1460b7b
Compare
tusharpandey13
left a comment
There was a problem hiding this comment.
Please take a look
7e1d219 to
4561c7e
Compare
Closes #2517
🎯 Problem Statement
Original Issue
Edge Runtime builds were failing with:
Root Cause
dpopUtils.tshad staticimport { crypto }at the topuseDPoP=false, the crypto module was being bundledcryptomodule → build failure✅ Solution Overview
Strategy
📊 Before vs After Comparison
BEFORE: Eager Validation (Static Imports)
Runtime Flow
Bundle Impact: crypto included even when
useDPoP=false❌AFTER: Lazy Validation (Dynamic Imports)
Runtime Flow
Bundle Impact: crypto ONLY included when
useDPoP=trueAND env vars present ✓🔒 Error Timing Analysis
Scenario: Missing DPoP Environment Variables
Scenario: Invalid DPoP Keys (Invalid PEM format)
Before:
After:
Error timing shifted from construction to first operation
Slightly Delayed Validation
Additional File
Dynamic Import Complexity
✅ Backward Compatibility
No breaking changes - User code works unchanged:
📋 Testing Checklist
📌 Summary
✅ Backward Compatible - No breaking changes, no migration needed
🚀 Performance Impact - Negligible (~1-5ms one-time validation on first DPoP operation)
📦 Bundle Size - Crypto module excluded when
useDPoP=false(~50KB savings)Key Files Changed:
src/utils/dpopRetry.ts(new) - Crypto-free utilitiessrc/utils/dpopUtils.ts- Now crypto-only, dynamically importedsrc/server/client.ts- Removed static validationsrc/server/auth-client.ts- Added lazy validation withensureDpopValidated()