Repository navigation
fix(team-vault): never show a secret the server refused as saved (#608) - #609
Merged
Merged
Conversation
Saving a port-knock sequence on a team-vault host against a server older than its knock support failed with a bare "400", yet the port reappeared when the editor was reopened: the value was cached before the upload and never taken back. The Port Knocking switch, stored on the host itself, saved fine, so the host could end up knocking with no ports and fail to connect for the whole team. The client now reads the secret types a server advertises in /v1/meta and never uploads one that is missing. A server too old to advertise anything is still tried; a 400 on the knock sequence is read as "too old" and remembered until the next check. Either way the cache goes back to what the server holds, the error says the server needs an update, and the refusal is logged with the secret type and client version. On such a server the knock panel of a team-vault host explains why instead of offering ports, the switch can only be turned off, and a switch whose sequence was just refused is turned back off. A secret queued for retry after a move into a team vault keeps its local copy as before and uploads once the server is updated.
kipavy
added a commit
that referenced
this pull request
Oct 11, 2026
) A team secret whose upload failed stayed in the in-memory cache as if the server held it, then vanished at the next vault load. #609 fixed that only for a server too old for the secret's type. The cache now keeps two layers: what the server holds, and over it the values whose upload has not landed. A write shows its value from the second layer and moves it to the first only once the server has accepted it. - Refused (any 4xx except 401, 408 and 429): the value is dropped at once and the editor shows what the server holds again. - Not reached (offline, timeout, 5xx, expired session): the value stays usable, survives vault reloads, and is uploaded again after every load of the team, foreground or background, until it lands or the app closes. Nothing is written to disk, so the memory-only rule of #402 holds. Clearing the secret drops the unsent value, so a later retry cannot bring it back. Connect prompts, import, paste, duplicate, copy to vault, undo and plugin key creation only logged these failures; they now raise one toast per distinct failure. The opportunistic public-key backfill stays log-only. Keys queued by a move into a team keep their on-device copy and their sweep retry, as before. Refs #608
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.
Closes #608. Server side: VoltiusApp/server#103.
Problem
On a self-hosted server older than its port-knock support (VoltiusApp/server#100), editing a team-vault host:
team secret upload failed for knock_sequence:<id>: 400.writeSecretAtcached the value before the upload and never took it back, so it lasted until the next vault load.The client had no way to know what the server supports.
Fix
services/serverCapabilities.ts): readsteam_secret_typesfrom/v1/meta(added in feat(meta): advertise the team secret types the server accepts server#103), refreshed at most every 5 minutes and reset on logout. A type the server does not list is never uploaded.400onconnection_knock_sequenceis read as "server too old" and remembered until the server advertises a list. Servers that already store knock sequences but predate the list keep working.fetchServerMetais now shared by identity picks and the capability check.Personal-vault hosts are unaffected whatever the server supports.
Cons
GET /v1/metaat most every 5 minutes while team secrets are written or a host editor is open.Deploy order
Server first (VoltiusApp/server#103), as usual. The client also works against the current server, which advertises nothing.
Tests
serverCapabilities.test.ts(8 tests): advertised list, unknown server, refusal memory, refresh interval, failed fetch, reset.secretRouting.test.ts: unlisted type never uploaded and cache restored;400from an old server drops the value and is remembered;400on a type every server stores stays an ordinary failure; queued key keeps its local copy; unreachable meta never blocks an upload.PortKnockPanel.test.tsxandconnectionForms.characterisation.test.tsx: warning shown, port list hidden, switch off-only, sequence withheld and knocking switched back off, personal host untouched.tsc --noEmit: clean.vitest: all 807 test files pass.400to this type.