From df093255348a9073bfee12fd0e97cb8daa281e6f Mon Sep 17 00:00:00 2001 From: NikitolProject Date: Thu, 26 Feb 2026 23:55:23 +0300 Subject: [PATCH] docs(12-01): complete CLI key input plan - SUMMARY.md with execution results and decisions - STATE.md updated with position, metrics, decisions - ROADMAP.md updated with phase 12 progress - REQUIREMENTS.md: KEY-01, KEY-02, KEY-07 marked complete Co-Authored-By: Claude Opus 4.6 --- .planning/REQUIREMENTS.md | 12 +- .planning/ROADMAP.md | 2 +- .planning/STATE.md | 37 +++-- .../phases/12-user-key-input/12-01-SUMMARY.md | 127 ++++++++++++++++++ 4 files changed, 157 insertions(+), 21 deletions(-) create mode 100644 .planning/phases/12-user-key-input/12-01-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 2559e10..69614e2 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -99,13 +99,13 @@ ### User Key Input (Пользовательский ввод ключа) -- [ ] **KEY-01**: CLI аргумент `--key ` — 64 символа hex, декодируется в 32-байтный AES-256 ключ -- [ ] **KEY-02**: CLI аргумент `--key-file ` — чтение ровно 32 байт из файла как raw ключ +- [x] **KEY-01**: CLI аргумент `--key ` — 64 символа hex, декодируется в 32-байтный AES-256 ключ +- [x] **KEY-02**: CLI аргумент `--key-file ` — чтение ровно 32 байт из файла как raw ключ - [ ] **KEY-03**: CLI аргумент `--password [VALUE]` — интерактивный промпт (rpassword) или значение из CLI - [ ] **KEY-04**: Argon2id KDF — деривация 32-байтного ключа из пароля + 16-байтный random salt - [ ] **KEY-05**: Хранение salt в архиве — flags bit 4 (0x10), 16-байтный salt между header и TOC при pack - [ ] **KEY-06**: Чтение salt из архива при unpack/inspect — автоматическое определение по flags bit 4 -- [ ] **KEY-07**: Один из `--key`, `--key-file`, `--password` обязателен для pack/unpack; inspect принимает ключ опционально +- [x] **KEY-07**: Один из `--key`, `--key-file`, `--password` обязателен для pack/unpack; inspect принимает ключ опционально ## Future Requirements @@ -192,13 +192,13 @@ | TST-05 | Phase 11 | Pending | | TST-06 | Phase 11 | Pending | | TST-07 | Phase 11 | Pending | -| KEY-01 | Phase 12 | Pending | -| KEY-02 | Phase 12 | Pending | +| KEY-01 | Phase 12 | Complete | +| KEY-02 | Phase 12 | Complete | | KEY-03 | Phase 12 | Pending | | KEY-04 | Phase 12 | Pending | | KEY-05 | Phase 12 | Pending | | KEY-06 | Phase 12 | Pending | -| KEY-07 | Phase 12 | Pending | +| KEY-07 | Phase 12 | Complete | **Coverage:** - v1.0 requirements: 30 total -- all Complete diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index a30e8e6..0444865 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -222,7 +222,7 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 **Goal:** Replace hardcoded encryption key with user-specified key input: `--password` (interactive prompt or CLI value, derived via Argon2id), `--key` (raw 64-char hex), `--key-file` (read 32 bytes from file). All three methods produce a 32-byte AES-256 key passed through pack/unpack/inspect. **Requirements**: KEY-01, KEY-02, KEY-03, KEY-04, KEY-05, KEY-06, KEY-07 **Depends on:** Phase 11 -**Plans:** 2 plans +**Plans:** 1/2 plans executed Plans: - [ ] 12-01-PLAN.md -- CLI key args (--key, --key-file, --password), refactor archive.rs to accept key parameter, update all tests diff --git a/.planning/STATE.md b/.planning/STATE.md index d23de99..00567be 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,13 +2,13 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: Directory Support -status: unknown -last_updated: "2026-02-26T19:09:56.676Z" +status: in-progress +last_updated: "2026-02-26T20:53:36Z" progress: - total_phases: 9 + total_phases: 12 completed_phases: 9 - total_plans: 13 - completed_plans: 13 + total_plans: 15 + completed_plans: 14 --- # Project State @@ -18,29 +18,30 @@ progress: See: .planning/PROJECT.md (updated 2026-02-25) **Core value:** Archive impossible to unpack without knowing the format -- standard tools (7z, tar, unzip, binwalk) cannot recognize or extract contents -**Current focus:** Milestone v1.1 Directory Support -- Phase 9: Kotlin Decoder Update COMPLETE +**Current focus:** Phase 12: User Key Input -- Plan 01 COMPLETE, Plan 02 next ## Current Position -Phase: 9 of 11 (Kotlin Decoder Update) -- COMPLETE -Plan: 1 of 1 -- COMPLETE -Status: Phase 9 complete, Kotlin decoder updated for v1.1 format with directory support -Last activity: 2026-02-26 -- Phase 9 Plan 01 executed (Kotlin decoder v1.1 update) +Phase: 12 of 12 (User Key Input) +Plan: 1 of 2 -- COMPLETE +Status: Phase 12 Plan 01 complete, --key and --key-file support added +Last activity: 2026-02-26 -- Phase 12 Plan 01 executed (CLI key input + archive refactor) -Progress: [#############.......] 68% (13/~19 plans estimated) +Progress: [##############......] 70% (14/~20 plans estimated) ## Performance Metrics **Velocity:** -- Total plans completed: 13 +- Total plans completed: 14 - Average duration: 3.6 min -- Total execution time: 0.8 hours +- Total execution time: 0.9 hours | Phase | Plan | Duration | Tasks | Files | |-------|------|----------|-------|-------| | 07-01 | Format Spec Update | 8 min | 2 | 1 | | 08-01 | Rust Directory Archiver | 6 min | 3 | 4 | | 09-01 | Kotlin Decoder Update | 2 min | 2 | 2 | +| 12-01 | CLI Key Input | 5 min | 2 | 8 | ## Accumulated Context @@ -66,11 +67,19 @@ Recent decisions affecting current work: - v1.1: Kotlin decoder uses Java File API owner/everyone permission model (no group-level granularity) - v1.1: Directory entries in Kotlin decoder skip crypto pipeline entirely, use mkdirs() - v1.1: Permission application order: everyone flags first, then owner-only overrides +- v1.2: KeyArgs as top-level clap flatten (--key before subcommand) +- v1.2: inspect accepts optional key: without key shows header only, with key shows full TOC +- v1.2: LEGACY_KEY kept as #[cfg(test)] for golden test vectors +- v1.2: All archive functions parameterized by explicit key (no global state) ### Pending Todos None yet. +### Roadmap Evolution + +- Phase 12 added: User-specified encryption key (--password, --key, --key-file) + ### Blockers/Concerns None. @@ -78,5 +87,5 @@ None. ## Session Continuity Last session: 2026-02-26 -Stopped at: Completed 09-01-PLAN.md -- Phase 9 complete, Kotlin decoder updated for v1.1 +Stopped at: Completed 12-01-PLAN.md -- Phase 12 Plan 01 complete, --key and --key-file support Resume file: None diff --git a/.planning/phases/12-user-key-input/12-01-SUMMARY.md b/.planning/phases/12-user-key-input/12-01-SUMMARY.md new file mode 100644 index 0000000..7c16d31 --- /dev/null +++ b/.planning/phases/12-user-key-input/12-01-SUMMARY.md @@ -0,0 +1,127 @@ +--- +phase: 12-user-key-input +plan: 01 +subsystem: crypto +tags: [clap, hex, aes-256, key-management, cli] + +# Dependency graph +requires: + - phase: 08-rust-directory-archiver + provides: "pack/unpack/inspect with hardcoded key" +provides: + - "CLI --key (hex) and --key-file (raw) key input for pack/unpack" + - "inspect works without key (header only) or with key (full TOC listing)" + - "KeySource enum and resolve_key() in key.rs" + - "All archive functions parameterized by user-provided key" +affects: [12-02-PLAN, kotlin-decoder] + +# Tech tracking +tech-stack: + added: [hex 0.4] + patterns: [key-parameterized archive API, clap arg group for mutually exclusive key sources] + +key-files: + created: [] + modified: + - Cargo.toml + - src/cli.rs + - src/key.rs + - src/archive.rs + - src/main.rs + - src/crypto.rs + - tests/round_trip.rs + - tests/golden.rs + +key-decisions: + - "KeyArgs as top-level clap flatten (not per-subcommand) so --key goes before subcommand" + - "inspect accepts optional key: without key shows header only, with key shows full TOC" + - "LEGACY_KEY kept as #[cfg(test)] constant for golden vectors" + - "Password option uses Option> for future interactive prompt support" + +patterns-established: + - "Key threading: all archive functions accept explicit key parameter instead of global state" + - "cmd_with_key() test helper for CLI integration tests" + +requirements-completed: [KEY-01, KEY-02, KEY-07] + +# Metrics +duration: 5min +completed: 2026-02-26 +--- + +# Phase 12 Plan 01: User Key Input Summary + +**CLI key input via --key (hex) and --key-file (raw bytes), replacing hardcoded constant, with inspect working keyless for header metadata** + +## Performance + +- **Duration:** 5 min +- **Started:** 2026-02-26T20:47:52Z +- **Completed:** 2026-02-26T20:53:36Z +- **Tasks:** 2 +- **Files modified:** 8 + +## Accomplishments +- Removed hardcoded KEY constant from production code; all archive functions now parameterized by key +- Added --key (64-char hex) and --key-file (32-byte raw file) as mutually exclusive CLI args +- inspect works without a key (shows header metadata + "TOC is encrypted" message) and with a key (full entry listing) +- All 47 tests pass: 25 unit + 7 golden + 15 integration (6 new tests added) + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add CLI key args and refactor key.rs + archive.rs signatures** - `acff31b` (feat) +2. **Task 2: Update tests and verify round-trip with explicit key** - `551e499` (test) + +## Files Created/Modified +- `Cargo.toml` - Added hex 0.4 dependency +- `src/cli.rs` - Added KeyArgs struct with --key, --key-file, --password as clap arg group +- `src/key.rs` - Replaced hardcoded KEY with KeySource enum and resolve_key() function +- `src/archive.rs` - Refactored pack/unpack/inspect to accept key parameter +- `src/main.rs` - Wired CLI key args to key resolution and archive functions +- `src/crypto.rs` - Updated tests to use local TEST_KEY constant +- `tests/golden.rs` - Updated to use local KEY constant instead of imported +- `tests/round_trip.rs` - All tests updated with --key, 6 new tests added + +## Decisions Made +- KeyArgs placed at top-level Cli struct (not per-subcommand) so --key goes BEFORE the subcommand name +- inspect accepts optional key: without key shows only header fields, with key decrypts and shows full TOC +- LEGACY_KEY kept as #[cfg(test)] constant in key.rs for golden test vector compatibility +- Password field uses `Option>` to support both `--password mypass` and `--password` (future interactive prompt) + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Fixed wrong-key test assertion** +- **Found during:** Task 2 (test_rejects_wrong_key) +- **Issue:** Wrong key causes TOC decryption failure ("invalid padding or wrong key") before HMAC check on individual files. The test expected "HMAC" or "verification" in stderr. +- **Fix:** Broadened assertion to also accept "Decryption failed" or "wrong key" in error message +- **Files modified:** tests/round_trip.rs +- **Verification:** Test passes with actual error behavior +- **Committed in:** 551e499 (Task 2 commit) + +--- + +**Total deviations:** 1 auto-fixed (1 bug fix in test) +**Impact on plan:** Trivial test assertion fix. No scope creep. + +## Issues Encountered +None + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- Key input foundation complete for Plan 02 (Argon2 password-based key derivation) +- --password CLI arg already accepted (returns "not yet implemented" error) +- KeySource::Password variant ready for Plan 02 implementation + +## Self-Check: PASSED + +All 9 files verified present. Both task commits (acff31b, 551e499) found in git log. + +--- +*Phase: 12-user-key-input* +*Completed: 2026-02-26*