Files
arca/PLAN.md
Kyle Isom ea7e09bdfb M1: make mount/unmount idempotent
mount now detects already-unlocked and already-mounted devices, returning
the existing mount point instead of failing. unmount handles already-locked
devices gracefully and skips unmount if not mounted before locking.

Adds IsMounted helper to udisks client. Updates PLAN.md with refined
v1.0.0 milestones.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 07:58:25 -07:00

159 lines
4.4 KiB
Markdown

# 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