Back to Index

Case study · Platform · Non-profit

Avery & Aubrey's Way Portal

A document portal for a non-profit, inherited from a previous vendor with no source code, security gaps, and uploads that silently failed. Hardened in place instead of rewritten.

RoleDeveloper of record
TimelineMay 2026 – present
StackSpring Boot 3 · Java 17 · MySQL 8 · nginx · systemd · Google Compute Engine
Liveaveryandaubreyswayportal.org
The portal's public home page
The public face. Most of the work is behind the login.

The problem

The organization helps families apply for assistance programs; applicants upload documents, and administrators review them. The previous vendor had left. What remained was a compiled JAR on a single VM, a database, and a front end. There was no repository. Files over one megabyte failed to upload with no error. Access control and the API surface had gaps that a written review documented in detail.

My role

HausHive took over as developer of record. I did the review, the recovery of a buildable codebase, the security fixes, the infrastructure hardening, the deploys, and the client communication. Every change was framed as ours to fix, with the client owning the decisions that needed her account access.

What I built

Architecture

Browsercookie or bearer nginxauth gate · 7 public routesrate limits · 25 MB capTLS · blocked /actuator Spring Boot 3systemd, own userconfig in /etc, 0640JWT iss/aud checked MySQLleast-priv One Compute Engine VM, 2 GB RAM. Files are stored as database blobs, so the upload cap has to match in nginx and Spring.

Request path: browser to nginx gate to Spring Boot service under systemd to MySQL, all on one VM.

Difficult problems

Rebuilding without source. The decompiled project compiles and boots equivalently to the production JAR only after fixing lambda parameter shadowing, raw generic collections, and a constant the decompiler had turned into a reference to a class that did not exist. The build is now trusted enough to deploy from.

The 29-hour outage. The inherited machine lost its network under resource pressure while the cloud console still reported it healthy. Recovery had to preserve the public address, because DNS pointed at it, which ruled out the obvious fix. Resource limits and monitoring followed so it cannot fail silently again.

An unexpected account found mid-deploy. While retiring the previous vendor's access, an administrator account nobody recognized turned up, created through one of the gaps being closed at that moment. It was removed in the same change, and every admin change is now recorded.

// Ownership check on file reads: 404, never 403, so IDs cannot be probed
public FileDTO getById(Long id, User caller) {
    return repo.findById(id)
        .filter(f -> f.ownerId().equals(caller.id()) || caller.isAdmin())
        .map(mapper::toDto)
        .orElseThrow(NotFound::new);
}

Decisions and tradeoffs

Impact

25 MBupload limit, up from 1 MB, the cause of every silent failure
100%of admin changes recorded in an append-only audit log
0deploys needed to add a document category
Previous: GloriaNext: ADUAtlas
Download PDF