The situation
A life sciences company needed a quality management system, the kind of platform that holds all the controlled documents, the standard operating procedures, the training records, the change controls that a regulated manufacturer runs on.
The reason this is hard has nothing to do with the features. Plenty of tools can store a document and track a few versions. The reason it is hard is that in a GxP environment, the system itself becomes part of what gets inspected. When an auditor walks in, they do not just look at your product. They look at the system you used to control the quality of that product, and they expect it to prove, on demand, that every controlled document was created, reviewed, approved, and retired properly, by the right people, in the right order, with a record of all of it.
If the system cannot show that, it does not matter how nice it looks. A gap in the audit trail is a finding. A finding can hold up a release, or worse.
The question was never “can we build a document manager.” It was “can we build something that will still be telling the truth when an auditor is sitting across the table asking it to.”
The hard part
The obvious hard part is the compliance itself, and I will come to that, but the one that actually shaped the whole build was subtler.
A quality platform is not one module. It is a dozen of them. Document control, training, change control, CAPA, supplier quality, and so on. And every single one of them has the same compliance requirements underneath. Every one needs an immutable audit trail. Every one needs electronic signatures tied to a real identity. Every one needs a controlled lifecycle where you cannot skip a step. Every one needs to prove its records have not been altered.
The tempting way to build that is module by module. You build document control, get it compliant, then build training, and somewhere along the way training ends up with a slightly different audit format, a slightly different signature flow, a lifecycle that works a little differently. Now you have a dozen modules that are each sort of compliant in their own way, and when the auditor asks why the training records and the document records tell their history differently, you do not have a good answer. That inconsistency is exactly the kind of thing that turns into a finding.
So the real hard part was resisting the module-by-module approach, and instead building compliance once, as a shared foundation, and making every module inherit it. That is harder up front. It is the thing that holds up under inspection.
There was a second problem that looks simple and is not, and it is the one that really tests whether a system understands GxP or just decorates it. What happens when a document that is already effective needs to change?
In an ordinary document system, you just edit it. In a controlled environment, that is the one thing you absolutely cannot do. An effective document is the current instruction that people are working to right now. If you quietly edit it, you have destroyed the record of what the instruction used to be, which version was in force last month, and what people were actually following when they did the work. That is not a small bug. That is the exact gap an auditor is trained to find, and it can call into question every activity performed against that document.
So “change an effective document” cannot mean “edit it.” It has to mean something much more careful, and getting that flow right, without ever leaving a window where the wrong version is in force or where the history is ambiguous, is where a lot of the real work went.
What we did
We built the compliance substrate first, and then built the modules on top of it, so they inherit it rather than each reinventing it.
At the centre is the way controlled documents are handled, because that is where the GxP requirements are sharpest, and every document carries the properties an auditor actually asks about, enforced by the system rather than by procedure. Every document has a clear identity, a known origin and owner, an integrity guarantee, and a known effective date with an automatic review date after it.
Integrity is worth dwelling on, because it is where the naive approach quietly fails. You cannot prove a record is unaltered by trusting a database row and a “last modified” date, a row can be changed and a timestamp can be forged. So every version is stored immutably with a SHA-256 content hash. You can re-hash any version and compare, and prove it is exactly what it was when it was signed, years later if you have to.
Underneath is a lifecycle the system enforces rather than suggests. A document moves through draft, in-review, approved, effective, and eventually obsolete, and the transitions are strictly validated. You cannot approve something that was never reviewed. You cannot make a document effective without the approval being on the record. You cannot obsolete something that was never effective. Every transition is written to a history trail with who did it, when, and why, the ones that matter require an electronic signature tied to the person identity, and actions like rejecting or obsoleting a document force a reason to be recorded.
That lifecycle is also how we solved the problem of changing an effective document. You never edit the effective one. Instead, the system creates a new version that starts its own life back at draft, and that new version goes through the entire cycle again, review, approval, signature, on its own. The document everyone is currently following stays effective and untouched the whole time. Only at the moment the new version is approved and made effective does the old one move to obsolete, and that handover is a single recorded, signed transition. So there is never a moment where nothing is in force, and never a moment where two versions are both effective. Both versions are kept forever.
The part we are most satisfied with is that none of this lives only in the document module. It is the substrate. Training, change control, supplier quality, and the rest sit on the same audit trail, the same signature model, the same lifecycle discipline. When an auditor moves from one part of the system to another, the records tell their history the same way everywhere, because underneath, it is the same machinery.
The outcome
The platform was built and delivered across 22 phases of work, as a multi-tenant system where the controlled-document characteristics, the enforced lifecycle, the immutable audit trail, and the electronic signatures are part of the foundation, and where the other quality modules inherit that foundation rather than each implementing their own version of it.
What the client got is a quality system where the honest answer to “can this survive an audit” is built into how it works, not written into a binder of procedures designed to cover for what the software cannot do.
If you are facing the same thing
If you are building or buying a system that will end up inside a regulated process, the useful question is not “does it have an audit trail and electronic signatures.” Almost everything can claim those. There are two better questions. First, are the compliance properties structural, or were they added at the end to check a box. And second, are they consistent across the whole system, or does each part do compliance slightly differently. Auditors probe both, and it is the second one that catches most people out.
Getting that right means deciding, before you build the features, what the system has to be able to prove about itself at any moment, building that as a foundation, and then making every module stand on it. We have now done that inside a GxP quality system, a HIPAA billing system, and a financial-services assurance platform. The domains are different, but the discipline is the same one every time: build the thing that has to be true underneath everything, first.
Putting software into a process that gets inspected?
That is the conversation worth having. If you are building software into a regulated process, we have done this before, and we can talk through what has to be structural for it to hold up.
Start a conversation →