auth: add POST /auth/lockdown to trigger the distress lockdown

exposes the duress lockdown as an endpoint (needs the distress password in the
body, rate-limited) so it can be tripped from a shortcut/webhook, not only by
typing the distress password at the login form.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 00:22:48 +00:00
co-authored by Claude Opus 4.8
parent cf2962fd67
commit b96b23d92b
2 changed files with 18 additions and 0 deletions
+3
View File
@@ -19,6 +19,7 @@ import { forgotPasswordHandler } from './forgot-password';
import { resetPasswordHandler } from './reset-password';
import { bootstrapHandler } from './bootstrap';
import { usersMe } from './users-me';
import { lockdownHandler } from './lockdown';
import { passkeyRouter } from './passkey-router';
export const authRouter = createRouter();
@@ -34,6 +35,8 @@ authRouter.post('/signin', signinRateLimiter, signinHandler);
authRouter.post('/signout', userMiddleware, signoutHandler);
// Explicit "revoke the current token" alias (same effect as signout: blacklists this JWT).
authRouter.post('/blacklist-token', userMiddleware, signoutHandler);
// Trigger the duress lockdown programmatically (needs the distress password in the body).
authRouter.post('/lockdown', signinRateLimiter, lockdownHandler);
authRouter.post('/signup', signupRateLimiter, signupHandler);
authRouter.post('/bootstrap', signupRateLimiter, bootstrapHandler);
authRouter.post('/verify', verifyHandler);
+15
View File
@@ -0,0 +1,15 @@
import type { Handler } from 'hono';
import * as errors from '@@/custom-errors';
import { triggerLockdown } from './distress';
const { DISTRESS_PASSWORD } = process.env;
// Trigger the duress lockdown programmatically — same effect as entering the distress password at
// login. Requires the distress password in the body so only its holder can trip it (rate-limited at
// the route). Once tripped, all logins and existing sessions are refused until the server restarts.
export const lockdownHandler: Handler = async (ctx) => {
const { password } = ctx.get('body') as { password?: string };
if (!DISTRESS_PASSWORD || password !== DISTRESS_PASSWORD) throw errors.UNAUTHORIZED();
triggerLockdown();
return ctx.json({ ok: true });
};