mirror of
https://github.com/temetro/temetro.git
synced 2026-08-12 03:26:53 +00:00
feat(ai): clinic-wide AI kill-switch (admin-controlled)
- new org_ai_policy table + GET/PUT /api/ai/policy (read for any member, write owner/admin only); migration 0018 - /api/chat hard-blocks (403) when AI is off for the caller - Settings → AI "Availability" section: enable AI, or disable for employees only (owners/admins keep access); read-only for non-admins - sidebar, command palette and route guard hide/redirect the AI chat when it's disabled for the current user Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,3 +12,4 @@ export * from "./notifications.js";
|
||||
export * from "./settings.js";
|
||||
export * from "./ai.js";
|
||||
export * from "./ai-chat.js";
|
||||
export * from "./org-ai-policy.js";
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
|
||||
import { organization } from "./auth.js";
|
||||
|
||||
// Clinic-wide AI availability, controlled by owners/admins. One row per clinic
|
||||
// (organization). Absent row = AI enabled for everyone (the default).
|
||||
// aiEnabled = false → AI hidden + blocked for the whole clinic.
|
||||
// disabledForEmployees = true → AI hidden + blocked for non-admins; owners
|
||||
// and admins keep access.
|
||||
export const orgAiPolicy = pgTable("org_ai_policy", {
|
||||
organizationId: text("organization_id")
|
||||
.primaryKey()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
aiEnabled: boolean("ai_enabled").notNull().default(true),
|
||||
disabledForEmployees: boolean("disabled_for_employees")
|
||||
.notNull()
|
||||
.default(false),
|
||||
updatedAt: timestamp("updated_at")
|
||||
.defaultNow()
|
||||
.$onUpdate(() => new Date())
|
||||
.notNull(),
|
||||
});
|
||||
Reference in New Issue
Block a user