Files
treatvault/README.md

57 lines
3.3 KiB
Markdown

# TreatVault
TreatVault manages Barkstack's namespaced secrets. It keeps an age-encrypted source-of-truth file on disk, watches it for changes, and reconciles its contents with Docker Swarm secrets.
## Model
- The Barkfile `treatvault` block names the encrypted file (a bind-mounted path) and the bootstrap Docker secret holding the age X25519 identity (`barkstack_<reference>`).
- The encrypted file is safe to commit and back up: contents are age-encrypted with the X25519 identity; only the identity secret itself stays outside source control.
- Each logical secret is stored as a versioned record. Sync creates one immutable Docker secret per record revision, named `barkstack_tv_<vaultId>_<revision>`, labeled with the logical name and vault ID.
- Consumers mount secrets at the stable target path `barkstack_<name>`; rotations swap the mounted source and update the service, leaving a rollback path.
- Obsolete Barkstack-managed secret objects are deleted; objects still mounted by a managed service are reported in the sync status and refused for deletion via the API until their consumers are updated.
## CLI
```sh
treatvault keygen --identity ./treatvault-identity.txt
treatvault init --file ./secrets.age --identity ./treatvault-identity.txt
treatvault set --name database_password --file ./secrets.age --identity ./treatvault-identity.txt # value on stdin
treatvault list --file ./secrets.age --identity ./treatvault-identity.txt
treatvault delete --name database_password --file ./secrets.age --identity ./treatvault-identity.txt
treatvault serve --file ./secrets.age --identity ./treatvault-identity.txt --listen :9090
```
## HTTP API
- `GET /barkstack/ui/manifest.json` - Barkstack plugin manifest (id `treatvault`, mount `/treatvault`).
- `GET /barkstack/api/secrets` - secret names, sync state, consumers; never returns values.
- `PUT /barkstack/api/secrets/{name}` - create or rotate (`{"value":"..."}`); triggers an immediate sync.
- `DELETE /barkstack/api/secrets/{name}` - delete; `409 Conflict` while a managed service still mounts the secret.
- `GET /healthz` - ready/degraded sync state.
## Barkstack deployment
Add a `treatvault` block to the Barkfile and run `barkstack init` on a Swarm manager:
```text
treatvault {
file ./secrets.age
identity_secret treatvault_identity
}
```
`barkstack init` provisions the `barkstack-treatvault` service (manager-constrained) with the encrypted file bind-mounted read-write at its host path, the Docker socket, the `barkstack_treatvault_identity` secret mounted at `/run/secrets/barkstack_treatvault_identity`, and no published ports; the console reaches it over the overlay network at `:9090`.
Services that consume vault secrets carry the `io.barkstack.treatvault.secrets=true` label plus an `io.barkstack.treatvault.names` label listing the logical names they need; `barkstack init` labels the PawSQL service automatically. Each sync mounts the current revision at the stable `/run/secrets/barkstack_<name>` target, so consumers read the same path across rotations.
The Barkstack console automatically gains a TreatVault page (plugin id `treatvault`) for creating, rotating, and deleting secrets. Deletion is refused with `409 Conflict` while a labeled service still mounts the secret.
## Build
```sh
cd ui && bun install && bun run build && cd ..
go build -o treatvault ./cmd/treatvault
docker build -t treatvault .
```