Skip to content

Capability Coverage (capabilities-coverage.yaml)

Every adapter carries a capabilities-coverage.yaml at its root. It is a machine-comparable declaration of how the integration covers the device capabilities in the capability catalog. When this file is part of the delivery, prepare it yourself with PQ SDK Tooling. The tool creates the catalog rows and checks their values. You supply the device facts and write the customer-facing limitations.

This is not the framework Thing function library. Rows here are adapter capabilities such as offline audit recovery, credential management, card formats, arm/disarm, bypass, and alarms/tampers/troubles/restores. Framework functions like HistoryPoll, StatusPoll, Reader, Door, Partition, and IntrusionDetector are backing primitives only.

[PQ SDK Tooling](../pq-tools/index.md) explains how to install the tool. Run --scaffold to create the catalog rows, then run --assess to answer the questions at the console. The tool records a state and, when needed, a one-line limitation. --validate reports incomplete rows and malformed values. See Writing and delivering adapter documentation.

Schema

catalog_source: reference/capability-catalog.md
generated: "2026-05-30"

capabilities:
  cross_cutting.connection_session:
    domain: cross_cutting
    catalog_label: "Connection & session"
    state: implemented
    reason: null
    backing_primitives: [ConnectionBase]
    evidence: "Protocol guide, section 4.2: GxyLogin and Login(41) use an encrypted TCP channel"
  access.card_formats:
    domain: access
    catalog_label: "Card formats"
    state: intentionally_deferred_by_explicit_user_scope
    reason: not_yet_implemented
    backing_primitives: [AccessSynchronization, access-model.yaml]
    evidence: "Primary CSN/RawHex only; Wiegand/proprietary mapping deferred"
    limitation: "Only the card's serial number is read; site and card numbers printed on the card are not."

Fields

Field Required Values
domain always cross_cutting, access, intrusion, fire, safety, video, io, gateway_native_sdk, or adapter-specific extra domain
catalog_label always Exact capability label from capability-catalog.md
state always One Definition-of-Done final state, normalized to snake_case
reason required unless state: implemented null, protocol_limitation, device_limitation, not_yet_implemented, out_of_scope, no_framework_mapping, needs_vendor, needs_hardware
backing_primitives always PQ functions, commands, events, YAML models, or services used by the adapter
evidence optional Internal source note; leave it empty unless the delivery explicitly asks for it; do not add protocol text
limitation required unless state: implemented One sentence in plain language saying what the user does not get

Writing limitation

evidence and limitation describe the same fact to two different readers, and they are not interchangeable.

evidence is an optional internal source note. You may identify a source document, section, example, or observation, but you do not need to copy protocol details into this file, the adapter repository, or the adapter source code. limitation is for the person who operates the installation and has never heard of any of them. Write it as a consequence they can observe, in one sentence, with no protocol names, no framework types, no state or reason tokens.

  • good: "The clock is synchronized only when the device starts, not continuously."
  • good: "Cards can be added and removed, but not temporarily suspended."
  • bad: "StatusPoll has no watchdog frame" — names framework internals
  • bad: "protocol_limitation" — restates the reason token
  • bad: "Partially implemented" — restates the state and says nothing

The published adapter page renders limitation in its capability table. Keep that text useful to the installer. Do not put protocol details into it.

Final States

Use the Definition-of-Done states, normalized for YAML:

  • implemented
  • not_supported_by_protocol
  • not_supported_by_framework
  • blocked_by_missing_or_ambiguous_documentation
  • blocked_by_hardware_only_verification
  • intentionally_deferred_by_explicit_user_scope

Use partial only when part of a catalog capability is implemented and the remaining part has a different final state that must be explained in limitation.

Key Names

Keys are stable slugs: <domain>.<capability_label_normalized>. --scaffold emits them for you, so you rarely type one by hand; the rule is here for when you read or edit a key.

Normalize labels by lowercasing, replacing & with and, replacing / with _, removing parentheses, and converting other non-alphanumeric separators to single underscores.

Examples:

  • Connection & session -> cross_cutting.connection_and_session
  • Offline audit recovery -> cross_cutting.offline_audit_recovery
  • Reset & restore -> access.reset_and_restore
  • Alarms / tampers / troubles / restores -> intrusion.alarms_tampers_troubles_restores

Re-running the scaffold

--scaffold is a merge, not a blind regeneration. Run it again after the catalog grows and it:

  1. Keeps every row you have already assessed, verbatim.
  2. Adds any catalog capability new to your in-scope domains, as an unassessed row for you to fill.
  3. Leaves adapter-specific extras — rows in a domain the catalog does not define — untouched.

It never rewrites a state you wrote; re-assessing against new adapter behaviour is yours to do. Run --validate afterwards to see the newly added rows waiting for an assessment.

Out Of Scope

Do not add framework Thing functions as rows. If a capability is backed by a function, list it under backing_primitives.