Plan B Phase 7 sub-step 2 — moves the bodies of parse_month_year,
base32_decode_lenient, guess_mime from crates/relicario-cli/src/parse.rs
to relicario-core. The CLI's parse.rs becomes a 19-line shim re-exporting
the new core API.
New core surface:
- time::MonthYear::parse (Result<_, RelicarioError>)
- mime::guess_for_extension (new mime module)
- item_types::TotpConfig::parse_secret — Zeroizing<Vec<u8>> wrapper
over base32::decode_rfc4648_lenient
base32 module promoted from pub(crate) to pub so non-core consumers
(CLI shim, future Phase 8 WASM exports) can reach it. New
RelicarioError::InvalidMonthYear(String) for the parse error path
(mirrors sub-step 1's InvalidBase32). MonthYear::new keeps its
&'static str error type — bringing it to RelicarioError is DEV-A's P3.
CLI callsites unchanged (commands/{add,edit,attach}.rs); RelicarioError
auto-converts to anyhow::Error at ? boundaries.
cargo test --workspace: green (core 143, +7 from new tests)
cargo clippy --workspace: silent
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New crates/relicario-core/src/base32.rs hosts encode_rfc4648 +
decode_rfc4648_lenient (case-insensitive, optional padding, whitespace
stripped). Folds inline base32_encode (item.rs:255-275) and
decode_base32_totp (import_lastpass.rs:202-220) into the shared module;
both call sites updated.
- New RelicarioError::InvalidBase32(String) variant for the decoder
error path
- Module is pub(crate); public API surface unchanged
- Steam alphabet (item_types/totp.rs:13) intentionally separate with
neighbour comment pointing at crate::base32
Plan B Phase 7 sub-step 1 (DEV-A P2 base32 dedup half).
docs/superpowers/specs/2026-05-04-cli-restructure-design.md.
cargo test --workspace: green
cargo clippy --workspace: silent
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
HOTP requires incrementing and persisting the counter after each use.
Without vault-save machinery in compute_totp_code, HOTP would desync
immediately. Now returns HotpNotSupported error.
TOTP and Steam codes continue to work.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Brand name uses capital R in user-facing text — extension UI strings,
CLI clap help / descriptions / error prose, markdown docs. Lowercase
preserved for the binary command, crate names, npm package, file
paths, env vars, and code identifiers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds csv = "1" to relicario-core; introduces
ImportCsvHeader and ImportCsvFormat. Foundation for the
import_lastpass module landing in Task 2.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds zstd, tar, base64 to relicario-core; introduces
BackupBadMagic / BackupUnsupportedVersion / BackupSchemaMismatch.
Foundation for the backup module landing in Task 2.
Resolves conflicts from merging origin/main (idfoto→relicario rename):
- Kept Plan 1A's typed-item vault.rs, lib.rs, integration.rs over main's
old entry-based versions
- Took main's relicario_dir() fix in CLI main.rs (sed had missed idfoto_dir)
- Kept Plan 1A's UnsupportedFormatVersion error variant in crypto.rs
- Kept Plan 1A's opaque Decrypt message (audit M4) in error.rs
- Deleted entry.rs (replaced by item.rs + typed modules in Plan 1A)
- Resolved Cargo.toml description to main's "relicario password manager"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renames crate directories and sweeps identifiers so Plan 1B can reference
the post-rename names throughout.
- git mv crates/idfoto-{core,cli,wasm} → crates/relicario-{core,cli,wasm}
- sed sweep: idfoto_core/idfoto-core/IdfotoError/IDFOTO_IMAGE/.idfoto/ etc.
- All 128 relicario-core tests pass post-sweep
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>