Skip to main content

SimulationView

Struct SimulationView 

Source
pub struct SimulationView<'a> { /* private fields */ }

Implementations§

Source§

impl SimulationView<'_>

Source

pub fn plugin_archive_object( &self, namespace: &str, object_id: &str, ) -> Result<Option<Vec<u8>>, CanwuError>

Loads a package-owned cold object through the host provider attached to this runtime. Package code remains responsible for authenticating the bytes against its committed archive root before using them.

Source

pub const fn time(&self) -> SimTime

Source

pub fn army(&self, id: ArmyId) -> Result<Option<&Army>, CanwuError>

Examples found in repository?
examples/plugin.rs (line 22)
11fn set_stance(
12    view: &SimulationView<'_>,
13    context: &CommandContext,
14    payload: &Value,
15) -> Result<Vec<SystemDirective>, CanwuError> {
16    let army = ArmyId::new(
17        payload
18            .get("army")
19            .and_then(Value::as_u64)
20            .expect("payload was validated before the handler ran"),
21    );
22    let Some(army_state) = view.army(army)? else {
23        return Err(CanwuError::new(
24            ErrorCode::ArmyNotFound,
25            format!("army {army} was not found"),
26        ));
27    };
28    if context.issuer != Issuer::Actor(army_state.commander) {
29        return Err(CanwuError::new(
30            ErrorCode::InvalidAuthority,
31            "only the army commander may set its stance",
32        ));
33    }
34    Ok(vec![SystemDirective::SetComponent {
35        state: StateKey::new("military", "stance"),
36        entity: EntityRef::Army(army),
37        component: "stance".to_owned(),
38        value: payload["stance"].clone(),
39        summary: format!("Army {army} changed stance"),
40    }])
41}
Source

pub fn person(&self, id: PersonId) -> Result<Option<&Person>, CanwuError>

Source

pub fn government( &self, id: GovernmentId, ) -> Result<Option<&Government>, CanwuError>

Source

pub fn territory( &self, id: TerritoryId, ) -> Result<Option<&Territory>, CanwuError>

Source

pub fn route(&self, id: RouteId) -> Result<Option<&Route>, CanwuError>

Source

pub fn actor_knowledge( &self, actor: PersonId, ) -> Result<Option<&ActorKnowledge>, CanwuError>

Source

pub fn knowledge_record_count_in_namespace( &self, namespace: &str, ) -> Result<usize, CanwuError>

Counts records in a knowledge namespace at the current proposal-visible cut.

Source

pub fn knowledge_records( &self, holder: KnowledgeHolderRef, query: &KnowledgeQuery, ) -> Result<KnowledgeQueryResult, CanwuError>

Queries holder-relative records for an omniscient plugin system.

This enforces the declared canwu.core.knowledge read and returns an owned projection. It is not an actor-facing authorization API.

Source

pub fn command( &self, id: CommandId, ) -> Result<Option<&CommandRecord>, CanwuError>

Resolves an exact command ID from the retained runtime journal in O(1).

An archived command remains valid identity evidence, but its payload is no longer available through this view: lookup returns ErrorCode::EvidenceContentUnavailable. None means the ID has neither retained content nor a committed archive receipt.

Source

pub fn event(&self, id: EventId) -> Result<Option<&SimEvent>, CanwuError>

Resolves an exact event ID from the retained runtime journal in O(1).

An archived event remains valid identity evidence, but its payload is no longer available through this view: lookup returns ErrorCode::EvidenceContentUnavailable. None means the ID has neither retained content nor a committed archive receipt.

Source

pub fn ingress( &self, id: IngressId, ) -> Result<Option<&IngressRecord>, CanwuError>

Examples found in repository?
examples/governance_transition.rs (line 175)
167fn owned_order_ingress(
168    view: &SimulationView<'_>,
169    context: &BoundaryContext,
170    owner: &str,
171    packet_type: &str,
172) -> Result<Option<String>, CanwuError> {
173    let mut order_id = None;
174    for ingress_id in &context.admitted_ingress {
175        let Some(record) = view.ingress(*ingress_id)? else {
176            continue;
177        };
178        let IngressPayload::Plugin {
179            plugin,
180            packet_type: admitted_packet_type,
181            payload,
182            ..
183        } = &record.payload
184        else {
185            continue;
186        };
187        if plugin != owner || admitted_packet_type != packet_type {
188            continue;
189        }
190        if order_id.is_some() {
191            return Err(CanwuError::new(
192                ErrorCode::InvalidBoundary,
193                format!("{owner} received duplicate {packet_type} ingress"),
194            ));
195        }
196        let value = payload
197            .get("order_id")
198            .and_then(Value::as_str)
199            .ok_or_else(|| {
200                CanwuError::new(
201                    ErrorCode::InvalidPayload,
202                    format!("{owner}.{packet_type} is missing order_id"),
203                )
204            })?;
205        order_id = Some(value.to_owned());
206    }
207    Ok(order_id)
208}
Source

pub fn plugin_ingress_matches( &self, id: IngressId, plugin: &str, packet_type: &str, ) -> Result<bool, CanwuError>

Matches retained, plugin-generated ingress provenance without exposing its payload.

Durable evidence may cite ingress admitted at an earlier boundary, but a generated record still waiting in the scheduler is not yet admissible. Format-7 archive receipts retain a Merkle-bound compact producer proof, so archived payload bytes do not need to return to the hot path.

Source

pub fn plugin_ingress_payload_matches( &self, id: IngressId, plugin: &str, packet_type: &str, occurred_at: SimTime, expected_payload: &Value, ) -> Result<bool, CanwuError>

Matches a retained plugin ingress to an exact provider payload and delivery time. Payload inspection is deliberately limited to retained records: archived receipts prove producer identity, but cannot safely be reused to authorize a different legal proposal without the original bytes.

Source

pub fn decision_attempt( &self, request_id: DecisionRequestId, ) -> Result<Option<&DecisionAttemptRecord>, CanwuError>

Returns the retained outcome for one exact decision request.

Source

pub fn decision_controller( &self, id: &str, ) -> Result<Option<&DecisionControllerBinding>, CanwuError>

Returns one current decision-controller binding after an explicit core read.

Source

pub fn decision_ticket( &self, id: DecisionTicketId, ) -> Result<Option<&DecisionTicket>, CanwuError>

Returns one current decision ticket after an explicit core read.

Examples found in repository?
examples/uncertainty_resolution.rs (line 27)
22fn random_resolution_system(
23    view: &SimulationView<'_>,
24    context: &BoundaryContext,
25) -> Result<BoundaryProposal, CanwuError> {
26    let ticket = view
27        .decision_ticket(RANDOM_TICKET)?
28        .expect("the example opens the ticket before the daily boundary");
29    let calendar_ingress = context
30        .admitted_ingress
31        .first()
32        .copied()
33        .expect("the example runs this system from calendar ingress");
34    let option_weights = vec![
35        DecisionOptionWeight::new("fail", 25),
36        DecisionOptionWeight::new("pass", 75),
37    ];
38    let sample = view.random_sample_for_operation(
39        &decision_stream(),
40        EvidenceRef::Ingress(calendar_ingress),
41        "decision_selection",
42        "law-proposal-42",
43        RandomOperationTarget::DecisionTicket {
44            ticket_id: ticket.id,
45            ticket_version: ticket.version,
46        },
47        0,
48        100,
49        "select whether the law passes from configured weights",
50    )?;
51    Ok(BoundaryProposal {
52        directives: vec![BoundaryDirective::ResolveDecisionRandomly {
53            resolution: RandomDecisionResolution {
54                priority: 0,
55                decision_request_id: DecisionRequestId::new(3),
56                command_request_id: None,
57                ticket_id: ticket.id,
58                expected_version: ticket.version,
59                controller_id: ticket.assigned_controller.clone(),
60                sample,
61                option_weights,
62            },
63        }],
64        ..BoundaryProposal::default()
65    })
66}
Source

pub fn domain_record( &self, reference: &DomainRecordRef, ) -> Result<Option<&DomainRecord>, CanwuError>

Examples found in repository?
examples/governance_transition.rs (line 388)
366fn audit_order(
367    view: &SimulationView<'_>,
368    context: &BoundaryContext,
369) -> Result<BoundaryProposal, CanwuError> {
370    if owned_order_ingress(view, context, CENTRAL_PLUGIN, ISSUE_INGRESS)?.is_some() {
371        return Ok(BoundaryProposal::default());
372    }
373    let order = order_payload(view)?;
374    for (label, reference, expected_plugin, expected_system) in [
375        (
376            "treasury",
377            treasury_reference().as_untyped(),
378            TREASURY_PLUGIN,
379            "prepare-treasury",
380        ),
381        (
382            "county",
383            county_reference().as_untyped(),
384            COUNTY_PLUGIN,
385            "prepare-county",
386        ),
387    ] {
388        let record = view.domain_record(reference)?.ok_or_else(|| {
389            CanwuError::new(
390                ErrorCode::InvalidBoundary,
391                format!("central audit is missing the {label} relief disposition"),
392            )
393        })?;
394        let expected_hash = action_hash(600)?;
395        validate_order(&order, expected_system, expected_plugin, &expected_hash)?;
396        let actual_hash = canonical_hash(ACTION_HASH_DOMAIN, &record.payload)?;
397        if record.version != 1
398            || !record.is_active()
399            || record.owner != expected_plugin
400            || actual_hash != expected_hash
401            || record.payload != json!({"status": "committed", "grain_units": 600})
402        {
403            return Err(CanwuError::new(
404                ErrorCode::InvalidBoundary,
405                format!("central audit found an invalid {label} disposition"),
406            ));
407        }
408    }
409    Ok(BoundaryProposal::default())
410}
Source

pub fn typed_domain_record<T>( &self, reference: &TypedDomainRecordRef<T>, ) -> Result<Option<&DomainRecord>, CanwuError>

Examples found in repository?
examples/governance_transition.rs (line 211)
210fn order_payload(view: &SimulationView<'_>) -> Result<ReliefOrder, CanwuError> {
211    view.typed_domain_record(&order_reference())?
212        .ok_or_else(|| CanwuError::new(ErrorCode::InvalidBoundary, "relief order is missing"))?
213        .decode_payload::<ReliefOrderRecord>()
214}
215
216fn validate_order(
217    order: &ReliefOrder,
218    expected_system: &str,
219    expected_plugin: &str,
220    expected_hash: &str,
221) -> Result<(), CanwuError> {
222    let valid = order.order_id == ORDER_ID
223        && order.issued_by == CENTRAL_PLUGIN
224        && order.treasury_system == "prepare-treasury"
225        && order.treasury_version == 1
226        && order.treasury_disposition == "committed"
227        && order.county_system == "prepare-county"
228        && order.county_version == 1
229        && order.county_disposition == "committed"
230        && ((expected_plugin == TREASURY_PLUGIN
231            && expected_system == "prepare-treasury"
232            && order.treasury_hash == expected_hash)
233            || (expected_plugin == COUNTY_PLUGIN
234                && expected_system == "prepare-county"
235                && order.county_hash == expected_hash));
236    if !valid {
237        return Err(CanwuError::new(
238            ErrorCode::InvalidBoundary,
239            format!("{expected_plugin} received an invalid relief manifest"),
240        ));
241    }
242    Ok(())
243}
244
245fn publish_order(
246    view: &SimulationView<'_>,
247    context: &BoundaryContext,
248) -> Result<BoundaryProposal, CanwuError> {
249    let Some(order_id) = owned_order_ingress(view, context, CENTRAL_PLUGIN, ISSUE_INGRESS)? else {
250        return Ok(BoundaryProposal::default());
251    };
252    if order_id != ORDER_ID {
253        return Err(CanwuError::new(
254            ErrorCode::InvalidBoundary,
255            "the issue ingress names an unexpected relief order",
256        ));
257    }
258    if view.typed_domain_record(&order_reference())?.is_some() {
259        return Err(CanwuError::new(
260            ErrorCode::InvalidBoundary,
261            "the relief order already exists; duplicate issue ingress is invalid",
262        ));
263    }
264    let treasury_hash = action_hash(600)?;
265    let county_hash = action_hash(600)?;
266    let manifest = DomainRecordDraft::from_typed(
267        order_reference(),
268        &ReliefOrder {
269            order_id: ORDER_ID.to_owned(),
270            issued_by: CENTRAL_PLUGIN.to_owned(),
271            treasury_system: "prepare-treasury".to_owned(),
272            treasury_version: 1,
273            treasury_disposition: "committed".to_owned(),
274            treasury_hash,
275            county_system: "prepare-county".to_owned(),
276            county_version: 1,
277            county_disposition: "committed".to_owned(),
278            county_hash,
279        },
280    )?;
281    Ok(BoundaryProposal {
282        directives: vec![
283            BoundaryDirective::MutateRecord {
284                mutation: DomainRecordMutation::Create { record: manifest },
285                summary: "Publish the central relief order manifest".to_owned(),
286            },
287            BoundaryDirective::SchedulePluginIngress {
288                target_plugin: TREASURY_PLUGIN.to_owned(),
289                after: SimDuration::ZERO,
290                packet_type: EXECUTE_INGRESS.to_owned(),
291                priority: 0,
292                payload: json!({"order_id": ORDER_ID}),
293                affected: Vec::new(),
294            },
295            BoundaryDirective::SchedulePluginIngress {
296                target_plugin: COUNTY_PLUGIN.to_owned(),
297                after: SimDuration::ZERO,
298                packet_type: EXECUTE_INGRESS.to_owned(),
299                priority: 0,
300                payload: json!({"order_id": ORDER_ID}),
301                affected: Vec::new(),
302            },
303        ],
304        ..BoundaryProposal::default()
305    })
306}
Source

pub fn proposed_domain_record( &self, reference: &DomainRecordRef, ) -> Result<Option<&DomainRecord>, CanwuError>

Source

pub fn proposed_typed_domain_record<T>( &self, reference: &TypedDomainRecordRef<T>, ) -> Result<Option<&DomainRecord>, CanwuError>

Source

pub fn proposed_domain_record_version( &self, reference: &DomainRecordRef, ) -> Result<Option<DomainRecordVersionRef>, CanwuError>

Returns the exact evidence reference assigned to a domain-record version proposed earlier in the current boundary.

Source

pub fn current_domain_record_version( &self, reference: &DomainRecordRef, ) -> Result<Option<DomainRecordVersionRef>, CanwuError>

Returns the exact evidence reference for the currently visible version of a domain record. Strategic aggregation runs after atomic commit, therefore it cannot use Self::proposed_domain_record_version.

The current boundary overlay/proposal is preferred, followed by the runtime’s verified current-record provenance index. The index is maintained at commit time and rebuilt from canonical evidence on restore, so lookup does not scan retained or archived history.

Source

pub fn domain_record_version_evidence_exists( &self, reference: &DomainRecordVersionRef, ) -> Result<bool, CanwuError>

Returns whether an exact domain-record version reference is valid at this proposal-visible cut.

This validates both the record identity/version and its establishment source. Earlier same-boundary proposals are considered before retained or archived runtime evidence.

Source

pub fn domain_record_version_is_current( &self, reference: &DomainRecordVersionRef, ) -> Result<bool, CanwuError>

Checks that an exact domain-record version is both valid evidence and current.

Source

pub fn evidence_exists( &self, reference: &EvidenceRef, ) -> Result<bool, CanwuError>

Returns whether a generic evidence identity is retained or archived.

Domain-record versions proposed earlier in this boundary are visible. Archived identities count as existing even when their bodies are no longer retained.

Source

pub fn evidence_time( &self, reference: &EvidenceRef, ) -> Result<Option<SimTime>, CanwuError>

Returns when retained or earlier same-boundary evidence first became authoritative at this proposal-visible cut.

Archived identity receipts do not retain a precise semantic time, so they return None and callers that require temporal ordering must fail closed or load the archived evidence body.

Source

pub fn domain_record_version( &self, reference: &DomainRecordVersionRef, ) -> Result<Option<DomainRecord>, CanwuError>

Resolves the retained record body for one exact domain-record version.

Archived receipts prove that a version existed but do not contain its body, so this returns None when the corresponding evidence segment is not live in the runtime.

Source

pub fn domain_records_of_kind( &self, kind: &DomainRecordKind, limit: usize, ) -> Result<Vec<DomainRecord>, CanwuError>

Returns a bounded, deterministic projection of records of one kind.

Same-boundary overlays take precedence over current state. Records are ordered by their canonical reference, so result order is replay stable.

Source

pub fn domain_records_of_kind_after( &self, kind: &DomainRecordKind, after: Option<&DomainRecordRef>, limit: usize, ) -> Result<Vec<DomainRecord>, CanwuError>

Returns one bounded deterministic page of records after a canonical record-reference cursor.

The cursor is exclusive and must name the same kind. This keeps plugin scans bounded without imposing a 10,000-record lifetime ceiling on a domain kind. Same-boundary overlays retain the same precedence as Self::domain_records_of_kind.

Source

pub fn knowledge_changes_by_correlation( &self, plugin: &str, producer_correlation: &str, ) -> Result<Vec<BoundaryKnowledgeChange>, CanwuError>

Finds committed knowledge changes produced with an exact correlation.

This supports next-boundary operation finalization without granting a plugin unrestricted access to unrelated knowledge payloads.

Source

pub fn knowledge_changes_by_correlation_prefix( &self, plugin: &str, producer_correlation_prefix: &str, ) -> Result<Vec<BoundaryKnowledgeChange>, CanwuError>

Finds committed knowledge changes whose producer correlation begins with a deterministic operation prefix.

The prefix remains plugin-scoped. This is intended for bounded multi-holder operation finalization where every holder batch must keep a unique full correlation value.

Source

pub fn reservation( &self, reservation: &ReservationRef, ) -> Result<Option<&ReservationAllocation>, CanwuError>

Examples found in repository?
examples/phased_boundary.rs (line 53)
48fn apply_grain(
49    view: &SimulationView<'_>,
50    _context: &BoundaryContext,
51) -> Result<BoundaryProposal, CanwuError> {
52    let reservation = ReservationRef::new("example-demand", "request", "daily-grain");
53    let allocation = view.reservation(&reservation)?.ok_or_else(|| {
54        CanwuError::new(
55            ErrorCode::InvalidBoundary,
56            "the declared grain reservation did not produce allocation evidence",
57        )
58    })?;
59    let territory = EntityRef::Territory(TerritoryId::new(1));
60    Ok(BoundaryProposal {
61        directives: vec![
62            BoundaryDirective::SetComponent {
63                state: StateKey::new("garrison", "grain"),
64                entity: territory.clone(),
65                component: "daily_grant".to_owned(),
66                value: Value::from(allocation.granted),
67                summary: format!(
68                    "Granted {} grain to the western garrison",
69                    allocation.granted
70                ),
71            },
72            BoundaryDirective::Emit {
73                event_type: "grain_allocated".to_owned(),
74                summary: "The daily grain allocation settled".to_owned(),
75                affected: vec![territory],
76            },
77        ],
78        ..BoundaryProposal::default()
79    })
80}
Source

pub fn random_range( &self, stream: &RandomStreamKey, upper_exclusive: u64, purpose: &str, ) -> Result<u64, CanwuError>

Source

pub fn random_range_for_operation( &self, stream: &RandomStreamKey, evidence: EvidenceRef, operation_kind: &str, application_operation_id: &str, target: RandomOperationTarget, draw_slot: u32, upper_exclusive: u64, purpose: &str, ) -> Result<u64, CanwuError>

Source

pub fn random_sample_for_operation( &self, stream: &RandomStreamKey, evidence: EvidenceRef, operation_kind: &str, application_operation_id: &str, target: RandomOperationTarget, draw_slot: u32, upper_exclusive: u64, purpose: &str, ) -> Result<RandomSample, CanwuError>

Examples found in repository?
examples/uncertainty_resolution.rs (lines 38-50)
22fn random_resolution_system(
23    view: &SimulationView<'_>,
24    context: &BoundaryContext,
25) -> Result<BoundaryProposal, CanwuError> {
26    let ticket = view
27        .decision_ticket(RANDOM_TICKET)?
28        .expect("the example opens the ticket before the daily boundary");
29    let calendar_ingress = context
30        .admitted_ingress
31        .first()
32        .copied()
33        .expect("the example runs this system from calendar ingress");
34    let option_weights = vec![
35        DecisionOptionWeight::new("fail", 25),
36        DecisionOptionWeight::new("pass", 75),
37    ];
38    let sample = view.random_sample_for_operation(
39        &decision_stream(),
40        EvidenceRef::Ingress(calendar_ingress),
41        "decision_selection",
42        "law-proposal-42",
43        RandomOperationTarget::DecisionTicket {
44            ticket_id: ticket.id,
45            ticket_version: ticket.version,
46        },
47        0,
48        100,
49        "select whether the law passes from configured weights",
50    )?;
51    Ok(BoundaryProposal {
52        directives: vec![BoundaryDirective::ResolveDecisionRandomly {
53            resolution: RandomDecisionResolution {
54                priority: 0,
55                decision_request_id: DecisionRequestId::new(3),
56                command_request_id: None,
57                ticket_id: ticket.id,
58                expected_version: ticket.version,
59                controller_id: ticket.assigned_controller.clone(),
60                sample,
61                option_weights,
62            },
63        }],
64        ..BoundaryProposal::default()
65    })
66}
Source

pub fn component( &self, state: &StateKey, entity: &EntityRef, component: &str, ) -> Result<Option<&Value>, CanwuError>

Source

pub fn proposed_component( &self, state: &StateKey, entity: &EntityRef, component: &str, ) -> Result<Option<&Value>, CanwuError>

Trait Implementations§

Auto Trait Implementations§

§

impl<'a> !Freeze for SimulationView<'a>

§

impl<'a> !RefUnwindSafe for SimulationView<'a>

§

impl<'a> !Send for SimulationView<'a>

§

impl<'a> !Sync for SimulationView<'a>

§

impl<'a> !UnwindSafe for SimulationView<'a>

§

impl<'a> Unpin for SimulationView<'a>

§

impl<'a> UnsafeUnpin for SimulationView<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.