How We Reviewed a 13-Application Intranet Before Cutover
The short answer
A large internal platform needs more than a test suite. We planned work in bounded slices, resolved research questions against the code before implementation, recorded architectural decisions while they were still live, and used independent security review plus live smoke testing as shipping gates. Code completion and organisational cutover remained separate claims.
By Timothy Indarsingh, Founder & CEO, Firelinkx
This is the delivery-method companion to our intranet platform case study. The platform spans thirteen domain applications, multiple services and roughly fourteen hundred tests. The delivery capacity behind it is a three-person internal IT department that also has to operate the insurance group's existing systems. Under those conditions, speed is not the interesting claim. The interesting question is how a small team replaces the peer review, handoffs and specialist scrutiny that a larger programme gets by default.
Our answer was to make the work unusually inspectable. Plans, research questions, decisions, execution deviations, test claims, findings and completion records live beside the code. Review is a gate over the cumulative change, not a quick approval at the end. And the project says plainly where software delivery stops and organisational cutover begins.
A slice begins with its boundary
Every increment has a numbered plan written before implementation. It names the contracts and migrations expected to move, the behaviour being added, the verification required and the work explicitly excluded. The exclusions matter as much as the scope. A plan can state that it delivers receipt handling while deliberately leaving reservation, transfer, notification and stocktake work for later.
That makes an incomplete state deliberate rather than accidental. The inventory domain, for example, accepted inbound stock for a full release before any deduction path existed. The boundary was documented and safe. Nobody could confuse the increment with a complete stock ledger, and the next slice could design drawdown against a stable receipt model instead of building both sides speculatively.
The completion record closes the loop. It lists what actually landed, which tests ran, what changed from the plan and what remained outside the slice. When implementation discovers something the plan did not foresee, the deviation becomes part of the record instead of being cleaned out of the story after the fact.
Research questions are gates, not notes for later
A plan can look complete while depending on an assumption about the existing code. Before work starts, the project identifies questions that have to be answered from the repository itself: where authorization is really resolved, which model owns a state transition, whether a database constraint already expresses an invariant, or which service is authoritative for an identifier. Implementation waits for those answers.
This avoids a common failure in established systems: designing the correct feature for an imagined codebase. A research gate can end by confirming the plan, revising it, or narrowing the slice. What it cannot do is remain an unanswered comment while implementation proceeds on the most convenient assumption.
Our working definition of ready
A requirement written down but not checked against the current code is not resolved. A test claimed but not rerun on suitable infrastructure is not verified. A feature built but not exercised in the running application is not demonstrated.
Decision records capture the argument, not only the winner
The project carries nineteen architecture decision records. They cover infrastructure and boundaries, but also vocabulary. One decision exists because a single ambiguous term was doing three jobs across contracts, models and audit columns. Retiring it required new names, a migration and changes across the live codebase. That is not a visible feature, yet leaving the ambiguity would make every later feature harder to reason about.
A useful decision record preserves the alternatives while they are still credible. Months later, the chosen design can look inevitable and the rejected option foolish. The record shows what each option cost at the time, what evidence was available and which consequence we accepted. That context is especially valuable when a later requirement reopens the same trade-off.
Architecture boundaries are then enforced where possible. Import rules prevent layers from reaching across the approved dependency matrix. Navigation is filtered through the set of implemented route identifiers, making a menu link to an unfinished page structurally impossible. Small guards like that remove entire classes of embarrassing failure without relying on somebody to remember a release checklist.
The review ladder asks different questions at each rung
- Tests are written with the slice and protect the behaviour the implementation team believes it built.
- A mandatory security review examines the cumulative change as a merge gate, with findings identified and tracked to resolution.
- Independent review rounds revisit the same cumulative diff instead of assuming the first reviewer exhausted it.
- A live smoke test exercises the running application separately from the automated suite.
- Out-of-scope discoveries are filed and preserved rather than being slipped into the branch without their own plan.
The layers are intentionally redundant in coverage and different in perspective. Tests are good at preventing a known rule from regressing. An independent reviewer can question the rule itself. A live test can expose a missing interaction or a screen that technically renders but does not let a person finish the task. Folding all three into one confidence score would hide which kind of evidence is absent.
This process found a permission resolver that ignored a narrower scope, a delivery permission combined too broadly with a role grant, a missing resource lock and an approval check that behaved incorrectly for an empty collection. Each issue was corrected before release. More tests written from the original mental model would not necessarily have found them; the review step had to question that model. The authorization examples are explained in Permission Bugs Are Silent, with the fixes and pre-release status attached.
A live finding is not permission to expand the slice
The smoke test found front-end gaps that were real and still outside the increment being verified. We filed them as issues instead of correcting them inside the review session. That preserved the evidence and let each gap receive its own scope, regression check and completion record. Quietly fixing whatever appears during a live review makes the branch harder to explain and can invalidate the baseline other reviewers are using.
Urgent security findings are different: they block the merge and are resolved through the numbered finding process. The distinction is not severity versus inconvenience alone. It is whether the observed issue violates the slice's shipping gate or describes valuable work outside the promise being tested. Writing that rule down prevents both casual scope growth and the use of 'out of scope' as an escape hatch for a release blocker.
Record the starting state before remediation
A remediation round begins by recording the exact commit, working-tree state and test counts for each application. If a known defect is being handed forward, the pre-flight confirms that it still exists and that the written description still matches it. This prevents a later round from proving a different starting condition than the one it claims to address.
One known defect was held as a strict expected failure. The test suite would complain if the defect disappeared without the record being updated. That sounds backwards until you consider the alternative: somebody fixes the symptom incidentally, the explicit remediation plan becomes stale, and nobody knows whether the underlying condition was addressed or merely moved.
Some rounds changed no production code. They added missing tests or re-verified claims from the previous round on fresh infrastructure. A deliverable whose conclusion is 'we now know the earlier change is true' can be difficult to schedule, but treating another branch's closing note as evidence would make independent review performative.
Fixtures and documentation have to survive contact with the code
Mock-data fixtures had drifted far enough to describe fields that no longer existed and models that had never existed. We rebuilt them against the current schema, removed the fictional parts and verified the full load order into a scratch database. Documentation that looks detailed but cannot initialise the application is worse than a shorter guide whose commands still work.
The repository also includes guided code tours for different readers: a short orientation, day-one onboarding, architecture and module boundaries, domain internals, an end-to-end request trace, and a security reviewer's tour of trust boundaries and known gaps. The last one is the strongest signal. It does not make reviewers rediscover the intended security model before they can challenge it.
The commit mix corroborates the method. Documentation changes outnumber feature changes because plans, decisions, completion records, fixtures and remediation notes move with the implementation. The large number of fix commits needs context too: they are predominantly numbered findings from internal pre-release review, not a history of users discovering defects after launch. A count without provenance says very little about quality.
The working rhythm is episodic as well. Delivery happened in concentrated pushes around the department's operational responsibilities, not as an artificial steady stream. That is why resumable records mattered: the next working session needed to recover the exact boundary, open questions and verified state without relying on memory of a conversation weeks earlier.
Code complete is not cut over
The first two stage groups are built and tested across identity, requisitions, inventory, directory, communications, knowledge, helpdesk, booking and reporting. The project does not translate that statement into 'the organisation has fully adopted the platform.' Parallel-run reconciliation, operational ownership and business sign-off remain cutover criteria. They are labelled as business process rather than code.
That separation prevents technical completion from forcing an operational claim the evidence cannot support. A migration can compile, a workflow can pass end-to-end tests and a security review can close, while the department still needs to compare results with the existing process and accept responsibility for the new one. Treating those as different gates makes the remaining work visible instead of making the project appear more finished than it is.
What a small team has to buy back
A small team can move quickly because coordination is cheap. What it loses is the natural adversary: another specialist who did not share the design conversation and therefore does not share its assumptions. Tests cannot replace that person when the test author and implementer misunderstand the same requirement.
The plans and records make the system reviewable; they do not review it. The independent gates supply the disagreement. They are slower than approving a green build and cheaper than discovering a silent authorization error after cutover. Compressed delivery works only when scrutiny is treated as planned production work rather than spare time at the end.
The takeaway
The delivery method is a chain of falsifiable claims. The plan says what the slice will do. Research checks that plan against the real code. Decisions record the trade-offs. Tests exercise the understood rules. Independent review challenges the understanding. Live testing checks the usable result. Cutover waits for organisational evidence. Any missing link leaves a different kind of uncertainty, so none should be disguised by the overall size of the test suite.
Ready to replace your manual workaround?
Firelinkx helps Guyanese businesses get this right. Get a clear scope, timeline, and price, or just ask a question. We respond within 24 hours on business days.