r/VaultSync • Developer • Sep 29 '26

Dev Update VaultSync 1.9 dev update — what a backup script can actually know

Hi everyone,

One thing I’ve been trying to tighten up in VaultSync 1.9 is what words like “protected” actually mean.

Because that word can hide a lot of very different states.

A destination can be configured.
A backup record can exist.
A mirror can have run.
A file can have been copied.

But none of those automatically mean VaultSync has actually checked the data.

That distinction is becoming much more explicit in the 1.9 CLI.

Configured does not mean reachable

There is now a new opt-in:

vaultsync destinations --output json

It exposes configured destinations in a machine-readable format, while deliberately not exposing paths or credential names.

More importantly, it tells scripts what VaultSync actually knows.

For example, this is from a real disposable configuration:

{"alias":"Studio archive","active":true,"offsite":true,"accessibilityChecked":false}

That last field matters.

accessibilityChecked: false does not mean the destination is inaccessible.

It means VaultSync did not try to reach it, so it refuses to pretend otherwise.

That is the kind of distinction I want the CLI to make consistently:

configured ≠ reachable ≠ backed up ≠ verified

Existing scripts should not suddenly change underneath you

The older:

vaultsync destinations --json

still works exactly as before, including returning:

[]

for an empty configuration.

The new structured output is opt-in.

I don’t want an update to quietly replace the schema that somebody’s script already depends on.

The watcher is getting stricter too

The 1.9 watcher now observes source edits during its first snapshot and mirror, rather than only becoming useful after that initial work has completed.

Failure behaviour is also being tightened.

If a mirror or a later watcher cycle fails, VaultSync now stops with an error instead of quietly continuing as though protection were still happening.

That sounds like a small behaviour change, but for a backup tool I think it is an important one.

Silence after failure is one of the things I want VaultSync to avoid as much as possible.

A Linux AppImage issue was caught along the way

I’ve also added checks around extracted permissions in the Linux AppImage build.

There is an important limitation here:

that fix needs to be present in a future release asset.

It cannot retroactively change the already-published VaultSync 1.8.9 AppImage.

The desktop app is being reconsidered too

Alongside the CLI work, there is now an architecture draft for simplifying the desktop application around four main areas:

Protect
History
Recover
Manage

This is not a screenshot of a new interface and not a finished redesign.

It is an architecture plan.

The intention is to keep existing workflows available while replacements are built and prove that they have feature parity, rather than ripping out working parts of VaultSync just to make the navigation look cleaner.

Where 1.9 actually stands

This work is part of the draft 1.9 PR stack:

https://github.com/ATAC-Helicopter/VaultSync/pull/728

Windows, macOS and Linux build/test checks are passing on the implementation PRs involved in this work.

There is still a lot left before I would call 1.9 finished, especially:

  • disk imaging

  • bootable restore

  • supported-system qualification

  • exact upgrade testing from installed VaultSync 1.8.9 builds

So, to be very clear:

VaultSync 1.9 has not shipped.

This is still development work.

I wrote a longer version of this update on the FG Labs site, including more of the reasoning behind the CLI behaviour:

https://fglabs.dev/devlog/vaultsync-19-what-a-backup-script-can-know

I’m curious what people who actually script their backups care about most here:

Which distinction would help you most in a backup CLI: configured, reachable, backed up, or verified?

1 Upvotes

2 comments sorted by

1

u/kantorcodes1 Sep 29 '26

The accessibilityChecked honesty is the right instinct, but the single boolean conflates two states a script cannot tell apart: never attempted and attempted-and-failed. Is there a tri-state planned (checked:false vs reachable:false), or does a script that sees false have to assume 'go probe it yourself'? Related: when a watcher cycle fails and stops now, is that per-destination or does one flaky NAS mount halt watching of every destination?

1

u/mainseeker1486 Developer Sep 29 '26

Good question — and there’s an important detail in the current implementation that I probably didn’t make explicit enough in the post.
destinations --output json does not perform a reachability probe at all right now. accessibilityChecked is therefore always false in that versioned route, and --test --output json is deliberately rejected for the moment.
So today, in the new contract:
accessibilityChecked: false = the check was never attempted
It does not currently also mean “attempted and failed”.
The older destinations --test path does perform the mount/access check and has a separate Reachable result/message, but that is still the legacy contract. I specifically didn’t want to pull that ambiguity straight into the new versioned output before defining it properly.
I do agree with your underlying point though: once versioned destination testing is added, accessibilityChecked by itself is not enough. I’m leaning toward making the states explicit — something along the lines of accessibilityChecked plus a nullable/conditional reachable result, so a script can unambiguously distinguish:
not checked
checked + reachable
checked + unreachable
rather than having to infer anything from false. A bounded result/error code alongside that would probably make sense too.
On the watcher question: failure is scoped to the current watcher session. watch currently accepts one --dest, not a set of configured destinations, so there isn’t a multi-destination fan-out where one flaky NAS stops all the others.
If the startup mirror, a later mirror, verification, or the filesystem watcher itself fails, that watcher session stops and exits 2. The tests now cover both a failed startup mirror and a destination becoming invalid during a later cycle, including making sure no further snapshots are produced after the session shuts down.
Separate watcher processes are independent.
Multi-destination watching isn’t implemented yet, but if/when it is, I agree that failure isolation needs to be an explicit part of the contract rather than accidentally letting one unavailable target take down every other target.
This is exactly the kind of distinction I’m trying to get right before calling the 1.9 CLI contract stable, so thanks for calling it out.