Skip to content

feat: log liq_trade, liq_transfer and liq_event lines from committed events [RAI-3104] - #1696

Open
JuaniRios wants to merge 1 commit into
rai-2998-alert-kindfrom
rai-2998-event-lines
Open

JuaniRios wants to merge 1 commit into
rai-2998-alert-kindfrom
rai-2998-event-lines

Conversation

@JuaniRios

@JuaniRios JuaniRios commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Part of RAI-3104.

The bot now writes liq_trade, liq_transfer, and liq_event log lines from committed events, each with a stable event_id. Item 5 of the RAI-2998 stack, the part that #1695 left out.

Live effect: new INFO lines on three new targets. Dashboard broadcast and trade delivery are unchanged · Risk: low to medium (one extra SQLite read per trade event inside the commit's reactor dispatch, and more log volume) · Ships: with the next bot release, but not before the merge condition below

Merge condition

Switch st0x-event-sorcery and sqlite-es in Cargo.toml back to a released tag before merge. Both pin a git rev of ST0x-Technology/event-sorcery#64 for now, cause that's where Reactor::react_committed lives and it isn't released yet. Order: merge event-sorcery#64, release it (v0.3.2 or whatever it gets), bump the tag here, then merge this. Plus the same conditions as the stack below.

Why

The board (item 6b) needs real trade and transfer rows from the bot instead of the exporter's liquidity-trades and liquidity-transfers logs. Each line needs an id that doesn't change across restarts, so a duplicate is harmless. The id is <aggregate type>:<aggregate id>:<sequence>, and the sequence comes from the event store.

Writing lines from evolve() would re-log everything on every replay. The Reactor trait dropped the sequence, so that needed event-sorcery#64 first.

What

  • Broadcaster overrides react_committed. react and react_committed share handle(event, Option<Committed>). Lines only get written with a commit, so replay, hydration, view rebuilds, and the handoff retry path write nothing.
  • src/dashboard/event_lines.rs:
    • liq_trade: one line per terminal trade. Fields event_id, id, occurred_at, venue, direction, symbol, shares, status, error, price (Trade.price from feat: carry the fill price on the dashboard trade [RAI-3101] #1693), and usd (shares * price). A venue correction (SourceAttributed) writes the trade again with the new venue.
    • liq_transfer: one line per status change. Fields event_id, kind, id, symbol, direction, amount, status, started_at, and usd. Equity is valued at the symbol's mark when the event commits (empty with no live mark). USDC is valued at its amount. The last status per transfer is kept in memory to skip events that don't change it.
    • liq_event: one line per committed trade or transfer event. Fields event_id, parent (trade or transfer), venue or kind, id, sequence, step, and payload. step and payload have the same shape as the /liquidity-read/.../events endpoints, and those now share the helpers.
    • Every line always has the same fields. A value that isn't known is "".
  • New targets in DOMAIN_TARGETS and in the docs/observability.md targets table, plus a section with the full contract.

Decisions

  • payload is a JSON string, not a nested object (tracing has no stable nested fields). 6b's detail.js has to JSON.parse it.
  • signature and raw values are redacted at any depth in payload. Some events persist a signed mint authorization or a signed tx before it's delivered or broadcast, and those shouldn't sit in Cloud Logging. Tested on the real events.
  • Position events get no liq_event: they belong to no trade or transfer.
  • I added occurred_at to liq_trade even though the plan didn't list it. The exporter used it as the row time, and a caught-up onchain fill would otherwise show the catch-up time.

Known gaps (honest list)

  • At most once. A crash between the commit and the reactor, or a failed entity reload in the reactor (WARN on dashboard with the event_id), loses the line for good.
  • Stores built without the Broadcaster write no lines: send_command and the operator paths with their own store (CLI manual transfers, fails, reconciles, clear-pending-burn, and the hedge release). Those events still reach the events table and the event endpoints. Fixing that means routing them through the conductor's stores, so it's a follow-up, not this PR.
  • The lines live in the dashboard Broadcaster. Stage 6 retires the dashboard, so it must move them out first.

Proof

  • Exact field sets and values for every line type, transfer dedupe (including terminal statuses and Failed to Reconciled), redaction, and USD with and without a mark.
  • Through real stores: an onchain fill writes liq_event and liq_trade with OnChainTrade:<id>:1. Then a restart (new store, view rebuild_all, load_entity) writes nothing, and the next command writes :2. Also a failed counter trade, a USDC bridge, a source correction, a Position event (no line), and react without a commit (no line).
  • Full cargo nextest run -p st0x-hedge -p st0x-config --all-features: 5350 of 5351 pass. The one failure is the known anvil timing flake in api::tests (a_signed_burn_that_fails_to_record_releases_its_nonce), and it passes alone. Clippy, fmt, and pre-commit are clean.
  • Multi-model review (sol, Cursor Grok, composer, flash, opus), 4 passes. Pass 1 found 2 highs (signed material in payloads) plus mediums on transfer dedupe and docs. All fixed. Passes 2 and 3 were lows only, fixed. Pass 4 had one low left (this repo's docs/cqrs.md doesn't mention react_committed yet). I left that for the tag bump, since the upstream docs cover it.
  • Not verified: real lines on staging. That needs log_format = "json" and t0.devops#792, which this PR doesn't flip.

@linear-code

linear-code Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

RAI-2998

RAI-3063

RAI-3104

@JuaniRios

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

JuaniRios commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label add-to-gt-merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@JuaniRios
JuaniRios force-pushed the rai-2998-event-lines branch from 45fb360 to b3a7815 Compare October 10, 2026 00:18
@JuaniRios
JuaniRios force-pushed the rai-2998-alert-kind branch from fbd6bef to 94cbce9 Compare October 10, 2026 01:15
@JuaniRios
JuaniRios force-pushed the rai-2998-event-lines branch 2 times, most recently from 675357a to f87b405 Compare October 10, 2026 01:58
@JuaniRios
JuaniRios force-pushed the rai-2998-alert-kind branch from 94cbce9 to 93e82b9 Compare October 10, 2026 01:58
@JuaniRios
JuaniRios force-pushed the rai-2998-event-lines branch from f87b405 to 703b653 Compare October 10, 2026 02:39
@JuaniRios
JuaniRios force-pushed the rai-2998-alert-kind branch 2 times, most recently from 2d7244c to 86403e8 Compare October 10, 2026 03:14
@JuaniRios
JuaniRios force-pushed the rai-2998-event-lines branch from 703b653 to 6421f57 Compare October 10, 2026 03:14
@JuaniRios
JuaniRios force-pushed the rai-2998-event-lines branch from 6421f57 to e0ddd8c Compare October 10, 2026 04:11
@JuaniRios
JuaniRios force-pushed the rai-2998-alert-kind branch from 86403e8 to 7320f93 Compare October 10, 2026 04:11
This was referenced Oct 10, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant