{
  "contract": "editorial-orchestrator-events-v1",
  "schema_version": "2026-07-15",
  "updated": "2026-07-15",
  "purpose": "Versioned, metadata-only event contract for editorial systems. Edpol publishes the contract; each producer owns delivery, storage and retry state.",
  "delivery": {
    "transport": "HTTPS webhook",
    "authentication": "QazStack v1 timestamped HMAC-SHA256 over '<timestamp>.<exact request body>'",
    "requiredHeaders": [
      "Content-Type: application/json",
      "Idempotency-Key",
      "X-QazStack-Timestamp",
      "X-QazStack-Event-Id",
      "X-QazStack-Signature: v1=<hex>"
    ],
    "deliverySemantics": "at-least-once",
    "consumerRule": "Consumers must deduplicate by eventId and Idempotency-Key before applying side effects.",
    "retry": {
      "strategy": "exponential backoff with jitter",
      "maxAttempts": 8,
      "retryableStatusCodes": [408, 425, 429, 500, 502, 503, 504],
      "terminalHandling": "Persist the failed delivery in the producer-owned dead-letter store and expose it to operators."
    },
    "preferredProfile": {
      "schemaVersion": "qazstack-editorial-webhook-v1",
      "envelopeSchema": "/schemas/qazstack-editorial-webhook-v1.schema.json",
      "timestampToleranceSeconds": 300,
      "supportsSecretRotation": true,
      "consumerReplayRule": "Verify timestamp and signature before decoding, then claim eventId in durable consumer storage before side effects."
    },
    "legacyProfile": {
      "status": "deprecated-but-accepted",
      "envelopeSchema": "/schemas/editorial-event-envelope.schema.json",
      "requiredHeaders": [
        "Idempotency-Key",
        "X-Edpol-Event-Id",
        "X-Edpol-Event-Type",
        "X-Edpol-Signature: sha256=<hex>"
      ],
      "migrationRule": "Total.kz may keep the legacy profile until its producer adapter is upgraded and verified. Removal requires two production release cycles, at least 30 days and a successful replay-safe live smoke.",
      "notBeforeRemoval": "2026-08-15"
    }
  },
  "privacy": {
    "forbidden": [
      "article body",
      "raw evidence",
      "source credentials",
      "reader personal data",
      "unnecessary reviewer personal data"
    ],
    "allowed": [
      "stable article reference",
      "content fingerprint",
      "policy version",
      "decision state",
      "typed evidence metadata without raw evidence",
      "opaque reviewer references",
      "risk and language states"
    ]
  },
  "eventTypes": [
    {
      "type": "editorial.article.changed",
      "producer": "CMS",
      "purpose": "A material revision changed; any prior decision should be re-evaluated against the new fingerprint."
    },
    {
      "type": "editorial.decision.recorded",
      "producer": "CMS",
      "purpose": "A local quality-gate decision was recorded for a concrete article revision."
    },
    {
      "type": "editorial.review.required",
      "producer": "CMS or Shield",
      "purpose": "A required editorial, legal or safety review is pending."
    },
    {
      "type": "editorial.correction.required",
      "producer": "CMS",
      "purpose": "A correction, update, takedown or right-of-reply requires cross-system handling."
    },
    {
      "type": "editorial.correction.published",
      "producer": "CMS or Qposter",
      "purpose": "A visible correction record was attached to the original material and its required distribution state was recorded."
    },
    {
      "type": "editorial.trust.updated",
      "producer": "CMS",
      "purpose": "Reader-facing trust metadata changed for a concrete article revision."
    },
    {
      "type": "editorial.publication.completed",
      "producer": "CMS",
      "purpose": "A reviewed revision was published and may be distributed by Qposter."
    }
  ],
  "schemas": {
    "eventEnvelope": "/schemas/editorial-event-envelope.schema.json",
    "qazstackWebhookEnvelope": "/schemas/qazstack-editorial-webhook-v1.schema.json",
    "editorialDecision": "/schemas/editorial-decision.schema.json",
    "evidenceReference": "/schemas/evidence-reference.schema.json",
    "editorialCase": "/schemas/editorial-case.schema.json",
    "articleTrustMetadata": "/schemas/article-trust-metadata.schema.json",
    "correctionRecord": "/schemas/correction-record.schema.json"
  },
  "ownership": {
    "edpol": "Publishes this contract and policy requirements only.",
    "CMS": "Owns article state, event outbox, delivery audit and publication side effects.",
    "QazPipe": "Owns collection, capture manifests and freshness behind typed metadata references.",
    "QazLake": "Owns raw and durable evidence artifacts, archive references, retention and retrieval indexes.",
    "Shield": "Owns risk scoring and casework.",
    "Qalam": "Owns translation and language-parity QA.",
    "Qposter": "Owns channel delivery and correction propagation."
  }
}
