Skip to content

Model ownership

Canwu splits responsibility across three layers. The engine owns what must be deterministic, authoritative, and replayable. Optional extension crates own generic domain mechanics, such as movement or law, built on the public API. Your application owns period content and the decisions that give those mechanics meaning. Use this page to decide where a new rule belongs and which crate your code should depend on.

Dependency layers: the application and extension crates build on the public API, which wraps the engine crates. View diagram source.
View diagram source
flowchart TB
  App["Your application<br/>period content, scenarios,<br/>incidents, authority records"]
  Ext["Extension crates<br/>canwu-movement, canwu-law,<br/>canwu-culture, canwu-society, …"]
  Ref["Reference integrations<br/>canwu-reference-world and others<br/>replaceable examples"]
  Api["canwu-api<br/>public API"]
  Engine["Engine and mechanism crates<br/>canwu-core, canwu-event, canwu-sim,<br/>canwu-routing, canwu-transport, …"]
  App --> Ext
  App --> Api
  Ext --> Api
  Ref --> Api
  Api --> Engine

Arrows point from a crate to what it depends on. Engine and mechanism crates never depend on extensions, reference integrations, or application code.

Generic engine crates own deterministic simulation contracts: state, settlement, evidence, randomness, persistence, and replay. Extension crates and reference integrations own concrete world concepts, such as armies, governments, territories, people, and letters, together with the event payloads that describe them.

The rule also covers changes that span several plugins. When a maintenance operation must update records owned by different plugins, for example when a culture target retires while legal records still cite it, the kernel checks the participant set, the record versions, the work budgets, and that everything commits together or not at all. Each participant changes only records whose schema its own plugin owns, and the plugin that owns the target record must include an exact change to it. Plugins register as participants with register_owner_authorized_maintenance_participant or as dependency resolvers with register_maintenance_dependency_resolver. Both registrations are stored in the plugin descriptor, so a caller cannot leave a participant out.

The table lists concerns that come up often and shows which crate owns the mechanism and what your application decides.

Concern Owned by Your application decides
Person life and custody state, runtime person creation, withdrawing queued ingress canwu-sim core state and directives When a person dies, is captured, is released, or appears; what to withdraw
Multi-owner conditional transitions canwu-sim transition manifest, phase-10 staging, and phase-11 audit The participants, expected versions, and meaning of each transition
Rule-evaluation evidence canwu-core record, canwu-sim boundary evidence, canwu-api viewer read Rule IDs and what their terms mean
Decision lineage and seat succession canwu-decision ticket and controller binding Who holds a seat and when a successor takes over
Delegated resource access canwu-resource access grant and Granted source policy Who may grant access to whom, and the authority evidence record
Movement lifecycle and capacity pools canwu-movement runtime record and plugin; canwu-transport records and pure allocation Incidents, hazards, hostility, their random draws, and authority-basis records
Delegated carriers and carrier seizure canwu-correspondence The relationship behind a delegation, and relaying news of a seizure to the sender
Authenticity findings canwu-information interpretation How likely a forgery is to be detected
Weighted, unit-block, and advisory procedure stages canwu-law compiled procedure Seat weights, blocks, and the tie-break rule
Culture boundary settlement canwu-culture CultureBoundaryPlugin settles the lifecycle and produces deltas; canwu-society stays the only writer of canwu.society:state Exposure signals and the culture definition
Policy-pressure provenance and cohort headcount rebase canwu-society The external stock record a rebase cites
External transmission sources canwu-technology The cited content record and its declared reliability

Two movement crates have similar names. canwu-reference-world includes a movement plugin that moves the example world’s armies and people with its order_movement_v1 command; it is replaceable example code. canwu-movement is the generic movement lifecycle extension for canwu-transport records and has no knowledge of the reference world.

canwu-event holds only generic event contracts:

Type What it is
SimEvent The event envelope: identity, time, affected entities, summary, cause, and correlation ID
EventKind A type tag plus flattened structured fields. Domain crates define typed payloads and convert them with from_payload and decode_payload.
CauseRef The cause of an event: a command, a parent event, a boundary, or a system
EventAudience Who may see an event in actor-relative views; Private unless the plugin declares otherwise
EventKindError The error returned when a payload cannot be encoded or decoded

Typed payloads for movement, army arrival, person travel, letter delivery, report dispatch, knowledge, and debug fields live with the integrations that own them. The runtime keeps private compatibility payloads that validate the older event tags and fields strictly. A plugin event carries its plugin name and event type, which EventKind::plugin_identity returns. See the event system for how events are recorded and shown.

Earlier versions shipped a canwu-world crate that put one example world into the engine’s dependency graph. Its twelve public types, MapPoint, Person, PersonTransitState, LetterStatus, LetterCargo, Government, Territory, Route, TransitState, Army, WorldSnapshot, and WorldDiff, now live in canwu-reference-world. That crate provides them through the public API, together with the example movement plugin, a detached projection, and the routing adapter planning_snapshot_from_world. canwu-routing plans over the generic PlanningSnapshot and does not depend on the example world.

canwu-sim still keeps its own copies of most of these types, re-exported by canwu-api, for the deprecated Canwu::world() projection and the legacy Command::OrderMovement path. New code should use canwu-reference-world or its own domain records. The per-type rationale is in the repository’s world and event ownership audit.