mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-05 06:08:59 +00:00
Seven version sources move together to 1.75.0-beta.1, both changelogs close their section over what has landed since the stable v1.74.0, the release notes carry the one shipped bullet on each side with the grouped small-fixes bullet last, and STATUS says what this beta is. What the user gets: the House Plan sidebar page can no longer serve a previous version of the card. The panel entry fetched it through `./houseplan-card.js` — a relative specifier, and relative resolution does not inherit the `?v=` a dashboard gets from its Lovelace resource, while the entry files carry no Cache-Control at all. A browser was free to answer from its own heuristic cache for hours, and a stale loader named a stale immutable chunk, so the panel ran an old card against the current backend with nothing but the version banner to show for it — and reloading could not help, because the address never changed (#535). Internal in the line: #536 — the version banner now asks the host to repaint when it drops the notice on disconnect, instead of leaving its removal to whatever unrelated update happened to run next. npm test 2532/2530/0 fail (the #349 manifest-tracking check goes green with this commit), release contract green on all seven sources, bundle 287 323 B gzip inside the ceiling, docs strict green. The `Release:` trailer is what asks CI for the heavy gates — smokes, golden and the full performance comparison — on this exact SHA (#479). Issue: #535 User-Visible: yes Release: v1.75.0-beta.1
135 lines
6.0 KiB
Python
Executable File
135 lines
6.0 KiB
Python
Executable File
"""Constants of the House Plan integration."""
|
|
|
|
DOMAIN = "houseplan"
|
|
STORAGE_KEY = f"{DOMAIN}.layout"
|
|
STORAGE_CONFIG_KEY = f"{DOMAIN}.config"
|
|
STORAGE_VIRTUAL_LIGHTS_KEY = f"{DOMAIN}.virtual_lights"
|
|
STORAGE_VERSION = 1
|
|
STORAGE_MINOR_VERSION = 2
|
|
FRONTEND_URL = "/houseplan_files/houseplan-card.js"
|
|
FRONTEND_ASSETS_URL = "/houseplan_files/houseplan-assets"
|
|
PANEL_FRONTEND_URL = "/houseplan_files/houseplan-panel.js"
|
|
PANEL_URL_PATH = "houseplan"
|
|
PANEL_URL = f"/{PANEL_URL_PATH}"
|
|
PANEL_COMPONENT_NAME = "houseplan-panel"
|
|
PANEL_TITLE = "House Plan"
|
|
PANEL_ICON = "mdi:floor-plan"
|
|
PLANS_URL = "/houseplan_files/plans"
|
|
PLANS_DIR = "houseplan/plans" # relative to the HA configuration directory
|
|
FILES_URL = "/houseplan_files/files"
|
|
# authenticated read path (audit B1): /api/houseplan/content/<plans|files>/<sub>/<name>
|
|
CONTENT_URL = "/api/houseplan/content"
|
|
|
|
# How many paths one houseplan/content/sign call may carry. The card batches to
|
|
# the same number; a client that sends more used to get a partial answer with no
|
|
# way to tell which paths were dropped (review R2-2).
|
|
MAX_SIGN_PATHS = 200
|
|
|
|
# Nothing is ever deleted for being old (docs/SCOPE.md), so growth has to be
|
|
# stopped at the door instead. These bound the whole store, not one request: by
|
|
# default any authenticated user may upload, and a per-request cap of 8/50 MB
|
|
# says nothing about how many requests there are (HP-1470-01).
|
|
MAX_PLANS_BYTES = 256 * 1024 * 1024
|
|
MAX_PLANS_FILES = 200
|
|
# How many the picker asks for at once — newest first.
|
|
MAX_PLANS_LISTED = 60
|
|
MAX_FILES_BYTES = 1024 * 1024 * 1024
|
|
MAX_FILES_COUNT = 1000
|
|
MAX_DECOR_ASSET_BYTES = 2 * 1024 * 1024
|
|
MAX_DECOR_ASSETS_BYTES = 256 * 1024 * 1024
|
|
MAX_DECOR_ASSETS_COUNT = 200
|
|
# Refuse to write when the disk is nearly full: filling the config partition
|
|
# breaks .storage, the recorder and backups, not just this card.
|
|
MIN_FREE_BYTES = 512 * 1024 * 1024
|
|
|
|
# An uploaded plan that no accepted configuration references is collected only
|
|
# once it is this old. Age is a race guard, not a policy: a plan uploaded
|
|
# seconds ago may belong to another client's transaction that has not written
|
|
# its configuration yet (review R3-1).
|
|
PLAN_ORPHAN_TTL_S = 3600
|
|
|
|
# Kept for compatibility with anything reading it; the collectors no longer use
|
|
# a long grace at all. Every attempt to age files out ended badly — first by
|
|
# deleting detached plans, then by racing the save that was about to reference a
|
|
# retried upload. What is left is deliberately simple: files go when the user's
|
|
# action says so, plus staging folders after PLAN_ORPHAN_TTL_S.
|
|
SCHEDULED_GRACE_S = 30 * 24 * 3600
|
|
FILES_DIR = "houseplan/files"
|
|
ASSETS_DIR = "houseplan/assets"
|
|
CONF_ADMIN_ONLY = "admin_only"
|
|
VERSION = "1.75.0-beta.1"
|
|
DECOR_ASSETS_API_VERSION = 1
|
|
SUMMARY_PANEL_API_VERSION = 1
|
|
|
|
# #43: the support transport is deliberately not configurable. A user supplied
|
|
# URL would turn the integration into an SSRF proxy and make the privacy notice
|
|
# false. The relay is deployed and operated by the project; changing it is a
|
|
# reviewed release change, not a Home Assistant option.
|
|
SUPPORT_RELAY_URL = "https://support.houseplan.tech/v1/reports"
|
|
SUPPORT_PREVIEW_TTL_S = 10 * 60
|
|
SUPPORT_API_VERSION = 1
|
|
MAX_SUPPORT_PREVIEWS_PER_USER = 3
|
|
MAX_SUPPORT_PREVIEWS_TOTAL = 3
|
|
MAX_SUPPORT_ATTACHMENT_BYTES = 8 * 1024 * 1024
|
|
MAX_SUPPORT_MESSAGE_CODEPOINTS = 10_000
|
|
MAX_SUPPORT_CONTACT_CODEPOINTS = 320
|
|
|
|
# Portable backup format. This is deliberately independent from the Home
|
|
# Assistant Store version above: storage migrations and files exported by a
|
|
# user have different compatibility lifecycles.
|
|
PLAN_MODEL_VERSION = 10
|
|
EXPORT_VERSION = 2
|
|
MAX_EXPORT_BYTES = 8 * 1024 * 1024
|
|
IMPORT_PREVIEW_TTL_S = 10 * 60
|
|
MAX_IMPORT_PREVIEWS_PER_USER = 3
|
|
# Parsed documents are larger than their wire representation. Keep the
|
|
# original three-preview memory ceiling global as well as per user so turning
|
|
# off the admin-only policy cannot multiply it by the number of household
|
|
# accounts.
|
|
MAX_IMPORT_PREVIEWS_TOTAL = 3
|
|
|
|
DEFAULT_CONFIG: dict[str, object] = {
|
|
"spaces": [],
|
|
"markers": [],
|
|
"settings": {"bg_mode": "daynight"},
|
|
}
|
|
|
|
# #42: THE stable public error-code contract. Every code a user-facing
|
|
# failure can carry — send_error literals, exception-class codes and the
|
|
# literal MarkerControlError codes — lives here; the scanner in
|
|
# tests_backend/test_backend_quality.py fails when a source emits a code
|
|
# outside this set (fail-closed), and every fixed code has a localized
|
|
# `backup.error.<code>` message on the frontend.
|
|
ERROR_CODES: frozenset[str] = frozenset({
|
|
"capacity_exceeded", "commit_failed", "conflict",
|
|
"content_confirmation_required", "duplicate_marker_control",
|
|
"future_model", "in_use", "invalid_config", "invalid_content",
|
|
"invalid_data", "invalid_format", "invalid_image", "invalid_json", "invalid_layout",
|
|
"invalid_light_entity", "invalid_marker_control", "invalid_name",
|
|
"invalid_partition_opening_host",
|
|
"invalid_partition_opening_jamb_margin", "invalid_passage_fields",
|
|
"invalid_space_id", "invalid_toggle_entity", "invalid_vacuum_map_route",
|
|
"invalid_value_badge",
|
|
"invalid_value_badge_attribute", "invalid_value_badge_position",
|
|
"invalid_value_badge_source", "invalid_value_source",
|
|
"invalid_value_source_attribute", "io_error", "marker_control_cycle",
|
|
"marker_control_missing", "marker_control_not_light",
|
|
"marker_control_self", "missing_content", "missing_plan", "no_backup",
|
|
"not_ready", "not_toggleable", "nothing_to_repair", "preview_expired",
|
|
"preview_owner_mismatch", "space_in_use", "space_not_found",
|
|
"support_invalid_message", "support_package_too_large",
|
|
"support_preview_expired", "support_rate_limited", "support_rejected",
|
|
"support_unavailable",
|
|
"too_large", "unauthorized", "unsupported_export_version", "unsupported_image",
|
|
"value_badge_source_required", "wall_model_client_outdated",
|
|
"wall_model_migration_blocked",
|
|
})
|
|
|
|
# Template-code families: f-string codes carry one of these prefixes and are
|
|
# served by the generic per-code fallback on the frontend.
|
|
ERROR_CODE_FAMILIES: tuple[str, ...] = (
|
|
"junction_limit_",
|
|
"value_badge_",
|
|
"value_source_",
|
|
)
|