Files
home-information/docs/integrations/_template.md
Tony C 35c6f8532c Integration Capabilities framework (#355) (#359)
* Rename Connect vocabulary across the integrations framework

Three coordinated rename groups (no behavior change):

- test_connection -> validate_access on IntegrationGateway and all
  service overrides + call sites. The generalized verb covers both
  network probes (today) and access checks for future Import-capability
  integrations.
- is_initial_import -> is_initial_connect across the synchronizer
  protocol, view layer, templates, and tests. Internal sync /
  synchronize vocabulary is preserved.
- UI labels updated: IMPORT -> CONNECT (in live-discovery contexts),
  REFRESH -> UPDATE (button) / Update (inline link), Initial Import ->
  Initial Connect, Refresh Result -> Update Check Result. The
  no-items hero copy reads 'No items found.' with non-redundant
  sub-text.

Prerequisite for the broader integration-capabilities work in #355.

* Restructure HomeBox importer/ — Connect code to connector/, dormant preserved

The reachable Connect-mode synchronizer code moves from
services/homebox/importer/ to connector/:

- HomeBoxSynchronizer relocates to connector/hb_sync.py.
- New HbEntityFactory in connector/hb_entity_factory.py carries the
  two entity-create/update classmethods previously on HbImporter.

The dormant attribute-population code stays in importer/ for #358:

- HbImporter retains only its four attribute-side classmethods with a
  narrowed docstring noting their dormant status.
- The synchronizer's removed attribute-orchestration methods extract as
  HbAttributeSync in importer/hb_attribute_sync.py with a docstring
  marking them preserved for the HomeBox Importer in #358.

No behavior change. (#355)

* Phase 3 (#355): split integrations app into umbrella + connect sub-package

Relocate the Connect-capability machinery (gateways, synchronizers, sync-check,
views, view mixins, entity operations, attribute edit context, sync-result, and
related transient models) from hi/integrations/ into hi/integrations/connect/.
Umbrella-level modules (models, forms, enums, manager, urls, exceptions, etc.)
stay at hi/integrations/ as the framework root.

This re-shapes the package along capability lines ahead of the Import
capability being added by #358: the umbrella holds capability-agnostic
framework code; each capability sub-package holds the per-capability machinery.

No behavior changes. All call sites updated to the new module paths; all 3141
tests pass and lint is clean.

* Tolerate unreadable sync-check cache entries

The sync-check probe state is stored in Redis as a pickled
SyncCheckResult dataclass. Any class rename, module move, or shape
change can leave stale entries that fail to deserialize on read,
which previously propagated ModuleNotFoundError / AttributeError /
UnpicklingError straight out through the manage page.

Wrap the cache.get in get_state with a broad except: log the failure,
evict the bad key so the next request runs clean, and degrade to a
cache miss. The next probe cycle (or a Refresh) writes fresh state.

The cache is informational drift state, not load-bearing — a soft
miss is the right failure mode.

* Phase 4 (#355): add EntityDataSource enum + Entity.data_source field

EntityDataSource is the entity-wide provenance signal (INTERNAL when HI
owns the representation; EXTERNAL when an upstream system does).
Surfaces via Entity.data_source — a typed accessor over the new
data_source_str CharField, following the existing entity_type pattern.

Migration 0021 backfills integration-attached entities that disallow
internal attributes to EXTERNAL. Today this picks out only HomeBox-
Connect entities; HA / ZM / Frigate / native entities stay INTERNAL.

No UI impact yet. Phase 6 will consume data_source for cross-capability
transition prompts and Import-discard scoping.

* Phase 5 (#355): add IntegrationCapability enum + metadata declaration

IntegrationCapability declares what an integration brings to HI:
CONNECT (live mirror) or IMPORT (one-shot pull). IntegrationMetaData
now carries a `capabilities` frozenset declaring which capability set
the integration participates in; defaults to {CONNECT} since that is
the existing behavior for all four current integrations. An empty
set raises at construction time so a future integration cannot
silently register with no capability.

ALL_CAPABILITIES is provided as a frozenset convenience over all
enum members for callers that want "available everywhere" semantics.

No UI impact yet. Per-attribute capability filtering deferred until
Phase 6 introduces the consumer.

* Phase 6 (#355): make capability filtering explicit at integration list and attribute formset sites

Extend IntegrationAttributeType to accept an optional 8th tuple element
declaring which IntegrationCapabilities the attribute applies to
(defaults to ALL_CAPABILITIES, so existing declarations are unchanged).

Convert the previously-implicit "everything is Connect" assumption into
explicit capability filters at four sites that all run in Connect-mode
context today:

  * IntegrationSelectView (Enable Integrations picker modal)
  * IntegrationManageView (Config tab — enabled-integrations list and
    default-integration selector)
  * IntegrationAttributeItemEditContext (formset construction, used by
    both the Configure modal and the Config tab attribute pane)

IntegrationManager.get_integration_data_list() and
get_default_integration_data() gain an optional `capabilities`
frozenset kwarg. IntegrationAttributeItemEditContext gains a required
`capability` __init__ arg; its formset queryset is now filtered to
attribute rows whose AttributeType includes that capability. The same
class can be reused for the Import edit context in #358 by passing
IntegrationCapability.IMPORT.

Behavior unchanged today (all integrations are Connect, all attributes
default to ALL_CAPABILITIES) but the filter rules are now testable
with mixed-capability fixtures.

The Importer protocol, workflow/views/templates, and cross-capability
transition prompts originally listed in Phase 6 absorb into #358 (the
HomeBox Importer) — they are easier to design with a concrete consumer
driving them.

* Phase 7 (#355): collapse Configure + Pre-Sync + Sync into one CONNECT click

The initial-connect flow becomes a single workflow under
IntegrationEnableView: the user fills the configure form once and
clicks CONNECT, which validates access, saves attributes, enables
the integration, and runs the synchronizer in one pass — landing
directly on the sync-result modal. The previous Configure → Pre-Sync
confirm → Sync handshake is gone from this path, along with the
REVIEW CONFIG round-trip affordance.

Extracted IntegrationViewMixin.render_sync_result so the
synchronizer-invocation + cache-invalidation + sync-result rendering
is shared between IntegrationEnableView (initial-connect) and
IntegrationSyncView (update-check). Action button label flips from
the conditional CONFIGURE/UPDATE to a fixed CONNECT.

IntegrationPreSyncView and its template still serve the manage-page
UPDATE / CONNECT-when-no-entities paths unchanged; the
removal_summary policy choice (RETAIN MISSING / REMOVE MISSING) for
user-data-bearing integrations is preserved end-to-end.

Net behavior change: one fewer modal click on first-time setup.

* Phase 8 (#355): align documentation with the new Connect/Update vocabulary

Update the user-facing button-label references in the per-integration
docs (Refresh / REFRESH → Update / UPDATE; Import action → Connect)
and the developer-facing references where they were tied to user
surfaces. Internal developer vocabulary stays as "sync" — that is
the implementation-side term.

Add a Capability Model subsection to integration-guidelines.md
covering IntegrationCapability, the optional per-attribute capability
restriction, and EntityDataSource. Points at the enum modules; keeps
the explanation brief since the code is the authoritative source.

Update the per-integration doc template's vocabulary instruction so
new integrations start with the right terms.

* Address review feedback: sharpen vocabulary and add IntegrationEnableView POST tests

Four fixes from the pre-PR review pass:

- Sharpen EntityDataSource enum descriptions to disambiguate from raw
  value provenance: "HI owns the editable representation" /
  "Upstream constrains HI-side edits" (the actual semantics codified
  by migration 0021's allow_internal_attributes-based backfill).
- Replace the self-contradicting "first **Import**" / "post-import
  state" in docs/integrations/_template.md with the **Connect**
  vocabulary the same template instructs authors to use.
- Reword frigate.md troubleshooting heading "Update imports zero
  cameras" → "Update finds zero cameras" to stop mixing the UPDATE
  button label with the "imports" verb.
- Add two IntegrationEnableView.post() tests covering the Phase 7
  collapse: the happy path verifies enable + synchronizer.sync()
  fire and the sync-result modal renders; the synchronizer-less
  path verifies enable still flips but no sync-result is returned.
2026-05-24 16:58:18 -05:00

3.3 KiB

Home Information Logo

Overview

One short paragraph: what this integration is for, what kinds of items it imports into HI, and the use cases it best serves. Avoid marketing language; describe behavior.

Introduce Home Information (HI) by full name on first mention, then use the HI abbreviation thereafter. Same convention for upstream services with common abbreviations (e.g., Home Assistant (HA)) — full name first, abbreviation after.

Use item (not "entity") when referring to HI's own representation. Reserve entity / entities for the upstream service when that is the term that service uses (HA, for example, calls them entities, so "HA entity" is correct in that context).

Prerequisites

What the user must have running or installed on their side before configuring this integration in HI. List concretely:

  • Service version supported / minimum tested.
  • Network reachability requirements (must be reachable from the HI server; same LAN; reverse proxy considerations).
  • Any account, API key, or admin permission the user must already have.

Obtaining credentials

Step-by-step instructions specific to this service. Use a numbered list. Where the upstream service has its own documentation for the step, link to it rather than restating.

Screenshots are optional but encouraged when a credential-acquisition step is non-obvious (hidden menu, required role, etc.).

  1. ...
  2. ...
  3. ...

Configuration values

Map exactly what the user enters into each field of HI's Configure form for this integration. Include URL format details that are easy to get wrong (scheme, port, path suffix, trailing slash).

Field What to enter Notes
... ... ...

Setup walkthrough

What the user does in HI to enable the integration once they have their credentials, and what to expect on the first Connect. Keep this brief — it is mostly continuity from the previous section into the post-connect state.

The standard first step is opening HI's integration picker — link back to Enabling an integration for the conditional UI flow rather than restating it here, so a UI change only needs to be reflected in one place.

Use the user-facing terms: Connect for the first run and Update for subsequent runs (matching the button labels). Avoid "sync" in user-facing copy.

Troubleshooting

Common errors and their fixes. Treat this as an accreting list — add entries here as real-world issues surface, rather than aiming for completeness up front.

What it usually means and how to fix it.

...

Known limitations

Things this integration does not do, or does differently from what a new user might reasonably expect. State them plainly so users do not spend time looking for features that are not there.

  • ...
  • ...