Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
13737ff
Bump librehardwaremonitor-api to version 1.10.1 (#163572)
Sab44 Feb 23, 2026
99bd661
Add allow_none_value=True to MatterDiscoverySchema for electrical po…
lboue Feb 23, 2026
ea71c40
Bump deebot-client to 18.0.0 (#163835)
edenhaus Feb 23, 2026
85eeac6
Fix Matter energy sensor discovery when value is null (#162044)
kshypachov Feb 23, 2026
bd6b8a8
Teltonika integration: add reauth config flow (#163712)
karlbeecken Feb 23, 2026
9d54236
Add integration_type hub to waqi (#163754)
joostlek Feb 23, 2026
fe377be
Add integration_type hub to wallbox (#163752)
joostlek Feb 23, 2026
cf5733d
Add integration_type device to tilt_pi (#163667)
joostlek Feb 23, 2026
77a56a3
Add integration_type device to smart_meter_texas (#163398)
joostlek Feb 23, 2026
0f6a3a8
Add integration_type service to snapcast (#163401)
joostlek Feb 23, 2026
6299e8c
Add support for current sensors to egauge integration (#163728)
neggert Feb 23, 2026
74a3f4b
Bump securetar to 2026.2.0 (#163226)
emontnemery Feb 23, 2026
cdb92a5
Fix Matter speaker mute toggle (#161128)
lboue Feb 23, 2026
e1667bd
Increase request timeout from 10 to 20s in FRITZ!SmartHome (#163818)
mib1185 Feb 23, 2026
5e3d2be
Add integration_type device to sia (#163393)
joostlek Feb 23, 2026
8093649
Add Zinvolt integration (#163449)
joostlek Feb 23, 2026
f304274
Deprecate Libre Hardware Monitor versions below v0.9.5 (#163838)
Sab44 Feb 23, 2026
ac65163
Bump forecast-solar to v5.0.0 (#163841)
klaasnicolaas Feb 23, 2026
dfb17c2
Add configurable panel properties to frontend (#162742)
piitaya Feb 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .strict-typing
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ homeassistant.components.yale_smart_alarm.*
homeassistant.components.yalexs_ble.*
homeassistant.components.youtube.*
homeassistant.components.zeroconf.*
homeassistant.components.zinvolt.*
homeassistant.components.zodiac.*
homeassistant.components.zone.*
homeassistant.components.zwave_js.*
2 changes: 2 additions & 0 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 4 additions & 20 deletions homeassistant/backup_restore.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from collections.abc import Iterable
from dataclasses import dataclass
import hashlib
import json
import logging
from pathlib import Path
Expand Down Expand Up @@ -40,17 +39,6 @@ class RestoreBackupFileContent:
restore_homeassistant: bool


def password_to_key(password: str) -> bytes:
"""Generate a AES Key from password.

Matches the implementation in supervisor.backups.utils.password_to_key.
"""
key: bytes = password.encode()
for _ in range(100):
key = hashlib.sha256(key).digest()
return key[:16]


def restore_backup_file_content(config_dir: Path) -> RestoreBackupFileContent | None:
"""Return the contents of the restore backup file."""
instruction_path = config_dir.joinpath(RESTORE_BACKUP_FILE)
Expand Down Expand Up @@ -96,15 +84,14 @@ def _extract_backup(
"""Extract the backup file to the config directory."""
with (
TemporaryDirectory() as tempdir,
securetar.SecureTarFile(
securetar.SecureTarArchive(
restore_content.backup_file_path,
gzip=False,
mode="r",
) as ostf,
):
ostf.extractall(
ostf.tar.extractall(
path=Path(tempdir, "extracted"),
members=securetar.secure_path(ostf),
members=securetar.secure_path(ostf.tar),
filter="fully_trusted",
)
backup_meta_file = Path(tempdir, "extracted", "backup.json")
Expand All @@ -126,10 +113,7 @@ def _extract_backup(
f"homeassistant.tar{'.gz' if backup_meta['compressed'] else ''}",
),
gzip=backup_meta["compressed"],
key=password_to_key(restore_content.password)
if restore_content.password is not None
else None,
mode="r",
password=restore_content.password,
) as istf:
istf.extractall(
path=Path(tempdir, "homeassistant"),
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/backup/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@
"home-assistant_v2.db",
"home-assistant_v2.db-wal",
]

SECURETAR_CREATE_VERSION = 2
25 changes: 12 additions & 13 deletions homeassistant/components/backup/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,9 @@
from typing import IO, TYPE_CHECKING, Any, Protocol, TypedDict, cast

import aiohttp
from securetar import SecureTarFile, atomic_contents_add
from securetar import SecureTarArchive, atomic_contents_add

from homeassistant.backup_restore import (
RESTORE_BACKUP_FILE,
RESTORE_BACKUP_RESULT_FILE,
password_to_key,
)
from homeassistant.backup_restore import RESTORE_BACKUP_FILE, RESTORE_BACKUP_RESULT_FILE
from homeassistant.const import __version__ as HAVERSION
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import (
Expand Down Expand Up @@ -60,6 +56,7 @@
EXCLUDE_DATABASE_FROM_BACKUP,
EXCLUDE_FROM_BACKUP,
LOGGER,
SECURETAR_CREATE_VERSION,
)
from .models import (
AddonInfo,
Expand Down Expand Up @@ -1858,20 +1855,22 @@ def is_excluded_by_filter(path: PurePath) -> bool:

return False

outer_secure_tarfile = SecureTarFile(
tar_file_path, "w", gzip=False, bufsize=BUF_SIZE
)
with outer_secure_tarfile as outer_secure_tarfile_tarfile:
with SecureTarArchive(
tar_file_path,
"w",
bufsize=BUF_SIZE,
create_version=SECURETAR_CREATE_VERSION,
password=password,
) as outer_secure_tarfile:
raw_bytes = json_bytes(backup_data)
fileobj = io.BytesIO(raw_bytes)
tar_info = tarfile.TarInfo(name="./backup.json")
tar_info.size = len(raw_bytes)
tar_info.mtime = int(time.time())
outer_secure_tarfile_tarfile.addfile(tar_info, fileobj=fileobj)
with outer_secure_tarfile.create_inner_tar(
outer_secure_tarfile.tar.addfile(tar_info, fileobj=fileobj)
with outer_secure_tarfile.create_tar(
"./homeassistant.tar.gz",
gzip=True,
key=password_to_key(password) if password is not None else None,
) as core_tar:
atomic_contents_add(
tar_file=core_tar,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/backup/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"integration_type": "service",
"iot_class": "calculated",
"quality_scale": "internal",
"requirements": ["cronsim==2.7", "securetar==2025.2.1"],
"requirements": ["cronsim==2.7", "securetar==2026.2.0"],
"single_config_entry": true
}
Loading
Loading