Overview

A plain-language companion to the full technical planRebuilding Our Notary Software, Properly

This summarizes a plan to rebuild our notary and finance software on modern, well-supported technology — while keeping every customer's existing records completely safe throughout. It's written for a general business read, not a developer, but it doesn't skip the substance: what's wrong today, what we're actually changing, what the real risks are, and what we need from you.

Stage: Planning, nothing built yet
Customer data: never copied or put at risk
Old system: keeps running during the switch
Scope: 50+ customers, one shared codebase

How this is organized

Nine short pages, each focused on one topic. The sidebar (or the links below on a phone) takes you anywhere directly — you don't have to read in order, though pages 1 and 2 give the most useful overall context if you only have a few minutes.

Start here

What we're fixing in the background

New capabilities we're adding

These are the biggest, most visible changes beyond "same software, newer foundation" — each gets a full page.

Timing

Page 1Why We're Doing This

Our notary and finance software works — the business runs on it every day, and nothing here suggests an emergency. But it was built up over many years by copying the same program for each customer and adjusting each copy slightly. That approach has quietly built up real, specific problems, reviewed in detail below.

One program, 50+ hand-copied versions

Today, each customer effectively runs their own separately-copied version of the software, with their own branding and settings hard-coded in. When we want to fix something or add a feature, it has to be repeated by hand, separately, for each copy that needs it.

In practice, this means the copies have already drifted apart. We found a real, confirmed example: one government fee was added to some customers' copies and never made it into others — so today, the exact same software behaves differently for different customers, not by design, just because a rollout was incomplete and nothing caught it. That's not a one-off accident; it's the natural result of maintaining 50+ separate copies of the same program by hand.

Money records aren't as solid as they should be

Many money amounts in the system are stored as plain text rather than as real numbers. In practice this is similar to keeping accounts in a spreadsheet where some cells are typed as words instead of numbers — it mostly looks fine, but it opens the door to small, hard-to-spot errors in totals, and makes those totals harder to fully trust.

On top of that, when the software shows "how much is owed" or "how much the business has," it doesn't read that from one trustworthy, permanently-recorded total. It recalculates it live, from scratch, by re-running the same business rules — and those rules are written out separately in more than one place. If those separate copies of the same rule ever disagree even slightly, two different reports could show two different answers, and nothing in the system would flag that as a problem.

No safety net between related records

Today, nothing formally checks that connected pieces of information actually belong together — for example, that a payment is genuinely linked to a real, existing client record, or that a document belongs to an office that actually exists. The software mostly just trusts that everything lines up. It's the digital equivalent of a filing system with no rule requiring a folder to actually exist before someone can write its name on a label and file something under it. Most of the time this is fine, but it means a typo or a bug elsewhere can create a "orphaned" record that nothing would catch.

Every office's paperwork tool is its own separate program

The tool that produces our official documents isn't one shared program — every single office has its own, independently written copy, with that office's legal wording typed directly into the program code rather than kept as an editable template. Some of these copies are enormous — comparable in length to a long book. A formatting bug in just one office's copy once needed its own special, one-off repair, which is a real sign of how fragile this approach already is: the exact same bug could exist, unnoticed, in several of the other 45 copies right now.

Staff access is too blunt

Permissions like "can edit" or "can delete" apply the same way across every part of the system a staff member can see — there's no way to say "this person can edit reception records but should never delete them, while also having full control over bank accounts." More detail, including a specific gap we found in how one type of staff account is set up, is on page 5.

A few real security weaknesses

We also found a small number of genuine security gaps during review — nothing known to have been exploited, but real weaknesses worth closing properly. Full detail on page 8.

The good news None of this means our data is unsafe today, or that anything is on fire right now. It means the software has reached the point where patching around these problems, one at a time, forever, costs more than fixing them properly once — while rebuilding on a foundation that makes it much cheaper to add things correctly going forward.

Page 2The Plan, In Short

We're rebuilding the software on a modern, widely-used, well-supported foundation (a framework called Laravel — one of the most common choices for business software like ours, with a large community and a long support horizon), as one single, properly built system that serves every customer, instead of dozens of separately hand-copied versions.

One system, every customer, same look and feel they're used to

Each customer will keep seeing their own familiar setup — their own company name, their own branding, their own staff, offices, and document wording. What changes is underneath: instead of each customer running their own separately-copied program, every customer is served by the same well-maintained codebase, with each one's own database kept completely separate and private from every other customer's. A new feature or a fix gets built once and becomes available to everyone, instead of being repeated by hand 50+ times.

Nobody's information moves or is put at risk

The one rule everything else follows

No customer's records are ever copied, exported, or moved to a new location. Every customer keeps their existing information exactly where it already lives, in the same database they already have. We improve that information in place — fixing real problems directly in the records that already exist — rather than building a fresh copy and switching over to it. There's never an "old data" and "new data" to reconcile, because there's only ever one copy of anything.

This matters because some of our customers have very large amounts of historical data — in the tens or hundreds of millions of records for a few of them. Copying or reshaping that much live, legally-significant information would be slow, risky, and completely unnecessary when the better option — fixing it where it already lives — is available instead.

The old system keeps running until we're sure

While we build the new system, the current software keeps working exactly as it does today, for every customer. Nothing about this project forces anyone off the old system before we're ready. When a customer is ready to move over, we test everything carefully against their real, live information first, and only switch them to the new system once we're confident it's working correctly for them. If anything looked wrong after switching, we could point that customer straight back at the old system — nothing about their underlying information would have changed in a way that prevents that.

We move customers over one at a time

  1. Start with one test customer — a cooperative one with a fairly typical setup, not our most complex or most important account, so an early mistake is cheap to catch.
  2. Check everything carefully against their real, existing records before going live.
  3. Switch that one customer over, and watch closely for a period afterward.
  4. Repeat for a small second group of fairly standard customers, to confirm the first success wasn't a fluke specific to that one account.
  5. Roll out to the rest of our standard customers, gradually, at a pace we're genuinely comfortable validating.
  6. Save our most heavily customized customers for last, once we've already ironed out anything unusual on the simpler accounts first.

A practical detail worth knowing

Because every customer keeps their own separate, private database, the new system needs to be able to connect to 50+ (and growing) separate databases at once on our current hosting setup. Some hosting plans cap how many separate databases one account can have — we're confirming our current plan comfortably allows for this before any of this work depends on it, since it would otherwise be a real blocker worth catching early rather than late.

What's actually changing, besides the rebuild itself

Alongside moving to the new system, we're fixing several real problems and adding genuinely new capabilities. Each one gets its own full page:

What stays exactly the same, deliberately

The billing system we use to track which customers have paid us and manage access for those who haven't is tied into a separate system our sales team already manages day-to-day. We're keeping it exactly as it is, functionally — not rebuilding it as part of this project — since redesigning it isn't ours to decide unilaterally. We'll only do routine internal clean-up on it (matching the same data-quality standard as everything else), coordinated with the sales team first.

The core day-to-day work — drafting documents, collecting fees, managing offices and staff — will feel familiar to everyone using it; it's being rebuilt to work the same way our staff already know, just on sturdier, more maintainable foundations.

Page 3Cleaning Up How Information Is Stored

A handful of real, structural problems in how our information is stored today — each one fixed directly and carefully, without copying, losing, or hiding any existing record.

Money amounts become real numbers everywhere

Today

Many money amounts are stored as plain text rather than true numbers. It mostly works, but it's the kind of thing that can let an unexpected value slip through unnoticed, or make a calculation very slightly wrong without anyone realizing.

Going forward

Every money amount, everywhere, becomes a real, proper number. Before this change is made on any set of records, we check the existing values carefully and flag anything that doesn't look like a clean number for a person to review — nothing gets silently guessed at or rounded away.

Related records get a real safety check

Today

The system mostly trusts that connected pieces of information line up correctly — a payment and the client it belongs to, for example — without the computer actually verifying that. It's the equivalent of trusting that every form was stapled to the right file, without ever checking the staple.

Going forward

We add real checks that catch a mismatch the moment it would happen, instead of letting it through silently. Before switching a check on for any given type of record, we first look for any existing mismatches in that data and fix them by hand, case by case — nothing is deleted or hidden just to make a check pass.

Knowing exactly who did what, and when

Today

When something is "deleted," it's usually just marked in an informal way rather than properly removed or properly recoverable. And when we want to know who created or last changed something, the system only ever recorded a login name at the time — which isn't fully reliable if that login name is ever reused or changed later.

Going forward

Every record clearly shows who created or last changed it, tied to the actual person, not just a login name from the time. Deleted items are marked properly so they can be safely found and restored if needed, instead of guessed at. For older, historical records, we fill in who-did-what only where we're genuinely certain — anything unclear is left blank and flagged for a person to review by hand, never guessed.

No more cut-off information

Today

Some text fields are quite short — short enough that, in rare cases, a long entry could theoretically get cut off before it's fully saved.

Going forward

We widen these fields to a comfortable, safe size across the board, so this risk goes away entirely, for every customer.

How we make these changes without taking anyone offline

A few of our customers have extremely large amounts of historical data — some well over a hundred million records. Changing how a table of that size is structured can't just be done with a quick command; done carelessly, it could lock up the system for everyone using it at that moment. We use specialized, well-established tools built exactly for this: they quietly build a corrected copy of just that one table in the background while the current system keeps running completely normally, then switch over to the corrected version in an instant once it's ready and verified. Smaller pieces of information get fixed directly and immediately, since there's no meaningful risk at that size.

A related risk, found during review

We also confirmed that a core part of the system that creates a new case can fail partway through — it makes about thirty separate small updates in a row, with nothing to automatically undo them if something goes wrong midway. That could leave a half-created, incomplete case sitting in the system today, for any customer, with nothing flagging it. The new system wraps this kind of multi-step action as one single, all-or-nothing operation — either everything happens, or nothing does, with no in-between state possible. Any already-existing incomplete case we find is reviewed and fixed by hand, not silently ignored.

How we know it worked

Before any customer is switched over to the new system, we check that a sample of their real, existing records — cases, receipts, balances — look identical in the new system to how they look in the old one today. This is a straightforward check, not a guess: same record, same information, viewed through two different programs.

Page 4 · New capabilityReal, Professional Bookkeeping

We're introducing double-entry bookkeeping — the standard method every trained accountant and auditor already expects — to replace a system that currently recalculates totals on the fly, every time, using business rules that are written out separately in more than one place.

What this means in one sentence Instead of guessing a balance by redoing the math each time someone looks at it, every transaction gets written down once, correctly, as a balanced two-sided entry, and every balance is simply read from that permanent record.

How it works today

Account balances are updated directly, by several different parts of the program, each time money comes in or goes out — a client payment, a payment to a ministry, a staff payment, each handled by its own separate piece of code. Nothing checks that these updates stay correct relative to each other over time.

Separately, when someone wants to see "how much is owed" or "how much money the business has," the system doesn't read that from a stored, trustworthy total at all — it re-runs the underlying business calculation live, from scratch, every single time the report is opened. That calculation is written out in more than one place in the program, and nothing guarantees those copies always agree with each other.

In practice, this means it's possible — not something we know has happened, but structurally possible today — for a reported balance to quietly drift from what it should actually be, with nothing in the system that would catch it happening.

How it will work

Every financial event — a client payment, a fee sent on to a government ministry, a staff payment — gets recorded once, as a real double-entry: money is always shown moving from one place to another, and the two sides always have to add up to exactly the same amount. If they don't match, the record is rejected outright, before it's ever saved — there's no way to save an entry that doesn't balance.

For example: a client pays us $500, made up of our own service fee and a government fee we're collecting on their behalf. That single payment becomes one balanced entry — money coming in increases our cash on one side, while on the other side it's split correctly between "we've earned this" (our fee) and "we owe this to the government" (their fee) until it's actually paid over. Every report from then on is just a sum over entries like this one, not a recalculation.

A real improvement, not just a technical one

Today, money we collect on behalf of a government ministry and money the firm has actually earned are both just treated as "an amount" by the system, with no structural difference between them. Under the new design, these are properly told apart: money collected for a ministry is recorded as something we still owe out, right up until it's actually paid over — not as money the business has earned. That's a more accurate day-to-day picture of our finances than what we have today, not just a tidier one.

It also opens the door to reports we don't really have today in a trustworthy form — a genuine profit-and-loss view, for instance, becomes a natural by-product of this approach rather than something that would need its own separate, hand-built calculation.

Nothing old is rewritten

We don't go back and rebuild history, and we don't touch a single existing financial record. For each customer, at the moment we switch them over, we record one simple opening figure per bank account — "this is what it held on the day we started" — and the new, proper bookkeeping begins from that point forward. Every record that already exists stays exactly as it is, fully intact and fully accessible, forever.

The main risk, and how we're managing it

The real risk with any change like this is designing the categories wrong at the start, and having to restructure them later once real transactions already depend on them. We're addressing this by testing the new design against a sample of real, historical transactions for a sample customer before going live with it anywhere — checking that the numbers it would have produced match what we already know to be correct — rather than finding out after the fact.

Page 5 · New capabilitySmarter Staff Permissions

We're replacing the current all-or-nothing permission switches with a flexible, modern roles system — giving us precise, combinable control over who can do what, instead of broad settings that apply the same way everywhere a person can see.

How it works today

Each staff member has a simple on/off switch for every area of the system they're allowed to see — bank accounts, reception, payroll, and so on, around two dozen such areas in total. On top of that, there are just four general permissions — create, edit, delete, back up — and whichever of these are switched on for a person apply the same way, everywhere they can see.

So today, we genuinely can't say "this person can edit reception records but should never delete them, while also having full control over bank accounts." It's one setting for everything a person can see, or nothing — there's no middle ground.

We also confirmed a real gap: one particular, rarely-used staff type gets created with zero permissions assigned at all — not "limited" access, but nothing. If anyone ever assumed that account type had at least some basic access, they'd be wrong, and nothing in the system would warn them.

How it will work

Permissions become specific and combinable — "can edit reception records," "can delete bank accounts," and so on, each its own separate switch. These get bundled into sensible, reusable roles — for example, a "Clerk" role, a "Cashier" role, an "Office Manager" role — so setting up a new staff member correctly becomes a matter of picking the right role for their job, not ticking roughly thirty individual boxes by hand and hoping the combination is right.

The rarely-used staff type that currently gets no permissions at all will instead get a real, clearly defined, deliberately limited set of permissions — closing that gap properly instead of carrying it forward unexamined.

How we move everyone over without breaking anyone's access

Every current staff member's existing access is carefully translated into the new system, using exactly what their current switches already allow — nobody loses or gains access just because of the switch itself. Before fully relying on the new system for a given customer, we run both the old and new permission systems side by side for a trial period, silently comparing what each one would allow for every action — any mismatch gets logged and reviewed by a person before it's ever acted on. Only once that comparison shows no disagreements do we retire the old permission system for that customer.

What we're watching out for

The real risk in a move like this is accidentally granting someone slightly more, or slightly less, access than they had before. If a staff member's current combination of switches doesn't map cleanly onto one of our new standard roles, we assign their permissions individually instead of forcing them into the nearest-fitting role — and we flag that person's account for a manual double-check rather than quietly guessing.

Page 6 · New capabilityTidying Up Settings

A smaller clean-up than the others on this list, but a real one: today, dozens of unrelated settings are all dumped into one general-purpose storage area with no labels or structure. We're giving each one a proper, clearly-named home.

How it works today

All sorts of unrelated settings are stored in one generic, catch-all place, each just marked with a short internal code with no explanation attached. Looking closely, the settings actually being used today include: which financial year is currently active, a default option on the fee-collection screen, what happens right after a new case is created, how many signatures a generated government bill needs, a document-display preference, our social media links, and a dashboard display preference.

There's no master list anywhere describing what codes are valid or what each one is actually supposed to do — you can only find out by reading the program itself. We even found one of these settings being used in the software today that was never properly recorded as a valid setting in the first place, which is proof that this list has already been quietly growing messier over time without anyone noticing.

One of the items stored this way isn't really a "setting" at all — it's a running counter used to generate official document numbers, something that changes constantly during normal business use, not something an admin occasionally adjusts. Storing it the same way as a true setting is its own separate problem: if two people create a case at exactly the same moment, there's a real possibility of that counter not advancing safely, leading to a duplicate number.

How it will work

Each true setting gets its own clearly-labeled home, grouped sensibly with closely related settings — our social media links, for example, naturally belong together on one simple screen. From now on, adding a new setting means making a deliberate, visible, reviewed change, not quietly adding one more unlabeled entry to an undocumented pile.

The running document-number counter gets separated out entirely and handled the way a constantly changing piece of business data should be — with a proper safeguard against two people accidentally being given the same number at the same moment.

Page 7 · New capabilityEasier Fee Changes

Adding a new government or office fee today is slow and genuinely risky. We're redesigning this so it becomes a quick, safe, low-risk configuration step instead.

How it works today

Every time a new fee needs to be added — a new government charge, for example — our developers have to make a correct change in roughly twenty different places across the program: the form where a new case is opened, the screen where payment is taken, the government billing screen, several reports, and more. Each one has to be found and updated by hand, correctly, in the right order, by someone who remembers every place that needs touching.

We confirmed this is a real, live problem today, not a theoretical risk. One fee that was supposed to be fully added recently is still only half-working right now, months later, because one of those twenty-odd steps was missed — it has no way to actually be collected through the normal receipt screen, even though it's set up everywhere else. Nothing in the system flagged that this was incomplete; it was simply discovered by looking closely.

How it will work

Adding a new fee becomes a configuration step, not a code-rewriting exercise. Once a fee is described in the system once — its name, who collects it, how it's calculated, and which other fees it travels alongside — it automatically shows up correctly everywhere it needs to: the intake form, the receipt screen, the government billing screen, and every report. There's no longer twenty separate places to remember, so there's no longer a way to accidentally miss one.

How we get there without disrupting anything working today

We don't touch how our current fees work right now — every one of them keeps working exactly as it does today, with no change in behavior for existing customers. The new, easier approach is proven out first in two low-risk ways: on a brand-new fee that doesn't exist in the system yet, and on properly finishing the one fee we already know is only half-working today. Only once the new approach has proven itself on those would we even consider — as a separate, deliberate decision later, not assumed now — whether any of our existing, already-working fees are worth moving onto it too.

Why this matters beyond convenience

This isn't just about saving developer time, though it does that too. Every one of those twenty manual steps is also a chance for a mistake that affects real money — a government fee that's collected but never correctly billed onward, for instance. Reducing twenty manual, error-prone steps to one configuration step is a real reduction in financial risk, not just a convenience.

Page 8Closing Security Gaps

While reviewing the current software closely, we found a small number of genuine security weaknesses. Nothing suggests any of them have actually been exploited — but each one is real, and each is being properly closed as part of this rebuild, not just patched around.

The "keep me logged in" feature

The "remember me" feature that keeps someone logged in between visits checks who's returning in an unsafe way — it builds its lookup directly out of information sent by the visitor's browser, without properly guarding against that information being deliberately malformed. This is a well-known category of weakness (commonly called SQL injection), and in the worst case it could let someone with the right know-how get into the system without ever having a valid password. Regular password logins, separately, are already handled safely — this weakness is specific to the "remember me" shortcut.

We replace this feature entirely with the secure, modern version built into our new foundation — not a patch on the existing approach, a full replacement using an approach that isn't vulnerable to this category of attack by design.

Pages tricking the system into an unintended action

None of our screens currently protect against a well-known trick (commonly called cross-site request forgery, or CSRF) where a malicious webpage, open in the same browser at the same time, quietly tries to make our system perform an action — like submitting a form — on the real, logged-in user's behalf, without them realizing it happened.

This protection is switched on everywhere automatically, as a standard, built-in feature of the new foundation — not something that has to be remembered and added screen by screen, the way it would need to be today.

How information is looked up internally

In several places across the system, looking up information builds its request in a way that isn't fully guarded against unexpected or unusual input — the same general category of weakness as the "remember me" issue above, just appearing in more places. In the wrong circumstances, this kind of weakness could be used to see or change information that shouldn't be reachable that way.

Every lookup in the new system is built using the safe, standard approach that our new foundation expects and defaults to — so this becomes something the system is simply not susceptible to by construction, rather than something that has to be checked for, file by file, forever.

Why we're confident these are fixable cleanly

All three of these issues share the same root cause: parts of the current system build their own database requests by hand, out of raw text, instead of using a safer, standard method that keeps user input clearly separate from the request itself. The technology we're rebuilding on uses that safer method by default — so these fixes aren't three separate, hand-written patches, they're a natural result of building the new system the way it's meant to be built.

Page 9How We'll Roll This Out

No fixed calendar dates yet — this is a solo-built project, and we'd rather be honest about pace once we have real experience than promise a date now and miss it. What follows is the order things happen in, and the reasoning behind that order.

The build order

  1. Foundation first. The basic skeleton of the new system — logging in, recognizing each customer, and the structure behind the new staff-permission system from page 5 — gets built first, since everything else depends on it existing.
  2. Build and test the clean-up tools. The fixes from page 3 are built and proven against sample information first — never run against anyone's real, live records until they're proven reliable.
  3. Rebuild the core day-to-day work. Opening and completing a case — the heart of what the software is actually for — comes next, starting with our most common type of case, so there's something real and usable early on.
  4. Document generation. The tool that produces our official paperwork, rebuilt as one shared system instead of 46 separate copies, comes after the core workflow it depends on.
  5. Fees, bookkeeping, and the staff-permission migration, together. These three are grouped because they're the riskiest to get wrong later and hardest to retrofit, and because all three depend on the clean-up work from step 2 already being done.
  6. Settings clean-up. From page 6 — lower risk, so it comes after the harder pieces above.
  7. Everything else — staff records, paper archive tracking — follows, each a smaller, lower-risk piece on its own.
  8. Keeping our existing billing system working exactly as it does today, integrated with the new system, per page 2.
  9. A dedicated security check. Before we trust the new system with anyone's real information, we specifically verify every fix from page 8 is actually, provably in place — a focused review step, not just "we think we did it."
  10. One real customer, carefully. We run the full clean-up-and-switch-over process against one real customer's live information, check everything thoroughly, then switch just that one customer over.
  11. Everyone else, gradually. A small second group of standard customers next, to prove the first success wasn't a fluke, then the rest of our standard customers, then our most specially-customized customers last.
What this means for day-to-day business

Nobody experiences a disruptive "switch everything over this weekend" moment. Each customer moves over individually, only once we're genuinely confident, with the old system available as a safety net the entire time — right up until that specific customer's cutover is complete and verified.