Architecture Decision Records

The design forks: where more than one option was viable, the reasoning that picked one, and what was accepted in doing so. Each record is the durable answer to “why is it built this way, and what did we turn down?”

Read this index before reopening a question. If a record already answers it, the answer stands until a new record changes it. That is the point of the section: a decision argued once should not have to be argued again from memory.

Records are point-in-time. They say what was decided and why on the day it was decided, and they are not rewritten afterward. The architecture and reference pages are kept current; the decision log is kept honest.

When a decision changes

Two different things happen to an old record, and they are not the same:

  • Extended. The record was right but incomplete: building the thing exposed a question it never asked. A new record answers that question, the old one stays Accepted, and each links to the other.
  • Superseded. Acting on the record would now be a mistake. A new record replaces it, the old one is marked Superseded and links forward.

The test is whether the earlier record is still safe to act on. If yes, extend it. If not, supersede it.

Format

FieldPurpose
StatusProposed, Accepted, Superseded or Deprecated
DateThe day the decision was made, not the day it was written up
ContextThe situation and the goals that forced a choice
Options consideredThe viable alternatives, each with what it would cost
DecisionWhat was chosen
ConsequencesWhat it commits us to, good and bad
  • Records are numbered in the order they are opened and never renumbered. The number is claimed when the question is written down, not when it is answered.
  • A record sits at Proposed while it rests on something not yet proven: a protocol not yet tried against the real player, a limit not yet measured. The evidence is added to the record when it arrives, and the status moves with it.
  • Some early records are backfilled: the decision was made and argued in a README before this section existed. They carry the date of the decision and say that they are backfilled.

EdS records and Deevnet records

EdS runs on Deevnet IoTaaS, which keeps its own ADRs, change records and incidents under the same names. To keep the two apart:

  • A bare ADR-0006, CHG-0001 or INC-0001 anywhere in this repository means an EdS record, on this site.
  • A Deevnet IoTaaS record is always written Deevnet ADR-0012, and links to deevnet-docs.

Records

ADRDateDecisionStatus
00012026-09-07The stand renders effects locally and never receives framesAccepted
00022026-09-07Gamma belongs to the firmware, not the wireAccepted
00032026-09-07The MQTT broker is Deevnet IoTaaS’s, not a tenant VMAccepted
00042026-10-10Firmware secrets are NVS-only, and the broker’s CA is provisionedAccepted
00052026-10-10A device reports key events over MQTT, not its serial logAccepted
00062026-10-10Now playing is a bus of small drivers behind one contractAccepted
00072026-10-10Drivers are portable Go, in one agent binaryAccepted
00082026-10-10nowplayd picks the current track and guarantees title, album and artAccepted
00092026-10-10lightd takes covers from a topic as a second inputAccepted
00102026-10-10Home-LAN drivers reach the broker through a dual-homed mobile PiAccepted
00112026-10-10iTunes is read by remote pairing, the way the phone remote does itAccepted
00122026-10-10Spotify is read from the account, through the Web APIAccepted
00132026-10-10MusicBee is read through the MusicBee Remote plugin’s protocolProposed
00142026-10-10TIDAL is read through Last.fm, because nothing better is offeredProposed
00152026-10-10EdS builds its own Pi images, on Deevnet IoTaaS’s base; a relay is an agent Pi with a second legAccepted
00162026-10-11A source can be reported without its cover, and Spotify is: known, and not litAccepted
00172026-10-11An agent Pi is a registered device, and reports its events like oneAccepted
00182026-10-11EdS has a console of its own, fed from the bus, and it only looksAccepted
00192026-10-11An album can have a look of its own, named on the music side and drawn on the light sideProposed
00202026-10-11A touch screen shows the cover and can change what plays, by asking nowplaydProposed
00212026-10-11The turntable is identified by listening, with a recognizer that can be replacedProposed
00222026-10-12For a source that plays the owner’s records, the owner’s collection names the recordProposed
00232026-10-12A source’s equipment can say it is on, and a source that is on holds the standProposed
00242026-10-12A track left paused is not playing for ever, and a room with nothing playing is dimProposed
00252026-10-12The current track says when there is nothing a controller could doProposed
00262026-10-12A gap between tracks is listened for, and a silent turntable is idle in twenty secondsProposed
00272026-10-12What EdS asks of other people’s services is counted, a minute at a time, and nowplayd writes its counts to the log store itselfProposed
00282026-10-13The stand is lit for records only, and is dim only while the turntable is onProposed
00292026-10-13The stand starts dark, and says in red blinks how far it gotProposed
00302026-10-13One piece of music can have a look of its own, shown whatever plays it, and the stand learns to scanProposed
00312026-10-13Spotify is reported with its cover, and treated as iTunes isProposed
00322026-10-13The Spotify driver carries out commands, with a wider authorization, for what is playing hereProposed
00332026-10-13The whole back end can run on one Pi, as an image built on Deevnet’s take-home oneProposed
00342026-10-16Presence is heard, not remembered: everything says it is there every thirty secondsProposed
00352026-10-16Firmware is updated through the broker, and a build that cannot reach it is undoneAccepted
00362026-10-17The cover screen sleeps when nothing has played for five minutes, and wakes for musicAccepted
00372026-10-18The secrets nothing else can issue are kept encrypted in the repository, with sops and ageProposed
00382026-10-19The turntable’s album is the one the track is on, and the original one, not a time since the lastProposed
00392026-10-19The console can light the stand for every source, a retained setting that stays until switched backProposed
00402026-10-23A request can name an album to play, and iTunes plays it from its own libraryProposed
00412026-10-24An artist’s first album is their first studio album, counted in MusicBrainzProposed
00422026-10-24A spoken request is sent whole to the workload, written down there, and made a commandProposed
00432026-10-24The reSpeaker runs firmware of EdS’s own, and sends a request when its button is held, then when it hears its nameProposed
00442026-10-24The music is turned down while a request is heard, and comes back by itselfProposed
00452026-10-24An artist’s Nth album, when the library does not have it, is the next of theirs it doesProposed
00462026-10-24Requests are matched against the owner’s library, as its XML lists itProposed
00472026-10-24voiced asks eds-inventory for the owner’s albums, in place of its own indexAccepted
00482026-10-25The turntable is heard on both channels, and one gone silent is said on the consoleProposed
00492026-10-26A device holds two sites’ settings, and is told which to use by a messageProposed
00502026-10-27How each track’s album and cover were found is written down, one line a track, and sent to the log storeProposed
00512026-10-28Spotify is switched on and off from the console, a retained setting the agent obeys; off asks Spotify nothingAccepted
00522026-10-28Each Pi’s iTunes pairing is kept, encrypted with sops, and a card written again starts pairedAccepted
00532026-10-28A home Pi opens a Wi-Fi leg onto the home LAN for the van, for a while, when asked from inside; SSH onlyProposed