max / makenotwork
- Co-Authored-By
- Claude Opus 4.6 (1M context) <noreply@anthropic.com>
41 files changed,
+409 insertions,
-420 deletions
| @@ -3445,7 +3445,7 @@ | |||
| 3445 | 3445 | ||
| 3446 | 3446 | [[package]] | |
| 3447 | 3447 | name = "makenotwork" | |
| 3448 | - | version = "0.5.10" | |
| 3448 | + | version = "0.5.11" | |
| 3449 | 3449 | dependencies = [ | |
| 3450 | 3450 | "anyhow", | |
| 3451 | 3451 | "argon2", |
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | [package] | |
| 2 | 2 | name = "makenotwork" | |
| 3 | - | version = "0.5.11" | |
| 3 | + | version = "0.5.12" | |
| 4 | 4 | edition = "2024" | |
| 5 | 5 | license-file = "LICENSE" | |
| 6 | 6 |
| @@ -528,19 +528,18 @@ | |||
| 528 | 528 | let mut chars = s.chars(); | |
| 529 | 529 | while let Some(c) = chars.next() { | |
| 530 | 530 | if c == '\x1b' { | |
| 531 | - | // Consume the '[' and then any parameter/intermediate bytes up to | |
| 532 | - | // the final byte (an ASCII letter). | |
| 533 | - | if let Some(next) = chars.next() { | |
| 534 | - | if next == '[' { | |
| 535 | - | // CSI sequence: skip until we hit a letter (0x40..=0x7E). | |
| 536 | - | for tail in chars.by_ref() { | |
| 537 | - | if tail.is_ascii_alphabetic() { | |
| 538 | - | break; | |
| 539 | - | } | |
| 531 | + | // Consume the next char; if it's '[' we have a CSI sequence | |
| 532 | + | // and we skip parameter/intermediate bytes up to the final byte. | |
| 533 | + | // Otherwise (OSC / other sequences) just drop the two-char escape. | |
| 534 | + | if let Some(next) = chars.next() | |
| 535 | + | && next == '[' | |
| 536 | + | { | |
| 537 | + | // CSI sequence: skip until we hit a letter (0x40..=0x7E). | |
| 538 | + | for tail in chars.by_ref() { | |
| 539 | + | if tail.is_ascii_alphabetic() { | |
| 540 | + | break; | |
| 540 | 541 | } | |
| 541 | 542 | } | |
| 542 | - | // OSC / other sequences starting with ESC but not '[' — | |
| 543 | - | // just drop the two-char escape and continue. | |
| 544 | 543 | } | |
| 545 | 544 | } else { | |
| 546 | 545 | result.push(c); |
| @@ -185,7 +185,7 @@ | |||
| 185 | 185 | ], | |
| 186 | 186 | link_prefix: "/docs".to_string(), | |
| 187 | 187 | unpublished_pattern: Some("unpublished/".to_string()), | |
| 188 | - | examples_path: Some(std::path::Path::new(&docs_path).join("../examples").into()), | |
| 188 | + | examples_path: Some(std::path::Path::new(&docs_path).join("../examples")), | |
| 189 | 189 | }, | |
| 190 | 190 | )); | |
| 191 | 191 |
| @@ -286,18 +286,18 @@ | |||
| 286 | 286 | } | |
| 287 | 287 | routes.push((method, path, status, count)); | |
| 288 | 288 | } | |
| 289 | - | } else if let Some(rest) = line.strip_prefix("http_errors_total{") { | |
| 290 | - | if let Some((labels, value)) = rest.rsplit_once("} ") { | |
| 291 | - | let count: u64 = value.parse().unwrap_or(0); | |
| 292 | - | let kind = extract_label(labels, "kind"); | |
| 293 | - | errors.push((kind, count)); | |
| 294 | - | } | |
| 289 | + | } else if let Some(rest) = line.strip_prefix("http_errors_total{") | |
| 290 | + | && let Some((labels, value)) = rest.rsplit_once("} ") | |
| 291 | + | { | |
| 292 | + | let count: u64 = value.parse().unwrap_or(0); | |
| 293 | + | let kind = extract_label(labels, "kind"); | |
| 294 | + | errors.push((kind, count)); | |
| 295 | 295 | } | |
| 296 | 296 | } | |
| 297 | 297 | ||
| 298 | - | routes.sort_by(|a, b| b.3.cmp(&a.3)); | |
| 298 | + | routes.sort_by_key(|r| std::cmp::Reverse(r.3)); | |
| 299 | 299 | routes.truncate(20); | |
| 300 | - | errors.sort_by(|a, b| b.1.cmp(&a.1)); | |
| 300 | + | errors.sort_by_key(|e| std::cmp::Reverse(e.1)); | |
| 301 | 301 | ||
| 302 | 302 | let total_errors = errors.iter().map(|(_, c)| c).sum(); | |
| 303 | 303 |
| @@ -207,20 +207,20 @@ | |||
| 207 | 207 | } | |
| 208 | 208 | ||
| 209 | 209 | // Create WAM ticket on degradation/error transitions | |
| 210 | - | if snap.status != MonitorStatus::Operational { | |
| 211 | - | if let Some(ref wam) = state.wam { | |
| 212 | - | let priority = match snap.status { | |
| 213 | - | MonitorStatus::Error => "critical", | |
| 214 | - | MonitorStatus::Degraded => "high", | |
| 215 | - | MonitorStatus::Operational => unreachable!(), | |
| 216 | - | }; | |
| 217 | - | let title = format!("Health status: {}", snap.status.as_str()); | |
| 218 | - | let body = format!( | |
| 219 | - | "db: {}\ns3: {}\nsessions: {}\ncheck_ms: {}", | |
| 220 | - | snap.db_ok, snap.s3_ok, snap.sessions_ok, snap.check_duration_ms, | |
| 221 | - | ); | |
| 222 | - | wam.create_ticket(&title, Some(&body), priority, "health-status-change", None).await; | |
| 223 | - | } | |
| 210 | + | if snap.status != MonitorStatus::Operational | |
| 211 | + | && let Some(ref wam) = state.wam | |
| 212 | + | { | |
| 213 | + | let priority = match snap.status { | |
| 214 | + | MonitorStatus::Error => "critical", | |
| 215 | + | MonitorStatus::Degraded => "high", | |
| 216 | + | MonitorStatus::Operational => unreachable!(), | |
| 217 | + | }; | |
| 218 | + | let title = format!("Health status: {}", snap.status.as_str()); | |
| 219 | + | let body = format!( | |
| 220 | + | "db: {}\ns3: {}\nsessions: {}\ncheck_ms: {}", | |
| 221 | + | snap.db_ok, snap.s3_ok, snap.sessions_ok, snap.check_duration_ms, | |
| 222 | + | ); | |
| 223 | + | wam.create_ticket(&title, Some(&body), priority, "health-status-change", None).await; | |
| 224 | 224 | } | |
| 225 | 225 | ||
| 226 | 226 | previous_status = Some(snap.status); | |
| @@ -235,12 +235,12 @@ | |||
| 235 | 235 | tracing::warn!(pool_size, active, idle = pool_idle, "DB pool pressure >80%"); | |
| 236 | 236 | let cooldown_ok = last_pool_alert_at | |
| 237 | 237 | .is_none_or(|t| t.elapsed().as_secs() >= constants::ALERT_COOLDOWN_SECS); | |
| 238 | - | if cooldown_ok { | |
| 239 | - | if let Some(ref wam) = state.wam { | |
| 240 | - | let title = format!("DB pool pressure: {active}/{pool_size} active"); | |
| 241 | - | wam.create_ticket(&title, None, "high", "db-pool-pressure", None).await; | |
| 242 | - | last_pool_alert_at = Some(Instant::now()); | |
| 243 | - | } | |
| 238 | + | if cooldown_ok | |
| 239 | + | && let Some(ref wam) = state.wam | |
| 240 | + | { | |
| 241 | + | let title = format!("DB pool pressure: {active}/{pool_size} active"); | |
| 242 | + | wam.create_ticket(&title, None, "high", "db-pool-pressure", None).await; | |
| 243 | + | last_pool_alert_at = Some(Instant::now()); | |
| 244 | 244 | } | |
| 245 | 245 | } | |
| 246 | 246 | } |
| @@ -509,7 +509,7 @@ | |||
| 509 | 509 | ||
| 510 | 510 | async fn delete_prefix(&self, prefix: &str) -> Result<()> { | |
| 511 | 511 | self.inner.delete_prefix(prefix).await | |
| 512 | - | .map_err(|e| AppError::Storage(e)) | |
| 512 | + | .map_err(AppError::Storage) | |
| 513 | 513 | } | |
| 514 | 514 | ||
| 515 | 515 | async fn check_connectivity(&self) -> std::result::Result<(), String> { |
| @@ -149,7 +149,7 @@ | |||
| 149 | 149 | ) -> Result<Vec<DbDiscoverItemRow>> { | |
| 150 | 150 | let search_term = normalize_search(filters.search); | |
| 151 | 151 | let has_search = search_term.is_some(); | |
| 152 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 152 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 153 | 153 | ||
| 154 | 154 | // Build the base query with optional similarity score. | |
| 155 | 155 | // For short queries (1-2 chars) use a constant match_score since trigram | |
| @@ -274,7 +274,7 @@ | |||
| 274 | 274 | ) -> Result<i64> { | |
| 275 | 275 | let search_term = normalize_search(filters.search); | |
| 276 | 276 | let has_search = search_term.is_some(); | |
| 277 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 277 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 278 | 278 | ||
| 279 | 279 | let mut query = String::from( | |
| 280 | 280 | r#" | |
| @@ -316,7 +316,7 @@ | |||
| 316 | 316 | ) -> Result<Vec<DbDiscoverProjectRow>> { | |
| 317 | 317 | let search_term = normalize_search(search); | |
| 318 | 318 | let has_search = search_term.is_some(); | |
| 319 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 319 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 320 | 320 | ||
| 321 | 321 | let mut query = if has_search && !short_query { | |
| 322 | 322 | String::from( | |
| @@ -437,7 +437,7 @@ | |||
| 437 | 437 | ) -> Result<i64> { | |
| 438 | 438 | let search_term = normalize_search(search); | |
| 439 | 439 | let has_search = search_term.is_some(); | |
| 440 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 440 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 441 | 441 | ||
| 442 | 442 | let mut query = String::from( | |
| 443 | 443 | r#" | |
| @@ -486,7 +486,7 @@ | |||
| 486 | 486 | ) -> Result<Vec<DbItemTypeCount>> { | |
| 487 | 487 | let search_term = normalize_search(search); | |
| 488 | 488 | let has_search = search_term.is_some(); | |
| 489 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 489 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 490 | 490 | ||
| 491 | 491 | let mut query = String::from( | |
| 492 | 492 | r#" | |
| @@ -552,7 +552,7 @@ | |||
| 552 | 552 | ) -> Result<DbPriceRangeCounts> { | |
| 553 | 553 | let search_term = normalize_search(search); | |
| 554 | 554 | let has_search = search_term.is_some(); | |
| 555 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 555 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 556 | 556 | ||
| 557 | 557 | let mut query = String::from( | |
| 558 | 558 | r#" | |
| @@ -627,7 +627,7 @@ | |||
| 627 | 627 | ) -> Result<Vec<DbItemTypeCount>> { | |
| 628 | 628 | let search_term = normalize_search(search); | |
| 629 | 629 | let has_search = search_term.is_some(); | |
| 630 | - | let short_query = search_term.as_deref().map_or(false, is_short_query); | |
| 630 | + | let short_query = search_term.as_deref().is_some_and(is_short_query); | |
| 631 | 631 | ||
| 632 | 632 | let mut query = String::from( | |
| 633 | 633 | r#" |
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | /// | |
| 12 | 12 | /// Auto-generates a URL-safe slug from the title. If the slug collides with | |
| 13 | 13 | /// an existing item in the same project, appends a counter suffix. | |
| 14 | + | #[allow(clippy::too_many_arguments)] | |
| 14 | 15 | #[tracing::instrument(skip_all)] | |
| 15 | 16 | pub async fn create_item( | |
| 16 | 17 | pool: &PgPool, |
| @@ -31,7 +31,7 @@ | |||
| 31 | 31 | ) | |
| 32 | 32 | .bind(&s3_keys) | |
| 33 | 33 | .bind(&buckets) | |
| 34 | - | .bind(&vec![source; keys.len()]) | |
| 34 | + | .bind(vec![source; keys.len()]) | |
| 35 | 35 | .execute(pool) | |
| 36 | 36 | .await?; | |
| 37 | 37 | Ok(()) |
| @@ -1016,6 +1016,7 @@ | |||
| 1016 | 1016 | /// Create a completed free guest transaction. | |
| 1017 | 1017 | /// | |
| 1018 | 1018 | /// Returns the number of rows inserted (0 if already claimed via ON CONFLICT). | |
| 1019 | + | #[allow(clippy::too_many_arguments)] | |
| 1019 | 1020 | #[tracing::instrument(skip_all)] | |
| 1020 | 1021 | pub async fn create_free_guest_transaction( | |
| 1021 | 1022 | pool: &PgPool, |
| @@ -683,6 +683,7 @@ | |||
| 683 | 683 | } | |
| 684 | 684 | ||
| 685 | 685 | /// Update a user's email notification preferences. | |
| 686 | + | #[allow(clippy::too_many_arguments)] | |
| 686 | 687 | #[tracing::instrument(skip_all)] | |
| 687 | 688 | pub async fn update_notification_preferences( | |
| 688 | 689 | pool: &PgPool, |
| @@ -28,12 +28,11 @@ | |||
| 28 | 28 | ||
| 29 | 29 | // Reject arbitrary revparse expressions (e.g. HEAD~99999, @{upstream}). | |
| 30 | 30 | // Only allow simple ref-like names: alphanumeric, dots, hyphens, underscores, slashes. | |
| 31 | - | if refname.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '-' | '_' | '/')) { | |
| 32 | - | if let Ok(obj) = repo.revparse_single(refname) | |
| 33 | - | && let Ok(commit) = obj.peel(ObjectType::Commit) | |
| 34 | - | { | |
| 35 | - | return Ok(commit.id()); | |
| 36 | - | } | |
| 31 | + | if refname.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '-' | '_' | '/')) | |
| 32 | + | && let Ok(obj) = repo.revparse_single(refname) | |
| 33 | + | && let Ok(commit) = obj.peel(ObjectType::Commit) | |
| 34 | + | { | |
| 35 | + | return Ok(commit.id()); | |
| 37 | 36 | } | |
| 38 | 37 | ||
| 39 | 38 | Err(GitError::RefNotFound) |