A document update becomes more complicated when a team needs to explain who requested it, why it was necessary, who approved it, and what changed between versions.

I recently led development of a company platform built around that workflow. I wrote the project documentation and implemented both the frontend and backend, with support from my team.

The platform brings together project documentation, change tickets, review, publication, version comparison, attachments, and notifications.

These are some of the engineering decisions that shaped the implementation.

Turning the workflow into explicit steps

The process starts with an approved document baseline.

A user proposes a change and records the reason. The work is authorized, implemented, submitted for review, and then approved or returned for changes.

Publication can happen immediately after approval or wait for the author to publish.

These distinctions affect the interface. Users need to understand whether a ticket is waiting for authorization, ready for implementation, awaiting review, or approved for publication.

They also affect the backend. Each transition needs permission checks and validation against the current state.

I kept the requested-change notes separate from the document content. That preserves what someone originally asked for alongside what was eventually implemented.

Keeping concurrent requests consistent

The application allows one open ticket per documentation section.

Checking whether a ticket exists and then inserting another in separate operations creates a race. Two requests could both observe that the section is available.

The backend checks for open work while holding the document row lock inside a transaction.

Approval has a similar consistency requirement. Creating a version, updating the document’s current-version pointer, and recording the decision all describe one action. The transaction needs to keep those records consistent.

Version ordering also deserved attention. Labels such as 1.9 and 1.10 are readable, but comparing them as strings can produce the wrong order. A separate numeric sequence gives history and filters a reliable ordering key.

Making the tests follow the current product rules

The project includes unit, database integration, and API end-to-end tests.

Some CI failures came from test fixtures that still reflected earlier requirements.

Project creation had become restricted, but fixtures were still trying to create projects with ordinary newly registered accounts. Other tests expected ownership transfers or submitted ticket work before it had been authorized.

Fixing them required checking the controllers, services, and migrations,