PRJ · 2026
Migration Tracker: Every User to Done Before a License Ends
A read-only tracker that snapshots a SaaS workspace, compares each run and walks every user to done before a license ends.
A worklist spreadsheet that never refreshed to A re-runnable tracker with a full history


What it is
A small tool for retiring a SaaS platform on a deadline. It reads the platform (read-only), saves a dated snapshot of every user and the projects they own, compares each run with the last, and walks each user through the steps their move needs until they reach done. It moves no data itself: the destination's own importer does that. The tracker is the record of who is where, what is blocking them and who acts next.
The problem
A license end date sets the deadline. The list of people to move lived in a spreadsheet that did not refresh, did not show who owned which projects now, and could not say when a person was finished. For most users the job was not an import at all: it was handing their projects to a new owner and removing their access. And the same exercise comes around again whenever another license approaches its end.
What I built
- Read-only snapshots, each compared with the last, so joiners, leavers and ownership changes show up on their own.
- A step pipeline that depends on each user's destination: a full import path, a lighter one, or none, where the import steps read N/A rather than blank. Changing a user's destination re-derives the steps and keeps the history.
- An exceptions view: projects still owned past the point they should have moved, projects with no owner, and the users whose access still has to be removed, with the days left.
- Per-project import tracking with a gate: a user cannot be marked as having sync turned off until every project imported for them shows it off, and the tracker names the ones that do not.
- An append-only log: every step records who, when and why, backward moves need a note, and the history replays to the current state. A CSV export gives the platform admins the same picture without the tool.
How it is built
Python standard library only, with no dependencies and no install step, and SQLite with triggers that refuse updates and deletes. It reads through OAuth with read scopes only; secrets stay in the operating system's credential store and never touch the code. The shared copy sits behind sign-in, with hashed tokens and daily verified backups. Tests cover the boundaries, the pipeline rules and a real browser, and the page meets WCAG 2.2 AA with full keyboard use. People's names stay in the tool's data folder: test fixtures use placeholders.
Why it matters
Retiring a platform is the last step of application rationalization, and it is where the plan meets real people and real deadlines. A tracker that can be run again for the next license turns a one-off scramble into a repeatable step.