import "server-only"; import { cookies } from "next/headers"; import type { Role, Session } from "./types"; import { store } from "./store"; export const SESSION_COOKIE = "lkc_session"; /** Resolve the current session from the signed demo cookie. */ export async function getSession(): Promise { const jar = await cookies(); const raw = jar.get(SESSION_COOKIE)?.value; if (!raw) return null; try { const parsed = JSON.parse( Buffer.from(raw, "base64url").toString("utf8") ) as Session; const user = store.users.find((u) => u.id === parsed.userId); if (!user || !user.active || user.suspended) return null; return { userId: user.id, username: user.username, name: user.name, role: user.role, }; } catch { return null; } } export function encodeSession(session: Session): string { return Buffer.from(JSON.stringify(session), "utf8").toString("base64url"); } /* ------------------------------------------------------------------ */ /* Permission matrix (SRS ยง3.3) */ /* ------------------------------------------------------------------ */ export type Permission = | "manage_users" | "manage_tokens" | "system_config" | "audit_log" | "xml_export" | "quick_input" | "direct_approval" | "view_pending_queue" | "primary_validate" | "view_editor_approved_queue" | "final_validate" | "escalate" | "arbitration_vote" | "tie_breaker" | "apply_corrections" | "override_state" | "assign_entries" | "bulk_operations" | "search_internal" | "statistics" | "dispute"; const MATRIX: Record = { manage_users: ["PLATFORM_ARCHITECT"], manage_tokens: ["PLATFORM_ARCHITECT"], system_config: ["PLATFORM_ARCHITECT"], audit_log: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR"], xml_export: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR"], quick_input: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "CONTRIBUTOR"], direct_approval: ["SYSTEM_MODERATOR"], view_pending_queue: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "LEXICAL_EDITOR"], primary_validate: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "LEXICAL_EDITOR"], view_editor_approved_queue: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "CHIEF_LEXICAL_EDITOR"], final_validate: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "CHIEF_LEXICAL_EDITOR"], escalate: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "LEXICAL_EDITOR", "CHIEF_LEXICAL_EDITOR"], arbitration_vote: ["ARBITRATION_CURATOR"], tie_breaker: ["SYSTEM_MODERATOR"], apply_corrections: ["SYSTEM_MODERATOR"], override_state: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR"], assign_entries: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR"], bulk_operations: ["PLATFORM_ARCHITECT", "SYSTEM_MODERATOR"], search_internal: [ "PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "CONTRIBUTOR", "LEXICAL_EDITOR", "CHIEF_LEXICAL_EDITOR", "ARBITRATION_CURATOR", ], statistics: [ "PLATFORM_ARCHITECT", "SYSTEM_MODERATOR", "CONTRIBUTOR", "LEXICAL_EDITOR", "CHIEF_LEXICAL_EDITOR", "ARBITRATION_CURATOR", ], dispute: ["CONTRIBUTOR"], }; export function hasPermission( role: Role | null | undefined, permission: Permission ): boolean { if (!role) return false; return MATRIX[permission].includes(role); }