Files
Aura/crates/aura-ingest/tests/instrument_spec_deploy_metadata.rs
T
Brummel b91c89f964 feat(broker-foundation): InstrumentSpec deploy metadata + PositionEvent schema
The realistic-broker milestone's (C10 A-side) two foundation value types — no
broker, no derivation yet, fully tested.

#113 — InstrumentSpec gains six deploy-grade fields (instrument_id,
contract_size, pip_value_per_lot, min_lot, lot_step, quote_currency) and the
vetted table is populated for GER40/FRA40/EURUSD/GBPUSD/USDCAD. The struct stays
Copy (quote_currency is &'static str); the _ => None refuse-don't-guess arm is the
permanent floor. This is the milestone's permanent authored floor (recorded-metadata
tier is forward work, #124).

#114 — PositionAction { Buy, Sell, Close } (closed enum, serde-encoded as a bare
i64 0/1/2 via From/TryFrom) + PositionEvent in aura-engine beside RunMetrics,
faithful to the C10 column spec: event_ts, action, position_id, instrument_id,
unsigned volume; no open_ts; direction is the action (no signed-volume trick).
Re-exported from the crate root.

Derived fork decisions (recorded on #113): quote_currency &'static str; action as
ordinal i64; stable instrument_id + overridable vetted values.

Verified by the orchestrator: cargo test --workspace = 458 passed / 0 failed;
clippy --all-targets -D warnings clean. An adversarial 4-lens review (ledger
faithfulness, downstream soundness, serde/wire robustness, test honesty) returned
3 SOUND + 1 CONCERN: quote_currency &'static str cannot hold a runtime-sourced
currency at the #124 resolver — not a blocker (#115/#116 read only the authored
floor), logged on #124 as a deliberate deferred design choice. The implementer's
deviation from the plan snippet (vec![..] -> [..]) avoids clippy::useless_vec;
semantics identical.

Two tester-authored consumer-boundary E2E tests added beyond the inline units:
instrument_spec_deploy_metadata.rs (public resolution seam) and
position_event_table.rs (persisted bare-int wire shape + reversal table).

closes #113 #114
2026-06-22 19:51:17 +02:00

73 lines
3.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! End-to-end verification of the public instrument-spec resolution seam
//! (#113): a downstream broker resolves deploy-grade metadata by symbol through
//! `aura_ingest::instrument_spec` — the permanent authored floor of the
//! milestone's override hierarchy (#124). These tests pin the *consumer-visible*
//! contract (the public return shape + the refuse-don't-guess arm), distinct
//! from the crate-internal literal-table unit tests.
use aura_ingest::{instrument_spec, InstrumentSpec};
/// The vetted symbols a deploy step may ask for. Kept here (not imported) so the
/// test fails loudly if the public lookup ever stops resolving one of them.
const VETTED: [&str; 5] = ["GER40", "FRA40", "EURUSD", "GBPUSD", "USDCAD"];
/// Property: every vetted symbol resolves through the *public* lookup to a fully
/// populated `InstrumentSpec` whose six deploy fields are all present and sane
/// (positive sizes, a non-empty quote currency). This is the floor a broker
/// reads before sizing a lot; a regression that left any field at a placeholder
/// (0.0 / "") or dropped a symbol from the table would size positions wrong with
/// no error. Asserts only the consumer-visible guarantees, not the exact vetted
/// literals (those are the crate's own unit test's remit).
#[test]
fn every_vetted_symbol_resolves_to_a_complete_spec() {
for sym in VETTED {
let s: InstrumentSpec = instrument_spec(sym).unwrap_or_else(|| {
panic!("vetted symbol {sym} must resolve through the public lookup")
});
assert!(s.instrument_id > 0, "{sym}: instrument_id must be a real (>0) id");
assert!(s.pip_size > 0.0, "{sym}: pip_size must be positive");
assert!(s.contract_size > 0.0, "{sym}: contract_size must be positive");
assert!(s.pip_value_per_lot > 0.0, "{sym}: pip_value_per_lot must be positive");
assert!(s.min_lot > 0.0, "{sym}: min_lot must be positive");
assert!(s.lot_step > 0.0, "{sym}: lot_step must be positive");
assert!(!s.quote_currency.is_empty(), "{sym}: quote_currency must be labelled");
}
}
/// Property: the cross-field deploy invariant `pip_value_per_lot ==
/// contract_size * pip_size` holds for every vetted instrument as a downstream
/// broker observes it through the public lookup. A broker computing pip P&L may
/// use either `pip_value_per_lot` directly or derive it from contract_size ×
/// pip_size; this pins that the two paths agree, so the choice is free. A future
/// table edit that broke the identity (e.g. a typo'd pip_value) would silently
/// double or halve every realistic-broker P&L.
#[test]
fn pip_value_is_consistent_with_contract_and_pip_at_the_public_boundary() {
for sym in VETTED {
let s = instrument_spec(sym).expect("vetted symbol");
let derived = s.contract_size * s.pip_size;
assert!(
(s.pip_value_per_lot - derived).abs() < 1e-9,
"{sym}: pip_value_per_lot {} must equal contract_size {} * pip_size {} = {}",
s.pip_value_per_lot,
s.contract_size,
s.pip_size,
derived,
);
}
}
/// Property: an un-vetted symbol resolves to `None` — the refuse-don't-guess
/// honesty lever (#113). A broker that asked for a symbol with no authored floor
/// must get nothing back, never a fabricated/defaulted spec, so deploy fails
/// loudly rather than sizing on a guessed pip value. A regression that returned
/// a `Some(default)` for unknown symbols is exactly the silent-guess failure
/// this guards.
#[test]
fn unvetted_symbol_refuses_with_none() {
assert_eq!(instrument_spec("NOT_A_REAL_SYMBOL"), None);
assert_eq!(instrument_spec(""), None);
// case sensitivity is part of the refuse arm: the table is exact-match only.
assert_eq!(instrument_spec("ger40"), None);
}