De pagina van Evolu Relay op de lijst van de gebruiker
Negen punten uit echt gebruik met 0.4.0, alle negen gedaan. Twee ervan waren onderzoeksvragen en die staan onderaan. Evolu Relay 0.5.0 - Een tijdvenster van twee minuten voor nieuwe eigenaars, met een stopknop. De teller zit in het relay-proces en niet in de pagina: een teller in een tabblad dat je sluit, sluit de deur niet. policy.js kreeg learningUntil, isLearningOpen en expireLearning. - decideOwner kijkt naar isLearningOpen en niet naar het veld learning. De lus die een verlopen venster opruimt loopt elke twee seconden, en in dat gat zou een onbekende alsnog binnenkomen. - Zonder STATE_VERSION te verhogen, met een toets die dat verdedigt: een verhoging zou de allowlist van de draaiende installatie laten afwijzen en de deur sluiten voor eigenaars die er al in stonden. - Labels op een eigenaar-id, in een eigen labels.json met de agent als enige schrijver. Een label zegt niets over toegang, dus de relay hoeft het niet te weten; het is daardoor meteen opgeslagen en werkt ook als de relay omligt. - Geblokkeerde en geweigerde eigenaars in een kader, met een badge die zegt welke van de twee het is. De badge staat buiten het hover-blok, anders is dat onderscheid onzichtbaar tenzij je over de regel gaat. - Maatvoering gelijk aan Electrum Gate: 1760px, hetzelfde raster, icoon van 64 pixels, dezelfde kop, versienummer erachter. Uitleg uit de kaders, knoppen pas bij hover, geen voetregel. Electrum Gate 0.0.24 - Menu-item "About this app", in beide apps. - De statuswidget zei "Answering" met "answered in 7 ms, from inside the app" en zegt nu "Running" met de meting eronder. De nuance dat de controle van container naar container loopt is verplaatst naar een eigen kopje in die dialoog, waar er ruimte voor is; vier woorden waren te weinig. Toetsen en gereedschap - tests/test_relay_agent.py (nieuw, 65 toetsen) en tests/test_paginas_parsen.mjs (nieuw). Muteertests gedraaid op de beslissende regels. - Een dollarteken-toets in test_appstore_vorm.py. Het commentaar in drie bestanden beweerde al dat die test bestond; nu is dat waar. - Een toets dat er geen werkbestanden in een app-map staan. umbreld kopieert de hele map naar het apparaat en in de back-up. - tools/voorbeeldpagina.mjs maakt van een *.template een pagina die je in een browser kunt openen. Dat vond meteen twee echte opmaakfouten. De twee onderzoeksvragen - Een geweigerde eigenaar komt niet in de database: isOwnerAllowed zit in de WebSocket-upgrade, dus het is een 401 en een gesloten socket. Het gewenste gevolg treedt wel op, via de client: die is local-first en levert bij toelating de hele geschiedenis. Blokkeren werkt daarentegen pas bij de volgende verbinding, en dat staat als open punt. - De blobs zijn niet met een xpub te ontcijferen; een OwnerId komt daar niet uit. Met de SLIP-21-node van het apparaat kan het wel, maar die geeft volledige zeggenschap, dus dat hoort niet in een relay. Als plan-punt opgenomen bij de tool in HomeGit/Trezor. Nog niet uitgerold: de image 0.5.0 moet gebouwd en geduwd worden. De digest staat daarom niet in de compose, want een oude digest onder een nieuwe tag levert stil de oude relay. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -560,6 +560,19 @@ body {
|
||||
want in de melding staat een zin die je eerst leest. */
|
||||
.alert-action { margin-top: 0.7rem; }
|
||||
|
||||
/* De dialoog "About this app" is lopende tekst en geen lijst met waarden, dus hij
|
||||
heeft opmaak nodig die de certificaatdialoog niet gebruikt. Kopjes in de maat
|
||||
van een .t-label, want ze verdelen de tekst en zijn er niet om gelezen te
|
||||
worden. */
|
||||
.sheet-prose h3 {
|
||||
font-size: 0.68rem; font-weight: 600; letter-spacing: 0.08em;
|
||||
text-transform: uppercase; color: var(--text-sec);
|
||||
margin: 1.6rem 0 0.5rem;
|
||||
}
|
||||
.sheet-prose h3:first-child { margin-top: 0; }
|
||||
.sheet-prose p { font-size: 0.85rem; line-height: 1.65; color: var(--text-sec); margin-bottom: 0.7rem; }
|
||||
.sheet-prose p strong { color: var(--text-primary); font-weight: 600; }
|
||||
|
||||
/* ── Het instelkader ────────────────────────────────────────────────────── */
|
||||
.setup > summary { list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: 0.8rem; flex-wrap: wrap; }
|
||||
.setup > summary::-webkit-details-marker { display: none; }
|
||||
@@ -692,6 +705,19 @@ body {
|
||||
<button class="menu-item" id="menu-certs" type="button">
|
||||
<span>Settings…</span>
|
||||
</button>
|
||||
<!-- "About this app" op verzoek van de gebruiker (30-08-2026), en aan
|
||||
beide apps in deze store toegevoegd. Hier stond de marketingtekst
|
||||
nergens op de pagina: die staat in umbrel-app.yml en dus alleen in de
|
||||
winkel, terwijl je juist ná het installeren nog eens wil kunnen
|
||||
nalezen wat dit ding voor je doet en wat het niet doet.
|
||||
|
||||
Boven "Appearance" en onder "Settings…": van wat je het meest doet
|
||||
naar wat je het minst doet is hier de verkeerde ordening, want dan zou
|
||||
het thema bovenaan staan. De ordening is wat over de app gaat eerst,
|
||||
wat over deze pagina gaat daarna. -->
|
||||
<button class="menu-item" id="menu-about" type="button">
|
||||
<span>About this app…</span>
|
||||
</button>
|
||||
<!-- De regel toont de huidige stand en niet de handeling. De losse knop
|
||||
hiervoor deed het andersom, met "Light" terwijl de pagina donker was.
|
||||
Als knop klopte dat, want dat was waar je heen ging; als menuregel
|
||||
@@ -943,6 +969,82 @@ body {
|
||||
</div><!-- /sheet-body -->
|
||||
</dialog>
|
||||
|
||||
<!-- De dialoog "About this app", toegevoegd op verzoek van de gebruiker
|
||||
(30-08-2026) en in dezelfde vorm aan Evolu Relay.
|
||||
|
||||
De tekst is die uit umbrel-app.yml, ingekort en met kopjes erin. Wijzig je
|
||||
daar iets aan de strekking, dan hoort het hier ook te veranderen; ze staan
|
||||
niet met een test aan elkaar vast omdat de vorm verschilt.
|
||||
|
||||
Wat hier bovendien staat en nergens anders: de grens van de statuswidget.
|
||||
Die zei tot 0.0.24 "answered in 7 ms, from inside the app", en dat was
|
||||
precies genoeg tekst om onduidelijk te zijn en te weinig om de nuance te
|
||||
dragen. De nuance is nu hier, waar er ruimte voor is. -->
|
||||
<dialog id="about-dialog" class="sheet">
|
||||
<form method="dialog" class="sheet-head">
|
||||
<h2 class="t-h3">About this app</h2>
|
||||
<button class="sheet-close" value="close" aria-label="Close" title="Close">×</button>
|
||||
</form>
|
||||
|
||||
<div class="sheet-body sheet-prose">
|
||||
<h3>What it is for</h3>
|
||||
<p>
|
||||
The privacy win is already yours: you run the Electrum server. A public one gets asked for the
|
||||
history of every address in your wallet, and that tells it which addresses and which balance
|
||||
belong to one person. Your own server never reports back.
|
||||
</p>
|
||||
<p>
|
||||
What is left is a trade. <strong>Tor</strong> is the more private way in, and every wallet
|
||||
speaks it. But it adds hundreds of milliseconds to every request, it drops when a phone sleeps
|
||||
or changes network, and plenty of networks block it outright. Electrum Gate is the other side
|
||||
of that trade: a TLS front door on your node. Fast, no fingerprint to type over, and it works
|
||||
on any network you happen to be on.
|
||||
</p>
|
||||
|
||||
<h3>The certificate</h3>
|
||||
<p>
|
||||
It reuses the Let's Encrypt certificate your reverse proxy already manages, so there is
|
||||
nothing to request and nothing to renew. A renewal is picked up on its own, without dropping
|
||||
connections that are already open. You can also upload a certificate you manage yourself, if
|
||||
you do not run a reverse proxy on this machine.
|
||||
</p>
|
||||
<p>
|
||||
When more than one certificate could fit and you have not chosen, the app <strong>refuses</strong>
|
||||
rather than picking one. A wrong certificate gives a connection that looks fine and only breaks
|
||||
later, inside your wallet, on name verification.
|
||||
</p>
|
||||
|
||||
<h3>Nothing in the middle</h3>
|
||||
<p>
|
||||
The connection runs from your wallet straight to your own node, encrypted with a certificate
|
||||
you already own, for a domain you already control. There is no account to create, no tunnel
|
||||
service that terminates your traffic along the way, and no client to install on every device
|
||||
you use: the wallets already speak TLS, they only need an address. What it does ask of you is
|
||||
one forwarded port on your router.
|
||||
</p>
|
||||
|
||||
<h3>What the Status card does and does not prove</h3>
|
||||
<p>
|
||||
The app opens a TLS connection to its own front door every minute and checks that the
|
||||
certificate it gets back is the one you selected. <strong>Running</strong> means that
|
||||
succeeded.
|
||||
</p>
|
||||
<p>
|
||||
It is measured from inside the app, so it says nothing about the way in from outside: a router
|
||||
that no longer forwards the port, or a firewall in between, still reads as Running here. If a
|
||||
wallet cannot connect while this card says Running, the fault is on the route and not in this
|
||||
app.
|
||||
</p>
|
||||
|
||||
<h3>Which wallets</h3>
|
||||
<p>
|
||||
Useful for wallets connecting from outside your home: Trezor Suite, Electrum, Sparrow,
|
||||
BlueWallet, Nunchuk, Blockstream and BitBoxApp. Apps on the Umbrel itself do not need it, they
|
||||
already reach the Electrum server directly.
|
||||
</p>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<!-- Voorstel, nog niet besloten. De agent stelt de regels samen uit de
|
||||
stream-access-log van nginx. Bewust zonder client-IP en zonder bronpoort:
|
||||
dat is precies het soort gegeven dat deze app dichtzet, en het is niet
|
||||
@@ -1121,6 +1223,20 @@ body {
|
||||
el('menu-certs').addEventListener('click', openSheet);
|
||||
el('alert-nocert-open').addEventListener('click', openSheet);
|
||||
|
||||
// ── De dialoog "About this app" ─────────────────────────────────────────
|
||||
// Dezelfde route als hierboven, met dezelfde terugval voor een browser zonder
|
||||
// showModal.
|
||||
var about = el('about-dialog');
|
||||
|
||||
el('menu-about').addEventListener('click', function () {
|
||||
closeMenu();
|
||||
if (typeof about.showModal === 'function') {
|
||||
about.showModal();
|
||||
} else {
|
||||
about.setAttribute('open', '');
|
||||
}
|
||||
});
|
||||
|
||||
// ── Hulpjes ─────────────────────────────────────────────────────────────
|
||||
function el(id) { return document.getElementById(id); }
|
||||
|
||||
@@ -1290,12 +1406,26 @@ body {
|
||||
// Gebouwd in de agent in 0.0.16, hier getoond sinds de tweede indeling.
|
||||
//
|
||||
// Let op het woord dat hier niet staat: "reachable". De agent verbindt van
|
||||
// container naar container, dus dit zegt niets over de poortmapping naar de
|
||||
// host of over de doorstuurregel in de router. "Answering" met daaronder "from
|
||||
// inside the app" is wat er gemeten is; alles wat verder gaat, zou de tegel
|
||||
// container naar container, dus dit zegt niets over de poortmapping naar de host
|
||||
// of over de doorstuurregel in de router. Alles wat verder gaat, zou de tegel
|
||||
// laten liegen op precies het punt waar iemand hem gelooft.
|
||||
//
|
||||
// Hier stond "Answering", met daaronder "answered in 7 ms, from inside the app".
|
||||
// De gebruiker meldde op 30-08-2026 dat die tegel onduidelijk is en dat die van
|
||||
// Evolu Relay ("Running") meteen leest, en dat is terecht om twee redenen:
|
||||
//
|
||||
// - "Answering" is een tegenwoordig deelwoord en leest dus als een handeling die
|
||||
// bezig is, niet als een toestand. "Checking" ernaast maakt dat erger, want
|
||||
// dát is er wél een;
|
||||
// - "from inside the app" is de nuance hierboven in vier woorden, en vier
|
||||
// woorden zijn er te weinig voor. Wie het niet al weet, leest er niets uit.
|
||||
//
|
||||
// Wat er nu staat is "Running", met de meting eronder. De nuance is niet
|
||||
// weggelaten maar verplaatst naar de dialoog "About this app", onder een eigen
|
||||
// kopje: daar is ruimte om te zeggen wat het wél en niet bewijst. Haal dat kopje
|
||||
// niet weg zonder hier iets terug te zetten, want dan staat de bewering nergens.
|
||||
var SELF = {
|
||||
ok: { label: 'Answering', bad: false },
|
||||
ok: { label: 'Running', bad: false },
|
||||
failed: { label: 'Not answering', bad: true },
|
||||
'wrong-certificate': { label: 'Wrong certificate', bad: true },
|
||||
// Geen certificaat is de normale begintoestand van een verse installatie en
|
||||
@@ -1322,7 +1452,10 @@ body {
|
||||
node.classList.toggle('bad', kind.bad);
|
||||
|
||||
if (self.state === 'ok') {
|
||||
sub.textContent = 'answered in ' + self.ms + ' ms, from inside the app';
|
||||
// Wat er gemeten is, in gewone woorden. Het getal blijft, want dat is het
|
||||
// enige harde gegeven op deze tegel; wat het niet bewijst staat in de
|
||||
// dialoog "About this app".
|
||||
sub.textContent = 'the TLS port answered in ' + self.ms + ' ms';
|
||||
} else if (self.state === 'off') {
|
||||
sub.textContent = 'no certificate selected, so nothing is listening';
|
||||
} else if (self.state === 'wrong-certificate') {
|
||||
|
||||
Reference in New Issue
Block a user