Artifact
The stored file a successful run produced. One run, one artifact.
View as MarkdownAn artifact is the stored file a run produced. It exists only once archived: a failed run leaves a failed run and no artifact.
One run produces exactly one artifact. Sources that are naturally many files, s3,
folder, are streamed into a single archive, which keeps
keep_last counting runs rather than files and keeps one restore one operation.
What it records
| Field | Meaning |
|---|---|
filename | Derived from the source. A convenience, not a contract |
size_bytes | The size of what is stored |
original_bytes | The size of what was uploaded, before our transforms |
checksum | SHA-256 of the file as uploaded |
compressed, encrypted | What was actually done to it |
key_id | Fingerprint of the public key it was encrypted to |
lock | Whether, and until when, it cannot be deleted |
locations | One row per copy |
checksum attests to what you gave us, not to what we stored. For a local backup those
are the same object, so it matches the downloaded file directly. For cloud and manual backups
where we applied compression or encryption, it matches only after you decrypt.
original_bytes differing from size_bytes is the signal.
An artifact has locations, not a location
A run delivering to our storage and two of your buckets produces one artifact with three locations. Each says where a copy went and whether it got there.
| Location kind | Where |
|---|---|
permanent | Our archive |
destination | One of your own buckets |
A copy that failed is visible as a failed location rather than being rounded away. That is how a partially delivered run stays honest: the artifact exists, the run failed, and the locations say precisely what you have.
States
(none) ──finalize──► archived ──retention sweep──► expired
──you delete──────► deletedAn artifact is written by the pipeline and never by an API call. There is no endpoint that creates one.
It is an ordinary file
There is no saved.sh container format. An artifact is a dump wrapped in at most two standard layers:
[ PGP message [ compressed [ the dump ] ] ]Both wrappers are optional and standard. gpg --decrypt opens one, and so does anything else
that speaks OpenPGP.
This is deliberate, and it costs us something. A container format would let us record the source type and layer order in a header, and would be more convenient eleven months a year. In the twelfth, when the thing that went wrong is us, you would need a working saved.sh to read your own backup. See artifact format.
Deleting
| Refusal | Meaning |
|---|---|
| Locked | Inside its protection window. Nothing removes it early, including us |
| Last artifact | The only one left. A backup that has run keeps something to restore from |
Deleting removes our copy. Copies in your own buckets are left where they are, because we hold write credentials rather than a mandate to destroy data in your storage.
Ordinary expiry is retention, applied by a daily sweep. Deleting by hand is for one artifact you want gone now.
Downloading
Downloads use a presigned URL straight from object storage. The bytes do not pass through our API.
Two things follow:
- We do not observe the transfer. The audit trail records that a URL was issued, which is the last moment we can see.
- A
skip_permanentbackup cannot be downloaded from us, because the bytes only ever went to your bucket. We tell you where instead.