diff --git a/Docs/CONTINUE_HERE.md b/Docs/CONTINUE_HERE.md index 9133a6f..a3b49a8 100644 --- a/Docs/CONTINUE_HERE.md +++ b/Docs/CONTINUE_HERE.md @@ -24,7 +24,7 @@ | Plan | App | Volgende stap | Status | |-|-|-|-| | [Umbrelapp](Plannen/Actief/008-Umbrelapp/TAKEN.md) | Relay | **0.7.1 bouwen, duwen en pinnen op de Umbrel. Eigenaar: gebruiker.** De compose staat op `evolu-relay:0.7.1` zónder digest, zodat een installatie hard faalt tot de image bestaat. **0.7.0 draait sinds 10-09-2026** en de wachtlijst is daar de enige weg naar binnen; 0.7.1 is wat een dag gebruiken opleverde, vier punten van de gebruiker over de twee eigenaarskaders. Eén ervan was meer dan een woordkeuze: een rij werd hoger op het moment dat je hem een naam gaf, en nu zijn alle rijen even hoog | 🔶 | -| [Testclient](Plannen/Actief/003-Testclient/TAKEN.md) | Relay | **Wacht op 0.7.0 op het apparaat.** De cliënt is af en werkt: register, negen opdrachten, een bedieningsvlak op `127.0.0.1:4380` met `Start.bat` en `Start.command`, en `test` die de HTTP-status van de WebSocket-upgrade toont. De eerste proef is geslaagd: een onbekende eigenaar krijgt 401 over `wss://` via de reverse proxy, en dat stond tot dan alleen als redenering in `Upstream-evolu-relay.md` §10. De rest van fase 4 vraagt een relay die eigenaars toelaat. Uitkomst die het meeste stuurt: `@evolu/nodejs` bevat géén cliënt, dus de afhankelijkheden voor `createEvolu` worden zelf samengesteld; de valstrikken staan in `PLAN.md` §4e | 🔶 | +| [Testclient](Plannen/Actief/003-Testclient/TAKEN.md) | Relay | **Wacht niet meer: 0.7.0 draait sinds 10-09-2026, dus fase 4 kan af.** De drie resterende proeven vragen om en om een handeling op de statuspagina en een ronde met de cliënt. Op 10-09-2026 opgelost: losmaken maakte niets los, want de socket zit in de gedeelde worker en een transport uit de config van `createEvolu` is nergens op te zeggen; nu gaat hij erin met `evolu.useOwner`. De cliënt is af en werkt: register, negen opdrachten, een bedieningsvlak op `127.0.0.1:4380` met `Start.bat` en `Start.command`, en `test` die de HTTP-status van de WebSocket-upgrade toont. De eerste proef is geslaagd: een onbekende eigenaar krijgt 401 over `wss://` via de reverse proxy, en dat stond tot dan alleen als redenering in `Upstream-evolu-relay.md` §10. De rest van fase 4 vraagt een relay die eigenaars toelaat. Uitkomst die het meeste stuurt: `@evolu/nodejs` bevat géén cliënt, dus de afhankelijkheden voor `createEvolu` worden zelf samengesteld; de valstrikken staan in `PLAN.md` §4e | 🔶 | ## B - Los oppakbaar (geen blokkade, geen vaste volgorde) diff --git a/Docs/Plannen/Actief/003-Testclient/PROGRESS.md b/Docs/Plannen/Actief/003-Testclient/PROGRESS.md index 8253c61..a35680b 100644 --- a/Docs/Plannen/Actief/003-Testclient/PROGRESS.md +++ b/Docs/Plannen/Actief/003-Testclient/PROGRESS.md @@ -1,5 +1,24 @@ # Voortgang - Testclient +## 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. + ## 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 diff --git a/Docs/Plannen/Actief/003-Testclient/TAKEN.md b/Docs/Plannen/Actief/003-Testclient/TAKEN.md index d2a31f8..f8a2924 100644 --- a/Docs/Plannen/Actief/003-Testclient/TAKEN.md +++ b/Docs/Plannen/Actief/003-Testclient/TAKEN.md @@ -12,6 +12,15 @@ ## Volgende stap +- [ ] **Fase 4 afmaken, nu 0.7.0 op het apparaat draait.** De wachtlijst is daar de enige weg naar binnen, + dus de drie proeven die een toegelaten eigenaar nodig hebben kunnen. Ze vragen om en om een handeling + van de gebruiker op de statuspagina en een ronde met de cliënt +- [x] **Losmaken maakte niets los (10-09-2026).** Gemeld door de gebruiker: een eigenaar uit het register + halen liet de relay hem zien tot het proces stopte. De socket zit in de gedeelde worker, niet in de + instantie, en een transport uit de config van `createEvolu` is nergens meer op te zeggen. Nu start de + instantie met `transports: []` en gaat de transport erin met `evolu.useOwner`, die een opzegging + teruggeeft. Bewezen tegen een relay op localhost: met de oude vorm bleven het 2 verbindingen na het + sluiten van de ene eigenaar, met de nieuwe 1 - [ ] **De logregels van de relay-container lezen, want daar zit het antwoord op [OPEN.md](OPEN.md) punt 9.** Twee eigenaars die toegelaten waren zijn uit de allowlist verdwenen, en de cliënt kan niet zien waarom. Gezocht wordt naar `learned a new owner`, `owners.json was unreadable`, `refused a write of diff --git a/tools/relay-client/src/client.js b/tools/relay-client/src/client.js index 6ea1bad..45e31d7 100644 --- a/tools/relay-client/src/client.js +++ b/tools/relay-client/src/client.js @@ -179,8 +179,20 @@ export const openStore = async ({ ? [createOwnerWebSocketTransport({ url: relayUrl, ownerId: owner.id })] : []; + // De instantie start ZONDER sync en de transport gaat er daarna met `useOwner` + // in, ook al is het de eigen appOwner. Dat is geen omweg maar het enige wat + // losmaken werkelijk losmaakt. + // + // Waarom: de socket zit niet in deze instantie maar in de gedeelde worker, en + // die blijft staan zolang er nog één store open is (zie `gedeeld` bovenaan). + // Een transport die je in de config meegeeft, kun je daarna nergens meer + // opzeggen; het gevolg was dat de relay een eigenaar bleef zien nadat je hem + // in de cliënt had losgekoppeld of zelfs vergeten, tot je het proces stopte. + // Gemeld door de gebruiker op 10-09-2026. `useOwner` geeft een opzegging terug + // en Evolu telt de verwijzingen naar een transport, dus de laatste opzegging + // sluit de socket. const uitkomst = await run( - createEvolu(Schema, { appName: APP_NAME, appOwner: owner, transports }), + createEvolu(Schema, { appName: APP_NAME, appOwner: owner, transports: [] }), ); if (!uitkomst.ok) { @@ -193,6 +205,9 @@ export const openStore = async ({ const evolu = uitkomst.value; + // `useOwner` eist een niet-lege lijst, dus alleen als er een relay is. + let zegSyncOp = transports.length > 0 ? evolu.useOwner(owner, transports) : null; + return { ownerId: owner.id, /** De URL waarmee verbonden wordt, of null bij een instantie zonder sync. */ @@ -228,6 +243,12 @@ export const openStore = async ({ * de uitleg bovenaan bij `gedeeld`. */ sluit: async () => { + // Eerst de sync opzeggen en dan de run weggooien. Andersom is de instantie + // al weg als de opzegging aankomt. + if (zegSyncOp) { + zegSyncOp(); + zegSyncOp = null; + } await run[Symbol.asyncDispose](); if (onDefect) defectMelders.delete(onDefect); if (onWebSocket) socketMelders.delete(onWebSocket);