## Summary
- normalize manually entered server URLs by stripping path, query, and
fragment while preserving port and authority
- use the normalized base URL for onboarding auth and for the stored
manual server URL
- add tests covering auth URL construction, discovered manual URLs, and
the shared URL helper
## Root cause
Manual onboarding appended /auth/authorize to the full user-entered URL.
If the user entered a frontend route like /lovelace/0, the auth flow
loaded /lovelace/0/auth/authorize and never reached the expected
callback.
## Summary
Custom widget AppIntents
(`CustomWidgetToggle/Activate/PressButton/UpdateWidgetItemConfirmationStateAppIntent`)
used a single combined `guard` block with a silent `return .result()` on
failure. When a tap bailed out — wrong domain, missing parameters,
server lookup miss, no active URL — nothing was logged anywhere, which
made user reports like
[#4488](https://github.com/home-assistant/iOS/issues/4488) ("widget taps
do nothing on iOS 26.4+") impossible to triage.
Changes:
- Split each guard into separate checks with an `Current.Log.error(...)`
line per failure mode, so the widget-extension log now shows *which*
precondition failed.
- Extract the server/connection lookup into a small
`CustomWidgetIntentHelper.resolveConnection` so the three intents don't
duplicate the same boilerplate.
- When `Current.api(for: server)` returns nil (i.e. `activeURL()` is nil
— server unreachable from this network), dispatch a local notification
("Home Assistant could not be reached…") so the tap no longer silently
does nothing.
No behavior change for the success path. Failure paths still `return
.result()` — they just now leave evidence behind.
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Before forwarding unknown tags to Home Assistant, present a confirmation
dialog.
Android implementation:
https://github.com/home-assistant/android/pull/6814
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="966" height="1004" alt="CleanShot 2026-05-07 at 15 56 54@2x"
src="https://github.com/user-attachments/assets/b7411e42-c2ec-473b-8241-c3280531737f"
/>
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Fixes mTLS client certificate sharing across multiple servers when the
same .p12 / SecIdentity is assigned to more than one server.
- Store imported client certificate identities using a stable SHA-256
fingerprint of the leaf certificate instead of a server-specific
identifier.
- Update duplicate Keychain identity handling so re-importing the same
certificate migrates the existing item to the stable fingerprint-based
label.
- Avoid deleting a shared Keychain identity when removing or replacing a
certificate on one server if another configured server still references
it.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
As part of removing legacy iOS actions from the app completely, this PR
adds a way for the user to choose what to display in app icon long press
menu.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="3216" height="1890" alt="CleanShot 2026-04-30 at 11 35
28@2x"
src="https://github.com/user-attachments/assets/4680d7e4-4790-4f21-b4b4-b93f641ce769"
/>
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
## Summary
Now that PRs #4560–#4564 have migrated every Eureka-based settings
screen to SwiftUI, every remaining Eureka file on `main` is dead code.
This PR removes them, the Eureka pod, and the two Eureka-community
add-on pods.
**Reachability check before deleting:**
- `SettingsRootDataSource.swift` (the legacy Eureka settings root) has
zero inbound references. The active settings root is
`SettingsItem.swift`, which already routes to SwiftUI views
(`NFCListView()`, `ComplicationListView()`, etc.).
- The legacy `*ViewController.swift` files (`NFCListViewController`,
`ComplicationListViewController`, `SettingsDetailViewController`, etc.)
are reachable only from `SettingsRootDataSource` and from each other.
- The Eureka helper-row library (`Sources/App/Settings/Eureka/`) is used
only by those legacy view controllers.
- A handful of doc-comment mentions in active SwiftUI code (e.g. `//
SwiftUI replacement for ButtonRowWithLoading`) are not real references.
- Tests don't import Eureka. `ColorPickerRow` and `ViewRow` (Eureka
community pods) aren't referenced anywhere.
## What's removed
- `Sources/App/Settings/Eureka/` — 14 files (`HAFormViewController`,
helper rows, `AccountInitialsImage`)
- `Sources/App/Settings/MaterialDesignIcons+Eureka.swift` — `SearchItem`
conformance for the now-deleted `SearchPushRow`
- `Sources/App/Settings/SettingsRootDataSource.swift`
- `Sources/App/Settings/Settings/SettingsDetailViewController.swift`
-
`Sources/App/Settings/AppleWatch/Complication{List,FamilySelect,Edit}ViewController.swift`
- `Sources/App/Settings/NFC/NFC{List,Tag}ViewController.swift`
- `Sources/App/Utilities/{SearchPushRow,WebSocketStatusRow}.swift`
- `Eureka`, `ColorPickerRow`, `ViewRow` pods (Podfile + Podfile.lock)
- `import Eureka` from `SettingsSceneDelegate.swift`
- `-framework "Eureka"` from inlined `OTHER_LDFLAGS` in
`project.pbxproj`
24 files deleted, 4 modified. Pure dead-code removal — no behavior
changes.
## Stacked on #4563
This PR targets `claude/eureka-notification-categories-swiftui` (PR
#4563). After #4563 merges, GitHub will auto-rebase the base to `main`.
## Test plan
- [ ] CI lint + test passes
- [ ] Build succeeds with the smaller pod set
- [ ] Manual smoke test: open Settings → NFC, Settings → Complications,
Notifications → Categories — all SwiftUI screens still functional
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Replace the Eureka actions list with `ActionsSettingsView` +
`ActionsSettingsViewModel` (value-type Realm snapshots, delete/reorder,
scene toggle + customize flow, server refresh). Replace
`ActionConfigurator` with `ActionConfiguratorView` using SwiftUI `Form`,
`IconPicker`, SwiftUI `ColorPicker`, the existing
`WidgetBasicButtonView` preview, and a new inline `ActionServerPicker`.
`SettingsItem.actions` is wired directly to the SwiftUI view and the
Eureka actions code is removed from `SettingsDetailViewController`.
## Screenshots
_Pending — to be added before merge._
## Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
## Any other notes
Part of a five-PR Eureka → SwiftUI migration tracked in
`UIKitToSwiftUIMigration.md` (siblings: #4560, #4562, #4563, #4564). The
`Eureka`, `ColorPickerRow`, and `ViewRow` pods stay until all slices
land.
`ServerSelectRow.swift` is intentionally kept in-tree because
`ComplicationEditViewController` still uses it — both come out once the
complications slice (#4564) merges.
Not build-verified locally yet; may surface access-level fixes (e.g.
internal synthesized initializers on Shared types) during build.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
iPad has supported Live Activities since iPadOS 17 — the previous
`userInterfaceIdiom == .pad` guard in `LiveActivitySettingsView` was
incorrect. `areActivitiesEnabled` (the `ActivityAuthorizationInfo` API)
already returns the correct value on iPad, so no platform-specific gate
is needed.
Changes:
- Remove the `userInterfaceIdiom == .pad` branch from
`LiveActivitySettingsView` that showed a static "Not available on iPad"
label. iPad users now see the same enabled/open-settings states as
iPhone.
- Drop the `live_activity.status.not_supported` localisation key from
all 34 locale files and the generated `Strings.swift` accessor.
- Update a stale comment in `HAAPI.swift` that incorrectly stated iPads
report `false` for `areActivitiesEnabled`.
ActivityKit handles Dynamic Island availability transparently — the
island pill appears on iPhone 14 Pro/Pro Max and all iPhone 15 and later
models; on iPad and older iPhones it simply doesn't render, and the
activity shows on the Lock Screen only.
## References
- Apple docs confirming iPad support: [Displaying live data with Live
Activities](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities)
- Companion docs PR: home-assistant/companion.home-assistant#1303
## Test plan
- [ ] On iPhone: Live Activities settings screen shows
enabled/open-settings as before
- [ ] On iPad (iPadOS 17+): settings screen no longer shows "Not
available on iPad"; shows enabled/open-settings
- [ ] On iPad (iPadOS 17+): Live Activities can be started and updated
from Home Assistant
- [ ] On iPad (iPadOS 16 or earlier): `areActivitiesEnabled` returns
`false`; open-settings button shown
- [ ] Verify `live_activity.status.not_supported` key is absent from all
`.lproj` files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Avoid passing an explicit empty passphrase to SecPKCS12Import on macOS
by introducing ClientCertificateManager.pkcs12ImportOptions(password:).
importP12 now uses this helper so an empty password results in no
passphrase option being supplied. Added unit tests verifying both empty
and non-empty password behavior and imported Security in the test file.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
https://github.com/user-attachments/assets/e6c5eecb-4399-4e44-94e8-dc0b5ed8d744
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Fixes three distinct crashes in the widget extension process that cause
widgets to go blank and not recover until the app is reinstalled.
- **ServerCache precondition crash** — `ServerCache.info.didSet` uses a
`precondition` that reads `deletedServers` from shared UserDefaults on
every check. When the main app deletes a server, the widget's cached
`info` dict still contains it, causing the precondition to fail on the
next mutation. Replaced with an error log, matching the existing pattern
for the `server` dict. This was the most common crash (4 of 10 logs)
and created a permanent crash loop only fixable by reinstalling.
- **Thread-unsafe `cachedApis` dictionary** —
`AppEnvironment.cachedApis`
is a plain dictionary accessed concurrently from multiple AppIntent
threads (`ScriptAppIntent`, `SwitchIntent`), causing memory corruption.
Added `NSLock` synchronization around all access.
- **`fatalError` in GRDB initialization** — When `DatabaseQueue` fails
to
open the on-disk database (locked file, corruption, file protection),
the widget extension calls `fatalError`. Replaced with a fallback to an
in-memory database, matching Realm's existing pattern.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="2792" height="1558" alt="CleanShot 2026-04-14 at 15 20
18@2x"
src="https://github.com/user-attachments/assets/59c1e658-d7fd-4b9c-9712-9421911ce554"
/>
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
## Summary
Follow-up fixes after #4444 merged, addressing issues found during Mac
Catalyst testing:
- **Fix `›` character in Frequent Updates footer** — `.strings` files
don't interpret `\uXXXX` escapes at runtime; replaced with the literal
`›` character
- **Fix Mac Catalyst compilation** — `ActivityKit` APIs
(`ActivityAttributes`, `Activity`, `ActivityUIDismissalPolicy`, etc.)
are marked unavailable on Mac Catalyst even though
`canImport(ActivityKit)` returns true there. Replaced all `#if
canImport(ActivityKit)` and bare `#if os(iOS)` guards around ActivityKit
code with `#if os(iOS) && !targetEnvironment(macCatalyst)`. Files
affected:
- `HALiveActivityAttributes.swift`
- `LiveActivityRegistry.swift`
- `HandlerLiveActivity.swift`
- `LiveActivitySettingsView.swift`
- `HADynamicIslandView.swift`
- `HALockScreenView.swift`
- `HALiveActivityConfiguration.swift`
- `Widgets.swift` (three `HALiveActivityConfiguration()` call sites)
- `Environment.swift`, `AppDelegate.swift`, `HAAPI.swift`,
`NotificationsCommandManager.swift`, `SettingsItem.swift` (inline
guards)
## Test plan
- [x] iOS builds and runs
- [x] macOS (Mac Catalyst) builds and launches
- [ ] Live Activities settings entry does not appear on macOS (filtered
by `isTestFlight` + `#available(iOS 17.2, *)`)
- [ ] Live Activities work as expected on iOS TestFlight build
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Remove the portWithFallback helper and update port comparisons to use
URL.port directly. baseIsEqual now compares ports via url.port (no
80/443 fallback), and SafeScriptMessageHandler passes url.port ?? 0 when
building origin keys (security origin uses port 0 when unspecified).
This simplifies port handling and avoids implicit defaulting to standard
ports.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
## Summary
> For architecture decisions, data model details, iOS version strategy,
push token flow, and rate limiting — see
[technical-brief.pdf](https://github.com/user-attachments/files/26280274/technical-brief.pdf)
Adds iOS Live Activities support, letting Home Assistant automations
push real-time state to the Lock Screen — washing machine countdowns, EV
charging progress, delivery tracking, alarm states, or anything
time-sensitive that benefits from glanceable visibility without
unlocking the phone.
When an automation sends a notification with `live_update: true` in the
data payload, the companion app starts a Live Activity instead of (or in
addition to) a standard notification banner. Subsequent pushes with the
same `tag` update it in-place silently. `clear_notification` + `tag`
ends it.
Field names (`tag`, `title`, `message`, `progress`, `progress_max`,
`chronometer`, `when`, `when_relative`, `notification_icon`,
`notification_icon_color`) are intentionally shared with Android's Live
Notifications API. Both platforms use the same `live_update: true`
trigger — a single YAML block targets iOS 17.2+ and Android 16+ with no
platform-specific keys.
```yaml
data:
title: "Washing Machine"
message: "Cycle in progress"
data:
tag: washer_cycle
live_update: true # Android 16+ and iOS 17.2+
progress: 2700
progress_max: 3600
chronometer: true
when: 2700
when_relative: true
notification_icon: mdi:washing-machine
notification_icon_color: "#2196F3"
```
**New files:**
- `Sources/Shared/LiveActivity/HALiveActivityAttributes.swift` — the
`ActivityAttributes` type. Field names match the Android payload spec.
**Struct name and `CodingKeys` are wire-format frozen** — APNs
push-to-start payloads reference the Swift type name directly.
- `Sources/Shared/LiveActivity/LiveActivityRegistry.swift` — Swift
`actor` managing `Activity<HALiveActivityAttributes>` lifecycle. Uses a
reservation pattern to prevent duplicate activities when two pushes with
the same `tag` arrive simultaneously.
-
`Sources/Shared/Notifications/NotificationCommands/HandlerLiveActivity.swift`
— start/update and end `NotificationCommandHandler` implementations,
guarded against the `PushProvider` extension process where ActivityKit
is unavailable.
- `Sources/Extensions/Widgets/LiveActivity/` — `ActivityConfiguration`
wrapper, Lock Screen / StandBy view, and compact / minimal / expanded
Dynamic Island views.
- `Sources/App/Settings/LiveActivity/LiveActivitySettingsView.swift` —
activity status, active list, privacy disclosure, and 11 debug scenarios
for pre-server-side testing.
**Modified files:**
- `Widgets.swift` — registers `HALiveActivityConfiguration` in all three
`WidgetBundle` variants behind `#available(iOSApplicationExtension 17.2,
*)`
- `NotificationsCommandManager.swift` — registers new handlers;
`HandlerClearNotification` now also ends a matching Live Activity when
`tag` is present
- `HAAPI.swift` — adds `supports_live_activities`,
`supports_live_activities_frequent_updates`,
`live_activity_push_to_start_token`,
`live_activity_push_to_start_apns_environment` to registration payload
under a single `#available(iOS 17.2, *)` check
- `AppDelegate.swift` — reattaches surviving activities at launch and
starts observing push-to-start tokens under a single `#available(iOS
17.2, *)` check
- `Info.plist` — `NSSupportsLiveActivities` +
`NSSupportsLiveActivitiesFrequentUpdates`
- `SettingsItem.swift` / `SettingsView.swift` — Live Activities settings
row is gated behind `Current.isTestFlight` and shows a `BetaLabel` badge
**Tests:**
- *Unit Tests*
- 45 new tests (36 handler tests, 9 command manager routing tests). All
490 existing tests continue to pass.
- *Device Tests*
- I tried to test with my physical device, however I do not have a paid
account. Turns out I could not deploy without disabling a lot of
entitlements for compilation. Even so, once I did get it deployed and
running Live Activities wouldn't show unless some of those settings that
I disable were re-enable and leaving me in a particular spot.
- I mainly tested with the simulator which is what is shown below
## Screenshots

## Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#1303
## Link to pull request in push relay repository
Relay server: home-assistant/mobile-apps-fcm-push#278
## Link to pull request in HA core
Core: home-assistant/core#166072
## Any other notes
**iOS version gating at 17.2.** The entire feature is gated at
`#available(iOS 17.2, *)` — this is the minimum for push-to-start (the
primary server-side start mechanism). A single availability check now
covers all Live Activity APIs: `supports_live_activities`,
`frequentPushesEnabled`, push-to-start token, and all ActivityKit usage.
This eliminates the nested 16.2/17.2 check pattern.
**Push-to-start (iOS 17.2+) is client-complete.** The token is observed,
stored in Keychain, and included in registration payloads. All companion
server-side PRs are now open — relay server at
home-assistant/mobile-apps-fcm-push#278 and HA core webhook handlers at
home-assistant/core#166072. The relay server uses FCM's native
`apns.liveActivityToken` support (Firebase Admin SDK v13.5.0+) — no
custom APNs client or credentials needed.
> **Server-side work** — all PRs now open:
> - ~~`supports_live_activities` field handling in device registration~~
✓ home-assistant/core#166072
> - ~~`mobile_app_live_activity_token` webhook handler~~ ✓
home-assistant/core#166072
> - ~~`mobile_app_live_activity_dismissed` webhook handler~~ ✓
home-assistant/core#166072
> - ~~Relay server: Live Activity delivery via FCM
`apns.liveActivityToken`~~ ✓ home-assistant/mobile-apps-fcm-push#278
> - ~~`notify.py` routing: includes Live Activity APNs token alongside
FCM token~~ ✓ home-assistant/core#166072
**Live Activities entry in Settings is gated behind TestFlight.** The
settings row only appears when `Current.isTestFlight` is true,
preventing it from surfacing in a release build before the feature is
fully tested. A `BetaLabel` badge is shown alongside the row title.
**iPad:** `areActivitiesEnabled` is always `false` on iPad — Apple
system restriction. The Settings screen shows "Not available on iPad."
The registry silently no-ops. HA receives `supports_live_activities:
false` in the device registration for iPad.
**`HALiveActivityAttributes` is frozen post-ship.** The struct name
appears as `attributes-type` in APNs push-to-start payloads. Renaming it
silently breaks all remote starts. The `ContentState` `CodingKeys` are
equally frozen — only additions are safe. Both have comments in the
source calling this out.
**The debug section in Settings is intentional.** Gated behind `#if
DEBUG` so it only appears in debug builds — it never ships to TestFlight
or the App Store. It exercises the full ActivityKit lifecycle without
requiring the server-side chain.
**`UNUserNotificationCenter` in tests.** The `clear_notification` +
`tag` → Live Activity dismissal path is covered by code review rather
than a unit test. `HandlerClearNotification` calls
`UNUserNotificationCenter.current().removeDeliveredNotifications`
synchronously, which requires a real app bundle and throws
`NSInternalInconsistencyException` in the XCTest host. A comment in the
test file explains this.
**Rate limiting on iOS 18.** Apple throttles Live Activity updates to
~15 seconds between renders. Automations should trigger on state change
events, not polling timers.
**Related:**
- Community discussion:
https://github.com/orgs/home-assistant/discussions/84
- Android companion reference: https://github.com/home-assistant/android
- Roadmap: https://github.com/home-assistant/roadmap/issues/52
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Bruno Pantaleão Gonçalves <5808343+bgoncal@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="800" height="480" alt="Simulator Screenshot - Daily tester 2
- 2026-03-31 at 16 45 28"
src="https://github.com/user-attachments/assets/927764c8-9de7-49e9-98c4-8cc8fd0bcf6b"
/>
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="2030" height="494" alt="CleanShot 2026-03-31 at 10 36 48@2x"
src="https://github.com/user-attachments/assets/539853f4-f8dc-46d6-a167-25af8ca0b399"
/>
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
## Summary
Rebrand the `BetaLabel` component: replace "BETA" text with "Labs" and
add a leading MaterialDesignIcons test-tube icon.
- Replace `"BETA"` → `"Labs"` in both the capsule label and the info
sheet navigation title
- Add `MaterialDesignIcons.testTubeIcon` (15×15, white) as a leading
element in the HStack, consistent with how `ExternalLinkButton` and
`SettingsButton` use MDI icons
## Screenshots
## Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
## Any other notes
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
## Summary
Remove 3 unused localization strings flagged by the unused strings check
in #4451:
- `kiosk.auth.try_again`
- `kiosk.exit_button`
- `kiosk.exit_hint`
Removed from all 34 `Localizable.strings` language files and the
SwiftGen-generated `Strings.swift`.
## Screenshots
N/A — no UI changes; these strings had no references in the codebase.
## Link to pull request in Documentation repository
N/A
## Any other notes
Pure deletions only (108 lines removed across 35 files). Verified zero
references to these strings exist in Swift source.
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## Summary
Reopening kiosk mode PR (previously #4218) after addressing all review
feedback from @bgoncal. Apologies for the delay — some family matters
pulled me away, but I'm excited to get this implemented and am fully
committed to seeing it through.
This PR adds the foundational infrastructure for **kiosk mode** — a
feature designed for wall-mounted iPad displays running Home Assistant
dashboards.
### What's included:
- **KioskModeManager** — Central coordinator singleton with
KioskModeObserver protocol (no NotificationCenter)
- **KioskSettings** — Comprehensive settings model with GRDB persistence
(camelCase columns, Codable)
- **Screensaver system** — Clock screensaver with 4 styles, pixel shift
for OLED burn-in prevention
- **Secret exit gesture** — Configurable corner tap to access settings
when locked down
- **Status bar hiding** — StatusBarForwardingNavigationController for
proper UIKit integration
- **Settings UI** — SwiftUI settings accessible via Settings menu and
secret gesture
- **28 unit tests** — Covering settings serialization, time logic,
orientations, enums
### Changes since #4218 (all review feedback addressed):
- ✅ Fixed settings modal dismissal on iOS 15 (UINavigationController +
explicit onDismiss closure)
- ✅ Fixed status bar hiding (StatusBarForwardingNavigationController +
statusBarView integration)
- ✅ Removed non-functional settings (navigationLockdown,
TouchFeedbackManager, IconMapper)
- ✅ Replaced `Date()` with `Current.date()` for testability
- ✅ GRDB persistence follows CarPlayConfig/WatchConfig pattern with
DatabaseTableProtocol
- ✅ All strings localized via L10n (SwiftGen)
- ✅ SFSafeSymbols used throughout (no string-based systemName)
- ✅ KioskModeObserver protocol (no NotificationCenter)
- ✅ Kiosk files prefixed with `Kiosk`
- ✅ UIKit screensaver container (required for status bar/home indicator
control)
- ✅ macCatalyst filtered out
- ✅ Merged with latest upstream/main (adapted to Frontend/ directory
restructure)
- ✅ Idle timer pauses when settings view is open
- ✅ TODO comments (no PR-specific comments)
### Testing Instructions
1. **Settings → Companion App → Kiosk Mode** → Enable "Enable Kiosk
Mode"
2. Set screensaver timeout to **30 seconds** for quick testing
3. Wait for screensaver → tap to wake
4. Use secret gesture (default: 3 taps in top-left corner) to access
settings
### Previous review context
All feedback from @bgoncal in #4218 has been addressed. See that PR for
full discussion history.
## Test plan
- [ ] Enable/disable kiosk mode from Settings
- [ ] Screensaver activates after timeout
- [ ] Tap to wake from screensaver
- [ ] Secret gesture opens settings
- [ ] Status bar hides when kiosk mode active (full-screen iPad only)
- [ ] Device authentication toggle works
- [ ] Settings persist across app restart
- [ ] Clock screensaver styles (large, minimal, digital, analog)
- [ ] Pixel shift moves clock position periodically
- [ ] Kiosk entry hidden on macCatalyst
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Nick Stefanelli <nstefanelli@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Introduce HAAppUsedContent to centralize the list of Home Assistant
domains and provide rawValues. Use HAAppUsedContent.rawValues in
AppEntitiesModel to filter entities (removing the local domains list).
Update EntityAddToHandler to only add CustomWidgetAction when the
entity's Domain can be constructed and is included in
HAAppUsedContent.domains. Change MagicItem's default interactionType
from a refresh app intent to a navigateIntent that opens the entity deep
link (AppConstants.openEntityDeeplinkURL). These changes restrict widget
availability to supported domains and make default item interactions
navigate directly to the entity.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="603" height="1311" alt="Captura de Tela 2026-03-09 à(s) 15
16 13"
src="https://github.com/user-attachments/assets/17c166ec-815e-4311-acaa-127e431e655a"
/>
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->