// SPDX-License-Identifier: AGPL-3.0-or-later // Clean-room stage-one implementation. Contract evidence is recorded in // audit/pncc-migration-provenance.json; no donor source was copied. use fs2::FileExt; use ring::digest::{digest, SHA256}; use serde::{Deserialize, Serialize}; use std::fs::{self, OpenOptions}; use std::io::Write; use std::path::{Component, Path, PathBuf}; use std::process::{Command, Output}; use uuid::Uuid; const REMOTE_MOUNT_SCHEMA: &str = "hololake.pncc-stage-one-remote-mount/v1"; const CURSOR_SCHEMA: &str = "hololake.pncc-stage-one-remote-cursor/v1"; #[cfg(test)] const DEFAULT_BRANCH: &str = "main"; const DEFAULT_CACHE_LIMIT_BYTES: u64 = 128 * 1024 * 1024; const MIN_CACHE_LIMIT_BYTES: u64 = 1024 * 1024; const MAX_CACHE_LIMIT_BYTES: u64 = 4 * 1024 * 1024 * 1024; const MAX_TEXT_OBJECT_BYTES: usize = 2 * 1024 * 1024; const MAX_CONTINUITY_DEPTH: usize = 4096; #[cfg(test)] #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct RegisterPnccRemoteMountInput { pub mount_id: String, pub remote_url: String, pub branch: Option, } #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct ReadMountedPnccRemoteObjectInput { pub mount_id: String, pub relative_path: String, pub expected_head: Option, pub max_cache_bytes: Option, } #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct PnccRemoteObjectReceipt { pub schema: &'static str, pub mount_id: String, pub remote_identity_hash: String, pub remote_head: String, pub previous_verified_head: Option, pub cursor_advanced: bool, pub continuity_verified: bool, pub fetched_incremental_objects: bool, pub cache_rehydrated: bool, pub relative_path: String, pub git_object_id: String, pub content: String, pub content_sha256: String, pub cache_bytes: u64, pub cache_limit_bytes: u64, pub cache_state: &'static str, pub worktree_created: bool, pub full_history_requested: bool, pub model_inference_started: bool, pub reality_execution_allowed: bool, pub receipt_id: String, } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct RemoteMountRecord { schema: String, mount_id: String, remote_url: String, remote_identity_hash: String, branch: String, } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct CursorRecord { schema: String, remote_identity_hash: String, branch: String, verified_head: String, previous_verified_head: Option, generation: u64, } #[cfg(test)] fn register_remote_mount_at( root: &Path, input: RegisterPnccRemoteMountInput, allow_file_remote: bool, ) -> Result<(), String> { validate_machine_id(&input.mount_id, "REMOTE_MOUNT_ID")?; validate_remote_url(&input.remote_url, allow_file_remote)?; let branch = input.branch.unwrap_or_else(|| DEFAULT_BRANCH.into()); validate_branch(&branch)?; let identity = remote_identity(&input.remote_url, &branch); let record = RemoteMountRecord { schema: REMOTE_MOUNT_SCHEMA.into(), mount_id: input.mount_id.clone(), remote_url: input.remote_url, remote_identity_hash: identity.clone(), branch: branch.clone(), }; let mounts = child_root(root, "mounts")?; write_json_atomic(&mounts.join(format!("{}.json", input.mount_id)), &record)?; Ok(()) } pub(crate) fn read_mounted_remote_object_at( root: &Path, input: ReadMountedPnccRemoteObjectInput, ) -> Result { read_mounted_remote_object_with_file_policy(root, input, false) } fn read_mounted_remote_object_with_file_policy( root: &Path, input: ReadMountedPnccRemoteObjectInput, allow_file_remote: bool, ) -> Result { validate_machine_id(&input.mount_id, "REMOTE_MOUNT_ID")?; validate_relative_path(&input.relative_path)?; let maximum = input.max_cache_bytes.unwrap_or(DEFAULT_CACHE_LIMIT_BYTES); if !(MIN_CACHE_LIMIT_BYTES..=MAX_CACHE_LIMIT_BYTES).contains(&maximum) { return Err("PNCC_REMOTE_CACHE_LIMIT_INVALID".into()); } let expected_head = input .expected_head .map(|head| validate_head(&head)) .transpose()?; let mounts = child_root(root, "mounts")?; let record: RemoteMountRecord = read_json(&mounts.join(format!("{}.json", input.mount_id)))?; if record.schema != REMOTE_MOUNT_SCHEMA || record.mount_id != input.mount_id { return Err("PNCC_REMOTE_MOUNT_RECORD_INVALID".into()); } validate_remote_url(&record.remote_url, allow_file_remote)?; validate_branch(&record.branch)?; let identity = remote_identity(&record.remote_url, &record.branch); if identity != record.remote_identity_hash { return Err("PNCC_REMOTE_MOUNT_IDENTITY_MISMATCH".into()); } let locks = child_root(root, "locks")?; let _lock = lock_file(&locks.join(format!("{identity}.lock")))?; let remote_head = read_remote_head(&record.remote_url, &record.branch)?; if expected_head .as_deref() .is_some_and(|head| head != remote_head) { return Err("PNCC_REMOTE_HEAD_MISMATCH".into()); } let object_root = child_root(root, "objects")?; let cursor_root = child_root(root, "continuity")?; let cache_path = object_root.join(format!("{identity}.git")); let cursor_path = cursor_root.join(format!("{identity}.json")); let cursor = read_cursor(&cursor_path, &identity, &record.branch)?; let previous = cursor.as_ref().map(|value| value.verified_head.clone()); ensure_bare_cache(&cache_path, &record.remote_url)?; let remote_ref = format!("refs/remotes/origin/{}", record.branch); let cached = optional_ref(&cache_path, &remote_ref)?; match (previous.as_deref(), cached.as_deref()) { (None, Some(_)) => return Err("PNCC_REMOTE_CACHE_WITHOUT_CONTINUITY_CURSOR".into()), (Some(expected), Some(observed)) if expected != observed => { return Err("PNCC_REMOTE_CACHE_CURSOR_MISMATCH".into()) } _ => {} } let fetched_incremental_objects = cached.as_deref() != Some(remote_head.as_str()); let cache_rehydrated = cached.is_none() && previous.is_some(); if fetched_incremental_objects { if let Err(error) = fetch_continuity( &cache_path, &record.branch, previous.as_deref(), cached.is_some(), ) { if cache_path.exists() { remove_exact_cache(&object_root, &cache_path)?; } return Err(error); } } let fetched_head = required_ref(&cache_path, &remote_ref)?; if fetched_head != remote_head { return Err("PNCC_REMOTE_FETCH_HEAD_MISMATCH".into()); } if let Some(previous_head) = previous.as_deref() { if previous_head != remote_head && !is_ancestor(&cache_path, previous_head, &remote_head)? { remove_exact_cache(&object_root, &cache_path)?; return Err("PNCC_REMOTE_HISTORY_REWRITE_REJECTED".into()); } } let (object_id, content_bytes) = read_regular_blob( &cache_path, &remote_head, &input.relative_path, MAX_TEXT_OBJECT_BYTES, )?; let content = String::from_utf8(content_bytes).map_err(|_| "PNCC_REMOTE_OBJECT_NOT_UTF8".to_string())?; let content_sha256 = sha256_hex(content.as_bytes()); let cursor_advanced = previous.as_deref() != Some(remote_head.as_str()); let next = CursorRecord { schema: CURSOR_SCHEMA.into(), remote_identity_hash: identity.clone(), branch: record.branch, verified_head: remote_head.clone(), previous_verified_head: previous.clone(), generation: cursor .as_ref() .map(|value| value.generation.saturating_add(u64::from(cursor_advanced))) .unwrap_or(1), }; write_json_atomic(&cursor_path, &next)?; let observed_cache_bytes = directory_size(&cache_path)?; let (cache_bytes, cache_state) = if observed_cache_bytes > maximum { remove_exact_cache(&object_root, &cache_path)?; (0, "EVICTED_AFTER_BOUNDED_READ") } else { (observed_cache_bytes, "BOUNDED_PARTIAL_OBJECT_CACHE") }; let receipt_id = sha256_hex( format!( "{}\n{}\n{}\n{}\n{}", input.mount_id, remote_head, input.relative_path, object_id, content_sha256 ) .as_bytes(), ); Ok(PnccRemoteObjectReceipt { schema: "hololake.pncc-stage-one-remote-object-read/v1", mount_id: input.mount_id, remote_identity_hash: identity, remote_head, previous_verified_head: previous, cursor_advanced, continuity_verified: true, fetched_incremental_objects, cache_rehydrated, relative_path: input.relative_path, git_object_id: object_id, content, content_sha256, cache_bytes, cache_limit_bytes: maximum, cache_state, worktree_created: false, full_history_requested: false, model_inference_started: false, reality_execution_allowed: false, receipt_id, }) } fn validate_remote_url(remote_url: &str, allow_file_remote: bool) -> Result<(), String> { if remote_url.len() > 4096 || remote_url.contains(['\n', '\r', '\0']) { return Err("PNCC_REMOTE_URL_UNSUPPORTED".into()); } if allow_file_remote && remote_url.starts_with("file://") { return Ok(()); } let url = tauri::Url::parse(remote_url).map_err(|_| "PNCC_REMOTE_URL_UNSUPPORTED".to_string())?; if url.scheme() != "https" || url.host_str().is_none() || !url.username().is_empty() || url.password().is_some() || url.query().is_some() || url.fragment().is_some() { return Err("PNCC_REMOTE_URL_MUST_BE_CREDENTIAL_FREE_HTTPS".into()); } Ok(()) } fn validate_branch(branch: &str) -> Result<(), String> { if branch.is_empty() || branch.len() > 200 || branch.starts_with('-') { return Err("PNCC_REMOTE_BRANCH_INVALID".into()); } let output = trusted_git() .args(["check-ref-format", "--branch", branch]) .output() .map_err(|error| format!("PNCC_GIT_UNAVAILABLE: {error}"))?; if output.status.success() { Ok(()) } else { Err("PNCC_REMOTE_BRANCH_INVALID".into()) } } fn validate_relative_path(relative: &str) -> Result<(), String> { let path = Path::new(relative); if relative.is_empty() || relative.len() > 1024 || path.is_absolute() || path.components().any(|component| { matches!( component, Component::ParentDir | Component::RootDir | Component::Prefix(_) ) }) || path .components() .any(|component| component.as_os_str() == ".git") { return Err("PNCC_REMOTE_PATH_INVALID".into()); } Ok(()) } fn validate_head(head: &str) -> Result { if head.len() == 40 && head .bytes() .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte)) { Ok(head.into()) } else { Err("PNCC_REMOTE_HEAD_INVALID".into()) } } fn validate_machine_id(value: &str, label: &str) -> Result<(), String> { if value.is_empty() || value.len() > 128 || !value .bytes() .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.')) { return Err(format!("PNCC_{label}_INVALID")); } Ok(()) } fn remote_identity(remote_url: &str, branch: &str) -> String { sha256_hex(format!("{remote_url}\n{branch}").as_bytes()) } fn read_remote_head(remote_url: &str, branch: &str) -> Result { let full_ref = format!("refs/heads/{branch}"); let output = trusted_git() .env("GIT_TRACE_PACKET", "1") .args([ "-c", "protocol.version=2", "ls-remote", "--exit-code", "--heads", remote_url, &full_ref, ]) .output() .map_err(|error| format!("PNCC_REMOTE_HEAD_READ_FAILED: {error}"))?; let output = require_success(output, "PNCC_REMOTE_HEAD_READ")?; let trace = String::from_utf8_lossy(&output.stderr); if !trace.lines().any(|line| { line.split_whitespace().any(|word| word == "filter") && line .split_whitespace() .any(|word| word.starts_with("fetch=")) }) { return Err("PNCC_REMOTE_PARTIAL_OBJECT_PROTOCOL_REQUIRED".into()); } let response = String::from_utf8(output.stdout) .map_err(|_| "PNCC_REMOTE_HEAD_RESPONSE_NOT_UTF8".to_string())?; let mut lines = response.lines(); let first = lines .next() .ok_or_else(|| "PNCC_REMOTE_BRANCH_NOT_FOUND".to_string())?; if lines.next().is_some() { return Err("PNCC_REMOTE_HEAD_AMBIGUOUS".into()); } let mut fields = first.split_whitespace(); let head = fields.next().unwrap_or_default().to_ascii_lowercase(); if fields.next() != Some(full_ref.as_str()) || fields.next().is_some() { return Err("PNCC_REMOTE_HEAD_RESPONSE_INVALID".into()); } validate_head(&head) } fn ensure_bare_cache(cache: &Path, remote_url: &str) -> Result<(), String> { if cache.exists() { if git_text( cache, &["rev-parse", "--is-bare-repository"], "PNCC_CACHE_PROBE", )? .trim() != "true" { return Err("PNCC_REMOTE_CACHE_NOT_BARE".into()); } if git_text( cache, &["remote", "get-url", "origin"], "PNCC_CACHE_ORIGIN_READ", )? .trim() != remote_url { return Err("PNCC_REMOTE_CACHE_ORIGIN_MISMATCH".into()); } return Ok(()); } fs::create_dir(cache).map_err(|error| format!("PNCC_REMOTE_CACHE_CREATE_FAILED: {error}"))?; git_status( trusted_git().args(["init", "--bare", &cache.to_string_lossy()]), "PNCC_REMOTE_CACHE_INIT", )?; git_status( git_at(cache).args(["remote", "add", "origin", remote_url]), "PNCC_REMOTE_CACHE_ORIGIN_ADD", )?; git_status( git_at(cache).args(["config", "remote.origin.promisor", "true"]), "PNCC_REMOTE_CACHE_PROMISOR_CONFIG", )?; git_status( git_at(cache).args(["config", "remote.origin.partialclonefilter", "blob:none"]), "PNCC_REMOTE_CACHE_FILTER_CONFIG", ) } fn fetch_continuity( cache: &Path, branch: &str, previous: Option<&str>, cache_has_previous: bool, ) -> Result<(), String> { let refspec = format!("+refs/heads/{branch}:refs/remotes/origin/{branch}"); if previous.is_none() || !cache_has_previous { fetch_depth(cache, &refspec, 1)?; } else { fetch_incremental(cache, &refspec)?; } let Some(previous) = previous else { return Ok(()); }; let current = required_ref(cache, &format!("refs/remotes/origin/{branch}"))?; if previous == current || is_ancestor(cache, previous, ¤t)? { return Ok(()); } if cache_has_previous { return Err("PNCC_REMOTE_HISTORY_REWRITE_REJECTED".into()); } let mut depth = 2; while depth <= MAX_CONTINUITY_DEPTH { fetch_depth(cache, &refspec, depth)?; if is_ancestor(cache, previous, ¤t)? { return Ok(()); } depth = depth.saturating_mul(2); } Err("PNCC_REMOTE_CONTINUITY_WINDOW_EXCEEDED".into()) } fn fetch_depth(cache: &Path, refspec: &str, depth: usize) -> Result<(), String> { let depth = format!("--depth={depth}"); let output = git_at(cache) .args([ "fetch", "--no-tags", &depth, "--filter=blob:none", "origin", refspec, ]) .output() .map_err(|error| format!("PNCC_REMOTE_INCREMENTAL_FETCH_FAILED: {error}"))?; require_partial_fetch(output) } fn fetch_incremental(cache: &Path, refspec: &str) -> Result<(), String> { let output = git_at(cache) .args([ "fetch", "--no-tags", "--update-shallow", "--filter=blob:none", "origin", refspec, ]) .output() .map_err(|error| format!("PNCC_REMOTE_INCREMENTAL_FETCH_FAILED: {error}"))?; require_partial_fetch(output) } fn require_partial_fetch(output: Output) -> Result<(), String> { let output = require_success(output, "PNCC_REMOTE_INCREMENTAL_FETCH")?; let diagnostic = String::from_utf8_lossy(&output.stderr); if diagnostic.contains("filtering not recognized") || diagnostic.contains("filter-spec") { Err("PNCC_REMOTE_PARTIAL_OBJECT_PROTOCOL_REQUIRED".into()) } else { Ok(()) } } fn read_regular_blob( cache: &Path, head: &str, relative: &str, maximum: usize, ) -> Result<(String, Vec), String> { validate_head(head)?; validate_relative_path(relative)?; let tree = git_text( cache, &["ls-tree", head, "--", relative], "PNCC_REMOTE_OBJECT_MODE_READ", )?; let mut fields = tree.split_whitespace(); let mode = fields.next().unwrap_or_default(); let kind = fields.next().unwrap_or_default(); let object_id = fields.next().unwrap_or_default().to_ascii_lowercase(); if !matches!(mode, "100644" | "100755") || kind != "blob" { return Err("PNCC_REMOTE_OBJECT_NOT_REGULAR_FILE".into()); } validate_head(&object_id)?; let bytes = git_bytes( cache, &["cat-file", "blob", &object_id], "PNCC_REMOTE_OBJECT_READ", )?; if bytes.is_empty() || bytes.len() > maximum { return Err("PNCC_REMOTE_OBJECT_SIZE_INVALID".into()); } Ok((object_id, bytes)) } fn is_ancestor(cache: &Path, ancestor: &str, descendant: &str) -> Result { validate_head(ancestor)?; validate_head(descendant)?; let output = git_at(cache) .args(["merge-base", "--is-ancestor", ancestor, descendant]) .output() .map_err(|error| format!("PNCC_REMOTE_CONTINUITY_CHECK_FAILED: {error}"))?; match output.status.code() { Some(0) => Ok(true), Some(1) => Ok(false), _ => Err(format!( "PNCC_REMOTE_CONTINUITY_CHECK_FAILED: {}", String::from_utf8_lossy(&output.stderr).trim() )), } } fn optional_ref(cache: &Path, reference: &str) -> Result, String> { let output = git_at(cache) .args(["rev-parse", "--verify", reference]) .output() .map_err(|error| format!("PNCC_REMOTE_CURSOR_READ_FAILED: {error}"))?; if !output.status.success() { return Ok(None); } let value = String::from_utf8(output.stdout) .map_err(|_| "PNCC_REMOTE_CURSOR_NOT_UTF8".to_string())? .trim() .to_ascii_lowercase(); validate_head(&value).map(Some) } fn required_ref(cache: &Path, reference: &str) -> Result { optional_ref(cache, reference)?.ok_or_else(|| "PNCC_REMOTE_FETCH_HEAD_MISSING".into()) } fn read_cursor(path: &Path, identity: &str, branch: &str) -> Result, String> { if !path.exists() { return Ok(None); } let record: CursorRecord = read_json(path)?; if record.schema != CURSOR_SCHEMA || record.remote_identity_hash != identity || record.branch != branch || record.generation == 0 { return Err("PNCC_REMOTE_CURSOR_RECORD_INVALID".into()); } validate_head(&record.verified_head)?; if let Some(previous) = record.previous_verified_head.as_deref() { validate_head(previous)?; } Ok(Some(record)) } fn child_root(root: &Path, child: &str) -> Result { let canonical_root = root .canonicalize() .map_err(|error| format!("PNCC_REMOTE_STORAGE_UNAVAILABLE: {error}"))?; let path = root.join(child); fs::create_dir_all(&path) .map_err(|error| format!("PNCC_REMOTE_STORAGE_UNAVAILABLE: {error}"))?; let canonical = path .canonicalize() .map_err(|error| format!("PNCC_REMOTE_STORAGE_UNAVAILABLE: {error}"))?; if canonical.parent() != Some(canonical_root.as_path()) || !canonical.is_dir() { return Err("PNCC_REMOTE_STORAGE_BOUNDARY_INVALID".into()); } Ok(canonical) } fn lock_file(path: &Path) -> Result { let file = OpenOptions::new() .read(true) .write(true) .create(true) .truncate(false) .open(path) .map_err(|error| format!("PNCC_REMOTE_LOCK_FAILED: {error}"))?; file.lock_exclusive() .map_err(|error| format!("PNCC_REMOTE_LOCK_FAILED: {error}"))?; Ok(file) } fn write_json_atomic(path: &Path, value: &T) -> Result<(), String> { let parent = path .parent() .ok_or("PNCC_REMOTE_STORAGE_BOUNDARY_INVALID")?; let temporary = parent.join(format!(".pncc-{}.tmp", Uuid::new_v4())); let bytes = serde_json::to_vec_pretty(value) .map_err(|error| format!("PNCC_REMOTE_RECORD_INVALID: {error}"))?; let mut file = OpenOptions::new() .write(true) .create_new(true) .open(&temporary) .map_err(|error| format!("PNCC_REMOTE_RECORD_WRITE_FAILED: {error}"))?; file.write_all(&bytes) .and_then(|_| file.sync_all()) .map_err(|error| format!("PNCC_REMOTE_RECORD_WRITE_FAILED: {error}"))?; fs::rename(&temporary, path) .map_err(|error| format!("PNCC_REMOTE_RECORD_WRITE_FAILED: {error}")) } fn read_json Deserialize<'de>>(path: &Path) -> Result { let metadata = fs::symlink_metadata(path).map_err(|error| { if error.kind() == std::io::ErrorKind::NotFound { "PNCC_REMOTE_RECORD_NOT_FOUND".to_string() } else { format!("PNCC_REMOTE_RECORD_READ_FAILED: {error}") } })?; if metadata.file_type().is_symlink() || !metadata.is_file() { return Err("PNCC_REMOTE_RECORD_INVALID".into()); } serde_json::from_slice( &fs::read(path).map_err(|error| format!("PNCC_REMOTE_RECORD_READ_FAILED: {error}"))?, ) .map_err(|error| format!("PNCC_REMOTE_RECORD_INVALID: {error}")) } fn directory_size(root: &Path) -> Result { let mut total = 0_u64; let mut pending = vec![root.to_path_buf()]; while let Some(path) = pending.pop() { let metadata = fs::symlink_metadata(&path) .map_err(|error| format!("PNCC_REMOTE_CACHE_MEASURE_FAILED: {error}"))?; if metadata.file_type().is_symlink() { return Err("PNCC_REMOTE_CACHE_SYMLINK_REJECTED".into()); } if metadata.is_file() { total = total.saturating_add(metadata.len()); } else if metadata.is_dir() { for entry in fs::read_dir(&path) .map_err(|error| format!("PNCC_REMOTE_CACHE_MEASURE_FAILED: {error}"))? { pending.push( entry .map_err(|error| format!("PNCC_REMOTE_CACHE_MEASURE_FAILED: {error}"))? .path(), ); } } } Ok(total) } fn remove_exact_cache(root: &Path, cache: &Path) -> Result<(), String> { if cache.parent() != Some(root) || cache == root || !cache.starts_with(root) { return Err("PNCC_REMOTE_CACHE_BOUNDARY_INVALID".into()); } fs::remove_dir_all(cache).map_err(|error| format!("PNCC_REMOTE_CACHE_EVICTION_FAILED: {error}")) } fn trusted_git() -> Command { let executable = if cfg!(windows) { "git" } else { "/usr/bin/git" }; let mut command = Command::new(executable); command.env_clear(); #[cfg(unix)] command.env("PATH", "/usr/bin:/bin"); #[cfg(windows)] for key in ["PATH", "SystemRoot", "WINDIR", "TEMP", "TMP"] { if let Some(value) = std::env::var_os(key) { command.env(key, value); } } command .env("GIT_CONFIG_NOSYSTEM", "1") .env( "GIT_CONFIG_GLOBAL", if cfg!(windows) { "NUL" } else { "/dev/null" }, ) .env("GIT_TERMINAL_PROMPT", "0") .env("GCM_INTERACTIVE", "Never") .args(["-c", "protocol.file.allow=never"]); if cfg!(test) { command.args(["-c", "protocol.file.allow=always"]); } command } fn git_at(path: &Path) -> Command { let mut command = trusted_git(); command.arg("-C").arg(path); command } fn git_status(command: &mut Command, label: &str) -> Result<(), String> { let output = command .output() .map_err(|error| format!("{label}_FAILED: {error}"))?; require_success(output, label).map(|_| ()) } fn git_text(path: &Path, args: &[&str], label: &str) -> Result { let output = git_at(path) .args(args) .output() .map_err(|error| format!("{label}_FAILED: {error}"))?; String::from_utf8(require_success(output, label)?.stdout) .map_err(|_| format!("{label}_NOT_UTF8")) } fn git_bytes(path: &Path, args: &[&str], label: &str) -> Result, String> { let output = git_at(path) .args(args) .output() .map_err(|error| format!("{label}_FAILED: {error}"))?; Ok(require_success(output, label)?.stdout) } fn require_success(output: Output, label: &str) -> Result { if output.status.success() { Ok(output) } else { Err(format!( "{label}_FAILED: {}", String::from_utf8_lossy(&output.stderr).trim() )) } } fn sha256_hex(bytes: &[u8]) -> String { digest(&SHA256, bytes) .as_ref() .iter() .map(|byte| format!("{byte:02x}")) .collect() } #[cfg(test)] mod tests { use super::*; use tempfile::TempDir; fn fixture() -> (TempDir, PathBuf, PathBuf, String) { let temp = TempDir::new().unwrap(); let source = temp.path().join("source"); let remote = temp.path().join("remote.git"); let storage = temp.path().join("storage"); fs::create_dir_all(source.join("brain")).unwrap(); fs::create_dir(&storage).unwrap(); test_git(&source, &["init", "-b", "main"]); fs::write(source.join("brain/CORE.hldp"), "first\n").unwrap(); test_git(&source, &["add", "."]); test_git( &source, &[ "-c", "user.name=PNCC Test", "-c", "user.email=pncc@test.invalid", "commit", "-m", "first", ], ); let output = trusted_git() .args(["init", "--bare", &remote.to_string_lossy()]) .output() .unwrap(); assert!(output.status.success()); test_git(&remote, &["config", "uploadpack.allowFilter", "true"]); test_git( &remote, &["config", "uploadpack.allowAnySHA1InWant", "true"], ); test_git( &source, &["remote", "add", "origin", &remote.to_string_lossy()], ); test_git(&source, &["push", "-u", "origin", "main"]); let remote_url = format!("file://{}", remote.display()); register_remote_mount_at( &storage, RegisterPnccRemoteMountInput { mount_id: "persona-primary".into(), remote_url: remote_url.clone(), branch: None, }, true, ) .unwrap(); (temp, source, storage, remote_url) } fn test_git(path: &Path, args: &[&str]) -> String { let mut command = trusted_git(); command .env("GIT_ALLOW_PROTOCOL", "file") .arg("-C") .arg(path) .args(args); let output = command.output().unwrap(); assert!( output.status.success(), "git {args:?}: {}", String::from_utf8_lossy(&output.stderr) ); String::from_utf8_lossy(&output.stdout).trim().into() } fn read_input() -> ReadMountedPnccRemoteObjectInput { ReadMountedPnccRemoteObjectInput { mount_id: "persona-primary".into(), relative_path: "brain/CORE.hldp".into(), expected_head: None, max_cache_bytes: None, } } #[test] fn reads_incrementally_without_worktree_or_model_execution() { let (_temp, _source, storage, _url) = fixture(); let first = read_mounted_remote_object_with_file_policy(&storage, read_input(), true).unwrap(); assert_eq!(first.content, "first\n"); assert!(first.cursor_advanced); assert!(first.continuity_verified); assert!(first.fetched_incremental_objects); assert!(!first.worktree_created); assert!(!first.full_history_requested); assert!(!first.model_inference_started); assert!(!first.reality_execution_allowed); let second = read_mounted_remote_object_with_file_policy(&storage, read_input(), true).unwrap(); assert!(!second.cursor_advanced); assert!(!second.fetched_incremental_objects); assert_eq!(second.previous_verified_head, Some(first.remote_head)); } #[test] fn appends_only_a_descendant_segment_and_rejects_rewritten_history() { let (_temp, source, storage, _url) = fixture(); let first = read_mounted_remote_object_with_file_policy(&storage, read_input(), true).unwrap(); fs::write(source.join("brain/CORE.hldp"), "second\n").unwrap(); test_git(&source, &["add", "."]); test_git( &source, &[ "-c", "user.name=PNCC Test", "-c", "user.email=pncc@test.invalid", "commit", "-m", "second", ], ); test_git(&source, &["push", "origin", "main"]); let second = read_mounted_remote_object_with_file_policy(&storage, read_input(), true).unwrap(); assert_eq!(second.previous_verified_head, Some(first.remote_head)); assert_eq!(second.content, "second\n"); test_git(&source, &["checkout", "--orphan", "rewrite"]); test_git(&source, &["rm", "-rf", "."]); fs::create_dir_all(source.join("brain")).unwrap(); fs::write(source.join("brain/CORE.hldp"), "rewrite\n").unwrap(); test_git(&source, &["add", "."]); test_git( &source, &[ "-c", "user.name=PNCC Test", "-c", "user.email=pncc@test.invalid", "commit", "-m", "rewrite", ], ); test_git(&source, &["branch", "-M", "main"]); test_git(&source, &["push", "--force", "origin", "main"]); assert_eq!( read_mounted_remote_object_with_file_policy(&storage, read_input(), true).unwrap_err(), "PNCC_REMOTE_HISTORY_REWRITE_REJECTED" ); } #[test] fn public_registration_rejects_credentials_and_non_https_remotes() { assert_eq!( validate_remote_url("https://token@example.invalid/repo.git", false).unwrap_err(), "PNCC_REMOTE_URL_MUST_BE_CREDENTIAL_FREE_HTTPS" ); assert_eq!( validate_remote_url("http://example.invalid/repo.git", false).unwrap_err(), "PNCC_REMOTE_URL_MUST_BE_CREDENTIAL_FREE_HTTPS" ); assert_eq!( validate_relative_path("../brain.hldp").unwrap_err(), "PNCC_REMOTE_PATH_INVALID" ); } #[test] fn cache_eviction_keeps_the_durable_continuity_cursor() { let (_temp, _source, storage, _url) = fixture(); let mut input = read_input(); input.max_cache_bytes = Some(MIN_CACHE_LIMIT_BYTES); let objects = child_root(&storage, "objects").unwrap(); let first = read_mounted_remote_object_with_file_policy(&storage, input.clone(), true).unwrap(); let cache = objects.join(format!("{}.git", first.remote_identity_hash)); fs::write( cache.join("force-budget-overrun"), vec![0_u8; MIN_CACHE_LIMIT_BYTES as usize], ) .unwrap(); let second = read_mounted_remote_object_with_file_policy(&storage, input, true).unwrap(); assert_eq!(second.cache_state, "EVICTED_AFTER_BOUNDED_READ"); assert!(!cache.exists()); assert!(storage .join("continuity") .join(format!("{}.json", second.remote_identity_hash)) .is_file()); } }