Writing a Matter App
Load this card when a task uses physical or virtual Matter devices: a
LibertasDevice or LibertasVirtualDevice field and its descriptor, Matter
requests, reports or callbacks, device subscriptions, virtual-device responses,
or the handling of a Matter status. Its rules are generated from the
device descriptor encodings and the
Matter interaction/status contract, which own
them. Use the installed public SDK for exact function and tuple shapes; the
annotation inventory gives each descriptor
annotation's Rust and TypeScript spelling, and the Rust manual's
Matter SDK dependency
covers a new Rust Matter App.
LibertasDevice selects a physical device; LibertasVirtualDevice identifies a
task-owned Matter server. The descriptor's byte encoding, load and access
meaning, and matching belong to Studio's editors and the clients that decode
them; a client implementer finds those rules on the
client runtime card.
Order of work
- Declare the device fields and their Studio-generated descriptors
(
matter.descriptor.*). - Use the typed SDK and register callbacks before requests
(
matter.interaction.*). - Submit each task's complete subscription list (
matter.subscription.*). - Handle statuses (
matter.status.*), including status-only completion. - Plan for command and attribute-write supersession (
matter.cmd.*,matter.write.*). - For a virtual device, answer through the SDK (
matter.virtual.*). - Compile with Studio and fix every reported rule.
Rules to apply
Studio does not check these rules. Each is quoted from its owner.
Matter device type attribute encodings
Owner: descriptors.md#matter-device-type-attribute-encodings
matter.descriptor.purpose: The descriptor is metadata used by the Hub and clients to filter a physical device or construct a task-owned virtual device.matter.descriptor.payload-not-runtime-id: This encoding does not describe the field's runtime object ID; that value is separate and is never part of the attribute payload.
Schema mapping
Owner: descriptors.md#schema-mapping
matter.descriptor.stored-verbatim: The schema node remains built-in and has no child fields. The parser stores the decorator or attribute argument verbatim as the attribute value.matter.descriptor.use-editor(judgment): Studio's Device Type Editor and Virtual Device Type Editor generate these strings. Application code should normally use those editors instead of assembling binary descriptors manually.
Excluded: runtime field value
Owner: descriptors.md#excluded-runtime-field-value
matter.descriptor.no-runtime-id: TheDeviceTypeandVirtualDeviceattributes contain only descriptor metadata. They never contain the selected or allocated Libertas object ID carried by the field at runtime. Runtime value serialization is therefore outside the attribute encoding specified by this document.
Libertas Matter client status contract
Owner: status.md#libertas-matter-client-status-contract
-
matter.status.u32: Libertas exposes Matter interaction results to TypeScript and Rust applications as one unsigned 32-bit value. This is an application-facing Libertas contract; it is not the two-fieldStatusIBencoding used on the Matter wire. -
matter.status.bits.interaction:Bits Meaning 0-7 Matter Interaction Model status -
matter.status.bits.cluster:Bits Meaning 8-15 Optional Matter cluster status; zero when absent -
matter.status.bits.hub:Bits Meaning 16-31 Libertas Hub status -
matter.status.zero-success: Zero is success. -
matter.status.test-whole-value(judgment): A client that cannot recover differently for individual errors should test the complete value for zero rather than decoding its fields.
App interaction invariants
Owner: status.md#app-interaction-invariants
matter.interaction.typed-sdk(judgment): Use the installed public SDK's typed Matter requests, reports, and response shapes.matter.interaction.callbacks-and-transactions: Register the device callback before issuing requests, preserve each transaction ID, and branch on the documented action and transaction semantics before decoding a callback.matter.interaction.report-not-response: A report or the ignored transaction ID is not automatically a response to the latest request.matter.interaction.status-only: An interaction may complete with a terminal error status even when no attribute, event, or command payload is returned; status-only completion is still a result and must not be discarded while waiting for payload data.matter.virtual.respond-to-request: A virtual device returns each response through the SDK with the exact peer and transaction ID from the request.matter.virtual.standard-status-only: It may return only standard Matter status bits 0-15; it never manufactures a Libertas Hub status.
Task subscription replacement
Owner: status.md#task-subscription-replacement
matter.subscription.task-list-replacement: Matter device subscriptions belong to the application-layer integration. Each subscription update is sent in one shot for one App task: collect its complete desired list of device subscriptions and submit that list together. A later accepted list completely replaces that task's previous list, including removal of omitted devices and paths. Tasks may replace their list repeatedly; separate per-device submissions do not accumulate subscriptions. An empty list clears that task's device subscriptions.
Hub statuses
Owner: status.md#hub-statuses
-
matter.status.superseded:Hub code Encoded client value Name Meaning 0x00010x00010000Superseded A queued command was replaced, or a retained attribute write differs from the value finally written. -
matter.status.superseded-constant(judgment):Supersededis available asLibertasMatterHubStatus.Supersededin the TypeScript SDK andlibertas_matter::frame::STATUS_SUPERSEDEDin the Rust SDK. Applications use that constant rather than copying the numeric value. -
matter.status.hub-bits-origin: Only the Hub generates bits 16-31, and only Libertas Matter client APIs carry them. -
matter.status.native-mapping: Native Matter peers receive standard Matter wire statuses: the Hub mapsSupersededtoBusyand an unknown nonzero Hub status toFailure. -
matter.virtual-device.standard-status: A virtual Matter device is a Matter server and must return a standard Matter status using bits 0-15 only.
Command supersession
Owner: status.md#command-supersession
matter.cmd.last-wins: Pending commands are last-command-wins per logical-device endpoint and cluster to reduce device traffic. When later commands replace a queued command:matter.cmd.displaced-retained: the displaced command's original ID and complete payload are retained;matter.cmd.newest-per-source: only the newest request/reference for each source object is retained for completion, counting both the surviving command and displaced requests;matter.cmd.older-no-response: when the surviving command carries a newer request from a source, that source's older displaced request receives no separate response. This keeps response bookkeeping bounded per source.matter.cmd.burst-newest: A burst from one peer leaves exactly its newest command queued; older queued references are discarded without acknowledgement. Only that peer's latest queued reference can receive completion or rejection.matter.cmd.sent-owned: A command already sent to the device remains owned by its active interaction.matter.cmd.deferred-reply: The retained response is not sent when the queue entry is replaced. It follows the replacement into the real Matter interaction and is sent only after that interaction has a terminal result.matter.cmd.report-independent: Attribute reports follow ordinary Matter subscription behavior independently; command completion does not establish report-delivery ordering.matter.cmd.displaced-superseded: A retained displaced command always receives the nonzeroSupersededrejection because it did not execute, even when its ID and payload equal the surviving command's. In anA -> B -> Achain, the retained firstAwas replaced and cannot receive success for the finalA's execution.matter.cmd.survivor-result: The surviving command alone receives its own success or error result; that result is not assigned to displaced requests.matter.cmd.reissue(judgment): Applications can handle the rejection and decide whether to issue a new command.
Attribute-write supersession
Owner: status.md#attribute-write-supersession
matter.write.per-attribute: Queued writes share one merged Matter write interaction. Supersession is therefore evaluated for each requested attribute rather than once for the whole request. The Hub retains each newest requester's exact attribute/value set and, after the interaction finishes, compares every requested value with the value finally written by the pooled Matter interaction:matter.write.equal-success: a retained attribute receives success when its requested value equals the finally written value;matter.write.differs-superseded: it receivesSupersededwhen the finally written value differs;matter.write.unreplaced-path-status: retained attributes which were not replaced receive their actual Matter path status.matter.write.final-comparison-only: This final comparison is deliberately not updated incrementally, so a chain of changes which eventually returns to the requested value is reported as success.matter.write.newest-reference-only: The Hub retains only the newest request/reference from each source object for a reply. An older request's values remain in the merged write unless another write replaces the same attributes, but its response correlation is discarded. A retained entry can consequently contain a mixture of success,Superseded, validation errors, and actual Matter path errors.matter.write.reply-after-finish: No retained write response is sent until the merged Matter write finishes.matter.write.path-status-overrides: A nonzero path status overrides the final value comparison for that attribute.matter.write.whole-failure: A failure of the whole interaction, including timeout or busy, becomes every retained attribute result without performing a value comparison.
Rules Studio enforces
Studio rejects a source that breaks one of these rules. The owner holds the full rule.
Schema mapping
Owner: descriptors.md#schema-mapping
matter.descriptor.host: DeviceType goes only on an effective Device and VirtualDevice only on an effective VirtualDevice; a List inherits neithermatter.descriptor.nonempty-and-placement: A device descriptor attribute needs a non-empty value and cannot be package-level