Subsystem Binding Model
Librux separates interface declaration from deployment wiring.
A subsystem binary should not need to know which concrete gateway, component, compound provider, simulator, or remote instance it will use in a final robot deployment.
The base model has three layers.
subsystem manifest = role plus what this subsystem provides and requires
deployment manifest = which provider instance satisfies each requirement
runtime registry = where the selected provider is currently reachable
Robot applications add two composition manifests above this base.
robot manifest = gateway, component, and compound slots plus robot capabilities
app-role subsystem manifest = top-level application requirements
deployment manifest = robot + application + package instances + bindings
Declaration Versus Binding
The subsystem manifest answers this question.
What does this subsystem provide, and what does it require?
The deployment manifest answers this question.
Which concrete provider satisfies each requirement in this deployment?
This distinction lets the same component binary bind to a real gateway, a simulator gateway, a test stub, or a remote provider without changing source code.
Provides And Requires
kind: librux.subsystem
version: 1
subsystem:
name: component.manipulator
role: component
requires:
actuator_servo:
contract: api.actuator.servo.v1
cardinality: one
required: true
provides:
manipulator:
contract: component.manipulator.v1
provides names interfaces implemented by this subsystem. requires names
logical dependencies that the subsystem code will use.
The names under requires are not provider identities. They are local logical
names. Deployment supplies the provider identity later.
Deployment Binding
A deployment chooses the provider instance for each requirement.
kind: librux.deployment
version: 1
instances:
component.manipulator:
manifest: ./component.manipulator/subsystem.yaml
gateway.servo:
manifest: ./gateway.servo/subsystem.yaml
bindings:
component.manipulator.actuator_servo:
to: gateway.servo.servo
The binding key is the consumer requirement.
<consumer-subsystem>.<required-interface>
The binding target is the provider interface.
<provider-subsystem>.<provided-interface>
The deployment loader validates that both manifests exist, both interfaces exist, and their contracts match.
Multiple Instances
Reusable packages can be instantiated more than once. In that case the deployment names concrete runtime identities while pointing them at the same package or subsystem manifest.
kind: librux.deployment
version: 1
instances:
component.left_manipulator:
package: ./packages/manipulator
params:
robot_id: left
component.right_manipulator:
package: ./packages/manipulator
params:
robot_id: right
gateway.servo:
manifest: ./gateway.servo/subsystem.yaml
bindings:
component.left_manipulator.actuator_servo:
to: gateway.servo.servo
component.right_manipulator.actuator_servo:
to: gateway.servo.servo
The package can be reusable while each runtime instance keeps its own subsystem identity, parameters, state directory, resource lease, and lifecycle state.
Public And Internal Contracts
Subsystem public interfaces are the standardization boundary. Public contracts
must resolve to Librux specs such as api.actuator.servo.v1,
component.mobile_base.v1, or capability.mobility.teleop.v1.
App-facing requirements should normally use capability.*. A capability spec
points to the backing API contract used for endpoint validation.
Private tutorial wiring can be marked explicitly.
provides:
service:
contract: tutorial.transport.service.v1
visibility: internal
visibility: internal means the interface is not claiming product-level
compatibility. Robot slots and capability implementations must bind through
public Librux spec interfaces.
Endpoint names are not runtime data. Librux validates endpoint registration as a closed-world contract surface, so a subsystem cannot create a new Event topic or Procedure name for every task, object, or operation. Use fixed contract endpoints and carry changing identifiers inside payload fields.
Runtime Availability
Binding validation is structural. It answers this question.
Is the deployment wired correctly?
Runtime route resolution answers a different question.
Is the selected provider currently running and reachable?
Those states are intentionally separate. A deployment can be structurally valid while a provider process is starting, restarting, waiting on another subsystem, or temporarily disconnected.
| State | Meaning |
|---|---|
INVALID_CONFIG |
Manifest or binding structure is invalid |
WAITING_BINDING |
Binding is missing or not structurally usable |
WAITING_TARGET |
Binding is valid but the provider route is not available yet |
BOUND |
Binding target is known and route resolution succeeded |
READY |
Required bindings and local registrations are ready |
DEGRADED |
A previously available runtime binding was lost |
What Goes Where
| Layer | Owns |
|---|---|
| Subsystem code | logical requirement names such as actuator_servo |
| Subsystem manifest | role, provides, requires, and interface contracts |
| Robot manifest | gateway, component, and compound slots, kinematics, parts, and robot capabilities |
| App-role subsystem manifest | top-level app subsystem and required platform labels or capabilities |
| Deployment manifest | platform, application, package instances, selected slots, and selected provider instance for each requirement |
| Runtime registry | current route, endpoint, host, socket, lifecycle, and health state |
| Package manifest | reusable executable launch, parameters, environment, resources, and app assets |
Diagram Model
The same data can be rendered at three levels.
- Static interface diagrams use subsystem manifests.
- Deployment wiring diagrams add robot, app-role subsystem, and deployment manifests.
- Runtime diagrams add live route, binding, lifecycle, and health state from the control backend.