Download Latest Version Nelsar.Axia 0.2.1 source code.zip (2.4 MB) Google Add to Preferred Sources
Home / v0.2.0
Name Modified Size InfoDownloads / Week
Parent folder
Nelsar.Axia 0.2.0 source code.tar.gz 2026-10-13 2.0 MB
Nelsar.Axia 0.2.0 source code.zip 2026-10-13 2.4 MB
README.md 2026-10-13 5.3 kB
Totals: 3 Items   4.4 MB 1

Hardening after the first release, and fixes to the console. Upgrading from 0.1.0 takes one step: the API's container no longer runs as root, so its volumes have to be handed to uid 1654 before the new image starts — see Changed.

Security

  • An account switched off in the directory loses its session within 30 seconds, instead of keeping it until the token expires: disabled or expired in Active Directory, locked by an administrator through OpenLDAP's password policy, or login-disabled in eDirectory. It can no longer sign in either, including against a directory that does not enforce those flags itself. A lockout after failed sign-ins does not count, so that nobody can end someone else's session by mistyping their password.
  • Directory calls give up instead of waiting indefinitely: a directory that accepts the connection and then does not answer is reported as unavailable after Ldap:OperationTimeoutSeconds, so it can no longer tie up the API's request threads. This includes StartTLS, which the LDAP library could not time out on its own.
  • Bulk batches are bounded: 100 rows when processed while the caller waits, 10,000 when queued, and at most 10 jobs waiting in the queue — a full queue answers 503 with Retry-After. A queued job's status and results can only be read by the account that queued it, in the same directory; before, anyone holding users.bulk could read any job by its id.
  • Organizational units and computers are held to the same rule as accounts and groups: nobody acts on something more powerful than they are. Renaming or moving a unit is judged by what it holds — a group mapped to a role the caller lacks, anything privileged in the directory, or the bind account — because everything beneath it is re-addressed; with orgunits.manage and users.update, moving the unit that held the Admin group used to be a way to reset an administrator's password. Domain controllers, read-only ones included, and other privileged computers can only be changed or deleted by someone holding every permission.
  • Units, groups and computers can only be created in, or moved to, a parent inside the base DN. The parent used to be whatever DN the request named, so anyone allowed to manage them could write one anywhere the bind account could.
  • Failed sign-ins are limited per account as well as per client address: after 5 in 15 minutes, from any number of addresses, the account's attempts are refused with 429 until the window ends, without being passed to the directory, so guesses spread over many addresses no longer count towards its lockout there. A successful sign-in clears the count. The limits are the new auth-login-account row on the Rate limiting page.
  • The console's image sends a Content-Security-Policy that allows nothing but its own origin, along with Cross-Origin-Opener-Policy, Permissions-Policy and Strict-Transport-Security. A script injected into the page, from another site or written inline, does not run.
  • Where the console is served with the API — built with VITE_API_SAME_ORIGIN=true, as the image is — its sign-in screen no longer offers to change the API address, and an address saved in the browser earlier is ignored. A link that set one could send the next sign-in, password included, to someone else's server.
  • Every API response says Cache-Control: no-store, so a session token, directory entries or the audit trail are kept by no cache, together with X-Content-Type-Options, X-Frame-Options, Referrer-Policy and a Content-Security-Policy. The Server header is no longer sent.
  • The API's container runs as the .NET images' unprivileged user, uid 1654, instead of root.

Added

  • Ldap:ConnectTimeoutSeconds (10) and Ldap:OperationTimeoutSeconds (30).
  • A rate-limited request is answered with Retry-After.

Changed

  • The console is built with React 19, Vite 8 and TypeScript 7, and CI builds it on Node 22. Building it from source now needs Node 20.19 or later, 22 recommended.
  • On upgrade: the API no longer runs as root, so whatever it writes to — /data and /app/logs — has to belong to uid 1654. Volumes created by 0.1.0 and host directories belong to root; hand them over before starting the new image: sudo chown -R 1654 /srv/nelsar-axia/data /srv/nelsar-axia/logs, with your own paths. The quick start's init container does this for its own volumes.

Fixed

  • An attempt to change something that an endpoint refused for want of a permission is recorded in the audit trail, as a failure, with who made it and the permission it needed. Only refusals made inside a use case were recorded before, so the commonest one — a permission not held at all — left no trace.
  • An account's detail view shows its groups. In a directory without memberOf it showed none, for accounts that were members, whenever the full listing had been read first.
  • An account opened from a search shows its login and DN, which read "—".
  • The dashboard counts groups and organizational units again; it asked for a page larger than the API serves and showed "API unavailable" for both.
  • The audit log's details wrap inside the table instead of running past its edge, and the signed-in user's name in the sidebar is no longer drawn under the theme toggle.
Source: README.md, updated 2026-10-13