Files
UmbrelApps/Docs/Plannen/Actief/008-Umbrelapp/TAKEN.md
T
HarmenandClaude Fable 5.1 a694a9cbd1 Relay 0.6.0: alles in een image, de app-map is leeg
Plan Eigenimage, fase 5, op keuze van de gebruiker: een image met de relay
erbij en geen tweede recept. agent.py, nginx.conf en index.html verhuizen
naar tools/evolu-relay/ naast src/; de Dockerfile blijft op node:24-slim en
haalt nginx en python3 uit apt. Drie containers uit een image: de relay als
node via de compose, de agent en nginx als root.

Anders dan alleen verplaatst: user www-data in nginx.conf (Debian heeft geen
gebruiker nginx), geen USER meer in de image, de versie in de kop via
api/status met RELAY_APP_VERSION. VERSION 0.6.0, manifest 0.6.0, drie keer
dezelfde tag in de compose, ongepind tot de eerste push.

Tests mee verhuisd; de vormtest toetst de drie tags tegen VERSION. Niet
gebouwd: er is hier geen Docker.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 16:36:30 +02:00

334 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Taken - Umbrelapp
> **App: Evolu Relay.** Prioriteit: **B** | Afhankelijk van:
>
> Van A naar B op 28-08-2026: het doel van dit plan is gehaald en het restwerk wacht nergens op.
>
> Actief sinds 25-08-2026. Gepromoveerd uit `Masterplannen/` omdat de gebruiker besloot het pakket meteen te
> maken. De afhankelijkheid op **Proefopstelling** is daarmee geen blokkade meer maar een parallelle bron:
> fase 1 daarvan is af en leverde de feiten waarop dit pakket rust. Wat er nog uit moet komen zijn twee
> vragen die pas bij het installeren pijn doen, en die staan hieronder als eigen taak.
>
> **Dit is de focus vanaf 27-08-2026, op verzoek van de gebruiker.** Het werk aan Electrum Gate is die dag
> afgerond tot en met de tweede indeling; het plan **Eigenimage** staat klaar maar ligt bewust stil. Twee
> feiten om mee te beginnen: **de app staat op dit moment uit** op de Umbrel, en hij is nog nooit met
> Trezor Suite verbonden geweest. "Gebouwd" is hier dus nog verder van "werkend" dan bij Gate.
## Volgende stap
- [x] **De eigenaars gesorteerd op laatst gezien, meest recent bovenaan (07-09-2026, 0.5.6).** Op verzoek
van de gebruiker; in beide kaders en over de groepen heen. Alleen de pagina, dus geen nieuwe image.
**Nog nakijken op het apparaat.**
- [ ] **"Laatst gezien" ook bijwerken bij een sync, niet alleen bij de verbinding.** Het relay-proces
zet `lastSeen` in `decideOwner`, en dat wordt alleen bij de WebSocket-upgrade gesteld. Een client die
dagen verbonden blijft, zakt dus in de lijst terwijl hij druk bezig is. De haak die per schrijfactie
loopt is `isOwnerWithinQuota`; daar kan een pure functie in `policy.js` het tijdstip bijwerken, met
een test in `test_limiter.mjs`. Leesacties zijn niet te zien: daar heeft de relay geen haak voor.
Kost een nieuwe image, dus alleen als de gebruiker dat wil.
- [x] **De accentgloed uitgezet, als schakelaar (04-09-2026, 0.5.5).** Op verzoek van de gebruiker, en in
dezelfde stap in Electrum Gate (0.0.29). `data-glow="on"` op het html-element zet hem terug, en
alleen samen met `data-depth="deep"`. De blur gaat met de gloed mee, waardoor het mobiele
terugvalblok uit 0.5.3 verviel. Alleen de pagina, dus geen nieuwe image.
- [x] **De image 0.5.0 gebouwd en geduwd op de Umbrel (30-08-2026), en gepind.** Digest
`sha256:1e4dafdc…acea49a`, en de suite meldt hem nu als `gepind`. Bouwen kan alleen daar: umbreld kan
niet bij een image die alleen lokaal bestaat, en `docker` vraagt op dat apparaat `sudo`.
**Twee dingen om te bewaren voor de volgende verhoging.** De digest stond hier bewust even níet, want
een oude digest onder een nieuwe tag levert stilzwijgend de oude image; ongepind faalt hard en
zichtbaar. Doe dat dus weer zo: digest weg, bouwen, duwen, nieuwe erin. En doe **beide** pushes naar
de repo vóórdat de app in umbrelOS geüpdatet wordt, anders is het toevoegen van de digest een tweede
compose-wijziging en kost het een extra versienummer.
`docker buildx imagetools inspect` gaf `MediaType: application/vnd.docker.distribution.manifest.v2+json`,
dus **één architectuur en geen multi-arch index**. Dat is bij bouwen op het apparaat zelf te
verwachten en het klopt per constructie met de host; voor de officiele store hoort er arm64 bij, en
dat staat bij **Publicatie-Relay**
- [x] **0.5.2: de opfrisbeurt uit het gedeelde designsysteem (31-08-2026).** Dezelfde drie dingen als in
Electrum Gate: accentgloed, doorschijnende kaarten met randlicht en schaduw, en één hoek voor elk
buitenste kader. Alleen de pagina, dus `VERSION` in `build.sh` blijft staan en het manifest gaat
alleen omhoog. Dat is de regel uit de kop van de changelog, en dit is het tweede geval op rij.
- [x] **0.5.1: de melding bovenaan ging nooit weg (30-08-2026).** Gemeld door de gebruiker binnen een uur
na 0.5.0, op de pagina op zijn eigen Umbrel. Eén ontbrekende tak: de ronde zette de melding wel áán
maar nooit uit, dus "Sent." bleef staan tot je herlaadde. Nu is de melding van de ronde en niet van de
klik. Een weigering is de uitzondering, blijft staan tot de volgende opdracht, en is rood geworden.
**Alleen een `*.template` geraakt, dus geen nieuwe image**: `build.sh` blijft op 0.5.0 en het manifest
gaat naar 0.5.1. Dat is de normale gang van zaken en niet een slordigheid; de regel staat in
[CHANGELOG-evolu-relay.md](../../../CHANGELOG-evolu-relay.md), waar hij bij 0.5.0 nog verkeerd stond
- [ ] **De app store verversen in umbrelOS en de app updaten naar 0.5.1. Eigenaar: gebruiker.**
- [ ] **Daarna op het apparaat nakijken wat een browser moet bewijzen (30-08-2026).** De pagina is met
nagemaakte gegevens bekeken en dat vond twee echte fouten, maar drie dingen kan alleen de app zelf
zeggen: loopt de teller écht af en gaat de deur dan dicht, blijft een label na een herstart staan, en
klopt het adres in het kader "Relay address" (dat gebruikt `window.location.hostname`, en achter de
app-proxy is dat een ander adres dan op een laptop)
- [x] **De kále Evolu-relay geprobeerd, en hij werkt (28-08-2026).** Trezor Suite op de desktop stuurde
elf labels naar `docker.io/evoluhq/relay:latest` en die kwamen aan: de database in het volume groeide
van 40960 naar 49152 bytes. **De protocolversie klopt**, en daarmee is de richting uit
[OPEN.md](OPEN.md) punt 6 gemeten in plaats van verwacht. Het protocol en alle metingen staan in
[PLAN.md](PLAN.md) §6a
- [x] **Uitgezocht waarom iOS niets doet (28-08-2026): het ligt aan het apparaat en niet aan dit pakket.**
De `OwnerId` wordt op de Trezor afgeleid, en het model van de gebruiker kan nog niet aan een iPhone
gekoppeld worden. Zonder apparaat kent de app geen `deviceStaticSessionId`, en dan slaat Suite een
label lokaal op en doet verder niets, zonder melding. De hele redenering met bronregels staat in
[OPEN.md](OPEN.md) punt 9
- [x] **De leeskant gemeten en in orde (28-08-2026).** Getest met een tweede gebruikersaccount op dezelfde
Mac, en dat is schoner dan een tweede apparaat: die installatie heeft een **lege** lokale
Evolu-database, dus alles wat daar verschijnt kan alleen van de relay komen. Dezelfde Trezor en
dezelfde wallet, dus dezelfde `OwnerId` en geen nieuwe eigenaar. De labels kwamen door. Daarmee zijn
beide richtingen bewezen
- [x] **Besloten wat er met het huidige pakket gebeurt (28-08-2026): het gaat eruit.** De relay van Trezor,
de quota-manager en de Postgres vervallen. Wat ervoor in de plaats komt staat in [PLAN.md](PLAN.md)
§4g en §4h
- [x] **De limiter gekozen (28-08-2026): weg 1, uitbreiden via `createRelay`.** Dat bleek veel kleiner dan
**Bereikbaarheid** §4b aannam: het zijn twee terugroepfuncties, `isOwnerAllowed` en
`isOwnerWithinQuota`, en Trezor doet zelf niets anders. De gebruiker breidde het ontwerp uit met een
schakelaar voor nieuwe eigenaars en met wissen per eigenaar. Zie [OPEN.md](OPEN.md) punt 8
- [x] **De vraag of het databaseschema zichzelf aanmaakt is vervallen.** Hij ging over het pakket dat eruit
gaat, en de kale relay maakt zijn database bij de start zelf aan; dat is op 28-08-2026 gezien
## Fase 5 - De verbouwing naar de kale relay
**Op 28-08-2026 in één sessie gedaan en op het apparaat draaiend, versie 0.3.0.** Wat er staat: het eigen
relay-programma met de allowlist, het bouwrecept, de compose met de omgedraaide poorten, de statuspagina, en
TLS via Zoraxy op een eigen subdomein. De Mac synchroniseert eroverheen, met een geleerde eigenaar en een
gesloten deur erna.
Wat er niet staat: iOS doet niets mee, en daardoor is de leeskant nooit gemeten. Beide staan hierboven bij
"Volgende stap".
- [x] **Het eigen relay-programma geschreven (28-08-2026).** `tools/evolu-relay/src/`: `policy.js` met het
beleid als pure functies, `store.js` voor de staat op schijf, en `index.js` dat `createRelay`
aanroept met de opstartvolgorde van Evolu zelf. Met test: `node tests/test_limiter.mjs`, 60 toetsen,
en de beslissende regel is muteertest gedaan
- [x] **Een getal gekozen voor `isOwnerWithinQuota`: 1 MB per schrijfactie**, instelbaar met
`RELAY_MAX_WRITE_BYTES`. Onderweg bleek de aanname hieronder fout: die 1 MB van de gepubliceerde image
is **per schrijfactie** en geen totaal per eigenaar. Er valt dus geen labelgeschiedenis tegenaan te
lopen. Een totaal per eigenaar zou vragen dat we in de opslag van de relay kijken, en dat doen we niet
- [x] **De allowlist als staat onder `${APP_DATA_DIR}/data/`**, naast de relay-database en niet erin:
`owners.json`, atomair geschreven, en `command.json` als postbus voor de pagina
- [ ] **Data per eigenaar wissen.** Nog niet gebouwd, en bewust niet gegokt: het beleid kan een eigenaar
vergeten en blokkeren, maar zijn berichten staan in de SQLite van de relay
(`evolu_message`, `evolu_history`, met `ownerId` als systeemkolom). Dat is schrijven in andermans
schema, dus dat wil eerst nagekeken worden in `createRelaySqliteStorage` van Evolu
- [ ] **Een `package-lock.json` maken en `npm install` in de Dockerfile omzetten naar `npm ci`.** De twee
pakketten van Evolu staan exact vast, maar wat eronder hangt beweegt nu nog mee. `build.sh` waarschuwt
hiervoor. Kan pas op een machine met netwerk en npm
- [ ] **Wissen per eigenaar laten doen door het relay-proces zelf**, aangestuurd met een vlagbestand vanaf
de pagina. Geen tweede container die langszij in de SQLite schrijft, en geen Docker-socket
- [x] **`tools/evolu-relay/build.sh` omgeschreven (28-08-2026):** bouwt de eigen `Dockerfile` in plaats van
de repo van Trezor te klonen. Git is niet meer nodig, de pin zit nu in `package.json`, en `VERSION`
in het script hoort gelijk te zijn aan `version` in het manifest
- [x] **De compose omgezet (28-08-2026):** pagina achter `app_proxy` mét de inlog, relay op host-poort
3852. Postgres, wachtwoord en quota-manager eruit; drie containers werden relay, agent en nginx. De
image is gepind op tag plus digest
- [x] **De statuspagina gebouwd (28-08-2026):** `index.html.template`, `nginx.conf.template` en
`agent.py.template`, met het ontwerpsysteem van Electrum Gate en zonder de Google Fonts-verwijzing.
Toont of de relay draait, de omvang en het laatste schrijfmoment van de database, het adres dat je in
Suite invult, en de eigenaars in drie lijsten met knoppen om te blokkeren, alsnog toe te laten of te
vergeten. **Nog nooit in een browser gezien**
- [x] **Het relay-programma op het apparaat geverifieerd (28-08-2026).** Losgedraaid uit het register,
buiten de app om. Het log meldde `learned a new owner`, en in `/app/data` stonden daarna
`evolu-relay.db` van 49152 bytes (dezelfde omvang als bij de proef van vanochtend, dus de labels zijn
geland) en `owners.json` van 241 bytes. Daarmee is de hele keten gemeten: `isOwnerAllowed` wordt
aangeroepen met iets wat het beleid begrijpt, de leerstand werkt, en de allowlist gaat naar schijf
- [x] **De pagina en de agent op het apparaat geverifieerd (28-08-2026).** De pagina rendert, toont de
gegevens van de relay, en de knop **Close** werkt: de leerstand ging naar `closed` en de geleerde
eigenaar staat in de lijst met eerste en laatste verschijning. Daarmee is de hele keten gemeten,
pagina → agent → postbus → relay-proces → schijf → pagina
- [x] **De fout die dat opleverde is gerepareerd:** de korte containernaam `agent` is op het gedeelde
Docker-netwerk niet uniek, dus de helft van de verzoeken kwam bij Electrum Gate uit. Beide apps
wijzen nu naar `<app-id>_agent_1`, en `test_appstore_vorm.py` toetst dat voortaan
- [x] **De app opnieuw geïnstalleerd in plaats van geüpdatet (28-08-2026).** De oude installatie was er
eerst afgehaald, en dat was ook de nette weg: niet elk bestand bereikt een bestaande installatie via
een update
- [x] **Zoraxy ingericht (28-08-2026)** op een eigen subdomein met TLS, doorverwijzend naar de relay-poort,
met de WebSocket-upgrade aan. De handshake-curl uit [PLAN.md](PLAN.md) §6a stap 3 geeft daar
`101 Switching Protocols`, en de desktop synchroniseert eroverheen
## Fase 6 - De statuspagina op de lijst van de gebruiker (0.5.0)
**De lijst kwam op 30-08-2026, nadat de gebruiker met 0.4.0 gewerkt had.** Negen punten, en alle negen
gedaan. Twee ervan waren onderzoeksvragen; die staan onderaan.
Waarom dit in één ronde kon: de pagina is een `*.template` en zit dus in de update-whitelist. Zodra hij in
een eigen image zit (het plan **Eigenimage**) kost elke tweak een bouw plus een digest, en dán is dit
duurder. Die volgorde stond als reden bij de vorige taak en is daarmee ingelost.
- [x] **Gelijkgetrokken met Electrum Gate.** Dezelfde `max-width: 1760px`, hetzelfde raster van twaalf
kolommen, hetzelfde icoon van 64 pixels met terugval, dezelfde `t-h1` van 2rem, hetzelfde menu met
drie punten, en het versienummer achter de tagline. De pagina leende dat ontwerp al maar op eigen maten
- [x] **Een tijdvenster van twee minuten voor nieuwe eigenaars, met een stopknop.** **De teller zit in het
relay-proces en niet in de pagina**, en dat is de kern van deze taak: een teller in een tabblad dat je
sluit, sluit de deur niet. `policy.js` heeft er een veld `learningUntil` voor gekregen, plus
`isLearningOpen` en `expireLearning`
- [x] **`decideOwner` kijkt naar `isLearningOpen` en niet naar het veld `learning`.** Dat is geen
netheid: de lus die het bestand opruimt loopt elke twee seconden, en in dat gat zou een onbekende
alsnog binnenkomen. Muteertest gedaan: de juiste drie toetsen vielen om
- [x] **Zonder `STATE_VERSION` te verhogen**, en met een toets die dat verdedigt. Een verhoging zou
`normalizeState` het bestand van de draaiende installatie laten afwijzen, en dan schuift `store.js` de
allowlist opzij en gaat de deur dicht voor eigenaars die er al in stonden
- [x] **Geweigerde en geblokkeerde eigenaars in één kader.** Wat je ermee doet is hetzelfde: toelaten of
vergeten. Welke van de twee een regel is, staat als badge op de regel, en die badge staat **buiten**
het hover-blok. Dat was de eerste van de twee fouten die de voorbeeldweergave vond: erbinnen was het
onderscheid onzichtbaar tenzij je over de regel ging, en dat is juist de informatie waarvoor de twee
kaders zijn samengevoegd
- [x] **De uitleggende regels eruit.** De koppen zeggen genoeg; wat er te weten valt staat in de nieuwe
dialoog. Wat níet weggegooid is maar verplaatst: dat het adres met `http` moet beginnen en niet met
`ws`, en wat de relay wel en niet kan zien
- [x] **Knoppen alleen bij hover, per regel.** Met opacity en niet met `display: none`, zodat ze met de
tab-toets bereikbaar blijven; `focus-within` maakt ze dan zichtbaar, en op een aanraakscherm staan ze
altijd aan. Dit had één gevolg dat je niet ziet aankomen: onzichtbare knoppen houden hun ruimte, dus
de kop "New owners" brak over twee regels en de waarde stond lager dan in de drie kaders ernaast.
Opgelost met kortere knoptekst plus hetzelfde afbreekpunt van 1400px dat Gate gebruikt
- [x] **Geen voetregel, en een menu-item "About this app" in plaats daarvan.** In **beide** apps, op verzoek
van de gebruiker. Bij Gate staat daar bovendien wat de statuswidget wél en niet bewijst
- [x] **Labels op een eigenaar-id, te onderhouden.** Hover een regel en klik **Label**: het veld komt in de
plaats van de titel, Enter bewaart, Escape breekt af. **De labels staan in een eigen bestand
`labels.json` met de agent als enige schrijver**, en niet in `owners.json`. Drie redenen: één schrijver
per bestand blijft de afspraak, een label is meteen opgeslagen in plaats van na de volgende ronde van
de relay, en labelen blijft werken als de relay omgevallen is. De relay hoeft dit niet te weten, want
een label zegt niets over wie er binnen mag
- [x] **De statuswidget van Electrum Gate verduidelijkt**, op de opmerking van de gebruiker dat die van
Evolu Relay veel duidelijker is. Er stond "Answering" met "answered in 7 ms, from inside the app"; nu
"Running" met de meting eronder, en de nuance staat onder een eigen kopje in de nieuwe dialoog
### Wat er aan toetsen bij kwam
De pagina's zijn samen bijna drieduizend regels en er stond geen enkele toets op. Dat blijft zo voor wat ze
tonen, maar drie klassen fouten hoeven niet op het apparaat gevonden te worden:
- [x] **`tests/test_relay_agent.py`** (nieuw, 65 toetsen): de labels en het tijdvenster in de agent. Twee
muteertests gedaan
- [x] **`tests/test_paginas_parsen.mjs`** (nieuw): loopt de JavaScript van elke pagina, en loopt hij ook nog
ná de invulling door umbreld. Muteertest gedaan met een echte syntaxfout
- [x] **Een dollarteken-toets in `test_appstore_vorm.py`.** Dit is de valstrik van dit hele project, en het
commentaar in drie bestanden beweerde al dat déze test hem dichthield terwijl dat niet zo was. Nu
wel. Hij vond meteen twee valse positieven in de eigen opzet (een kaal dollarteken in een
commentaarregel, en de exports van een afhankelijkheid), en die zijn in de toets opgelost en niet in
de bestanden
- [x] **Een toets dat er geen werkbestanden in een app-map staan.** umbreld kopieert de héle app-map naar
het apparaat, dus een bewerkbestand van een icoon van 175 kB gaat mee in elke back-up. Die stond er
op 30-08-2026
- [x] **`tools/voorbeeldpagina.mjs`** (nieuw): maakt van een `*.template` een pagina die je in een browser
kunt openen, met de variabelen ingevuld en nagemaakte gegevens erin. Geen toets en geen bewijs, maar
het vond in één keer de twee fouten hierboven. Uitvoer komt in `voorbeeld/` en die map is gitignored
### De twee onderzoeksvragen
- [x] **"Komen geweigerde eigenaars toch met de hele blow aan instellingen in de database?" Nee.**
`isOwnerAllowed` wordt in de WebSocket-**upgrade** aangeroepen; een weigering is een HTTP 401 en een
gesloten socket, dus er wordt niets opgeslagen. **Maar het gewenste gevolg treedt wel op**: Evolu is
local-first, de cliënt houdt alles zelf en probeert opnieuw, dus alsnog toelaten brengt de hele
geschiedenis binnen. De redenering met bronregels staat in
[Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md) §10, en daar staat ook de
scherpe kant: **blokkeren werkt pas bij de volgende verbinding**, want voor een lopende verbinding
wordt de vraag nooit opnieuw gesteld. Dat staat als open punt 10 in [OPEN.md](OPEN.md)
- [x] **"Kunnen we de blobs ontcijferen met de xpub?" Nee, en de premisse klopt niet.** Een `OwnerId` wordt
niet uit een xpub gemaakt: `OwnerId`, `OwnerEncryptionKey` en `OwnerWriteKey` komen alle drie met
SLIP-21 uit één 32-byte node die het apparaat aflevert. Dat spoor loopt langs de seed en niet langs
BIP32, dus uit een xpub is er niets te halen. **Met die node zelf kan het wél**, en `trezorlib` heeft
er een functie voor. Waarom dat níet in deze app hoort, en waar het wél hoort, staat in §11 van
hetzelfde document; het plan-punt staat in de repo `HomeGit/Trezor` bij **AdvancedUI**
## Fase 1 - De app-map
- [x] **`whatsnext-evolu-relay/` aangemaakt met `umbrel-app.yml` en `docker-compose.yml` (25-08-2026).**
Mapnaam gelijk aan het `id`, met het store-voorvoegsel `whatsnext-`, en de manifestvelden in de
voorgeschreven volgorde
- [x] `data/postgres/.gitkeep` erin, zodat de mount bij de eerste start niet als root wordt aangemaakt
- [x] **`dependencies` weggelaten en niet leeg gezet.** Deze app hangt van geen enkele andere app af; een
leeg veld zou suggereren dat er iets te kiezen valt
- [x] **Een eigen icoon (28-08-2026).** `icon.png` aangeleverd door de gebruiker, met de `icon`-regel in
het manifest die naar de rauwe versie in deze repo wijst. Als laatste regel, want bij inlevering in
de officiële store hoort hij weg
## Fase 2 - De compose
- [x] **`app_proxy` met `PROXY_AUTH_ADD: "false"`, en geen eigen `ports:`.** Trezor Suite is geen browser
met een sessiecookie. Dit is het patroon van de eigen `nostr-relay`-app van Umbrel, dus een precedent
en geen omweg; zie [PLAN.md](PLAN.md) §4c
- [x] **Relay en quota-manager uit één image met een ander `command`.** Expliciet en niet leunend op de
`CMD` van de Dockerfile, want daar staat `yarn start` met bovenstrooms zelf een twijfel erbij
- [x] **De quota-manager gaat mee.** Niet omdat de relay hem aanroept, maar omdat de relay elke eigenaar
zonder limietenrij weigert en dit is wat die rijen maakt
- [x] **Postgres onder `${APP_DATA_DIR}/data/postgres`**, wachtwoord uit `${APP_PASSWORD}`, `PGDATA` op een
submap, en `postgres:17-alpine` in plaats van `postgres` kaal
- [x] **Healthcheck op de eigen database en gebruiker**, niet op `-d postgres` zoals bovenstrooms: die
database bestaat hier niet, en dan is de controle groen op het verkeerde antwoord
- [x] **De eigen image gepind op tag plus digest (25-08-2026).**
`sc.kamenier-hamer.nl/sysop/evolu-relay:c03a204@sha256:2fe1e9e9…`, op beide services. Dat moest wel:
zie fase 4. **Let op dat dit één architectuur is** (amd64), want er is alleen amd64 geduwd. Voor de
officiele store hoort er een multi-arch index-digest met arm64 in; dat staat bij **Publicatie-Relay**
- [x] **De Postgres-pin is vervallen (28-08-2026):** die database zit niet meer in de app
- [x] **De statuspagina verbeteren, op een lijst van de gebruiker.** De lijst kwam op 30-08-2026 en is in
één ronde uitgevoerd; zie fase 6 hieronder
- [x] **`python:3-alpine` en `nginx:alpine` pinnen: vervallen (08-09-2026).** Sinds 0.6.0 zitten de agent
en de pagina in de eigen relay-image (plan **Eigenimage**, fase 5), en die twee images staan niet
meer in de compose. Wat er te pinnen is, is de eigen image, en dat gebeurt bij elke verhoging. De
oude tekst hieronder blijft staan als uitleg waarom er tot dan bewust níet gepind is.
Op aanwijzing van de gebruiker (30-08-2026): die twee images waren
de plek waar de agent en de pagina van deze app uitgevoerd werden, en dat is precies wat **Eigenimage**
naar een eigen image verhuisde. Pin je ze dan, dan pin je iets dat verdwijnt.
De eis komt uit **Publicatie-Relay** en die is nog ver weg, dus er is geen haast. De regel en de hele
keten erachter staan in [KNOWLEDGE.md](../../../KNOWLEDGE.md); de commando's in
[Images-pinnen.md](../../../Referenties/Images-pinnen.md).
**De eigen relay-image is een ander geval en die is wél gepind**, bij elke verhoging. Verwar die twee
niet: de suite drukt beide af in dezelfde lijst
## Fase 3 - Het bouwrecept
- [x] **`tools/evolu-relay/build.sh` (25-08-2026).** Haalt de broncode op een vastgezette commit en bouwt
de Dockerfile van Trezor. Niet hun bouwstappen nabouwen; wat wij toevoegen is de pin
- [x] **Niet in de app-map gezet, en dat is geen netheid.** Een `Dockerfile` staat niet in de
update-whitelist, dus bouwen-in-de-app zou elke nieuwe versie een herinstallatie kosten. Zie
[PLAN.md](PLAN.md) §4f
- [x] **Onder `tools/` en niet onder `build/`:** dat laatste staat in `.gitignore` als bouwselmap, dus het
recept zou stilzwijgend buiten de repo blijven. Gevonden bij het stagen, niet bij het schrijven
- [x] Het script controleert na het ophalen dat de commit is wat hij verwachtte, en faalt hard als dat niet
zo is. Zonder die regel bouwt het stil de verkeerde toestand
## Fase 4 - Installeren en verifiëren op de Umbrel
Niets hiervan is op een laptop te doen. Eigenaar van deze hele fase: **gebruiker**.
- [x] **De image gebouwd op de Umbrel (25-08-2026), in 50 seconden.** Twee dingen die het opleverde: de
gebruiker `umbrel` zit hier níet in de groep `docker`, dus het moet met `sudo`; en de Dockerfile van
Trezor bouwt zonder aanpassing
- [x] **In een register gezet, want anders kan umbreld er niet bij (25-08-2026).** Dit was de grote
verrassing van de dag en het staat met bron in
[Umbrel-appstore-spec.md](../../../Referenties/Umbrel-appstore-spec.md): umbreld haalt élke image via
de Docker Engine API op, niet via compose. Een lokaal gebouwde tag is dus onbereikbaar en
`pull_policy: never` doet niets, want de compose wordt niet gelezen om te pullen. Het Gitea-register op
dezelfde server als de store bleek de kortste weg, en anoniem halen werkt daar
- [x] **De app geïnstalleerd en alle drie de containers blijven draaien (25-08-2026).** `relay`,
`quota-manager` en `db`, met `db` op healthy en de app-proxy op 3851. De lokale images waren vooraf
weggehaald, dus de pull uit het register is echt gedaan en het hele pad is bewezen: broncode →
bouwrecept → register → gepinde digest → installatie
- [x] **De schemavraag is vervallen (28-08-2026):** de kale relay maakt zijn SQLite bij de start zelf aan,
en de Postgres waar deze vraag over ging zit niet meer in de app
- [x] **Trezor Suite synchroniseert (28-08-2026), heen én terug.** Niet naar 3851 zoals hier stond maar naar
3852: de poorten zijn omgedraaid, want 3851 draagt nu de statuspagina. Zie de "Volgende stap"
hierboven
- [ ] De app gestopt en gestart, en de data heeft het overleefd. **Nog niet gedaan**, en het is de laatste
controle van dit plan die er echt toe doet: de allowlist en de labels staan onder
`${APP_DATA_DIR}/data/relay`, dus een herstart hoort niets te kosten. **Eigenaar: gebruiker**
- [x] **Gecontroleerd of het toevoegen van deze app Electrum Gate raakt (28-08-2026), en dat deed het.**
Niet zoals verwacht via poorten of geheugen, maar via een naam: beide apps hadden een service `agent`
op hetzelfde Docker-netwerk, en Docker verdeelde de naam over allebei. De pagina van Gate ging daardoor
stuk. Gerepareerd in beide apps, met een toets in `test_appstore_vorm.py` zodat het niet stil
terugkomt
## Geblokkeerd / wacht op
**Leeg sinds 28-08-2026.** Beide blokkades zijn opgeheven en ze staan hier voor de geschiedenis.
- [x] **"Hoe registreer je een eigenaar bij de quota-manager?"** is vervallen: de quota-manager zit niet
meer in de app, en de kale relay kent geen limietentabel. De vraag bestond alleen bij het pakket van
Trezor
- [x] **"Accepteert Trezor Suite dit adres, en in welke vorm?"** is beantwoord: ja, met `http(s)://` en
desgewenst een pad, zowel via het dev-utils-veld als via de gewone "Custom server"-instelling. Gemeten
op de desktop, heen en terug