valis / Reference / API reference

Backup - API reference

Exported surface for the backup subsystem. Part of the API reference.

Package valis/src/backup

Conditions

acme-store-outside-restore-target

Signalled before anything is written when the ACME store a restore would land, as the restored configuration names it or, for a backup carrying none, as the environment does, lies outside the restore target and no ACME store directory was given. PATH is that store and STATE-DIR the target.

acme-store-overlaps-restored-state

Signalled before anything is written when the ACME store a restore would land holds, or lies inside, a place the restore lands other state: the owner keyfile, the store HEAD's directory, the vouch or revocation store, or the configuration directory. PATH is the ACME store and OVERLAPS lists those places.

backup-container-error

Signalled when a decrypted backup container fails its fixed-width parse: a bad magic/version, a length field that overruns the buffer, trailing bytes, or an unknown member kind. It is raised BEFORE any member is dispatched, so a corrupt container never writes partial state.

backup-error

Root of the backup subsystem's condition hierarchy. Every fault raised while assembling, sealing, opening, or unpacking a backup is a subtype of this, so a caller can catch the whole family in one clause without also swallowing unrelated errors.

backup-kdf-cost-out-of-bounds

Signalled by WRITE-BACKUP, before anything is assembled or written, when it is asked to seal at an argon2id cost below the minimum or above the ceiling mercer accepts when it opens a backup.

backup-owner-seed-missing

Signalled by ASSEMBLE-BACKUP-CRITICAL when the owner seed keyfile is absent. The seed is the one member of the backup-critical set with no legitimate absent case, so it is the floor under the set: its absence is refused before anything is collected and before mercer is asked to seal, because an artifact carrying no owner seed protects nothing while reading as a success. The report names the resolved keyfile path, since the operator's real fault is nearly always a wrong data root rather than a missing file.

configuration-not-backed-up

Signalled when a backup finds something under the configuration directory it will not carry, such as a symbolic link, before anything is sealed or written.

configuration-not-carried

Signalled as a warning when a restore opens a backup in a container format older than the one that carries the node's configuration. The restore goes on, since refusing it would cost the owner seed.

configuration-not-restored

Signalled when a restore carries configuration it cannot land, because no configuration directory was given for it; the restore is taken back.

restore-account-refused

Root of the refusals a restore makes, before anything is written, because of the account it runs as: what it landed would belong to an account the node cannot open files as. PATH is the directory judged.

restore-run-as-another-account

Signalled before anything is written when a restore runs as an account other than the one owning its state directory, or its ACME store directory, or, for one not made yet, the nearest directory above it that exists. RUNNING names the account the restore runs as, OWNER the account owning the directory, or NIL when that could not be determined, and SUDO-ACCOUNT how sudo names the owner.

restore-target-not-made

Signalled before anything is written when a restore runs as root and its state directory, or its ACME store directory, does not exist yet. Root may restore into a directory that already exists and that root owns, since the account a node runs as is the operator's choice; it may not make the directory, because whatever it made would belong to root.

restore-target-not-pristine

Signalled when a restore is asked to land into a StateDirectory whose data root already holds valis state: an owner keyfile, a store HEAD, a pub-store block directory, a vouch store, a configuration file, or a revocation store beside any of those. A lone revocation store is what an interrupted restore leaves, and a restore goes ahead over it when the backup carries every hash it holds; otherwise it is refused too. A restore is all-or-nothing into a pristine target: refusing up front, before any byte is written, avoids the half-replaced state a mid-restore failure would otherwise leave, exactly the crash-loop shape (a HEAD with no keyfile or blocks) a partial restore produces.

revocation-store-not-backed-up

Signalled when a backup finds a revocation store file it cannot read whole, before anything is sealed or written.

revocation-store-not-carried

Signalled as a warning when a restore opens a backup in a container format older than the one that carries the revocation store. The restore goes on, since refusing it would cost the owner seed.

revocation-store-not-restored

Signalled when a restore carries a revocation store member it cannot land, because its octets are not a whole number of hashes or no path was given for it; the restore is taken back.

vouch-store-left-out

Signalled as a warning when a backup finds a vouch store file that does not decode and takes the backup without it. PATH names the file and REASON says why it did not decode.

vouch-store-not-restored

Signalled as a warning when a restore carries a vouch store member it does not write, because its octets do not decode or no path was given for it. PATH is where it belongs and REASON says why it was not written.

Generic functions

acme-store-outside-restore-target-path

(acme-store-outside-restore-target-path condition)

Undocumented: this exported symbol needs a docstring.

acme-store-outside-restore-target-state-dir

(acme-store-outside-restore-target-state-dir condition)

Undocumented: this exported symbol needs a docstring.

acme-store-overlaps-restored-state-overlaps

(acme-store-overlaps-restored-state-overlaps condition)

Undocumented: this exported symbol needs a docstring.

acme-store-overlaps-restored-state-path

(acme-store-overlaps-restored-state-path condition)

Undocumented: this exported symbol needs a docstring.

backup-owner-seed-keyfile

(backup-owner-seed-keyfile condition)

Undocumented: this exported symbol needs a docstring.

configuration-problem-path

(configuration-problem-path condition)

Undocumented: this exported symbol needs a docstring.

configuration-problem-reason

(configuration-problem-reason condition)

Undocumented: this exported symbol needs a docstring.

restore-account-refused-path

(restore-account-refused-path condition)

Undocumented: this exported symbol needs a docstring.

restore-run-as-another-account-owner

(restore-run-as-another-account-owner condition)

Undocumented: this exported symbol needs a docstring.

restore-run-as-another-account-path

(restore-run-as-another-account-path condition)

Undocumented: this exported symbol needs a docstring.

restore-run-as-another-account-running

(restore-run-as-another-account-running condition)

Undocumented: this exported symbol needs a docstring.

restore-target-clashes

(restore-target-clashes condition)

Undocumented: this exported symbol needs a docstring.

restore-target-state-dir

(restore-target-state-dir condition)

Undocumented: this exported symbol needs a docstring.

revocation-store-problem-path

(revocation-store-problem-path condition)

Undocumented: this exported symbol needs a docstring.

revocation-store-problem-reason

(revocation-store-problem-reason condition)

Undocumented: this exported symbol needs a docstring.

vouch-store-left-out-path

(vouch-store-left-out-path condition)

Undocumented: this exported symbol needs a docstring.

vouch-store-left-out-reason

(vouch-store-left-out-reason condition)

Undocumented: this exported symbol needs a docstring.

vouch-store-not-restored-path

(vouch-store-not-restored-path condition)

Undocumented: this exported symbol needs a docstring.

vouch-store-not-restored-reason

(vouch-store-not-restored-reason condition)

Undocumented: this exported symbol needs a docstring.

Functions

assemble-backup-critical

(assemble-backup-critical &key keyfile head-path acme-store-path vouch-store-path revocation-path config-directory)

Collect the backup-critical set (owner seed, store HEAD, the reachable store blocks, the owner's vouch and revocation stores, the node's configuration, and the whole ACME store tree) into a single versioned, length-prefixed plaintext container, and return (values container member-count). Each member carries a kind tag, a length-prefixed name, and length-prefixed bytes so %unpack-container is fixed-width fail-closed. Holds NO crypto: the caller hands the container to mercer's seal-backup.

The HEAD names a content-addressed root tree; the pointer alone is useless on a fresh host. So when a HEAD is present, the same HEAD is decoded to its root entry, the block DAG it reaches is walked (collect-reachable-scores), and every referenced block is read from the store beside HEAD (pub-store/) and carried as a block member named by its hex score.

The owner seed is MANDATORY and is the floor under the whole set: when the keyfile is absent this signals BACKUP-OWNER-SEED-MISSING before collecting anything, so a seedless container never reaches seal-backup. Every other member is optional and an absent source is skipped, because those absences are real instance states rather than faults: a pre-issuance instance has no ACME store yet, and a genesis instance has no HEAD and therefore no blocks.

The vouch store at VOUCH-STORE-PATH is carried as the octets of its file, read under the lock of the store a running node holds open there, so the backup holds the trust state that node has published. A node with no vouch store file backs up without one, and never with an empty one in its place, because a restored empty store would let a node that has installed modules start without the credentials that admitted them. A vouch store file that does not decode never costs the backup: it is left out, with a log warning and a VOUCH-STORE-LEFT-OUT warning naming the file, and every other member is still carried.

The revocation store at REVOCATION-PATH is carried as the octets of its file. Taken inside a running node that holds the store open, it is read under that store's lock; taken from another process, it is read whole and checked by length alone. A node with no revocation file backs up without one. A revocation file that cannot be read as a whole number of hashes refuses the whole backup with REVOCATION-STORE-NOT-BACKED-UP, because a backup without it would restore a node that honours grants its owner revoked.

Every configuration file under CONFIG-DIRECTORY, the node's own and each module's, is carried as the octets of its file, named by its path relative to that directory. Taken inside a running node with that configuration open, the files are read under its configuration write lock, so the backup never carries a set one change has only part way altered. A node with no configuration directory backs up without one. A symbolic link under the directory refuses the whole backup with CONFIGURATION-NOT-BACKED-UP rather than being followed.

backup-to-artifact

(backup-to-artifact passphrase out-path)

Operator backup: seal the production backup-critical set to OUT-PATH under PASSPHRASE. Returns the member count.

check-restore-accounts

(check-restore-accounts state-dir &key acme-store-dir)

Refuse, before anything is written, a restore into STATE-DIR, landing its ACME store in ACME-STORE-DIR when one is given, that would land files the node cannot open: one run by an account other than the one owning each directory, or by root into a directory not made yet. Signals a RESTORE-ACCOUNT-REFUSED.

default-source-locations

(default-source-locations)

The production on-disk locations a backup reads from, as (values keyfile head-path acme-store-path vouch-store-path revocation-path config-directory): the owner keyfile, the store HEAD, the vouch store, the revocation store and the configuration directory under the valis data root, and the node's ACME store.

read-backup

(read-backup passphrase in-path &key keyfile head-path acme-store-path vouch-store-path revocation-path config-directory acme-store-dir resuming-in)

Read the envelope at IN-PATH, open it under PASSPHRASE via mercer's open-backup (a wrong passphrase or a tampered/corrupt envelope fails closed there before any write), then unpack the container fail-closed and dispatch every member to the fresh StateDirectory: the seed via custody's 0600 write, the HEAD file, the ACME store tree, and every store block through the block store's own verified write path (rooted at pub-store/ beside the restored HEAD). The whole container is unpacked BEFORE any member is written, so a corrupt container writes no partial state, and a restore that fails part way takes back everything it wrote.

The revocation store is landed first, at REVOCATION-PATH at mode 0600, merged with any store already there. One that cannot be landed, because no path was given or its octets are not a whole number of hashes, signals REVOCATION-STORE-NOT-RESTORED and the whole restore is taken back. When RESUMING-IN names the state directory being restored, a revocation store already at REVOCATION-PATH must hold only hashes this backup carries, or the restore signals RESTORE-TARGET-NOT-PRISTINE before anything is written. A backup in a format older than the one that carries it restores with a log warning and a REVOCATION-STORE-NOT-CARRIED warning, signalled before anything is written.

The configuration is landed right after the revocation store, each file under CONFIG-DIRECTORY at its relative name at mode 0600, in directories made 0700. A backup carrying configuration with no CONFIG-DIRECTORY given signals CONFIGURATION-NOT-RESTORED before anything is written. A backup in a format older than the one that carries configuration restores with a log warning and a CONFIGURATION-NOT-CARRIED warning, signalled before anything is written.

The ACME store lands in ACME-STORE-DIR when one is given. Otherwise it lands where the configuration the backup carries says the node keeps it, judged before anything is written, or at ACME-STORE-PATH for a backup carrying none. When RESUMING-IN names the state directory being restored, an ACME store that was not given and lies outside it signals ACME-STORE-OUTSIDE-RESTORE-TARGET, one that holds or lies inside a place other state lands signals ACME-STORE-OVERLAPS-RESTORED-STATE, and any file already where the ACME store lands, or a symbolic link on the way there, signals RESTORE-TARGET-NOT-PRISTINE, both before anything is written.

The vouch store is landed last, at VOUCH-STORE-PATH. If its octets do not decode it is not written and the rest of the restore stands, with a log warning and a VOUCH-STORE-NOT-RESTORED warning saying so. Emits a substrate restore.completed event (path + member count only). Returns the number of members restored.

restore-from-artifact

(restore-from-artifact passphrase in-path state-dir &key acme-store-dir)

Operator restore: open the artifact at IN-PATH under PASSPHRASE and land its members into the fresh StateDirectory STATE-DIR, then project the plaintext owner.did and store.head witnesses into the state-dir root (the byte-faithful witnesses the restore is compared against). A restore must run as the account owning STATE-DIR, and ACME-STORE-DIR when one is given, or, for a directory not made yet, the nearest directory above it that exists, and root may not make either; anything else is refused with a RESTORE-ACCOUNT-REFUSED before anything is written, since the node could not open what it would land. A restore demands a pristine target: if the state-dir data root already holds valis state (an owner keyfile, a store HEAD, a pub-store block directory, a vouch store, a configuration file, an ACME store where this restore lands one, or a revocation store beside any of those, or a lone one holding a hash the backup does not carry) the restore refuses before a single byte is written, signalling RESTORE-TARGET-NOT-PRISTINE, so a non-pristine node is never left half-replaced. The configuration lands before any member it places. The ACME store lands in ACME-STORE-DIR when one is given; otherwise where the restored configuration says the node keeps it, never where the restoring process's environment says, and only inside STATE-DIR: one outside it signals ACME-STORE-OUTSIDE-RESTORE-TARGET before anything is written, so a restore made to prove a backup can never overwrite a live node's certificates. A restore that fails after it has begun writing takes back everything it wrote, witnesses included, so the target is left as it was found and a retry is not refused. A vouch store that does not decode is the one member that does not fail the restore: it is reported with VOUCH-STORE-NOT-RESTORED and left unwritten. Returns the number of members restored.

state-dir-locations

(state-dir-locations state-dir)

The on-disk locations a restore writes into under a fresh StateDirectory, as (values keyfile head-path acme-store-path vouch-store-path revocation-path config-directory): the owner keyfile, the store HEAD under pub-store/, the ACME custody store, the vouch store, the revocation store, and the configuration directory. A restore is given the unit's StateDirectory, which the resident treats as its XDG data-home and appends valis/ to reach its data root; restore composes its targets from that same data root so a restored node reads exactly the members a restore wrote.

write-backup

(write-backup passphrase out-path &key keyfile head-path acme-store-path vouch-store-path revocation-path config-directory)

Assemble the backup-critical container, seal it under PASSPHRASE via mercer's seal-backup, and write the portable envelope to OUT-PATH. Emits a substrate backup.written event carrying only the artifact path and the member count, never key bytes. Returns the member count. A revocation store at REVOCATION-PATH that cannot be read whole signals REVOCATION-STORE-NOT-BACKED-UP, and a symbolic link under CONFIG-DIRECTORY signals CONFIGURATION-NOT-BACKED-UP, before anything is sealed, and nothing is written to OUT-PATH. Holds no crypto: the KDF and AEAD live in mercer, reached by late-resolved symbol-call.