Skip to content

Commit 2822177

Browse files
committed
refactor: migrate web package from env to webEnv
- Add ESLint rule to enforce webEnv import instead of env - Replace all env imports with webEnv in 17 web files - webEnv omits CODEBUFF_API_KEY for type-level security
1 parent 7190295 commit 2822177

File tree

18 files changed

+60
-46
lines changed

18 files changed

+60
-46
lines changed

web/.eslintrc.cjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ module.exports = {
3131
message: 'CODEBUFF_API_KEY is not allowed in web package. Users must provide their own API key via Authorization header.',
3232
},
3333
],
34+
// Enforce using webEnv instead of env in web package
35+
// webEnv omits CODEBUFF_API_KEY for type-level protection
36+
'no-restricted-imports': [
37+
'error',
38+
{
39+
paths: [
40+
{
41+
name: '@codebuff/internal/env',
42+
importNames: ['env'],
43+
message: "Use 'webEnv' instead of 'env' in web package. webEnv omits CODEBUFF_API_KEY for security.",
44+
},
45+
],
46+
},
47+
],
3448
},
3549
settings: {
3650
tailwindcss: {

web/scripts/discord/register-commands.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { env } from '@codebuff/internal/env'
1+
import { webEnv } from '@codebuff/internal/env'
22
import { REST, Routes, SlashCommandBuilder } from 'discord.js'
33

44
import { logger } from '@/util/logger'
@@ -15,13 +15,13 @@ const commands = [
1515
),
1616
]
1717

18-
const rest = new REST().setToken(env.DISCORD_BOT_TOKEN)
18+
const rest = new REST().setToken(webEnv.DISCORD_BOT_TOKEN)
1919

2020
async function main() {
2121
try {
2222
logger.info('Started refreshing application (/) commands.')
2323

24-
await rest.put(Routes.applicationCommands(env.DISCORD_APPLICATION_ID), {
24+
await rest.put(Routes.applicationCommands(webEnv.DISCORD_APPLICATION_ID), {
2525
body: commands,
2626
})
2727

web/src/app/api/auth/[...nextauth]/auth-options.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { generateCompactId } from '@codebuff/common/util/string'
88
import { loops } from '@codebuff/internal'
99
import db from '@codebuff/internal/db'
1010
import * as schema from '@codebuff/internal/db/schema'
11-
import { env } from '@codebuff/internal/env'
11+
import { webEnv } from '@codebuff/internal/env'
1212
import { stripeServer } from '@codebuff/internal/util/stripe'
1313
import { logSyncFailure } from '@codebuff/internal/util/sync-failure'
1414
import { eq } from 'drizzle-orm'
@@ -46,14 +46,14 @@ async function createAndLinkStripeCustomer(params: {
4646
// Create subscription with the usage price
4747
await stripeServer.subscriptions.create({
4848
customer: customer.id,
49-
items: [{ price: env.STRIPE_USAGE_PRICE_ID }],
49+
items: [{ price: webEnv.STRIPE_USAGE_PRICE_ID }],
5050
})
5151

5252
await db
5353
.update(schema.user)
5454
.set({
5555
stripe_customer_id: customer.id,
56-
stripe_price_id: env.STRIPE_USAGE_PRICE_ID,
56+
stripe_price_id: webEnv.STRIPE_USAGE_PRICE_ID,
5757
})
5858
.where(eq(schema.user.id, userId))
5959

@@ -137,8 +137,8 @@ export const authOptions: NextAuthOptions = {
137137
}) as Adapter,
138138
providers: [
139139
GitHubProvider({
140-
clientId: env.CODEBUFF_GITHUB_ID,
141-
clientSecret: env.CODEBUFF_GITHUB_SECRET,
140+
clientId: webEnv.CODEBUFF_GITHUB_ID,
141+
clientSecret: webEnv.CODEBUFF_GITHUB_SECRET,
142142
}),
143143
],
144144
session: {

web/src/app/api/auth/cli/code/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { genAuthCode } from '@codebuff/common/util/credentials'
22
import db from '@codebuff/internal/db'
33
import * as schema from '@codebuff/internal/db/schema'
4-
import { env } from '@codebuff/internal/env'
4+
import { webEnv } from '@codebuff/internal/env'
55
import { and, eq, gt } from 'drizzle-orm'
66
import { NextResponse } from 'next/server'
77
import { z } from 'zod/v4'
@@ -25,7 +25,7 @@ export async function POST(req: Request) {
2525
const fingerprintHash = genAuthCode(
2626
fingerprintId,
2727
expiresAt.toString(),
28-
env.NEXTAUTH_SECRET,
28+
webEnv.NEXTAUTH_SECRET,
2929
)
3030

3131
// Check if this fingerprint has any active sessions
@@ -56,7 +56,7 @@ export async function POST(req: Request) {
5656
}
5757

5858
// Generate login URL without modifying the fingerprint record
59-
const loginUrl = `${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/login?auth_code=${fingerprintId}.${expiresAt}.${fingerprintHash}${
59+
const loginUrl = `${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/login?auth_code=${fingerprintId}.${expiresAt}.${fingerprintHash}${
6060
referralCode ? `&referral_code=${referralCode}` : ''
6161
}`
6262

web/src/app/api/auth/cli/status/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { genAuthCode } from '@codebuff/common/util/credentials'
22
import db from '@codebuff/internal/db'
33
import * as schema from '@codebuff/internal/db/schema'
4-
import { env } from '@codebuff/internal/env'
4+
import { webEnv } from '@codebuff/internal/env'
55
import { and, eq, gt, or, isNull } from 'drizzle-orm'
66
import { NextResponse } from 'next/server'
77
import { z } from 'zod/v4'
@@ -45,7 +45,7 @@ export async function GET(req: Request) {
4545
const expectedHash = genAuthCode(
4646
fingerprintId,
4747
expiresAt.toString(),
48-
env.NEXTAUTH_SECRET,
48+
webEnv.NEXTAUTH_SECRET,
4949
)
5050
if (fingerprintHash !== expectedHash) {
5151
logger.info(

web/src/app/api/orgs/[orgId]/billing/setup/route.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { pluralize } from '@codebuff/common/util/string'
22
import db from '@codebuff/internal/db'
33
import * as schema from '@codebuff/internal/db/schema'
4-
import { env } from '@codebuff/internal/env'
4+
import { webEnv } from '@codebuff/internal/env'
55
import { stripeServer } from '@codebuff/internal/util/stripe'
66
import { eq, and, sql } from 'drizzle-orm'
77
import { NextResponse } from 'next/server'
@@ -190,13 +190,13 @@ export async function POST(req: NextRequest, { params }: RouteParams) {
190190
mode: 'subscription',
191191
line_items: [
192192
{
193-
price: env.STRIPE_TEAM_FEE_PRICE_ID,
193+
price: webEnv.STRIPE_TEAM_FEE_PRICE_ID,
194194
quantity: seatCount,
195195
},
196196
],
197197
allow_promotion_codes: true,
198-
success_url: `${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}/billing/purchase?subscription_success=true`,
199-
cancel_url: `${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}?subscription_canceled=true`,
198+
success_url: `${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}/billing/purchase?subscription_success=true`,
199+
cancel_url: `${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}?subscription_canceled=true`,
200200
metadata: {
201201
organization_id: orgId,
202202
type: 'subscription_setup',

web/src/app/api/orgs/[orgId]/billing/status/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import db from '@codebuff/internal/db'
22
import * as schema from '@codebuff/internal/db/schema'
3-
import { env } from '@codebuff/internal/env'
3+
import { webEnv } from '@codebuff/internal/env'
44
import { stripeServer } from '@codebuff/internal/util/stripe'
55
import { eq, and, sql } from 'drizzle-orm'
66
import { NextResponse } from 'next/server'
@@ -76,7 +76,7 @@ export async function GET(req: NextRequest, { params }: RouteParams) {
7676
// Create billing portal session
7777
const portalSession = await stripeServer.billingPortal.sessions.create({
7878
customer: organization.stripe_customer_id,
79-
return_url: `${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}/settings`,
79+
return_url: `${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}/settings`,
8080
})
8181
billingPortalUrl = portalSession.url
8282

web/src/app/api/orgs/[orgId]/credits/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { CREDIT_PRICING } from '@codebuff/common/old-constants'
33
import { generateCompactId } from '@codebuff/common/util/string'
44
import db from '@codebuff/internal/db'
55
import * as schema from '@codebuff/internal/db/schema'
6-
import { env } from '@codebuff/internal/env'
6+
import { webEnv } from '@codebuff/internal/env'
77
import { stripeServer } from '@codebuff/internal/util/stripe'
88
import { and, eq } from 'drizzle-orm'
99
import { NextResponse } from 'next/server'
@@ -231,8 +231,8 @@ export async function POST(request: NextRequest, { params }: RouteParams) {
231231
}
232232

233233
// Fall back to checkout session if direct charge failed or no valid payment method
234-
const successUrl = `${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}?purchase_success=true`
235-
const cancelUrl = `${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}?purchase_canceled=true`
234+
const successUrl = `${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}?purchase_success=true`
235+
const cancelUrl = `${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/orgs/${organization.slug}?purchase_canceled=true`
236236

237237
const checkoutSession = await stripeServer.checkout.sessions.create({
238238
payment_method_types: ['card', 'link'],

web/src/app/api/orgs/[orgId]/monitoring/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { calculateOrganizationUsageAndBalance } from '@codebuff/billing'
22
import db from '@codebuff/internal/db'
33
import * as schema from '@codebuff/internal/db/schema'
4-
import { env } from '@codebuff/internal/env'
4+
import { webEnv } from '@codebuff/internal/env'
55
import { eq, and, gte, sql } from 'drizzle-orm'
66
import { NextResponse } from 'next/server'
77
import { getServerSession } from 'next-auth'
@@ -143,7 +143,7 @@ export async function GET(
143143

144144
// Get alerts count
145145
const alertsResponse = await fetch(
146-
`${env.NEXT_PUBLIC_CODEBUFF_APP_URL}/api/orgs/${orgId}/alerts`,
146+
`${webEnv.NEXT_PUBLIC_CODEBUFF_APP_URL}/api/orgs/${orgId}/alerts`,
147147
{
148148
headers: {
149149
Cookie: request.headers.get('Cookie') || '',

web/src/app/api/orgs/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import db from '@codebuff/internal/db'
22
import * as schema from '@codebuff/internal/db/schema'
3-
import { env } from '@codebuff/internal/env'
3+
import { webEnv } from '@codebuff/internal/env'
44
import { stripeServer } from '@codebuff/internal/util/stripe'
55
import { eq, and } from 'drizzle-orm'
66
import { NextResponse } from 'next/server'
@@ -169,7 +169,7 @@ export async function POST(request: NextRequest) {
169169

170170
// Create Stripe customer if needed
171171
let stripeCustomerId = null
172-
if (env.STRIPE_SECRET_KEY) {
172+
if (webEnv.STRIPE_SECRET_KEY) {
173173
try {
174174
const customer = await stripeServer.customers.create({
175175
name: newOrg.name,

0 commit comments

Comments
 (0)