Skip to content

refactor: make kv redis optional#326

Open
drankou wants to merge 1 commit into
mainfrom
make-redis-optional-for-local-development-eng-3976
Open

refactor: make kv redis optional#326
drankou wants to merge 1 commit into
mainfrom
make-redis-optional-for-local-development-eng-3976

Conversation

@drankou
Copy link
Copy Markdown

@drankou drankou commented May 14, 2026

@vercel/kv redis is now optional for the dashboard. The app boots and runs core auth + dashboard flows without KV_REST_API_URL / KV_REST_API_TOKEN configured.

@cla-bot cla-bot Bot added the cla-signed label May 14, 2026
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 14, 2026

ENG-3976

@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
web Ready Ready Preview, Comment May 14, 2026 1:59pm
web-juliett Ready Ready Preview, Comment May 14, 2026 1:59pm

Request Review

@drankou drankou marked this pull request as ready for review May 14, 2026 14:41
@drankou drankou requested a review from ben-fornefeld as a code owner May 14, 2026 14:41
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71068a7bcd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/env.ts
Comment on lines 4 to +5
SUPABASE_SERVICE_ROLE_KEY: z.string().min(1),
KV_REST_API_TOKEN: z.string().min(1),
KV_REST_API_URL: z.url(),
KV_REST_API_TOKEN: z.string().min(1).optional(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Treat blank KV env vars as absent

When a deployment or local .env.local still contains the old KV_REST_API_URL= / KV_REST_API_TOKEN= entries with blank values, these fields are present as empty strings, so serverSchema rejects them before the new optional KV logic can run. That makes bun run dev/prebuild fail even though the runtime helper treats empty KV values as not_configured, so existing environments copied from the previous .env.example cannot actually opt out without deleting the variables entirely.

Useful? React with 👍 / 👎.

Comment on lines +117 to +120
context: {
email: validationResult.address,
reason: warnedAlternateEmail.reason,
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: MEDIUM

The new KV-unavailable warning path logs raw user emails via context.email (validationResult.address). This introduces direct PII logging for signup attempts whenever KV is not configured or temporarily failing.

Impact: Email addresses can be exposed through centralized log pipelines and wider operator access beyond the primary auth data path.

Comment thread scripts/check-app-env.ts
Comment on lines +9 to +15
.refine(
(data) => Boolean(data.KV_REST_API_URL) === Boolean(data.KV_REST_API_TOKEN),
{
message: 'KV_REST_API_URL and KV_REST_API_TOKEN must be set together',
path: ['KV_REST_API_URL'],
}
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 The new KV .refine block sets path: ['KV_REST_API_URL'] only, but validates a two-variable invariant. When an operator sets KV_REST_API_URL but forgets KV_REST_API_TOKEN (or vice versa), Zod's prettifyError will attribute the failure to KV_REST_API_URL — potentially the var that was actually set correctly. The two other refines in this same file (billing, captcha) list both fields in the path; fix is path: ['KV_REST_API_URL', 'KV_REST_API_TOKEN'].

Extended reasoning...

What the bug is

In scripts/check-app-env.ts:9-15, the new refine validates the together-or-neither invariant for KV configuration:

.refine(
  (data) => Boolean(data.KV_REST_API_URL) === Boolean(data.KV_REST_API_TOKEN),
  {
    message: 'KV_REST_API_URL and KV_REST_API_TOKEN must be set together',
    path: ['KV_REST_API_URL'],
  }
)

The check inspects two environment variables, but the issue path references only one. When the predicate fails, the path Zod surfaces points at KV_REST_API_URL regardless of which side of the pair was actually omitted.

Why this is inconsistent

The two other paired-variable refines added to this same file follow the opposite convention — they list both fields in path:

  • Billing refine (lines 26-30): path: ['BILLING_API_URL', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY']
  • Captcha refine (lines 42-46): path: ['NEXT_PUBLIC_TURNSTILE_SITE_KEY', 'TURNSTILE_SECRET_KEY']

So the new KV refine deviates from a convention already established in the same file.

Concrete proof / step-by-step

  1. Operator sets KV_REST_API_URL=https://kv.example.com in .env.local but forgets KV_REST_API_TOKEN.
  2. CI runs bun run check:env (or whatever invokes this script).
  3. Boolean(data.KV_REST_API_URL) === Boolean(data.KV_REST_API_TOKEN)true === falsefalse. Refine emits an issue with path: ['KV_REST_API_URL'].
  4. validateEnv calls z.prettifyError(parsed.error) (see src/lib/env.ts:73), which formats issues using their path as the field label.
  5. The output points the operator at KV_REST_API_URL — the variable they did set correctly — even though the missing one is KV_REST_API_TOKEN.

The full message text still names both vars, so a careful reader can recover. But the path label is misleading in CI/build logs, and exactly inverts what's useful when half the pair is set.

Addressing the refutation

One verifier objected that listing two strings in path is itself an imprecise use of Zod's API (since path semantically represents a nested object path, not a list of offending fields), so the new code isn't strictly worse — just different. That's a fair critique of the broader pattern, but the practical prettifyError output for a top-level schema renders path joined as a label, so listing both fields does produce a more useful pointer to the operator than listing just one. More importantly, the value here is consistency within the file: the rest of the file uses the two-element form, so a future reader scanning the refines will expect the same shape. The fix is one line and aligns with the established pattern.

Severity & fix

Nit. The script still fails the build with a message naming both vars, so no operator is truly stuck. Fix:

path: ['KV_REST_API_URL', 'KV_REST_API_TOKEN'],

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant