Skip to content

Add cryptographic puzzle integrity verification#43

Open
Lajishola wants to merge 1 commit into
MindFlowInteractive:mainfrom
Lajishola:feat/issue-42-puzzle-integrity-verification
Open

Add cryptographic puzzle integrity verification#43
Lajishola wants to merge 1 commit into
MindFlowInteractive:mainfrom
Lajishola:feat/issue-42-puzzle-integrity-verification

Conversation

@Lajishola

Copy link
Copy Markdown

Closes #42.

Summary

  • Puzzle gains a content_hash: Option<String> field plus compute_content_hash / generate_content_hash / verify_content_hash. The hash is SHA-256 over a canonical view of the puzzle's authored content (id, description, condition ids/descriptions, effects) — gameplay-state fields (state, Condition::satisfied) are deliberately excluded so solving a puzzle never changes its hash.
  • New PuzzleIntegrityError (MissingHash / Mismatch), wired into the repo's existing centralized AppError via a new AppError::PuzzleIntegrity variant (From impl, Display, source()), consistent with how Io/Serde errors are already handled.
  • New loader module:
    • load_puzzle_file / load_puzzles_from_dir — load and hash-verify puzzle JSON files, fail fast on the first bad file.
    • verify_puzzles_in_dir — checks every file and returns a report per file (doesn't stop at the first failure), backing the CLI's --verify-puzzles.
    • generate_hashes_in_dir — (re)stamps content_hash for every puzzle file in a directory.
  • CLI (main.rs):
    • --verify-puzzles [dir] (defaults to puzzles/) — checks all puzzle files and prints an OK/FAIL report.
    • --generate-hashes [dir] --admin — regenerates hashes; requires the explicit --admin flag since it rewrites puzzle files in place, per the issue's "admin use only" requirement.
  • Session / SessionData gain puzzle_content_hashes, via a new Session::complete_puzzle_with_hash, so a completed session carries per-puzzle content hashes for submission to logiquest_api. Note: this repo doesn't currently have a logiquest_api HTTP client, so this PR only wires the hash data through to SessionData — actual submission is left to whatever eventually implements that client.
  • puzzles/starter-lever.json — a sample puzzle file with a valid content_hash, so --verify-puzzles has something to check out of the box.
  • sha2 = "0.10" added as the hashing dependency (chosen over blake3 to avoid a C build dependency, given both were acceptable per the issue).

Test plan

  • cargo test — unit tests cover valid-hash verification, tampered description/effects, a missing hash field, hash generation, and that gameplay mutations don't change the hash (in puzzle::tests, loader::tests, session::tests, errors::tests).
  • cargo run -- --verify-puzzles reports OK puzzles/starter-lever.json.
  • cargo run -- --generate-hashes puzzles --admin regenerates hashes in place; running without --admin refuses with an explanatory message.
  • CI (cargo build --all-targets, cargo test, cargo clippy -- -D warnings, cargo fmt --check) passes.

I wasn't able to compile locally in my environment (missing Windows SDK / MSVC linker, and a space-in-path bug in the available MinGW toolchain) but reviewed the diff carefully by hand; the repo's CI runs on ubuntu-latest and should build cleanly.

…ctive#42)

Adds SHA-256 content hashing so puzzle definitions can be verified before
loading, preventing cheating via tampered local puzzle files:

- Puzzle gains a content_hash field plus compute/generate/verify methods,
  hashed over a canonical view of its authored content (id, description,
  condition ids/descriptions, effects) so gameplay-state mutations never
  change the hash.
- New PuzzleIntegrityError (missing/mismatched hash), wired into the
  existing centralized AppError via AppError::PuzzleIntegrity.
- New loader module: load_puzzle_file / load_puzzles_from_dir verify
  hashes on every load; verify_puzzles_in_dir reports every failure
  instead of failing fast; generate_hashes_in_dir (re)stamps files.
- CLI: `--verify-puzzles [dir]` checks all puzzle files and reports
  results; `--generate-hashes [dir] --admin` regenerates hashes and is
  gated behind an explicit --admin flag since it rewrites files in place.
- Session/SessionData now carry puzzle_content_hashes so a completed
  session's submission to logiquest_api can include per-puzzle hashes for
  server-side verification (no logiquest_api client exists in this repo
  yet, so this only wires the data through to SessionData).
- puzzles/starter-lever.json: a sample hashed puzzle file for the new
  loader/CLI to operate on.

Unit tests cover valid-hash verification, tampered content, a missing
hash field, and hash generation, per the issue's acceptance criteria.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Cryptographic Puzzle Integrity Verification

2 participants