Skip to content

fix: review findings on the subentry migration - #1515

Merged
raman325 merged 1 commit into
v6from
fix/v6-review-findings
Aug 28, 2026
Merged

fix: review findings on the subentry migration#1515
raman325 merged 1 commit into
v6from
fix/v6-review-findings

Conversation

@raman325

Copy link
Copy Markdown
Owner

Breaking change

None. Every change here fixes something already on v6.

Proposed change

Two independent review passes over #1514 agreed on the same critical, plus three smaller findings. Each fix comes with the guard that would have caught it.

1. The migration's device move never found a device

__init__.py looked slot devices up as identifiers={build_slot_device_identifier(...)} — a bare string. The device registry keys on (domain, identifier) tuples, which is how entity.py and every other call site creates them. The lookup returned None for every device, so the whole block was dead and every upgrading instance took the deprecated implicit path that block exists to avoid: one assigns an existing device to a different config subentry warning per slot device on every start, and a hard failure on HA Core 2027.8.

Its test could not have caught it. The test built its fixture device with the same malformed identifier the buggy code searched for, so the two agreed with each other and disagreed with production. It now registers the device through the same DeviceInfo the entities carry.

Correcting the identifier alone was still not enough: with the fixture fixed, the test still passed against the broken lookup, because a full setup adds the user's entities and those drag the device across by themselves. The end state is identical whether the migration moved the device or not. The test now exercises async_migrate_entry on its own, which is the only way to observe the difference.

2. Four allocation refusals had no sentence in the subentry flow

config_subentries.user.error was missing too_many_users, numbers_needed_exceed_capacity, search_limit_reached and occupancy_unknown. Adding a user is now the only way to add a user, so a full lock or a sleeping one — the likeliest refusal in practice — showed the bare translation key.

Guard: a test that reads every SlotAllocationError key out of allocation.py and asserts each flow that allocates has a sentence for it. Read from the source rather than listed, so it cannot go stale.

Also pruned options.error to the one key the locks-only options flow can still produce.

3. Editing a user who holds no number raised out of the dialog

subentry.data[CONF_SLOT] in the reconfigure step. Not a state the integration writes — hand-edited storage or a half-finished write leaves one — but it meant the one record a user might need to repair was the one record the UI could not touch. It now issues a number, or refuses cleanly if the lock cannot be read.

4. The shipped card was keeping a back-compat shim alive

add-user-card.ts called add_user with the flat pre-6.0 shape, which works only through _flat_user_to_list. Removing that shim would have broken the Add User button, and no frontend test would have said so — they mock callService, so nothing on that side ever meets the schema. The card now sends the declared users: [...] shape, with a contract test asserting it.

5. Docs promised a removed event still fires

BLUEPRINTS.md and AGENTS.md both said lock_code_manager_lock_state_changed "keeps firing" / is "retained for backward compatibility". It was removed in #1508. BLUEPRINTS.md's claim sat inside the breaking-change note explaining where to recover the fields the entity dropped — pointing users at an event that never fires.

Also

Corrected a comment in the update listener that stated an invariant the options flow can violate: an options submission that changes nothing returns before the settle, leaving options standing. Harmless while options only ever holds data's own contents, which is now noted at the site so nobody adds a field that breaks it.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

The migration's device move looked devices up by a bare string where the
registry keys on (domain, identifier) tuples, so it never found one and
the whole block was dead. Every upgrading instance took the deprecated
implicit path instead -- a warning per slot device today, a hard failure
on HA 2027.8.

Its test built the fixture device with the same malformed identifier, so
bug and test agreed with each other and disagreed with production. The
test now registers the device through the DeviceInfo the entities carry,
and exercises the migration on its own: a full setup adds the entities,
which drag the device across by themselves, so the end state is the same
either way and could never have told the difference.

Also: the four allocation refusals had no sentence in the subentry flow,
so a full or sleeping lock showed a bare translation key; editing a user
who somehow holds no number raised out of the dialog; the shipped card
was the only thing keeping the pre-6.0 flat add_user shim alive; and
BLUEPRINTS.md and AGENTS.md still promised a removed event kept firing.

Each gap gets the guard that would have caught it.

Entire-Checkpoint: 75d1ad41c0e9
Copilot AI lite review requested due to automatic review settings August 28, 2026 19:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added python Pull requests that update Python code javascript Pull requests that update javascript code documentation Documentation changes breaking-change Pull requests that break existing functionality bug Something isn't working labels Aug 28, 2026
@raman325
raman325 merged commit d082ef4 into v6 Aug 28, 2026
5 checks passed
@raman325
raman325 deleted the fix/v6-review-findings branch August 28, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Pull requests that break existing functionality bug Something isn't working documentation Documentation changes javascript Pull requests that update javascript code python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants