Problem Description
A Lock Code Manager config entry is a set of locks, and inside it sits N users you add and remove. Home Assistant has a first-class shape for exactly that — config subentries — and we hand-rolled the whole thing instead.
Today, adding and removing a user means machinery we wrote and maintain:
| what happens |
who does it now |
| Add a user |
lcm-add-user custom card + add_user action |
| Remove a user |
confirm dialog on the user card + delete_user action |
| Give the user a device |
build_slot_device_info, created by hand in the update listener |
| Clean up when a user goes |
_async_purge_dropped_slots, plus async_remove_config_entry_device guarding UI deletes |
| Reconfigure a user |
the entry's options flow, which edits the whole user map |
That last column is where the bugs have been. 5.0.0 shipped fixes for a removed user's PIN staying live on the lock, for orphaned per-user devices, for a config-entry device that existed only to parent them, and for registry rows surviving a dropped slot. Every one of those is lifecycle bookkeeping that Home Assistant already does for subentries.
Feature Description
Move users from entry.options["users"] into config subentries: one subentry per user, subentry_type: "user", title = the user's name.
What Home Assistant gives us for free
ConfigSubentryFlow renders Add user and Reconfigure user natively on the integration page — no custom card, no dialog.
async_add_entities(config_subentry_id=...) and config_subentry_id on device registry entries mean the user's device and entities belong to the subentry.
- Deleting the subentry reaps its devices and entities.
_async_purge_dropped_slots and the device-delete guard stop being ours to get right.
- The subentry
title is the user's name, so renaming is a title change rather than a re-key.
What does not change, and should not
- The model. 5.0.0's user-centric model is the prerequisite for this, not a competitor to it. Users are already name-keyed with slot assignment held separately; this moves where they are stored, not what they are.
add_user / delete_user stay. Subentry flows are UI-only and cannot be called from a script. Automations still need the actions; they would write subentries instead of entry options.
- Slot allocation stays entry-wide. It reads every lock in the entry and asks each provider where its numbers stop, so a subentry flow calls the same allocator. Slot numbers remain internal bookkeeping.
- Unique IDs.
{entry_id}|{slot}|{key} can stay exactly as it is, so entity IDs, history, and anything referencing them survive. Only the entity's owner changes.
Sketch of the work
async_get_supported_subentry_types returning a user flow; add + reconfigure steps reusing the existing name/PIN/condition validation.
- Config entry migration v4 → v5: each
users[name] entry becomes a subentry carrying its PIN, enabled state, condition and assigned slot.
- Entity platforms pass
config_subentry_id when adding; build_slot_device_info gains the subentry so HA owns the device.
add_user / delete_user rewritten onto async_add_subentry / async_remove_subentry.
- Retire
lcm-add-user and the remove dialog, or point them at the native flows.
- Websocket + dashboard strategy enumerate subentries rather than the user map.
Timing
Not next. 5.0.0 landed a one-way migration that renamed every entity ID, and a second breaking migration weeks later is a trust and support cost even when the diff is clean. Suggest 6.0, once 5.x has settled.
Anything else?
One constraint worth writing down now: users must live in exactly one place. A halfway state — users in entry options and in subentries — would be the same two-sources-of-truth trap behind most of the real bugs found while building 5.0.0: two lock display-name resolvers that disagreed, an entity name declared in strings.json and thrown away in code, a registry rewound while the recorder moved forward. The migration should be total.
Subentries are well within our floor: hacs.json requires HA 2026.7.0b0 and ConfigSubentryFlow predates it comfortably.
Config entry version is currently 4, so this would be 4 → 5.
Problem Description
A Lock Code Manager config entry is a set of locks, and inside it sits N users you add and remove. Home Assistant has a first-class shape for exactly that — config subentries — and we hand-rolled the whole thing instead.
Today, adding and removing a user means machinery we wrote and maintain:
lcm-add-usercustom card +add_useractiondelete_useractionbuild_slot_device_info, created by hand in the update listener_async_purge_dropped_slots, plusasync_remove_config_entry_deviceguarding UI deletesThat last column is where the bugs have been. 5.0.0 shipped fixes for a removed user's PIN staying live on the lock, for orphaned per-user devices, for a config-entry device that existed only to parent them, and for registry rows surviving a dropped slot. Every one of those is lifecycle bookkeeping that Home Assistant already does for subentries.
Feature Description
Move users from
entry.options["users"]into config subentries: one subentry per user,subentry_type: "user",title= the user's name.What Home Assistant gives us for free
ConfigSubentryFlowrenders Add user and Reconfigure user natively on the integration page — no custom card, no dialog.async_add_entities(config_subentry_id=...)andconfig_subentry_idon device registry entries mean the user's device and entities belong to the subentry._async_purge_dropped_slotsand the device-delete guard stop being ours to get right.titleis the user's name, so renaming is a title change rather than a re-key.What does not change, and should not
add_user/delete_userstay. Subentry flows are UI-only and cannot be called from a script. Automations still need the actions; they would write subentries instead of entry options.{entry_id}|{slot}|{key}can stay exactly as it is, so entity IDs, history, and anything referencing them survive. Only the entity's owner changes.Sketch of the work
async_get_supported_subentry_typesreturning auserflow; add + reconfigure steps reusing the existing name/PIN/condition validation.users[name]entry becomes a subentry carrying its PIN, enabled state, condition and assigned slot.config_subentry_idwhen adding;build_slot_device_infogains the subentry so HA owns the device.add_user/delete_userrewritten ontoasync_add_subentry/async_remove_subentry.lcm-add-userand the remove dialog, or point them at the native flows.Timing
Not next. 5.0.0 landed a one-way migration that renamed every entity ID, and a second breaking migration weeks later is a trust and support cost even when the diff is clean. Suggest 6.0, once 5.x has settled.
Anything else?
One constraint worth writing down now: users must live in exactly one place. A halfway state — users in entry options and in subentries — would be the same two-sources-of-truth trap behind most of the real bugs found while building 5.0.0: two lock display-name resolvers that disagreed, an entity name declared in
strings.jsonand thrown away in code, a registry rewound while the recorder moved forward. The migration should be total.Subentries are well within our floor:
hacs.jsonrequires HA 2026.7.0b0 andConfigSubentryFlowpredates it comfortably.Config entry version is currently 4, so this would be 4 → 5.