chore(hardening): tighten security and footprint defaults

This commit is contained in:
2026-04-24 19:03:57 +01:00
parent 55b34d8ffc
commit b333c6229e
36 changed files with 8702 additions and 254 deletions

View File

@@ -9,6 +9,7 @@ use tauri::Emitter;
use crate::commands::build_initial_prompt;
use crate::commands::models::{default_model_id_for_engine, ensure_model_loaded};
use crate::commands::security::ensure_main_window;
use crate::AppState;
use kon_ai_formatting::{post_process_segments, FormatMode, PostProcessOptions};
use kon_core::constants::WHISPER_SAMPLE_RATE;
@@ -20,6 +21,7 @@ const PARAKEET_CHUNK_OVERLAP_SECS: usize = 1;
const FILE_CHUNK_THRESHOLD_SECS: usize = 8 * 60;
const FILE_CHUNK_SECS: usize = 3 * 60;
const FILE_CHUNK_OVERLAP_SECS: usize = 2;
const MAX_FILE_TRANSCRIPTION_SECS: f64 = 2.0 * 60.0 * 60.0;
struct ChunkingStrategy {
chunk_samples: usize,
@@ -138,6 +140,7 @@ fn transcribe_samples_sync(
/// Transcribe raw PCM f32 samples (Whisper). Emits "transcription-result" event.
#[tauri::command]
pub async fn transcribe_pcm(
window: tauri::WebviewWindow,
state: tauri::State<'_, AppState>,
app: tauri::AppHandle,
samples: Vec<f32>,
@@ -150,6 +153,7 @@ pub async fn transcribe_pcm(
format_mode: String,
profile_id: Option<String>,
) -> Result<(), String> {
ensure_main_window(&window)?;
let resolved_profile_id =
profile_id.unwrap_or_else(|| kon_storage::DEFAULT_PROFILE_ID.to_string());
@@ -230,6 +234,7 @@ fn join_segment_text(segments: &[Segment]) -> String {
/// Transcribe an audio file by path. Decodes, resamples to 16kHz, runs Whisper.
#[tauri::command]
pub async fn transcribe_file(
window: tauri::WebviewWindow,
state: tauri::State<'_, AppState>,
path: String,
engine: Option<String>,
@@ -242,6 +247,7 @@ pub async fn transcribe_file(
format_mode: String,
profile_id: Option<String>,
) -> Result<serde_json::Value, String> {
ensure_main_window(&window)?;
let resolved_profile_id =
profile_id.unwrap_or_else(|| kon_storage::DEFAULT_PROFILE_ID.to_string());
@@ -275,9 +281,24 @@ pub async fn transcribe_file(
),
};
let engine_name_for_worker = engine_name.clone();
let path_for_probe = Path::new(&path);
if let Some(duration_secs) =
kon_audio::probe_audio_duration_secs(path_for_probe).map_err(|e| e.to_string())?
{
if duration_secs > MAX_FILE_TRANSCRIPTION_SECS {
return Err(format!(
"File is {:.1} hours long. Kon imports up to 2 hours at a time.",
duration_secs / 3600.0
));
}
}
let timed = tokio::task::spawn_blocking(move || {
let audio = kon_audio::decode_audio_file(Path::new(&path)).map_err(|e| e.to_string())?;
let audio = kon_audio::decode_audio_file_limited(
Path::new(&path),
Some(MAX_FILE_TRANSCRIPTION_SECS),
)
.map_err(|e| e.to_string())?;
let resampled = kon_audio::resample_to_16khz(&audio).map_err(|e| e.to_string())?;
transcribe_samples_sync(
engine,
@@ -319,6 +340,7 @@ pub async fn transcribe_file(
/// Transcribe raw PCM f32 samples (Parakeet). Emits "transcription-result" event.
#[tauri::command]
pub async fn transcribe_pcm_parakeet(
window: tauri::WebviewWindow,
state: tauri::State<'_, AppState>,
app: tauri::AppHandle,
samples: Vec<f32>,
@@ -329,6 +351,7 @@ pub async fn transcribe_pcm_parakeet(
format_mode: String,
profile_id: Option<String>,
) -> Result<(), String> {
ensure_main_window(&window)?;
let resolved_profile_id =
profile_id.unwrap_or_else(|| kon_storage::DEFAULT_PROFILE_ID.to_string());