Files
houseplan-card/docs/SUPPORT-PRIVACY.md
T
Codexandclaude[bot] 4f040c4c8e fix: exact upload quota, support palette allowlist, bounded SVG reference chains (#498)
Attachment uploads stage the body as `.upload-*` under files_root and then
asked the quota to count that file as stored usage *and* as the incoming
size, so the last file that still fit was refused at the boundary — by
bytes and by count. check_quota/dir_usage now take `exclude` for the
caller's own staged file; other staged files keep counting, so two
concurrent uploads can never both land past the limit.

The support package copied every string key of settings.fill_colors. The
schema stays open for compatibility, but the projection now keeps only the
eleven slots the card defines (SUPPORT_FILL_COLOR_KEYS, pinned to
src/logic.ts DEFAULT_FILL_COLORS by a test); an empty palette is omitted.

The SVG local-reference walk was a recursive DFS: a flat chain of a few
thousand hrefs passed every #436 bound and died with RecursionError, which
the upload view turned into a 500. The walk is iterative and measures the
longest chain through each node (memoised, order-independent); chains
deeper than MAX_SVG_REF_DEPTH = 64 are refused as too_large, cycles stay
invalid_image.

Tests: quota boundaries on the validator and the HA endpoint, a barrier
test for concurrent uploads, palette allowlist and TS parity, reference
chains (plain, hostile id order, cycle) on the validator and the endpoint;
six mutants caught by the standard runner.

Issue: #498
User-Visible: yes
2026-09-09 07:06:20 +00:00

67 lines
3.4 KiB
Markdown

# House Plan private support reports
Updated: 2026-09-02, issue #43.
House Plan keeps normal configuration, layout and uploaded content inside the
user's Home Assistant. The support relay is contacted only after the user
presses **Send** in **Help & feedback**. Opening the dialog and building or
downloading a preview do not make an external request.
## What is sent
Every report contains the user's plain-text message, optional contact, bounded
software versions and an idempotency key. The diagnostic JSON is optional and
off by default. If selected, the integration sends the exact canonical bytes
shown in the preview together with their size and SHA-256.
The package is constructed field by field. It contains plan geometry and
dimensions, safe display settings (the fill palette only by the eleven slot
names the card defines; any other key is dropped), structural counts,
validation/repair families and bounded browser/registry capability enums. Space, room, wall,
opening, marker and binding references receive random package-local names.
It excludes original names and text, Home Assistant installation/location,
device/entity/area IDs, current states and attributes, IP addresses, hostnames,
URLs, paths, filenames, plan/backdrop/manual bytes, vacuum calibration and
trails, backup history, message and contact. Unknown fields are dropped rather
than copied and redacted later.
The Zigbee topology snapshot is never offered to this package: raw provider
payloads, IEEE addresses, neighbor links, base topics, timestamps and provider
errors stay out of support preview/download/submission and out of browser
storage and logs.
## Preview and authorization
Only a Home Assistant user allowed to write House Plan can build or send a
report. Preview bytes live in integration memory for at most ten minutes and
are bound to that HA user and one dialog draft. Closing the dialog, disabling
the attachment or a successful submit removes the token; process exit also
removes it. Download uses the same preview text. The backend never rebuilds an
attachment during submit.
A valid 48-character token in a response that the card cannot adopt is also
discarded best-effort exactly once—even if the rest of the response is invalid,
the dialog changed meanwhile, or the local state update was refused. Cleanup
does not depend on whether that request is still current and never replaces the
original UI error. Malformed token strings are not sent back; backend TTL
remains the final guard if a discard transport itself fails.
## Transport and retention
The integration can contact only `https://support.houseplan.tech/v1/reports`.
The HTTPS host is compiled into the backend; redirects and user-configured
destinations are refused. Provider response bodies and submitted content are
not written to Home Assistant logs.
The relay writes an accepted report to its private spool before delivery to a
private maintainer channel. Delivered reports, including message, contact and
optional JSON, are retained for no more than **30 days**. Rate-limit and
idempotency records are retained for no more than **24 hours**. A daily purge
enforces both limits. No public GitHub issue or public Telegram post is created.
To request early deletion, contact the maintainer through the project's
[Telegram chat](https://t.me/ha_houseplan) and provide the report ID shown after
submission. The report ID is also the reference for follow-up; do not publish
the downloaded support package unless you deliberately choose to do so.