Matthew Jackson 0ed613d7a9 Add the qa gate: dev for speed, qa for proof
dev -> qa -> main, across every public repo.

dev is where work lands and is meant to be pushed to often, so ci.yml stays
the fast answer: fmt, clippy, unit tests, leak-guard. qa is the release
candidate, and qa.yml is the claim that a commit is production worth —
release-profile tests on all three platforms, and the Linux cross-target
clippy that the local precommit gate has always run but CI never did.

Release profile matters as its own gate: overflow checks are off, debug_assert
is compiled out, and inlining changes what the optimiser can prove. A test
that only passes in debug never guarded the binary anyone ships.

qa.yml checks siblings out at qa rather than dev. This is not a monorepo, and
a qa run resolving its dependencies from unreleased dev tips would go green on
a combination that is not the one shipping — the exact mismatch the branch
model exists to prevent. ci.yml now tracks whichever branch triggered it for
the same reason, since it also fires on qa.

The consequence is that repos move to qa together, in dependency order. qa is
backfilled from main so an unchanged crate still presents working code to the
crates built on it.
2026-08-05 20:59:34 -07:00
2026-08-05 13:59:41 -07:00
2026-07-10 12:31:19 -07:00
2026-07-28 15:35:19 -07:00

freemkv-unlock

The unlock layer for the freemkv toolchain.

An unlocker removes a drive-level bus-encryption barrier so the drive serves readable (de-bus'd / de-scrambled) sectors. Content-key decryption is a separate concern — the consumer's job.

This crate defines the Unlocker contract and a generic SCSI transport contract, and holds the self-contained unlocker modules. The consumer (libfreemkv) depends on this crate and dispatches through all_unlockers(); it never names an individual unlocker, and clients of libfreemkv are oblivious to unlockers entirely (as they are to the SCSI layer).

use freemkv_unlock::UnlockError;

// Drive-prep: try each unlocker's feature unlock until one claims the drive.
// `NotApplicable` means "not this unlocker's drive" — move on; a transport
// error means a dead bus — abort. `unlock_bus` follows the same contract for
// removing per-disc bus encryption.
for u in freemkv_unlock::all_unlockers() {
    match u.unlock_features(&mut scsi, &ctx) {
        Ok(unlocked) => return Ok(unlocked),
        Err(UnlockError::NotApplicable) => continue,
        Err(e) => return Err(e),
    }
}

To remove an unlocker, delete its module directory and its one line in all_unlockers() — nothing else changes.

License: MIT.

S
Description
No description provided
Readme MIT
1.3 MiB
Languages
Rust 100%