Files
tiennm99 10a3693f1b fix(scaffold): apply phase-0 review findings
- env: cross-check VERCEL_ENV against NEXT_PUBLIC_APP_ENV at boot so prod
  credentials cannot silently write into a dev keyspace
- upstash: tighten cache-key regex (kebab + colon only); split SCAN
  patterns into their own validator so glob '*' is allowed only there
- eslint: forbid raw @upstash/redis, @upstash/ratelimit, @supabase/supabase-js
  imports outside the named factory files
- supabase/admin: harmonize 'use cache' guidance with CONTRIBUTING.md
  (safe inside cache; partition key on identity for user-specific reads)
- app/layout: clarify global-error.tsx vs error.tsx shell requirements
  given the passthrough root layout
- readme: Next.js 15 -> 16 (matches scaffolded version)
2026-05-25 15:56:54 +07:00

25 lines
1005 B
TypeScript

import "server-only";
import { createClient } from "@supabase/supabase-js";
import { serverEnv, SUPABASE_SCHEMA } from "@/lib/env/server";
/**
* Privileged Supabase client (uses the secret key, bypasses RLS on behalf of no user).
* Use only for admin tasks: invites, cron sweeps, system writes.
* NEVER expose this client to the browser.
*
* `'use cache'` interaction: this factory does NOT read cookies, so it is safe
* to call inside a cached scope. But if the result depends on a caller's identity
* (user / role / tenant), the cache key MUST partition on that identity — otherwise
* one user sees another user's data. For genuinely user-agnostic reads (e.g.
* clinic settings, services list), no key partitioning is needed.
*/
export function createSupabaseAdminClient() {
return createClient(serverEnv.NEXT_PUBLIC_SUPABASE_URL, serverEnv.SUPABASE_SECRET_KEY, {
db: { schema: SUPABASE_SCHEMA },
auth: {
persistSession: false,
autoRefreshToken: false,
},
});
}