feat: Staff Impersonation backend + frontend wiring (#75)
* feat: implement Staff Impersonation backend and wire frontend Add server-side impersonation session management with full audit logging, replacing the frontend-only mock. Managers can start time-limited sessions to view the app as a specific client. Backend: - Add impersonation_sessions and impersonation_audit_logs tables (Drizzle schema) with proper FK constraints and status enum - Add Hono API routes: start/get/extend/end session + audit logging - Server-side session expiration, one-active-per-staff enforcement - Staff role validation (manager-only) Frontend: - Add CustomerPortal wrapper with URL-param session init - Add ImpersonationBanner with live countdown timer - Add AuditLogViewer modal for session audit trail - Add "View as Customer" button on Clients page - Auto-log page visits during impersonation Closes #74 Co-Authored-By: Paperclip <noreply@paperclip.ing> * chore: remove unused useNavigate import from Clients.tsx Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add authorization + expiry checks to impersonation endpoints, add tests Security: Add ownership verification (resolveStaff + staffId check) to GET /sessions/:id, POST /sessions/:id/log, and GET /sessions/:id/audit-log endpoints that were previously unprotected. Bug: Add time-based expiry checks to extend, end, get-session, and log endpoints via checkAndExpireSession() helper. Expired sessions are now auto-marked as expired in the DB and cannot be extended or logged to. Tests: Add 23 tests covering session creation (happy path, auth, conflict), extend (active, expired, non-owner, ended), end (active, expired, non-owner), audit logging (owner, non-owner, expired, ended), and audit-log retrieval (owner, non-owner, not found). Addresses QA review on PR #75 (GRO-66). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve @groombook/db source in vitest config Add resolve alias so vitest can resolve @groombook/db from source TypeScript files without requiring a prior build step. Fixes CI test failures when dist/ has not been compiled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Groom Book CEO <ceo@groombook.dev> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Groom Book CTO <cto@groombook.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Scrubs McBarkley <scrubs@groombook.app>
This commit was merged in pull request #75.
This commit is contained in:
committed by
GitHub
parent
ea5450651d
commit
70958542f8
@@ -149,6 +149,31 @@ export interface Invoice {
|
||||
tipSplits?: InvoiceTipSplit[];
|
||||
}
|
||||
|
||||
// ─── Impersonation ──────────────────────────────────────────────────────────
|
||||
|
||||
export type ImpersonationSessionStatus = "active" | "ended" | "expired";
|
||||
|
||||
export interface ImpersonationSession {
|
||||
id: string;
|
||||
staffId: string;
|
||||
clientId: string;
|
||||
reason: string | null;
|
||||
status: ImpersonationSessionStatus;
|
||||
startedAt: string;
|
||||
endedAt: string | null;
|
||||
expiresAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ImpersonationAuditLog {
|
||||
id: string;
|
||||
sessionId: string;
|
||||
action: string;
|
||||
pageVisited: string | null;
|
||||
metadata: Record<string, unknown> | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface BusinessSettings {
|
||||
id: string;
|
||||
businessName: string;
|
||||
|
||||
Reference in New Issue
Block a user