vault: allow the OffVault origin to sign in to the platform

Scope OFFICER_VAULT_ORIGIN to ['/api/auth', '/api/vault'] instead of
'/api/vault' only. The OffVault app authenticates to the platform first
(/api/auth/signin) and only then reaches the vault proxy — same shape as the
music app's ['/api/auth', '/api/music']. Without /api/auth the signin was
rejected in originScopeMiddleware with "Origin not permitted".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 01:44:08 +00:00
co-authored by Claude Opus 4.8
parent fcf6715844
commit 4d6975934a
@@ -33,9 +33,9 @@ const APP_ORIGINS: string[] = [
// Standalone officer-music app — its own custom-scheme origin. Allowlisted so it can authenticate // 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. // and stream; SCOPED_ORIGINS below restricts it to /api/auth + /api/music only.
MUSIC_APP_ORIGIN, MUSIC_APP_ORIGIN,
// OffVault app (Bitwarden-SDK client) — its own custom-scheme origin. Allowlisted so it can reach the // OffVault app (Bitwarden-SDK client) — its own custom-scheme origin. Allowlisted so it can sign in to
// Vaultwarden reverse-proxy; ORIGIN_RULES below restricts it to /api/vault only. It authenticates to // the platform AND reach the Vaultwarden reverse-proxy; ORIGIN_RULES below restricts it to
// Vaultwarden with its own bearer token (not a platform account), so no super-admin rule applies. // /api/auth + /api/vault. Vault access uses its own Bitwarden bearer token (not a platform account).
OFFICER_VAULT_ORIGIN, OFFICER_VAULT_ORIGIN,
].filter((o): o is string => Boolean(o)); ].filter((o): o is string => Boolean(o));
@@ -58,9 +58,10 @@ const ORIGIN_RULES: Record<string, OriginRule> = {};
if (PUBLIC_ORIGIN) ORIGIN_RULES[PUBLIC_ORIGIN] = { superAdminOnly: true }; if (PUBLIC_ORIGIN) ORIGIN_RULES[PUBLIC_ORIGIN] = { superAdminOnly: true };
if (OFFICER_APP_ORIGIN) ORIGIN_RULES[OFFICER_APP_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 }; 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, // OffVault signs in to the platform (/api/auth) and reaches the Vaultwarden proxy (/api/vault) — nothing
// not platform accounts, so the account backstop above never applies to them (verify() → null → passes). // else. No superAdminOnly: the owner signs in here, and vault calls carry Bitwarden tokens (not platform
if (OFFICER_VAULT_ORIGIN) ORIGIN_RULES[OFFICER_VAULT_ORIGIN] = { paths: ['/api/vault'] }; // accounts), so the account backstop never applies to them (verify() → null → passes).
if (OFFICER_VAULT_ORIGIN) ORIGIN_RULES[OFFICER_VAULT_ORIGIN] = { paths: ['/api/auth', '/api/vault'] };
// True when an Origin is reserved for the platform owner (used at signin to reject a non-owner login). // 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 { export function isSuperAdminOnlyOrigin(origin: string | undefined): boolean {