AlumDeck

Security and access

The unglamorous work, described precisely

None of this appeared anywhere on the previous version of this website, which is odd, because it is the part that separates AlumDeck from a theme with a contact form bolted to it.

Two-factor
App or emailed code, RFC 6238, no dependency
Permissions
13 admin areas, granted one at a time
Audit log
17 record types, plus sign-in events
Admin sessions
60 minutes idle, 12 hours absolute

Two-factor

Written from the specification, not pulled from a package#

An admin can use an authenticator app or an emailed one-time code. The authenticator side is an RFC 6238 implementation written for this product with no third-party dependency, checked against the published test vectors, six digits on a thirty-second step, tolerating one step of clock drift. There is a QR code to scan and a typed secret for the phone that will not scan.

Turning it on is itself protected: enrolment needs an emailed code first, which opens a fifteen-minute window. Eight failed challenges lock the account for fifteen minutes and write that to the log. There is a forty-five-second cooldown on resending a code, the session identifier is regenerated the moment two-factor passes, and a half-authenticated session expires after ten minutes. If somebody genuinely loses their device, a single command from the server clears it.

Off by default, one line from compulsory. Every install ships with two-factor available but not required. There is a single configuration line that makes it compulsory for every admin account, and we would encourage you to set it. But we will not claim mandatory two-factor when a fresh install does not have it. Separately, there is no two-factor for member accounts at all.

Sessions

An admin session that ends whether you remember to or not#

Sixty minutes idle

And the panel's own background polls, which fire every thirty seconds or so, are classified as passive: they enforce the deadline but never push it back. A tab left open does not keep you signed in.

Twelve hours absolute

Counted from sign-in, whatever you are doing. There is no way to extend it short of signing in again.

No remember-me in the panel

Admin sign-in offers no remember-me box, and any remember-me session found is terminated outright with its token cycled, because it would walk straight past the rules above.

Bound to the browser, rotated on a timer

The session is tied to a hash of the browser it started in, and a mismatch ends it. The session identifier is rotated every thirty minutes. Signing in from a new address is written to the log, deliberately without locking anyone out, because phones change address legitimately all day.

Permissions

Thirteen areas, handed out one at a time#

There are two tiers and no role system to configure. A full administrator can reach everything. Everybody else holds a list of areas: registrations, members, news, galleries, events, community, association, contact, heritage, giving, surveys, communications and users. An account with no areas at all cannot sign in to the panel in the first place.

The practical version: give the person who runs the reunion the events area and nothing else. Give the door volunteer the same, and they can check tickets in and see nothing else in the building. Give the treasurer giving. None of them can open the member register.

Some things are stricter still and need a full administrator: every settings screen, the backups screen, the member import wizard and the menu builder. The import wizard re-checks on every request rather than only when the page loads.

Self-escalation is closed off, deliberately. A staff account that is not a full administrator does not see the full-administrator switch, and submitting it anyway does not persist. They also cannot grant the users area to anybody, which is the permission that would let somebody edit permissions. And nobody can delete their own account.

The audit log

Append-only, read-only, and specific about its own limits#

Creates, edits and deletes are recorded across seventeen record types, including members, registration applications, users, posts, events, association documents, gallery albums, job postings, contact messages, pages, notable alumni, memorials, committee members, timeline entries, categories, school records and deletion requests.

Alongside those sit the events that matter when something has gone wrong: sign-in, sign-out, failed sign-in with the email address masked, sessions terminated with the reason, sign-in from a new address, two-factor lockouts, two-factor turned on and off, member deactivation and anonymisation, member imports that succeeded and failed, and every change to a tracking snippet. Each row carries who, what, when and the IP address.

The table has no update timestamp and the admin screen has no edit or delete action of any kind. Rows are pruned monthly, keeping a year by default, and the floor is thirty days: it cannot be configured down to nothing.

The Audit Logs screen in the admin panel, with four columns headed When, Who, Event and Detail. The newest row records a login by Demo Administrator with the detail User signed in. The rows beneath it record created and updated events from August 2026, some attributed to a named person and some to system, each naming the record affected, such as Member number 12, Ravi Deshpande, created. A sidebar on the left lists Backups, Audit log and Users under a System heading.
This is the whole screen. There is no edit action, no delete action and no way to change a row from inside the panel.

Three things it is not. It records which fields changed, never the values, so there is no before-and-after view and nothing that could be described as a diff. It does not record the browser. And it is append-only and read-only in the admin panel, which is not the same as storage-level immutable: somebody with database access can still reach it. Gifts, campaigns, email campaigns, surveys, menus and media are not audited at all.

Two quieter defences

Exports and admin-written content#

Spreadsheet formula injection

Every CSV export escapes cells that begin with a character a spreadsheet would treat as a formula. The attack it stops is real and specific: a member sets their employer to a formula, and it runs on a committee member's laptop when they open the export.

Cross-site scripting in rich text

All admin-written rich text passes through an allowlist sanitiser when it is rendered, not when it is saved. Scripts, frames, embeds, styles and event handlers are removed with their contents, links are restricted to safe schemes and given safe attributes, and top-level headings are demoted so admin content cannot break the page structure. The intent is that even a compromised admin account cannot store something executable in a public page.

Alongside those: security headers on every response, a strict transport policy over HTTPS, rate limits declared per route rather than globally, and correct visitor addresses behind Cloudflare so those limits apply to the right person.

What we will not claim. AlumDeck has not had an independent security audit. The sanitiser described above has no automated tests over it. Both of those are true today, and you should weigh them against the fact that you can read the source and that your data is on your own server rather than in somebody else's multi-tenant database.

Questions about security and access#

Is two-factor authentication compulsory?

Not as shipped. It is available to every admin account and each person can enable it, and there is a single line in your configuration that makes it compulsory for everyone. But a fresh install writes that line as off, so if your committee needs mandatory two-factor, somebody has to turn it on deliberately.

Does the audit log show what changed?

It shows which fields changed, never the old and new values. You get a record saying the email and city fields were changed on that member, by that person, at that time, from that address. You do not get a before-and-after comparison, and no setting produces one.

Can a limited staff account promote itself?

No. For anyone who is not a full administrator the full-administrator switch is invisible and would not save even if it were submitted, and they cannot grant the users permission to anyone. Nobody can delete their own account either.

Has AlumDeck had a security audit?

Not an independent one. That is worth saying plainly rather than implying otherwise with a badge. What we can point at is the specific work described on this page, and source you can read.

What happens to a member who leaves a laptop open?

Member sessions are ordinary sessions. The hardening described here applies to the admin panel, where an idle session ends after an hour and every session ends after twelve regardless. Members do not get two-factor at all.

See the audit log and the permission screen

Both are open on the demo. Create a limited staff account and watch what disappears from the menu.