update.php antwortet bei Validierungsfehlern mit HTTP 422 und nennt den
Grund im Body. Bisher warf Axios dabei nur "Request failed with status
code 422". Jetzt werden 4xx-Antworten ausgewertet und msg bzw. der Body
in die Fehlermeldung uebernommen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agrarmonitor hat eingangsrechnungen.php entfernt (404). Das
Bearbeiten-Formular kommt jetzt von editForm.php?invoiceID=<id>,
gespeichert wird per JSON-POST an update.php mit
{ rechnungID, formData }. setRechnungsdaten laedt dafuer das
aktuelle Formular, uebernimmt alle Felder und ueberschreibt nur die
geaenderten Werte. Eine Fehlermeldung (msg) aus update.php wird als
Exception weitergegeben.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The login flow was near-silent: three info lines with no way to see why a
session was considered expired or what happened to the cookies. Debugging
a failing login meant guessing.
Every login step now logs on debug level with a `phase` field: the login
page fetch, the extracted nonce, the POST to /login/api/login.php, the
session check, and any request retried after a re-login. Each of those
requests is bracketed by a cookie snapshot taken before it is sent and one
taken after, plus a delta of added/changed/removed cookies. The "before"
snapshot is logged prior to sending, so it survives a hanging request.
isLoginRequiredResponse() is split so the criterion that matched
(status-401, login-markup, ...) can be reported instead of just a boolean.
Secrets stay out of the log: the password is replaced by ***, and cookie
values - including those in the raw Set-Cookie header - are truncated to
their first four characters plus length. That still shows whether a
session id changed without putting the session itself in the log.
Detail logging is strictly debug-level via logLoginDetail(); the existing
logDebug() falls back to info, which would flood a plain info logger. When
no debug logger is attached, no snapshot is taken and nothing is
serialized.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The session check treated any response containing "Anmeldung" or
"Einloggen" as an expired session. Regular content pages (e.g. the FAQ)
mention these words in body text, which triggered a needless re-login and
returned the login page instead of the requested content.
Detection now relies on the status code and isLoginPageText() alone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>