You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(chaos): central md5+blake3 s6.3 content invariant + close M3.7 recheck-1
Closes the still-open M3.7 recheck round-1 codex findings (baseline 60d3a1c;
finding 1 disk-full was already resolved as an honest documented known-gap):
- F2 (P1) central no-data-loss now enforces STRESS_HARNESS s6.3 in full: for
every synced row the live object must exist, its md5 must match drive_md5,
AND (unencrypted + retained-bytes) the bytes must hash to hash_blake3. Adds
blake3 dep + InMemoryRemoteStore::object_content; gates the byte-hash on
!encryption_enabled (ciphertext != plaintext hash) and skips oracle-backed
huge files (md5 is their proof). Mirrors an md5 check into the drive_side
per-category checker.
- F3 (P1) drive-fileid-recycled asserts y.id == id_x so a regressed recycler
fails instead of passing vacuously on the op-uuid check.
- F4 (P1) distinct chaos-fake-drive CI job (3-OS) via run-all --fault-injection
+ registry::fault_injection_registry (ROADMAP M3.7 / STRESS_HARNESS s7).
- F5 (P2) fake trash()/about() use content_len() so oracle-backed objects free
their true logical size from bytes_stored.
- F6 (P2) mutator-drive-daily-quota runs hermetically via the real
with_daily_quota_after injector; drops the real-creds gate + SKIP early-return.
- F7 (P2) capability probes target the target/chaos-fixtures volume, not temp.
Gates: fmt; build; clippy -D warnings; test --workspace (all green); hermetic
56 PASS/29 SKIP/0 FAIL; fault-injection 27 PASS/0 FAIL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8meqeTo8bcZ3zjgKjBnJ4
// The current InMemoryRemoteStore fault surface cannot emit a faithful
1096
-
// `daily` (vs storage) quota signal; the executor classifies "daily"
1097
-
// only from a message the fake does not produce. Rather than assert a
1098
-
// weakened/faked code, this scenario records the capability gap and
1099
-
// returns a documented-skip outcome that the driver renders SKIPPED.
1100
-
ifmatches!(self.kind,DriveKind::DailyQuota){
1101
-
returnOk(Outcome{
1102
-
error_codes_seen:vec![],
1103
-
final_drive_object_count:0,
1104
-
final_hash_matches_local:true,
1105
-
notes:vec![
1106
-
"SKIP-by-capability: InMemoryRemoteStore exposes no faithful dailyLimitExceeded injector (only storageQuotaExceeded via with_quota_exhausted_after); the executor's daily classification needs a 'daily' message the fake does not emit. Not faking the code. Follow-up: add InMemoryRemoteStore::with_daily_quota_after to driven-drive fault_injection.".to_string(),
1107
-
"invariants: None - this is a capability SKIP early-return; no handle/source/remote was booted, so there is no single source+folder snapshot to sweep.".to_string(),
1108
-
],
1109
-
// Capability SKIP: nothing was synced, so there is no terminal
1110
-
// source+remote state for the canonical s6.3 sweep to read.
1111
-
invariants:None,
1112
-
});
1113
-
}
1114
-
1083
+
// Every kind - including daily-quota - now runs the same hermetic body:
1084
+
// `build_remote` rigs the kind's fault on the fake (the daily-quota row
1085
+
// uses the real `with_daily_quota_after` injector), and the run drives
1086
+
// cycles, collects the surfaced codes, and sweeps the canonical s6.3
1087
+
// invariants. No kind early-returns a capability SKIP any more.
1115
1088
let state_dir = tempfile::tempdir()?;
1116
1089
let root_dir = tempfile::tempdir()?;
1117
1090
// A modest multi-file population so a "after N bytes / N requests"
@@ -1667,27 +1640,38 @@ mod tests {
1667
1640
);
1668
1641
}
1669
1642
1670
-
/// The daily-quota scenario honestly SKIPS (capability gap) rather than
1671
-
/// faking a code the fake cannot emit.
1643
+
/// The daily-quota scenario now runs hermetically against the fake's
1644
+
/// `with_daily_quota_after` injector and surfaces the real
1645
+
/// `DriveDailyQuotaExhausted` code (distinct from storage quota). It is no
1646
+
/// longer a capability SKIP - the injector exists.
1672
1647
#[tokio::test]
1673
-
asyncfndrive_daily_quota_skips_by_capability(){
1648
+
asyncfndrive_daily_quota_surfaces_code(){
1674
1649
let scenario = DriveMutatorScenario::daily_quota_exhausted();
1650
+
// It runs on a stock host - no real-Drive capability required.
1651
+
assert!(
1652
+
scenario.requires().required.is_empty(),
1653
+
"daily-quota row needs no host capability now"
1654
+
);
1675
1655
let state_dir = tempfile::tempdir().expect("state dir");
1676
1656
let remote = Arc::new(InMemoryRemoteStore::new());
1677
1657
let handle = boot_handle(state_dir.path(), remote)
1678
1658
.await
1679
1659
.expect("boot placeholder handle");
1680
1660
let outcome = scenario.run_assertions(&handle).await.expect("runs");
1681
1661
assert!(
1682
-
outcome.error_codes_seen.is_empty(),
1683
-
"no code faked for the unavailable daily-quota injector"
1662
+
outcome
1663
+
.error_codes_seen
1664
+
.contains(&ErrorCode::DriveDailyQuotaExhausted),
1665
+
"drive.daily_quota_exhausted surfaced; saw {:?}",
1666
+
outcome.error_codes_seen
1684
1667
);
1668
+
// The daily code is classified distinctly from storage quota.
1685
1669
assert!(
1686
-
outcome
1687
-
.notes
1688
-
.iter()
1689
-
.any(|n| n.contains("SKIP-by-capability")),
1690
-
"records the capability gap reason"
1670
+
!outcome
1671
+
.error_codes_seen
1672
+
.contains(&ErrorCode::DriveQuotaExhausted),
1673
+
"daily quota is not misclassified as storage quota; saw {:?}",
0 commit comments