Proof: Preserve the completed first live BTC/EURe trade loop and establish the next approved implementation proof around pre-credit funding visibility and operator alerts. Assumptions: The live-trade loop is sufficiently proven by the recorded deposits, withdrawals, durable command/result chain, and successful mainnet quote responses; the next highest-value slice is operational visibility rather than new execution breadth. Still fake: The newly opened funding-visibility and alert turn is planning only; no pre-credit watcher or durable alert evaluator is implemented yet.
7.1 KiB
Implementation Turn: pre-credit funding visibility and operator alerts
Status: open Opened: 2026-04-02
Goal
Make the already-live BTC/EURe loop operationally understandable between external funding and spendable credit, and make critical stale or failed states queryable as durable alert records instead of transient logs.
Selected backlog items
- [O003] Alerts for stale reference prices, stale inventory state, stuck funding actions, and failed executor submissions.
- [O004] Pre-credit funding visibility for slow chains: watch configured deposit addresses at chain level, track inbound transfers through mempool and on-chain confirmation before bridge credit, persist that state separately from spendable inventory, and alert operators when funding is seen, delayed, or stuck.
Design rule
Keep the already-proven execution and inventory truth path intact:
- verifier and bridge credit remain the only spendable truth
- pre-credit visibility is additive observability
- alerts are additive operability
Event backbone
Retain Kafka as the backbone. Add only the minimal new topics required:
ops.funding_observationops.alert
These topics are append-only evidence streams, not control planes.
Durable store
Extend PostgreSQL with new append-only families:
funding_observationsops_alerts
If a current-state materialization is needed, derive it from append-only records or keep it as a clearly named snapshot table. Do not replace the append-only record.
Service changes
1. liquidity-manager
Extend the existing treasury owner instead of inventing a broad new funding stack.
New responsibilities:
- retain active funding handles by chain and asset
- poll configured chain observers for those handles
- emit
ops.funding_observation - correlate chain observations with bridge
recent_deposits - expose latest observations and credit-correlation state through
/state
Expected state shape additions:
funding_observations_by_handlelatest_funding_observation_atuncredited_funding_total_by_assetcredit_correlation
Control additions:
POST /refresh-funding-observations- optional
POST /pause-funding-observer - optional
POST /resume-funding-observer
Important implementation constraints:
- do not change withdrawal behavior
- do not reuse spendable inventory fields for pre-credit state
- keep BTC and EURe observation records in one shared schema
2. inventory-sync
Keep current spendable accounting intact.
Possible additions:
- read the latest funding observations
- expose a separate
pre_credit_inboundorfunding_visibilityfield in/state
Hard rule:
spendable,pending_inbound, and strategy-facing credited truth must not become looser
3. history-writer
Consume and persist the new topics:
ops.funding_observationops.alert
Expose through /state:
- latest funding-observation write time
- latest alert write time
- counts or offsets for the new topics
Add query-friendly indexes for:
tx_hashfunding_handlealert_codeingested_at
4. ops-sentinel or equivalent alert evaluator
Add one small service only if needed to keep alert logic separate and testable.
Responsibilities:
- consume:
ref.market_pricestate.intent_inventoryops.liquidity_actionops.funding_observationexec.trade_result
- evaluate policy windows for stale and stuck conditions
- emit
ops.alertraise/clear transitions - expose current alert state
Preferred alert model:
- stable
alert_code status:raisedorclearedseverityreasonfirst_raised_atlast_evaluated_at- correlation IDs when available
Minimal alert set for this turn:
reference_price_staleinventory_snapshot_stalefunding_seen_unconfirmedfunding_confirmed_credit_pendingfunding_stuckexecutor_submission_failed
Do not add Slack, email, or paging integrations in this turn unless required to prove the path. Durable alert records plus HTTP state are sufficient.
Chain observer plan
BTC
Must be the first-class proof path.
Implementation expectations:
- configurable observer endpoint
- look up the configured BTC deposit address
- detect:
- mempool appearance when available
- confirmation count
- credited transition once bridge/verifier catches up
Assumption to keep explicit in code:
- a chain observer can disappear or lag independently of the bridge
Gnosis / EURe
Nice-to-have within the same schema, but BTC is the proof-critical path.
If included this turn:
- watch the configured deposit address for EURe token transfers
- represent observation state in the same event model
Record shapes
ops.funding_observation
Required fields:
funding_observation_idaccount_idasset_idchainfunding_handlesourcetx_hashstatusamountconfirmationsfirst_seen_atlast_seen_atcredited_atwhen knownbridge_deposit_tx_hashwhen correlated
ops.alert
Required fields:
alert_event_idalert_codestatusseverityreasonservice_scopepairwhen relevantasset_idwhen relevanttx_hashwhen relevantraised_atcleared_atdetails
Control surface expectations
liquidity-manager
Must expose:
- active deposit handles
- latest pre-credit funding observations
- latest credit correlation
- whether the funding observer is healthy or paused
alert evaluator
Must expose:
- current active alerts
- latest cleared alerts
- per-alert evaluation timestamps
- pause state
history-writer
Must expose the new topic offsets and write status for funding observations and alerts.
Tests
Required automated coverage:
- BTC funding observation remains non-spendable before credit
- alert transitions raise then clear on recovered stale state
- funding observation correlates to a later credited deposit without losing the original tx hash
- executor failure produces an alert event
If a meaningful automated test cannot be written for a subpath, stop and record why instead of hand-waving.
Validation plan
- Safe induced stale-price alert:
- pause
market-reference-ingest - wait past freshness window
- observe
reference_price_stale - resume and observe clear
- pause
- Safe induced stale-inventory alert:
- pause
inventory-sync - wait past freshness window
- observe
inventory_snapshot_stale - resume and observe clear
- pause
- Funding visibility proof:
- use a real deposit address
- observe pre-credit chain state before bridge credit where timing allows
- later observe credit correlation
- Executor failure alert proof:
- use a controlled non-destructive failure mode such as temporary relay endpoint override in a safe environment or a replayable failure fixture
- verify
executor_submission_failed
Out of scope on purpose
- No new trading strategy
- No historical backtest engine
- No broad observability stack
- No polished dashboard frontend
- No automated treasury refills
Still fake at turn open
- Pre-credit funding visibility is still missing from the live cluster.
- Alert state is still mostly implicit in service logs and manual inspection.
- There is no durable operator-facing record yet for "funds are on the way but not spendable."