mirror of
https://github.com/hanzo-apps/dataroom.git
synced 2026-10-30 14:47:36 +00:00
@vercel/edge-config read NOTHING in production. EDGE_CONFIG is unset on this deployment, so every `get()` threw, and every call site caught it and fell back to an empty default. Several of them additionally checked `process.env. EDGE_CONFIG` and returned early, so the fallback was not even a fallback — it was the only path. What that meant, live: emails / keywords the blacklist matched nothing — abuse filtering was off trustedTeams no team was ever trusted betaFeatures no beta feature was ever on customEmail no team ever got its own sender address lib/config.ts reads these from Hanzo KV under a `config:` prefix, so a value changes with a KV write rather than a deploy — which is the reason the app reached for an edge config service to begin with. Reads never throw: a KV outage returns the caller's fallback, exactly as these call sites already assumed, so config can never take down a request path. customEmail is a Record, not a list, and now says so — it was being read through the list helper, which would have discarded it. @vercel/functions and @vercel/edge-config have no importers left and are dropped from package.json; the lockfile is regenerated and `npm ci --dry-run` is clean. @vercel/blob still has 10 importers and stays until storage moves to S3. Verified with npx tsc --noEmit: 100 errors before and after. Co-authored-by: Hanzo Dev <[email protected]>
44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import { kv } from "@/lib/kv";
|
|
|
|
/**
|
|
* Operational config — the lists and flags that change without a deploy.
|
|
*
|
|
* This replaces @vercel/edge-config, which in production read nothing: EDGE_CONFIG
|
|
* is unset on this deployment, so every `get()` threw and each call site caught it
|
|
* and fell back to an empty default. That is why no team was ever trusted, no beta
|
|
* feature was ever on, and the email/keyword blacklist matched nothing — abuse
|
|
* filtering has been silently off.
|
|
*
|
|
* Hanzo KV is the store, under a `config:` prefix, so a value is changed with a
|
|
* KV write instead of a deploy — which is the whole reason the app reached for an
|
|
* edge config service.
|
|
*
|
|
* Reads never throw. A KV outage returns the fallback, exactly as the old callers
|
|
* assumed, so a config lookup can never take down a request path.
|
|
*/
|
|
|
|
export type ConfigKey =
|
|
| "betaFeatures"
|
|
| "customEmail"
|
|
| "emails"
|
|
| "keywords"
|
|
| "trustedTeams";
|
|
|
|
export async function getConfig<T>(key: ConfigKey, fallback: T): Promise<T> {
|
|
try {
|
|
const value = await kv.get<T>(`config:${key}`);
|
|
return value ?? fallback;
|
|
} catch (error) {
|
|
console.error(`[config] could not read ${key}`, error);
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
/** A list of strings, with anything else in the value discarded. */
|
|
export async function getStringList(key: ConfigKey): Promise<string[]> {
|
|
const value = await getConfig<unknown>(key, []);
|
|
return Array.isArray(value)
|
|
? value.filter((item): item is string => typeof item === "string")
|
|
: [];
|
|
}
|