fix: restore security hardening compatibility and validation

Restore authorized rule reveal, explicit full HTTP capture and retention, video task business fields, and valid payment URLs. Add opt-in credential preservation for trusted recovery, fix frontend type contracts and async races, and eliminate PostgreSQL test fixture resource leaks. Document audit coverage and successful fmt and CI-scoped Clippy checks.
This commit is contained in:
elky
2026-09-07 21:14:27 +08:00
parent a5c3699ae9
commit a90d564931
191 changed files with 6785 additions and 1643 deletions
+61 -4
View File
@@ -4,6 +4,7 @@ use aether_data_contracts::repository::video_tasks::{
};
use serde_json::{json, Map, Value};
use crate::transport::{gemini_response_video_url, gemini_video_metadata};
use crate::types::sanitize_video_task_error_code;
use crate::{
build_video_follow_up_report_context, current_unix_timestamp_secs, gemini_metadata_video_url,
@@ -112,7 +113,16 @@ impl GeminiVideoTaskSeed {
self.error_code = None;
self.error_message = None;
}
self.metadata = json!({});
self.metadata = if error.is_none() {
gemini_video_metadata(
provider_body
.get("response")
.and_then(gemini_response_video_url)
.as_deref(),
)
} else {
json!({})
};
return;
}
@@ -365,8 +375,8 @@ mod tests {
use serde_json::json;
use crate::{
GeminiVideoTaskSeed, LocalVideoTaskPersistence, LocalVideoTaskStatus,
LocalVideoTaskTransport,
GeminiVideoTaskSeed, LocalVideoTaskPersistence, LocalVideoTaskSnapshot,
LocalVideoTaskStatus, LocalVideoTaskTransport,
};
use super::map_gemini_stored_task_to_read_response;
@@ -484,7 +494,54 @@ mod tests {
assert!(record.request_metadata.is_none());
assert_eq!(
record.video_url.as_deref(),
Some("https://files.example/video.mp4?alt=media")
Some("https://files.example/video.mp4?alt=media&token=sensitive")
);
assert_eq!(record.prompt.as_deref(), Some("business prompt"));
let transport = seed.transport.clone();
let mut snapshot = LocalVideoTaskSnapshot::Gemini(seed);
snapshot.apply_provider_body(json!({
"done": true,
"debug": "private-provider-debug",
"response": {
"provider_token": "private-provider-token",
"generateVideoResponse": {
"generatedSamples": [{
"video": {
"uri": "https://files.example/video.mp4?alt=media&token=signed%2Bvalue",
"debug": "private-video-debug"
}
}]
}
}
}).as_object().expect("provider body"));
assert!(!serde_json::to_string(&snapshot)
.expect("serialize snapshot")
.contains("private-"));
snapshot.sanitize_persisted_diagnostics();
let stored = snapshot.to_upsert_record().into_stored();
assert_eq!(stored.status, VideoTaskStatus::Completed);
assert_eq!(stored.prompt.as_deref(), Some("business prompt"));
assert_eq!(
stored.video_url.as_deref(),
Some("https://files.example/video.mp4?alt=media&token=signed%2Bvalue")
);
assert!(stored.request_metadata.is_none());
assert!(stored.original_request_body.is_none());
let mut restored =
LocalVideoTaskSnapshot::from_stored_task_with_transport(&stored, transport)
.expect("stored Gemini task should reconstruct");
restored.sanitize_persisted_diagnostics();
let restored_record = restored.to_upsert_record();
assert_eq!(restored_record.video_url, stored.video_url);
assert_eq!(restored_record.prompt, stored.prompt);
let response = restored.read_response();
assert_eq!(response.body_json["done"], true);
assert!(response
.body_json
.to_string()
.contains("/v1beta/files/aev_"));
assert!(!response.body_json.to_string().contains("signed%2Bvalue"));
}
}
+28 -4
View File
@@ -610,7 +610,7 @@ impl OpenAiVideoTaskSeed {
updated_at_unix_secs: self.completed_at_unix_secs.unwrap_or(now_unix_secs),
error_code: self.error_code.clone(),
error_message: None,
video_url: None,
video_url: self.video_url.clone(),
request_metadata: None,
};
record.sanitize_for_persistence();
@@ -626,8 +626,8 @@ mod tests {
use serde_json::json;
use crate::{
LocalVideoTaskPersistence, LocalVideoTaskStatus, LocalVideoTaskTransport,
OpenAiVideoTaskSeed,
LocalVideoTaskContentAction, LocalVideoTaskPersistence, LocalVideoTaskSnapshot,
LocalVideoTaskStatus, LocalVideoTaskTransport, OpenAiVideoTaskSeed,
};
use super::map_openai_stored_task_to_read_response;
@@ -751,9 +751,33 @@ mod tests {
assert!(record.original_request_body.is_none());
assert!(record.progress_message.is_none());
assert!(record.error_message.is_none());
assert!(record.video_url.is_none());
assert_eq!(record.video_url, seed.video_url);
assert_eq!(record.prompt, seed.prompt);
assert!(record.request_metadata.is_none());
assert_eq!(record.duration_seconds, Some(4));
assert_eq!(record.size.as_deref(), Some("1280x720"));
let mut stored = record.into_stored();
stored.status = VideoTaskStatus::Completed;
let snapshot =
LocalVideoTaskSnapshot::from_stored_task_with_transport(&stored, seed.transport)
.expect("stored task should reconstruct with current transport");
let LocalVideoTaskSnapshot::OpenAi(restored) = snapshot else {
panic!("expected OpenAI snapshot");
};
assert_eq!(restored.prompt, stored.prompt);
assert_eq!(restored.to_upsert_record().video_url, stored.video_url);
let Some(LocalVideoTaskContentAction::StreamPlan(plan)) =
restored.build_content_stream_action(None, "trace-download")
else {
panic!("completed stored task should stream content");
};
assert_eq!(Some(plan.url.as_str()), stored.video_url.as_deref());
assert!(plan.headers.is_empty());
let response = map_openai_stored_task_to_read_response(stored.clone());
assert_eq!(
response.body_json["video_url"].as_str(),
stored.video_url.as_deref()
);
}
}
@@ -1,6 +1,7 @@
use aether_data_contracts::repository::video_tasks::{StoredVideoTask, UpsertVideoTask};
use serde_json::{json, Map, Value};
use crate::transport::{gemini_metadata_video_url, gemini_video_metadata};
use crate::types::sanitize_video_task_error_code;
use crate::{
local_status_from_stored, non_empty_owned, request_body_string, GeminiVideoTaskSeed,
@@ -104,7 +105,7 @@ impl LocalVideoTaskSnapshot {
progress_percent: task.progress_percent,
error_code: task.error_code.clone(),
error_message: task.error_message.clone(),
metadata: Value::Object(Map::new()),
metadata: gemini_video_metadata(task.video_url.as_deref()),
persistence,
transport,
}))
@@ -128,7 +129,8 @@ impl LocalVideoTaskSnapshot {
let previous_error_code = seed.error_code.clone();
let error_code =
sanitized_error_code_for_status(seed.status, seed.error_code.take());
let safe_metadata = Value::Object(Map::new());
let safe_metadata =
gemini_video_metadata(gemini_metadata_video_url(&seed.metadata).as_deref());
let changed = previous_error_code != error_code
|| seed.error_message.is_some()
|| seed.metadata != safe_metadata;
@@ -450,6 +450,49 @@ mod tests {
})
}
#[test]
fn completed_gemini_download_survives_encrypted_file_reload() {
let path = temp_store_path("completed-download");
let video_url = "https://cdn.example.test/video.mp4?signature=a%2Fb%2Bc%3D";
let mut snapshot = sensitive_gemini_snapshot();
snapshot.apply_provider_body(
json!({
"done": true,
"debug": "private-debug",
"response": {
"generateVideoResponse": {
"generatedSamples": [{"video": {"uri": video_url}}]
}
}
})
.as_object()
.expect("provider body"),
);
let store = FileVideoTaskStore::new(&path, DEVELOPMENT_ENCRYPTION_KEY).expect("store");
store.insert(snapshot);
drop(store);
let bytes = std::fs::read_to_string(&path).expect("encrypted store file");
assert!(bytes.starts_with(ENCRYPTED_VIDEO_TASK_STORE_PREFIX));
assert!(!bytes.contains(video_url));
assert!(!bytes.contains("transport-key-required-for-resume"));
let restored =
FileVideoTaskStore::new(&path, DEVELOPMENT_ENCRYPTION_KEY).expect("restored store");
let task = restored
.clone_gemini("task-sensitive")
.expect("completed Gemini task");
let record = task.to_upsert_record();
assert_eq!(
record.status,
aether_data_contracts::repository::video_tasks::VideoTaskStatus::Completed
);
assert_eq!(record.video_url.as_deref(), Some(video_url));
assert_eq!(record.prompt.as_deref(), Some("create a video"));
assert!(!task.metadata.to_string().contains("private-debug"));
assert!(record.request_metadata.is_none());
drop(restored);
cleanup_store_path(&path);
}
#[test]
fn loading_encrypted_store_rewrites_legacy_provider_diagnostics() {
let path = temp_store_path("diagnostic-migration");
@@ -1,4 +1,4 @@
use serde_json::Value;
use serde_json::{json, Value};
use crate::LocalVideoTaskStatus;
@@ -20,9 +20,12 @@ pub fn parse_video_content_variant(query_string: Option<&str>) -> Option<&'stati
}
pub fn gemini_metadata_video_url(metadata: &Value) -> Option<String> {
metadata
.get("response")
.and_then(|value| value.get("generateVideoResponse"))
metadata.get("response").and_then(gemini_response_video_url)
}
pub(crate) fn gemini_response_video_url(response: &Value) -> Option<String> {
response
.get("generateVideoResponse")
.and_then(|value| value.get("generatedSamples"))
.and_then(Value::as_array)
.and_then(|value| value.first())
@@ -32,6 +35,19 @@ pub fn gemini_metadata_video_url(metadata: &Value) -> Option<String> {
.map(str::to_string)
}
pub(crate) fn gemini_video_metadata(video_url: Option<&str>) -> Value {
match video_url {
Some(video_url) => json!({
"response": {
"generateVideoResponse": {
"generatedSamples": [{"video": {"uri": video_url}}]
}
}
}),
None => json!({}),
}
}
pub fn map_openai_task_status(status: LocalVideoTaskStatus) -> &'static str {
match status {
LocalVideoTaskStatus::Submitted | LocalVideoTaskStatus::Queued => "queued",
@@ -98,10 +98,15 @@ impl LocalVideoTaskPersistence {
api_key_name: task.api_key_name.clone(),
client_api_format,
provider_api_format,
original_request_body: task
.original_request_body
.clone()
.unwrap_or_else(|| Value::Object(Map::new())),
original_request_body: task.original_request_body.clone().unwrap_or_else(|| {
serde_json::json!({
"prompt": task.prompt,
"seconds": task.duration_seconds,
"resolution": task.resolution,
"aspect_ratio": task.aspect_ratio,
"size": task.size,
})
}),
format_converted: task.format_converted,
})
}