Open punt 5 van Webinterface, goedgekeurd en gebouwd. De agent verbindt met de eigen TLS-poort, maakt de handdruk af en vergelijkt het getoonde certificaat byte voor byte met het gekozen bestand. Die vergelijking blijkt waardevoller dan de handdruk. Ze vangt een certificaatwissel die nginx nooit heeft toegepast, en dat is precies het geval waar een controle op vertrouwen blind voor is. Er wordt daarom bewust niet tegen de certificaatwinkel van het besturingssysteem geverifieerd: een zelfondertekend certificaat uploaden is een ondersteunde bron en die opstelling zou dan als kapot gemeld worden. Twee dingen liepen anders dan het plan zei en staan nu rechtgezet in PLAN 4a2, OPEN punt 5 en de changelog. De belofte "luisteren, certificaat en doorverbinding in een keer" klopt voor twee van de drie: na de handdruk wordt er niets verstuurd. Een echt verzoek zou de sessie bytes geven, en sessies met bytes worden nooit uit het activiteitenlog gefilterd, want die kunnen een storing zijn. En dat filteren was de tweede verrassing. Elke meting is voor nginx een gewone sessie en levert dus een logregel op; zonder rem ging het log over onszelf in plaats van over wallets. Er zit nu een rem van vijf minuten op, er wordt niet gemeten vlak na een herlading omdat het vorige certificaat er dan nog staat, en de eigen regels worden weggelaten op grond van het moment. Tests: 22 nieuw, met de nadruk op de niet-gelukkige paden en op de rem, want dat is wat het log bruikbaar houdt. Alle vier de beslissende regels mutatie-getest. De changelog kreeg ook de ontbrekende 0.0.15 erbij. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
390 lines
26 KiB
Markdown
390 lines
26 KiB
Markdown
# Webinterface - plan
|
|
|
|
> Gepromoveerd op 19-08-2026 vanuit `Plannen/Masterplannen/`, omdat het werk begonnen is: de pagina is
|
|
> herbouwd. Taken staan in [TAKEN.md](TAKEN.md), open punten in [OPEN.md](OPEN.md), de geschiedenis in
|
|
> [PROGRESS.md](PROGRESS.md).
|
|
>
|
|
> **De afhankelijkheid van Configuratie is vervallen.** Die stond er omdat de pagina de ingestelde
|
|
> waarden moet tonen. In het ontwerp dat er nu ligt haalt de pagina álles uit `status.json` en uit de
|
|
> umbrel-variabelen, en staat er geen enkele installatiespecifieke waarde meer in het bestand. Daarmee
|
|
> hoefde Configuratie er niet vóór, en is dit deel van Configuratie fase 2 meteen af.
|
|
|
|
## 1. Doel
|
|
|
|
De statuspagina toont verzonnen gegevens. De statuswaarden staan als de tekst `Online` in de HTML, het
|
|
domein staat er hardgecodeerd in en er wordt niets uitgelezen. De pagina meldt dus ook "Online" als
|
|
stunnel omgevallen is, en dat is erger dan geen pagina: hij wordt geraadpleegd juist wanneer er iets mis
|
|
lijkt, en geeft dan het verkeerde antwoord.
|
|
|
|
Als dit af is, toont de pagina alleen dingen die waar zijn, of hij zegt dat hij het niet weet.
|
|
|
|
## 2. Afbakening
|
|
|
|
Vastgesteld op 18-08-2026, na het zien van de pagina in bedrijf.
|
|
|
|
- De verzonnen status en het verzonnen logvenster eruit.
|
|
- **Blokhoogte en backend-status.** De hoogte via het Electrum-protocol, plus welke implementatie actief
|
|
is en of hij antwoordt. Dit is meteen de echte gezondheidscontrole.
|
|
- **Certificaat:** geldig tot, resterende dagen, een zichtbare waarschuwing onder de dertig dagen, en het
|
|
tijdstip van de laatste herlading.
|
|
- **Reactietijd van de backend**, en de geschiedenis daarvan als sparkline.
|
|
- Aansluiten op het design-systeem in `HomeGit/Docs/website-design-system.html`: donker-eerst met een
|
|
lichte variant, tokens voor kleur en radius, en de bestaande componenten `card`, `card-stat`, `badge`,
|
|
`alert` en `list-item`.
|
|
- **Verbindingsregels per client**, met kopieerknop. Toegevoegd 19-08-2026 op verzoek van de gebruiker.
|
|
De ene wallet wil `domein:poort:s` op één regel, de andere wil host en poort in aparte velden met SSL
|
|
aangevinkt, en juist die kleine verschillen kosten mensen tijd. De rijen komen uit
|
|
[Referenties/Clients.md](../../Referenties/Clients.md) §4; wie er een bijzet, zet hem daar ook bij.
|
|
- **Een activiteitenlog**, zie §4e. Herziening van een eerder niet-doel.
|
|
|
|
## 3. Niet-doelen
|
|
|
|
- **Een backend of API.** Zodra de pagina iets moet opvragen, is er een proces nodig dat luistert, en dan
|
|
is dit geen configuratie-app meer. De weg eromheen staat in §4.
|
|
- **Live logs, in de zin van een logvenster.** Ruwe logregels in de browser vragen precies de backend uit
|
|
het vorige punt, en bij een TLS-proxy staan er verbindingsgegevens in. `docker logs` blijft de plek
|
|
voor de echte logs. Wat er **wel** komt is een uitgedunde samenvatting per sessie; zie §4e. Dat is
|
|
op 19-08-2026 herzien op verzoek van de gebruiker, en het is een andere zaak dan een logvenster.
|
|
- **Instellingen bewerken in de pagina.** Uitdrukkelijk zo besloten in het plan **Configuratie**.
|
|
- **Koersgegevens en koersgrafieken.** Besloten op 18-08-2026, na afweging. Het vraagt een externe API,
|
|
en dan haalt de browser van iedereen die dit dashboard opent data op bij een derde partij. Bij een
|
|
zelfgehoste Bitcoin-opstelling is dat precies het soort lek dat deze app juist dichtzet, en umbrelOS
|
|
heeft er bovendien al widgets voor. **Alles op het dashboard komt uit lokale bronnen.**
|
|
- **Verbindingen per uur als grafiek.** Kan wel, maar bij één of twee wallets is die grafiek vrijwel
|
|
leeg. Het activiteitenlog uit §4e dekt dezelfde vraag beter.
|
|
- **De blokhoogte zelf als grafiek.** Die loopt met ongeveer één per tien minuten omhoog, dus het is
|
|
altijd dezelfde schuine lijn.
|
|
- **Blokken per uur, in welke vorm dan ook.** Geschrapt op 19-08-2026 door de gebruiker, nadat het als
|
|
grafiek én als tegel op de pagina had gestaan. Het antwoordt op een vraag die de gebruiker niet heeft:
|
|
of de node meekomt met het netwerk is de zorg van de Electrum-server en niet van deze proxy, en de
|
|
blokhoogte zelf zegt dat al. Gevolg voor het ontwerp: `history` in `status.json` hoeft alleen nog de
|
|
reactietijd te bewaren, want de sparkline is de enige afnemer.
|
|
- **De afweging Tor tegenover TLS op het dashboard.** Ook 19-08-2026, door de gebruiker. Die uitleg is
|
|
positionering en hoort in de winkelbeschrijving in `umbrel-app.yml`, waar iemand staat te kiezen. Wie
|
|
het dashboard opent, heeft al gekozen en komt iets nakijken. De onderbouwing blijft in
|
|
[Referenties/Clients.md](../../../Referenties/Clients.md) §1 staan; die voedt nu alleen de marketing.
|
|
|
|
## 4. Ontwerp
|
|
|
|
### 4a0. Wél een backend, en waarom die er alsnog is
|
|
|
|
Herzien op 19-08-2026, nadat de gebruiker vroeg of de WebDAV-truc uit §4f van
|
|
**Configuratie** eigenlijk de gebruikelijke manier is om een backend in een Umbrel-app te bouwen. Het
|
|
antwoord was nee, en het onderzoek eromheen veranderde deze paragraaf.
|
|
|
|
**Wat umbrelOS zelf aanbiedt is één instelling per app: de afhankelijkheidskeuze.** In
|
|
`AppSettingsSchema` staat `dependencies: z.record(z.string())` en verder niets. Daarom kostte het wisselen
|
|
tussen Electrs, Fulcrum en ElectrumX twee regels: dát mechanisme bestaat. Er is géén generiek
|
|
instellingenformulier dat een community-app kan declareren, en de andere umbrel-haken (`hooks/`,
|
|
`exports.sh`, `*.template`) zijn er voor het opstarten en voor andere apps, niet voor de gebruiker.
|
|
|
|
**Apps die wél instelbare configuratie hebben, zijn zelf een backend.** Nginx Proxy Manager, Home
|
|
Assistant en Jellyfin brengen hun eigen server en hun eigen instellingenscherm mee, in hun eigen image.
|
|
umbrelOS levert dat scherm niet; de app doet het. De juiste conclusie is dus niet "umbrelOS heeft er iets
|
|
voor" maar "die apps hebben een backend".
|
|
|
|
**Besluit van de gebruiker: een tweede container met een klein programma.** Een officiële
|
|
`python:3-alpine`, met het script uit `agent.py.template` zodat het bij een update meekomt. Geen eigen
|
|
image, dus geen bouwstap, geen registry en geen multi-arch-gedoe. Dat laatste is de reden dat een eigen
|
|
image afvalt, niet de complexiteit van het programma.
|
|
|
|
Wat die keuze onderweg oploste, en dat was de eigenlijke aanleiding:
|
|
|
|
- **de shell-lus was aan zijn plafond.** Een certificaatdatum lezen, een JSON-RPC-verzoek doen, een
|
|
geschiedenis bijhouden en een keuze valideren zijn geen dingen die je met `openssl` en `nc` aan elkaar
|
|
knoopt zonder dat het stil verkeerde antwoorden gaat geven;
|
|
- **de controles op `openssl`, `nc` en de WebDAV-module vervallen alle drie.** De agent doet dat werk zelf
|
|
met de standaardbibliotheek, dus de app hangt niet meer af van wat er toevallig in de nginx-image zit;
|
|
- **het hardgecodeerde domein is weg uit `docker-compose.yml` en `nginx.conf.template`.** De agent
|
|
schrijft `cert.conf` met de paden die hij gevonden heeft, en nginx doet daar een `include` op. Daarmee
|
|
is dat deel van **Configuratie** fase 2 af.
|
|
|
|
**Wat het kost.** Een tweede container, en een echt API-oppervlak in plaats van geen. Klein, maar niet
|
|
nul, en daarom staat de verantwoording bij de `location /api/` in `nginx.conf.template` en niet alleen
|
|
hier.
|
|
|
|
**nginx herladen kan de agent niet zelf**, want dat vraagt de Docker-socket en die is er bewust uit. De
|
|
agent zet een vlagbestand neer en de nginx-container herlaadt zichzelf zodra hij dat ziet. Die lus
|
|
verplaatst wat eerst de certificaatbewaking was, en doet nu alleen nog dit ene ding.
|
|
|
|
### 4a. Statusgegevens uit status.json
|
|
|
|
De pagina vraagt nooit iets aan een dienst die kan omvallen: de agent schrijft elke ronde een
|
|
`status.json`, en de pagina haalt dat op met `fetch` en vult zichzelf. Dat blijft de kern, ook nu er een
|
|
agent is; het alternatief, een pagina die live naar de backend vraagt, zou de pagina zelf laten hangen
|
|
als de backend hangt.
|
|
|
|
Wat er in staat: het domein en de poort waar de wallet heen moet, het adres en de naam van de backend, de
|
|
blokhoogte en de reactietijd, de einddatum van het actieve certificaat, de lijst met gevonden
|
|
certificaten, een geschiedenis van reactietijden over 24 uur, en de logregels. Plus het tijdstip van
|
|
schrijven, en dat is het belangrijkste veld van allemaal.
|
|
|
|
Wat de vorm oplevert:
|
|
|
|
- **de pagina kan niet meer liegen over "draait het".** Elk veld heeft een zichtbare onbekend-toestand en
|
|
nooit een lege waarde, want een leeg veld leest als "in orde". Dit is de pagina die juist geraadpleegd
|
|
wordt wanneer er iets mis lijkt;
|
|
- **oude gegevens zijn herkenbaar, en wel bij de waarde zelf.** Onder de blokhoogte staat "as of ... ago",
|
|
de badge bij de backend gaat van groen naar grijs met "last answered", en de voettekst noemt het
|
|
tijdstip. Dat is de enige manier waarop de pagina een gestopte agent kan opmerken.
|
|
|
|
**Bewust geen melding bovenaan daarvoor.** Die heeft er even gestaan en is er op 19-08-2026 op verzoek
|
|
van de gebruiker uit. De afweging is het opschrijven waard, want hij geldt voor elke volgende melding
|
|
die iemand wil toevoegen: een banner die hetzelfde zegt als wat er drie regels lager bij het getal
|
|
staat, voegt geen informatie toe maar wel gewicht, en dat gewicht gaat ten koste van de meldingen die
|
|
wél iets nieuws zeggen. Een melding bovenaan is er voor iets wat je nergens anders ziet, zoals een
|
|
ontbrekend certificaat;
|
|
- **de lus valt nooit stil.** Een mislukte ronde wordt gelogd en overgeslagen; stoppen zou de pagina op
|
|
oude gegevens bevriezen zonder dat iemand het ziet.
|
|
|
|
### 4a1. De indeling van de pagina
|
|
|
|
Vastgesteld door de gebruiker op 19-08-2026, na het bekijken van de eerste versie.
|
|
|
|
**De volgorde, van boven naar beneden:** Electrum-server, de drie statustegels, de certificaatkeuze, het
|
|
activiteitenlog, en onderaan het instellen van je wallet. De regel erachter: **eerst waar je naar kijkt
|
|
als je iets nakomt, onderaan waar je naar kijkt als je iets instelt.** Dat laatste doe je één keer.
|
|
|
|
De laatste twee zijn op verzoek van de gebruiker omgedraaid ten opzichte van de eerste opzet. Dat pakte
|
|
beter uit dan alleen als voorkeur: het certificaatkader is nu het smalle kader links en het log het brede
|
|
rechts, waardoor de kolomgrens samenvalt met die van de rij erboven in plaats van ertegenin te lopen. En
|
|
logregels zijn monospace, dus die hebben de breedte beter nodig dan een lijst met keuzerondjes.
|
|
|
|
**Twee kaders zijn er één geworden.** "Point your wallet here" en "Setting up your wallet" stelden dezelfde
|
|
vraag, dus het verbindingsadres met de kopieerknop staat nu bovenaan het instelkader in plaats van in een
|
|
eigen kader erboven.
|
|
|
|
**Breed, met kaders naast elkaar.** Twaalf kolommen, en de rijen wisselen 5/7 en 7/5 af: de
|
|
Electrum-server naast de statustegels, het log naast de certificaatkeuze, en het instelkader vol breed.
|
|
Afgekapt op 1760px, want op een ultrawide monitor levert een kader van 2500px regels op die niemand leest.
|
|
|
|
**Elk kader is hetzelfde opgebouwd.** Een `card-head` met een titel in `t-h3`, dan de inhoud. Bijgesteld op
|
|
19-08-2026 door de gebruiker: de drie statustegels hadden een eigen kleine grijze kop in kapitalen, en dat
|
|
maakte ze een apart soort ding zonder dat daar een reden voor was. De titel gebruikt de token
|
|
`--text-primary` en niet letterlijk wit, want in de lichte variant is wit onzichtbaar.
|
|
|
|
Wat daarbij vastligt en niet per ongeluk mag verschuiven:
|
|
|
|
- **de leesvolgorde in de HTML ís de bedoelde volgorde.** Er staat nergens een `order` of een `row-start`
|
|
die de opmaak laat afwijken van de bron, dus bij een smal scherm stapelt alles precies zoals het gelezen
|
|
hoort te worden. Wie hier een kader bijzet, zet het op de goede plek in de HTML en niet op de goede plek
|
|
in het raster;
|
|
- **de statustegels rekken mee met hun buur**, met de titel boven en het getal onder, want van zichzelf
|
|
zijn ze lager dan het kader ernaast en dan staat er een gat rechtsboven. De onderregel van een tegel
|
|
heeft daarvoor dezelfde hoogte als de sparkline, anders staat het getal van "Backend response" hoger dan
|
|
de andere twee;
|
|
- **het logblok scrollt zelf horizontaal in plaats van af te kappen.** Met puntjes zou een smal scherm de
|
|
bytes stil verbergen, en dat is dezelfde soort onwaarheid als een verzonnen statuswaarde;
|
|
- **twee kaders naast elkaar zijn even hoog**, en het langste bepaalt de rij. Wat mag meegroeien zegt dat
|
|
zelf: het logblok en de certificaatlijst. Daardoor is de certificaatlijst een scrollend vak in plaats van
|
|
een lijst die de pagina oprekt, en dat was nodig: een gedeelde certificatenmap kan er tientallen bevatten.
|
|
Het aantal staat in de kop, want zodra er een scrollbalk is, is niet meer te zien hoeveel er onder de rand
|
|
staan.
|
|
|
|
**Bewust een lijst en geen dropdown.** De gebruiker vroeg op 19-08-2026 of een dropdown niet netter was,
|
|
en dat is het visueel ook, maar het botst met wat dit besturingselement moet doen: je kiest hier op de
|
|
hostnaam waarop je wallet verbindt, en dan wil je bron, naam en resterende dagen naast elkaar kunnen
|
|
vergelijken. In een dropdown zie je er één per keer, en een verlopen certificaat kan er niet rood in
|
|
omdat `option`-opmaak per browser verschilt. De hoogtewinst die de dropdown zou opleveren komt er met een
|
|
scrollend vak ook, dus er hoefde niets ingeleverd te worden;
|
|
|
|
- **er is geen voetregel.** Er heeft er een gestaan met "Last reading ... ago" en het versienummer; die is
|
|
er op verzoek van de gebruiker uit. De leeftijd stond al bij de waarden zelf, dus dat was een derde keer
|
|
hetzelfde.
|
|
|
|
Het **versienummer** is wel gebleven, klein achter de tagline als `v0.0.3`. Dat is een aparte afweging en
|
|
hij viel andersom uit dan de rest van de voetregel: dit project verloor een keer een dag aan een wijziging
|
|
die niet uitrolde door een niet-verhoogde `version`, en dan is "welke versie zie ik nu eigenlijk" precies
|
|
de vraag die je stelt. Het staat in `--text-sec` en niet in `--text-ter`, want die laatste is in de lichte
|
|
variant `#bbbbbb` op wit en op deze grootte niet te lezen.
|
|
|
|
### 4a2. De tweede indeling
|
|
|
|
Opgegeven door de gebruiker op 27-08-2026, nadat hij alles uit de eerste indeling had gezien en getest.
|
|
Dit vervangt §4a1 als beschrijving van hoe de pagina eruit hoort te zien; §4a1 blijft staan als
|
|
verantwoording van wat er gebouwd is en waarom, want een deel van die redenen geldt nog steeds en een deel
|
|
wordt hier bewust teruggedraaid.
|
|
|
|
**De vorm.**
|
|
|
|
- **Rij 1: vijf kleine widgets.** Electrum-server, blokhoogte, reactietijd, certificaat, en de zelfcontrole
|
|
uit open punt 5. Allemaal even groot en van hetzelfde soort: een titel, één getal of één regel, en
|
|
hooguit één onderregel.
|
|
- **De certificaatwidget** toont het gekozen certificaat: naam, en het aantal dagen tot vernieuwing. Niet
|
|
de keuze zelf.
|
|
- **Kiezen, uploaden en afhandelen verhuizen naar een dialoog**, te openen uit een hamburger- of
|
|
puntjesmenu rechtsboven.
|
|
- **De licht/donker-schakelaar gaat mee dat menu in** (toegevoegd 27-08-2026 door de gebruiker). Die staat
|
|
nu als losse knop rechtsboven. Daarmee wordt het menu wat het hoort te zijn: de plek voor wat je zelden
|
|
aanraakt, en de kop houdt niets meer dan het merk en de tagline.
|
|
- **Het activiteitenlog gaat over de volle breedte.**
|
|
- **"Setting up your wallet" is dichtgeklapt** en veel compacter. Er zijn feitelijk twee vormen van
|
|
hetzelfde adres, dus twee kopieerknoppen; de rest is een opsomming van de wallets die ermee werken.
|
|
- **De Electrum-serverwidget wordt kleiner** en verliest onderteksten.
|
|
|
|
**Wat dit oplevert, los van smaak.** De eerste indeling had twee koppelingen die er alleen waren omdat twee
|
|
kaders naast elkaar stonden: de statustegels moesten meerekken met de hoogte van hun buur, en het logblok
|
|
en de certificaatlijst moesten samen groeien en krimpen. Dat laatste was de hele inhoud van 0.0.13. Met een
|
|
volle-breedte log en vijf gelijke widgets vervalt allebei. Dit is dus geen laag opmaak erbovenop maar
|
|
minder mechaniek dan er nu staat.
|
|
|
|
#### Wat hier bewust teruggedraaid wordt
|
|
|
|
Twee dingen gaan tegen een eerder besluit in. Ze staan hier opgeschreven zodat een latere sessie ze niet
|
|
"herstelt" met een verwijzing naar de oude reden.
|
|
|
|
1. **De kopieerknop per clientregel wordt weer één knop per vorm.** Op 19-08-2026 is het losse
|
|
verbindingsadres met kopieerknop juist wéggehaald, met als reden dat hetzelfde adres al bij elke client
|
|
stond in de vorm die díe client wil. Dat blijft waar, maar het weegt nu anders: het kader moet compact
|
|
en dichtgeklapt, en dan is een knop per wallet een lange lijst met vrijwel identieke regels.
|
|
|
|
**Wat daarbij niet verloren mag gaan:** welke wallet welke vorm wil. Die kennis staat in
|
|
`Referenties/Clients.md` §4 en is de reden dat er twee vormen zijn. De opsomming hoort daarom
|
|
**gegroepeerd onder de twee vormen** te staan, elk met zijn eigen kopieerknop, en niet als één platte
|
|
lijst wallets naast twee losse knoppen. Anders staat er wel een adres om te kopiëren maar niet meer bij
|
|
welke wallet welk adres hoort, en dat is precies wat dit kader moet vertellen.
|
|
2. **De certificaatlijst verhuist naar een dialoog.** Op 19-08-2026 is een dropdown afgewezen omdat je bron,
|
|
naam en resterende dagen naast elkaar moet kunnen vergelijken en een verlopen certificaat rood moet
|
|
kunnen zijn. **Die reden verbiedt een dialoog niet, hij verbiedt een dropdown**, en een dialoog geeft
|
|
meer ruimte dan het kader had. De lijst blijft dus een lijst, nu in de dialoog. Vervang hem daar niet
|
|
alsnog door een dropdown omdat het in een dialoog netjes zou staan.
|
|
|
|
#### De eis die deze indeling zelf oproept
|
|
|
|
Kiezen verstoppen achter een menu botst met de ergste toestand die deze app kent: **een verse installatie
|
|
heeft nog geen certificaat, en de pagina is de enige plek waar je er een kiest.** Dat is niet theoretisch;
|
|
het is de klem van 0.0.3, waar de app niet startte omdat er geen certificaat was en je dus niet bij de
|
|
pagina kwam waarop je er een koos.
|
|
|
|
Daaruit volgt een harde eis voor deze indeling: **de bestaande foutmelding bovenaan bij "geen certificaat
|
|
actief" blijft staan, en krijgt de knop die de dialoog opent.** De hamburger is de weg terug voor wie het
|
|
later nog eens wil wijzigen, nooit de enige weg erheen. Dezelfde redenering geldt voor een verlopen of
|
|
bijna verlopen certificaat: dat staat al als waarschuwing bovenaan en die verhuist niet mee de dialoog in.
|
|
|
|
#### Details die vastliggen
|
|
|
|
- **Vijf widgets passen niet in twaalf kolommen.** Rij 1 krijgt daarom een eigen raster van vijf gelijke
|
|
kolommen in plaats van een deling van het twaalfkolomsraster. Wat er bij het versmallen moet gebeuren,
|
|
hoort erbij bepaald te worden: op mobiel stapelen ze, en daartussen zit een breedte waarop vijf te smal
|
|
zijn. Dit is de eerste indeling met een rij die niet netjes in tweeën valt, dus dit is nieuw werk en geen
|
|
variant op het bestaande.
|
|
- **De leesvolgorde in de HTML blijft de bedoelde volgorde**, zonder `order` in de CSS. Die regel uit §4a1
|
|
geldt onverkort, ook voor de vijf widgets en voor het dichtgeklapte kader.
|
|
- **Dichtklappen met `details`/`summary`**, niet met eigen JavaScript: dat is toetsenbordbereikbaar en
|
|
werkt zonder script. Let op de valkuil die 0.0.13 opleverde: een blok dat opengaat mag geen gat
|
|
achterlaten in de rij eronder.
|
|
- **De schakelaar wisselt van vorm als hij het menu in gaat.** Nu is het een knop met het label van waar je
|
|
naartoe gaat ("Light"). In een menu leest dat verkeerd, want een menuregel toont een toestand en geen
|
|
handeling. Kies daar dus de vorm die de huidige stand toont, met een vinkje of twee regels. Dit is klein
|
|
maar het is precies het soort ding dat anders ongemerkt omdraait: wie het label laat staan, zet in het
|
|
menu "Light" terwijl de pagina licht is.
|
|
- **Het menu heeft daarmee twee regels**, certificaten en weergave, en dat is genoeg voor een menu. Het
|
|
versienummer verhuist er níet in: dat staat klein achter de tagline en dat is een eigen afweging uit
|
|
§4a1, die hier niet verandert.
|
|
- **De dialoog met het `dialog`-element**, om dezelfde reden: focus en Escape zitten erin. Wat er in moet
|
|
gebeuren is precies wat het certificaatkader nu doet, inclusief het uploaden en de melding dat de pagina
|
|
níet zelf zegt dat het gelukt is (§4b en fase 4b van `TAKEN.md`).
|
|
- **De zelfcontrole-widget is nieuw werk in de agent**, geen opmaak. Zie open punt 5. **Gebouwd in 0.0.16;
|
|
de widget zelf hoort bij deze fase.** Wat er te tonen is, staat in `status.json` onder `tls.self_check`,
|
|
met vier toestanden: `off` (geen certificaat gekozen, dus geen poort, en dat is geen storing), `ok`,
|
|
`wrong-certificate` en `failed` met een reden.
|
|
|
|
**Bij het bouwen bleek de belofte hierboven te ruim**, en de widget moet niet meer beweren dan er
|
|
gemeten wordt. Hier stond dat de controle luisteren, certificaat en doorverbinding in één keer bewijst.
|
|
De eerste twee kloppen; de doorverbinding niet. Er wordt na de handdruk niets verstuurd, want een
|
|
verzoek zou de sessie bytes geven en sessies met bytes worden nooit uit het activiteitenlog gefilterd.
|
|
De backend wordt apart bevraagd, dus wat tussen wal en schip valt is alleen de `proxy_pass` zelf.
|
|
|
|
Evenmin gemeten: de weg van buiten naar binnen. De verbinding loopt van container naar container, dus
|
|
een router die de poort niet meer doorstuurt leest hier als in orde. Een widget met de tekst "reachable"
|
|
zou dus liegen; hij gaat over de voordeur en niet over de weg ernaartoe.
|
|
|
|
### 4b. Waarschuwen op een aflopend certificaat
|
|
|
|
Met de einddatum in `status.json` is dit een vergelijking in de pagina zelf: onder de dertig dagen een
|
|
opvallende melding, verlopen een duidelijke fout. Dat is de enige echte toevoeging ten opzichte van nu,
|
|
en hij is goedkoop omdat de datum er toch al is.
|
|
|
|
### 4c. Welke backend er gekozen is
|
|
|
|
Die volgt uit `${APP_ELECTRS_NODE_IP}` en `${APP_ELECTRS_NODE_PORT}`, maar dat is een IP-adres en geen
|
|
naam. De adressen liggen per app vast (Electrs op `10.21.21.10`, Fulcrum op `10.21.21.200`, ElectrumX op
|
|
`10.21.21.199`), dus een vertaaltabel kan er een naam van maken. Dat is aardig, maar het is een tabel die
|
|
stilzwijgend veroudert als Umbrel de adressen wijzigt. Voorstel: het adres tonen, en de naam alleen als
|
|
extra wanneer hij in de tabel staat. Dan is de pagina bij veroudering minder informatief in plaats van
|
|
onwaar.
|
|
|
|
### 4e. Het activiteitenlog
|
|
|
|
Toegevoegd 19-08-2026, nadat de gebruiker vroeg of er iets over live client-aanroepen te tonen is, en
|
|
diezelfde dag bijgesteld naar logregels onder elkaar in plaats van een lijst met sessiekaarten.
|
|
|
|
**Eerst de grens, want die bepaalt de rest. Een regel per protocolaanroep kan niet.** De wallet doet zijn
|
|
verzoeken *binnen* één TLS-verbinding die hier getermineerd wordt en daarna als bytestroom naar de backend
|
|
gaat. nginx `stream` kent geen verzoeken, alleen verbindingen. Ze wél tellen zou betekenen dat de app de
|
|
Electrum-berichten van de gebruiker uitleest, en dat is precies het verkeer waarvoor deze app bestaat. Dat
|
|
is geen implementatiedrempel maar een ontwerpgrens, en hij hoort ook op de pagina te staan zodat niemand
|
|
denkt dat het log iets verzwijgt.
|
|
|
|
Wat er wél per regel in kan:
|
|
|
|
| Gebeurtenis | Waar het vandaan komt |
|
|
|-|-|
|
|
| `connect` | de verbindingsteller is opgelopen sinds de vorige ronde |
|
|
| ~~`traffic`~~ | vervallen op 20-08-2026, zie punt 2 onderaan deze paragraaf |
|
|
| `disconnect` | de `access_log`-regel van nginx, met duur en bytes |
|
|
| `probe` | een sessie die eindigde zonder één byte in beide richtingen. Toegevoegd 20-08-2026: een doorgestuurde poort wordt gescand, en zonder dit onderscheid gaf elke scan een rode `refused`-regel terwijl er niets geweigerd is. Bewust op de bytes en niet op de duur of de status: een scan die tien seconden open blijft is nog steeds een scan, en een echte sessie die na een halve seconde omvalt is nog steeds een storing |
|
|
| `refused` | de verbinding gaf wél verkeer door en liep daarna stuk. Dit is het geval dat rood mag zijn |
|
|
| `reload` | het certificaat is gewijzigd en nginx is herladen |
|
|
| `start` | de container is gestart en luistert |
|
|
|
|
Die regels komen als `log` in `status.json`, afgekapt op 24 uur. De pagina toont ze nieuwste bovenaan, in
|
|
een monospace-blok dat scrollt.
|
|
|
|
**Bewust niet gelogd: het IP-adres van de client en de bronpoort.** Dat is precies het soort gegeven dat
|
|
deze app van het netwerk af houdt, en om te zien dát het werkt is het niet nodig.
|
|
|
|
Twee dingen die eerst uitgezocht moeten worden, en die het bouwen kunnen blokkeren:
|
|
|
|
1. **Een `log_format` bevat nginx-variabelen met een dollarteken, en dit bestand is een template.** De
|
|
invulling bij het starten vervangt die en zou ze leegmaken; dat is dezelfde valkuil die nu bovenaan
|
|
`nginx.conf.template` beschreven staat. De uitweg is de `log_format` niet in het template te zetten
|
|
maar door het `command`-blok in `docker-compose.yml` te laten wegschrijven als een `include`-bestand,
|
|
want daar wordt een dollarteken al als `$$` ontsnapt. Te verifiëren.
|
|
2. **nginx `stream` schrijft zijn regel pas bij het sluiten van de sessie.** Een verbinding die twaalf uur
|
|
openstaat, verschijnt dus pas na afloop, en dat is de normale toestand van een wallet. Daarom komen
|
|
`connect` en `traffic` niet uit de log maar uit de lopende verbinding; anders lijkt een actieve wallet
|
|
afwezig. **Uitgezocht en gebouwd op 20-08-2026, nadat de gebruiker meldde dat hij van zijn verbonden
|
|
wallet niets terugzag:**
|
|
|
|
- **`connect` komt uit `/proc/net/tcp`.** Kolom 2 is het lokale adres met de poort in hex, kolom 4 de
|
|
toestand; tellen wat op `:C366` staat met toestand `01` geeft het aantal open wallet-verbindingen.
|
|
Dat bestand geldt **per netwerk-namespace**, en daar zit de bevinding: de agent kan het niet lezen,
|
|
want hij zit in een andere container. De teller staat daarom in de achtergrondlus van de
|
|
nginx-container, die het aantal naar een bestand schrijft dat de agent oppikt. Zelfde patroon als de
|
|
herlaadvlag, en om dezelfde reden: geen Docker-socket. Geteld wordt alleen het aantal;
|
|
- **`traffic` vervalt.** Bytes van een lopende sessie zijn er niet af te lezen: `/proc/net/tcp` heeft
|
|
geen tellers, en de interfacetellers van de container bevatten ook het dashboard- en backendverkeer.
|
|
Wat er dan overblijft is een schatting die als meting leest, en dat is precies wat §4c verbiedt. De
|
|
sessieregel bij het sluiten geeft de echte aantallen;
|
|
- **de pagina toont de teller in de badge van het activiteitenlog** en niet als logregel alleen. De
|
|
vraag is "is mijn wallet nu verbonden", en die hoort niet uit een lijst afgeleid te worden.
|
|
|
|
## 5. Het werk
|
|
|
|
Staat in [TAKEN.md](TAKEN.md), met de fase-indeling en wat er af is.
|
|
|
|
## 6. Open punten
|
|
|
|
Staan in [OPEN.md](OPEN.md).
|
|
|
|
## 7. Verificatie
|
|
|
|
Handmatig, want het gaat om wat er in een browser staat:
|
|
|
|
- de pagina toont het werkelijk ingestelde domein en de werkelijke poorten, niet die uit de HTML;
|
|
- na een certificaatvernieuwing verandert de einddatum op de pagina;
|
|
- **stunnel of de proxy stoppen laat de pagina niet "Online" tonen.** Dit is de controle die de aanleiding
|
|
van dit plan afdekt en de enige die per se gedaan moet worden;
|
|
- een certificaat dat binnen dertig dagen verloopt, geeft een zichtbare waarschuwing.
|