Citizens Advice helps millions of people a year with debt, benefits, housing, consumer and energy problems. Casebook is the Rails application its advisers use to do that work: every client, every case, every appointment, across the national network. I joined the engineering team as one of several senior developers and worked on the core of it.
What the system is
Casebook is the tool an adviser has open all day. It holds the client, the
case, the notes, the evidence, the referrals, the appointments and the
outcome. If it is slow, every adviser is slow. If it loses something, someone
seeking help loses it.
It is a Rails monolith, and deliberately so. Three product areas sit inside it
as mounted engines rather than separate services: the consumer service, money
advice, and a budget planner. One deployable, one test suite, one place to
reason about a case.
Why it is harder than it looks
Who may see a case is the central question. An advice record can contain
debt, disability, immigration status, domestic circumstances. Access is not a
checkbox on a user; it depends on the case, the office, the service and the
role. The system carries 65 authorisation policies, with their own test
matchers, because getting this wrong in the permissive direction is the worst
thing the software could do.
Consent is a moving object. People give consent, withdraw it, limit it to
one organisation, or ask for confidentiality against part of their own record.
The schema treats that as a first class concern: consent history,
confidentiality disclosures, per case consent answers, contact preferences.
None of it is a flag.
Forgetting is a feature. Records expire. Referral summaries have to be
produced in anonymised form. Everything an adviser types is scrubbed before it
is stored or shown, through a family of scrubbers written per content type
rather than one blunt sanitiser. That last point is the kind of detail that
only exists because someone was paying attention.
Appointments are a product inside the product. Calendars, templates,
custom days, bank holidays, locations, bookable advisers, and a full booking
lifecycle including check in and no show. It is a scheduling system that
happens to live inside a case management system.
It has to stay fast while it grows. Searching for a person by name across
a national caseload was engineered rather than assumed; the team wrote down
the decision to use edge ngram indexes and why.
How the team worked
The thing that stands out, reading it back, is the discipline. 658 spec files
and 221 Cucumber features, on a codebase this old, is not an accident. Nor are
thirteen architecture decision records, Brakeman in the pipeline, Dependabot
on the dependencies, linting in CI, and a local development setup that runs
the real thing on Kubernetes rather than a convenient approximation.
That is the environment I joined. Not a greenfield where you set the
standards, but an established team with high ones already, and other senior
engineers alongside me. My work sat in the core of the system rather than at
its edges.
Why it matters for your project
If you have a Rails application that real work depends on, that has been
growing for years, and that holds data you cannot afford to mishandle, this
is the shape of work I do. I am used to joining a team that already has
standards, meeting them quickly, and being trusted with the core of the thing
rather than the edges.
Stack: Rails 7, Ruby 3.2, PostgreSQL, GraphQL, ViewComponent, Pundit,
Haml, Cucumber, RSpec, Kubernetes (Helm, Skaffold, Tilt), Docker, Jenkins,
GitHub Actions, Brakeman.
Testimonials
Wagner integrated quickly within our team and led core development activities for our Case Management system, the central workflow tool that thousands of advisers relied upon every day. I valued his warm, friendly, and collaborative approach, which contributed towards building a great team culture. I would welcome any opportunities to work and collaborate with him again.