Skip to content

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:

  • bedroom for the dedicated Moto X appliance;
  • justin for Justin's devices;
  • andrea for 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.