Dev Blog: Keeping Async Consistent in the SSO Crypto Module (v1.0.29)
Dev Blog: Keeping Async Consistent in the SSO Crypto Module
Release: v1.0.29 · Affected files:
src/lib/sso-crypto.ts,src/lib/routers/sso.ts
What Was Found
During a code review pass on the SSO subsystem, a subtle style inconsistency was spotted in how encryptSsoSecret is called inside sso.ts.
The function is defined synchronously in src/lib/sso-crypto.ts:
// src/lib/sso-crypto.ts
export function encryptSsoSecret(secret: string): string {
// ... synchronous encryption logic
}
But at the call site in src/lib/routers/sso.ts (line ~79), it is invoked with await:
// src/lib/routers/sso.ts
const encryptedSecret = await encryptSsoSecret(input.clientSecret);
Is This a Bug?
No. This is not a runtime bug.
In JavaScript and TypeScript, awaiting a value that is not a Promise is perfectly valid — the runtime simply returns the value as-is. So await encryptSsoSecret(...) behaves identically to encryptSsoSecret(...) when the function is synchronous. There is no exception thrown, no data corruption, and no change in behaviour.
Why It Matters Anyway
Even though the code runs correctly, the stray await is misleading for a few reasons:
- It implies the function is async. A developer reading
await encryptSsoSecret(...)will reasonably assume the function returns aPromiseand may treat it as such elsewhere. - It likely signals copy-paste from an earlier version. The function may have been async at an earlier stage of development, and the
awaitwas not cleaned up when it was refactored to be synchronous. - Static analysis tools may flag it. Linters such as ESLint (with the
@typescript-eslint/await-thenablerule) will warn on this pattern.
The Fix
There are two valid approaches — pick the one that matches the codebase's existing style:
Option A — Remove await from the call site
If the function is and should remain synchronous, simply drop the await:
// src/lib/routers/sso.ts
const encryptedSecret = encryptSsoSecret(input.clientSecret);
This is the minimal change and keeps the function signature clean.
Option B — Make encryptSsoSecret explicitly async
If the router consistently uses await for all secret/crypto operations (for readability or future-proofing), align the function signature:
// src/lib/sso-crypto.ts
export async function encryptSsoSecret(secret: string): Promise<string> {
// wrap existing synchronous logic
return Promise.resolve(existingSyncEncryptLogic(secret));
}
This approach keeps the call site unchanged and makes the async intent explicit.
Recommendation
If the rest of sso.ts deals with genuinely async operations (database calls, network I/O), Option B avoids visual inconsistency — all operations in the handler look uniform. If encryptSsoSecret is a pure utility with no planned async future, Option A is the cleaner signal to future maintainers.
Takeaway
This is a good example of a zero-impact finding that still warrants a fix: the code does the right thing today, but leaves a small trap for the next developer who reads it. Cleaning it up now costs very little and removes a potential source of confusion.