unrip/docs/contracts.md

2.5 KiB

Event contracts

Envelope

All bus messages use this envelope:

{
  "event_id": "string",
  "event_type": "string",
  "venue": "string",
  "source": "string|null",
  "schema_version": 1,
  "observed_at": "ISO-8601|null",
  "ingested_at": "ISO-8601",
  "payload": {},
  "raw": {}
}

Topics

Current canonical topic set:

  • raw.near_intents.quote
  • norm.swap_demand
  • cmd.execute_trade
  • exec.trade_result

In Kubernetes bootstrap, Redpanda topic creation is currently handled by the repo-managed bootstrap job applied with the manifest set.

raw.near_intents.quote

  • event_type: near_intents_quote_raw
  • payload.message: original venue-native payload
  • raw: original venue-native payload

norm.swap_demand

  • event_type: swap_demand
  • payload:
    • quote_id
    • asset_in
    • asset_out
    • amount_in
    • amount_out
    • ttl_ms

cmd.execute_trade

  • event_type: execute_trade
  • payload:
    • command_id
    • idempotency_key
    • execution_key
    • quote_id
    • asset_in
    • asset_out
    • amount_in
    • amount_out
    • reason

exec.trade_result

  • event_type: trade_result
  • payload:
    • command_id
    • idempotency_key
    • execution_key
    • quote_id
    • status
    • result_code
    • note

Executor idempotency model

  • command_id is unique per trade command and currently deterministic as cmd-${quote_id}
  • idempotency_key is stable for semantic duplicate detection and currently ${venue}:${quote_id}
  • execution_key is the stable partition key and currently ${venue}:${asset_in}->${asset_out}
  • executor persists command state on durable storage before publishing a result
  • already-completed command_ids are skipped on replay or restart
  • if a command is seen again after a persisted processing state, the executor emits a recovered result path instead of blindly duplicating work

Deployment and persistence implications

These contracts are tied to deployment behavior:

  • executor duplicate suppression depends on durable persistence at EXECUTOR_STATE_DIR
  • local Compose mounts that path for development/runtime testing
  • the Hetzner single-node k3s path mounts persistent storage for the executor at /var/lib/unrip/executor-state
  • in the current single-node target, that persistence is node-backed and should be treated as required operational state

Operational consequence:

  • deleting the executor PVC or losing the node without migration discards idempotency history
  • that can allow already-seen commands to be treated as new after recovery