2026-09-09 12:59:55 +02:00
|
|
|
# Voortgang - Testclient
|
|
|
|
|
|
2026-09-10 09:55:05 +02:00
|
|
|
## 10-09-2026 - losmaken maakte niets los
|
|
|
|
|
|
|
|
|
|
Gemeld door de gebruiker: hij haalde een eigenaar uit het register, de rij verdween uit het bedieningsvlak,
|
|
|
|
|
en de relay bleef hem zien tot het proces stopte. Dat was geen vergissing in `vergeet`: die koppelt netjes
|
|
|
|
|
af. De socket zit niet in de Evolu-instantie maar in de gedeelde worker, en die blijft staan zolang er nog
|
|
|
|
|
één eigenaar open is. Een transport dat je in de config van `createEvolu` meegeeft, kun je daarna nergens
|
|
|
|
|
meer opzeggen.
|
|
|
|
|
|
|
|
|
|
De uitweg staat in de API zelf: `createEvolu` starten met `transports: []` en de transport erna met
|
|
|
|
|
`evolu.useOwner` erin zetten, ook al is het de eigen appOwner. Die geeft een opzegging terug en Evolu telt
|
|
|
|
|
de verwijzingen, dus de laatste opzegging sluit de socket werkelijk.
|
|
|
|
|
|
|
|
|
|
**Bewezen met een wegwerpproef tegen een relay op localhost die iedereen toelaat, want tegen de echte relay
|
|
|
|
|
is er niets te meten:** een geweigerde eigenaar levert nauwelijks verkeer op. Twee eigenaars open, dan de
|
|
|
|
|
ene sluiten. De maat is de verbindingstabel van het besturingssysteem en niet de `dicht`-melding van de
|
|
|
|
|
cliënt: `closeSocket` in `@evolu/common` zet `socket.onclose` op null vóórdat het sluit, dus een sluiting
|
|
|
|
|
die je zelf veroorzaakt meldt zichzelf nooit. Met de oude vorm bleven het 2 verbindingen, met de nieuwe
|
|
|
|
|
werd het 1, en de andere eigenaar kon daarna nog schrijven.
|
|
|
|
|
|
2026-09-09 12:59:55 +02:00
|
|
|
## 09-09-2026 - plan geschreven, gepromoveerd, en de samenstelling werkt
|
|
|
|
|
|
|
|
|
|
Het masterplan is geschreven en dezelfde dag gepromoveerd naar `Actief/003-Testclient/`, op verzoek van de
|
|
|
|
|
gebruiker. Bij het schrijven ging §4b eerst over de verkeerde vraag: "alles vanuit één scherm" werd gelezen
|
|
|
|
|
als een scherm over cliënt én relay. De server-app blijft ongemoeid en synchroniseert met Trezor Suite op
|
|
|
|
|
de Mac, dus dat is herschreven naar wat het scherm zelf doet.
|
|
|
|
|
|
|
|
|
|
Fase 1 is af, en dat was de stap waarvan het plan zei dat hij eerst moest. **`@evolu/nodejs` bevat geen
|
|
|
|
|
cliënt**, alleen de relay plus losse bouwstenen; `createEvolu` krijgt zijn afhankelijkheden nu uit
|
|
|
|
|
`tools/relay-client/src/evolu-node.js`, samengesteld uit de in-memory workers van `@evolu/common`. Vier
|
|
|
|
|
dingen zaten in de weg, alle vier stil falend: de ontbrekende `installPolyfills()` (Node 24 mist
|
|
|
|
|
`Map.getOrInsertComputed`), `createEvoluDeps` overslaan ("Expected tab leader port."), de
|
|
|
|
|
AsyncDisposableStack van `initSharedWorker` laten vallen, en workers zonder eigen `reportDefect`. Dat
|
|
|
|
|
laatste is waarom de andere drie te vinden waren; zonder dat zegt elke fout hetzelfde en noemt geen oorzaak.
|
|
|
|
|
|
|
|
|
|
Bewezen met een wegwerpproef: eigenaar aanmaken, `transports: []`, een rij met een `Uint8Array`-kolom
|
|
|
|
|
wegschrijven en teruglezen. De bytes komen er ongeschonden uit en het proces sluit schoon af.
|
|
|
|
|
|
|
|
|
|
**Nog niet geprobeerd: praten met de relay.** Daar is het adres van de Umbrel voor nodig en dat komt van de
|
|
|
|
|
gebruiker; het gaat niet in deze publieke repo.
|
2026-09-09 13:39:47 +02:00
|
|
|
|
|
|
|
|
## 09-09-2026 - de cliënt staat: opdrachtregel, bedieningsvlak en twee starters
|
|
|
|
|
|
|
|
|
|
Fase 2, 3 en 5 in één sessie. Er is een register (`owners.json` met naam, mnemonic en `OwnerId`), een
|
|
|
|
|
opdrachtregel met acht opdrachten, en een bedieningsvlak op `http://127.0.0.1:4380` met per eigenaar de
|
|
|
|
|
knoppen uit `PLAN.md` §4b. `Start.bat` en `Start.command` erbij op verzoek van de gebruiker: die draaien
|
|
|
|
|
`npm install` als het nodig is, waarschuwen als `.env` ontbreekt en openen de browser.
|
|
|
|
|
|
|
|
|
|
`OPEN.md` punt 1 is opgelost voordat het een probleem werd. `src/probe.js` doet de WebSocket-upgrade met
|
|
|
|
|
`node:http` in plaats van met de WebSocket van Node, want die laatste geeft je bij een weigering een
|
|
|
|
|
`error` en geen statuscode. De opdracht `klop` en de knop "Aankloppen" tonen dus 101 of 401.
|
|
|
|
|
|
|
|
|
|
Twee echte fouten gevonden en vastgezet in een toets. De eerste: de databasemap werd niet aangemaakt, en
|
|
|
|
|
omdat better-sqlite3 dat in een worker meldt was het symptoom een `lees` die nooit antwoordde. De tweede,
|
|
|
|
|
en die is er een om te onthouden: **`evolu.insert` geeft meteen een id terug en zet de schrijfactie in de
|
|
|
|
|
wachtrij van de worker**, dus wie vlak daarna afsluit is de rij kwijt. Het symptoom was een `lees` die
|
|
|
|
|
"nog geen blobs" meldde over een blob die zojuist bevestigd was. `schrijf` wacht nu op een query erachter,
|
|
|
|
|
en de toets sluit af en heropent.
|
|
|
|
|
|
|
|
|
|
In de browser nagekeken: een blob schrijven en teruglezen werkt vanuit de pagina, de gegevens zijn dezelfde
|
|
|
|
|
als die van de opdrachtregel, en licht en donker kloppen allebei.
|
|
|
|
|
|
|
|
|
|
**Wat er nu ligt te wachten is één regel in `.env`.** Alles wat de relay raakt is gebouwd en niets ervan is
|
|
|
|
|
beproefd, en dat blijft zo tot het adres er is.
|
2026-09-09 13:59:24 +02:00
|
|
|
|
|
|
|
|
## 09-09-2026 - de eerste proef, en hij slaagde
|
|
|
|
|
|
|
|
|
|
De gebruiker vulde `.env` in en de eerste poging faalde met `ECONNREFUSED`, op een adres van de vorm
|
|
|
|
|
`wss://host:3852`. Dat is een tegenstrijdigheid: poort 3852 is waar de relay zelf luistert in plat ws
|
|
|
|
|
binnen het netwerk, terwijl het certificaat op de reverse proxy zit en die op 443 luistert. Zonder poort
|
|
|
|
|
werkt het, en die valstrik staat nu in `.env.sample`.
|
|
|
|
|
|
|
|
|
|
**Daarmee is de eerste proef uit `PLAN.md` §4c gedaan, en hij bevestigt wat er tot nu toe alleen beredeneerd
|
|
|
|
|
was:** twee onbekende eigenaars krijgen allebei HTTP 401 op de WebSocket-upgrade. Zie §10 van
|
|
|
|
|
[Upstream-evolu-relay.md](../../../Referenties/Upstream-evolu-relay.md), waar dat uit de broncode was
|
|
|
|
|
afgeleid. Gratis erbij bewezen: de reverse proxy laat de WebSocket-upgrade door en het certificaat klopt,
|
|
|
|
|
dus de relay is over `wss://` bruikbaar. Dat raakt het masterplan **Bereikbaarheid**.
|
|
|
|
|
|
|
|
|
|
Wat deze cliënt niet kan zien, en dus bij de gebruiker ligt: staan die twee eigenaars in de weigerlijst op
|
|
|
|
|
de statuspagina van de app?
|
2026-09-09 14:15:09 +02:00
|
|
|
|
|
|
|
|
## 09-09-2026 - een eigen fout, en daarna een vraag aan de relay
|
|
|
|
|
|
|
|
|
|
De gebruiker liet beide eigenaars toe en kreeg meteen een defect op de tweede: "Expected tab leader port.".
|
|
|
|
|
**Een fout van ons, en precies de valstrik die in `PLAN.md` §4e als nummer 2 staat opgeschreven.**
|
|
|
|
|
`createEvoluDeps` vraagt via `navigator.locks` het slot "tab" aan en kondigt de houder aan als tab leader;
|
|
|
|
|
dat slot kan er maar één hebben. `openStore` maakte per eigenaar een eigen stel afhankelijkheden, dus de
|
|
|
|
|
tweede werd nooit leider. In een browser is dit vanzelf goed: daar is er één tabblad met één gedeelde
|
|
|
|
|
worker. Nu één stel per proces, met een teller zodat het pas opgeruimd wordt als de laatste store sluit,
|
|
|
|
|
en een toets met twee eigenaars tegelijk die de fout terugbrengt zodra iemand dat ongedaan maakt.
|
|
|
|
|
|
|
|
|
|
Daarna bleek er niets te synchroniseren. Twee dingen erbij gebouwd om dat überhaupt te kúnnen zien:
|
|
|
|
|
|
|
|
|
|
- **`spiegel <naam>`** opent dezelfde eigenaar in een lege database naast de bestaande. Alles wat daar
|
|
|
|
|
binnenkomt heeft de heenreis en de terugreis over de relay gemaakt, en dat is de enige manier waarop de
|
|
|
|
|
cliëntkant kan bewijzen dat er werkelijk iets op de relay staat. `lees` toont je namelijk altijd je eigen
|
|
|
|
|
rijen, ook als de relay ze nooit gezien heeft;
|
|
|
|
|
- **een luikje op de WebSocket** (`onWebSocket`), dat meldt welke URL er geopend wordt en wat ermee
|
|
|
|
|
gebeurt. Zonder dat ziet een relay die de socket dichtgooit er hetzelfde uit als een relay die traag is:
|
|
|
|
|
Evolu probeert het gewoon opnieuw.
|
|
|
|
|
|
|
|
|
|
Dat luikje gaf het antwoord in één keer: de socket komt nooit open, `WebSocketConnectError` en sluitcode
|
|
|
|
|
1006, in een herhaallus. Met het `ws`-pakket ernaast gelegd staat er wat de globale WebSocket verzwijgt:
|
|
|
|
|
**HTTP 401.** En `klop` zegt dat inmiddels ook, voor allebei de eigenaars, terwijl diezelfde opdracht
|
|
|
|
|
kort daarvoor nog twee keer 101 gaf.
|
|
|
|
|
|
|
|
|
|
**Daarmee ligt de vraag bij de relay en niet meer bij de cliënt: twee eigenaars die toegelaten waren zijn
|
|
|
|
|
uit de allowlist verdwenen.** Wat er op de statuspagina van staat is "turned away". Wat dit kan zijn staat
|
2026-09-09 14:20:22 +02:00
|
|
|
in [OPEN.md](OPEN.md) punt 9; het antwoord zit in de logregels van de relay-container en die kan alleen de
|
2026-09-09 14:15:09 +02:00
|
|
|
gebruiker lezen.
|
2026-09-09 14:20:22 +02:00
|
|
|
|
|
|
|
|
## 09-09-2026 - "Aankloppen" heet nu "Testen", en een weigering stopt de lus
|
|
|
|
|
|
|
|
|
|
Voorstel van de gebruiker, en het tweede deel loste meer op dan een knop. Een verbinding die geweigerd
|
|
|
|
|
wordt bleef namelijk eindeloos opnieuw proberen, en élke poging is een regel in de weigerlijst van de
|
|
|
|
|
relay; dat is precies hoe die lijst tijdens deze sessie volliep. Drie wijzigingen:
|
|
|
|
|
|
|
|
|
|
- **de naam.** `klop` heet `test` op de opdrachtregel en "Testen" op de pagina. Het verschil met verbinden
|
|
|
|
|
staat er nu ook uitgelegd: testen is één vraag met een statuscode als antwoord, verbinden is een gesprek
|
|
|
|
|
dat Evolu eindeloos blijft herstellen;
|
|
|
|
|
- **"Verbinden" gaat uit zodra een test zegt dat de eigenaar geweigerd wordt**, met de uitkomst in het rood
|
|
|
|
|
naast de naam. Onbekend telt als toegestaan, en dat is met opzet: eerst moeten testen om iets te mogen zou
|
|
|
|
|
betekenen dat je altijd een poging in de weigerlijst zet voordat je iets kunt doen. "Blob schrijven" gaat
|
|
|
|
|
door dezelfde poort en schrijft dan lokaal verder;
|
|
|
|
|
- **een lopende verbinding stopt zichzelf.** Na drie mislukte sockets wordt er precies één keer getest; is
|
|
|
|
|
het een weigering, dan gaat de verbinding eruit. Is het geen weigering, dan blijft hij staan, want dan is
|
|
|
|
|
het een relay die even weg is en daar is opnieuw proberen juist goed voor.
|
|
|
|
|
|
|
|
|
|
De melding in een dialoogvenster is eruit: de uitkomst staat naast de naam en in het log, en die blijven
|
|
|
|
|
staan. In de browser nagekeken: testen geeft 401, de regel verschijnt in het rood, en "Verbinden" is
|
|
|
|
|
uitgegrijsd voor de geteste eigenaar terwijl de ongeteste hem gewoon houdt.
|