# arca — v1.0.0 Plan ## Current State (v0.1.0) Working proof of concept. FIDO2 unlock via cryptsetup with passphrase fallback, privileged mount/unmount, config aliases with method sequencing, init and status commands. ## M1: Idempotent mount/unmount `mount` and `unmount` should be safe to run at any point in a device's lifecycle without producing confusing errors. ### Files changed - `cmd/mount.go` - `cmd/unmount.go` - `internal/udisks/client.go` ### Work 1. In `runMount`, after `FindDevice`, check if the device is already unlocked (`CleartextDevice` succeeds). If the cleartext device is already mounted, print the existing mount point and return success. If unlocked but not mounted, skip unlock and go straight to mount. 2. In `runUnmount`, handle each failure case: - `CleartextDevice` fails (already locked): print "already locked" and return success. - `Unmount` fails because not mounted: proceed to lock anyway. - `Lock` fails because already locked: return success. 3. Add `client.IsMounted(dev)` helper that returns `(mountpoint, bool)` to reduce duplicated mount-point checking logic. --- ## M2: Error messages Replace generic D-Bus errors with actionable messages. ### Files changed - `internal/udisks/client.go` - `cmd/mount.go`, `cmd/unmount.go`, `cmd/init.go`, `cmd/status.go` ### Work 1. Wrap the `dbus.SystemBus()` error in `NewClient` to detect "connection refused" or "no such file" and print: `"cannot connect to udisks2 — is the udisks2 service running?"` 2. In `FindDevice`, when no device matches, include what was searched and suggest `arca status` or `arca init`: `"device /dev/sda1 not found (run 'arca status' to list devices)"` 3. In the unlock sequencer, prefix each method error with context: `"fido2: cryptsetup open --token-only: exit status 5 (is the FIDO2 key plugged in?)"` --- ## M3: Unit tests Cover pure logic that doesn't need D-Bus or real devices. ### Files changed - `internal/config/config_test.go` (new) - `internal/cryptsetup/cryptsetup_test.go` (new) ### Work 1. **config_test.go** — test cases: - `ResolveDevice` with exact alias match - `ResolveDevice` with device path match (`/dev/sda1` -> `sda1`) - `ResolveDevice` with unknown name returns default methods - `ResolveDevice` with empty methods list defaults to `[passphrase]` - `AliasFor` finds alias by UUID - `AliasFor` returns "" for unknown UUID - `Load` with nonexistent file returns empty config - `Load` with valid YAML parses correctly 2. **cryptsetup_test.go** — test cases: - `MapperName("/dev/sda1")` == `"arca-sda1"` - `MapperName("/dev/nvme0n1p2")` == `"arca-nvme0n1p2"` - `hasTokenPlugins` with a temp dir containing a matching .so - `hasTokenPlugins` with an empty temp dir --- ## M4: CLI polish Small usability improvements. ### Files changed - `cmd/root.go` - `cmd/mount.go` - `cmd/init.go` - `main.go` - `.gitignore` (new) ### Work 1. Add `var version = "dev"` to `main.go`. Set `rootCmd.Version` in `cmd/root.go`. Build with `-ldflags "-X main.version=..."` in `flake.nix`. 2. Add `--mountpoint` / `-m` flag to `mount` subcommand. When set, pass it to `cryptsetup.Mount` (privileged path) or log a warning that udisks2 doesn't support custom mount points. 3. In `init`, use first 8 chars of UUID as alias instead of device path basename. Example: `b8b2f8e3` instead of `sda1`. UUIDs are stable across boots; device paths are not. 4. Create `.gitignore` containing `/arca`. --- ## M5: Documentation and packaging Make the project installable and the README trustworthy. ### Files changed - `README.md` - `flake.nix` ### Work 1. Update `README.md`: - Replace placeholder UUIDs with realistic examples from actual tested usage. - Add "NixOS notes" section documenting the `LD_LIBRARY_PATH` requirement for FIDO2/TPM2 and why `--external-tokens-path` doesn't work. - Add "Troubleshooting" section: no FIDO2 token enrolled, udisks2 not running, permission denied on mount. - Document `init` subcommand. 2. Verify `flake.nix`: - Run `nix build` and confirm it produces a working binary. - Add `-ldflags` for version injection from `self.rev` or a `version` variable. - Test the flake output: `./result/bin/arca --version`. 3. Tag `v1.0.0`. --- ## Non-goals for v1.0.0 - `--dry-run` flag - `--json` output for `status` - udev auto-mount on plug - Keyfile creation/management - Multiple config files or config includes