CLI no longer has its own charset-sampling path — uses the CSPRNG
generate_password / generate_passphrase in relicario-core, which use
rand::distributions::Uniform internally.
Extracted purge_item helper so cmd_trash_empty loops over it without
re-prompting for passphrase per item. Single git commit per trash empty
summarizing the count. Caught in Task 12 review.
Soft-delete sets trashed_at via Item::soft_delete; restore clears it.
Purge deletes item + attachment dir and removes manifest entry.
Trash empty scans for items past settings.trash_retention.
Title/group/tags always optional. Per-type prompts for core secret
fields (Login.password, Card.number, Key.material, SecureNote.body)
push the old value to field_history via a synthetic core:<key>
FieldId so rotation is audit-traceable.
Secrets masked by default (audit M7). --show reveals plaintext.
--copy writes to clipboard and spawns a detached 30s auto-clear
thread holding a Zeroizing copy that wipes on drop (audit M6).
SecureNote, Identity, Card, Key, Document (with inline attachment),
and Totp with base32 secret decoding. Document widens the commit
to include the attachment blob path.
Unlocks vault, builds LoginCore from flags (password via rpassword if
--password-prompt), saves item + manifest, commits via hardened git.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. Add .relicario/salt to the initial git commit so it syncs across
devices (Argon2 salt must match at unlock time).
2. Return a proper error instead of panicking when --output has no
filename component (e.g., trailing ..).
3. Wrap the generated 32-byte image_secret in Zeroizing for
consistency with the passphrase + master_key handling in Task 4.
Caught in Task 6 review.
Prompts for a strong passphrase (zxcvbn gate via core), generates a
32-byte image secret, embeds it in the carrier JPEG, writes the
standard vault skeleton, and makes an initial git commit via the
hardened git_command helper.
Every subcommand from the Plan 1B CLI spec present; bodies return
'not yet implemented' so subsequent tasks land one command at a time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
atomic_write now appends .tmp instead of replacing the extension
(manifest.enc.tmp, not manifest.tmp). image_secret is wrapped in
Zeroizing so both KDF inputs wipe on drop. Caught in Task 4 review.
Provides load/save helpers for Manifest/Settings/Item; atomic_write keeps
vault files consistent across crashes. main.rs is transiently broken
against the old Entry API — Task 5+ rewrites the command handlers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
peek_jpeg_dimensions reads jpeg[i+8] as the last byte, so the guard
should be \`i + 8 >= jpeg.len()\`, not \`i + 9 >= jpeg.len()\`. The old
guard would reject a valid SOF marker ending exactly at len()-1.
Caught in Task 2 code-quality review.
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>
Auto-deref at &Zeroizing<[u8;32]> call sites, range pattern in generators,
useless String::into conversions in tests, unused Zeroizing import.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The old Entry/ManifestEntry/Manifest types are gone. CLI/extension
references break and will be fixed by Plans 1B and 1C respectively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Forever, LastN, and Days policies all covered. Tests verify drop order
(keeps newest), days cutoff, and forever-no-op semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
encrypt_item / decrypt_item / encrypt_manifest / decrypt_manifest /
encrypt_settings / decrypt_settings. All plaintext flows through
Zeroizing so JSON buffers are wiped on drop.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AttachmentId is derived from sha256(plaintext) so identical content
deduplicates naturally. Size cap enforced at encrypt time, returning
IdfotoError::AttachmentTooLarge.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Avoids from_utf8 panic when Custom contains multi-byte UTF-8 chars
whose individual bytes are independently sampled into the output.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Uses rand::distributions::Uniform for unbiased sampling (audit H6).
Safe symbols = !@#$%^&*-_=+ (excludes characters that web forms
commonly reject). Test length capped at 128 (validator upper bound).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same latent bug as TrashRetention/HistoryRetention — serde's
internally-tagged repr cannot merge a newtype primitive payload
into a tag object. Add regression test for Custom round-trip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ManifestEntry holds the per-item browse summary including derived
icon_hint (Login URL hostname) and attachment_summaries. Search matches
title or tag substring case-insensitively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
set_field_value() captures old values for Password, Concealed, and Totp
kinds. Soft-delete via trashed_at timestamp; restore clears it. Kind
changes on set_field_value are rejected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Parallel kind/value enums with a validate() invariant. Password,
Concealed, and Totp kinds are marked history-tracked so the Item setter
(next task) can decide whether to capture history on update.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>