Rechtgezet op aanwijzing van de gebruiker; ik had aangenomen dat overal hetzelfde veld gebruikt was. Het maakt de conclusie sterker in plaats van zwakker: op iOS is juist de ondersteunde weg genomen en er gebeurde nog steeds niets, dus valt de verklaring 'verkeerd veld' af en blijft die uit open punt 9 over. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
407 lines
25 KiB
Markdown
407 lines
25 KiB
Markdown
# Upstream: `trezor/trezor-suite-sync` en Evolu Relay
|
|
|
|
Naslag, geen plan. **Nagetrokken tegen de bron op 25-08-2026**, met de URL's onderaan. Dat is een andere
|
|
status dan de eerste versie van dit document had: die leunde op vooronderzoek van dezelfde dag en meldde
|
|
per regel dat het niet geverifieerd was. Wat hieronder staat komt uit de bestanden zelf.
|
|
|
|
Op drie punten week de werkelijkheid af van het vooronderzoek, en alle drie raken het pakket. Ze staan in
|
|
§2, §3 en §4.
|
|
|
|
## 0. Let op: er zijn twee relays, en wij pakketteerden de zware
|
|
|
|
**Toegevoegd 25-08-2026, aan het eind van de dag, nadat de gebruiker
|
|
[evolu.dev/docs/relay](https://www.evolu.dev/docs/relay) aandroeg.** Dit staat bovenaan omdat het de rest
|
|
van dit document in een ander licht zet.
|
|
|
|
**Evolu is een eigen project** (`evoluhq/evolu`) en heeft een eigen relay. `trezor/trezor-suite-sync` is
|
|
niet dat project maar Trezor's **inzet** ervan, met een eigen opslaglaag en de quota-manager eromheen. Het
|
|
verschil is groot:
|
|
|
|
| | Evolu, `apps/relay` | Trezor, `trezor-suite-sync` |
|
|
|-|-|-|
|
|
| Containers | één | drie: relay, quota-manager, Postgres |
|
|
| Image | **gepubliceerd**: `docker.io/evoluhq/relay:latest` | geen; eigen Amazon ECR, dus zelf bouwen |
|
|
| Opslag | een datavolume op `/app/data`; de documentatie noemt de relay **stateless** en geschikt voor serverless | Postgres |
|
|
| Toegangscontrole | niets over gedocumenteerd | eigenaar zonder limietenrij wordt geweigerd |
|
|
| Poort | 4000, `ws://` | 4000 |
|
|
|
|
**De vraag die hieruit volgt is de belangrijkste die dit project nu heeft: praat Trezor Suite met een kale
|
|
Evolu-relay?** Zo ja, dan vervalt vrijwel alles wat dit pakket ingewikkeld maakt: geen bouwstap, geen eigen
|
|
register, geen onderhoudsplicht op een image, geen Postgres, geen wachtwoord, en vooral geen
|
|
eigenaarsregistratie, wat nu de blokkade is.
|
|
|
|
### Wat de cliëntkant zegt, en dat is beslissend
|
|
|
|
Nagelezen in de broncode van Trezor Suite zelf, die lokaal staat; zie §7. Drie bevindingen, en de tweede is
|
|
de belangrijkste van dit hele document.
|
|
|
|
**1. Suite kan naar een eigen relay wijzen, en het zijn twee losse adressen.** In de instellingen onder
|
|
**dev-utils** staan een relay-URL en een quota-manager-URL, elk met een eigen opslaan-knop. De e2e-test van
|
|
de mobiele app vult ze met `http://10.0.2.2:4000` en `http://10.0.2.2:4001`, dus **`http://` volstaat** en
|
|
de poorten zijn precies die van ons. Het aanzetten van de synchronisatie vraagt daarna een bevestiging op
|
|
het Trezor-apparaat zelf.
|
|
|
|
**2. Met een eigen relay-URL negeert Suite de quota-manager volledig.** Letterlijk, uit
|
|
`suite-common/suite-sync-quota-manager/src/createSuiteSyncQuotaManagerCompositionRoot.ts`:
|
|
|
|
```ts
|
|
// We only want to use QM for our own relay servers. In case custom URL has been set, QM is ignored,
|
|
// unless enforceQuotaManager is set (used for e2e tests with a local relay).
|
|
const getIsQuotaManagerEnabled = () =>
|
|
deps.getIsUsingTrezorRelay() || selectEnforceQuotaManager(deps.getState());
|
|
```
|
|
|
|
`enforceQuotaManager` staat standaard op `false` en bestaat voor hun eigen e2e-tests.
|
|
|
|
**Dat is een klem, en hij zit in Trezor's relay en niet in ons pakket.** De cliënt registreert geen eigenaar
|
|
zodra je een eigen relay gebruikt, maar de relay van Trezor blijft `isOwnerAllowed()` doen en weigert
|
|
iedereen zonder limietenrij (§3). Die rij komt er dus nooit, want het enige dat hem zou maken wordt door de
|
|
cliënt overgeslagen. **Trezor's relay is daarmee als zelf-gehoste relay in de kern onbruikbaar**, tenzij je
|
|
de rij met de hand in de database zet of de quota-manager buitenom aanroept.
|
|
|
|
**3. En dat maakt de kale Evolu-relay niet alleen eenvoudiger maar waarschijnlijk de enige die werkt.** Daar
|
|
is geen limietentabel en geen eigenaarscontrole, en de cliënt wil sowieso geen quota-manager bij een eigen
|
|
relay. De twee kanten passen op elkaar.
|
|
|
|
**Wat nog steeds gemeten moet worden**, want dit is redeneren uit code en geen proef: of de protocolversie
|
|
klopt. 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. Dat is nu het enige echte risico, en het is
|
|
in minuten te weerleggen: `docker run --rm -p 4000:4000 docker.io/evoluhq/relay:latest`, Suite ernaartoe
|
|
wijzen, label maken.
|
|
|
|
**4. De relay-URL bevat een pad, en de cliënt gebruikt hem letterlijk.** Toegevoegd 28-08-2026 uit
|
|
`suite-common/suite-sync/src/relay/relayUrl.test.ts`. Hun eigen standaardwaarden zijn
|
|
`https://suite-sync.trezor.io/evolu/` en lokaal `http://127.0.0.1:4000/evolu/`: de relay van Trezor hangt
|
|
dus achter een pad, en een eigen URL wordt overgenomen zoals hij is. De kale Evolu-relay luistert op de
|
|
wortel; dat is gemeten met `http://10.0.0.11:4000` zonder pad.
|
|
|
|
**Dat opent een goedkope toegangscontrole die in geen van de drie wegen van Bereikbaarheid §4b stond:** een
|
|
onraadbaar pad in de URL, afgedwongen door de reverse proxy die er toch al staat. Geen eigen image, geen
|
|
regel code.
|
|
|
|
**En het verklaart de foutmelding op iOS.** De URL wordt gevalideerd met een `.url()`-regel uit yup
|
|
(`relayServerSettings.ts`), en die accepteert `ws://` niet. "Enter a valid url" ging dus over het schema en
|
|
niet over het adres.
|
|
|
|
**5. Eén `OwnerId` per wallet, niet per apparaat en niet per installatie.** Toegevoegd 28-08-2026, nadat er
|
|
op de eigen relay tot verrassing twéé eigenaars verschenen.
|
|
|
|
De eigenaar komt van het apparaat zelf: `createRetrieveSuiteSyncOwner.ts` roept
|
|
`trezorConnect.evoluGetNode` aan met een proof of delegated identity onder de header `EvoluGetNode`. De
|
|
afleiding gebeurt dus op de Trezor. `createEnsureSuiteSyncOwner.ts` bewaart het resultaat vervolgens per
|
|
**`device.state.staticSessionId`**, en dat is in Suite een *device state*: een wachtwoordzin geeft een
|
|
andere state.
|
|
|
|
Wat daaruit volgt en wat makkelijk verkeerd gedacht wordt:
|
|
|
|
- **twee installaties met dezelfde Trezor en dezelfde wallet komen op dezelfde `OwnerId` uit.** Dat is wat
|
|
synchroniseren tussen apparaten mogelijk maakt zonder dat die apparaten elkaar kennen, en het betekent
|
|
dat een tweede apparaat géén nieuwe eigenaar oplevert;
|
|
- **meer dan één `OwnerId` betekent meer dan één wallet**, bijvoorbeeld een verborgen wallet achter een
|
|
wachtwoordzin. Niet meer dan één app.
|
|
|
|
Voor een relay met een eigenaars-allowlist is dat bepalend: het aantal eigenaars dat je toelaat is het
|
|
aantal wallets dat je synchroniseert. "De eerste eigenaar die verbindt" is dus te smal zodra iemand een
|
|
tweede wallet gebruikt, en dat is op 28-08-2026 meteen gebeurd.
|
|
|
|
Dat het huidige pakket de zware variant bevat is geen fout maar het gevolg van de volgorde waarin het
|
|
gevonden is: de laag van Trezor was eerder zichtbaar dan de laag eronder.
|
|
|
|
## 1. Wat het is
|
|
|
|
Trezor Suite kan labels en accountnamen synchroniseren tussen apparaten. De server die dat doet heet in de
|
|
interface "custom sync server"; het onderdeel zelf heet **Evolu Relay** en staat in de repo
|
|
`trezor/trezor-suite-sync` (standaardbranch `main`, licentie in `LICENSE.md`, door GitHub geclassificeerd
|
|
als "other").
|
|
|
|
Evolu is een local-first synchronisatielaag: de client houdt zijn eigen kopie bij en de relay is een
|
|
doorgeefluik voor versleutelde wijzigingen. Volgens Trezor is de data client-side end-to-end versleuteld,
|
|
dus de relay ziet niets leesbaars. **Zelf hosten haalt Trezor uit de vergelijking, het verandert de
|
|
privacygaranties niet.**
|
|
|
|
## 1b. Wat een relay is, wat hij ziet, en waarom hij niets hoeft te vertrouwen
|
|
|
|
Uitgezocht op 25-08-2026 op de vraag van de gebruiker of iemand met kennis van de API de labels kan
|
|
opvragen als de relay op een domein staat. Bronnen: [evolu.dev/docs/privacy](https://www.evolu.dev/docs/privacy),
|
|
[Owner](https://www.evolu.dev/docs/api-reference/common/local-first/Owner) en
|
|
[Protocol](https://www.evolu.dev/docs/api-reference/common/local-first/Protocol).
|
|
|
|
**Het is geen key-value-store.** De cliënt houdt zijn eigen SQLite bij; de relay bewaart versleutelde
|
|
CRDT-berichten per eigenaar en helpt twee kanten met range-based set reconciliation uitzoeken wat ze
|
|
allebei al hebben. Dichter bij een append-only berichtenlog dan bij een sleutel-waardetabel.
|
|
|
|
**Wat de relay ziet:** een `OwnerId`, tijdstempels, IP-adressen, en versleutelde blobs die gevuld zijn om
|
|
hun omvang te verhullen. Meer niet.
|
|
|
|
**Drie waarden, met SLIP-21 afgeleid uit één `OwnerSecret`:**
|
|
|
|
| Waarde | Wat het doet |
|
|
|-|-|
|
|
| `OwnerId` | de **publieke** identificatie |
|
|
| `OwnerEncryptionKey` | ontsleutelt de data |
|
|
| `OwnerWriteKey` | rotatable token dat schrijven autoriseert; zonder is een cliënt `ReadonlyOwner` |
|
|
|
|
**Het antwoord op de vraag is dus nee**, en de reden is scherper dan "het is versleuteld". De `OwnerId` is
|
|
expres niet geheim: hij gaat onversleuteld naar de relay en de beheerder ziet hem. De beveiliging leunt er
|
|
niet op dat niemand hem kent. Dat is het tegenovergestelde van een systeem waar een onraadbare URL de grens
|
|
is, en het is precies waarom je deze relay bij een onbekende partij kunt neerzetten.
|
|
|
|
Dat de drie waarden **onafhankelijk** zijn, is wat dat mogelijk maakt: je geeft de relay je identiteit
|
|
zonder iets over je sleutel prijs te geven, en je kunt de write key roteren zonder je identiteit te
|
|
verliezen. De protocol-documentatie zegt dat de write key gecontroleerd wordt **vóór** het verwerken van
|
|
berichten.
|
|
|
|
**Twee dingen die hier níet uit volgen, en die je niet moet gladstrijken:**
|
|
|
|
1. **Of iemand die een `OwnerId` kent de versleutelde blobs kan ophálen, staat nergens.** De
|
|
protocolpagina zwijgt erover. Kan het, dan leert zo iemand dat die eigenaar bestaat, wanneer hij actief
|
|
is en bij benadering hoeveel data er is. Niet de inhoud.
|
|
2. **Onraadbaarheid van de `OwnerId` beschermt tegen aflopen van de relay, niet tegen lezen.** Het is
|
|
verkeersbescherming en geen vertrouwelijkheid.
|
|
|
|
**En het echte risico van een publieke relay is een ander dan vertrouwelijkheid: misbruik als opslag.** Een
|
|
kale Evolu-relay kent geen accounts en geen toegangscontrole, dus iedereen kan een eigen owner aanmaken en
|
|
hem als gratis versleutelde opslag gebruiken. Je schijf groeit en je kunt niet zien van wie het is, want
|
|
dat is nu juist het ontwerp. Dit verklaart met terugwerkende kracht waarom Trezor een quota-manager heeft:
|
|
die is niet alleen voor facturering maar ook hun misbruikbeheersing. Wie hem eruit haalt, haalt die tweede
|
|
functie mee weg. Zie het masterplan **Bereikbaarheid**.
|
|
|
|
## 2. Eén codebase, vier processen, en een compose die de app niet draait
|
|
|
|
**Correctie op het vooronderzoek.** Daar stond dat er een `Dockerfile` en een `docker-compose.yaml` in de
|
|
repo staan en dat containeriseren dus "al gedeeltelijk gedaan is door Trezor zelf". Het eerste klopt, het
|
|
tweede niet: **de compose van Trezor draait de relay niet.** Er staan precies twee diensten in, en dat is
|
|
een ontwikkelopstelling:
|
|
|
|
- `db`: `image: postgres`, ongepind, met `PGDATA: /data/postgres` en `5432:5432` naar buiten;
|
|
- `prometheus`: `network_mode: host`, die `localhost:4003` afloopt.
|
|
|
|
De README bevestigt de bedoeling: `docker compose up` in de ene terminal voor de database, en in de andere
|
|
`yarn start-quota-manager`, `yarn start-evolu-relay` en `yarn start-metrics`. Wat Trezor zélf uitrolt staat
|
|
niet in de compose maar in `.k8s/`, met Kustomize-overlays voor dev en prod.
|
|
|
|
**Alle processen komen uit dezelfde codebase en dus uit dezelfde image.** Dat is de belangrijkste
|
|
pakketteerwinst van dit hele onderzoek: je hebt geen drie images nodig, maar één image met per service een
|
|
ander `command`. De `Dockerfile` is `node:24-alpine`, twee fasen, Yarn 4.12.0, met `EXPOSE 4000 4001` en
|
|
`CMD ["yarn", "start"]`. Bij dat `CMD` staat bovenstrooms zelf een commentaar dat het misschien
|
|
`start-quota-manager` of `start-evolu-relay` had moeten zijn, dus reken er niet op dat `yarn start` het
|
|
juiste doet; zet het commando expliciet.
|
|
|
|
De poorten, met hun standaardwaarde uit `src/config.ts`:
|
|
|
|
| Proces | Poort | Waarvoor |
|
|
|-|-|-|
|
|
| evolu-relay | 4000 | de sync-relay, dit is wat we nodig hebben |
|
|
| quota-manager | 4001 | quota- en betaalserver |
|
|
| health | 4002 | statuscontrole |
|
|
| metrics | 4003 | Prometheus |
|
|
|
|
In `.env.sample` staan ze alle vier uitgecommentarieerd, dus de standaardwaarden gelden tenzij je ze zet.
|
|
`DATA_DIR` heeft standaard de waarde `data`.
|
|
|
|
## 3. Is de quota-manager verplicht? Ja, in de praktijk wel
|
|
|
|
**Dit is de vraag waar het vooronderzoek op hoopte dat het antwoord nee zou zijn.** Dat is het niet, en de
|
|
reden is preciezer dan "de relay heeft de quota-manager nodig".
|
|
|
|
De relay bevat twee controles, in `src/evoluRelay/createEvoluRelay.ts`:
|
|
|
|
- **`isOwnerAllowed()`** vraagt `getLimitsForOwner({ ownerId })` op en staat de eigenaar alleen toe als daar
|
|
iets terugkomt dat niet leeg is;
|
|
- **`isOwnerWithinQuota()`** controleert bij schrijven of `usedBytes + requiredBytes` binnen de limiet
|
|
blijft.
|
|
|
|
De strekking: **een eigenaar zonder rij in de limietentabel wordt geweigerd.** En de quota-manager is
|
|
precies het onderdeel dat die rijen aanmaakt. Zonder hem is de relay dus niet "open", maar dicht voor
|
|
iedereen.
|
|
|
|
Twee dingen die dit relativeren en die het pakket bepalen:
|
|
|
|
- **er is geen HTTP-koppeling tussen de twee.** In `src/config.ts` staat geen URL of hostnaam voor de
|
|
quota-manager, alleen een poort waarop hij zelf luistert. Ze delen de Postgres. Praktisch gevolg: de
|
|
relay hoeft de quota-manager niet te kunnen bereiken, alleen de tabel moet gevuld zijn;
|
|
- **daarmee zijn er twee wegen**, en ze zijn allebei legitiem: de quota-manager meepakketteren en er één
|
|
eigenaar in registreren, of de limietenrij één keer zelf in de database zetten. Het tweede is minder
|
|
bewegende delen, maar het is wél zelf in andermans schema schrijven, en dat breekt bij een migratie.
|
|
|
|
**Wat hier niet is uitgezocht**, en het is de eerste vraag voor wie hier verder gaat: hoe je bij de
|
|
quota-manager een eigenaar registreert, en of daar iets extern voor nodig is. De README verwijst voor de
|
|
API-specificatie naar Notion en voor het uitproberen naar Bruno; er zit een `bruno-collection/` in de repo
|
|
die dat waarschijnlijk laat zien.
|
|
|
|
### De onopgeloste tegenspraak rond dev en prod
|
|
|
|
In `.env.sample` staat `SERVER_ENV="dev" # dev | prod (PROD enables evolu relay authentication)`. Dat
|
|
suggereert dat de controles in dev uit staan, en dat zou een self-hosted relay eenvoudig maken.
|
|
|
|
**Dat is niet terug te vinden in de code die ik gelezen heb.** In `src/config.ts` wordt
|
|
`isDevServer = SERVER_ENV === 'dev'` gezet, en in `createEvoluRelay.ts` bepaalt die vlag alleen het
|
|
logniveau (`debug` tegenover `info`). `createEvoluRelayCompositionRoot.ts` hangt `getLimitsForOwner`
|
|
onvoorwaardelijk in, zonder tak voor dev.
|
|
|
|
Dus: óf het commentaar in `.env.sample` gaat over iets anders dan deze twee controles, óf het is
|
|
achterhaald. **Ga er niet van uit dat `SERVER_ENV=dev` de deur opent**, en ga er ook niet van uit dat hij
|
|
dicht is: dit is precies het soort aanname waar een middag in gaat zitten. Het is met één keer starten te
|
|
meten en dat hoort in **Proefopstelling** fase 2.
|
|
|
|
## 4. Er is geen publieke image, en dat is de grootste consequentie
|
|
|
|
**Tweede correctie op het vooronderzoek**, en de duurste. Trezor bouwt wel een image, maar publiceert hem
|
|
niet ergens waar jij hem kunt halen.
|
|
|
|
Uit `.github/workflows/build-and-push-image.yml`: de image gaat via `aws-actions/amazon-ecr-login` naar een
|
|
**Amazon ECR in eu-central-1**, met de registry-hostnaam als uitvoer van die stap en de naam als
|
|
invoerparameter. Er is geen Docker Hub en geen ghcr in dat werkproces. Onder de namespace `trezor` op
|
|
Docker Hub staat niets dat hierop lijkt.
|
|
|
|
Wat daaruit volgt voor dit project:
|
|
|
|
- **je bouwt en publiceert de image zelf**, of er is geen Umbrel-app. Dat is geen eenmalige handeling maar
|
|
een doorlopende verplichting: bij elke nieuwe versie van Trezor bouw je opnieuw;
|
|
- **`linux/arm64` is geen risico meer.** Datzelfde werkproces bouwt `platforms: linux/amd64,linux/arm64`
|
|
met QEMU, dus de Dockerfile is bovenstrooms bewezen op arm64. Dat was punt 2 van de oude versie van dit
|
|
document en die vraag is hiermee weg;
|
|
- **de licentie wordt nu wél een vraag.** GitHub classificeert `LICENSE.md` als "other". Zolang je alleen
|
|
zelf draait is dat academisch; zodra je een image publiceert, distribueer je hun software. Lees dat
|
|
bestand voordat er iets in een openbaar register komt.
|
|
|
|
## 5. Wat er nog helemaal niet uitgezocht is
|
|
|
|
Deze staan hier omdat ze het pakket bepalen en omdat er in deze ronde geen antwoord op kwam. Ze zijn geen
|
|
taak (dat zijn ze in **Proefopstelling** en **Umbrelapp**).
|
|
|
|
1. **Kan Trezor Suite überhaupt naar een eigen sync-server wijzen, en op welk platform?** Onveranderd de
|
|
goedkoopste weerlegging van het hele project, en niets in deze repo zegt er iets over: dit is de
|
|
serverkant.
|
|
2. **Accepteert Trezor Suite een `http://`-adres, of eist het TLS?** Daar hangt het masterplan
|
|
**Bereikbaarheid** aan.
|
|
3. **Hoe registreer je een eigenaar bij de quota-manager**, en heeft die daarvoor iets extern nodig? Zie
|
|
§3. Begin bij `bruno-collection/`.
|
|
4. **Wat doet `SERVER_ENV=prod` dat `dev` niet doet?** Zie de tegenspraak in §3.
|
|
5. **Wat staat er in `LICENSE.md`?** Zie §4.
|
|
|
|
## 6. Bronnen
|
|
|
|
Alles hierboven komt uit deze bestanden, geraadpleegd op 25-08-2026:
|
|
|
|
- [`docker-compose.yaml`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/docker-compose.yaml)
|
|
- [`.env.sample`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/.env.sample)
|
|
- [`Dockerfile`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/Dockerfile)
|
|
- [`README.md`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/README.md)
|
|
- [`src/config.ts`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/src/config.ts)
|
|
- [`src/evoluRelay/createEvoluRelay.ts`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/src/evoluRelay/createEvoluRelay.ts)
|
|
- [`src/evoluRelay/createEvoluRelayCompositionRoot.ts`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/src/evoluRelay/createEvoluRelayCompositionRoot.ts)
|
|
- [`.github/workflows/build-and-push-image.yml`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/.github/workflows/build-and-push-image.yml)
|
|
- Docker Hub, namespace `trezor`: geen image die hierop lijkt
|
|
|
|
Het oorspronkelijke vooronderzoek van 25-08-2026 staat ongewijzigd in
|
|
[Vooronderzoek.PLAN.md](../Plannen/Masterplannen/Archief/Vooronderzoek.PLAN.md). Wat daar niet meer klopt,
|
|
staat hierboven in §2 en §4.
|
|
|
|
## 7. De broncode van Trezor Suite staat lokaal
|
|
|
|
Aangedragen door de gebruiker op 25-08-2026, en het beantwoordde in een half uur wat uit de serverkant
|
|
alleen niet te halen was. In een ander project van de gebruiker staat een kloon van de cliënt:
|
|
|
|
```
|
|
D:\HomeGit\Trezor\Repos\trezor-suite
|
|
```
|
|
|
|
Dat is de tegenkant van deze relay, en bij een vraag als "verwacht de cliënt dit eigenlijk wel" is dat de
|
|
snelste bron. De plekken die hier iets opleverden:
|
|
|
|
| Pad | Wat je er vindt |
|
|
|-|-|
|
|
| `suite-common/suite-sync-quota-manager/src/createSuiteSyncQuotaManagerCompositionRoot.ts` | de regel dat de quota-manager genegeerd wordt bij een eigen relay-URL |
|
|
| `suite-native/app/e2e/pageObjects/settingsActions.ts` | hoe je het in de interface instelt, met werkende voorbeeld-URL's op 4000 en 4001 |
|
|
| `suite-native/module-settings/src/hooks/useSuiteSyncRelayUrlForm.ts` | het formulier: keuze tussen de standaardserver en een eigen URL |
|
|
| `suite-native/suite-sync/src/createSuiteSyncNativeCompositionRoot.ts` | hoe de Evolu-cliënt wordt samengesteld |
|
|
| `.yarn/patches/@evolu-web-npm-3.0.0-next.1-*.patch` | dat Trezor de Evolu-cliënt **patcht**, en op welke versie |
|
|
|
|
Twee waarschuwingen bij die bron. Het meeste hierboven komt uit **`suite-native`**, dus de mobiele app; de
|
|
desktopversie kan andere instellingen op een andere plek hebben, en dat is niet nagekeken. En het is een
|
|
kloon op een moment in de tijd: bij twijfel de datum van die kloon opzoeken voordat je er een conclusie op
|
|
bouwt.
|
|
|
|
## 8. De uitbreidpunten van de kale relay
|
|
|
|
Nagetrokken 28-08-2026 in de broncode van `evoluhq/evolu`, nadat de proef bewees dat de kale relay bruikbaar
|
|
is. Dit is wat een eigen limiter mogelijk maakt, en het is aanzienlijk minder werk dan **Bereikbaarheid**
|
|
§4b aannam.
|
|
|
|
**Er wordt geen relay nagebouwd; er worden twee functies meegegeven.** `createRelay` uit `@evolu/nodejs`
|
|
heeft deze vorm:
|
|
|
|
```ts
|
|
createRelay({ port = 443, name, isOwnerAllowed, isOwnerWithinQuota }): Task<Relay, never, RelayDeps>
|
|
```
|
|
|
|
`isOwnerAllowed(ownerId)` beslist of een eigenaar er überhaupt in mag, `isOwnerWithinQuota(ownerId,
|
|
requiredBytes)` of een schrijfactie past. Beide zijn asynchroon. De opslag wordt intern gemaakt met
|
|
`createRelaySqliteStorage(deps)({ isOwnerWithinQuota })`, dus SQLite, en `createRelayDeps()` levert de
|
|
driver.
|
|
|
|
**Trezor doet exact dit en niets meer.** Hun `createEvoluRelay.ts` roept de relay aan met die twee
|
|
functies, en beide kijken in hun limietentabel via `getLimitsForOwner()`. De hele quota-manager plus
|
|
Postgres bestaat dus alleen om die tabel te vullen. Dat is het bewijs dat ons pakket met dezelfde twee
|
|
haken hetzelfde kan zonder die machinerie.
|
|
|
|
**De gepubliceerde image vult ze zelf al deels in**, en dat is een valstrik om te kennen. In
|
|
`apps/relay/src/index.ts` staat `isOwnerAllowed` **uitgecommentarieerd** (dus iedereen mag erin) en
|
|
`isOwnerWithinQuota` op **1 MB per eigenaar**. Dat is geen theorie maar de image die wij draaien:
|
|
|
|
- **die grens geldt per schrijfactie en niet per eigenaar.** De relay geeft door hoeveel bytes déze actie
|
|
nodig heeft; er wordt niets opgeteld. Trezor telt wél op, maar dat doen ze zelf uit hun eigen tabel, en
|
|
die tabel is precies wat een kale relay niet heeft. Een labelgeschiedenis kan hier dus niet tegenaan
|
|
lopen;
|
|
- **wat het wél tegenhoudt is één grote schrijfactie.** Dat dempt misbruik als gratis opslag, maar het is
|
|
geen totaalquotum. Wie dat wil, moet in de opslag van de relay kijken hoeveel een eigenaar al gebruikt,
|
|
en dat is schrijven noch lezen in je eigen schema.
|
|
|
|
De relay zet zijn data in een map `data` naast het programma (`mkdirSync` plus `process.chdir`), en dat is
|
|
het volume `/app/data` uit de image. In de database zitten onder meer `evolu_message` en `evolu_history`, en
|
|
`ownerId` is een systeemkolom. **Data per eigenaar wissen is daarmee mogelijk maar het is schrijven in
|
|
andermans schema**, met dezelfde bezwaren als bij Trezor's limietentabel.
|
|
|
|
Bronnen, geraadpleegd 28-08-2026:
|
|
|
|
- [`packages/nodejs/src/local-first/Relay.ts`](https://raw.githubusercontent.com/evoluhq/evolu/main/packages/nodejs/src/local-first/Relay.ts)
|
|
- [`apps/relay/src/index.ts`](https://raw.githubusercontent.com/evoluhq/evolu/main/apps/relay/src/index.ts)
|
|
- [`src/evoluRelay/createEvoluRelay.ts`](https://raw.githubusercontent.com/trezor/trezor-suite-sync/main/src/evoluRelay/createEvoluRelay.ts) van Trezor
|
|
- [evolu.dev/docs/relay](https://www.evolu.dev/docs/relay) en [evolu.dev/docs/evolu-server](https://www.evolu.dev/docs/evolu-server)
|
|
|
|
## 9. Wat Trezor er zelf over publiceert
|
|
|
|
Nagetrokken 28-08-2026 op de eigen documentatiepagina's, nadat op iOS niets bleek te werken. Drie feiten
|
|
die het pakket raken, en ze staan verspreid over pagina's die elkaar niet noemen.
|
|
|
|
**Een eigen relay is een gedocumenteerde functie en geen ontwikkelaarstruc.** De pagina
|
|
[Suite Sync in Trezor Suite](https://trezor.io/guides/trezor-suite/suite-sync) beschrijft "Custom server"
|
|
als keuze in de interface, met een invoerveld voor je eigen adres, ook op mobiel. Dat is prettig voor dit
|
|
plan: wat wij verpakken is een ondersteund gebruikspatroon en geen omweg.
|
|
|
|
**Op 28-08-2026 is via beide wegen getest:** op de desktop via het dev-utils-veld, op iOS via de gewone
|
|
"Custom server"-instelling. Dat is de moeite van het vastleggen waard, want het sluit een verklaring uit die
|
|
anders was blijven hangen: iOS deed niets terwijl daar juist de officiële, ondersteunde weg gebruikt werd.
|
|
Wat er overblijft is de verklaring uit het plan **Umbrelapp**, OPEN.md punt 9: zonder een apparaat dat aan
|
|
de telefoon kan, is er geen sleutel en dus niets om te synchroniseren.
|
|
|
|
**Suite Sync werkt op Safe 3, Safe 5 en Safe 7**, en aanzetten vraagt altijd een bevestiging op het
|
|
apparaat, ook op mobiel: "Confirm the action on your Trezor hardware wallet". Model One en Model T gebruiken
|
|
het oude labelformaat en doen niet mee.
|
|
|
|
**Op iOS werkt alleen de Safe 7.** Die verbindt over Bluetooth; alle andere modellen gaan over USB en dat
|
|
ondersteunt iOS niet, waar alleen view-only via XPUB overblijft. Zie de
|
|
[Trezor Suite Lite FAQ](https://trezor.io/guides/trezor-suite/trezor-suite-lite/trezor-suite-lite-faqs).
|
|
|
|
**De combinatie van die twee wordt nergens genoemd**, en dat is precies waar deze store een dag aan kwijt
|
|
was: de Suite Sync-pagina beschrijft de mobiele stappen alsof ze op elk toestel werken, terwijl de
|
|
bevestiging op een model dat niet aan een iPhone kan nooit gegeven kan worden. Er bestaat een forumdraad
|
|
"Suite Sync: confusion about device compatibility", niet leesbaar zonder inloggen, wat erop wijst dat meer
|
|
mensen hier tegenaan lopen.
|
|
|
|
**En één getal om te onthouden: hun eigen dienst kapt af op 1 MB, ongeveer 2500 bewerkingen per apparaat**,
|
|
waarna de rest lokaal blijft. Dat is een totaal, en het is de grens die hun quota-manager bewaakt. Een
|
|
zelf-gehoste relay kent die grens niet: wij begrenzen alleen één schrijfactie (zie §8), en dat is dus een
|
|
echt verschil in wat de app oplevert en geen detail.
|