v1.7.0
Three new capabilities and one fix reported from the app. No breaking changes, no config or schema changes — upgrading is a straight swap of the exe.
The logs that never reached the container
The estate shape this is for: fulls and differentials go to blob, and the transaction logs go somewhere else — a local or cluster disk for throughput, or a share because log shipping already owns them.
Point Nine Lives at the container and it builds an honest chain out of what it can see. That chain stops at the last differential, and nothing tells you the logs exist, where they went, or that the restore on offer is discarding hours of recoverable time. Finding out requires already knowing to look, which is exactly what nobody has at 3am on a server they did not build.
The instance that took them knows. Under the advanced restore options there is now a source instance picker and a check: it reads that instance's own record, sets it against what the container holds, and names what is missing — the folder it went to, how many files, how big, over what window, and how far behind the container is in recovery time.
Then two ways out, because both are legitimate:
Bring them in. A PowerShell script to run on the machine that holds them — azcopy with an Az.Storage fallback for blob, aws s3 cp for a bucket. Every file is named individually rather than globbed: a wildcard over the folder takes other databases' backups, an unrelated job's output, and whatever is half-written at that moment.
It carries no credential. That would have been one string interpolation away, and the result would sit in a .ps1 on a production server. The SAS or key pair is a mandatory parameter supplied at run time — which is also the form that wires into a scheduled task without touching disk.
Or leave them where they are. The one to reach for mid-incident, when uploading twenty-three files is time you do not have. Fold them into the timeline and the restore point extends to the newest of them; one script then reads the container by URL and those logs from their own path by DISK. The target has to be able to open that path as its own service account — a different question from whether the container is reachable, and one now asked before anything is dropped.
Carrying a login across from the source
When a restored database holds a user whose SID matches no login here, the advice was to create the login first, with a password set by whoever owns that account. Honest — inventing one would be worse — and it still left you holding a database whose users could not log in, with no way forward that did not involve tracking down the account owner.
There is a third option: neither invent the password nor go asking for it. Fetch the real one.
Run the new script on the instance the backup came from and it prints the CREATE LOGIN to run here, carrying the original password hash and the original SID. Both halves earn their place — the hash means applications authenticate with the password they already have, and the SID means the restored user is not orphaned at all. Its SID already matches, so there is no ALTER USER afterwards and no window where its permissions are wrong.
It reads and prints; it executes nothing, on either server. DEFAULT_DATABASE, DEFAULT_LANGUAGE, CHECK_POLICY and CHECK_EXPIRATION travel too, and a login disabled on the source is re-disabled on the target rather than arriving enabled.
SQL logins only. A Windows login carries no password and takes its SID from Active Directory, so the target recreates it with CREATE LOGIN ... FROM WINDOWS and the SIDs match by construction — the script says so rather than quietly finding nothing.
The Copy screen tells you why it will not generate
Reported from the app, and a good catch: every visible field filled in, the red banner naming the database that would be overwritten, and both buttons dead with nothing on screen saying why.
The source database had been cleared out from under the form. That screen re-reads its server list on every visit and re-assigns the source server to a fresh object each time, which clears the database and reloads the list — while the target server, container, name and overwrite tick all survive. So navigating away and back left a form that looked complete, refused to work, and explained nothing.
Your own choice is now put back when the same server arrives again. Never when you switch servers: putting back what somebody chose is not the same as choosing for them, and inventing a source database is the one thing that screen must not do — the wrong choice reads a production database at full speed and overwrites one on another server.
And six things have to be true before Generate is live. The screen named none of them; it now names the first one missing, along with the step to go back to.
Downloads. NineLives.exe is the app, 9lives.exe the CLI; take the -arm64 builds on Windows on ARM. Both are single self-contained executables — no installation. The zips carry both front ends together.
The binaries are unsigned, so SmartScreen will warn on first run (#33); each release carries a build provenance attestation you can verify with gh attestation verify.
Full detail in CHANGELOG.md.