Implement scoped upload invites
All checks were successful
Docker / build-and-push (push) Successful in 3m9s

Adds a second, narrower credential type alongside UPLOAD_PASSWORD: an
admin (ADMIN_PASSWORD-gated, /admin) can mint time-boxed, use-limited,
independently revocable invite links (?invite=<token>) that skip the
password screen for one-off sharing without handing out the master
password. Invite consumption is an atomic check-and-increment to avoid
a race on single-use invites; admin surface 503s (not boot failure)
when ADMIN_PASSWORD is unset.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
explewd
2026-07-12 19:29:46 +02:00
parent 0b62776282
commit 266f9708e3
13 changed files with 372 additions and 11 deletions

View File

@@ -1,9 +1,9 @@
export type Credential = { kind: 'password' | 'hash'; value: string }
export type Credential = { kind: 'password' | 'hash' | 'invite'; value: string }
function credentialHeaders(cred: Credential): Record<string, string> {
return cred.kind === 'password'
? { 'X-Upload-Password': cred.value }
: { 'X-Upload-Password-Hash': cred.value }
if (cred.kind === 'password') return { 'X-Upload-Password': cred.value }
if (cred.kind === 'hash') return { 'X-Upload-Password-Hash': cred.value }
return { 'X-Upload-Invite': cred.value }
}
export async function checkCredential(cred: Credential): Promise<boolean> {