Добавить контракт изменений деталей аудита

Детали событий описываются списком изменений «параметр: было → стало» (AuditChangeDto, AuditDetails), а не произвольным JSON. Запись везде идёт через конструктор AuditDetails; разбор старого плоского формата сохранён. Операторские ручки аудита отдают AuditRecordViewDto с changes и именем пользователя (батч-резолв через ITenantRepository.FindNamesByIdsAsync). Детектор подозрительной активности читает логин через новый разбор.
This commit is contained in:
2026-09-13 19:17:57 +03:00
parent 585397b9a3
commit 02a4f9c749
26 changed files with 407 additions and 94 deletions
@@ -94,7 +94,7 @@ public static class ContainersEndpoints
Note: body.Note ?? string.Empty),
ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerCreated, new { id = created.Id, name = created.Name }, ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerCreated, [AuditDetails.Set("containerId", created.Id), AuditDetails.Set("name", created.Name)], ct);
return Results.Ok(new { id = created.Id });
}
@@ -153,7 +153,7 @@ public static class ContainersEndpoints
patchBody.Policy),
ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerUpdated, new { id = updated.Id }, ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerUpdated, [AuditDetails.Set("containerId", updated.Id)], ct);
return Results.Ok(new { id = updated.Id });
}
@@ -171,7 +171,7 @@ public static class ContainersEndpoints
ContainersService containers = context.RequestServices.GetRequiredService<ContainersService>();
ContainerDto accepted = await containers.AcceptSuggestedAsync(containerId, ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerUpdated, new { id = accepted.Id }, ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerUpdated, [AuditDetails.Set("containerId", accepted.Id)], ct);
return Results.Ok(accepted);
}
@@ -189,7 +189,7 @@ public static class ContainersEndpoints
ContainersService containers = context.RequestServices.GetRequiredService<ContainersService>();
int moved = await containers.DeleteAsync(containerId, ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerDeleted, new { id = containerId }, ct);
await AuditAppender.AppendTenantAsync(context, AuditEvents.ContainerDeleted, [AuditDetails.Set("containerId", containerId)], ct);
return Results.Ok(new { ok = true, movedToInbox = moved });
}