Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Reading the market — providers, subscribers, rates

audience: ai

With the bridge registered (binding), its observation loop can start consuming the Compute module’s public surfaces. There are three of them that a bridge watches:

  1. The ProviderCard collection — every provider in the coalition, the bridge included. This is how the bridge sees its competitors’ declared rates, TDX posture, and region coverage.
  2. Subscriber cardinality — the count of coalition agents bonded to this bridge’s own card. Rises and falls with the bridge’s competitiveness.
  3. The clearing-record stream — one commit per clearing round, exposing the cleared price and the winning provider.

Wrapped non-mosaik signals (cloud list prices, bare-metal amortisation) come from chapter 4. This chapter stays on mosaik surfaces.

Why the on-mosaik reads are useful

The same reasons they are useful on the consumer side. Every commit on ProviderCard and every clearing record carries blake3 pointers back into the commits it folded, so an auditor can reconstruct a clearing decision without trusting the scheduler committee. The Compute module’s own Almanac integration stamps every commit, so the bridge’s rate-adjustment loop, card-refresh cadence, and retirement decision all sequence on the same clock. Reads stay live while the TicketValidator keeps admitting the module’s Config; there is no centralised rate-limit and no revocation list.

Reading the ProviderCard collection

The module’s Collection<ProviderId, ProviderCard> is the full roster — the bridge’s own card plus every competitor’s. The bridge subscribes and treats it as the ground truth of who else is in the market:

use coalition_compute::{
    ProviderCardCollection, ProviderCard, ProviderId,
};

let mut roster = network
    .subscribe::<ProviderCardCollection>(
        compute_cfg.stable_id(),
    ).await?;

while let Some(ev) = roster.next().await {
    let ProviderCard {
        provider_id,
        capabilities,
        declared_rates,
        tdx_quote,
        refreshed_at,
        ..
    } = ev;

    if provider_id == self_id { continue; }

    market_view.upsert(
        provider_id,
        CompetitorView {
            tdx_capable:      capabilities.tdx_capable,
            regions:          capabilities.regions,
            rates:            declared_rates,
            tdx_measurements: tdx_quote.measurements(),
            last_seen:        refreshed_at,
        },
    );
}

The bridge does not filter out stale cards; the scheduler does that at clearing time. The market_view carries every card the bridge has ever seen so the dashboard can show the operator the full field.

What determines which bridge wins

Four parameters on the card drive clearing. The declared rate is the most visible. Region coverage filters early — grants often request a region, and only bridges whose capability union covers it are eligible. TDX posture is either-or (grants marked tdx = required filter non-TDX bridges out entirely). Some grants pin a specific tdx_mrtd the bridge’s backend must launch nested guests under (the bare-TDX case); mismatches filter.

A bridge with regions no competitor covers (bare- TDX in a jurisdiction without cloud TDX, say) can quote rates competitors cannot touch. A bridge quoting above-market in a crowded region sits idle.

Watching subscriber cardinality

The dashboard surfaces the count of coalition agents bonded to the bridge’s own provider card:

let subscribers = network
    .bond_count(
        compute_cfg.stable_id(),
        self_id,
    ).await?;

dashboard.record(DashboardEvent::SubscriberCount {
    count: subscribers,
}).await;

One integer. No identities cross the layer. What the number says depends on how it moves. A rising count that holds means the bridge’s rates, regions, and posture are competitive. A rising count that then falls means the bridge registered but cannot honour grants — scheduler clears work to the bridge, the bridge fails to provision, the reputation organism (chapter 7) scores down, agents unbond. A count falling all at once means Measurements rotated without a card republish, or a competitor undercut on the main region.

Reading clearing records

The Compute module commits one ClearingRecord per round:

pub struct ClearingRecord<'a> {
    pub round:           AlmanacTick,
    pub winning_provider: ProviderId,
    pub clearing_rate:   RateQ64, // $/core-hour, q64
    pub region:          &'a str,
    pub tdx_required:    bool,
    pub evidence:        UniqueId,
}

The bridge aggregates into a rolling rate view and lets its rate-control policy propose adjustments:

let mut clearings = network
    .subscribe::<ClearingRecords>(
        compute_cfg.stable_id(),
    ).await?;

while let Some(r) = clearings.next().await {
    rate_view.window_mut()
        .ingest(r.region, r.clearing_rate, r.round);
    if let Some(delta) = rate_view.recommend_delta() {
        rate_controller.propose_rate_change(delta);
    }
}

Clearings are public; losing bids are not. A bridge sees what won, not what else was offered. Rate recalibration is policy, not substrate: the rate_controller can be a moving-average bidder, a reinforcement-learning agent, or an operator-set lever. The declared rates are folded into the provider card’s content, so changing them re-derives the card; competitors reading the card see the new rates with evidence pointers back to the clearing records that drove the change.

Cross-lattice subscriptions are not a thing here

Unlike the searcher in web3, a compute-bridge does not subscribe to multiple coalitions from one process. A bridge serves one coalition’s Compute module; to serve several, run several bridges. Each one has its provider card pinned to one compute_cfg.stable_id(). The running cost is low — same backends, same TDX image, different COALITION_CONFIG_PATH.

Self-observation is operator-facing

The bridge computes rolling aggregates for the dashboard:

pub struct BridgeObservation {
    pub tick:             AlmanacTick,
    pub subscribers:      u32,
    pub active_grants:    u32,
    pub window_cleared:   u64,
    pub rank_in_market:   u16, // 1 = cheapest in our region
    pub rate_diff_bps:    i16, // basis points vs median
    pub evidence:         &'a [EvidencePointer<'a>],
}

Unlike the searcher’s Observation stream, this does not get published on any public mosaik surface. The operator reads it locally. Publishing it would leak the bridge’s rate strategy to competitors.

Cross-references