ADR 0002: Device feeds, HTTPS trust, and durable media¶
- Status: Accepted
- Date: 2026-09-27
Context¶
The first client is a Moto X XT1058 running Android 5.1, but the same dashboard should also be testable and useful on modern Samsung phones. The household needs three independently configurable content experiences without maintaining different application builds:
bedroomfor the dedicated Moto X appliance;justinfor Justin's devices;andreafor Andrea's devices.
The Moto X predates the ISRG Root X1 trust anchor used by current Let's Encrypt chains. The system must preserve normal HTTPS hostname and chain validation without relying on an accept-all trust manager or pinning a frequently renewed leaf certificate.
The initial dashboard does not need a database, but later photo albums and DRM-free music playlists require durable media storage that survives application releases.
Decision¶
One application, multiple assigned feeds¶
Ship one Java APK with minSdk = 22 and a current target SDK. Do not create
per-person APK variants. Each installation receives a revocable, read-only device
credential and is assigned to one feed: bedroom, justin, or andrea.
Multiple devices may share a feed. The server authorizes the device first and then composes the assigned feed. Feed names are not credentials and must not grant access by themselves. Future enrollment should avoid baking a shared production secret into the APK; a short-lived enrollment code or QR flow is the preferred direction.
The manifest contract should support conditional refresh with an entity tag or equivalent version so an unchanged feed has negligible transfer cost. Presentation policy remains device-aware: the Moto can use appliance behavior such as forced landscape, always-on display, and immersive mode, while a daily-use phone can use a normal viewer mode.
HTTPS trust across Android versions¶
Use a public HTTPS hostname and a normally renewed public certificate. The
implemented Android transport supplements platform system roots with the
official ISRG Root X1 and ISRG Root YR certificates. It filters the platform
store to system roots, verifies both bundled DER fingerprints and validity,
and applies the trust manager only to connections for the configured API
origin. Hostname, certificate-date, signature, and chain validation remain
enabled; the renewable server leaf is not pinned and an accept-all trust
manager is not used. Root X1 and Root YR fingerprints were verified against
the official Let's Encrypt certificate downloads and chain
list on 2026-10-01. Their bundled
self-signed certificates have notAfter dates in 2035 and 2045, respectively;
those dates are distinct from root-program trust policy. As of that check,
Let's Encrypt listed X1 trust through 2030-06-04 and YR as not yet included in
root-program trust stores. The app's scoped additional trust design does not
depend on broader platform trust-store inclusion.
Android 5.1 lacks declarative Network Security Configuration, so this compatibility path lives in Java at the HTTP transport boundary. The optional proposal to install Root X1 in the phone's user certificate store is not needed by the app and is not part of its trust configuration. The dashboard does not trust user-installed CAs. Never install or pin the short-lived server leaf certificate.
The 2026-10-01 API-22 acceptance run passed 31 instrumented tests on the XT1058, including positive transport, API-22 system-store failure, another system-root success, and negative wrong-host, expired, self-signed, and untrusted-root cases. Certificate-renewal acceptance, modern-device transport, and a real production-feed request remain explicit follow-up checks.
Durable media without stateful application containers¶
Keep the API container replaceable and stateless. The first clock/feed version
needs no database. When albums or server-hosted music are introduced, store their
durable files outside release directories and containers under a dedicated path
such as /srv/motoxdashboard/media, with independent backup and retention.
Serve large immutable media through Nginx when practical, including HTTP range requests for audio. The API supplies authorized manifests, playlist metadata, content hashes, and bounded URLs. A read-only bind mount may expose media metadata to the API when required.
Prefer local copies of selected DRM-free music on the phone for reliable offline shower playback. Server streaming is an optional source, not the only playback path. Begin with versioned JSON metadata; add a small persistent database such as SQLite only when an actual administration workflow requires mutable metadata.
Do not place personal Moto media in AndreaWeb's business media bucket by default. The two systems should have separate credentials, backups, retention, and failure boundaries even when they share a VPS.
Consequences¶
- One signed APK can run on API 22 and modern Android devices.
- Feed membership is server-side authorization and can be changed or revoked without rebuilding the application.
- The application needs a stable release-signing key and monotonically increasing version codes so testers can install updates without uninstalling.
- HTTPS compatibility requires deliberate trust-store tests on the physical Moto X.
- Media growth consumes separately visible and backed-up storage rather than silently enlarging application images or release archives.
- A future administration site can edit feed assignments and metadata through the same application services without becoming part of the Android client.