feat(settings): Schweizer Endpunkt aus der App konfigurierbar machen - #28
Merged
Merged
Conversation
The Infomaniak product id was read from process.env only. A packaged, GUI-launched app never has it, so the Swiss endpoint silently failed to register and there was no way for a user to fix that. It is now a setting, with the environment kept as a development fallback. Settings win: a value someone typed into the app beats one the process happened to inherit. Entering or clearing it takes effect immediately — `applyInfomaniakConfig` runs at startup and on every settings update, so no restart is needed. Clearing the id REMOVES the registry entry rather than leaving the previous URL in place. A leftover entry would keep claiming Swiss residency for an endpoint the user has disowned, and the policy would keep routing sensitive requests to it. That is the case the tests guard hardest. Making the setting real meant closing three gaps behind it, each of which would have left a field that looks configured and does nothing: - The registry decides who MAY receive a request; the client manager is what can actually send one. Only the first was being registered, so the endpoint was selectable and unreachable. - `validateProvider` was a hardcoded list of four names and gates both saving an API key and loading it back at startup. The token field would have failed silently. A provider now qualifies by being built in or registered — earned rather than enumerated, and an arbitrary string still cannot reach the keychain. - A SECOND `validateProvider`, with its own copy of that list, gated the send path in ipc-handlers.ts. A configured endpoint could have held a key and still been refused a message. The two are now one function. UI lives on the Privacy tab, where the residency story already is: product id, token, and a warning when one is set without the other. Sabotages, each verified red: - drop the removal on clear -> the stale-endpoint test fails - read the environment only -> the settings-precedence tests fail 1426 tests green, typecheck exit 0, build:main and build:renderer exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Was
Die Infomaniak-Produkt-ID und der Token lassen sich jetzt in den Einstellungen eintragen — und der Endpunkt funktioniert danach wirklich.
Warum
Die Produkt-ID kam ausschliesslich aus
process.env. Eine gepackte, per Doppelklick gestartete App hat sie nie, also wurde der Schweizer Endpunkt nicht registriert, und ein Nutzer hatte keine Möglichkeit, das zu ändern.Sie ist jetzt eine Einstellung; die Umgebungsvariable bleibt als Entwicklerpfad. Die Einstellung gewinnt — ein Wert, den jemand in die App getippt hat, schlägt einen, den der Prozess zufällig geerbt hat. Eingeben oder Löschen wirkt sofort, ohne Neustart.
Löschen entfernt den Registry-Eintrag, statt die alte URL stehen zu lassen. Ein Rest-Eintrag würde weiter Schweizer Residenz behaupten für einen Endpunkt, den der Nutzer verworfen hat — und die Policy würde weiter sensible Anfragen dorthin leiten. Das ist der Fall, den die Tests am härtesten bewachen.
Drei Lücken dahinter
Die Einstellung wirklich wirksam zu machen hiess, drei Dinge zu schliessen. Jedes einzelne hätte ein Feld hinterlassen, das konfiguriert aussieht und nichts tut:
Der Client fehlte. Die Registry entscheidet, wer eine Anfrage bekommen darf; der Client-Manager ist, was tatsächlich senden kann. Registriert wurde nur ersteres — der Endpunkt war wählbar und unerreichbar.
validateProviderwar eine Whitelist aus vier Namen und bewacht sowohl das Speichern eines Schlüssels als auch das Laden beim Start. Das Token-Feld hätte still versagt. Ein Anbieter qualifiziert sich jetzt dadurch, dass er eingebaut oder registriert ist — verdient statt aufgezählt. Eine beliebige Zeichenkette kommt weiterhin nicht an den Keychain.Es gab eine ZWEITE
validateProvidermit einer eigenen Kopie derselben Liste, die den Sendepfad inipc-handlers.tsbewachte. Ein konfigurierter Endpunkt hätte einen Schlüssel halten und trotzdem keine Nachricht bekommen können. Beide sind jetzt eine Funktion — zwei Prüfungen mit zwei Listen sind genau die Bauart, aus der so ein Zustand entsteht.Tests
npm test→ 1426 passed | 29 skipped (97 Dateien), Exit 0 ·npm run typecheck→ Exit 0 ·build:mainundbuild:renderer→ Exit 0Kein bestehender Test verändert.
Sabotagen, jede rot gesehen:
Review-Punkte
validateProviderist eine Sicherheitsschranke, und ich habe sie geweitet. Vorher: vier Namen. Jetzt: eingebaut oder in der Registry. Ein mandantenseitig eingetragener Endpunkt qualifiziert sich damit ebenfalls — das ist beabsichtigt, denn Bring-your-own-key ist genau dessen Zweck, und Invariante I2 regelt, was so ein Endpunkt über seine Residenz behaupten darf, nicht ob der Nutzer einen Schlüssel dafür ablegen darf. Ein Test hält fest, dass eine unbekannte Zeichenkette weiterhin abgewiesen wird.Die Oberfläche ist ungetestet. Das Repo hat keine Komponententests, und ich habe dafür kein Framework eingeführt. Die Logik dahinter — Auflösung, Registrierung, Entfernung, Validierung — ist es vollständig.
Der Token wandert in den Keychain, die Produkt-ID in die Einstellungen. Die ID steht in einer URL und ist kein Geheimnis; sie dort zu verschlüsseln wäre Sicherheitstheater.
🤖 Generated with Claude Code