4 Commits

Author SHA1 Message Date
0xJacky
90ac073f5c fix(notification): gate notifier changes behind an interactive admin 2026-08-12 13:37:03 +08:00
0xJacky
b06159cb13 fix(demo): block destructive routes in demo mode
A demo visitor could change the admin password and lock everyone out.
The chain: demo mode refuses TOTP enrollment (api/user/otp.go), so
userNeedsSecureSession() is false, so RequireSecureSession() passes
through, and POST /api/user/password had no demo guard of its own.

Everything else with an effect outside the container was open for the
same reason: ACME issuance against a real CA, backup archives carrying
the crypto secret, outbound webhooks, DNS provider mutations, service
token minting, and a site health check whose request body chooses the
outbound destination. Until now the only thing preventing any of it was
that docker-compose-demo.yml disables outbound NAT.

Add RejectInDemo()/DemoReadOnly() and attach them to those routes. Local
CRUD stays open: the demo runs on ephemeral disk and restores itself, so
creating a site is a feature rather than a risk.

Note these guards are not redundant with RequireSecureSession — that
middleware is inert for a user with no OTP, 2FA or passkey, which on a
demo node is every user.

Also move the middleware error scope into its own errors.go: the errdef
generator resolves a scope per file, so errors declared alongside a
scope defined elsewhere were silently missing from the generated
frontend constants.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 00:32:20 +08:00
0xJacky
3a123cf1fa feat(notification): add test message API #1262 2025-07-28 16:46:55 +08:00
Jacky
04de1360c2 feat: external notification 2025-04-09 17:25:07 +08:00