The Gotify and ntfy tokens, the SMTP password and the webhook secret were stored
as plain text in the settings table. They are now encrypted with the same key as
integration credentials (CREDENTIALS_ENCRYPTION_KEY), marked with an "enc:v1:"
prefix. Settings are decrypted when read and encrypted when written, so nothing
else changes; values saved before this are converted at startup.
An edit that doesn't touch a credential keeps its stored ciphertext, so a wrong or
missing key (which reads as empty) can't be made permanent by an unrelated edit.
Without a key new credentials fall back to plain storage, and the startup warning,
.env.example and the Privacy page say so.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Name lists now live in settings instead of the web bundle. Admins edit them under
Settings -> Names (add/remove names, create/rename/delete lists, reset a built-in
list). Names are folded to hostname-safe form (a-z, 0-9, hyphen) and validated on
the server; saves are audited.
Adds Swedish boy names, Pixar, Norse mythology and Astrid Lindgren lists, and
lengthens the Swedish girl and Disney lists. "Mixed" is now every list with each
name counted once.
Admins can preview and import the most common Swedish names from Skatteverket's
open "Namn pa nyfodda" data (girls or boys, latest 1-5 full years); nothing is
stored until the editor is saved. The old comment that credited SCB statistics is
gone: SCB stopped publishing name statistics after 2023.
Privacy page, README and ROLES updated for the new outbound call and page.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A check of every write path found gaps in what the audit log captured:
- Sign-ins and sign-outs are now recorded with the IP they came from
(sign-out is recorded first and can't block signing out).
- A new account is recorded when it's created on first sign-in, including
when the very first user becomes admin - so the log shows who gained
access, not only who changed things.
- The automatic log purge, which deletes audit entries, now records
itself, attributed to "system". recordAudit() takes an optional actor
for this. It only records when something was actually deleted.
- Settings updates record what changed (before and after) instead of only
which sections were touched. The notification channels (Gotify, ntfy,
SMTP, webhook) record field names only: they hold credentials, and
webhook URLs and public ntfy topics act as secrets, while the audit log
is readable by operators and Settings is admin-only.
- Integration edits record renames, enabling/disabling, whether
credentials were replaced (never the credentials), and which settings
fields changed (names only).
The Privacy page and README now say sign-ins store an IP in the audit log.
Verified through the real routes against a scratch database: user
creation, the logout route, the automatic purge, settings and
integration edits - including that a secret token and a webhook URL
appear nowhere in the stored entries. The sign-in callback itself needs
a real identity provider and wasn't run.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A page every signed-in user can open. It states what the installation
stores (accounts, sign-in sessions, audit and diagnostic logs, server
reports, the secrets tracker, credentials, inventory) and for how long,
where data goes (Authentik, integrations, DNS providers, notification
channels, domain registries, certificate checks, port scans), what lives
in the browser, who can see what, and how to limit or remove data.
Written from what the code actually does, including the uncomfortable
parts: the session file keeps the user's Authentik ID token plus the IP
and browser from sign-in; audit entries keep a name snapshot after an
account is gone; the app has no delete-account function; cron commands
in agent reports can contain sensitive text. It also says what isn't
there -- no telemetry, update checks, third-party scripts, fonts or
tracking cookies -- which was checked against the web build and the
server's outbound calls before being asserted.
Live values rather than boilerplate: log retention (and whether it's on),
which integration and DNS provider types are enabled, how many domains,
certificate checks and reporting servers, and which notification channels
are on. Channel addresses are shown to admins only, and only the host --
never a path, query string or token -- since a webhook URL can embed a key.
Each user also sees their own account and active sign-ins, and can
"Download my data": their account, their sign-ins and the audit-log entries
made under their account, as JSON. Only their own -- never another user's --
and without session ids or ID tokens. The export is itself audit-logged, so
a later export shows it.
Verified with 23 backend checks (own-vs-others isolation for audit counts,
sessions and export; no session ids, ID tokens or channel secrets in any
response; admin-vs-viewer channel visibility; live counts; audit of the
export; auth) using an isolated session directory so real sessions are
never read, and in a browser against the real router, including the
download. Real dev database and session files untouched.
Not legal text: this is a transparency page for the people using the app,
not a privacy policy or a GDPR compliance document.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>