Surface / Surface and Bundle

Common confusions, corrected

  • "A Surface is a lightweight Submodel." It is not a Submodel at all. No private Model, no child update, no wrapping. If it folds Messages, it is misnamed.
  • "A Bundle is a component." It has a view part, but its job is the transitions, init, Subscriptions, and resources behind the view. A component without those is not a Bundle-shaped problem.
  • "A Bundle is like a ManagedResource." Lifetimes rhyme; ownership does not. A Bundle adds Model fields and Message cases and decides transitions. A ManagedResource provides a handle by tag for Commands/Subscriptions and owns no Model, Message, or update. A Bundle may provide ManagedResources.
  • "A Bundle is for any reusable behaviour." One-shot work is a Command (copyText); element-scoped observation is a Mount (Resize, Intersection); a bare ongoing stream is a Subscription entry. Reach for a Bundle when there is a state slice plus transitions to own.
  • "A writable projection owns its slice." Projection.pick and FieldRef.set are plumbing: Sync installs reconciled state through the shared projection (sync.projection.set(model, shared) on every exchange). Using them does not transfer ownership and does not skip the owning update; causing a child transition means sending the root Message that routes to the child.
  • MessageSet versus wrapper. A MessageSet marks existing union variants durable or exposable; it routes nothing. A wrapper variant routes a child's Messages to its slice. Marking is policy; wrapping is routing.
  • Two applications, one field name. Every ref and Surface carries App.owner; mixing applications is a type error or a runtime throw. A Bundle placed through another application's ref is a foreign-contract finding in Module.validate, not a working program.