LedgerMap · design options · 17/10/2026
Lock LedgerMap to one PC, with no user accounts
Three ways to make the desktop app run only on PCs that you approve. Each option has a diagram, its strong and weak points, and the work it needs. The recommendation and a rollout plan come at the end.
First, the honest truth about hardware locks
The user controls their PC. A skilled person can edit the .exe to skip a check, or fake a hardware ID. No hardware lock that runs only on the PC is safe from this.
LedgerMap already needs our server. It reads PDFs, matches ledgers and keeps the saved work. If the server serves only approved PCs, an edited app gets nothing. The server is our real lock.
Device key with server approval
The PC makes a secret key inside its security chip. The key can never leave that PC. You approve the key once. After that, the PC proves who it is every time the app starts.
4827 19364827 1936What the user sees on a new PC
This PC is not approved yet
Send this code to your LedgerMap contact.
What you do
Later, the same list can be an admin screen in the desktop app. A faster start is also possible: you make a one-time 8-digit setup code for a customer. The first PC that enters it is approved at once, and the code then stops working.
Strong points
- A copy on another PC cannot work. The key cannot leave the chip.
- No login. The app signs in by itself at each start.
- You approve each PC, and you can revoke one at any time. The change works at once.
- An edited
.exedoes not help. The server refuses any PC it does not know. - Ready for the paid plan. Add "paid until" and "number of PCs" to the customer.
Weak points
- It needs the internet. LedgerMap needs it already, so nothing new here.
- Some old PCs have no TPM chip, or it is turned off. Those PCs use a key locked with Windows DPAPI instead. A full disk clone could copy that key.
- A new Windows install or a new motherboard means a new key, so you approve that PC again.
- It is the most work of the three to build.
Licence file locked to a hardware ID
The app reads the PC's hardware (motherboard ID, disk serial, Windows ID) and shows a Machine ID. You sign a licence file for that ID. The app checks the file each time it starts, without the internet.
9F2C-…-41AEasmark.lic with your private key.exe. If someone removes it, the app runs, and the server cannot tell this PC from an approved one.Strong points
- Simple to understand. No server work to check a licence.
- Works offline. This only matters for apps that do not need a server.
- Uses the signing method we already use for app updates (Ed25519).
Weak points
- Only the app checks the lock. An edited app or a faked hardware ID gets past it.
- It does not protect the server. We would still need Option 1 or passwords for that.
- You cannot revoke a file. It works until it expires.
- A new disk or motherboard changes the ID, so the user needs a new file.
- Sending files back and forth by hand is slow for users.
Licensing service (Keygen, Cryptlex, LicenseSpring)
A company that sells licence systems does the PC locking. It gives you a dashboard for customers, PCs and seat limits, and later for payments. Our server must still check that service's tokens.
Strong points
- Ready-made: PC limits, offline grace days, expiry and a dashboard.
- Connects to payments (for example Stripe) when LedgerMap becomes paid.
- Their team keeps the licence system working, not ours.
Weak points
- Two systems to keep in step: the service and our server, which still needs its own check.
- A monthly cost that grows with the number of customers.
- Customer names and PC details go to another company.
- If the service is down, nobody can start the app.
- Most of these services use a PC fingerprint, not a chip key. So copying is easier than in Option 1.
Side by side
| 1 · Device key + approval | 2 · Licence file | 3 · Licensing service | |
|---|---|---|---|
| Copy to another PC is stopped | Yes. The key cannot leave the chip. | Partly. Only the app checks. | Mostly. Fingerprint only. |
| No login for the user | Yes | Yes | A licence key once |
| You approve each PC | Yes, with one command or a setup code | Yes, by signing a file | Yes, in their dashboard |
| Revoke a PC at once | Yes | No. It works until it expires. | Yes |
| Protects our server | Yes | No | Only if our server checks tokens |
| An edited .exe gets in | No | Yes | No, when our server checks |
| Data stays with us | Yes | Yes | No |
| Running cost | None | None | Monthly fee |
| Ready for paid plans | Yes. Add expiry and PC count. | Expiry only | Yes, with payments |
| Work to build | Most (about 3 PRs) | Least (about 2 PRs) | Medium + vendor setup |
How hard is it to get around the lock?
Recommendation: Option 1
LedgerMap already depends on our server, so the server is where the lock belongs. Option 1 meets all three requirements. It costs nothing to run, keeps customer data with us, and later becomes the paid plan without a rebuild. Option 3 is worth a look later, only if you want a ready-made payment and licence dashboard.
Rollout plan
devices, approve, revoke, setup-code. The server records each request, approval and revocation in usage tracking.Build log
Updated as the work goes on. Nothing merges into main until you approve it.
device-lock. Part 1, the contract (docs/device-access.md), is its first commit. PR #138PASSWORD_LOGIN switch. PR #140. All server checks pass, including PostgreSQL integration tests (full flow, setup code used once under 4 parallel requests, revoke ends sessions, limits, cleanup). OpenQodex: passed, no findings.docs/device-access.md, clearer message when password login is closed, version 0.4.0, and a fix for a race in the admin commands. PR #141.- You chose Option 1 with 8-digit numeric codes.
- Wrote the shared contract (wire format, routes, admin commands). OpenQodex review: passed, no findings. Opened PR #138.
- Started two sub-agents in their own worktrees: one for the server, one for the desktop app and the screen.
- Server part merged (PR #140):
server/device.go,server/device_admin.go, schema changes, admin commandsdevices / approve / revoke / setup-code / customers. - Contract gap: the contract did not say what a malformed public key returns. The server answers
400 device_key_invalid. The desktop side must handle it; this is checked in the review. - Small gaps the server agent decided: a revoked pending request is never cleaned up;
--customerrefuses a name that already exists; requests that keep racing can get409after 5 tries. All documented indocs/device-access.md. - OpenQodex's golangci-lint scanner failed to run (exit 2). The reviewer itself ran and passed the change.
- Wrote part 4 (PR #141). Rollout order: deploy server → give existing accounts setup codes, or approve with
--user <email>to keep their data → publish 0.4.0 as a required update → setPASSWORD_LOGIN=off. - OpenQodex found a race: two admin commands at the same moment could create two customers with one name. Fixed with a database lock.
- OpenQodex flagged that version 0.4.0 must not ship without the desktop code. So PR #141 merges only after part 3.
- The first PostgreSQL test run used wrong credentials. A rerun with the local development database settings passed.
Questions you may have
Is an 8-digit number safe enough?
The request code (PC → you) is only a label for a pending request. The chip key holds the security. The server picks the number at random, no two pending requests share it, and the list shows the name and time beside it. So 8 digits are plenty.
The setup code (you → PC) is a secret. It has 100 million choices, works once, expires after 24 hours, and the server allows only a few wrong tries per address and about 100 wrong tries per hour in total. Against one code, that gives a guesser roughly a 1 in 40,000 chance. Bank OTPs use 6 digits with the same kind of limits.
The user gets a new PC or reinstalls Windows. What then?
The app makes a new key and shows a new code. You approve it for the same customer, and all their work is there. You revoke the old PC.
Can one customer use two PCs?
Yes, if you allow it. Each PC has its own key, and all of them belong to one customer. They share the same parties. When LedgerMap becomes paid, the number of PCs can be part of the plan.
What if a PC has no TPM chip?
All Windows 11 PCs have one. Most Windows 10 PCs from about 2016 on have one too, but it is sometimes turned off. Without it, the key is locked with Windows DPAPI for that PC. Copying the app folder still does not work, but a full disk image clone could carry the key. The server can mark these PCs so you can see them.
Can someone just copy the app folder or the installer?
Yes, but the copy is useless. The key lives in the chip (or in DPAPI), not in the app folder. On the new PC the app has no key and shows a new pending request.
Can an attacker spam the server with requests?
Requests are rate-limited per address, and a pending request expires after a few days. Pending PCs cannot use the API until you approve them.
What changes when we start to charge?
Add "paid until" and "PCs allowed" to each customer. At sign-in, the server checks them and tells the app when a plan has expired. There is no new lock to build.
Words used on this page
- TPM chip
- A small security chip on the motherboard. It can make keys that never leave it.
- DPAPI
- A Windows feature that encrypts data so only that PC can decrypt it. It is the fallback when there is no TPM.
- Public / private key
- A pair of keys. The private key signs and stays secret on the PC. The public key checks signatures and can be shared with the server.
- Challenge
- A random value that the server sends. The PC signs it, so an old signature cannot be used again.
- Fingerprint / Machine ID
- A value made from hardware serial numbers. It is easy to read, so it is also easy to fake.