# LegacyHUB — dispatch participant contract Status: draft · 2026-06-15 · D4 / 08_DECISIONS, INTER_MODULE_CONTRACT §2 LegacyHUB joins the shared platform RabbitMQ via `dispatch-api` (not directly). Internal background work stays on Celery+Redis; this contract covers only the inter-module bus. ## Participant | Field | Value | |---|---| | `participant_code` | `legacyhub` | | `participant_type` | `service` | | Auth to dispatch-api | `X-API-Key` (env `DISPATCH_API_KEY`) | | Delivery mode (inbound) | `http_inbox` → `POST /api/v1/dispatch/inbox` + business-confirm | | Inbox auth | service `X-API-Key` (`require_service_api_key`) | Configuration: `DISPATCH_ENABLED`, `DISPATCH_API_URL`, `DISPATCH_API_KEY`, `DISPATCH_PARTICIPANT_CODE`, `DISPATCH_TIMEOUT_SECONDS`. ## Envelope (INTER_MODULE_CONTRACT §2.4) ```json { "message_id": "", "event_id": "", "card_uid": "", "message_type": "", "participant_code": "legacyhub", "created_at": "", "body": { "...": "JSON only — no binary, no presigned URLs, no local paths" } } ``` ## Published events | `message_type` | When | Body (JSON) | |---|---|---| | `LegacyhubDocumentIndexed` | After a document reaches `INDEXING_COMPLETED` (post-commit) | `document_id`, and for asset ingests `asset_id`, `owner_module`, `owner_record_type`, `owner_record_id`, `manifest_version` | | `AssetDerivativeReady` | After OCR/markdown derivative is produced for an asset ingest (respects `ingest_options.emit_events`) | `event_type=AssetDerivativeReady`, `asset_id`, `owner_*`, `derivative_type=ocr_markdown`, `content_type=text/markdown`, `source_asset_sha256`, `generator{pipeline,version}` | Idempotency: `event_id = uuid5(namespace, business-key)`, so re-emits of the same indexing/derivative are de-dupable by consumers. ## Subscriptions (inbound) | `message_type` | Action | |---|---| | `ReindexRequested` / `LegacyhubReindexRequested` | Resolve `document_id` (directly or via `asset_id`) and enqueue the Celery reindex task | Inbound delivery is at-least-once; the inbox is idempotent by `event_id` (recorded in `audit_log` as `dispatch.inbox.processed`). ## Boundaries - No direct RabbitMQ from this module — only `dispatch-api`. - No binary payloads / presigned URLs / local filesystem paths in any body (10 §7). Originals stay owner-module-owned; LegacyHUB references object storage + `asset_id` only.