mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 04:32:42 +00:00
fix(coach): enforce the module gate on coach chat and list routes
The streaming POST and the conversation-list GET enforced only the
legacy operator assistant flag (requireAssistantSurface("coach")),
missing the per-user disableCoach opt-out and the operator
module-availability layer. Both handlers now run the two-layer
requireModuleEnabled(userId, "coach") gate right after auth, returning
403 module.disabled when the account has Coach turned off — even with a
valid Bearer token. The legacy assistant-flag check stays in place.
This commit is contained in:
1 parent
00d16ea275
commit
2b5974cf4a
1 file changed
+8
@@ -35,6 +35,7 @@ import { auditLog } from "@/lib/auth/audit";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { checkRateLimit } from "@/lib/rate-limit";
|
||||
import { requireAssistantSurface } from "@/lib/feature-flags";
|
||||
import { requireModuleEnabled } from "@/lib/modules/gate";
|
||||
|
||||
import { resolveServerLocale } from "@/lib/i18n/server-locale";
|
||||
import {
|
||||
@@ -151,6 +152,10 @@ function buildHistoryWindow(
|
||||
|
||||
async function handleChatRequest(request: NextRequest): Promise<Response> {
|
||||
const auth = await requireAuth();
|
||||
// v1.18.0 — two-layer module gate (operator availability + per-user
|
||||
// disableCoach) on top of the legacy assistant flag. 403 module.disabled.
|
||||
const gate = await requireModuleEnabled(auth.user.id, "coach");
|
||||
if (!gate.enabled) return gate.response;
|
||||
// v1.4.31 — operator can disable the Coach surface app-wide.
|
||||
// Throws AssistantDisabledError → apiHandler returns 403 +
|
||||
// `errorCode: "assistant.disabled.coach"` per the iOS contract.
|
||||
@@ -687,6 +692,9 @@ export const POST = apiHandler(handleChatRequest);
|
||||
*/
|
||||
export const GET = apiHandler(async (request: NextRequest) => {
|
||||
const auth = await requireAuth();
|
||||
// v1.18.0 — same two-layer module gate as the SSE POST.
|
||||
const gate = await requireModuleEnabled(auth.user.id, "coach");
|
||||
if (!gate.enabled) return gate.response;
|
||||
// v1.4.31 — same gate as the SSE POST. Hiding the rail when
|
||||
// the operator has disabled Coach matches the FAB suppression
|
||||
// on the client.
|
||||
|
||||
Reference in new issue
Block a user