Files
UmbrelApps/Docs/Plannen/Actief/008-Umbrelapp/OPEN.md
T

323 lines
23 KiB
Markdown
Raw Normal View History

# Open punten - Umbrelapp
> Beslissingen die nog een **eigenaar** of een **moment** nodig hebben. Staat een punt hier zonder allebei,
> dan is dat de eerste fout om op te lossen. Wordt een punt een taak, dan verhuist het naar
> [TAKEN.md](TAKEN.md).
>
> **Nummers blijven staan**, ook als een punt beslist is: er kan elders naar verwezen worden, ook vanuit
> codecommentaar. Beslissen betekent verplaatsen naar de kop hieronder, niet hernummeren.
## Nog te beslissen
6. **Pakketteren we wel de juiste relay?** - **beslist op 28-08-2026 door de proef: nee, en het wordt de
kale Evolu-relay.** Dit punt blijft hier staan tot de verbouwing gedaan is, want het beschrijft de reden
waarom het huidige pakket eruit gaat. De volledige meting staat in [PLAN.md](PLAN.md) §6a.
`trezor/trezor-suite-sync` is niet Evolu maar Trezor's inzet ervan, met een Postgres en een
quota-manager voor hún gehoste dienst. Het project eronder, `evoluhq/evolu`, heeft een eigen relay: één
container, een **gepubliceerde** image `docker.io/evoluhq/relay:latest`, een datavolume in plaats van een
database, en niets gedocumenteerd over toegangscontrole. Zie
[Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md) §0.
Werkt Trezor Suite daarmee, dan vervalt zowat alles waar dit pakket moeilijk van doet: de bouwstap, het
eigen register, de onderhoudsplicht op een image, de Postgres met zijn wachtwoord, en de
eigenaarsregistratie die nu de blokkade is. Drie containers worden er één.
**Nog diezelfde avond grotendeels beantwoord uit de cliëntkant**, nadat de gebruiker erop wees dat de
broncode van Trezor Suite lokaal staat in een ander project. Uit een commentaarregel van Trezor zelf:
*"We only want to use QM for our own relay servers. In case custom URL has been set, QM is ignored."*
Daarmee draait de vraag om. **Met een eigen relay-URL registreert Suite geen eigenaar**, en Trezor's relay
weigert iedereen zonder limietenrij. Die rij komt er dus nooit. Niet de kale Evolu-relay is de gok, maar
het pakket dat er nu staat: **Trezor's relay is als zelf-gehoste relay in de kern onbruikbaar** tenzij je
die rij met de hand zet.
Wat er nog écht open is, is één ding en dat is geen redenering maar een proef: **klopt de
protocolversie?** Suite gebruikt `@evolu/web@3.0.0-next.1` met een eigen patch in `.yarn/patches/`, en
`docker.io/evoluhq/relay:latest` hoeft daar niet bij te passen.
**Meten en niet redeneren:** `docker run --rm -p 4000:4000 docker.io/evoluhq/relay:latest`, Suite
ernaartoe wijzen, label maken. De instellingen staan onder **dev-utils** en `http://` volstaat; zie
[Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md) §0 en §7.
**Richting gekozen door de gebruiker op 27-08-2026: we gaan voor de kale relay**, met een eigen limiter
erop en de statuspagina uit punt 2. Zijn woorden: "dat wordt beter."
**Dat was een richting en geen besluit, en op 28-08-2026 is het er alsnog een geworden.** De proef is
gedaan en geslaagd: Suite op de desktop stuurde elf labels naar `docker.io/evoluhq/relay:latest` en die
kwamen aan. De protocolversie klopt dus, en daarmee vervalt de enige uitweg waarin de hele richting
omviel. Wat nu volgt is verbouwen, en de eerste vraag daarbij is de limiter uit punt 8.
Wat de richting wél nu al vastlegt, zodat het niet opnieuw uitgezocht hoeft te worden:
- **de drie dingen horen bij elkaar en zijn geen wensenlijstje.** De kale relay heeft géén
toegangscontrole, en dat is bij Evolu geen omissie maar het ontwerp. Vandaag is het enige dat de schade
beperkt juist een applicatiecontrole: Trezor's relay weigert elke eigenaar zonder limietenrij (zie
punt 2). **Gaan we kaal, dan verdwijnt precies die bescherming**, en wordt de limiter van "leuk" naar
"voorwaarde". Het instinct om ze in één adem te noemen klopt dus;
- **de statuspagina krijgt er een taak bij.** Hij toont niet alleen of het werkt, hij is ook de plek waar
je ziet wélke eigenaar is toegelaten en waar de knop zit om die keuze te wissen. Zie punt 8;
- **een eigen image is geen blokkade.** De gebruiker meldde op 27-08-2026 dat de broncode nog op zijn
Umbrel staat, dus opnieuw bouwen en naar het eigen Gitea-register duwen kan gewoon. Dat is relevant
omdat de limiter dat waarschijnlijk vraagt; zie punt 8.
**Moment:** beslist op 28-08-2026; dit punt sluit zodra de verbouwing gedaan is · **Eigenaar:**
gebruiker
9. **Heeft de iOS-app TLS nodig, en wat kost dat?**
Nieuw op 28-08-2026. De desktop werkt over `http://` op een LAN-adres; de iOS-app doet met dezelfde
instelling geen enkele verbindingspoging. Het vermoeden van de gebruiker is dat iOS onversleuteld
verkeer weigert, en dat is plausibel: App Transport Security blokkeert standaard `http` en `ws`, en de
schakelaar voor lokaal netwerk verscheen niet, wat past bij een verbinding die het besturingssysteem
nooit heeft laten vertrekken.
**Het is een vermoeden en geen meting.** Een tweede verklaring past even goed op wat we zagen: het
synchroniseren kwam op de telefoon nooit op gang omdat de bevestiging op het apparaat ontbrak. Die twee
zijn van buitenaf niet te scheiden, en ze hebben een heel verschillende prijs.
**Want TLS is hier duur, en dat is de reden dat dit een open punt is en geen taak.** Een certificaat
voor een LAN-adres als `10.0.0.11` krijg je niet van een publieke uitgever, en een zelfondertekend
certificaat wordt door precies dezelfde iOS-controle geweigerd. De wegen die wél bestaan lopen via het
masterplan **Bereikbaarheid**: Tailscale geeft een echte naam met een geldig certificaat, en een reverse
proxy met een eigen domein is wat Electrum Gate al doet. Beide veranderen dit van "een vlag omzetten" in
een eigen ontwerpvraag.
**Richting van de gebruiker, 28-08-2026:** een certificaat op een eigen subdomein, en Zoraxy dat die
naam doorzet naar de relay op de interne poort. Dat is dezelfde weg die Electrum Gate al gebruikt, dus
het is bekend terrein en geen nieuw bouwwerk. Twee dingen die daarbij vastliggen:
- **Zoraxy moet de WebSocket-upgrade doorlaten.** Dit is geen gewone HTTP-site; alles loopt over één
opgewaardeerde verbinding, en bij de meeste reverse proxies is dat een schakelaar per host. Staat die
uit, dan lijkt het beeld op dat van vanochtend: een server die leeft en een cliënt die niets doet. De
handshake-curl uit [PLAN.md](PLAN.md) §6a stap 3 is dan de test, met de publieke naam in plaats van
het IP;
- **TLS lost punt 8 niet op, het maakt het dringender.** Een certificaat regelt versleuteling en
waarschijnlijk iOS, maar niet wie er mag schrijven. Achter een publieke naam is de kale relay vanaf
het internet bereikbaar zonder enige toegangscontrole. De kale relay op een LAN is iets anders dan de
kale relay op een publiek subdomein.
**Stand aan het eind van 28-08-2026, en het vermoeden is weerlegd.** TLS is er inmiddels: Zoraxy zet
het subdomein door naar de relay, de handshake-curl geeft `101 Switching Protocols`, en de Mac
synchroniseert daar overheen. Op iOS is daarna alles ingesteld wat er in te stellen valt: de relay-URL
staat opgeslagen en overleeft een herstart, en de aparte schakelaar voor Suite Sync staat aan. De app
toont geen enkele foutmelding.
**En er komt nog steeds niets aan.** Dat is nu hard gemeten en geen indruk meer: sinds 0.3.0 logt het
relay-proces élke eigenaar die zich meldt, ook een bekende en ook een geweigerde. Bij elke verbinding
van de Mac verschijnt `owner ... connected`; van de telefoon verschijnt niets. Geen verbinding, geen
weigering, geen poging. Daarmee is de hele app vrijgepleit: allowlist, quota, beleid en opslag komen er
niet aan te pas.
Ook uitgesloten: dat het aan de wallet zou liggen. Een `OwnerId` hoort bij een wallet en niet bij een
apparaat (zie [Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md) §0 punt 5), dus
dezelfde wallet op iOS zou een `OwnerId` opleveren die al toegelaten is. Een andere wallet zou als
geweigerde poging zichtbaar zijn geweest. Geen van beide gebeurt.
**Wat nog niet gemeten is, en dat is de volgende stap:** verlaat het verzoek de telefoon überhaupt?
Zoraxy logt elk verzoek dat het subdomein bereikt. Open op de iPhone `https://<subdomein>/` in Safari
en kijk of die regel verschijnt. De pagina toont niets, want het is een WebSocket-server, maar de
logregel is het antwoord:
- **wél een regel** → route, DNS, certificaat en Zoraxy zijn in orde, en dan belt de app gewoon niet.
Dat is dan een tekortkoming van de cliënt en niet van dit pakket;
- **geen regel** → de telefoon bereikt die naam niet. Dan is het DNS of routering: mobiel netwerk in
plaats van WiFi, of een subdomein dat alleen in de interne DNS bestaat.
**En aan het eind van de dag kwam het antwoord alsnog, uit de cliëntcode en uit een opmerking van de
gebruiker: het ligt aan het apparaat, niet aan het netwerk.** Hij merkte op dat hij op de Mac per wallet
op de hardware wallet moest goedkeuren, en dat zijn model nog niet aan een iPhone te koppelen is; de
Safe 7 wel.
Dat sluit de keten, en die is in de broncode van Suite na te lezen:
- de `OwnerId` wordt op het apparaat afgeleid. `createRetrieveSuiteSyncOwner.ts` begint met
`if (!device.connected) return err(DeviceNotConnectedError(...))`;
- `selectIsSuiteSyncInitPossible` eist `device.connected && isSuiteSyncSupportedByDevice(device)`;
- `selectSuiteSyncInteraction` geeft **`null`** zodra er geen `deviceStaticSessionId` is, dus zodra de
app helemaal geen apparaat kent;
- en in `useTurnOnSuiteSyncGuard` valt `null` in dezelfde tak als `'unsupported'`: **`return ok()`**.
Het label wordt lokaal opgeslagen, er gebeurt verder niets, en er is niets te melden.
Dat verklaart alle waarnemingen tegelijk: de schakelaar liet zich aanzetten (dat is een instelling,
`settings.isSuiteSyncEnabled`, en die zegt op zichzelf niets), er kwam geen foutmelding, er was geen
groen bolletje, en onze relay zag nooit een eigenaar. **Zonder een Trezor die aan de telefoon kan, is er
geen eigenaar, en zonder eigenaar valt er niets te synchroniseren, met of zonder relay.**
**Conclusie: dit is geen tekortkoming van dit pakket en er valt hier niets te repareren.** De relay
werkt; de cliënt komt op dat platform niet aan een sleutel.
**En dat betekent dat het met Trezor's eigen server net zo stil zou zijn**, want die controle zit in de
cliënt en niet in de relay. Zelf hosten kost hier dus niets. Het experiment dat daarvoor in beeld was,
iOS en de desktop tijdelijk op de standaard-relay zetten, zou niets hebben opgeleverd behalve de labels
op een server van een ander. Wat het wél betekent voor de app-tekst is dat
"werkt op je telefoon" niet beloofd moet worden zolang dat van het model afhangt.
Wat nog de moeite waard is om te meten, en alleen omdat het goedkoop is: of het verzoek de telefoon
überhaupt verlaat, via het log van Zoraxy. Bij de verklaring hierboven hoort dat het níet vertrekt. Zie
je toch verzoeken, dan klopt er iets niet aan deze redenering en begint het opnieuw.
**Moment:** beantwoord op 28-08-2026; de controle in Zoraxy is optioneel · **Eigenaar:** gebruiker
8. **Welke limiter komt er op de kale relay?** - **beslist op 28-08-2026: weg 1, de relay uitbreiden via
`createRelay`.** Het ontwerp staat in [PLAN.md](PLAN.md) §4g en bleek veel kleiner dan hieronder
aangenomen: het zijn twee terugroepfuncties en geen eigen relay. De gebruiker breidde het uit met een
schakelaar voor nieuwe eigenaars en het wissen van data per eigenaar. Het geheime pad uit de vierde weg
is bewust niet genomen. De rest van dit punt blijft staan als onderbouwing tot de verbouwing er is.
Nieuw op 27-08-2026, uit de richting in punt 6. Dit is de vraag die met "kaal gaan" meekomt en die je
niet kunt uitstellen tot na de verbouwing, want hij bepaalt of er een eigen image nodig blijft.
**Wat het níet kan zijn: de quota-manager die er nu in zit.** Die schrijft rijen in de limietentabel van
Trezor's schema, en de kale relay heeft dat schema niet, geen Postgres, en geen begrip van eigenaars. Wat
er komt is dus nieuw werk en geen hergebruik.
De drie wegen staan in het masterplan **Bereikbaarheid** §4b en verschillen sterk in prijs:
1. **de relay uitbreiden via `createRelay`** uit `@evolu/nodejs`. Dat is het bedoelde uitbreidpunt en
vrijwel zeker wat Trezor gedaan heeft. Prijs: een eigen kleine dienst schrijven en onderhouden, en
**weer een eigen image bouwen**;
2. **terug naar Trezor's relay** met een eigen interface die de limietenrij zet. Schrijven in andermans
schema, dus breekbaar bovenstrooms, plus de Postgres terug;
3. **geen allowlist maar het netwerk**: Tailscale of een IP-beperking. Kost geen regel code, maar beperkt
wie er mag verbinden en niet welke eigenaar mag schrijven.
**De spanning die hierbij hoort, eerlijk opgeschreven:** weg 1 haalt een deel van de winst van kaal gaan
weer weg, want de bouwstap en het eigen register komen terug. Wat er dan nog steeds overblijft is
aanzienlijk: geen Postgres, geen wachtwoord, geen onderhoud aan andermans schema, en een relay die
bovenstrooms gewoon meebeweegt. De gebruiker heeft dat op 27-08-2026 al ondervangen: de broncode staat
nog op zijn Umbrel, dus opnieuw bouwen en naar het eigen register duwen is geen nieuw obstakel.
**Eén detail dat weg 1 en 2 lastiger maakt dan ze klinken, en de uitweg erbij:** je moet je eigen
`OwnerId` kennen om hem te kunnen toelaten, en Suite toont die waarschijnlijk nergens. De uitweg uit §4b
is de allowlist niet te laten typen maar te laten leren: **de eerste eigenaar die verbindt wordt
toegelaten, de rest geweigerd**, met een knop om die keuze te wissen. Dat vraagt geen interface om een id
in te tikken, en het is precies genoeg voor één huishouden. Die knop hoort dan op de statuspagina uit
punt 2, en dat is meteen het argument dat die pagina meer is dan gemak.
**Moment:** zodra de proef uit punt 6 geslaagd is · **Eigenaar:** gebruiker beslist, met een voorstel
vanuit de sessie
2026-08-25 18:37:18 +02:00
5. **Is de app bruikbaar voor iemand anders die deze store toevoegt?**
Nieuw op 25-08-2026, en het is de keerzijde van punt 1. De store is publiek, dus een vreemde kan hem
toevoegen en Evolu Relay installeren. Zijn Umbrel haalt de image dan uit
`sc.kamenier-hamer.nl` van de gebruiker. Dat gaat vandaag waarschijnlijk gewoon werken, en dat is
precies wat het een keuze maakt in plaats van een detail: je serveert dan images van je eigen server aan
onbekenden, en jouw uptime bepaalt of hun app installeert. Electrum Gate heeft dit niet, want die draait
op images uit Docker Hub.
2026-08-25 18:37:18 +02:00
Drie richtingen: laten zoals het is; `disabled: true` in het manifest zolang de image niet op een neutrale
plek staat (dat veld bestaat in het schema); of de image naar Docker Hub duwen en het probleem weghalen.
**Moment:** als fase 4 helemaal af is, dus als bewezen is dat er iets te delen valt · **Eigenaar:**
gebruiker
2. **Komt er een statuspagina?** - **beslist op 28-08-2026: ja, en achter de umbrelOS-inlog.** De
poortindeling gaat om: de pagina komt op de app-proxy mét inlog, de relay op een eigen gepubliceerde
poort waar Zoraxy naartoe wijst. Daarmee vervalt het bezwaar hieronder, want de pagina ligt dan wél
achter een grens. Zie [PLAN.md](PLAN.md) §4h.
Electrum Gate heeft er een en die bleek in de praktijk het nuttigste deel van die app. Hier zou dat
kunnen: draait de relay, hoe groot is de database, wanneer was de laatste synchronisatie, en is er een
eigenaar geregistreerd. Dat laatste is meer dan gemak, want het is precies waar het stil kan misgaan.
Ertegen: het is een eigen container en een eigen onderhoudslast, en het is geen voorwaarde om te kunnen
synchroniseren. Ervoor, en dat is nieuw sinds de samenvoeging van de repo's: de pagina en de agent van
Electrum Gate staan in dezelfde repo en zijn grotendeels over te nemen.
Let op één ding als het ervan komt: de app-proxy staat op `PROXY_AUTH_ADD: "false"`, dus een pagina zou
net zo onbeschermd zijn als de relay. Bij Electrum Gate zit de pagina juist wél achter de inlog. Dat
vraagt dan een tweede poort of een smalle whitelist.
**En dat weegt zwaarder dan het leek, want er zijn twee wegen naar binnen en de tweede is onzichtbaar
in de compose** (vastgesteld op 25-08-2026, nadat de gebruiker vroeg of deze app kwaad kon):
- **het thuisnetwerk.** De app-proxy publiceert `0.0.0.0:3851`, dus alle interfaces en niet alleen
localhost. Alles op het LAN kan bij de relay, zonder aanmelding;
- **Tor.** umbrelOS maakt per app een hidden service, en die stond bij de eerste installatie gewoon aan.
Zonder inlog betekent dat **bereikbaar vanaf het internet**, alleen beschermd doordat het
`.onion`-adres onraadbaar is. Te zien aan `~/umbrel/tor/data/app-<app-id>/hostname` en uit te zetten
in umbrelOS. De gebruiker zet hem uit.
Wat de schade in beide gevallen beperkt is een applicatiecontrole en geen netwerkgrens: de relay weigert
elke eigenaar zonder limietenrij. Dat is precies waarom een statuspagina hier een andere afweging is dan
bij Electrum Gate: die zou achter geen van beide grenzen liggen, en een statuspagina vertelt per definitie
iets over de machine waarop hij draait.
**De gebruiker wil hem, gezegd op 27-08-2026 in één adem met de kale relay en de limiter.** Twee dingen
die dat verandert. De pagina krijgt een taak die verder gaat dan status: hij toont welke eigenaar
toegelaten is en draagt de knop om die keuze te wissen (punt 8). En de afweging hierboven wordt
scherper, niet milder: de zin "wat de schade beperkt is een applicatiecontrole" gaat niet meer op zodra
de relay kaal is, want die controle is dan juist weg. Een pagina zonder inlog is dan het enige wat er
nog bij staat. **De tweede poort of de smalle whitelist is daarmee geen detail maar onderdeel van het
ontwerp.**
**Moment:** samen met de limiter uit punt 8, dus nadat de proef uit punt 6 geslaagd is ·
**Eigenaar:** gebruiker
3. **Wat doen we met de quota-manager als blijkt dat hij iets extern nodig heeft?**
Hij is meegepakketteerd omdat de relay zonder limietenrij niemand toelaat. Als het registreren van een
eigenaar een betaalprovider of een Notion-sleutel vraagt, klopt die keuze niet meer en wordt de tweede
weg uit [PLAN.md](PLAN.md) §4b weer actueel: de rij met de hand in de database zetten.
**Moment:** zodra **Proefopstelling** de registratievraag beantwoordt · **Eigenaar:** volgt uit dat plan
2026-08-28 11:49:15 +02:00
7. **Hoe positioneren we de app als het de generieke Evolu-relay wordt?** - **beslist op 28-08-2026 door
de gebruiker: helemaal generiek.** De app-tekst noemt Trezor niet meer, `category` gaat van `bitcoin`
naar `files`, en de pagina spreekt over "your app" in plaats van één cliënt. De onderbouwing komt van
Evolu zelf: local-first, end-to-end versleuteld, en een relay die alleen een `OwnerId`, tijdstempels en
gevulde blobs ziet.
**De tegenwerping hieronder is niet weerlegd maar geaccepteerd**, en dat hoort erbij: "Evolu Relay" zegt
een Umbrel-gebruiker niets, terwijl de labels van Trezor Suite een concrete reden zijn om te
installeren. Vindbaarheid inleveren is hier een keuze en geen vergissing. Blijkt het later te knellen,
dan is dit de plek om terug te lezen waarom.
Opgemerkt door de gebruiker op 25-08-2026, meteen na punt 6: verpakken we niet langer iets van Trezor maar
een relay van Evolu, dan hoeft de app-tekst niet meer over Trezor te gaan.
**Meevaller die dat goedkoop maakt:** de identiteit is al generiek. `id: whatsnext-evolu-relay` en
`name: Evolu Relay` kunnen blijven staan, en dat is niet niks, want een id-wijziging is voor umbrelOS een
andere app en dus een herinstallatie. Wat Trezor-specifiek is, is alleen de framing: `tagline`,
`description` en `category: bitcoin`.
Wat er verder mee vervalt: de licentievraag uit
[Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md) §4. Bij een gepubliceerde image
distribueren we niets van Trezor en bouwen we niets; er is geen `LICENSE.md` meer om je zorgen over te
maken. En **Publicatie-Relay** wordt een stuk plausibeler: een gepubliceerde upstream-image die je pint,
in plaats van een eigen image die je moet onderhouden.
**De tegenwerping hoort er wel bij, want breder is niet vanzelf beter.** "Evolu Relay" zegt een
Umbrel-gebruiker niets; "synchroniseer je Trezor Suite-labels via je eigen machine" is een reden om te
installeren. Wie hiernaar zoekt, zoekt op Trezor. Het voorstel is dus niet Trezor weglaten maar de
volgorde omdraaien: de concrete reden voorop, en erachter dat elke Evolu-app hem kan gebruiken. Dan
verlies je de vindbaarheid niet en beweer je ook niet dat dit een Trezor-product is.
Blijft over: `category`. `bitcoin` klopt bij de Trezor-lezing en niet bij de generieke. Voor de
vindbaarheid pleit `bitcoin` alsnog, want daar kijkt het publiek dat hier iets aan heeft.
**Moment:** zodra punt 6 gemeten is, en pas dan; bij een negatieve uitslag blijft de huidige tekst juist ·
**Eigenaar:** gebruiker
2026-08-25 18:37:18 +02:00
## Beslist
1. **Waar komt de image te staan?** - **het ingebouwde containerregister van de eigen Gitea**
(25-08-2026), als `sc.kamenier-hamer.nl/sysop/evolu-relay`.
Hier stond dat lokaal bouwen de eerste stap was en dat dit beslist zou worden "zodra lokaal niet meer
volstaat". Dat moment kwam dezelfde dag, en niet uit vrije keuze: **lokaal volstaat nooit.** umbreld haalt
élke image via de Docker Engine API op en niet via compose, dus een lokaal gebouwde tag is onbereikbaar en
de installatie faalt met `pull access denied` voordat er iets start. Met bron in
[Umbrel-appstore-spec.md](../../../Referenties/Umbrel-appstore-spec.md).
Waarom Gitea en niet Docker Hub: zelfde host als de store, geldig certificaat, geen nieuw account, en de
eigenaar `sysop` staat publiek zodat anoniem halen werkt. Dat laatste is gecontroleerd met een uitgelogde
pull, en daarna bewezen door de installatie zelf met de lokale images vooraf weggehaald.
Wat hiermee **niet** beslist is: Docker Hub blijft nodig zodra het de officiële store in gaat, en dan moet
er ook arm64 bij. Zie **Publicatie-Relay**. En lees dan eerst `LICENSE.md` van Trezor, dat door GitHub als
"other" geclassificeerd staat.
## Bewust uitgesteld
4. **`SERVER_ENV` op `prod` of `dev`?** - `prod`, tot het tegendeel gemeten is (25-08-2026).
`.env.sample` zegt dat prod authenticatie aanzet; in de code die gelezen is bepaalt die vlag alleen het
logniveau en staan de autorisatiecontroles onvoorwaardelijk aan. Eén van de twee is achterhaald.
`prod` is de veilige kant van die onduidelijkheid: als het iets aanzet, willen we dat het aanstaat. Maar
het is een gok tot het gemeten is, en het is met één keer starten te meten. Staat als taak in
**Proefopstelling** fase 2.
**Moment:** bij de eerste geslaagde start · **Eigenaar:** volgt uit Proefopstelling