Skip to content

Properties

Catalog, under Telemetry: Properties (with property_type:read, covered by every viewer’s *:read floor) is one of the fleet’s two signal catalogs: the value lane. A property is a value, what something is, including a number used as a name (a serial number identifies a unit, it measures nothing); a numeric quantity you would average or graph is a metric, the other lane, with its own catalog and its own page. Here, a property is a name plus a data type, with an optional label and validation. The name is its canonical identifier, a single lowercase kebab segment, and the same property is the same concept wherever it appears, whether a device reports it (an observed value) or an operator types it (a declared value). Registering serial-number once means it cannot drift into serialNumber in one place and serial_number in another.

A property is used in three moves, and this page walks all three: the catalog names it, a classifier declares it (with a default, and whether it is required), and an instance sets it. There are three classifiers and they behave identically: a product declares for its components, a standard for its systems, and a location type for its locations.

The catalog is fleet-wide reference data, not a scoped resource, so every property is visible to every reader; the write gates decide who may change it.

  • The directory lists every property sorted by name, each showing its name (the canonical identifier, with its label on the line above it), type (string, bool, or json), and origin (official or custom). name filters by the name or its label; type and official narrow the list.

  • A property is a value (what something is: an input, a firmware version, a reachability verdict); a numeric quantity is a metric, its own catalog beside this one (Catalog, under Telemetry: Metrics), carrying the numeric facts (unit, precision). The two catalogs share one name rule and refuse a name the other holds. A property nothing observes is simply declared-only, something an operator sets, like serial-number.

  • New property (with property_type:create, granted to operators) opens a create drawer: give it a name (a single lowercase kebab segment, for example serial-number or interface-reachable), choose its data type, and optionally add a label and description. An invalid name (an uppercase letter, an underscore, a leading hyphen, a dot) is refused with a message.

  • Pick a row to open its detail blade. The footer Edit pencil (with property_type:update) edits the label and description; the name and data type are fixed at creation, since changing a property’s type under the values that already use it is unsafe and a name is what every driver and contract maps onto. Delete (with property_type:delete) removes a custom property, behind a confirm. A verb you lack greys just that button, its hover reason naming the permission (Requires property_type:update, Requires property_type:delete); the pair never disappears.

  • A property can carry a validation JSON Schema (for example a pattern on a MAC address or an enum on a discrete value), shown read-only on the blade. Editing the schema in the console is a follow-up; set it through the API for now. A schema whose required list names a property its properties block does not declare is refused with the name: the validator would never enforce it, and the catalog does not store a schema that means less than it says.

  • An official property is always read-only: the blade keeps the Edit and Delete pair in place, greyed, with the reason on hover: “Official: ships with Omniglass and updates with it.” The shared vocabulary is the same from install to install. This catalog is the deliberate exception to the operator-owned rule that shipped standards and location types follow: a property name is the vocabulary a driver maps onto, so a release has to be able to correct it (the seed model).

    The baseline ships this catalog, rendered from the seed itself (make gen) so the list cannot drift from the binary:

    NameKindTypeUnitDescription
    interface-reachablestringPer-interface reachability verdict, the AND of the interface's probe results (up = every applicable probe reached the target). A built-in state: availability is time_in_state over it. Unknown/stale are read-time derivations, not stored values.
    healthstringThe rolled-up health verdict for a component, system, or location, worst-wins over its inputs (a component's active alarms, a system's roles, the systems under a location). Recorded transition-only, so the series is the edges: when it broke and when it came back, not a sample per check. incomplete ranks between healthy and degraded and means a commissioning gap: a role short because its hardware was never installed, which no alarm will ever fire for.
    video-inputstringThe selected video input on a display or switcher. A settable state: the set-input command tells the device which input to select (opening an intended value), and the device reports the observed input, so the two reconcile.
    serial-numberstringThe manufacturer serial number of the device.
    mac-addressstringThe primary hardware (MAC) address, lowercase colon-separated.
    firmware-versionstringThe installed firmware or software version.
    model-numberstringThe manufacturer model number.
  • A duplicate name is refused (409), and an attempt to change an official property is refused too: the catalog has exactly one entry per name.

The catalog is also the collection vocabulary: a telemetry sample lands only if its name is registered in its lane’s catalog, a property here or a metric in the Metrics catalog (an unregistered name is dropped, not invented).

The catalog says a property exists; a classifier says which properties its instances have. That declaration is the classifier’s contract, edited in a Declared properties panel on the classifier’s own detail blade. Each line names a catalog property, optionally gives it a default, and optionally marks it required.

| Declare it on | For | Where | Gated by | |---|---|---|---| | a product | its components | Catalog, under Components: Products | product:update / :delete | | a standard | the systems that conform to it | Catalog, under Systems: Standards | standard:update / :delete | | a location type | the locations of that type | Catalog, under Locations: Types | location_type:update / :delete |

Declaring serial-number, firmware-version, and model-number on a Samsung QM55 is what makes every QM55 in the fleet carry those three, with the same names and the same types, without touching a component. Declaring room-capacity on Huddle Room does the same for every huddle room. Type and validation are not repeated in the contract, they stay on the catalog entry, so a property means one thing everywhere.

Inheritance is live, not a copy: revise a contract default and every instance that has not overridden that property picks up the new value. Withdrawing a line leaves any value an instance set, now reading as off contract.

Open a component, a system, or a location from its inventory page. The detail carries a Properties panel: one row per property its classifier declares, resolved to the value that applies here, the value set on the instance or the contract default when nothing is set. An override reads with an accent dot on its name and its value in the accent colour, while an inherited (defaulted) property stays muted. The three panels are the same surface over the same resolver; only the classifier behind them differs.

Property edits are batched with the entity’s edit, not saved per property. Click Edit and each property becomes a stacked cell: a name row with a right-aligned Override switch, and a value row below it. The blade’s Save changes commits every property you touched alongside the rest of the detail, and Cancel discards them.

  • The Override switch is the choice. With the switch off the property inherits the resolved value (the contract default), shown muted with no editable input. Flip it on and a type-aware input appears, seeded from that value, and the row now reads as your own. Revert is the switch off: there is no separate clear. Both directions are the owning entity’s own write (component:update, system:update, or location:update, all operator permissions), and setting is an idempotent upsert, so overriding an already-set property patches it in place rather than failing on a second write.
  • A bool reads as a word, overrides as a toggle. Inherited, a bool shows the resolved word (true / false) muted, not a switch you appear to have set; override on gives a real editable toggle.
  • A required property must be filled. A property the contract marks required carries a red * by its name, stays overridden, and cannot be switched off until it holds a value. The red input box and a “This value is required” label appear only after a Save attempt leaves it empty, and Save is blocked while any required property is unfilled.
  • Off contract is legal. A property the contract does not declare can still be set directly on one instance (a one-off asset tag on a single unit). Those rows group under a dashed-bordered Off contract heading, so the shared shape and the local exception never blur together. Clearing an off-contract property removes it outright, since nothing declares it.
  • An instance with no classifier is all off contract. A productless component and a one-off system (one conforming to no standard) have no contract at all, so everything they carry is off contract. Nothing breaks; the panel simply shows one group.
  • An instance in a scope you cannot reach is not found, not forbidden: the panel resolves properties only within your read scope for that entity kind, mirroring secrets and variables. The same scope check runs on the write, so setting a property on a system or location outside your scope is a 404 too, never a silent success.

From the CLI, the contract side is omniglass product property list|update|delete, omniglass standard property list|update|delete, and omniglass location-type property list|update|delete; the value side is omniglass component|system|location property list|update|delete (see the CLI reference).