A stock Bitwarden client speaks Vaultwarden's protocol and nothing else: it gets its own bearer token from /identity/connect/token and has nowhere to put a platform JWT, so the authenticated /api/vault router cannot serve it. This was dropped during the extraction because a plugin's routes mount behind the account gate. It comes back through the platform's own mechanism rather than an exception: `unauthenticatedPaths: ['/bw/*']` in the manifest, resolved against this plugin's mount and re-checked for containment at boot. ONE prefix, not the four root mounts the platform version needed. A Bitwarden client takes `https://<officer>/api/vault/bw` as its server URL and derives /api, /identity, /icons and /notifications beneath it, so the whole protocol fits under a single declared path. The router is mounted BEFORE this file's middleware, deliberately: Hono collects handlers in registration order, so a route registered ahead of a `.use()` answers without it. Verified rather than assumed, because it is an auth boundary — /api/vault/bw/* reaches the passthrough with no session while /api/vault/config still goes through userMiddleware and the owner gate. Not new exposure: everything here was already reachable at the Vaultwarden URL it replaces, guarded by the same master password and the same Vaultwarden auth. Officer adds no security to a Bitwarden client because it has no credential to check. What it buys is that Vaultwarden need not be exposed at all — on this install it listens on 127.0.0.1 only, and Officer, already behind the tailnet and already terminating TLS, becomes the single address any client needs. Net reduction in surface. Still temporary, and still deleted rather than adjusted once a first-party extension authenticates to Officer against the /session/login broker. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vault
Your passwords, in a Vaultwarden you already run, reached through Officer.
Vault does not store passwords and cannot read them. It is two things: a reverse-proxy to a Vaultwarden server you point it at, and a credential broker that keeps the vault session on the server so your devices never have to hold one. The vault is end-to-end encrypted — every byte through here is ciphertext, and nothing in this plugin decrypts, parses, caches or logs a request body.
What you get
- One address for everything. Officer's own mobile app signs in to Officer and reaches the vault at
/api/vault— it never sees a Vaultwarden token, because the server holds it and injects it on the way through. - A session that follows your Officer session. Sign out and the brokered vault session goes with it. Hit distress or panic and the stored unlock key goes too, so the next unlock needs the master password — which is the whole point of those buttons.
- A settings screen at
/vault: paste the URL of your Vaultwarden, see whether it answers, turn the proxy off without forgetting where it lives.
What you need
A Vaultwarden you already run. This plugin does not install one, provision a container, or manage anything about it — you give it a URL and it forwards there. It is equally happy with one on the same machine, one on your tailnet, or one behind a reverse proxy somewhere else.
Nothing else. No system packages, no host binaries.
Setup
- Install the plugin.
- Open /vault and enter your Vaultwarden's address, e.g.
https://vault.example.com. - Press Check. A green "Answering" means Officer can reach it.
Changing the URL later takes effect within about ten seconds — the sidecar re-reads it on a short timer, so there is nothing to restart.
What it deliberately does not do yet
Stated plainly, because a store listing that only says what works is an advertisement.
- There is no password list, and there will not be one here. Reading vault items needs the decryption keys, which live on your devices. Use a Bitwarden client or Officer's mobile app.
- Third-party Bitwarden clients cannot point at Officer. The browser extension used to be able to, through an unauthenticated passthrough at Officer's own hostname. That path could not come with the plugin: a plugin's routes mount behind Officer's account gate, and top-level unauthenticated routes are not something a plugin can declare. Point Bitwarden clients at your Vaultwarden directly for now. The intended replacement is a first-party browser extension that authenticates to Officer like every other client, which removes the need rather than restoring the workaround.
- Push notifications fall back to polling. Vaultwarden's live "your vault changed" socket is not proxied — no plugin owns a websocket yet on this platform. SignalR degrades to HTTP long-polling on its own, so clients still sync; they learn about changes on their next poll rather than instantly.
- One Vaultwarden per install, and it is the owner's. The URL is server-wide and every route is owner-only. Mapping additional Officer accounts onto Vaultwarden's own users is a real feature and is not built.
- Uninstalling keeps your data. The tables survive, as they do for every plugin — only deleting the plugin's source drops them. Your Vaultwarden is untouched either way; this plugin never wrote to it.