evOo-local/packages/core/src/signup-policy.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

45 lines
1.5 KiB
TypeScript

export function parseAllowlist(raw: string | undefined): string[] {
if (!raw) return [];
return raw
.split(",")
.map((item) => item.trim().toLowerCase())
.filter(Boolean);
}
export function emailAllowed(email: string, allowlist: string[]): boolean {
if (allowlist.length === 0) return true;
const normalized = email.trim().toLowerCase();
const domain = normalized.split("@")[1];
return allowlist.some((entry) => {
if (entry.startsWith("@")) return domain === entry.slice(1);
return normalized === entry;
});
}
/** Internal messaging users have no mailbox and cannot authenticate by email. */
export function isMessagingEmail(email: string): boolean {
return email.trim().toLowerCase().endsWith("@messaging.invalid");
}
/** A successful signup with an explicit null token awaits mailbox proof. */
export function signupRequiresEmailVerification(response: unknown): boolean {
return Boolean(
response && typeof response === "object" && "token" in response && response.token === null,
);
}
export function signupsOpen(enabled: string | undefined): boolean {
if (enabled === undefined) return true;
return enabled !== "false" && enabled !== "0";
}
export function signupPolicyFromEnv(input: {
signupsEnabled: string | undefined;
signupAllowlist: string | undefined;
}): { enabled: boolean; allowlist: string[] } {
return {
enabled: signupsOpen(input.signupsEnabled),
allowlist: parseAllowlist(input.signupAllowlist),
};
}