Legacy X-ray
Case study · technical demonstration

X-ray and rebuild of a public Access warranty app

We ran our full method on a real Microsoft Access app that its author published as open source. The X-ray found 3 confirmed defects, 10 potential ones and 2 decisions for the owner. We then rebuilt the whole app and checked it against 1,574 results recorded from the original.

This is a technical demonstration of our discovery and verification methodology, not a completed customer migration. Nobody commissioned it, nobody uses the rebuild, and it isn't deployed.

The appWarranty claims and repair orders for a motorcycle dealer's service department, Microsoft Access, built 2003–2012
Size8 forms, 25 queries, 20 tables plus 1 linked file, 3 reports, about 2,900 lines of VBA
Data in the copy14 repair orders, 21 warranty claims, 93 part and labour lines, 22 customers
Business rulesAbout 45, each catalogued with where it lives in the app
Findings3 confirmed, 10 potential, 2 decisions; plus 3 usability bugs and 5 defects in code nothing calls
RebuiltEvery screen and live rule, in Django and PostgreSQL. How it was checked

On this page:The sourceFindingsHow we checkedThe rebuildFound while rebuildingDecisionsCost

The source, and what we changed

The app is ob080270/Husqvarna-Warranty on GitHub, published by its author under the MIT licence. We chose it because it's public: anyone can check our findings against the original. It isn't a client project. Legacy X-ray has no connection with the app's author, its users, or the brand in the repository's name.

We changed the data only, never the code, queries or forms:

What the X-ray found

Every finding is classified. Confirmed: we reproduced it in the original app and its consequence is shown. Potential: it's in the app, but we haven't reproduced its consequence (often because the shipped data never triggers it). Decision: behaviour the owner should choose to keep or change.

StatusFindingWhat it can costEvidence
ConfirmedWarranty tags always print claim #15 (the number is hard-coded in the tag query)Wrong parts tagged for return. 9 of 21 claims affected.The original's own query, run on the shipped data
ConfirmedThe exchange-rate table is a link to a file on the original developer's PCNo default rate on any other machineThe link fails when the app runs anywhere else
ConfirmedThat file stores every rate divided by 100 (found while rebuilding)Where the link works, every new repair order defaults to 0.435 per euro instead of 43.51. A wrong reimbursement wasn't reproduced: see below.Reproduced in the original app
PotentialEvery price, rate and quantity is stored as a 32-bit floatStored amounts drift from what was typed (10,433.48 is held as 10,433.4801828861); no wrong total found in the shipped dataDatabase file, running app
PotentialRepair-order totals add lines from any other order with the same numberWrong totals once order numbers repeat; none repeat in the shipped dataDatabase file
PotentialScreen and printout round differentlyScreen and paper can disagree by 0.01; they agree on every shipped claimDatabase file
PotentialThe audit field records the Access user, which is "Admin" without user securityNobody could tell who marked a claim as filed. Older records still show real users: the trail broke when the app was converted to the newer file format, which dropped Access user security. Not observed in a run.Database file, data
PotentialClaim and customer numbers are "highest + 1"Two people adding at once get the same numberDatabase file
PotentialDates are typed with 2-digit yearsFrom 2030, a typed "30" becomes 1930. Birthdays before 1930 can't be entered.Database file
PotentialPart and labour lines have no primary keyDuplicate lines can't be prevented or told apartDatabase file
PotentialThree input-loss bugsTicking a tag on a labour line wipes that line's edits; an unknown defect code erases the description; clearing a reimbursement leaves the old amount (that one can't happen through the shipped screens)Form code, in the database file
DecisionNobody can type a reimbursement on screen, yet every line has oneWho enters reimbursements, and where, is a question for the businessRunning app
DecisionCodes are compared without regard to case, and a quarter of the defect categories are stored in lowercaseKeep (the rebuild does); changing it would split existing dataData, running app

Also found: the repair-order form opens editable when its own code says it should be locked (confirmed when we ran it); and, in the form code, a crash when searching for a claim that doesn't exist and an empty warning box after every customer save (potential). Five more defects sit in code that nothing calls.

How we checked

  1. Read the published code. 2,837 lines of VBA flagged 15 suspected problems.
  2. Extracted the real database file. That gave us all 149 objects, including the queries and form settings the code depends on. Two suspicions were false alarms (plate search and labour billing both work), and 10 new defects surfaced, among them the hard-coded claim #15 and the 32-bit floats.
  3. Ran the original app and recorded it. A suspected compile error turned out not to stop the app, and the repair-order form proved to open editable. Access itself recomputed the totals for all 14 repair orders and 21 claims, which became the reference results.
  4. Rebuilt it and compared. Two findings surfaced only then: the exchange-rate file's values, and the reimbursement field that nobody can type into.

Every finding above was checked in the database file itself, which holds the forms' code as well as the data, not just in the published code. The two false alarms never reached the report.

The rebuild, and how it was checked

We rebuilt every screen and every live business rule as a Django web app on PostgreSQL, then checked it against the original. The expected answers weren't written by us: Access itself produced them, by running the original app's own queries, lookups and reports on the anonymised copy.

Part of the appRebuilt?Checked against the original
Customers, motorcycles and searchYesEvery recorded search returns the same customers
Repair orders, claims, part and labour lines, money totalsYes133 of 133 money totals match; lists, lookups and find-by-claim match
Defect-code picker (Russian and English)YesGroups, lists, search and descriptions match
Warranty-admin screenYesList order and every computed field match
Warranty labels and the claim printoutYesPrinted data, line order and totals match (labels for the claim on screen: defect 1 fixed)
Email notificationsAs draftsSame recipients and subjects; the person reviews and sends them, as in the original
Reimbursement entryRead-onlyAs in the original, where the field is disabled; how reimbursements get in is an open decision

The numbers: 1,574 of 1,574 recorded results and 133 of 133 money totals match, and 70 automated tests pass. Recording the original a second time, after restarting the machine, gave byte-identical results. As a check on the checks, we deliberately broke the rebuild in 16 different ways, re-introducing the original's defects and plausible mistakes, and the tests caught every one.

Ready for: showing the method on a real app, starting with a free X-ray. Not ready for: production use. That would need roles (who may stamp a claim as filed), multi-factor sign-in, a record of who changed money and statuses, monitoring, a plan for moving live data, and the customer's own acceptance tests.

What the tests do and don't check. Of the app's 44 business rules, 20 are checked against behaviour recorded from the original, 21 against our written catalogue of the rules (our reading of the code, which the owner would sign off on a real project), and 3 (cursor placement and the clearing of search boxes) have no automated test. Each sign-off decision has its own test.

Not yet validated: how the screens and printouts look next to the original (layout isn't tested), several people using it at once in real work (conflicting edits are detected and refused, and tested, but no team has used it), deployment to a real server, and moving a live customer database across. Nobody uses this rebuild; it isn't deployed.

The tests earned their keep. The first money run matched 125 of 133: the original keeps each converted reimbursement line to 4 decimal places and rounds only the total, while our first migration rounded every line. Nobody would have spotted that on screen. Keeping 4 decimal places fixed it.

Found while rebuilding

Keep or fix: the decisions

Copying the old app blindly would also copy the claim #15 tags. So before the rebuild, each defect got a decision, under one policy: fix anything that corrupts money or data, crashes, or loses input, and keep interface quirks as they are. The tests check the decided behaviour, while the recordings keep the old behaviour as evidence. For this sample, we made those decisions ourselves, acting as the client. On a real project, you make them.

What this says about price

Not a price, yet. The rebuild took our engineering tools well under an hour of working time once the method existed, but that leaves out the parts a customer project adds: our review, your sign-offs, moving your live data, deployment and two weeks side by side. Until a customer project has been delivered, we won't quote this sample's size as a price.

For a real app, the diagnostic establishes the full scope, timeline and fixed price before implementation begins. Rebuilds start at $6,000 for smaller applications.

The full sample report is available on request: [email protected].

Want the same for your app?

Send us one app for a free X-ray. You get the report two business days after we accept your submission.