SQLite migration Infra
Replacing JSON file persistence with embedded SQLite. Work in progress — the test suite is red while the storage layer is being swapped underneath it.
A time and attendance system that reads what a physical clock device writes, takes corrections through an approval workflow, and reports the hours actually worked.
A clock device on a wall produces tab-separated exports and no opinions. This turns them into per-employee hour reports, and handles the part the device cannot: the day somebody forgot to clock out.
The design rule is the one I learned on validated machines — history is not edited, it is corrected. A correction is a proposal until it is approved, the original reading stays where it was, and every applied change can be undone from a history panel. An incomplete session shows its running duration instead of the word "incomplete", because a supervisor needs the number, not the label.
It started as a Python script that parsed the export files, grew a web UI, and became difficult to reason about — one server file doing everything. Splitting it into readable chunks helped, but only postponed the decision.
May — the rewrite. Migrated to a TypeScript monorepo with Vue and Vite, which is where the approval workflow, the change history with undo, and multi-file uploads landed. Then a deliberate pass removing dead code and the antipatterns the first version had accumulated.
August — the foundations. Login and session handling hardened against leaking personal data, an architecture document written to make the module boundaries explicit, and persistence moving from flat files to embedded SQLite — in progress: that last migration still has red tests, and it is the next thing to close.
Replacing JSON file persistence with embedded SQLite. Work in progress — the test suite is red while the storage layer is being swapped underneath it.
Closed the paths where personal data could leak through login responses and session handling. In a system that holds when each person came and went, that is the whole risk surface.
A written module inventory and data-flow map, with an honest read of where the code does and does not follow clean architecture. Written to be argued with, not to decorate the repo.
From a Python server to Vue and Vite in a typed monorepo, with tests. The same features, on foundations that could carry the next ones — followed by a pass that removed unused code and the antipatterns the first version had grown.
A correction is proposed, not applied: employees can raise and cancel their own, an approver accepts or rejects, and every applied change can be undone from a history panel that sits beside the pending queue.
Multi-file upload of the clock exports, with the view reloading as new files arrive. Incomplete sessions show a computed running duration instead of the word "incomplete".
A parser for a tab-separated export, and the suspicion that this would not stay a script.