asyncapi: "2.6.0"

info:
  title: Integration Hub Service - Async API
  version: "1.0.0"
  description: |
    AsyncAPI specification for the **integration-hub-svc** Kafka event contracts.

    The integration-hub-svc is the centralized gateway for all third-party API
    integrations in the EventZR platform. It manages providers (Stripe, Twilio,
    WhatsApp Business API, OpenAI, Google Maps, etc.), credentials, OAuth
    connections, marketplace integrations, sync jobs, WhatsApp messaging,
    webhooks, budgets, compliance, and cost analytics.

    **Event Format:** CloudEvents 1.0
    **Broker:** Amazon MSK Serverless (Kafka)
    **Topic Pattern:** `eventzr.integration-hub.<entity>.<action>.v1`
    **Partition Key:** `tenant_id` (ensures per-tenant ordering)
    **Delivery:** Transactional outbox pattern (KAFKA_ENABLED=false on Lambda;
    outbox-publisher polls every 10 seconds and publishes pending events)

    **19 Database Tables Generating Events:**
    providers, credentials, usage, oauth_connections, installed_integrations,
    marketplace_integrations, audit_logs, budget_policies, compliance_policies,
    cost_anomalies, provider_health_checks, workflow_templates, tenant_workflows,
    whatsapp_templates, message_deliveries, messaging_windows, outbox_events,
    sync_jobs, sync_events
  contact:
    name: EventZR Platform Team
    email: platform@eventzr.com
  license:
    name: Proprietary
    url: https://eventzr.com/license

servers:
  msk-staging:
    url: "{mskBootstrapServers}"
    protocol: kafka-secure
    protocolVersion: "3.6"
    description: Amazon MSK Serverless (staging) - ap-south-1
    security:
      - saslScram: []
    variables:
      mskBootstrapServers:
        default: "boot-xxxxxxxx.c2.kafka-serverless.ap-south-1.amazonaws.com:9098"
        description: MSK Serverless bootstrap servers (from .aws-services.env)

  msk-production:
    url: "{mskBootstrapServers}"
    protocol: kafka-secure
    protocolVersion: "3.6"
    description: Amazon MSK Serverless (production) - ap-south-1
    security:
      - saslScram: []
    variables:
      mskBootstrapServers:
        default: "boot-xxxxxxxx.c2.kafka-serverless.ap-south-1.amazonaws.com:9098"
        description: MSK Serverless bootstrap servers (production)

defaultContentType: application/json

# ============================================================================
# CHANNELS
# ============================================================================

channels:
  # --------------------------------------------------------------------------
  # PROVIDER events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.provider.created.v1:
    description: Emitted when a new provider is registered in the catalog.
    publish:
      operationId: publishProviderCreated
      summary: Provider created
      message:
        $ref: "#/components/messages/ProviderCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: provider_id (ULID)
          groupId: false

  eventzr.integration-hub.provider.updated.v1:
    description: Emitted when a provider's configuration, capabilities, or metadata are updated.
    publish:
      operationId: publishProviderUpdated
      summary: Provider updated
      message:
        $ref: "#/components/messages/ProviderUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: provider_id (ULID)

  eventzr.integration-hub.provider.deleted.v1:
    description: Emitted when a provider is soft-deleted from the catalog.
    publish:
      operationId: publishProviderDeleted
      summary: Provider deleted
      message:
        $ref: "#/components/messages/ProviderDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: provider_id (ULID)

  eventzr.integration-hub.provider.status_changed.v1:
    description: >
      Emitted when a provider's operational status changes
      (e.g., active to maintenance, or inactive due to circuit breaker).
    publish:
      operationId: publishProviderStatusChanged
      summary: Provider status changed
      message:
        $ref: "#/components/messages/ProviderStatusChangedV1"
      bindings:
        kafka:
          key:
            type: string
            description: provider_id (ULID)

  # --------------------------------------------------------------------------
  # CREDENTIAL events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.credential.created.v1:
    description: Emitted when a new credential reference is stored (secret handle in AWS Secrets Manager).
    publish:
      operationId: publishCredentialCreated
      summary: Credential created
      message:
        $ref: "#/components/messages/CredentialCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.credential.updated.v1:
    description: Emitted when a credential's metadata or status is updated.
    publish:
      operationId: publishCredentialUpdated
      summary: Credential updated
      message:
        $ref: "#/components/messages/CredentialUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.credential.rotated.v1:
    description: Emitted when a credential is rotated (new secret created, old moved to previous).
    publish:
      operationId: publishCredentialRotated
      summary: Credential rotated
      message:
        $ref: "#/components/messages/CredentialRotatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.credential.revoked.v1:
    description: Emitted when a credential is revoked by an admin.
    publish:
      operationId: publishCredentialRevoked
      summary: Credential revoked
      message:
        $ref: "#/components/messages/CredentialRevokedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.credential.deleted.v1:
    description: Emitted when a credential is soft-deleted.
    publish:
      operationId: publishCredentialDeleted
      summary: Credential deleted
      message:
        $ref: "#/components/messages/CredentialDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # USAGE events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.usage.recorded.v1:
    description: >
      Emitted for every integration execution (API call to external provider).
      Immutable time-series record used for billing, quota enforcement, and analytics.
    publish:
      operationId: publishUsageRecorded
      summary: Usage recorded
      message:
        $ref: "#/components/messages/UsageRecordedV1"
      bindings:
        kafka:
          key:
            type: string
            description: usage_id (ULID)

  # --------------------------------------------------------------------------
  # OAUTH CONNECTION events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.oauth-connection.created.v1:
    description: Emitted when a new OAuth 2.0 connection is established (after callback and token exchange).
    publish:
      operationId: publishOAuthConnectionCreated
      summary: OAuth connection created
      message:
        $ref: "#/components/messages/OAuthConnectionCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.oauth-connection.updated.v1:
    description: Emitted when an OAuth connection is refreshed or status changes.
    publish:
      operationId: publishOAuthConnectionUpdated
      summary: OAuth connection updated
      message:
        $ref: "#/components/messages/OAuthConnectionUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.oauth-connection.deleted.v1:
    description: Emitted when a user disconnects an OAuth provider.
    publish:
      operationId: publishOAuthConnectionDeleted
      summary: OAuth connection deleted
      message:
        $ref: "#/components/messages/OAuthConnectionDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # INSTALLED INTEGRATION events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.installed-integration.created.v1:
    description: Emitted when a tenant installs a marketplace integration.
    publish:
      operationId: publishInstalledIntegrationCreated
      summary: Integration installed
      message:
        $ref: "#/components/messages/InstalledIntegrationCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.installed-integration.updated.v1:
    description: Emitted when a tenant updates installed integration configuration or status.
    publish:
      operationId: publishInstalledIntegrationUpdated
      summary: Installed integration updated
      message:
        $ref: "#/components/messages/InstalledIntegrationUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.installed-integration.deleted.v1:
    description: Emitted when a tenant uninstalls an integration.
    publish:
      operationId: publishInstalledIntegrationDeleted
      summary: Integration uninstalled
      message:
        $ref: "#/components/messages/InstalledIntegrationDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # MARKETPLACE INTEGRATION events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.marketplace-integration.created.v1:
    description: Emitted when a new integration is published to the marketplace catalog.
    publish:
      operationId: publishMarketplaceIntegrationCreated
      summary: Marketplace integration created
      message:
        $ref: "#/components/messages/MarketplaceIntegrationCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: marketplace_integration_id (ULID)

  eventzr.integration-hub.marketplace-integration.updated.v1:
    description: Emitted when a marketplace integration listing is updated (version bump, metadata change).
    publish:
      operationId: publishMarketplaceIntegrationUpdated
      summary: Marketplace integration updated
      message:
        $ref: "#/components/messages/MarketplaceIntegrationUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: marketplace_integration_id (ULID)

  eventzr.integration-hub.marketplace-integration.deleted.v1:
    description: Emitted when a marketplace integration is archived or removed.
    publish:
      operationId: publishMarketplaceIntegrationDeleted
      summary: Marketplace integration deleted
      message:
        $ref: "#/components/messages/MarketplaceIntegrationDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: marketplace_integration_id (ULID)

  # --------------------------------------------------------------------------
  # AUDIT LOG events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.audit-log.created.v1:
    description: >
      Emitted when a significant action is recorded in the audit trail
      (credential access, provider changes, integration install/uninstall, etc.).
    publish:
      operationId: publishAuditLogCreated
      summary: Audit log entry created
      message:
        $ref: "#/components/messages/AuditLogCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # BUDGET POLICY events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.budget-policy.created.v1:
    description: Emitted when a tenant creates a new monthly budget policy.
    publish:
      operationId: publishBudgetPolicyCreated
      summary: Budget policy created
      message:
        $ref: "#/components/messages/BudgetPolicyCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.budget-policy.updated.v1:
    description: Emitted when a budget policy limit or currency is updated.
    publish:
      operationId: publishBudgetPolicyUpdated
      summary: Budget policy updated
      message:
        $ref: "#/components/messages/BudgetPolicyUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.budget-policy.deleted.v1:
    description: Emitted when a budget policy is removed.
    publish:
      operationId: publishBudgetPolicyDeleted
      summary: Budget policy deleted
      message:
        $ref: "#/components/messages/BudgetPolicyDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # COMPLIANCE POLICY events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.compliance-policy.created.v1:
    description: Emitted when a compliance policy (per-provider rules) is created.
    publish:
      operationId: publishCompliancePolicyCreated
      summary: Compliance policy created
      message:
        $ref: "#/components/messages/CompliancePolicyCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.compliance-policy.updated.v1:
    description: Emitted when a compliance policy's rules are updated.
    publish:
      operationId: publishCompliancePolicyUpdated
      summary: Compliance policy updated
      message:
        $ref: "#/components/messages/CompliancePolicyUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.compliance-policy.deleted.v1:
    description: Emitted when a compliance policy is removed.
    publish:
      operationId: publishCompliancePolicyDeleted
      summary: Compliance policy deleted
      message:
        $ref: "#/components/messages/CompliancePolicyDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # COST ANOMALY events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.cost-anomaly.created.v1:
    description: Emitted when a cost anomaly is detected for a provider (spend deviation).
    publish:
      operationId: publishCostAnomalyCreated
      summary: Cost anomaly detected
      message:
        $ref: "#/components/messages/CostAnomalyCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # COST events (domain-specific, from cost.producer.ts)
  # --------------------------------------------------------------------------
  eventzr.integration-hub.cost.threshold_exceeded.v1:
    description: Emitted when a tenant's budget threshold is exceeded.
    publish:
      operationId: publishCostThresholdExceeded
      summary: Budget threshold exceeded
      message:
        $ref: "#/components/messages/CostThresholdExceededV1"
      bindings:
        kafka:
          key:
            type: string
            description: budget_id (UUID)

  eventzr.integration-hub.cost.anomaly_detected.v1:
    description: Emitted when unusual spend patterns are detected for a provider.
    publish:
      operationId: publishCostAnomalyDetected
      summary: Cost anomaly detected (analytics)
      message:
        $ref: "#/components/messages/CostAnomalyDetectedV1"
      bindings:
        kafka:
          key:
            type: string
            description: anomaly_id (UUID)

  eventzr.integration-hub.cost.forecast_generated.v1:
    description: Emitted when a cost forecast is generated for a tenant.
    publish:
      operationId: publishCostForecastGenerated
      summary: Cost forecast generated
      message:
        $ref: "#/components/messages/CostForecastGeneratedV1"
      bindings:
        kafka:
          key:
            type: string
            description: forecast_id (UUID)

  # --------------------------------------------------------------------------
  # PROVIDER HEALTH CHECK events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.provider-health-check.created.v1:
    description: Emitted when a provider health check is executed and the result is recorded.
    publish:
      operationId: publishProviderHealthCheckCreated
      summary: Provider health check created
      message:
        $ref: "#/components/messages/ProviderHealthCheckCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # WORKFLOW TEMPLATE events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.workflow-template.created.v1:
    description: Emitted when a new workflow template is created.
    publish:
      operationId: publishWorkflowTemplateCreated
      summary: Workflow template created
      message:
        $ref: "#/components/messages/WorkflowTemplateCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: workflow_template_id (UUID)

  eventzr.integration-hub.workflow-template.updated.v1:
    description: Emitted when a workflow template definition is updated.
    publish:
      operationId: publishWorkflowTemplateUpdated
      summary: Workflow template updated
      message:
        $ref: "#/components/messages/WorkflowTemplateUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: workflow_template_id (UUID)

  eventzr.integration-hub.workflow-template.deleted.v1:
    description: Emitted when a workflow template is removed.
    publish:
      operationId: publishWorkflowTemplateDeleted
      summary: Workflow template deleted
      message:
        $ref: "#/components/messages/WorkflowTemplateDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: workflow_template_id (UUID)

  # --------------------------------------------------------------------------
  # TENANT WORKFLOW events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.tenant-workflow.created.v1:
    description: Emitted when a tenant instantiates a workflow from a template.
    publish:
      operationId: publishTenantWorkflowCreated
      summary: Tenant workflow created
      message:
        $ref: "#/components/messages/TenantWorkflowCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.tenant-workflow.updated.v1:
    description: Emitted when a tenant workflow configuration is updated.
    publish:
      operationId: publishTenantWorkflowUpdated
      summary: Tenant workflow updated
      message:
        $ref: "#/components/messages/TenantWorkflowUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.tenant-workflow.deleted.v1:
    description: Emitted when a tenant workflow is removed.
    publish:
      operationId: publishTenantWorkflowDeleted
      summary: Tenant workflow deleted
      message:
        $ref: "#/components/messages/TenantWorkflowDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # WHATSAPP TEMPLATE events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.whatsapp-template.created.v1:
    description: Emitted when a WhatsApp message template is synced from Meta for the first time.
    publish:
      operationId: publishWhatsAppTemplateCreated
      summary: WhatsApp template created
      message:
        $ref: "#/components/messages/WhatsAppTemplateCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.whatsapp-template.updated.v1:
    description: Emitted when a WhatsApp template is re-synced with updated status or body from Meta.
    publish:
      operationId: publishWhatsAppTemplateUpdated
      summary: WhatsApp template updated
      message:
        $ref: "#/components/messages/WhatsAppTemplateUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.whatsapp-template.deleted.v1:
    description: Emitted when a WhatsApp template is soft-deleted (removed from Meta).
    publish:
      operationId: publishWhatsAppTemplateDeleted
      summary: WhatsApp template deleted
      message:
        $ref: "#/components/messages/WhatsAppTemplateDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # MESSAGE DELIVERY events (WhatsApp)
  # --------------------------------------------------------------------------
  eventzr.integration-hub.whatsapp.message.sent.v1:
    description: >
      Emitted when a WhatsApp message (text, template, or media) is sent via Meta API.
      Corresponds to the initial queued/sent status.
    publish:
      operationId: publishWhatsAppMessageSent
      summary: WhatsApp message sent
      message:
        $ref: "#/components/messages/WhatsAppMessageSentV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.whatsapp.message.delivered.v1:
    description: Emitted when Meta confirms a message was delivered to the recipient device.
    publish:
      operationId: publishWhatsAppMessageDelivered
      summary: WhatsApp message delivered
      message:
        $ref: "#/components/messages/WhatsAppMessageDeliveredV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.whatsapp.message.received.v1:
    description: >
      Emitted when an inbound WhatsApp message is received from a user
      (opens or extends the 24-hour messaging window).
    publish:
      operationId: publishWhatsAppMessageReceived
      summary: WhatsApp inbound message received
      message:
        $ref: "#/components/messages/WhatsAppMessageReceivedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.whatsapp.status.updated.v1:
    description: >
      Emitted when a message delivery status webhook is received from Meta
      (queued, sent, delivered, read, failed).
    publish:
      operationId: publishWhatsAppStatusUpdated
      summary: WhatsApp delivery status updated
      message:
        $ref: "#/components/messages/WhatsAppStatusUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.whatsapp.media.sent.v1:
    description: Emitted when a WhatsApp media message (image, video, audio, document) is sent.
    publish:
      operationId: publishWhatsAppMediaSent
      summary: WhatsApp media sent
      message:
        $ref: "#/components/messages/WhatsAppMediaSentV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # MESSAGING WINDOW events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.messaging-window.created.v1:
    description: Emitted when a new 24-hour messaging window is opened for a recipient.
    publish:
      operationId: publishMessagingWindowCreated
      summary: Messaging window opened
      message:
        $ref: "#/components/messages/MessagingWindowCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.messaging-window.updated.v1:
    description: Emitted when a messaging window is extended (new inbound message resets 24h timer).
    publish:
      operationId: publishMessagingWindowUpdated
      summary: Messaging window updated
      message:
        $ref: "#/components/messages/MessagingWindowUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # OUTBOX EVENT events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.outbox-event.created.v1:
    description: >
      Internal event emitted when a new entry is written to the transactional outbox table.
      The outbox-publisher polls this table every 10 seconds and publishes to Kafka.
    publish:
      operationId: publishOutboxEventCreated
      summary: Outbox event queued
      message:
        $ref: "#/components/messages/OutboxEventCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID) or aggregate_id

  # --------------------------------------------------------------------------
  # SYNC JOB events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.sync-job.created.v1:
    description: Emitted when a new sync job is configured.
    publish:
      operationId: publishSyncJobCreated
      summary: Sync job created
      message:
        $ref: "#/components/messages/SyncJobCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.sync-job.updated.v1:
    description: Emitted when a sync job schedule, filters, or status is updated.
    publish:
      operationId: publishSyncJobUpdated
      summary: Sync job updated
      message:
        $ref: "#/components/messages/SyncJobUpdatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  eventzr.integration-hub.sync-job.deleted.v1:
    description: Emitted when a sync job is soft-deleted (stops scheduled runs).
    publish:
      operationId: publishSyncJobDeleted
      summary: Sync job deleted
      message:
        $ref: "#/components/messages/SyncJobDeletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # SYNC (domain) events (from sync.producer.ts)
  # --------------------------------------------------------------------------
  eventzr.integration-hub.sync.completed.v1:
    description: Emitted when a sync job execution completes successfully.
    publish:
      operationId: publishSyncCompleted
      summary: Sync completed
      message:
        $ref: "#/components/messages/SyncCompletedV1"
      bindings:
        kafka:
          key:
            type: string
            description: sync_id (ULID)

  eventzr.integration-hub.sync.failed.v1:
    description: Emitted when a sync job execution fails.
    publish:
      operationId: publishSyncFailed
      summary: Sync failed
      message:
        $ref: "#/components/messages/SyncFailedV1"
      bindings:
        kafka:
          key:
            type: string
            description: sync_id (ULID)

  # --------------------------------------------------------------------------
  # SYNC EVENT events
  # --------------------------------------------------------------------------
  eventzr.integration-hub.sync-event.created.v1:
    description: Emitted when a sync event (individual record sync result) is recorded within a sync job.
    publish:
      operationId: publishSyncEventCreated
      summary: Sync event created
      message:
        $ref: "#/components/messages/SyncEventCreatedV1"
      bindings:
        kafka:
          key:
            type: string
            description: tenant_id (UUID)

  # --------------------------------------------------------------------------
  # WEBHOOK events (from webhook.producer.ts)
  # --------------------------------------------------------------------------
  eventzr.integration-hub.webhook.received.v1:
    description: Emitted when an inbound webhook is received from an external provider.
    publish:
      operationId: publishWebhookReceived
      summary: Webhook received
      message:
        $ref: "#/components/messages/WebhookReceivedV1"
      bindings:
        kafka:
          key:
            type: string
            description: webhook_id (ULID)

  eventzr.integration-hub.webhook.delivered.v1:
    description: Emitted when an inbound webhook has been processed and delivered to the target service.
    publish:
      operationId: publishWebhookDelivered
      summary: Webhook delivered
      message:
        $ref: "#/components/messages/WebhookDeliveredV1"
      bindings:
        kafka:
          key:
            type: string
            description: webhook_id (ULID)

# ============================================================================
# COMPONENTS
# ============================================================================

components:
  # --------------------------------------------------------------------------
  # Security Schemes
  # --------------------------------------------------------------------------
  securitySchemes:
    saslScram:
      type: scramSha256
      description: >
        SASL/SCRAM-SHA-256 authentication for Amazon MSK Serverless.
        Credentials are stored in AWS Secrets Manager and injected via
        environment variables (KAFKA_SASL_USERNAME, KAFKA_SASL_PASSWORD).

  # --------------------------------------------------------------------------
  # Messages
  # --------------------------------------------------------------------------
  messages:
    # ---- PROVIDER ----
    ProviderCreatedV1:
      name: ProviderCreatedV1
      title: Provider Created
      contentType: application/json
      schemaFormat: application/schema+json;version=draft-07
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"
      examples:
        - name: StripeProviderCreated
          payload:
            specversion: "1.0"
            type: eventzr.integration-hub.provider.created.v1
            source: integration-hub-svc
            id: 01HQRS9V0K5P6T7M8N9QWERTYU
            time: "2026-02-20T10:00:00.000Z"
            datacontenttype: application/json
            subject: 01HQRS9V0K5P6T7M8N9QWERTYU
            tenantid: null
            data:
              providerId: 01HQRS9V0K5P6T7M8N9QWERTYU
              providerKey: stripe
              name: Stripe Payments
              category: payments
              createdAt: "2026-02-20T10:00:00.000Z"

    ProviderUpdatedV1:
      name: ProviderUpdatedV1
      title: Provider Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    ProviderDeletedV1:
      name: ProviderDeletedV1
      title: Provider Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    ProviderStatusChangedV1:
      name: ProviderStatusChangedV1
      title: Provider Status Changed
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/ProviderStatusChangedPayload"

    # ---- CREDENTIAL ----
    CredentialCreatedV1:
      name: CredentialCreatedV1
      title: Credential Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    CredentialUpdatedV1:
      name: CredentialUpdatedV1
      title: Credential Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    CredentialRotatedV1:
      name: CredentialRotatedV1
      title: Credential Rotated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    CredentialRevokedV1:
      name: CredentialRevokedV1
      title: Credential Revoked
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    CredentialDeletedV1:
      name: CredentialDeletedV1
      title: Credential Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- USAGE ----
    UsageRecordedV1:
      name: UsageRecordedV1
      title: Usage Recorded
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/UsageRecordedPayload"
      examples:
        - name: StripeChargeUsage
          payload:
            specversion: "1.0"
            type: eventzr.integration-hub.usage.recorded.v1
            source: integration-hub-svc
            id: 01HQRS9V0K5P6T7M8N9QWERTYU
            time: "2026-02-20T10:30:00.000Z"
            datacontenttype: application/json
            subject: tenants/acme-123/usage
            tenantid: acme-123
            data:
              usageId: 01HQRS9V0K5P6T7M8N9QWERTYU
              tenantId: acme-123
              providerId: 01HQRS9V0K5STRIPE0PROVIDER
              providerKey: stripe
              category: payments
              costUsd: 0.029
              quotaConsumed: 1
              subscriptionTier: pro
              timestamp: "2026-02-20T10:30:00.000Z"

    # ---- OAUTH CONNECTION ----
    OAuthConnectionCreatedV1:
      name: OAuthConnectionCreatedV1
      title: OAuth Connection Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    OAuthConnectionUpdatedV1:
      name: OAuthConnectionUpdatedV1
      title: OAuth Connection Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    OAuthConnectionDeletedV1:
      name: OAuthConnectionDeletedV1
      title: OAuth Connection Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- INSTALLED INTEGRATION ----
    InstalledIntegrationCreatedV1:
      name: InstalledIntegrationCreatedV1
      title: Integration Installed
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    InstalledIntegrationUpdatedV1:
      name: InstalledIntegrationUpdatedV1
      title: Installed Integration Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    InstalledIntegrationDeletedV1:
      name: InstalledIntegrationDeletedV1
      title: Integration Uninstalled
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- MARKETPLACE INTEGRATION ----
    MarketplaceIntegrationCreatedV1:
      name: MarketplaceIntegrationCreatedV1
      title: Marketplace Integration Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    MarketplaceIntegrationUpdatedV1:
      name: MarketplaceIntegrationUpdatedV1
      title: Marketplace Integration Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    MarketplaceIntegrationDeletedV1:
      name: MarketplaceIntegrationDeletedV1
      title: Marketplace Integration Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- AUDIT LOG ----
    AuditLogCreatedV1:
      name: AuditLogCreatedV1
      title: Audit Log Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/AuditLogPayload"

    # ---- BUDGET POLICY ----
    BudgetPolicyCreatedV1:
      name: BudgetPolicyCreatedV1
      title: Budget Policy Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    BudgetPolicyUpdatedV1:
      name: BudgetPolicyUpdatedV1
      title: Budget Policy Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    BudgetPolicyDeletedV1:
      name: BudgetPolicyDeletedV1
      title: Budget Policy Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- COMPLIANCE POLICY ----
    CompliancePolicyCreatedV1:
      name: CompliancePolicyCreatedV1
      title: Compliance Policy Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    CompliancePolicyUpdatedV1:
      name: CompliancePolicyUpdatedV1
      title: Compliance Policy Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    CompliancePolicyDeletedV1:
      name: CompliancePolicyDeletedV1
      title: Compliance Policy Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- COST ANOMALY ----
    CostAnomalyCreatedV1:
      name: CostAnomalyCreatedV1
      title: Cost Anomaly Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CostAnomalyPayload"

    # ---- COST (domain) ----
    CostThresholdExceededV1:
      name: CostThresholdExceededV1
      title: Cost Threshold Exceeded
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CostThresholdExceededPayload"

    CostAnomalyDetectedV1:
      name: CostAnomalyDetectedV1
      title: Cost Anomaly Detected (Analytics)
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CostAnomalyDetectedPayload"

    CostForecastGeneratedV1:
      name: CostForecastGeneratedV1
      title: Cost Forecast Generated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CostForecastGeneratedPayload"

    # ---- PROVIDER HEALTH CHECK ----
    ProviderHealthCheckCreatedV1:
      name: ProviderHealthCheckCreatedV1
      title: Provider Health Check Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/ProviderHealthCheckPayload"

    # ---- WORKFLOW TEMPLATE ----
    WorkflowTemplateCreatedV1:
      name: WorkflowTemplateCreatedV1
      title: Workflow Template Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    WorkflowTemplateUpdatedV1:
      name: WorkflowTemplateUpdatedV1
      title: Workflow Template Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    WorkflowTemplateDeletedV1:
      name: WorkflowTemplateDeletedV1
      title: Workflow Template Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- TENANT WORKFLOW ----
    TenantWorkflowCreatedV1:
      name: TenantWorkflowCreatedV1
      title: Tenant Workflow Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    TenantWorkflowUpdatedV1:
      name: TenantWorkflowUpdatedV1
      title: Tenant Workflow Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    TenantWorkflowDeletedV1:
      name: TenantWorkflowDeletedV1
      title: Tenant Workflow Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- WHATSAPP TEMPLATE ----
    WhatsAppTemplateCreatedV1:
      name: WhatsAppTemplateCreatedV1
      title: WhatsApp Template Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppTemplatePayload"

    WhatsAppTemplateUpdatedV1:
      name: WhatsAppTemplateUpdatedV1
      title: WhatsApp Template Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppTemplatePayload"

    WhatsAppTemplateDeletedV1:
      name: WhatsAppTemplateDeletedV1
      title: WhatsApp Template Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- WHATSAPP MESSAGE DELIVERY ----
    WhatsAppMessageSentV1:
      name: WhatsAppMessageSentV1
      title: WhatsApp Message Sent
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppMessagePayload"

    WhatsAppMessageDeliveredV1:
      name: WhatsAppMessageDeliveredV1
      title: WhatsApp Message Delivered
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppMessagePayload"

    WhatsAppMessageReceivedV1:
      name: WhatsAppMessageReceivedV1
      title: WhatsApp Message Received (Inbound)
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppInboundMessagePayload"

    WhatsAppStatusUpdatedV1:
      name: WhatsAppStatusUpdatedV1
      title: WhatsApp Delivery Status Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppStatusPayload"

    WhatsAppMediaSentV1:
      name: WhatsAppMediaSentV1
      title: WhatsApp Media Sent
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WhatsAppMediaPayload"

    # ---- MESSAGING WINDOW ----
    MessagingWindowCreatedV1:
      name: MessagingWindowCreatedV1
      title: Messaging Window Opened
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/MessagingWindowPayload"

    MessagingWindowUpdatedV1:
      name: MessagingWindowUpdatedV1
      title: Messaging Window Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/MessagingWindowPayload"

    # ---- OUTBOX EVENT ----
    OutboxEventCreatedV1:
      name: OutboxEventCreatedV1
      title: Outbox Event Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/OutboxEventPayload"

    # ---- SYNC JOB ----
    SyncJobCreatedV1:
      name: SyncJobCreatedV1
      title: Sync Job Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    SyncJobUpdatedV1:
      name: SyncJobUpdatedV1
      title: Sync Job Updated
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    SyncJobDeletedV1:
      name: SyncJobDeletedV1
      title: Sync Job Deleted
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- SYNC (domain) ----
    SyncCompletedV1:
      name: SyncCompletedV1
      title: Sync Completed
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/SyncCompletedPayload"

    SyncFailedV1:
      name: SyncFailedV1
      title: Sync Failed
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/SyncFailedPayload"

    # ---- SYNC EVENT ----
    SyncEventCreatedV1:
      name: SyncEventCreatedV1
      title: Sync Event Created
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/CloudEventEnvelope"

    # ---- WEBHOOK (domain) ----
    WebhookReceivedV1:
      name: WebhookReceivedV1
      title: Webhook Received
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WebhookReceivedPayload"

    WebhookDeliveredV1:
      name: WebhookDeliveredV1
      title: Webhook Delivered
      contentType: application/json
      traits:
        - $ref: "#/components/messageTraits/CloudEventHeaders"
      payload:
        $ref: "#/components/schemas/WebhookDeliveredPayload"

  # --------------------------------------------------------------------------
  # Message Traits
  # --------------------------------------------------------------------------
  messageTraits:
    CloudEventHeaders:
      headers:
        type: object
        required:
          - ce_specversion
          - ce_type
          - ce_source
          - ce_id
          - ce_time
        properties:
          ce_specversion:
            type: string
            const: "1.0"
            description: CloudEvents specification version.
          ce_type:
            type: string
            description: >
              Event type in reverse-DNS notation.
              Pattern: eventzr.integration-hub.<entity>.<action>.v<N>
          ce_source:
            type: string
            const: integration-hub-svc
            description: Source service producing the event.
          ce_id:
            type: string
            description: Unique event identifier (ULID or UUID).
          ce_time:
            type: string
            format: date-time
            description: ISO 8601 timestamp of event occurrence.
          ce_datacontenttype:
            type: string
            const: application/json
          ce_subject:
            type: string
            description: Subject of the event (typically entity ID or resource path).
          ce_tenantid:
            type: string
            format: uuid
            description: Tenant UUID for multi-tenant isolation and partitioning.
          ce_correlationid:
            type: string
            format: uuid
            description: Correlation ID for distributed tracing.

  # --------------------------------------------------------------------------
  # Schemas
  # --------------------------------------------------------------------------
  schemas:
    # ========================================================================
    # CLOUD EVENTS ENVELOPE (generic)
    # ========================================================================
    CloudEventEnvelope:
      type: object
      description: CloudEvents 1.0 envelope used by all integration-hub-svc events.
      required:
        - specversion
        - type
        - source
        - id
        - time
        - datacontenttype
        - data
      properties:
        specversion:
          type: string
          const: "1.0"
          description: CloudEvents specification version.
        type:
          type: string
          description: >
            Event type. Pattern: eventzr.integration-hub.<entity>.<action>.v1
          examples:
            - eventzr.integration-hub.provider.created.v1
            - eventzr.integration-hub.credential.rotated.v1
            - eventzr.integration-hub.usage.recorded.v1
        source:
          type: string
          const: integration-hub-svc
          description: Source service.
        id:
          type: string
          description: Unique event ID (ULID or UUID).
        time:
          type: string
          format: date-time
          description: ISO 8601 timestamp.
        datacontenttype:
          type: string
          const: application/json
        subject:
          type: string
          description: Entity ID or resource path.
        tenantid:
          type: string
          format: uuid
          description: Tenant UUID.
          x-nullable: true
        correlationid:
          type: string
          format: uuid
          description: Distributed tracing correlation ID.
        data:
          type: object
          description: Event-specific payload (see individual schemas below).

    # ========================================================================
    # PROVIDER payload schemas
    # ========================================================================
    ProviderPayload:
      type: object
      description: Provider entity data included in provider events.
      required:
        - providerId
        - providerKey
        - name
        - category
      properties:
        providerId:
          type: string
          description: Provider ULID.
        providerKey:
          type: string
          description: Unique provider key (kebab-case, e.g. stripe, twilio).
        name:
          type: string
          description: Display name.
        category:
          type: string
          enum:
            [cpaas, payments, llm, maps, calendar, media, crm, analytics, other]
        status:
          type: string
          enum: [active, inactive, deprecated, beta, maintenance]
        isFallback:
          type: boolean
        routingPriority:
          type: integer
          minimum: 0
          maximum: 100
        tenantId:
          type: string
          format: uuid
          x-nullable: true
          description: Null for global providers.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        deletedAt:
          type: string
          format: date-time
          x-nullable: true

    ProviderStatusChangedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - providerId
                - providerKey
                - oldStatus
                - newStatus
                - changedAt
              properties:
                providerId:
                  type: string
                providerKey:
                  type: string
                oldStatus:
                  type: string
                  enum: [active, inactive, degraded, maintenance]
                newStatus:
                  type: string
                  enum: [active, inactive, degraded, maintenance]
                changedAt:
                  type: string
                  format: date-time

    # ========================================================================
    # CREDENTIAL payload schemas
    # ========================================================================
    CredentialPayload:
      type: object
      description: >
        Credential reference data. NEVER includes plaintext secrets.
        Only secret handles (AWS Secrets Manager ARNs) are stored.
      required:
        - credentialId
        - tenantId
        - providerId
        - credentialType
        - displayName
        - status
      properties:
        credentialId:
          type: string
          description: Credential ULID.
        tenantId:
          type: string
          format: uuid
        providerId:
          type: string
          description: Provider ULID.
        credentialType:
          type: string
          enum: [api_key, oauth, jwt, basic_auth, bearer_token, hmac, mtls]
        displayName:
          type: string
        status:
          type: string
          enum: [active, rotating, expired, revoked, failed]
        isActive:
          type: boolean
        expiresAt:
          type: string
          format: date-time
          x-nullable: true
        lastRotatedAt:
          type: string
          format: date-time
          x-nullable: true
        createdAt:
          type: string
          format: date-time

    # ========================================================================
    # USAGE payload
    # ========================================================================
    UsageRecordedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - usageId
                - tenantId
                - providerId
                - providerKey
                - category
                - costUsd
                - quotaConsumed
                - subscriptionTier
                - timestamp
              properties:
                usageId:
                  type: string
                  description: Usage ULID.
                tenantId:
                  type: string
                  format: uuid
                providerId:
                  type: string
                providerKey:
                  type: string
                category:
                  type: string
                  enum:
                    [
                      cpaas,
                      payments,
                      llm,
                      maps,
                      media,
                      calendar,
                      crm,
                      analytics,
                      other,
                    ]
                intent:
                  type: string
                  description: "Integration intent (e.g. payment.create.charge)."
                status:
                  type: string
                  enum: [ok, failed, degraded, timeout, circuit_breaker]
                costUsd:
                  type: number
                  minimum: 0
                  description: Estimated cost in USD.
                quotaConsumed:
                  type: number
                  minimum: 0
                  description: Quota units consumed.
                subscriptionTier:
                  type: string
                  enum:
                    [base, student, startup, pro, promax, enterprise, custom]
                latencyMs:
                  type: integer
                  minimum: 0
                  description: Execution latency in milliseconds.
                timestamp:
                  type: string
                  format: date-time
                requestId:
                  type: string
                  format: uuid
                correlationId:
                  type: string
                  format: uuid

    # ========================================================================
    # OAUTH CONNECTION payload
    # ========================================================================
    OAuthConnectionPayload:
      type: object
      required:
        - connectionId
        - tenantId
        - providerId
        - userId
        - status
      properties:
        connectionId:
          type: string
          description: OAuth connection ULID.
        tenantId:
          type: string
          format: uuid
        providerId:
          type: string
        userId:
          type: string
          format: uuid
        providerUserId:
          type: string
          x-nullable: true
        status:
          type: string
          enum: [active, expired, revoked, refreshing, failed]
        scopes:
          type: array
          items:
            type: string
        expiresAt:
          type: string
          format: date-time
          x-nullable: true
        createdAt:
          type: string
          format: date-time

    # ========================================================================
    # INSTALLED INTEGRATION payload
    # ========================================================================
    InstalledIntegrationPayload:
      type: object
      required:
        - installationId
        - tenantId
        - marketplaceIntegrationId
        - status
      properties:
        installationId:
          type: string
          description: Installation ULID.
        tenantId:
          type: string
          format: uuid
        marketplaceIntegrationId:
          type: string
        status:
          type: string
          enum: [installing, active, paused, error, uninstalling]
        isEnabled:
          type: boolean
        executionCount:
          type: integer
          minimum: 0
        installedBy:
          type: string
          format: uuid
          x-nullable: true
        createdAt:
          type: string
          format: date-time

    # ========================================================================
    # MARKETPLACE INTEGRATION payload
    # ========================================================================
    MarketplaceIntegrationPayload:
      type: object
      required:
        - integrationId
        - tenantId
        - providerId
        - name
        - slug
        - category
        - status
        - visibility
      properties:
        integrationId:
          type: string
          description: Marketplace integration ULID.
        tenantId:
          type: string
          format: uuid
          description: Tenant UUID for multi-tenant isolation.
        providerId:
          type: string
        name:
          type: string
        slug:
          type: string
        category:
          type: string
          enum:
            [cpaas, payments, llm, maps, calendar, media, crm, analytics, other]
        version:
          type: string
        status:
          type: string
          enum: [draft, published, deprecated, archived]
        visibility:
          type: string
          enum: [public, premium, enterprise, private]
        minTier:
          type: string
          enum: [base, student, startup, pro, promax, enterprise, custom]
        pricingModel:
          type: string
          enum: [free, freemium, paid, custom]
        installationCount:
          type: integer
          minimum: 0
        averageRating:
          type: number
          minimum: 0
          maximum: 5
          x-nullable: true

    # ========================================================================
    # AUDIT LOG payload
    # ========================================================================
    AuditLogPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - auditLogId
                - tenantId
                - action
                - actor
                - resourceType
                - resourceId
              properties:
                auditLogId:
                  type: string
                  format: uuid
                tenantId:
                  type: string
                  format: uuid
                action:
                  type: string
                  description: "Action performed (e.g. credential.create, provider.update)."
                actor:
                  type: string
                  description: "Actor identifier (user ID or system:service-name)."
                resourceType:
                  type: string
                  description: "Resource type (e.g. provider, credential, integration)."
                resourceId:
                  type: string
                  description: Resource identifier.
                ipAddress:
                  type: string
                  x-nullable: true
                userAgent:
                  type: string
                  x-nullable: true
                metadata:
                  type: object
                  additionalProperties: true
                  x-nullable: true
                createdAt:
                  type: string
                  format: date-time

    # ========================================================================
    # BUDGET POLICY payload
    # ========================================================================
    BudgetPolicyPayload:
      type: object
      required:
        - budgetPolicyId
        - tenantId
        - monthlyLimit
        - currency
      properties:
        budgetPolicyId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        monthlyLimit:
          type: number
          description: Monthly spend limit (precision 12,2).
        currency:
          type: string
          description: ISO 4217 currency code.
          default: USD

    # ========================================================================
    # COMPLIANCE POLICY payload
    # ========================================================================
    CompliancePolicyPayload:
      type: object
      required:
        - compliancePolicyId
        - tenantId
        - provider
        - rules
      properties:
        compliancePolicyId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        provider:
          type: string
          description: Provider key this policy applies to.
        rules:
          type: object
          additionalProperties: true
          description: Compliance rules definition (JSON).

    # ========================================================================
    # COST ANOMALY payload
    # ========================================================================
    CostAnomalyPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - anomalyId
                - tenantId
                - provider
                - deltaUsd
              properties:
                anomalyId:
                  type: string
                  format: uuid
                tenantId:
                  type: string
                  format: uuid
                provider:
                  type: string
                deltaUsd:
                  type: number
                  description: Spend deviation in USD.
                createdAt:
                  type: string
                  format: date-time

    # ========================================================================
    # COST domain event payloads (from cost.producer.ts)
    # ========================================================================
    CostThresholdExceededPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - tenantId
                - budgetId
                - threshold
                - currentSpend
                - timestamp
              properties:
                tenantId:
                  type: string
                  format: uuid
                budgetId:
                  type: string
                  format: uuid
                threshold:
                  type: number
                  description: Budget threshold percentage (0-100).
                currentSpend:
                  type: number
                  description: Current month spend in USD.
                timestamp:
                  type: string
                  format: date-time

    CostAnomalyDetectedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - tenantId
                - anomalyId
                - providerId
                - expectedSpend
                - actualSpend
                - deviation
                - timestamp
              properties:
                tenantId:
                  type: string
                  format: uuid
                anomalyId:
                  type: string
                providerId:
                  type: string
                expectedSpend:
                  type: number
                  description: Expected spend in USD.
                actualSpend:
                  type: number
                  description: Actual spend in USD.
                deviation:
                  type: number
                  description: Deviation factor (e.g. 2.5 means 250% of expected).
                timestamp:
                  type: string
                  format: date-time

    CostForecastGeneratedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - tenantId
                - forecastId
                - period
                - predictedSpend
                - confidence
                - timestamp
              properties:
                tenantId:
                  type: string
                  format: uuid
                forecastId:
                  type: string
                period:
                  type: string
                  description: "Forecast period (e.g. 2026-03, 2026-Q1)."
                predictedSpend:
                  type: number
                  description: Predicted spend in USD.
                confidence:
                  type: number
                  minimum: 0
                  maximum: 1
                  description: Prediction confidence score (0-1).
                timestamp:
                  type: string
                  format: date-time

    # ========================================================================
    # PROVIDER HEALTH CHECK payload
    # ========================================================================
    ProviderHealthCheckPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - healthCheckId
                - tenantId
                - providerId
                - status
              properties:
                healthCheckId:
                  type: string
                  format: uuid
                tenantId:
                  type: string
                  format: uuid
                providerId:
                  type: string
                  description: Provider ULID.
                status:
                  type: string
                  enum: [healthy, degraded, unhealthy, timeout]
                details:
                  type: string
                  x-nullable: true
                  description: Additional health check details.
                createdAt:
                  type: string
                  format: date-time

    # ========================================================================
    # WORKFLOW TEMPLATE payload
    # ========================================================================
    WorkflowTemplatePayload:
      type: object
      required:
        - workflowTemplateId
        - tenantId
        - name
        - definition
      properties:
        workflowTemplateId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
          description: Tenant UUID for multi-tenant isolation.
        name:
          type: string
        definition:
          type: object
          additionalProperties: true
          description: Workflow step definitions (JSON).

    # ========================================================================
    # TENANT WORKFLOW payload
    # ========================================================================
    TenantWorkflowPayload:
      type: object
      required:
        - tenantWorkflowId
        - tenantId
        - templateId
      properties:
        tenantWorkflowId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        templateId:
          type: string
          format: uuid
        config:
          type: object
          additionalProperties: true
          x-nullable: true
          description: Tenant-specific workflow configuration overrides.

    # ========================================================================
    # WHATSAPP TEMPLATE payload
    # ========================================================================
    WhatsAppTemplatePayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - templateId
                - tenantId
                - metaTemplateId
                - name
                - language
                - status
                - category
              properties:
                templateId:
                  type: string
                  description: Internal ULID.
                tenantId:
                  type: string
                  format: uuid
                metaTemplateId:
                  type: string
                  description: Meta WhatsApp template ID.
                name:
                  type: string
                  description: "Template name (e.g. welcome_message, event_reminder)."
                body:
                  type: string
                  description: "Template body with {{1}}, {{2}} variables."
                language:
                  type: string
                  description: BCP 47 language code (en, es, hi, ar).
                status:
                  type: string
                  enum: [APPROVED, PENDING, REJECTED, DISABLED]
                category:
                  type: string
                  enum: [MARKETING, UTILITY, AUTHENTICATION]
                variableCount:
                  type: integer
                  minimum: 0
                rejectionReason:
                  type: string
                  x-nullable: true
                syncedAt:
                  type: string
                  format: date-time

    # ========================================================================
    # WHATSAPP MESSAGE payloads
    # ========================================================================
    WhatsAppMessagePayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - deliveryId
                - tenantId
                - messageId
                - recipientPhone
                - messageType
                - status
              properties:
                deliveryId:
                  type: string
                  description: Internal ULID.
                tenantId:
                  type: string
                  format: uuid
                messageId:
                  type: string
                  description: WhatsApp message ID from Meta (wamid.xxx).
                wabaId:
                  type: string
                  x-nullable: true
                  description: WhatsApp Business Account ID.
                recipientPhone:
                  type: string
                  description: Recipient phone in E.164 format.
                messageType:
                  type: string
                  enum:
                    [text, image, video, audio, document, template, interactive]
                templateId:
                  type: string
                  x-nullable: true
                  description: WhatsApp template ULID (if template message).
                status:
                  type: string
                  enum: [queued, sent, delivered, read, failed]
                costUsd:
                  type: number
                  minimum: 0
                pricingCategory:
                  type: string
                  enum: [marketing, utility, authentication, service]
                within24hWindow:
                  type: boolean
                  description: Whether message was sent within 24-hour window.
                errorCode:
                  type: string
                  x-nullable: true
                errorMessage:
                  type: string
                  x-nullable: true
                requestId:
                  type: string
                  format: uuid
                  x-nullable: true
                traceId:
                  type: string
                  x-nullable: true

    WhatsAppInboundMessagePayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - tenantId
                - messageId
                - senderPhone
                - messageType
              properties:
                tenantId:
                  type: string
                  format: uuid
                messageId:
                  type: string
                  description: WhatsApp message ID from Meta.
                wabaId:
                  type: string
                  x-nullable: true
                senderPhone:
                  type: string
                  description: Sender phone in E.164 format.
                messageType:
                  type: string
                  enum:
                    [
                      text,
                      image,
                      video,
                      audio,
                      document,
                      location,
                      contacts,
                      interactive,
                    ]
                body:
                  type: string
                  description: Message text content (if text message).
                  x-nullable: true
                timestamp:
                  type: string
                  format: date-time

    WhatsAppStatusPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - tenantId
                - messageId
                - status
                - timestamp
              properties:
                tenantId:
                  type: string
                  format: uuid
                messageId:
                  type: string
                  description: WhatsApp message ID.
                recipientPhone:
                  type: string
                status:
                  type: string
                  enum: [queued, sent, delivered, read, failed]
                errorCode:
                  type: string
                  x-nullable: true
                errorMessage:
                  type: string
                  x-nullable: true
                timestamp:
                  type: string
                  format: date-time

    WhatsAppMediaPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - tenantId
                - messageId
                - recipientPhone
                - mediaType
              properties:
                tenantId:
                  type: string
                  format: uuid
                messageId:
                  type: string
                  description: WhatsApp message ID from Meta.
                recipientPhone:
                  type: string
                  description: Recipient phone in E.164 format.
                mediaType:
                  type: string
                  enum: [image, video, audio, document]
                mediaUrl:
                  type: string
                  format: uri
                  description: S3 presigned URL or media URL.
                caption:
                  type: string
                  x-nullable: true
                mimeType:
                  type: string
                  x-nullable: true
                fileSizeBytes:
                  type: integer
                  minimum: 0
                  x-nullable: true
                timestamp:
                  type: string
                  format: date-time

    # ========================================================================
    # MESSAGING WINDOW payload
    # ========================================================================
    MessagingWindowPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - windowId
                - tenantId
                - recipientPhone
                - isOpen
              properties:
                windowId:
                  type: string
                  description: Messaging window ULID.
                tenantId:
                  type: string
                  format: uuid
                recipientPhone:
                  type: string
                  description: Recipient phone in E.164 format.
                isOpen:
                  type: boolean
                windowOpenedAt:
                  type: string
                  format: date-time
                  x-nullable: true
                windowExpiresAt:
                  type: string
                  format: date-time
                  x-nullable: true
                lastInboundAt:
                  type: string
                  format: date-time
                  x-nullable: true
                totalInboundMessages:
                  type: integer
                  minimum: 0
                totalOutboundMessages:
                  type: integer
                  minimum: 0
                windowOpenCount:
                  type: integer
                  minimum: 0

    # ========================================================================
    # OUTBOX EVENT payload
    # ========================================================================
    OutboxEventPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - outboxEventId
                - tenantId
                - aggregateType
                - aggregateId
                - eventType
                - status
              properties:
                outboxEventId:
                  type: string
                  description: Outbox event ULID (26 chars).
                aggregateType:
                  type: string
                  description: "Source entity type (e.g. provider, credential, usage)."
                aggregateId:
                  type: string
                  description: Source entity ID.
                eventType:
                  type: string
                  description: "Target event type (e.g. eventzr.integration-hub.provider.created.v1)."
                eventData:
                  type: object
                  additionalProperties: true
                  description: Original event payload (JSON).
                tenantId:
                  type: string
                  format: uuid
                  description: Tenant UUID for multi-tenant isolation.
                status:
                  type: string
                  enum: [pending, published, failed]
                retryCount:
                  type: integer
                  minimum: 0
                lastError:
                  type: string
                  x-nullable: true
                createdAt:
                  type: string
                  format: date-time
                publishedAt:
                  type: string
                  format: date-time
                  x-nullable: true

    # ========================================================================
    # SYNC domain payloads (from sync.producer.ts)
    # ========================================================================
    SyncCompletedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - syncId
                - tenantId
                - providerId
                - providerKey
                - recordsSynced
                - duration
                - completedAt
              properties:
                syncId:
                  type: string
                tenantId:
                  type: string
                  format: uuid
                providerId:
                  type: string
                providerKey:
                  type: string
                recordsSynced:
                  type: integer
                  minimum: 0
                  description: Number of records synced in this run.
                duration:
                  type: integer
                  minimum: 0
                  description: Duration in milliseconds.
                completedAt:
                  type: string
                  format: date-time

    SyncFailedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - syncId
                - tenantId
                - providerId
                - providerKey
                - error
                - failedAt
              properties:
                syncId:
                  type: string
                tenantId:
                  type: string
                  format: uuid
                providerId:
                  type: string
                providerKey:
                  type: string
                error:
                  type: string
                  description: Error message describing the failure.
                failedAt:
                  type: string
                  format: date-time

    # ========================================================================
    # SYNC JOB payload
    # ========================================================================
    SyncJobPayload:
      type: object
      required:
        - syncJobId
        - tenantId
        - providerId
        - name
        - syncType
        - syncDirection
        - status
      properties:
        syncJobId:
          type: string
          description: Sync job ULID.
        tenantId:
          type: string
          format: uuid
        providerId:
          type: string
        name:
          type: string
        syncType:
          type: string
          enum: [scheduled, on-demand, event-driven]
        syncDirection:
          type: string
          enum: [inbound, outbound, bidirectional]
        cronSchedule:
          type: string
          x-nullable: true
          description: "Cron expression (e.g. 0 * * * *)."
        conflictResolution:
          type: string
          enum: [last_write_wins, provider_wins, eventzr_wins, manual]
        status:
          type: string
          enum: [active, paused, running, failed, disabled]
        totalRuns:
          type: integer
          minimum: 0
        totalRecordsSynced:
          type: integer
          minimum: 0
        totalConflicts:
          type: integer
          minimum: 0
        failureCount:
          type: integer
          minimum: 0
        lastSyncAt:
          type: string
          format: date-time
          x-nullable: true
        nextRunAt:
          type: string
          format: date-time
          x-nullable: true

    # ========================================================================
    # SYNC EVENT payload
    # ========================================================================
    SyncEventPayload:
      type: object
      required:
        - syncEventId
        - tenantId
        - syncJobId
        - status
      properties:
        syncEventId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        syncJobId:
          type: string
          description: Parent sync job ULID.
        status:
          type: string
          description: "Individual record sync status (e.g. ok, skipped, error)."
        detail:
          type: string
          x-nullable: true
        createdAt:
          type: string
          format: date-time

    # ========================================================================
    # WEBHOOK domain payloads (from webhook.producer.ts)
    # ========================================================================
    WebhookReceivedPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - webhookId
                - tenantId
                - providerId
                - providerKey
                - url
                - method
                - receivedAt
              properties:
                webhookId:
                  type: string
                tenantId:
                  type: string
                  format: uuid
                providerId:
                  type: string
                providerKey:
                  type: string
                url:
                  type: string
                  format: uri
                method:
                  type: string
                  enum: [GET, POST, PUT, PATCH, DELETE]
                headers:
                  type: object
                  additionalProperties:
                    type: string
                payload:
                  type: object
                  additionalProperties: true
                  description: Raw webhook payload from provider.
                receivedAt:
                  type: string
                  format: date-time

    WebhookDeliveredPayload:
      allOf:
        - $ref: "#/components/schemas/CloudEventEnvelope"
        - type: object
          properties:
            data:
              type: object
              required:
                - webhookId
                - tenantId
                - providerId
                - url
                - status
                - deliveredAt
              properties:
                webhookId:
                  type: string
                tenantId:
                  type: string
                  format: uuid
                providerId:
                  type: string
                url:
                  type: string
                  format: uri
                status:
                  type: integer
                  description: HTTP status code from target service.
                deliveredAt:
                  type: string
                  format: date-time
