vault: Vaultwarden reverse-proxy as the officer-vault sidecar
Transparent pass-through fronting a self-hosted Vaultwarden so the OffVault (Bitwarden-SDK) app reaches it through the platform's per-app origin gate. True out-of-process sidecar (officer-vault): it owns all Vaultwarden knowledge (URL, paths, notifications WebSocket) on a random loopback port and registers via the sidecar connector; the platform is a thin origin-gated forwarder that knows only the sidecar's port. Never decrypts/parses/rewrites/logs bodies. - sidecar/vault: HTTP + notifications-WS proxy to VAULTWARDEN_URL, /_health - api/vault: sidecar-port discovery + thin forwarder + WS pipe + origin gate - origin: OFFICER_VAULT_ORIGIN allow-listed, scoped to /api/vault - mounted top-level (not protected) so the Bitwarden bearer token isn't 401'd - protocol: vault:server event; ecosystem: officer-vault app Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { IS_DEV_BUILD } from '../build-env';
|
||||
import { verify } from '../jwt';
|
||||
import { isSuperAdmin } from '../super-admin';
|
||||
|
||||
const { PUBLIC_URL, OFFICER_APP_ORIGIN, MUSIC_APP_ORIGIN } = process.env;
|
||||
const { PUBLIC_URL, OFFICER_APP_ORIGIN, MUSIC_APP_ORIGIN, OFFICER_VAULT_ORIGIN } = process.env;
|
||||
|
||||
// The allowed production web origin comes from PUBLIC_URL in .env (e.g. https://officer.pastilhas.dev),
|
||||
// not a hardcoded domain.
|
||||
@@ -33,6 +33,10 @@ const APP_ORIGINS: string[] = [
|
||||
// Standalone officer-music app — its own custom-scheme origin. Allowlisted so it can authenticate
|
||||
// and stream; SCOPED_ORIGINS below restricts it to /api/auth + /api/music only.
|
||||
MUSIC_APP_ORIGIN,
|
||||
// OffVault app (Bitwarden-SDK client) — its own custom-scheme origin. Allowlisted so it can reach the
|
||||
// Vaultwarden reverse-proxy; ORIGIN_RULES below restricts it to /api/vault only. It authenticates to
|
||||
// Vaultwarden with its own bearer token (not a platform account), so no super-admin rule applies.
|
||||
OFFICER_VAULT_ORIGIN,
|
||||
].filter((o): o is string => Boolean(o));
|
||||
|
||||
// The only path prefixes a non-owner account (and the music app) may reach.
|
||||
@@ -54,6 +58,9 @@ const ORIGIN_RULES: Record<string, OriginRule> = {};
|
||||
if (PUBLIC_ORIGIN) ORIGIN_RULES[PUBLIC_ORIGIN] = { superAdminOnly: true };
|
||||
if (OFFICER_APP_ORIGIN) ORIGIN_RULES[OFFICER_APP_ORIGIN] = { superAdminOnly: true };
|
||||
if (MUSIC_APP_ORIGIN) ORIGIN_RULES[MUSIC_APP_ORIGIN] = { paths: NON_OWNER_PATHS };
|
||||
// OffVault may reach ONLY the Vaultwarden proxy. No superAdminOnly: its callers hold Bitwarden tokens,
|
||||
// not platform accounts, so the account backstop above never applies to them (verify() → null → passes).
|
||||
if (OFFICER_VAULT_ORIGIN) ORIGIN_RULES[OFFICER_VAULT_ORIGIN] = { paths: ['/api/vault'] };
|
||||
|
||||
// True when an Origin is reserved for the platform owner (used at signin to reject a non-owner login).
|
||||
export function isSuperAdminOnlyOrigin(origin: string | undefined): boolean {
|
||||
|
||||
Reference in New Issue
Block a user