zhuyuan-ice-gl-zy001/ZCODE-DEV-20260826/public-spine/shell-frozen-src/src-tauri/src/pncc_remote_git.rs

955 lines
32 KiB
Rust

// 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<String>,
}
#[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<String>,
pub max_cache_bytes: Option<u64>,
}
#[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<String>,
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<String>,
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<PnccRemoteObjectReceipt, String> {
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<PnccRemoteObjectReceipt, String> {
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<String, String> {
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<String, String> {
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, &current)? {
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, &current)? {
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<u8>), 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<bool, String> {
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<Option<String>, 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<String, String> {
optional_ref(cache, reference)?.ok_or_else(|| "PNCC_REMOTE_FETCH_HEAD_MISSING".into())
}
fn read_cursor(path: &Path, identity: &str, branch: &str) -> Result<Option<CursorRecord>, 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<PathBuf, String> {
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<std::fs::File, String> {
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<T: Serialize>(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<T: for<'de> Deserialize<'de>>(path: &Path) -> Result<T, String> {
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<u64, String> {
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<String, String> {
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<Vec<u8>, 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<Output, String> {
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());
}
}