fix(workout): make mobile verification fail closed
Make workout mobile-verify reject non-HTTPS origins and release kits that omit detected external signing/toolchain blockers, so verification checks objective release preconditions instead of pretending to predict store approval. req: examples/006
This commit is contained in:
@@ -29,8 +29,11 @@ target/hemx-mobile/workout/
|
||||
ios/README.md
|
||||
```
|
||||
|
||||
Use `workout mobile-verify` to check the generated kit and release binary. Use
|
||||
`workout doctor` when you only want to see missing external inputs.
|
||||
Use `workout mobile-verify` to check the generated kit and release binary. It
|
||||
fails on a non-HTTPS production origin, missing/inconsistent Android or iOS
|
||||
metadata, or external toolchain/signing blockers that were not written into the
|
||||
manifest and `BLOCKERS.md`. Use `workout doctor` when you only want to see
|
||||
missing external inputs.
|
||||
|
||||
## Production configuration
|
||||
|
||||
|
||||
+59
-2
@@ -261,7 +261,7 @@ fn verify_workout_mobile_release(
|
||||
config: &WorkoutMobileConfig,
|
||||
require_server_binary: bool,
|
||||
) -> Vec<String> {
|
||||
let mut failures = Vec::new();
|
||||
let mut failures = mobile_policy_failures(config);
|
||||
if require_server_binary && !Path::new("target/release/hemx-workout-example").exists() {
|
||||
failures.push(
|
||||
"target/release/hemx-workout-example is missing; run workout-mobile release first"
|
||||
@@ -329,6 +329,23 @@ fn verify_workout_mobile_release(
|
||||
],
|
||||
&mut failures,
|
||||
);
|
||||
|
||||
for blocker in mobile_external_blockers(config) {
|
||||
check_file_contains(&manifest_path, &[&blocker], &mut failures);
|
||||
check_file_contains(&blockers_path, &[&blocker], &mut failures);
|
||||
}
|
||||
|
||||
failures
|
||||
}
|
||||
|
||||
fn mobile_policy_failures(config: &WorkoutMobileConfig) -> Vec<String> {
|
||||
let mut failures = Vec::new();
|
||||
if !config.origin.starts_with("https://") {
|
||||
failures.push(
|
||||
"HEMX_WORKOUT_ORIGIN must be a production HTTPS origin before mobile verification can pass"
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
failures
|
||||
}
|
||||
|
||||
@@ -797,6 +814,25 @@ mod tests {
|
||||
.any(|blocker| blocker.contains("production HTTPS origin")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workout_mobile_verify_fails_closed_on_non_https_origin() {
|
||||
// req: examples/006
|
||||
let config = workout_mobile_config_at(
|
||||
"http://workout.example.com",
|
||||
"target/test-workout-mobile-non-https",
|
||||
);
|
||||
let _ = fs::remove_dir_all(&config.out_dir);
|
||||
write_workout_mobile_release(&config, &mobile_external_blockers(&config))
|
||||
.expect("write release kit");
|
||||
|
||||
let failures = verify_workout_mobile_release(&config, false);
|
||||
|
||||
assert!(failures
|
||||
.iter()
|
||||
.any(|failure| failure.contains("production HTTPS origin")));
|
||||
let _ = fs::remove_dir_all(&config.out_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workout_mobile_verify_accepts_generated_release_kit() {
|
||||
// req: examples/006
|
||||
@@ -805,7 +841,7 @@ mod tests {
|
||||
"target/test-workout-mobile-accepts",
|
||||
);
|
||||
let _ = fs::remove_dir_all(&config.out_dir);
|
||||
write_workout_mobile_release(&config, &["Android signing key not configured".into()])
|
||||
write_workout_mobile_release(&config, &mobile_external_blockers(&config))
|
||||
.expect("write release kit");
|
||||
|
||||
assert!(verify_workout_mobile_release(&config, false).is_empty());
|
||||
@@ -813,6 +849,27 @@ mod tests {
|
||||
let _ = fs::remove_dir_all(&config.out_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workout_mobile_verify_rejects_unacknowledged_external_blockers() {
|
||||
// req: examples/006
|
||||
let config = workout_mobile_config_at(
|
||||
"https://workout.example.com",
|
||||
"target/test-workout-mobile-unacknowledged-blockers",
|
||||
);
|
||||
let _ = fs::remove_dir_all(&config.out_dir);
|
||||
write_workout_mobile_release(&config, &[]).expect("write release kit");
|
||||
|
||||
let failures = verify_workout_mobile_release(&config, false);
|
||||
|
||||
assert!(failures.iter().any(|failure| {
|
||||
failure.contains("release-manifest.json") && failure.contains("Android")
|
||||
}));
|
||||
assert!(failures
|
||||
.iter()
|
||||
.any(|failure| failure.contains("BLOCKERS.md") && failure.contains("Android")));
|
||||
let _ = fs::remove_dir_all(&config.out_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workout_mobile_verify_rejects_missing_release_kit() {
|
||||
// req: examples/006
|
||||
|
||||
Reference in New Issue
Block a user