Files
craftvia/src/server/services/lotse/chat/access.ts
T
msolarczekandClaude Opus 5 68f4eb32dc L16 Lotse-Chat für Monteure: Datenmodell, Provider mit Tool-Schleife, Vorschläge und Bestätigen über bestehende Services
Chatverlauf (LotseConversation/-Message) und Aktionskarten (LotseActionProposal) als
Mandantentabellen mit RLS; Schalter lotseChatEnabled. Tool-Use-Schleife mit Runden- und
Tokengrenze, Datenminimierung per Platzhalter, Auftragszuordnung im Sichtbarkeits-Scope,
Bestätigen/Verwerfen/Alle bestätigen mit Hash, Ablauf und Idempotenz, Transkriptions-API.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 18:57:20 +02:00

28 lines
1.5 KiB
TypeScript

import { assertCan, can, ServiceError, type ServiceCtx } from "@/server/services/context";
import { isLotseEnabled } from "../settings";
/**
* Gate of the Lotse chat for technicians (lane L16): `lotse:use` + `field:execute`, Lotse module on
* (TenantModule `lotse`) and the tenant switch „Lotse-Chat für Monteure" (TenantSettings.lotseChatEnabled,
* default on). Switched off → `blocked` (reason disabled / chat_disabled).
*/
export async function isLotseChatEnabled(ctx: Pick<ServiceCtx, "db" | "tenantId">): Promise<boolean> {
if (!(await isLotseEnabled(ctx))) return false;
const s = await ctx.db.tenantSettings.findFirst({ select: { lotseChatEnabled: true } });
return s?.lotseChatEnabled ?? true;
}
/** UI convenience: may the user open the chat at all (permissions + switches)? Never a security check. */
export async function canUseLotseChat(ctx: ServiceCtx): Promise<boolean> {
return can(ctx, "lotse:use") && can(ctx, "field:execute") && (await isLotseChatEnabled(ctx));
}
export async function assertLotseChatUsable(ctx: ServiceCtx): Promise<void> {
assertCan(ctx, "lotse:use");
assertCan(ctx, "field:execute");
if (!(await isLotseEnabled(ctx))) throw new ServiceError("blocked", "lotse disabled for tenant", { reason: "disabled" });
const s = await ctx.db.tenantSettings.findFirst({ select: { lotseChatEnabled: true } });
if (s && !s.lotseChatEnabled) throw new ServiceError("blocked", "lotse chat disabled for tenant", { reason: "chat_disabled" });
}