architect/_archive/2025-11-13-before-restructure/platform-projects/projects/cifra/archive/2025-11-10-restructure-v2/MISSING_PIECES.md

Что ещё нужно в CIFRA Platform

Дата: 2025-11-10
Версия: 1.0.0
Цель: Инвентаризация недостающих компонентов системы


КРАТКИЙ ОТВЕТ

Что мы уже охватили ✅

✅ Иерархическая композиция (Элементы → Модули → Компоненты)
✅ Архитектура классов (Метапрограммирование, Descriptors, Factory)
✅ Метастандарты (BPMN, DMN, OpenAPI, GraphQL, ArchiMate)
✅ Именование (CIFRA Platform, CIFRA Spec)
✅ Описание процессов (Business Process, Workflow, Saga)

Что нужно добавить 🔴

1. PERMISSIONS & SECURITY (безопасность и права)
2. UI/UX SPECIFICATION (описание интерфейсов)
3. INTEGRATIONS (внешние системы)
4. NOTIFICATIONS & ALERTS (уведомления)
5. REPORTS & ANALYTICS (отчёты и аналитика)
6. TESTING (тестирование)
7. DEPLOYMENT & DEVOPS (деплой и мониторинг)
8. LOCALIZATION (мультиязычность)
9. VERSIONING & MIGRATIONS (версионирование)
10. SCHEDULING & CRON (планировщик задач)

Часть 1: PERMISSIONS & SECURITY (Безопасность)

1.1 Role-Based Access Control (RBAC)

# security/rbac.cifra
security:
  authentication:
    type: jwt
    token_expiration: 3600
    refresh_token: true
    providers:
      - local  # Email + Password
      - oauth:
          google:
            client_id: "{env.GOOGLE_CLIENT_ID}"
            client_secret: "{env.GOOGLE_CLIENT_SECRET}"
          github:
            client_id: "{env.GITHUB_CLIENT_ID}"
            client_secret: "{env.GITHUB_CLIENT_SECRET}"

  # Определение ролей
  roles:
    - id: admin
      name: "Администратор"
      description: "Полный доступ ко всей системе"
      permissions: ["*"]  # Все права

    - id: sales_manager
      name: "Менеджер по продажам"
      description: "Управление сделками и клиентами"
      permissions:
        - contacts:read
        - contacts:create
        - contacts:update
        - deals:*  # Все права на сделки
        - reports:sales:read

    - id: sales_rep
      name: "Менеджер продаж"
      description: "Работа со своими сделками"
      permissions:
        - contacts:read
        - contacts:create
        - deals:read
        - deals:create
        - deals:update:own  # Только свои сделки

    - id: customer
      name: "Клиент"
      description: "Доступ к своим заказам"
      permissions:
        - orders:read:own
        - profile:read:own
        - profile:update:own

  # Права (permissions)
  permissions:
    # Format: resource:action[:scope]

    # CRUD для контактов
    - id: contacts:read
      name: "Просмотр контактов"
      resource: Contact
      action: read

    - id: contacts:create
      name: "Создание контактов"
      resource: Contact
      action: create

    - id: contacts:update
      name: "Редактирование контактов"
      resource: Contact
      action: update

    - id: contacts:delete
      name: "Удаление контактов"
      resource: Contact
      action: delete

    # Специальные права
    - id: deals:update:own
      name: "Редактировать свои сделки"
      resource: Deal
      action: update
      scope: own  # Только принадлежащие пользователю
      condition: "resource.owner_id == user.id"

    - id: deals:approve
      name: "Одобрять сделки"
      resource: Deal
      action: approve
      condition: "resource.amount < 100000 OR user.role == 'admin'"

  # Field-level security (права на уровне полей)
  field_security:
    Contact:
      email:
        read: [admin, sales_manager, sales_rep]
        write: [admin, sales_manager]

      phone:
        read: [admin, sales_manager, sales_rep]
        write: [admin, sales_manager, sales_rep]

      company:
        read: ["*"]  # Все могут читать
        write: [admin, sales_manager]

    Deal:
      amount:
        read: [admin, sales_manager, sales_rep:own]
        write: [admin, sales_manager]

      commission:
        read: [admin, sales_manager]
        write: [admin]

1.2 Attribute-Based Access Control (ABAC)

# security/abac.cifra
security:
  abac_policies:
    # Политика: Менеджер может редактировать сделки своего региона
    - id: regional_deal_access
      name: "Доступ к сделкам региона"
      effect: allow
      principals:
        roles: [sales_manager]
      resources:
        type: Deal
      actions: [read, update]
      conditions:
        - "user.region == resource.customer.region"

    # Политика: После 18:00 нельзя одобрять сделки > 50000
    - id: after_hours_limit
      name: "Ограничение одобрений после 18:00"
      effect: deny
      principals:
        roles: [sales_manager]
      resources:
        type: Deal
      actions: [approve]
      conditions:
        - "current_time().hour >= 18"
        - "resource.amount > 50000"

    # Политика: VIP клиенты видят специальные цены
    - id: vip_pricing
      name: "Специальные цены для VIP"
      effect: allow
      principals:
        attributes:
          customer_type: VIP
      resources:
        type: Product
      actions: [read]
      transform:
        price: "resource.price * 0.85"  # 15% скидка

  # Row-Level Security (RLS)
  row_level_security:
    Contact:
      - policy: own_contacts
        condition: "owner_id == current_user.id"
        roles: [sales_rep]

      - policy: team_contacts
        condition: "owner.team_id == current_user.team_id"
        roles: [sales_manager]

      - policy: all_contacts
        condition: "true"
        roles: [admin]

    Order:
      - policy: customer_own_orders
        condition: "customer_id == current_user.id"
        roles: [customer]

      - policy: all_orders
        condition: "true"
        roles: [admin, sales_manager]

Часть 2: UI/UX SPECIFICATION (Описание интерфейсов)

2.1 Forms (Формы)

# ui/contact_form.cifra
ui:
  forms:
    - id: create_contact_form
      name: "Создание контакта"
      entity: Contact
      mode: create

      layout: two_column  # one_column, two_column, grid

      sections:
        - id: personal_info
          title: "Личная информация"
          fields:
            - first_name:
                label: "Имя"
                required: true
                placeholder: "Введите имя"
                validation:
                  - type: min_length
                    value: 2
                    message: "Минимум 2 символа"

            - last_name:
                label: "Фамилия"
                required: true

            - email:
                label: "Email"
                required: true
                type: email
                help_text: "Мы не передаём email третьим лицам"

            - phone:
                label: "Телефон"
                type: phone
                mask: "+7 (999) 999-99-99"

        - id: company_info
          title: "Информация о компании"
          collapsible: true
          collapsed: false
          fields:
            - company:
                label: "Компания"
                type: relation
                entity: Company
                display_field: name
                searchable: true
                allow_create: true  # Можно создать новую компанию

            - position:
                label: "Должность"
                type: string

        - id: additional
          title: "Дополнительно"
          fields:
            - tags:
                label: "Теги"
                type: tags
                max_tags: 10
                suggestions: [vip, partner, lead]

            - notes:
                label: "Примечания"
                type: textarea
                rows: 5
                max_length: 1000

      buttons:
        - type: submit
          label: "Создать контакт"
          style: primary
          icon: save

        - type: cancel
          label: "Отмена"
          style: secondary

      validation:
        on_submit: true
        inline: true  # Валидация при вводе

      hooks:
        before_submit: |
          # JavaScript код для обработки перед отправкой
          if (data.email.includes('+')) {
            confirm('Email содержит +, продолжить?')
          }

        after_submit: |
          # После успешного создания
          notify('Контакт создан успешно')
          navigate('/contacts/' + result.id)

2.2 Lists & Tables (Списки и таблицы)

# ui/contact_list.cifra
ui:
  lists:
    - id: contacts_list
      name: "Список контактов"
      entity: Contact

      # Колонки таблицы
      columns:
        - field: full_name
          label: "Имя"
          sortable: true
          searchable: true
          width: 200px
          render: |
            <div class="flex items-center">
              <Avatar src="{row.avatar}" />
              <div>
                <div class="font-medium">{row.full_name}</div>
                <div class="text-sm text-gray-500">{row.position}</div>
              </div>
            </div>

        - field: email
          label: "Email"
          sortable: true
          searchable: true

        - field: company.name
          label: "Компания"
          sortable: true
          link: "/companies/{row.company.id}"

        - field: tags
          label: "Теги"
          render: |
            {row.tags.map(tag => <Badge>{tag}</Badge>)}

        - field: created_at
          label: "Создан"
          sortable: true
          format: date
          format_pattern: "DD.MM.YYYY"

        - field: actions
          label: ""
          width: 100px
          render: |
            <ActionMenu>
              <MenuItem onClick="{editContact}">Редактировать</MenuItem>
              <MenuItem onClick="{deleteContact}">Удалить</MenuItem>
              <MenuItem onClick="{sendEmail}">Отправить email</MenuItem>
            </ActionMenu>

      # Фильтры
      filters:
        - field: company
          type: select
          label: "Компания"
          options: "query(Company, {}, {name: 1})"

        - field: tags
          type: multiselect
          label: "Теги"

        - field: created_at
          type: date_range
          label: "Дата создания"

      # Поиск
      search:
        enabled: true
        placeholder: "Поиск по имени, email, телефону..."
        fields: [first_name, last_name, email, phone]

      # Действия над выбранными
      bulk_actions:
        - id: delete
          label: "Удалить"
          icon: trash
          confirm: "Удалить выбранные контакты?"

        - id: export
          label: "Экспорт в Excel"
          icon: download

        - id: assign_tag
          label: "Добавить тег"
          icon: tag
          form:
            fields:
              - tag: {type: select, options: [vip, partner, lead]}

      # Pagination
      pagination:
        page_size: 50
        page_size_options: [25, 50, 100, 200]

      # Экспорт
      export:
        formats: [excel, csv, pdf]

2.3 Dashboards (Дашборды)

# ui/sales_dashboard.cifra
ui:
  dashboards:
    - id: sales_dashboard
      name: "Дашборд продаж"
      layout: grid
      refresh_interval: 60s  # Автообновление каждую минуту

      widgets:
        # Карточки с метриками
        - type: metric_card
          position: {row: 1, col: 1, width: 3, height: 1}
          metric: total_revenue
          title: "Общая выручка"
          query: |
            SELECT SUM(amount) as value
            FROM deals
            WHERE status = 'won'
            AND created_at >= current_date - interval '30 days'
          format: currency
          trend:
            query: |
              SELECT SUM(amount) as previous_value
              FROM deals
              WHERE status = 'won'
              AND created_at >= current_date - interval '60 days'
              AND created_at < current_date - interval '30 days'
            show_percentage: true

        - type: metric_card
          position: {row: 1, col: 4, width: 3, height: 1}
          title: "Новые сделки"
          query: |
            SELECT COUNT(*) as value
            FROM deals
            WHERE created_at >= current_date - interval '7 days'
          icon: trending_up
          color: green

        # График
        - type: chart
          position: {row: 2, col: 1, width: 8, height: 4}
          title: "Выручка по месяцам"
          chart_type: line
          query: |
            SELECT
              DATE_TRUNC('month', created_at) as month,
              SUM(amount) as revenue,
              COUNT(*) as deals_count
            FROM deals
            WHERE status = 'won'
            AND created_at >= current_date - interval '12 months'
            GROUP BY month
            ORDER BY month
          x_axis: month
          y_axis: [revenue, deals_count]
          options:
            smooth: true
            fill: true

        # Таблица топ клиентов
        - type: table
          position: {row: 2, col: 9, width: 4, height: 4}
          title: "Топ клиенты"
          query: |
            SELECT
              c.name,
              COUNT(d.id) as deals_count,
              SUM(d.amount) as total_revenue
            FROM customers c
            JOIN deals d ON d.customer_id = c.id
            WHERE d.status = 'won'
            GROUP BY c.id
            ORDER BY total_revenue DESC
            LIMIT 10
          columns:
            - {field: name, label: "Клиент"}
            - {field: deals_count, label: "Сделок"}
            - {field: total_revenue, label: "Выручка", format: currency}

        # Воронка продаж
        - type: funnel
          position: {row: 6, col: 1, width: 6, height: 4}
          title: "Воронка продаж"
          stages:
            - {name: "Лиды", query: "SELECT COUNT(*) FROM deals WHERE stage = 'lead'"}
            - {name: "Квалификация", query: "SELECT COUNT(*) FROM deals WHERE stage = 'qualification'"}
            - {name: "Предложение", query: "SELECT COUNT(*) FROM deals WHERE stage = 'proposal'"}
            - {name: "Переговоры", query: "SELECT COUNT(*) FROM deals WHERE stage = 'negotiation'"}
            - {name: "Выиграно", query: "SELECT COUNT(*) FROM deals WHERE stage = 'won'"}

      # Фильтры для всего дашборда
      filters:
        - field: date_range
          type: date_range
          label: "Период"
          default: last_30_days

        - field: sales_rep
          type: select
          label: "Менеджер"
          query: "SELECT id, name FROM users WHERE role = 'sales_rep'"

Часть 3: INTEGRATIONS (Интеграции)

3.1 External APIs

# integrations/external_apis.cifra
integrations:
  # Stripe (платёжный шлюз)
  - id: stripe
    name: "Stripe Payments"
    type: rest_api
    base_url: https://api.stripe.com
    auth:
      type: bearer
      token: "{env.STRIPE_SECRET_KEY}"

    endpoints:
      - id: create_charge
        path: /v1/charges
        method: POST
        params:
          amount: {type: integer, required: true}
          currency: {type: string, default: "rub"}
          source: {type: string, required: true}

      - id: create_refund
        path: /v1/refunds
        method: POST
        params:
          charge: {type: string, required: true}

  # SendGrid (email)
  - id: sendgrid
    name: "SendGrid Email Service"
    type: rest_api
    base_url: https://api.sendgrid.com/v3
    auth:
      type: bearer
      token: "{env.SENDGRID_API_KEY}"

    endpoints:
      - id: send_email
        path: /mail/send
        method: POST
        body_schema:
          personalizations:
            - to: [{email: string, name: string}]
              subject: string
          from: {email: string, name: string}
          content:
            - type: text/html
              value: string

  # Google Maps (геокодирование)
  - id: google_maps
    name: "Google Maps API"
    type: rest_api
    base_url: https://maps.googleapis.com/maps/api
    auth:
      type: api_key
      param: key
      value: "{env.GOOGLE_MAPS_KEY}"

    endpoints:
      - id: geocode
        path: /geocode/json
        method: GET
        params:
          address: {type: string, required: true}

  # Twilio (SMS)
  - id: twilio
    name: "Twilio SMS"
    type: rest_api
    base_url: https://api.twilio.com/2010-04-01
    auth:
      type: basic
      username: "{env.TWILIO_ACCOUNT_SID}"
      password: "{env.TWILIO_AUTH_TOKEN}"

    endpoints:
      - id: send_sms
        path: /Accounts/{account_sid}/Messages.json
        method: POST
        params:
          To: {type: phone, required: true}
          From: {type: phone, required: true}
          Body: {type: string, required: true, max_length: 1600}

3.2 Message Queues

# integrations/message_queues.cifra
integrations:
  message_queues:
    # Kafka
    - id: kafka
      type: kafka
      brokers:
        - kafka1.example.com:9092
        - kafka2.example.com:9092
        - kafka3.example.com:9092

      topics:
        - name: orders.created
          partitions: 6
          replication_factor: 3
          config:
            retention.ms: 604800000  # 7 days

        - name: payments.completed
          partitions: 6

      consumers:
        - name: order_processor
          topics: [orders.created]
          group_id: order-processing-group
          auto_offset_reset: earliest

      producers:
        - name: order_events
          topics: [orders.created, orders.updated]

    # RabbitMQ
    - id: rabbitmq
      type: rabbitmq
      host: rabbitmq.example.com
      port: 5672
      vhost: /
      auth:
        username: "{env.RABBITMQ_USER}"
        password: "{env.RABBITMQ_PASSWORD}"

      exchanges:
        - name: orders
          type: topic
          durable: true

      queues:
        - name: email_notifications
          durable: true
          arguments:
            x-message-ttl: 86400000  # 24 hours

        - name: sms_notifications
          durable: true

      bindings:
        - queue: email_notifications
          exchange: orders
          routing_key: "order.*.email"

3.3 Storage (Хранилища)

# integrations/storage.cifra
integrations:
  storage:
    # AWS S3
    - id: s3_documents
      type: s3
      bucket: company-documents
      region: eu-west-1
      auth:
        access_key_id: "{env.AWS_ACCESS_KEY_ID}"
        secret_access_key: "{env.AWS_SECRET_ACCESS_KEY}"

      folders:
        invoices: /invoices/{year}/{month}/
        contracts: /contracts/{customer_id}/
        reports: /reports/{year}/

      lifecycle:
        - id: archive_old_files
          transition:
            days: 90
            storage_class: GLACIER

    # MinIO (S3-compatible)
    - id: minio_uploads
      type: s3
      endpoint: https://minio.example.com
      bucket: user-uploads
      auth:
        access_key: "{env.MINIO_ACCESS_KEY}"
        secret_key: "{env.MINIO_SECRET_KEY}"

      public_url: https://cdn.example.com

Часть 4: NOTIFICATIONS & ALERTS (Уведомления)

# notifications/system.cifra
notifications:
  channels:
    # Email
    - id: email
      type: email
      provider: sendgrid
      from:
        email: noreply@example.com
        name: "CRM System"

      templates:
        - id: welcome_email
          subject: "Добро пожаловать в CRM!"
          body_html: templates/welcome.html
          body_text: templates/welcome.txt
          variables: [user_name, login_url]

        - id: order_confirmation
          subject: "Заказ #{order_number} подтверждён"
          body_html: templates/order_confirmation.html

    # SMS
    - id: sms
      type: sms
      provider: twilio
      from: "+79991234567"

      templates:
        - id: order_shipped
          body: "Ваш заказ #{order_number} отправлен. Трек-номер: {tracking_number}"

    # Push notifications
    - id: push
      type: push
      provider: firebase
      credentials: "{env.FIREBASE_CREDENTIALS}"

      templates:
        - id: new_message
          title: "Новое сообщение"
          body: "{sender_name}: {message_preview}"
          icon: /icons/message.png
          click_action: /messages/{message_id}

    # In-app notifications
    - id: in_app
      type: in_app
      storage: database
      retention: 30d  # Хранить 30 дней

  # Правила отправки
  rules:
    # Уведомление при создании заказа
    - trigger: entity_created
      entity: Order
      channels: [email, sms, in_app]
      recipients:
        - type: entity_field
          field: customer
      template: order_confirmation
      conditions:
        - "order.total > 0"

    # Уведомление менеджера о новом лиде
    - trigger: entity_created
      entity: Deal
      stage: lead
      channels: [email, in_app, push]
      recipients:
        - type: entity_field
          field: assigned_to
      template: new_lead_assigned
      priority: high

    # Напоминание об истекающей задаче
    - trigger: scheduled
      schedule: "0 9 * * *"  # Каждый день в 9:00
      channels: [email, in_app]
      template: task_due_reminder
      query: |
        SELECT * FROM tasks
        WHERE due_date = current_date
        AND status != 'completed'

  # Настройки пользователя (preferences)
  user_preferences:
    - channel: email
      frequency: immediate  # immediate, hourly, daily, weekly
      enabled_events: [order_created, deal_won, task_assigned]

    - channel: push
      frequency: immediate
      enabled_events: [new_message, task_due]
      quiet_hours:
        start: "22:00"
        end: "08:00"

Часть 5: REPORTS & ANALYTICS (Отчёты)

# reports/sales_reports.cifra
reports:
  - id: monthly_sales_report
    name: "Отчёт по продажам за месяц"
    category: sales
    type: tabular

    parameters:
      - month: {type: month, required: true}
      - sales_rep: {type: relation, entity: User, required: false}

    query: |
      SELECT
        u.name as sales_rep,
        COUNT(d.id) as deals_count,
        SUM(CASE WHEN d.status = 'won' THEN d.amount ELSE 0 END) as won_amount,
        SUM(CASE WHEN d.status = 'lost' THEN d.amount ELSE 0 END) as lost_amount,
        ROUND(100.0 * COUNT(CASE WHEN d.status = 'won' THEN 1 END) / COUNT(*), 2) as conversion_rate
      FROM deals d
      JOIN users u ON d.assigned_to = u.id
      WHERE DATE_TRUNC('month', d.created_at) = :month
        AND (:sales_rep IS NULL OR d.assigned_to = :sales_rep)
      GROUP BY u.id, u.name
      ORDER BY won_amount DESC

    columns:
      - {field: sales_rep, label: "Менеджер", width: 200}
      - {field: deals_count, label: "Всего сделок", align: center}
      - {field: won_amount, label: "Выиграно", format: currency}
      - {field: lost_amount, label: "Проиграно", format: currency}
      - {field: conversion_rate, label: "Конверсия", format: percentage}

    totals:
      - deals_count: sum
      - won_amount: sum
      - lost_amount: sum
      - conversion_rate: avg

    export_formats: [excel, pdf, csv]

    schedule:
      frequency: monthly
      day_of_month: 1
      time: "09:00"
      recipients: [sales_manager@example.com]

  - id: customer_lifetime_value
    name: "Customer Lifetime Value"
    type: chart
    chart_type: scatter

    query: |
      SELECT
        c.name,
        COUNT(o.id) as orders_count,
        SUM(o.total) as total_spent,
        DATE_PART('day', MAX(o.created_at) - MIN(o.created_at)) as days_active
      FROM customers c
      JOIN orders o ON o.customer_id = c.id
      GROUP BY c.id
      HAVING COUNT(o.id) > 1

    axes:
      x: days_active
      y: total_spent
      size: orders_count
      label: name

Часть 6: TESTING (Тестирование)

# tests/contact_tests.cifra
tests:
  unit:
    - name: "Contact validation"
      entity: Contact
      test_cases:
        - name: "Valid contact creation"
          action: create
          data:
            first_name: "Иван"
            last_name: "Петров"
            email: "ivan@example.com"
          expect:
            status: success
            result:
              full_name: "Иван Петров"

        - name: "Invalid email"
          action: create
          data:
            first_name: "Иван"
            last_name: "Петров"
            email: "invalid-email"
          expect:
            status: error
            error_code: validation_error
            error_field: email

  integration:
    - name: "Order fulfillment process"
      process: OrderFulfillment
      test_cases:
        - name: "Successful order"
          setup:
            - create_entity: Product
              data: {sku: "TEST-001", stock: 100}
            - create_entity: Customer
              data: {email: "test@example.com"}

          input:
            product_id: "{created.Product.id}"
            customer_id: "{created.Customer.id}"
            quantity: 5

          expect:
            process_status: completed
            entities_created: [Order, Shipment]
            final_state:
              Order.status: shipped
              Product.stock: 95

        - name: "Out of stock"
          input:
            product_id: "{product.id}"
            quantity: 200  # Больше чем stock

          expect:
            process_status: failed
            error: "Insufficient stock"

  e2e:
    - name: "User can create and complete order"
      type: browser
      steps:
        - action: navigate
          url: /products

        - action: click
          selector: "[data-test='add-to-cart']"

        - action: click
          selector: "[data-test='checkout']"

        - action: fill
          selector: "[name='email']"
          value: "test@example.com"

        - action: click
          selector: "[data-test='submit-order']"

        - action: wait_for
          selector: "[data-test='order-confirmation']"

        - action: assert
          selector: "[data-test='order-status']"
          text: "Order placed successfully"

Часть 7: DEPLOYMENT & DEVOPS

# deployment/production.cifra
deployment:
  environments:
    - id: development
      name: "Development"
      url: https://dev.example.com
      auto_deploy: true
      branch: develop

    - id: staging
      name: "Staging"
      url: https://staging.example.com
      auto_deploy: false
      branch: main
      requires_approval: true

    - id: production
      name: "Production"
      url: https://example.com
      auto_deploy: false
      branch: main
      requires_approval: true
      approvers: [cto@example.com, lead@example.com]

  infrastructure:
    type: kubernetes
    cluster: production-cluster

    services:
      - name: api
        replicas: 3
        image: company/api:latest
        port: 8000
        resources:
          cpu: 1
          memory: 2Gi
        env:
          DATABASE_URL: "{secrets.database_url}"
          REDIS_URL: "{secrets.redis_url}"

      - name: worker
        replicas: 2
        image: company/worker:latest
        resources:
          cpu: 0.5
          memory: 1Gi

    databases:
      - type: postgresql
        version: "14"
        size: 100GB
        backup:
          frequency: daily
          retention: 30d

      - type: redis
        version: "7"
        size: 10GB

  monitoring:
    - service: prometheus
      scrape_interval: 15s
      metrics:
        - http_requests_total
        - http_request_duration_seconds
        - database_connections

    - service: grafana
      dashboards:
        - System Overview
        - Application Metrics
        - Business Metrics

    - service: sentry
      dsn: "{env.SENTRY_DSN}"
      sample_rate: 1.0
      traces_sample_rate: 0.1

  logging:
    - service: loki
      retention: 30d
      labels:
        - service
        - environment
        - level

  alerts:
    - name: high_error_rate
      condition: "error_rate > 5%"
      duration: 5m
      severity: critical
      notify: [ops-team@example.com, slack://ops-channel]

    - name: high_latency
      condition: "p95_latency > 2s"
      duration: 10m
      severity: warning
      notify: [dev-team@example.com]

Часть 8: LOCALIZATION (Локализация)

# localization/i18n.cifra
localization:
  default_locale: ru_RU
  supported_locales:
    - ru_RU
    - en_US
    - de_DE
    - zh_CN

  # Переводы
  translations:
    Contact:
      ru_RU:
        singular: "Контакт"
        plural: "Контакты"
        fields:
          first_name: "Имя"
          last_name: "Фамилия"
          email: "Email"
          phone: "Телефон"

      en_US:
        singular: "Contact"
        plural: "Contacts"
        fields:
          first_name: "First Name"
          last_name: "Last Name"
          email: "Email"
          phone: "Phone"

  # Форматирование
  formatting:
    ru_RU:
      date: "DD.MM.YYYY"
      time: "HH:mm"
      datetime: "DD.MM.YYYY HH:mm"
      currency: "# ##0,00 ₽"
      number: "# ##0,##"
      phone: "+7 (###) ###-##-##"

    en_US:
      date: "MM/DD/YYYY"
      time: "hh:mm A"
      datetime: "MM/DD/YYYY hh:mm A"
      currency: "$#,##0.00"
      number: "#,##0.##"
      phone: "+1 (###) ###-####"

  # Валюты
  currencies:
    - code: RUB
      symbol: "₽"
      name:
        ru_RU: "Российский рубль"
        en_US: "Russian Ruble"

    - code: USD
      symbol: "$"
      name:
        ru_RU: "Доллар США"
        en_US: "US Dollar"

Часть 9: VERSIONING & MIGRATIONS

# versioning/migrations.cifra
versioning:
  # Версионирование CIFRA спецификаций
  schema_version: 2.0.0

  migrations:
    - version: 2.0.0
      date: "2025-11-10"
      description: "Добавлено поле commission в Deal"
      up: |
        ALTER TABLE deals
        ADD COLUMN commission DECIMAL(15,2);

        UPDATE deals
        SET commission = amount * 0.05
        WHERE status = 'won';

      down: |
        ALTER TABLE deals
        DROP COLUMN commission;

    - version: 1.9.0
      date: "2025-10-15"
      description: "Добавлена таблица tags"
      up: |
        CREATE TABLE tags (
          id UUID PRIMARY KEY,
          name VARCHAR(100) UNIQUE,
          created_at TIMESTAMP DEFAULT NOW()
        );

        CREATE TABLE contact_tags (
          contact_id UUID REFERENCES contacts(id),
          tag_id UUID REFERENCES tags(id),
          PRIMARY KEY (contact_id, tag_id)
        );

      down: |
        DROP TABLE contact_tags;
        DROP TABLE tags;

  # Обратная совместимость
  compatibility:
    api_versions:
      - version: v1
        deprecated: false
        sunset_date: null

      - version: v0
        deprecated: true
        sunset_date: "2026-01-01"
        migration_guide: /docs/v0-to-v1-migration

Часть 10: SCHEDULING & CRON

# scheduling/jobs.cifra
scheduling:
  jobs:
    # Ежедневная отправка отчётов
    - id: daily_sales_report
      name: "Ежедневный отчёт по продажам"
      schedule: "0 9 * * *"  # Каждый день в 9:00
      timezone: Europe/Moscow
      action:
        type: generate_report
        report: daily_sales
        send_to: [sales-team@example.com]

    # Очистка старых записей
    - id: cleanup_old_logs
      name: "Очистка старых логов"
      schedule: "0 2 * * 0"  # Каждое воскресенье в 2:00
      action:
        type: execute_query
        query: |
          DELETE FROM audit_logs
          WHERE created_at < NOW() - INTERVAL '90 days'

    # Напоминания об истекающих задачах
    - id: task_reminders
      name: "Напоминания о задачах"
      schedule: "0 */4 * * *"  # Каждые 4 часа
      action:
        type: run_process
        process: SendTaskReminders

    # Синхронизация с внешней системой
    - id: sync_with_external_crm
      name: "Синхронизация с внешней CRM"
      schedule: "*/15 * * * *"  # Каждые 15 минут
      retry:
        max_attempts: 3
        delay: 5m
      action:
        type: call_integration
        integration: external_crm
        endpoint: sync_contacts

Заключение

Итоговая картина CIFRA Platform:

CIFRA PLATFORM = Всё для создания бизнес-приложений

✅ ОХВАТИЛИ:
  1. Данные (Entity, Fields)
  2. Логика (Classes, Methods)
  3. Процессы (BPMN-like workflows)
  4. Архитектура (Иерархическая композиция)
  5. Стандарты (BPMN, OpenAPI, GraphQL)

🔴 ДОБАВИЛИ СЕГОДНЯ:
  6. Безопасность (RBAC, ABAC, RLS)
  7. UI/UX (Forms, Lists, Dashboards)
  8. Интеграции (APIs, Queues, Storage)
  9. Уведомления (Email, SMS, Push)
  10. Отчёты (Reports, Analytics)
  11. Тестирование (Unit, Integration, E2E)
  12. DevOps (Deployment, Monitoring, Alerts)
  13. Локализация (i18n, l10n)
  14. Версионирование (Migrations)
  15. Планировщик (Cron, Jobs)

Теперь можно описать ПОЛНОЕ приложение:

# complete_crm.cifra
cifra: 1.0.0

# 1. Данные
entities: {...}

# 2. Процессы
processes: {...}

# 3. Правила
rules: {...}

# 4. API
api: {...}

# 5. Безопасность
security: {...}

# 6. UI
ui: {...}

# 7. Интеграции
integrations: {...}

# 8. Уведомления
notifications: {...}

# 9. Отчёты
reports: {...}

# 10. Тестирование
tests: {...}

# 11. Deployment
deployment: {...}

# 12. Локализация
localization: {...}

# 13. Планировщик
scheduling: {...}

Результат: Одна спецификация → Полноценное Enterprise приложение 🚀