Context
UK supported housing providers are regulated. They hold sensitive personal data about vulnerable residents, they are inspected against care standards, and they must be able to produce evidence on request — who did what, when, and on whose authority. Most of them run this on a spreadsheet estate: residents in one workbook, incidents in an email thread, compliance evidence in a shared drive that one person understands.
I have worked in and around that sector, which is where the problem came from. It is not a market that needs another dashboard. It needs a system that can answer an inspector's question without anyone having to go and look for the file.
The problem
Three constraints pull against each other in this domain:
- Isolation. Multiple organisations on one platform, and a cross-tenant data leak in this sector is not a bug report — it is a data protection incident involving vulnerable adults.
- Evidence. Compliance is not a status field. It is a trail: the document, its version, who uploaded it, who read it, and when.
- Usability under pressure. The people entering this data are support workers at the end of a shift, not analysts. An eleven-step onboarding form that loses your work on a dropped connection will simply not be used.
What I built
Tenancy as a data-model property, not a filter
Every domain row carries an organizationId and access is scoped at that level rather
than by filtering in the application layer. One database, logical separation per organisation. The
distinction matters: a filter you can forget to apply is not an isolation boundary, it is a
convention. Scoping the data model means the wrong query returns nothing rather than returning
someone else's residents.
Documents encrypted, hashed and time-limited
Documents are encrypted at rest with AES-256-GCM and hashed with SHA-256, and downloads are issued as time-limited tokens rather than as durable URLs. TLS 1.3 covers transit. The design goal was that possession of a link, a database dump, or a stale browser tab should each be insufficient on its own.
Four-tier RBAC with an audit trail behind it
Admin, Operations, Support Worker and Viewer — four roles, because a care setting genuinely has four levels of legitimate access and inventing a fifth would just push people into sharing logins. Every user action writes to an audit log. Authentication is JWT in HTTP-only cookies with bcrypt-hashed passwords, Helmet security headers, and rate limiting on the auth paths.
The modules that actually get used
Resident management with an eleven-step onboarding wizard (autosave, per-step validation, resumable progress); properties and room allocation; staff management; incident tracking with full audit trails; compliance tracking; weekly support notes with PDF export; and reporting across all of it.
An AI layer that stays advisory
Claude is wired in for compliance chat, risk surfacing and policy review. What it is deliberately not wired to do is take an action on a resident record. In a regulated care setting, a model that can silently change a compliance status is a liability dressed as a feature. It reads, it advises, a human decides.
A written design system before the screens
The interface is governed by a design specification written before the components: a Material Design 3–derived approach chosen deliberately for data-dense enterprise screens, with a documented light and dark palette in HSL, a nine-step type scale, spacing primitives, and patterns for tables, modals and multi-step forms. Four principles govern it — information hierarchy, workflow efficiency, trust and professionalism, and scalable complexity.
Decisions I would defend
One database with row-level scoping, not a database per tenant
Database-per-tenant is the reflexive answer and it is the right one at a different scale. At this one it multiplies migration risk by the number of customers, and a schema change that half-applies across twenty databases is a far more likely failure than a scoping bug in a codebase where every query goes through the same access layer. I chose the failure mode I could test.
Encrypting documents even though it complicates every read path
It would have been faster to rely on storage-level encryption and call it done. Application-level AES-256-GCM means every read and write goes through the crypto path and every bug there is visible. For files describing vulnerable adults, that is the correct trade: the cost is my time, and the alternative externalises the risk onto residents.
Autosave on the onboarding wizard
Eleven steps is a lot of form. The engineering-convenient answer is a single submit at the end. The real-world answer is that the person filling it in is interrupted — that is the nature of the job — so the wizard autosaves and resumes. Documenting it as a reusable interaction pattern rather than a one-off screen means the next long form inherits it.
Saying "in demonstration discussions" and nothing more
AccomPro has no paying users. It is in demonstration discussions with a supported housing provider. I state that precisely, on the portfolio and here, because the first thing a technical reviewer does with an inflated traction claim is discount everything next to it.
The result
- A working multi-tenant platform covering residents, properties, staff, incidents, documents, compliance, support notes and reporting.
- Security design that holds together as a set rather than as a feature list: isolation at the data model, encryption at rest and in transit, RBAC, and an audit trail that makes both observable.
- A UK GDPR–conscious design and an ITIL-informed view of the service around the software, not just the software.
- A running demonstration environment with seeded data, so a prospective user sees the product rather than an empty state.
What I would do next
Automated cross-tenant isolation tests in CI — the property that matters most is currently guaranteed by design and review, and it should be guaranteed by a test that fails loudly. After that, evidence export: an inspector-ready pack generated from the audit trail rather than assembled by hand, which is the feature the sector would actually pay for.
My role and stack
Role: Solo engineer and designer — architecture, data model, backend, frontend, security design, design system, demo environment.
Frontend: React, TypeScript, TanStack Query, shadcn/ui (Radix + Tailwind), Vite.
Backend: Node.js, Express, TypeScript, Prisma, PostgreSQL (Neon), JWT, Helmet, Zod.
Security: AES-256-GCM at rest, TLS 1.3 in transit, SHA-256 document hashing,
time-limited download tokens, four-tier RBAC, full audit logging.