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:
@ -465,8 +465,262 @@ interface WholesaleWorkflowUI {
|
||||
|
||||
> Поставщик **НЕ МОЖЕТ** изменять статусы заказов напрямую, только через бизнес-процессы
|
||||
|
||||
## 💻 ТЕХНИЧЕСКИЕ КОМПОНЕНТЫ КАБИНЕТА
|
||||
|
||||
### АРХИТЕКТУРА КОМПОНЕНТОВ:
|
||||
|
||||
```typescript
|
||||
src/components/
|
||||
├── warehouse/ # Компоненты склада поставщика
|
||||
│ ├── warehouse-dashboard.tsx # Главный dashboard склада
|
||||
│ ├── product-card.tsx # Карточка товара
|
||||
│ ├── product-form.tsx # Форма создания/редактирования товара
|
||||
│ └── warehouse-statistics.tsx # Статистика склада
|
||||
├── supplier-orders/ # Компоненты обработки заказов
|
||||
│ ├── supplier-orders-dashboard.tsx # Главный dashboard заказов
|
||||
│ ├── supplier-order-card.tsx # Карточка заказа
|
||||
│ ├── supplier-orders-tabs.tsx # Табы по статусам заказов
|
||||
│ ├── supplier-orders-search.tsx # Поиск и фильтры
|
||||
│ └── supplier-order-stats.tsx # Статистика заказов
|
||||
└── economics/ # Экономическая аналитика
|
||||
└── wholesale-economics-page.tsx # Финансовая отчетность
|
||||
```
|
||||
|
||||
### СТРАНИЦЫ (NEXT.JS ROUTES):
|
||||
|
||||
```typescript
|
||||
src/app/
|
||||
├── warehouse/
|
||||
│ └── page.tsx # /warehouse - управление складом
|
||||
├── supplier-orders/
|
||||
│ └── page.tsx # /supplier-orders - обработка заказов
|
||||
└── economics/
|
||||
└── page.tsx # /economics - финансовая аналитика
|
||||
```
|
||||
|
||||
## 🛠️ GRAPHQL API ПОСТАВЩИКОВ
|
||||
|
||||
### ОСНОВНЫЕ ЗАПРОСЫ:
|
||||
|
||||
```graphql
|
||||
# Получение товаров поставщика
|
||||
query GetMyProducts {
|
||||
myProducts {
|
||||
id
|
||||
name
|
||||
article
|
||||
price
|
||||
quantity
|
||||
organization {
|
||||
id
|
||||
name
|
||||
market # Физический рынок поставщика
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Получение заказов поставщика
|
||||
query GetSupplierOrders {
|
||||
supplyOrders(where: { partnerId: $myOrgId }) {
|
||||
id
|
||||
status
|
||||
totalAmount
|
||||
organization {
|
||||
name
|
||||
} # Заказчик
|
||||
}
|
||||
}
|
||||
|
||||
# Получение партнеров
|
||||
query GetMyCounterparties {
|
||||
myCounterparties {
|
||||
id
|
||||
name
|
||||
type
|
||||
market
|
||||
fullName
|
||||
inn
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### МУТАЦИИ ОБРАБОТКИ ЗАКАЗОВ:
|
||||
|
||||
```graphql
|
||||
# Одобрение заказа поставщиком
|
||||
mutation SupplierApproveOrder($orderId: ID!) {
|
||||
supplierApproveOrder(id: $orderId) {
|
||||
success
|
||||
order {
|
||||
id
|
||||
status
|
||||
organization {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Отклонение заказа
|
||||
mutation SupplierRejectOrder($orderId: ID!, $reason: String) {
|
||||
supplierRejectOrder(id: $orderId, reason: $reason) {
|
||||
success
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
# Отгрузка заказа
|
||||
mutation SupplierShipOrder($orderId: ID!) {
|
||||
supplierShipOrder(id: $orderId) {
|
||||
success
|
||||
order {
|
||||
id
|
||||
status # SHIPPED -> IN_TRANSIT
|
||||
organization {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Создание товара
|
||||
mutation CreateProduct($input: ProductInput!) {
|
||||
createProduct(input: $input) {
|
||||
success
|
||||
product {
|
||||
id
|
||||
article
|
||||
organization {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ПРАВИЛА ПАРТНЕРСТВА В API:
|
||||
|
||||
```typescript
|
||||
// ✅ ПРАВИЛЬНО: Поставщики берутся ТОЛЬКО из партнеров
|
||||
const suppliers = await useQuery(GET_MY_COUNTERPARTIES, {
|
||||
variables: { type: 'WHOLESALE' },
|
||||
})
|
||||
|
||||
// ❌ НЕПРАВИЛЬНО: Прямой запрос поставщиков
|
||||
const suppliers = await useQuery(GET_SUPPLY_SUPPLIERS)
|
||||
```
|
||||
|
||||
## 🔐 ТЕХНИЧЕСКИЕ ПРАВИЛА БЕЗОПАСНОСТИ
|
||||
|
||||
### КОНТРОЛЬ ДОСТУПА НА УРОВНЕ КОМПОНЕНТОВ:
|
||||
|
||||
```typescript
|
||||
// Проверка типа организации в UI
|
||||
{user?.organization?.type === "WHOLESALE" && (
|
||||
<WarehouseDashboard />
|
||||
)}
|
||||
|
||||
// Условный рендеринг функций поставщика
|
||||
{user?.organization?.type === 'WHOLESALE' ? (
|
||||
<SupplierOrdersTabs />
|
||||
) : (
|
||||
<AccessDenied />
|
||||
)}
|
||||
```
|
||||
|
||||
### ПРОВЕРКИ В GRAPHQL РЕЗОЛВЕРАХ:
|
||||
|
||||
```typescript
|
||||
// Проверка что пользователь - поставщик
|
||||
if (context.user.organization.type !== 'WHOLESALE') {
|
||||
throw new Error('Access denied: Wholesale access required')
|
||||
}
|
||||
|
||||
// Проверка доступа к своим товарам
|
||||
const product = await prisma.product.findFirst({
|
||||
where: {
|
||||
id: productId,
|
||||
organizationId: context.user.organizationId,
|
||||
},
|
||||
})
|
||||
|
||||
// Фильтрация заказов для поставщика
|
||||
let whereClause
|
||||
if (currentUser.organization.type === 'WHOLESALE') {
|
||||
// Поставщик видит заказы, где он является поставщиком
|
||||
whereClause = { partnerId: currentUser.organization.id }
|
||||
} else {
|
||||
// Остальные видят заказы, которые они создали
|
||||
whereClause = { organizationId: currentUser.organization.id }
|
||||
}
|
||||
```
|
||||
|
||||
### ОБЯЗАТЕЛЬНЫЕ ВАЛИДАЦИИ:
|
||||
|
||||
```typescript
|
||||
const wholesaleValidations = {
|
||||
// Основные проверки
|
||||
organizationType: 'organization.type === "WHOLESALE"',
|
||||
accessControl: 'GraphQL resolver level validation',
|
||||
inventoryControl: 'Stock availability before order confirmation',
|
||||
|
||||
// Запрещенные действия
|
||||
forbidden: [
|
||||
'Создание товаров с типами DEFECT или FINISHED_PRODUCT',
|
||||
'Изменение статусов заказов минуя workflow',
|
||||
'Показ данных других поставщиков',
|
||||
'Прямое изменение статусов без бизнес-процессов',
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## 🚨 КРИТИЧЕСКИЕ ПРОБЛЕМЫ И РЕШЕНИЯ
|
||||
|
||||
### ВЫЯВЛЕННЫЕ ПРОБЛЕМЫ В WORKFLOW:
|
||||
|
||||
```typescript
|
||||
// ❌ ПРОБЛЕМА: Отображается статус вместо только кнопок действий
|
||||
// Поставщик видит "ожидает подтверждения" вместо чистых кнопок
|
||||
|
||||
// ❌ ПРОБЛЕМА: Нет валидации минимальных количеств заказа
|
||||
// Отсутствует проверка доступности товаров у поставщика
|
||||
|
||||
// ❌ ПРОБЛЕМА: Нет уведомления поставщика о новом заказе
|
||||
// Поставщик не знает о поступивших заказах в реальном времени
|
||||
|
||||
// 🔧 РЕШЕНИЕ: Исправленный код фильтрации заказов
|
||||
const fixedOrderFiltering = `
|
||||
if (currentUser.organization.type === 'WHOLESALE') {
|
||||
whereClause = {
|
||||
partnerId: currentUser.organization.id, // Мы - поставщик
|
||||
}
|
||||
}
|
||||
`
|
||||
```
|
||||
|
||||
### ТРЕБОВАНИЯ К ИСПРАВЛЕНИЯМ:
|
||||
|
||||
```typescript
|
||||
interface WholesaleFixes {
|
||||
ui: {
|
||||
orderButtons: 'Показывать только кнопки действий, скрывать статусы'
|
||||
realTimeNotifications: 'Уведомления о новых заказах'
|
||||
inventoryValidation: 'Проверка остатков перед подтверждением'
|
||||
}
|
||||
|
||||
backend: {
|
||||
minOrderValidation: 'Валидация минимальных количеств'
|
||||
stockAvailability: 'Проверка доступности товаров'
|
||||
notificationSystem: 'Система уведомлений поставщиков'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
_Извлечено из анализа: GraphQL resolvers, supply chain workflow, бизнес-логика поставщиков_
|
||||
_Дата создания: 2025-08-21_
|
||||
_Основано на коде: src/graphql/resolvers.ts, supply order management, wholesale patterns_
|
||||
_Дополнено техническими деталями из: legacy-rules/wholesale-cabinet-rules.md, правила создания поставки товаров.md_
|
||||
_Дата обновления: 2025-08-22_
|
||||
_Основано на коде: src/components/supplier-orders/, src/graphql/resolvers.ts, supply order management_
|
||||
|
Reference in New Issue
Block a user