feat: Phase 1 - Implementation of Data Security Infrastructure

Implemented comprehensive data security infrastructure for SFERA platform:

## Security Classes Created:
- `SupplyDataFilter`: Role-based data filtering for supply orders
- `ParticipantIsolation`: Data isolation between competing organizations
- `RecipeAccessControl`: Protection of production recipes and trade secrets
- `CommercialDataAudit`: Audit logging and suspicious activity detection
- `SecurityLogger`: Centralized security event logging system

## Infrastructure Components:
- Feature flags system for gradual security rollout
- Database migrations for audit logging (AuditLog, SecurityAlert models)
- Secure resolver wrapper for automatic GraphQL security
- TypeScript interfaces and type safety throughout

## Security Features:
- Role-based access control (SELLER, WHOLESALE, FULFILLMENT, LOGIST)
- Commercial data protection between competitors
- Production recipe confidentiality
- Audit trail for all data access
- Real-time security monitoring and alerts
- Rate limiting and suspicious activity detection

## Implementation Notes:
- All console logging replaced with centralized security logger
- Comprehensive TypeScript typing with no explicit 'any' types
- Modular architecture following SFERA coding standards
- Feature flag controlled rollout for safe deployment

This completes Phase 1 of the security implementation plan.
Next phases will integrate these classes into existing GraphQL resolvers.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Veronika Smirnova
2025-08-22 17:51:02 +03:00
parent e7e4889102
commit 6e3201f491
20 changed files with 5671 additions and 66 deletions

View File

@ -54,20 +54,20 @@ graph TD
**GraphQL мутация подтверждения поставщиком:**
```graphql
# Поставщик может указать детали упаковки при подтверждении
# Поставщик указывает детали упаковки при одобрении (опционально)
mutation SupplierApproveOrderWithPackaging($id: ID!, $packagesCount: Int, $volume: Float) {
supplierApproveOrderWithPackaging(
id: $id
packagesCount: $packagesCount # Количество грузовых мест
volume: $volume # Объём в м³ (влияет на логистические тарифы)
packagesCount: $packagesCount # Опционально: количество грузовых мест
volume: $volume # Опционально: объём в м³ для расчета логистических тарифов
) {
success
message
order {
id
status
packagesCount
volume
packagesCount # null если не указано
volume # null если не указано
}
}
}
@ -247,6 +247,211 @@ createSupplyOrder(input: {
**Обработка входящих заказов:**
```typescript
// Поставщик получает заказы где он является поставщиком
const supplierOrders = await prisma.supplyOrder.findMany({
where: {
partnerId: currentUser.organization.id, // Мы - поставщик
status: 'PENDING', // Ожидает подтверждения
},
})
```
**Действия поставщика:**
```graphql
# Одобрение заказа
mutation SupplierApproveOrder($orderId: ID!) {
supplierApproveOrder(id: $orderId) {
success
order {
id
status
} # PENDING → SUPPLIER_APPROVED
}
}
# Отклонение заказа
mutation SupplierRejectOrder($orderId: ID!, $reason: String) {
supplierRejectOrder(id: $orderId, reason: $reason) {
success
message
}
}
# Отгрузка товара (после подтверждения логистики)
mutation SupplierShipOrder($orderId: ID!) {
supplierShipOrder(id: $orderId) {
success
order {
id
status
} # LOGISTICS_CONFIRMED → SHIPPED
}
}
```
**Компоненты поставщика:**
```typescript
// Техническая реализация кабинета поставщика
src/components/supplier-orders/
├── supplier-orders-dashboard.tsx # Главный dashboard
├── supplier-order-card.tsx # Карточка заказа
├── supplier-orders-tabs.tsx # Табы по статусам
├── supplier-orders-search.tsx # Поиск и фильтры
└── supplier-order-stats.tsx # Статистика заказов
```
**Возможности:**
- ✅ Просматривать входящие заказы (PENDING)
- ✅ Одобрять заказы (PENDING → SUPPLIER_APPROVED)
- ✅ Отклонять заказы (PENDING → CANCELLED)
- ✅ Отгружать товары (LOGISTICS_CONFIRMED → SHIPPED)
- ❌ Изменять детали заказа после создания
- ❌ Видеть заказы других поставщиков
## 🚨 КРИТИЧЕСКИЕ ПРОБЛЕМЫ WORKFLOW
### ВЫЯВЛЕННЫЕ ПРОБЛЕМЫ В ЦЕПОЧКЕ ПОСТАВОК:
#### ❌ **ПРОБЛЕМА 1: Неправильное отображение статусов у поставщика**
```typescript
// ПРОБЛЕМА: Поставщик видит "ожидает подтверждения" вместо только кнопок
// РЕШЕНИЕ: Показывать только кнопки действий, скрывать статусы
// Текущий код (неправильно):
<StatusBadge status={order.status} />
<ActionButtons />
// Правильный код:
{user?.organization?.type === 'WHOLESALE' ? (
<ActionButtons only /> // Только кнопки, без статуса
) : (
<StatusBadge status={order.status} />
)}
```
#### ❌ **ПРОБЛЕМА 2: Отсутствие полей ввода у поставщика**
```typescript
// ПРОБЛЕМА: Поставщик не может указать важные данные при одобрении
interface SupplierPackagingFields {
packagesCount?: number // ОПЦИОНАЛЬНО: Количество грузовых мест
volume?: number // ОПЦИОНАЛЬНО: Объем груза для логистических расчетов
readyDate?: DateTime // ОПЦИОНАЛЬНО: Дата готовности к отгрузке
notes?: string // ОПЦИОНАЛЬНО: Комментарии для логистики
}
// ТРЕБОВАНИЯ:
// ✅ Поля НЕ обязательные - заказ можно одобрить без них
// ✅ Показываются сразу при одобрении для удобства заполнения
// ✅ Используются логистикой для расчета тарифов и планирования
// ✅ Отображаются на 1-м уровне визуализации поставки
// РЕШЕНИЕ: Расширить мутацию supplierApproveOrder
mutation SupplierApproveOrder($input: SupplierApprovalInput!) {
supplierApproveOrder(input: $input) {
success
order {
id, status, packagesCount, volume, readyDate, notes
}
}
}
```
#### ❌ **ПРОБЛЕМА 3: Конфликт статусов в приемке фулфилмента**
```typescript
// КРИТИЧЕСКАЯ ОШИБКА: Резолвер ожидает SHIPPED, но получает SUPPLIER_APPROVED
if (supplyOrder.status !== 'SHIPPED') {
return {
success: false,
message: 'Заказ должен быть в статусе SHIPPED для приемки', // ❌ БЛОКИРУЕТ ПРОЦЕСС
}
}
// РЕШЕНИЕ: Исправить проверку статуса
if (!['SUPPLIER_APPROVED', 'LOGISTICS_CONFIRMED'].includes(supplyOrder.status)) {
return {
success: false,
message: 'Заказ должен быть одобрен поставщиком для приемки',
}
}
```
#### ❌ **ПРОБЛЕМА 4: Отсутствие уведомлений поставщика**
```typescript
// ПРОБЛЕМА: Поставщик не знает о новых заказах в реальном времени
// РЕШЕНИЕ: Добавить систему уведомлений
interface SupplierNotifications {
newOrder: 'Новый заказ от {sellerName} на сумму {amount}'
orderCancelled: 'Заказ #{orderNumber} отменен заказчиком'
logistics: 'Логистика подтверждена для заказа #{orderNumber}'
}
```
### ПЛАН ИСПРАВЛЕНИЯ WORKFLOW:
```typescript
interface WorkflowFixes {
// Фаза 1: UI поставщика
supplierInterface: {
hideStatuses: 'Показывать только кнопки действий'
addFields: 'Поля для packagesCount, volume, readyDate'
realtime: 'Уведомления о новых заказах'
}
// Фаза 2: Backend логика
backendLogic: {
expandMutation: 'Расширить supplierApproveOrder с дополнительными полями'
fixStatusCheck: 'Исправить проверку статусов в fulfillmentReceiveOrder'
notifications: 'Система реалтайм уведомлений'
}
// Фаза 3: Интеграция
integration: {
validation: 'Валидация минимальных количеств заказа'
inventory: 'Проверка доступности товаров у поставщика'
logistics: 'Автоматическое назначение логистики'
}
}
```
### ТРЕБОВАНИЯ К РЕАЛИЗАЦИИ:
```typescript
// 1. Исправленная фильтрация заказов для поставщика
const fixedSupplierFilter = `
if (currentUser.organization.type === 'WHOLESALE') {
whereClause = {
partnerId: currentUser.organization.id, // Мы - поставщик
}
} else {
whereClause = {
organizationId: currentUser.organization.id, // Мы - заказчик
}
}
`
// 2. Правильная обработка статусов
const correctStatusHandling = `
// Поставщик видит только кнопки, без статусов
{userRole === 'WHOLESALE' && status === 'PENDING' && (
<ApproveRejectButtons orderId={order.id} />
)}
// Остальные видят статусы
{userRole !== 'WHOLESALE' && (
<StatusBadge status={status} />
)}
`
```
```typescript
// Из кода resolvers.ts:
const incomingSupplierOrders = await prisma.supplyOrder.count({