Files
B2BCall-dialer/packages/auth/src/audit.ts
Matheus 70c5586595 feat: implement authentication and RBAC
- packages/auth: Argon2id password hashing, JWT access tokens (jose),
  opaque refresh tokens with rotation, generic error messages (no
  user-enumeration via timing or message differences)
- roles/permissions/role_permissions/user_roles/sessions/audit_logs schema
  (agente.md secoes 142-150); RBAC scope PLATFORM vs TENANT
- withUserContext(): narrow RLS exception so a user can discover their own
  tenant_memberships before a tenant is chosen (login flow)
- userHasPermission()/isPlatformUser(): explicit service-layer RBAC checks
  (roles/permissions tables are not RLS-protected — documented why in
  docs/AUTHENTICATION.md)
- seed: permission catalog, 4 system roles, initial Platform Super Admin
  (password written once to FIRST_LOGIN.txt, 600, outside Git)
- automated end-to-end test: login, RBAC check, refresh rotation, logout
2026-08-28 05:58:49 -03:00

30 lines
775 B
TypeScript

import type { Prisma, PrismaClient } from "@b2bcall/database";
export interface AuditEvent {
action: string;
tenantId?: string | null;
userId?: string | null;
entityType?: string;
entityId?: string;
before?: Prisma.InputJsonValue;
after?: Prisma.InputJsonValue;
ipAddress?: string;
userAgent?: string;
}
export async function recordAuditEvent(prisma: PrismaClient, event: AuditEvent): Promise<void> {
await prisma.auditLog.create({
data: {
action: event.action,
tenantId: event.tenantId ?? null,
userId: event.userId ?? null,
entityType: event.entityType,
entityId: event.entityId,
before: event.before,
after: event.after,
ipAddress: event.ipAddress,
userAgent: event.userAgent,
},
});
}