Off by default. Once a PIN is set in Settings -> System & backup, every non-GET /api/*
request (plus GET /api/ammc/config) needs a signed 30-day HttpOnly cookie, which also
closes the unauthenticated /api/update/run restart trigger. A 401 opens a PIN dialog
and the pending save is retried after login. Reads stay open because the public overlay
hydrates through GET /api/state. Optional RC_ADMIN_ALLOWED_CIDRS restricts the same
routes by client address.
The PIN hash and signing secret live in data/, outside the app_state blob, so they
never leak through GET /api/state, exports or backups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
npm audit stays clean (0 vulnerabilities). Checked every new db.prepare()/spawn()/
execFileSync() call added since the last audit for injection risk - none found, all
parameterized SQL and array-form process args. Confirmed the CORS/security-header
middleware still covers every route added since, including the new ones.
One new notable finding: POST /api/update/run unconditionally stops the server before
checking whether an update is even available, making it a more direct denial-of-service
primitive than the app's other already-documented unauthenticated endpoints. No code
change made - tracked alongside the deferred permissions/auth work.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>