garden/lock.go: Lock() and Unlock() toggle the locked flag on
existing tracked entries. Errors on untracked paths. Persists
to manifest.
cmd/sgard/lock.go: sgard lock <path>..., sgard unlock <path>...
6 tests: lock/unlock existing entry, persistence, error on untracked,
checkpoint behavior changes after lock, status changes between
drifted and modified after unlock.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLI: sgard encrypt init [--fido2], add-fido2 [--label], remove-slot,
list-slots, change-passphrase. sgard add --encrypt flag with
passphrase prompt for DEK unlock.
Garden: RemoveSlot (refuses last slot), ListSlots, ChangePassphrase
(re-wraps DEK with new passphrase, fresh salt).
Proto: ManifestEntry gains encrypted + plaintext_hash fields. New
KekSlot and Encryption messages. Manifest gains encryption field.
server/convert.go: full round-trip conversion for encryption section
including KekSlot map.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FIDO2Device interface abstracts hardware interaction (Register, Derive,
Available, MatchesCredential). Real libfido2 implementation deferred;
mock device used for full test coverage.
AddFIDO2Slot: registers FIDO2 credential, derives KEK via HMAC-secret,
wraps DEK, adds fido2/<label> slot to manifest.
UnlockDEK: tries all fido2/* slots first (checks credential_id against
connected device), falls back to passphrase. User never specifies
which method.
6 tests: add slot, reject duplicate, unlock via FIDO2, fallback to
passphrase when device unavailable, slot persistence, encrypted
round-trip unlocked via FIDO2.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Client orchestrates the two-step push/pull protocol: manifest exchange
followed by chunked blob streaming. Push detects server-newer (returns
ErrServerNewer) and up-to-date states. Pull computes missing blobs
locally and streams only what's needed. Prune delegates to server RPC.
6 integration tests via in-process bufconn server.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Step 10: GetManifest, BlobExists, ReadBlob, WriteBlob, ReplaceManifest
accessor methods on Garden. 5 tests.
Step 11: ManifestToProto/ProtoToManifest conversion functions in
server package with time.Time <-> timestamppb handling. Round-trip
test covering all 3 entry types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove: untrack files, remove manifest entries, save. 2 tests.
Verify: check blobs against manifest hashes, report ok/mismatch/missing. 3 tests.
List: return all tracked entries, CLI formats by type. 2 tests.
Diff: compare stored blob vs current file, simple line diff. 3 tests.
Each command in its own file (garden/<cmd>.go) for parallel development.
Remove, verify, list implemented by parallel worktree agents; diff manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restore writes tracked files back to their original locations.
Supports selective path restoration, force mode, and a confirm
callback for files where the on-disk mtime >= manifest timestamp
(truncated to seconds for cross-platform reliability). Creates
parent directories, recreates symlinks, and sets file permissions.
CLI: sgard restore [path...] [--force].
6 new tests (file, permissions, symlink, parent dirs, selective, confirm skip).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checkpoint re-hashes all tracked files, stores changed blobs, and
updates per-file timestamps only when content changes. Missing files
are skipped gracefully. Status compares each tracked entry against
the filesystem and reports ok/modified/missing.
CLI: sgard checkpoint [-m message], sgard status.
4 new tests (changed file, unchanged file, missing file, status).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Garden package ties manifest and store together. Supports adding
files (hashed and stored as blobs), directories (manifest-only),
and symlinks (target recorded). Paths under $HOME are stored as
~/... in the manifest for portability. CLI init and add commands
wired up via cobra.
8 tests covering init, open, add for all three entry types,
duplicate rejection, HashFile, and tilde path expansion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Manifest package (5 tests): Manifest/Entry structs with YAML tags,
New(), Load(), Save() with atomic write.
Store package (11 tests): content-addressable blob store keyed by
SHA-256, Write/Read/Exists/Delete with atomic writes, two-level
directory layout, hash validation.
Both implemented in parallel worktrees and merged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements Manifest and Entry structs with YAML tags, New() constructor,
Load(path) for reading, and Save(path) with atomic write (temp file +
rename). Tests cover round-trip serialization, atomic save cleanup,
entry type invariants, nonexistent file error, and empty manifest.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove all old C++ source files, proto definitions, CMake build,
clang configs, IDE files, and Trunk linter config. Initialize Go
module (github.com/kisom/sgard) with cobra and yaml.v3 deps.
Set up cobra root command with --repo persistent flag.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>