Fix the six findings of the review on config set, version and blob names
check / check (push) Successful in 11m16s
check / check (push) Successful in 11m16s
README.md: config set keeps comments and can remove blank lines; a config that does not load yet also has a value that is not a size refused; vaultik version reports a tag and adds a development-build note to every other version. docs/REPOSTRUCTURE.md and README.md: someone who has a blob's whole contents can compute its name and see whether it is stored. docs/DATAMODEL.md: snapshot list shows an unfinished snapshot as remote only once its manifest is at the destination; closing a full blob commits the first chunk of the next one. internal/cli/config.go: config set --help says the same about comments and blank lines. Model: fable-5-1
This commit is contained in:
1 parent
f65fd2870b
commit
a8b9c57e93
4 files changed
+22
-15
No files matched your search
@@ -64,9 +64,8 @@ It was written to meet these requirements together:
|
||||
## Getting started
|
||||
|
||||
Installing needs Go 1.26.1 or later. `go install` builds the newest tagged
|
||||
version. `vaultik version` then reports that tag and calls the build a release.
|
||||
Generating a key pair needs `age-keygen`, which comes with
|
||||
[age](https://age-encryption.org/).
|
||||
version. `vaultik version` then reports that tag. Generating a key pair needs
|
||||
`age-keygen`, which comes with [age](https://age-encryption.org/).
|
||||
|
||||
```sh
|
||||
# Install vaultik.
|
||||
@@ -294,7 +293,7 @@ list or a map prints as YAML.
|
||||
Sets one value in the config file. The key is a dotted path, as in
|
||||
`vaultik config set compression_level 9`.
|
||||
|
||||
- Comments and formatting in the file are kept.
|
||||
- Comments in the file are kept. Blank lines can be removed.
|
||||
- A key that no setting has is refused. A key that is not in the file yet is
|
||||
created. A missing parent becomes a list when the next part of the path is a
|
||||
number, and a map otherwise.
|
||||
@@ -307,12 +306,13 @@ The command refuses a change that would stop the config from loading. An example
|
||||
is `vaultik config set compression_level 99`. The file is then left unchanged.
|
||||
|
||||
A config that does not load yet is checked less strictly. An example is the file
|
||||
`config init` writes, which has no `storage_url`. There the command refuses only
|
||||
three things:
|
||||
`config init` writes, which has no `storage_url`. There the command refuses
|
||||
these:
|
||||
|
||||
- an unknown key
|
||||
- a value of the wrong type, such as a word where a number belongs
|
||||
- a `${ENV:NAME}` value whose variable is unset or empty
|
||||
- a value that is not a size, for a size setting
|
||||
|
||||
### `snapshot create`
|
||||
|
||||
@@ -1292,6 +1292,7 @@ destination still learns these:
|
||||
- when each backup finished
|
||||
- how many blobs each snapshot uses, and their sizes
|
||||
- which blobs two snapshots share
|
||||
- whether a blob holds data they already have in full
|
||||
- whether a hostname and snapshot name they guess exist there
|
||||
|
||||
The last point holds because a remote key is a plain hash of the snapshot ID,
|
||||
@@ -1503,8 +1504,8 @@ the version Go recorded in it:
|
||||
`v`, so the tag `v1.0.0` gives `vaultik 1.0.0`. `script/release-snapshot` stamps
|
||||
`dev-` followed by 12 characters of the commit.
|
||||
|
||||
`vaultik version` calls a build a release only when its version is a plain tag,
|
||||
such as `v1.0.0` or `1.0.0`. Every other version is a development build.
|
||||
`vaultik version` adds a development-build note to every version except a plain
|
||||
tag, such as `v1.0.0` or `1.0.0`.
|
||||
|
||||
`make` stops with an error when `script/version` gives no version.
|
||||
|
||||
|
||||
+5
-3
@@ -195,8 +195,9 @@ example is `server1_home_2025-06-01T12:00:00Z`. It has three parts:
|
||||
The `snapshot list` table shows `uncompressed_chunk_size` as `UNCOMPRESSED SIZE`
|
||||
and `new_chunk_size` as `NEW CHUNK SIZE`.
|
||||
|
||||
A snapshot with `completed_at` set to `NULL` is unfinished. `snapshot list` does
|
||||
not show it. The next backup deletes it, and so does `prune`.
|
||||
A snapshot with `completed_at` set to `NULL` is unfinished. `snapshot list`
|
||||
shows it only when its manifest is at the destination, and then as remote only.
|
||||
The next backup deletes it, and so does `prune`.
|
||||
|
||||
### `snapshot_files`
|
||||
|
||||
@@ -324,7 +325,8 @@ Storing a changed file writes these rows:
|
||||
|
||||
- A row in `blobs`, when packing of a blob starts.
|
||||
- When the blob is closed, in one transaction:
|
||||
- a row in `chunks` for each new chunk in the blob
|
||||
- a row in `chunks` for each chunk queued since the last blob was closed.
|
||||
When a blob is full, that includes the first chunk of the next blob.
|
||||
- the blob's rows in `blob_chunks`
|
||||
- the blob's `blob_hash`, sizes and `finished_ts`
|
||||
- When the blob is stored at the destination, in one transaction:
|
||||
|
||||
@@ -94,13 +94,16 @@ A blob's name is `hex(SHA256(SHA256(uncompressed contents)))`. The contents are
|
||||
the chunk data, joined in order, before compression and encryption. The name is
|
||||
not a hash of the stored bytes.
|
||||
|
||||
This has two consequences:
|
||||
This has three consequences:
|
||||
|
||||
- Checking a blob against its name needs the private key. The blob must be
|
||||
decrypted and decompressed first. `snapshot restore` and
|
||||
`snapshot verify --deep` do this.
|
||||
- Without the key, only a blob's presence and size can be checked.
|
||||
`snapshot verify` does this.
|
||||
- Someone who has the whole contents of a blob can compute its name, and so see
|
||||
whether it is stored. This works for a file they have that fills blobs on its
|
||||
own.
|
||||
|
||||
`blobgen.DoubleSHA256` in `internal/blobgen` computes the name.
|
||||
|
||||
@@ -224,6 +227,7 @@ Someone who can read the destination therefore learns these:
|
||||
- when each backup finished
|
||||
- how many blobs each snapshot uses, and how large they are
|
||||
- which blobs two snapshots share
|
||||
- whether a blob holds data they already have in full
|
||||
- whether a snapshot ID they guess exists
|
||||
|
||||
They do not learn these:
|
||||
|
||||
@@ -446,9 +446,9 @@ func newConfigSetCommand() *cobra.Command {
|
||||
Use: "set <key> <value>",
|
||||
Short: "Set a config value by dotted path (e.g. compression_level 5)",
|
||||
Long: `Sets a scalar config value addressed by dotted YAML path and writes
|
||||
the file back, preserving comments and formatting. Missing keys along
|
||||
the path are created: as a list when the next path element is a
|
||||
number, otherwise as a map.
|
||||
the file back. Comments in the file are kept. Blank lines can be
|
||||
removed. Missing keys along the path are created: as a list when the
|
||||
next path element is a number, otherwise as a map.
|
||||
|
||||
If the config loads, a change after which it would not, such as
|
||||
compression_level 99, is refused and the file is left unchanged. A
|
||||
|
||||
Reference in new issue
Block a user