Files
2026-02-25 00:23:05 +03:00

175 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 03-round-trip-verification
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/lib.rs
- src/main.rs
- Cargo.toml
- src/crypto.rs
- src/compression.rs
- src/format.rs
autonomous: true
requirements: [TST-03]
must_haves:
truths:
- "Unit tests pass for crypto module: encrypt/decrypt round-trip, HMAC compute/verify, SHA-256 known value"
- "Unit tests pass for compression module: compress/decompress round-trip, empty data, should_compress heuristic"
- "Unit tests pass for format module: header write/read round-trip, TOC entry write/read round-trip (ASCII + Cyrillic names)"
- "Project compiles as both library crate and binary crate (cargo build succeeds)"
artifacts:
- path: "src/lib.rs"
provides: "Library crate re-exporting all modules for integration tests"
contains: "pub mod crypto"
- path: "Cargo.toml"
provides: "Dev-dependencies for test infrastructure"
contains: "tempfile"
key_links:
- from: "src/main.rs"
to: "src/lib.rs"
via: "use encrypted_archive:: imports"
pattern: "use encrypted_archive::"
- from: "src/lib.rs"
to: "src/crypto.rs"
via: "pub mod crypto"
pattern: "pub mod crypto"
---
<objective>
Create the library crate structure, add test dependencies, and implement unit tests for every pipeline module (crypto, compression, format serialization).
Purpose: TST-03 requires unit tests for each pipeline stage. The lib.rs creation also unblocks Plan 02 which needs to import library functions from integration tests in `tests/`.
Output: `src/lib.rs` with module re-exports, dev-dependencies in `Cargo.toml`, unit tests in `#[cfg(test)]` blocks inside `crypto.rs`, `compression.rs`, `format.rs`.
</objective>
<execution_context>
@/home/nick/.claude/get-shit-done/workflows/execute-plan.md
@/home/nick/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/03-round-trip-verification/03-RESEARCH.md
@docs/FORMAT.md
@src/main.rs
@src/crypto.rs
@src/compression.rs
@src/format.rs
@src/key.rs
@Cargo.toml
</context>
<tasks>
<task type="auto">
<name>Task 1: Create lib.rs, update main.rs imports, add dev-dependencies</name>
<files>src/lib.rs, src/main.rs, Cargo.toml</files>
<action>
1. Create `src/lib.rs` that re-exports all modules as public:
```rust
pub mod archive;
pub mod cli;
pub mod compression;
pub mod crypto;
pub mod format;
pub mod key;
```
2. Update `src/main.rs` to use the library crate instead of local `mod` declarations:
- Remove all `mod` declarations (archive, cli, compression, crypto, format, key)
- Replace with `use encrypted_archive::cli::{Cli, Commands};` and `use encrypted_archive::archive;`
- Keep the `use clap::Parser;` import
- The `main()` function body stays the same
3. Add dev-dependencies to `Cargo.toml`:
```toml
[dev-dependencies]
tempfile = "3.26"
assert_cmd = "2.1"
hex-literal = "1.1"
predicates = "3.1"
```
IMPORTANT: Use Context7 to verify `tempfile` and `assert_cmd` API before writing code if needed. The research doc already verified versions (tempfile 3.26.0, assert_cmd 2.1.2, hex-literal 1.1.0, predicates 3.1.4).
4. Verify: `cargo build` succeeds (both lib and bin targets compile).
</action>
<verify>
<automated>cd /home/nick/Projects/Rust/encrypted_archive && cargo build 2>&1</automated>
<manual>No lib.rs compilation errors, main.rs uses encrypted_archive:: imports</manual>
</verify>
<done>Project compiles as both library and binary crate. All six modules re-exported via lib.rs. Dev-dependencies declared in Cargo.toml.</done>
</task>
<task type="auto">
<name>Task 2: Add unit tests to crypto.rs, compression.rs, and format.rs</name>
<files>src/crypto.rs, src/compression.rs, src/format.rs</files>
<action>
Add `#[cfg(test)] mod tests { ... }` blocks at the bottom of each module file.
**src/crypto.rs** -- add these unit tests:
- `test_encrypt_decrypt_roundtrip`: Encrypt "Hello, World!" with KEY and a zero IV, decrypt, assert equality.
- `test_encrypt_decrypt_empty`: Encrypt empty slice, decrypt, assert empty result. Verifies PKCS7 full-block padding on 0-byte input.
- `test_encrypted_size_formula`: Assert `encrypt_data(b"Hello", &KEY, &iv).len() == 16` (5 bytes -> ((5/16)+1)*16 = 16). Also test 16 bytes -> 32 (full padding block), and 0 bytes -> 16.
- `test_hmac_compute_verify`: Compute HMAC for a fixed IV + ciphertext, then verify_hmac returns true. Also test with wrong expected value returns false.
- `test_sha256_known_value`: SHA-256("Hello") must equal `185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969` (from FORMAT.md Section 12.3). Use `hex_literal::hex!()` macro for the expected value.
- `test_sha256_empty`: SHA-256("") must equal `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`.
Import `use super::*;` and `use crate::key::KEY;` and `use hex_literal::hex;` inside the test module.
**src/compression.rs** -- add these unit tests:
- `test_compress_decompress_roundtrip`: Compress "Hello, World! This is test data for compression." -> decompress -> assert equals original.
- `test_compress_decompress_empty`: Compress empty slice -> decompress -> assert empty.
- `test_compress_decompress_large`: Compress 10000 bytes of pattern data -> decompress -> assert equals original.
- `test_should_compress_text`: Assert `should_compress("readme.txt", &[])` is true. Also test "data.json".
- `test_should_not_compress_known_extensions`: Assert `should_compress("app.apk", &[])` is false. Also test "photo.jpg", "archive.zip".
- `test_should_not_compress_excluded`: Assert `should_compress("special.dat", &["special.dat".into()])` is false.
Import `use super::*;` inside the test module.
**src/format.rs** -- add these unit tests:
- `test_header_write_read_roundtrip`: Create a Header with typical values (version=1, flags=0x01, file_count=3, toc_offset=HEADER_SIZE, toc_size=330, toc_iv=zeroed, reserved=zeroed). Write to Vec<u8>, assert len == HEADER_SIZE. Read back from Cursor, assert all fields match.
- `test_toc_entry_roundtrip_ascii`: Create a TocEntry for "hello.txt" with known field values. Write to Vec<u8>, assert len == 101 + 9. Read back, assert all fields match including iv/hmac/sha256 byte arrays.
- `test_toc_entry_roundtrip_cyrillic`: Create a TocEntry for "тестовый_файл.txt". Write, read back, assert name and all fields match. Verify buf length == 101 + "тестовый_файл.txt".len() (which is 29 bytes for UTF-8 Cyrillic).
- `test_toc_entry_roundtrip_empty_name`: Create a TocEntry with name="" (edge case). Write, read back, assert name is empty string.
- `test_header_rejects_bad_magic`: Create a buffer with wrong magic bytes, attempt read_header, assert error.
- `test_header_rejects_bad_version`: Create a valid-magic buffer but version=2, attempt read_header, assert error.
- `test_entry_size_calculation`: Assert `entry_size(&entry_for_hello_txt) == 110` and `entry_size(&entry_for_data_bin) == 109`. Test `compute_toc_size` on both entries equals 219 (matching FORMAT.md worked example).
Import `use super::*;` and `use std::io::Cursor;` inside the test module.
All assertions should use `assert_eq!` for value comparison (gives diff on failure) or `assert!` for boolean checks.
</action>
<verify>
<automated>cd /home/nick/Projects/Rust/encrypted_archive && cargo test 2>&1</automated>
<manual>All unit tests pass, no compilation errors</manual>
</verify>
<done>Unit tests exist and pass for all three pipeline modules: crypto (6 tests), compression (6 tests), format (7 tests). Total: 19 unit tests covering encrypt/decrypt, HMAC, SHA-256, compress/decompress, should_compress, header/TOC serialization round-trips, and error cases.</done>
</task>
</tasks>
<verification>
- `cargo build` succeeds (lib + bin)
- `cargo test` passes all unit tests
- `src/lib.rs` exists and re-exports all modules
- `src/main.rs` uses `use encrypted_archive::` imports (no local `mod` declarations)
- Each of crypto.rs, compression.rs, format.rs has a `#[cfg(test)]` module with tests
</verification>
<success_criteria>
1. `cargo test` runs 19+ unit tests, all pass
2. Project structure supports both `cargo run` (binary) and `use encrypted_archive::module` (library imports)
3. TST-03 is satisfied: unit tests cover compression, encryption, HMAC, SHA-256, format serialization/deserialization
</success_criteria>
<output>
After completion, create `.planning/phases/03-round-trip-verification/03-01-SUMMARY.md`
</output>