Skip to content

Add mdns#204

Closed
aaronaddleman wants to merge 24 commits into
balena-io-experimental:masterfrom
aaronaddleman:add-mdns
Closed

Add mdns#204
aaronaddleman wants to merge 24 commits into
balena-io-experimental:masterfrom
aaronaddleman:add-mdns

Conversation

@aaronaddleman

Copy link
Copy Markdown

No description provided.

aaronaddleman and others added 24 commits January 27, 2026 18:00
…odify server.js to disable password manager features
… modify server.js to disable password saving features
Advertise the browser API on the local network as an _http._tcp service
and optionally browse the LAN for a service to auto-display in the kiosk.

- src/mdns.js: pure-JS (bonjour-service) advertise/browse/discover helpers
- server.js: advertise on startup (MDNS_ADVERTISE), discover a URL in
  getUrlToDisplayAsync (MDNS_DISCOVER), and expose GET /mdns
- unpublish on SIGINT
- document new env vars and endpoint in readme
- gitignore node_modules and package-lock.json

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Debian 13's Sequoia (sqv) verifier rejects the SHA1 self-signature on the
Raspberry Pi archive key as of 2026-02-01, causing install_chromium to fail
with "repository is not signed" on RPi/Fin builds. Copy apt's default crypto
policy and extend the SHA1 second-preimage-resistance cutoff so the (still
sound) key is accepted, without disabling signature verification.

Ref: https://michael-prokop.at/blog/2026/01/31/apt-sha-1-keys-2026-02-01/

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the committed Raspberry Pi archive key with the re-certified key
from raspberrypi-archive-keyring 2025.1+rpt1. It is the same key
(fingerprint CF8A1AF502A2AA2D763BAE7E82B129927FA3303E) but its UID and
subkey-binding self-signatures now use SHA512 instead of SHA1, so Debian
13's Sequoia (sqv) verifier accepts it.

This is the proper fix for the "repository is not signed" failure, so the
SHA1 crypto-policy workaround added in the previous commit is reverted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MDNS_DISCOVER_TYPE now accepts a comma-separated list (e.g. "http,https")
so discovery can browse multiple DNS-SD types at once, and the displayed
URL scheme is derived from the matched service's type rather than only its
port (fixing https services on non-443 ports being built as http URLs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scripts/balena-env-diff.sh lists the env-var names this block supports
(derived from process.env references in src/ and the readme table) and
diffs them against those set on a balena fleet or device, reporting which
supported vars are unset, which are recognised, and which are unknown.
Names only are printed, never values. Works with both `balena env list`
and `balena envs` CLI spellings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The env diff now supports `--all <fleet>`, which diffs the fleet level plus
every device in the fleet in one run, so per-device UUID looping is no longer
needed. Refactored the diff into a reusable diff_one() function; single fleet
and single device modes are unchanged. Also falls back between the
`balena device list` / `balena devices` CLI spellings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mDNS services advertise only a host and port, so discovery previously landed
on the site root. MDNS_DISCOVER_PATH appends a path to the discovered
host:port, e.g. discovering a Home Assistant server
(MDNS_DISCOVER_TYPE=home-assistant) and opening a specific dashboard at
/lovelace-tvboard/tvboard. This lets a kiosk target a deep link by IP
instead of an unresolvable .local hostname, and survives DHCP changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HA login recording has a hard-coded origin (the IP of the network it was
recorded on), so login broke whenever the browser loaded HA at a different
IP/host (e.g. via mDNS discovery or a new DHCP lease). Instead of editing the
recording, retarget it at runtime: drop the recorded /auth/ navigations (the
browser is already on the correct auth page, and their embedded
client_id/redirect_uri reference the stale origin) and rewrite any remaining
navigation (the final dashboard) to the origin actually loaded. Login now
works on any network without re-recording.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Strip the two redundant /auth/ navigation steps (the block reaches the auth
page via discovery) and replace the recorded IP (10.0.0.78) with a
placeholder host in the remaining steps, so no stale address is baked into
the recording. Runtime retargeting now also rewrites assertedEvents URLs, not
just navigate URLs, so the runner's post-action navigation waits assert the
origin actually loaded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The app runs as the non-root 'chromium' user, but recorder scripts copied
from a build context with restrictive (0600) source permissions ended up
root-owned and unreadable, causing "EACCES: permission denied" when reading
ha_login.json and silently skipping HA login. chmod the recorder-scripts
directory readable in the image so this is robust regardless of source perms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HA login replay focused the username field but never typed into it, then
timed out. The recording's 'change' steps list an aria/label selector first,
which resolves to the shadow-DOM wrapper (clickable but not typeable) rather
than the inner <input>. Reorder change-step selectors to prefer the concrete
input selector. Also add a per-step logging runner extension so any remaining
timeout points at the exact step instead of just "Timed out after 30000ms".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The recorded label/focus clicks target elements inside HA web components'
shadow DOM whose selectors do not resolve, hanging the replay for 30s at the
username label click. Drop the redundant focus-clicks and the post-login
sidebar click, keeping only: type username, type password, click Log in,
navigate to the dashboard. The change steps focus their own inputs and the
explicit navigation lands on the board, so the removed clicks were redundant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recorded CSS selectors (ha-auth-form-string ... input) can't pierce Home
Assistant's shadow DOM, so the login replay hung on the field-fill step. Add
recorder.smartLogin(), which fills input[autocomplete=username] /
input[autocomplete=current-password] via pierce/ selectors and submits; the
auth redirect_uri returns to the requested dashboard. server.js uses it as the
primary login path, falling back to the recording replay.

Add a local test harness (scripts/test-recorder.js) and a Docker wrapper
(scripts/Dockerfile.test + test-recorder-docker.sh) that run the exact shared
login logic (src/recorder.js) against a real HA in a Node 22 + Chromium
container, dumping per-step traces, screenshots, and the live form's real
selectors — so login can be debugged locally without balena deploys.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Home Assistant's auth redirect returns to the dashboard but drops query
params, so ?kiosk (kiosk-mode sidebar/header hiding) was lost after
smartLogin. Re-navigate to the intended display URL after a successful
login so those params take effect. The test harness mirrors this.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@flowzone-app

flowzone-app Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

A repository maintainer needs to approve these workflow run(s).

To approve, maintainers can either:

Submit an approval review on this pull request, OR

Submit a review comment starting with /deploy

Then re-run the failed job(s) via the Checks tab above.

Reviews must be on the specific commit SHA of the workflow run to be considered.

1 similar comment
@flowzone-app

flowzone-app Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

A repository maintainer needs to approve these workflow run(s).

To approve, maintainers can either:

Submit an approval review on this pull request, OR

Submit a review comment starting with /deploy

Then re-run the failed job(s) via the Checks tab above.

Reviews must be on the specific commit SHA of the workflow run to be considered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant