From 5bd47bbcf1aa4e058e977d0ed65239e3b6a47f07 Mon Sep 17 00:00:00 2001 From: YOMXXX Date: Fri, 29 May 2026 10:12:11 +0800 Subject: [PATCH] ci: extend Windows secrets ACL timeout (#2654) Co-authored-by: Steven Enamakel --- src/openhuman/vault/mod.rs | 2 +- src/openhuman/vault/ops.rs | 18 +++++++++++++++++- src/openhuman/vault/tests.rs | 36 ++++++++++++++++++++++++++++++++++++ tests/vault_sync_e2e.rs | 14 ++++++++++++-- 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/openhuman/vault/mod.rs b/src/openhuman/vault/mod.rs index b0a3462ea..d1bb6b44d 100644 --- a/src/openhuman/vault/mod.rs +++ b/src/openhuman/vault/mod.rs @@ -2,7 +2,7 @@ //! //! A `Vault` points at a local directory; on `vault.sync` we walk it, route //! files to extractors by extension, and feed them into the memory pipeline -//! under namespace `vault:`. Per-file dedup uses (path, mtime, content +//! under a vault-derived namespace. Per-file dedup uses (path, mtime, content //! hash) so re-syncs only touch what changed. pub mod ops; diff --git a/src/openhuman/vault/ops.rs b/src/openhuman/vault/ops.rs index a3766932a..3975ebf0e 100644 --- a/src/openhuman/vault/ops.rs +++ b/src/openhuman/vault/ops.rs @@ -2,6 +2,7 @@ use chrono::Utc; use futures::FutureExt; +use sha2::{Digest, Sha256}; use uuid::Uuid; use crate::openhuman::config::Config; @@ -15,6 +16,21 @@ use super::store; use super::sync; use super::types::{Vault, VaultFile, VaultSyncState, VaultSyncStatus}; +/// Derive a stable memory namespace for a vault without embedding the raw UUID. +/// +/// Memory writes reject namespace/key values that resemble PII. Raw UUID hex can +/// occasionally match strict alphanumeric identifier patterns, so vault +/// namespaces use an alphabet-only digest suffix instead. +pub(crate) fn vault_namespace_for_id(id: &str) -> String { + let digest = Sha256::digest(id.as_bytes()); + let suffix: String = digest + .iter() + .take(24) + .map(|byte| char::from(b'a' + (byte % 26))) + .collect(); + format!("vault-{suffix}") +} + /// Create a new vault pointing at a local folder. pub async fn vault_create( config: &Config, @@ -46,7 +62,7 @@ pub async fn vault_create( include_globs.len(), exclude_globs.len(), ); - let namespace = format!("vault:{id}"); + let namespace = vault_namespace_for_id(&id); let vault = Vault { id: id.clone(), name: trimmed_name.to_string(), diff --git a/src/openhuman/vault/tests.rs b/src/openhuman/vault/tests.rs index cb2aea3b9..972ddc86d 100644 --- a/src/openhuman/vault/tests.rs +++ b/src/openhuman/vault/tests.rs @@ -344,6 +344,42 @@ async fn vault_create_returns_current_host_os() { assert_eq!(outcome.value.host_os.as_deref(), Some(std::env::consts::OS)); } +#[tokio::test] +async fn vault_create_uses_pii_safe_memory_namespace() { + let tmp = TempDir::new().unwrap(); + let config = make_config(&tmp); + + let outcome = ops::vault_create( + &config, + "Test", + tmp.path().to_str().unwrap(), + vec![], + vec![], + ) + .await + .unwrap(); + + let namespace = &outcome.value.namespace; + assert!(namespace.starts_with("vault-")); + assert!(!namespace.contains(&outcome.value.id)); + assert!(!crate::openhuman::memory_store::safety::has_likely_secret( + namespace + )); + assert!(!crate::openhuman::memory_store::safety::pii::has_likely_pii(namespace)); +} + +#[test] +fn vault_namespace_derivation_does_not_embed_pii_like_ids() { + let namespace = ops::vault_namespace_for_id("VECJ880326XK4"); + + assert!(namespace.starts_with("vault-")); + assert!(!namespace.contains("VECJ880326XK4")); + assert!(!crate::openhuman::memory_store::safety::has_likely_secret( + &namespace + )); + assert!(!crate::openhuman::memory_store::safety::pii::has_likely_pii(&namespace)); +} + #[tokio::test] async fn vault_sync_status_returns_idle_for_unknown_vault() { let outcome = ops::vault_sync_status("__ops_status_unknown__") diff --git a/tests/vault_sync_e2e.rs b/tests/vault_sync_e2e.rs index 45d00e0dc..a72c5c203 100644 --- a/tests/vault_sync_e2e.rs +++ b/tests/vault_sync_e2e.rs @@ -99,7 +99,12 @@ async fn vault_sync_roundtrip_updates_memory_and_ledger() { .await .expect("vault_sync first"); let first = wait_for_sync(&vault.id).await; - assert_eq!(first.status, VaultSyncStatus::Completed); + assert_eq!( + first.status, + VaultSyncStatus::Completed, + "first sync failed with errors: {:?}", + first.errors + ); assert_eq!(first.ingested, 2); assert_eq!(first.removed, 0); assert_eq!(first.failed, 0); @@ -168,7 +173,12 @@ async fn vault_sync_roundtrip_updates_memory_and_ledger() { .await .expect("vault_sync second"); let second = wait_for_sync(&vault.id).await; - assert_eq!(second.status, VaultSyncStatus::Completed); + assert_eq!( + second.status, + VaultSyncStatus::Completed, + "second sync failed with errors: {:?}", + second.errors + ); assert_eq!(second.ingested, 2); assert_eq!(second.removed, 1); assert_eq!(second.failed, 0);