chahinebrini 76f8595a4f feat(backend): lyra voice picker for legend (mvp)
- profile.ts: Whitelist (null | iFSsEDGbm0FiEd2IVH4w | Gt7OshJCH7MuzX96wFHi) + setLyraVoiceId()
- profile/me/lyra-voice.patch.ts: neuer Endpoint, Legend-Gate (403 legend_only),
  Validation gegen Whitelist (400 invalid_voice_id). DB-Wert bleibt bei Plan-Downgrade.
- coach/speak.post.ts: ElevenLabs-Voice-Prioritätskette nimmt userLyraVoiceId
  zuerst (nur wenn plan === legend), sonst voiceCfg / config / env / FALLBACK.
- auth/me.get.ts: lyraVoiceId in der Profile-Response damit Frontend hydriert.

Schema-Feld lyraVoiceId existiert bereits aus migration
20260507_profile_demographics_and_trial — keine neue Migration nötig.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 22:15:42 +02:00

42 lines
1.4 KiB
TypeScript

import { getProfile } from "../../db/profile";
import { getPlanLimits } from "../../utils/plan-features";
export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const dbProfile = await getProfile(user.id);
const plan = (dbProfile?.plan === "premium"
? "legend"
: dbProfile?.plan === "standard"
? "pro"
: dbProfile?.plan ?? "free") as "free" | "pro" | "legend";
const limits = getPlanLimits(plan);
return {
id: user.id,
email: user.email,
username: dbProfile?.username ?? "",
nickname: dbProfile?.nickname ?? null,
avatar: dbProfile?.avatar ?? null,
plan,
foundingMember: dbProfile?.foundingMember ?? false,
streak: dbProfile?.streak ?? 0,
lyraVoiceId: dbProfile?.lyraVoiceId ?? null,
created_at: dbProfile?.createdAt?.toISOString() ?? user.created_at,
// Für useUserPlan im Frontend — Key-Subset der PlanLimits
planLimits: {
customDomains: limits.customDomains,
domainRefill: limits.domainRefill,
mailAgents: limits.mailAgents === Infinity ? null : limits.mailAgents,
globalBlocklist: limits.globalBlocklist,
maxAppDevices: limits.maxAppDevices,
maxProtectedDevices: limits.maxProtectedDevices,
canCreateGroup: limits.canCreateGroup,
canAddToBlocklist: limits.canAddToBlocklist,
},
globalBlocklistGraceUntil:
dbProfile?.globalBlocklistGraceUntil?.toISOString() ?? null,
};
});