# C15 — Resampling-as-node; sessions/calendars **Guarantee.** A resampler is a node (finer stream → coarser bar stream), clock-sensitive, emitting a completed bar only at the boundary (C2). Calendars and instrument specs are **metadata** — non-scalar reference data held beside the hot path, never streamed. Session *context* is exposed as scalar streams via a `SessionNode`, so "the 3rd 15m candle after session open" is a plain node checking `bars_since_open == 3`, not special-cased session logic. **Forbids.** Streaming the calendar; special-casing session logic outside the stream model. **Why.** Keeps the line consistent — everything a signal needs arrives as a stream; reference data feeds source/session nodes from beside the hot path. ## Current state **Session context — `bars_since_open` is the shipped contract (#154).** The session-context node `Session` (`crates/aura-market/src/session.rs`) emits **one** scalar stream, `bars_since_open: i64` (tz-aware, DST-correct, over a baked Frankfurt open), and takes no scalar params; the zero-arg `SessionFrankfurt` roster preset (#261) exposes it with a single `period_minutes` knob. This is a deliberate narrowing pinned in the node's own contract: `bars_since_open` alone is the gate — a downstream `EqConst(== N)` subsumes an `in_session: bool` stream (pre-open instants read `<= 0`, which never match), and nothing consumes a `session_open_ts: timestamp`. The two further session-context streams the design intent names — `in_session: bool` and `session_open_ts: timestamp` — remain **deferred** until a consumer needs them (#154); the stream model is untouched, session context is still exposed as scalar streams fed from beside the hot path. **Instrument geometry — recorded sidecar, refuse-don't-guess.** The "instrument specs are metadata" half is realized by the **recorded geometry sidecar**: `aura_ingest::instrument_geometry(server, symbol)` returns the neutral, broker-agnostic `InstrumentGeometry` (re-exported from `data_server::meta`; the raw provider JSON never enters this repo) — non-scalar reference data keyed by symbol, held beside the hot path. It feeds the sim-optimal broker's pip divisor (C10; consumed in `aura-runner`): the real-path pip is sourced from `InstrumentGeometry.pip_size`, and geometry that is absent is **refused, not guessed**. There is no Rust-authored instrument floor — `InstrumentSpec` / `instrument_spec` and the vetted table were removed once the sidecar supplied the real-path pip. The speculative deploy-grade fields and the authored override/floor tiers of the #124 hierarchy (tier 1 override, tier 3 floor), together with the `quote_currency` runtime-type transition, are **deferred** until a consumer — the cost model's currency→R normalization (C10) or the live deploy edge (real broker) — needs them, read from the sidecar geometry then; #124 collapses to *recorded sidecar geometry → refuse* in the meantime. ## See also - [C2](c02-causality.md) — the resampler emits a bar only once complete - [C8](c08-node-contract.md) — the node contract the resampler and session node obey - [C10](c10-bias-r-cost.md) — the pip divisor and currency→R normalization the geometry feeds - [C11](c11-sources-record-replay.md) — reference data fed from beside the hot path > History: [c15-resampling-sessions.history.md](c15-resampling-sessions.history.md)