asyncapi: 3.0.0

info:
  title: Nexus V0–V3 Event Schema
  version: 2.0.0
  description: |
    NATS JetStream event schema for Nexus platform.
    Subject pattern: nexus.{tenant_id}.{domain}.{event_type}
    Source of truth: STACK.md §19а.
    Covers: V0 core + pipeline, V1 KB, V2 verticals + integrations, V3 edge + IoT.

defaultContentType: application/json

servers:
  nats:
    host: nats:4222
    protocol: nats
    description: NATS JetStream (internal Docker network)

channels:
  # ─── Business Events ───

  bookingCreated:
    address: nexus.{tenant_id}.booking.created
    description: Новая запись создана
    parameters:
      tenant_id:
        description: Tenant identifier (e.g. salon-001)
    messages:
      bookingCreated:
        $ref: "#/components/messages/BookingEvent"

  bookingCancelled:
    address: nexus.{tenant_id}.booking.cancelled
    description: Запись отменена
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      bookingCancelled:
        $ref: "#/components/messages/BookingEvent"

  clientRegistered:
    address: nexus.{tenant_id}.client.registered
    description: Новый клиент зарегистрирован
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      clientRegistered:
        $ref: "#/components/messages/ClientEvent"

  paymentCompleted:
    address: nexus.{tenant_id}.payment.completed
    description: Оплата завершена
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      paymentCompleted:
        $ref: "#/components/messages/PaymentEvent"

  orderCreated:
    address: nexus.{tenant_id}.order.created
    description: Новый заказ создан
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      orderCreated:
        $ref: "#/components/messages/OrderEvent"

  inventoryLowStock:
    address: nexus.{tenant_id}.inventory.low_stock
    description: Низкий остаток на складе
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      inventoryLowStock:
        $ref: "#/components/messages/InventoryEvent"

  uiRenderRequest:
    address: nexus.{tenant_id}.ui.render_request
    description: JSON UI spec от агента для рендеринга (json-render)
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      uiRenderRequest:
        $ref: "#/components/messages/UIRenderEvent"

  # ─── System Events (Core only) ───

  tenantProvisioned:
    address: nexus._core.tenant.provisioned
    description: Новый tenant создан и провизионирован
    messages:
      tenantProvisioned:
        $ref: "#/components/messages/TenantEvent"

  moduleUpdated:
    address: nexus._core.module.updated
    description: WASM модуль обновлён через NATS OTA
    messages:
      moduleUpdated:
        $ref: "#/components/messages/ModuleEvent"

  capTokenIssued:
    address: nexus._core.audit.cap_token_issued
    description: Выдан новый CapToken (Ed25519)
    messages:
      capTokenIssued:
        $ref: "#/components/messages/AuditEvent"

  # ─── Agent Events ───

  agentHandoff:
    address: nexus._core.agent.handoff
    description: Передача задачи между агентами
    messages:
      agentHandoff:
        $ref: "#/components/messages/AgentHandoffEvent"

  agentHandoffAck:
    address: nexus._core.agent.handoff.ack
    description: Подтверждение приёма задачи агентом
    messages:
      agentHandoffAck:
        $ref: "#/components/messages/AgentHandoffAckEvent"

  agentDream:
    address: nexus._core.agent.dream
    description: Триггер dream-consolidation
    messages:
      agentDream:
        $ref: "#/components/messages/AgentDreamEvent"

  agentSelfEvolution:
    address: nexus._core.agent.self_evolution
    description: Результат 5-gate self-evolution
    messages:
      agentSelfEvolution:
        $ref: "#/components/messages/AgentEvolutionEvent"

  piiMasked:
    address: nexus.{tenant_id}.pii.masked
    description: PII prefilter сработал
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      piiMasked:
        $ref: "#/components/messages/PIIMaskedEvent"

  # ─── V0 Pipeline Events ───

  pipelineStageCompleted:
    address: nexus._core.pipeline.stage_completed
    description: Этап pipeline завершён (intake, generate, deploy, etc.)
    messages:
      pipelineStageCompleted:
        $ref: "#/components/messages/PipelineStageEvent"

  pipelineCompleted:
    address: nexus._core.pipeline.completed
    description: Pipeline полностью завершён для tenant
    messages:
      pipelineCompleted:
        $ref: "#/components/messages/PipelineCompletedEvent"

  telegramMessage:
    address: nexus._core.telegram.message
    description: Входящее / исходящее сообщение Telegram-бота
    messages:
      telegramMessage:
        $ref: "#/components/messages/TelegramMessageEvent"

  # ─── V1 KB Events ───

  kbIngested:
    address: nexus.{tenant_id}.kb.ingested
    description: Документ загружен и обработан KB-модулем
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      kbIngested:
        $ref: "#/components/messages/KBIngestedEvent"

  kbSearched:
    address: nexus.{tenant_id}.kb.searched
    description: Выполнен поиск по базе знаний
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      kbSearched:
        $ref: "#/components/messages/KBSearchedEvent"

  # ─── V2 Vertical Events ───

  restaurantOrderCreated:
    address: nexus.{tenant_id}.restaurant.order_created
    description: Создан заказ в ресторане (столик / доставка)
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      restaurantOrderCreated:
        $ref: "#/components/messages/RestaurantOrderEvent"

  manufacturingProductionStarted:
    address: nexus.{tenant_id}.manufacturing.production_started
    description: Запущен производственный заказ
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      manufacturingProductionStarted:
        $ref: "#/components/messages/ManufacturingProductionEvent"

  payrollCalculated:
    address: nexus.{tenant_id}.payroll.calculated
    description: Расчёт зарплаты завершён
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      payrollCalculated:
        $ref: "#/components/messages/PayrollCalculatedEvent"

  posReceiptCreated:
    address: nexus.{tenant_id}.pos.receipt_created
    description: Создан чек на POS-терминале
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      posReceiptCreated:
        $ref: "#/components/messages/POSReceiptEvent"

  integrationSynced:
    address: nexus.{tenant_id}.integration.synced
    description: Завершена синхронизация с внешней системой (1С, CRM, etc.)
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      integrationSynced:
        $ref: "#/components/messages/IntegrationSyncedEvent"

  # ─── V3 Edge & IoT Events ───

  edgeHealth:
    address: nexus._core.edge.health.{node_id}
    description: Heartbeat / health от edge-ноды
    parameters:
      node_id:
        description: Edge node identifier (e.g. edge-msk-01)
    messages:
      edgeHealth:
        $ref: "#/components/messages/EdgeHealthEvent"

  iotSensorData:
    address: nexus.{tenant_id}.iot.sensor_data
    description: Данные с IoT-датчика (температура, влажность, etc.)
    parameters:
      tenant_id:
        description: Tenant identifier
    messages:
      iotSensorData:
        $ref: "#/components/messages/IoTSensorEvent"

components:
  messages:
    BookingEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    ClientEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    PaymentEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    OrderEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    InventoryEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    UIRenderEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    TenantEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    ModuleEvent:
      payload:
        $ref: "#/components/schemas/ModuleUpdatePayload"

    AuditEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    AgentHandoffEvent:
      payload:
        $ref: "#/components/schemas/AgentHandoffPayload"

    AgentHandoffAckEvent:
      payload:
        $ref: "#/components/schemas/AgentHandoffAckPayload"

    AgentDreamEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    AgentEvolutionEvent:
      payload:
        $ref: "#/components/schemas/AgentEvolutionPayload"

    PIIMaskedEvent:
      payload:
        $ref: "#/components/schemas/PIIMaskedPayload"

    PipelineStageEvent:
      payload:
        $ref: "#/components/schemas/PipelineStagePayload"

    PipelineCompletedEvent:
      payload:
        $ref: "#/components/schemas/PipelineCompletedPayload"

    TelegramMessageEvent:
      payload:
        $ref: "#/components/schemas/TelegramMessagePayload"

    KBIngestedEvent:
      payload:
        $ref: "#/components/schemas/KBIngestedPayload"

    KBSearchedEvent:
      payload:
        $ref: "#/components/schemas/KBSearchedPayload"

    RestaurantOrderEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    ManufacturingProductionEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    PayrollCalculatedEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    POSReceiptEvent:
      payload:
        $ref: "#/components/schemas/EventEnvelope"

    IntegrationSyncedEvent:
      payload:
        $ref: "#/components/schemas/IntegrationSyncedPayload"

    EdgeHealthEvent:
      payload:
        $ref: "#/components/schemas/EdgeHealthPayload"

    IoTSensorEvent:
      payload:
        $ref: "#/components/schemas/IoTSensorPayload"

  schemas:
    EventEnvelope:
      type: object
      description: |
        Base event envelope. See core/schema-registry/schemas/event-envelope.schema.json.
        causal_id is used as OpenTelemetry trace_id.
      required:
        - causal_id
        - vector_clock
        - payload
      properties:
        causal_id:
          type: string
          description: "Causal identifier (also OTel trace_id). Format: evt-{uuid-v7-short}"
          examples:
            - "evt-9f3ac21d"
        vector_clock:
          type: object
          additionalProperties:
            type: integer
          description: "Vector clock for causal ordering"
          examples:
            - { "nexus-core": 42 }
        payload:
          type: object
          description: Domain-specific payload
        tenant:
          type: string
          description: Tenant identifier (optional for system events)
          examples:
            - "salon-001"
            - "sto-002"

    ModuleUpdatePayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              properties:
                module_name:
                  type: string
                  examples: ["scheduler", "crm", "oms"]
                abi_version:
                  type: integer
                  examples: [1]
                signature:
                  type: string
                  description: Ed25519 signature of the WASM artifact

    AgentHandoffPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - from
                - to
                - task
                - files
              properties:
                from:
                  type: string
                  examples: ["archi"]
                to:
                  type: string
                  examples: ["claw-code"]
                task:
                  type: string
                files:
                  type: array
                  items:
                    type: string
                context_summary:
                  type: string
                  maxLength: 2000

    AgentEvolutionPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              properties:
                gates_passed:
                  type: array
                  items:
                    type: integer
                gates_failed:
                  type: array
                  items:
                    type: integer
                target_file:
                  type: string
                diff_lines:
                  type: integer
                result:
                  type: string
                  enum: ["accepted", "rejected"]
                reason:
                  type: string

    AgentHandoffAckPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - agent
              properties:
                agent:
                  type: string
                  description: Agent accepting the handoff
                  examples: ["claw-code"]

    PIIMaskedPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              properties:
                fields_masked:
                  type: array
                  items:
                    type: string
                  examples:
                    - ["phone", "inn"]
                token_count_before:
                  type: integer
                token_count_after:
                  type: integer

    PipelineStagePayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - stage
                - status
              properties:
                stage:
                  type: string
                  enum: ["intake", "context", "generate", "build", "deploy", "notify"]
                  examples: ["intake"]
                status:
                  type: string
                  enum: ["started", "completed", "failed"]
                duration_ms:
                  type: integer
                error:
                  type: string

    PipelineCompletedPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - total_duration_ms
                - stages_completed
              properties:
                total_duration_ms:
                  type: integer
                stages_completed:
                  type: integer
                preview_url:
                  type: string
                  format: uri

    TelegramMessagePayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - direction
                - chat_id
                - text
              properties:
                direction:
                  type: string
                  enum: ["inbound", "outbound"]
                chat_id:
                  type: integer
                text:
                  type: string
                from_username:
                  type: string

    KBIngestedPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - document_id
                - facts_extracted
              properties:
                document_id:
                  type: string
                title:
                  type: string
                doc_type:
                  type: string
                  examples: ["pdf", "txt", "html"]
                facts_extracted:
                  type: integer
                size_bytes:
                  type: integer

    KBSearchedPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - query
                - results_count
              properties:
                query:
                  type: string
                results_count:
                  type: integer
                top_score:
                  type: number
                  format: float
                duration_ms:
                  type: integer

    IntegrationSyncedPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - provider
                - direction
                - records_synced
              properties:
                provider:
                  type: string
                  examples: ["1c", "bitrix", "moysklad"]
                direction:
                  type: string
                  enum: ["push", "pull", "bidirectional"]
                records_synced:
                  type: integer
                errors:
                  type: integer

    EdgeHealthPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - node_id
                - status
              properties:
                node_id:
                  type: string
                  examples: ["edge-msk-01"]
                status:
                  type: string
                  enum: ["healthy", "degraded", "offline"]
                uptime_secs:
                  type: integer
                cpu_pct:
                  type: number
                  format: float
                mem_pct:
                  type: number
                  format: float
                wasm_modules_loaded:
                  type: integer

    IoTSensorPayload:
      allOf:
        - $ref: "#/components/schemas/EventEnvelope"
        - type: object
          properties:
            payload:
              type: object
              required:
                - sensor_id
                - metric
                - value
              properties:
                sensor_id:
                  type: string
                  examples: ["temp-fridge-01"]
                metric:
                  type: string
                  examples: ["temperature", "humidity", "pressure"]
                value:
                  type: number
                  format: float
                unit:
                  type: string
                  examples: ["°C", "%", "hPa"]
                timestamp_unix:
                  type: integer
