Documentation
¶
Overview ¶
Package application implements the device-independent Application Binding engine for CloudPath.
An Application Plugin declares Capability Requirements and binds them to stable Entity IDs. Matching and validation consider only Capability ID / version compatibility and tenant scope. The engine must never reference a Driver ID, a serial port, or any concrete hardware field. A binding persists the stable entity_id; renames, Edge reconnects and Driver restarts must not change an existing binding.
The design contract lives in docs/architecture/capability-model.md (Application Binding, Reference Application, Compatibility & Migration and Invariants).
Index ¶
Constants ¶
const ( // CodeMissingRequired means a required (one or one-or-more) requirement has // no bound entity. CodeMissingRequired = "missing_required_capability" // CodeCapabilityMismatch means the bound entity does not provide the // required capability family. CodeCapabilityMismatch = "capability_mismatch" // CodeVersionIncompatible means the entity provides the capability family // but an older/incompatible version. CodeVersionIncompatible = "version_incompatible" // CodeCardinalityViolation means more entities than the cardinality allows. CodeCardinalityViolation = "cardinality_violation" // CodeBelowMinItems means fewer than minItems distinct entities. CodeBelowMinItems = "below_min_items" // CodeDuplicateOccupation means an entity is occupied by multiple // requirements (or slots) while none of them allows reuse. CodeDuplicateOccupation = "duplicate_occupation" // CodeCrossTenant means a binding references an entity outside the // application instance's tenant. CodeCrossTenant = "cross_tenant" // CodeUnknownRequirement means a binding references a requirement id that // the manifest does not declare. CodeUnknownRequirement = "unknown_requirement" // CodeUnknownEntity means a binding references an entity id that is not a // known candidate. CodeUnknownEntity = "unknown_entity" // CodeEmptyRequirementID means a binding has no requirement id. CodeEmptyRequirementID = "empty_requirement_id" // CodeEmptyEntityID means a binding has no entity id. CodeEmptyEntityID = "empty_entity_id" // CodeInvalidCapability means a capability reference cannot be parsed. CodeInvalidCapability = "invalid_capability" // CodeInvalidRequirement means a declared requirement violates the contract. CodeInvalidRequirement = "invalid_requirement" )
Machine-readable issue codes.
Variables ¶
var ErrNotFound = errors.New("binding set not found")
ErrNotFound is returned when a binding set is not present in a Repository.
Functions ¶
This section is empty.
Types ¶
type Binder ¶
Binder carries the tenant scope and instance identity for a binding operation. The engine matches and validates candidates purely by Capability and tenant; a Binder never couples to a Driver.
func (Binder) Match ¶
func (b Binder) Match(requirements []Requirement, candidates []Candidate) (BindingSet, error)
Match auto-selects a candidate entity for every requirement within the binder's tenant scope. It returns a fully valid BindingSet, or a *BindingError carrying the machine-readable issues when no valid set can be produced. Matching only uses Capability ID/version compatibility and tenant; it never references Driver ID, a port, or a hardware field.
func (Binder) Validate ¶
func (b Binder) Validate(requirements []Requirement, candidates []Candidate, bindings []Binding) ValidationResult
Validate checks a proposed binding list against the declared requirements and candidate entities. It produces machine-readable issues for: missing required capabilities, duplicate occupation (when reuse is not allowed), cross-tenant entities, cardinality violations, below-minItems, and version incompatibility.
type Binding ¶
type Binding struct {
RequirementID string `json:"requirement_id" yaml:"requirement_id"`
EntityID string `json:"entity_id" yaml:"entity_id"`
}
Binding pairs a Requirement with the stable entity_id that satisfies it. Bindings persist the entity_id only; the display name, port and connection are intentionally not stored.
type BindingError ¶
type BindingError struct {
Result ValidationResult
}
BindingError wraps a failed binding validation so callers can branch on machine-readable codes. It implements error.
func (*BindingError) Error ¶
func (e *BindingError) Error() string
Error returns a compact summary of the failing codes.
type BindingSet ¶
type BindingSet struct {
ApplicationID string `json:"application_id"`
PluginInstanceID string `json:"plugin_instance_id"`
TenantID string `json:"tenant_id"`
Bindings []Binding `json:"bindings"`
}
BindingSet is the set of Bindings for one Application instance in a tenant.
type Candidate ¶
type Candidate struct {
EntityID string `json:"entity_id" yaml:"entity_id"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
TenantID string `json:"tenant_id" yaml:"tenant_id"`
Capabilities []string `json:"capabilities" yaml:"capabilities"`
// DeviceID is metadata only. Not used for matching.
DeviceID string `json:"device_id,omitempty" yaml:"device_id,omitempty"`
// DriverID is metadata only. Not used for matching.
DriverID string `json:"driver_id,omitempty" yaml:"driver_id,omitempty"`
}
Candidate is the bindable view of an Entity. Only EntityID, TenantID and Capabilities participate in matching and validation. Name, DeviceID and DriverID are observational metadata; the engine MUST never use them to select or accept a binding. This is the device-independent boundary: an entity may be produced by any Driver, at any port, on any device.
type Cardinality ¶
type Cardinality string
Cardinality declares how many entities a Requirement accepts.
const ( // CardinalityOne requires exactly one bound entity. CardinalityOne Cardinality = "one" // CardinalityZeroOrOne accepts zero or one bound entity. CardinalityZeroOrOne Cardinality = "zero-or-one" // CardinalityOneOrMore requires at least one bound entity, and at least // minItems distinct entities when minItems is set. CardinalityOneOrMore Cardinality = "one-or-more" )
func (Cardinality) Valid ¶
func (c Cardinality) Valid() bool
Valid reports whether c is a supported cardinality.
type Issue ¶
type Issue struct {
Code string `json:"code"`
RequirementID string `json:"requirement_id,omitempty"`
EntityID string `json:"entity_id,omitempty"`
Message string `json:"message"`
}
Issue is one validation finding with a machine-readable code. The code is stable and intended for Core/UI to branch on; the message is human-facing.
type Repository ¶
type Repository interface {
// SaveBindingSet upserts a binding set for an application instance.
SaveBindingSet(ctx context.Context, bs BindingSet) error
// LoadBindingSet returns a binding set by application and plugin instance id.
LoadBindingSet(ctx context.Context, applicationID, pluginInstanceID string) (BindingSet, error)
// DeleteBindingSet removes a binding set.
DeleteBindingSet(ctx context.Context, applicationID, pluginInstanceID string) error
// ListBindingSets returns every binding set for a tenant (or all when tenant
// is empty).
ListBindingSets(ctx context.Context, tenantID string) ([]BindingSet, error)
}
Repository persists BindingSets. The in-memory implementation is the default for A6; a later wave (A8) may swap in a SQLite-backed implementation without changing callers. Repository implementations must copy on save and on load so callers cannot mutate stored state.
func NewMemoryRepository ¶
func NewMemoryRepository() Repository
NewMemoryRepository returns a fresh in-memory Repository.
type Requirement ¶
type Requirement struct {
// ID is the requirement's stable identifier within the manifest.
ID string `json:"id" yaml:"id"`
// Capability is the full capability reference, e.g.
// cloudpath.dev/capability/alarm@1.
Capability string `json:"capability" yaml:"capability"`
// Cardinality is the number of entities this requirement accepts.
Cardinality Cardinality `json:"cardinality" yaml:"cardinality"`
// MinItems is the minimum number of distinct entities for one-or-more.
MinItems int `json:"minItems,omitempty" yaml:"minItems,omitempty"`
// AllowReuse permits the same entity to satisfy multiple requirements (or
// multiple slots of this requirement). Default false means an entity may be
// occupied by at most one requirement slot.
AllowReuse bool `json:"allow_reuse,omitempty" yaml:"allow_reuse,omitempty"`
}
Requirement is one Capability the Application needs. Matching resolves each Requirement to a Candidate Entity.
func ParseRequirements ¶
func ParseRequirements(data []byte) ([]Requirement, error)
ParseRequirements decodes a manifest's requirement list. It accepts either a document with a top-level "requirements" key (plugin.yaml / requirements.yaml) or a bare YAML sequence of requirement objects. Declared requirements are validated; an invalid declaration returns an error.
func (Requirement) Validate ¶
func (r Requirement) Validate() error
Validate checks a Requirement against the binding contract.
type ValidationResult ¶
ValidationResult aggregates binding validation findings.
func (ValidationResult) HasCode ¶
func (r ValidationResult) HasCode(code string) bool
HasCode reports whether any issue carries the given machine-readable code.