Forge documentation
Library referenceRust

forge-code-safety

Runtime safety primitives for coding agents — worktree isolation, write scoping, delete prevention, approval gates, and audit logging

Runtime safety primitives for coding agents — worktree isolation, write scoping, delete prevention, approval gates, and audit logging

Package contract

FieldValue
Languagerust
Source version0.2.0
Manifestforge-rs/crates/forge-code-safety/Cargo.toml
Source files8
EvidenceSource reference; registry publication and runtime conformance are separate checks

Import boundary

use forge_code_safety;

Use a source checkout or your verified private registry. Manifest coordinates identify the package; they do not establish that a public registry release exists.

Crate boundary

The following entries are taken from src/lib.rs. Feature conditions in the exact source still apply.

#[cfg(not(target_arch = "wasm32"))]
pub mod approval;

#[cfg(not(target_arch = "wasm32"))]
pub mod audit;

#[cfg(not(target_arch = "wasm32"))]
pub mod delete_policy;

pub mod error;

#[cfg(not(target_arch = "wasm32"))]
pub mod lease;

#[cfg(not(target_arch = "wasm32"))]
pub mod worktree;

#[cfg(not(target_arch = "wasm32"))]
pub mod write_scope;

pub mod prelude;

#[cfg(not(target_arch = "wasm32"))]
pub use crate::approval::{ApprovalGate, ApprovalRequest, ApprovalResponse, AutoDenyGate};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::audit::{AuditEntry, FileAuditLog, FileOperation, OperationResult};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::delete_policy::{DeleteDecision, DeletePolicy, DeletePolicyMode, RiskLevel};

pub use crate::error::{CodeSafetyError, CodeSafetyResult};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::lease::{LeaseRequest, RepoLease, RepoLeaseManager};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::worktree::{WorktreeGuard, WorktreeInfo, WorktreeManager};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::write_scope::WriteScope;

Source reference

Download package reference JSON. Each original source file and generated declaration artifact has its own SHA-256 digest. Function bodies and constant values are omitted from downloads. These are source declaration inventories, not compiler-resolved rustdoc, TypeDoc, DocC, or Dokka output. Private modules can contain public declarations that are not reachable through the package boundary; consult the entry point before importing.

approval.rs

Read declaration text · 7 declaration entries

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApprovalRequest {
/// The DID of the agent requesting approval.

pub agent_did: String,
/// The operation type (e.g., "delete", "modify_protected", "force_push").

pub operation: String,
/// The file or directory path the operation targets.

pub path: PathBuf,
/// The assessed risk level of the operation.

pub risk_level: RiskLevel,
/// The agent's justification for why the operation is needed.

pub justification: String
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApprovalResponse {
/// Unique identifier for this approval decision.

pub decision_id: String,
/// Whether the operation was approved.

pub approved: bool,
/// The entity that made the approval decision.

pub reviewer: String,
/// Why the decision was made.

pub reason: String,
/// When the decision was made.

pub decided_at: DateTime<Utc>,
/// Optional conditions attached to the approval.

pub conditions: Vec<String>
}

#[async_trait]
pub trait ApprovalGate: Send + Sync {
    /// Requests approval for a file operation.
    ///
    /// # Arguments
    ///
    /// * `request` - The approval request with details about the operation.
    ///
    /// # Returns
    ///
    /// An [`ApprovalResponse`] indicating whether the operation was approved.
    async fn request_approval(&self, request: &ApprovalRequest) -> ApprovalResponse;
}

pub struct AutoDenyGate;

pub struct AutoApproveGate;

pub struct RiskBasedGate {

}

pub fn new(max_auto_approve: RiskLevel) -> Self;

audit.rs

Read declaration text · 12 declaration entries

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum FileOperation {
    /// Creating a new file.
    Create,
    /// Reading a file's contents.
    Read,
    /// Modifying an existing file.
    Modify,
    /// Deleting a file.
    Delete,
    /// Renaming or moving a file.
    Rename,
    /// Changing file permissions.
    Chmod,
    /// Creating a directory.
    CreateDir,
    /// Removing a directory.
    RemoveDir,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum OperationResult {
    /// The operation succeeded.
    Success,
    /// The operation was denied by policy.
    Denied {
        /// Why it was denied.
        reason: String,
    },
    /// The operation failed due to an error.
    Failed {
        /// What went wrong.
        reason: String,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuditEntry {
/// Unique identifier for this entry.

pub id: String,
/// When the operation occurred.

pub timestamp: DateTime<Utc>,
/// The DID of the agent that performed the operation.

pub agent_did: String,
/// The type of operation.

pub operation: FileOperation,
/// The file path targeted by the operation.

pub path: PathBuf,
/// The result of the operation.

pub result: OperationResult,
/// Optional additional context or notes.

pub context: Option<String>,
/// BLAKE3 hash of the previous entry for chain integrity.

pub previous_hash: String,
/// BLAKE3 hash of this entry's content.

pub entry_hash: String
}

pub struct FileAuditLog {

}

pub fn new() -> Self;

pub async fn record(
        &self,
        agent_did: &str,
        operation: FileOperation,
        path: PathBuf,
        result: OperationResult,
        context: Option<String>,
    );

pub async fn entries(&self) -> Vec<AuditEntry>;

pub async fn len(&self) -> usize;

pub async fn is_empty(&self) -> bool;

pub async fn entries_by_agent(&self, agent_did: &str) -> Vec<AuditEntry>;

pub async fn entries_by_operation(&self, operation: FileOperation) -> Vec<AuditEntry>;

pub async fn verify_chain(&self) -> Result<(), String>;

delete_policy.rs

Read declaration text · 12 declaration entries

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DeleteDecision {
    /// The delete is denied.
    Denied {
        /// The path that was denied.
        path: PathBuf,
        /// Why it was denied.
        reason: String,
    },
    /// The delete requires explicit approval before it can proceed.
    RequiresApproval {
        /// The path requiring approval.
        path: PathBuf,
        /// The risk level of the delete.
        risk_level: RiskLevel,
    },
    /// The delete is allowed (matches an approved pattern).
    Allowed {
        /// The path that was allowed.
        path: PathBuf,
        /// The pattern that matched.
        matched_pattern: String,
    },
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum RiskLevel {
    /// Low risk: generated files, build artifacts, temporary files.
    Low,
    /// Medium risk: test files, documentation, configuration.
    Medium,
    /// High risk: source code, production configuration, data.
    High,
    /// Critical risk: security files, keys, critical infrastructure.
    Critical,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeletePolicy {

}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DeletePolicyMode {
    /// All deletes are denied.
    DenyAll,
    /// Deletes require explicit approval.
    RequireApproval,
    /// Deletes matching specific patterns are allowed.
    AllowPattern,
}

pub fn deny_all(agent_did: impl Into<String>) -> Self;

pub fn require_approval(agent_did: impl Into<String>) -> Self;

pub fn with_allowed_patterns(agent_did: impl Into<String>, patterns: Vec<String>) -> Self;

pub fn protect_path(mut self, path: impl Into<PathBuf>) -> Self;

pub fn evaluate(&self, path: &Path) -> DeleteDecision;

pub fn enforce(&self, path: &Path) -> CodeSafetyResult<()>;

pub fn agent_did(&self) -> &str;

pub fn mode(&self) -> &DeletePolicyMode;

error.rs

Read declaration text · 2 declaration entries

#[derive(Debug, Error)]
pub enum CodeSafetyError {
    /// The agent attempted to write to a file outside its assigned write scope.
    ///
    /// Every coding agent is assigned an explicit write scope (a set of paths
    /// and glob patterns). Writes to files outside that scope are denied.
    #[error("write denied: agent '{agent_did}' attempted to write '{path}' which is outside assigned scope '{scope}'")]
    WriteOutsideScope {
        /// The path the agent tried to write to.
        path: PathBuf,
        /// The assigned write scope that was violated.
        scope: PathBuf,
        /// The DID of the agent that attempted the write.
        agent_did: String,
    },

    /// The agent attempted to delete a file, which is forbidden by default.
    ///
    /// Delete operations require explicit escalation and approval. The default
    /// policy is deny-all for deletes.
    #[error("delete denied: agent '{agent_did}' attempted to delete '{path}'; delete operations require explicit escalation (set escalation_policy to allow)")]
    DeleteDenied {
        /// The path the agent tried to delete.
        path: PathBuf,
        /// The DID of the agent that attempted the delete.
        agent_did: String,
    },

    /// The worktree does not exist or is not accessible.
    #[error(
        "worktree '{worktree_path}' not found or not accessible for agent '{agent_did}': {reason}"
    )]
    WorktreeNotFound {
        /// The worktree path that was expected.
        worktree_path: PathBuf,
        /// The DID of the agent that tried to use the worktree.
        agent_did: String,
        /// Why the worktree was not found.
        reason: String,
    },

    /// The worktree has already been leased to another agent.
    #[error("worktree '{worktree_path}' is already leased to agent '{existing_lessee}'; agent '{requesting_agent}' cannot acquire a concurrent lease")]
    WorktreeAlreadyLeased {
        /// The path of the contested worktree.
        worktree_path: PathBuf,
        /// The DID of the agent that currently holds the lease.
        existing_lessee: String,
        /// The DID of the agent that tried to acquire the lease.
        requesting_agent: String,
    },

    /// The agent does not hold a valid lease for the requested repo.
    #[error("no active lease: agent '{agent_did}' does not hold a lease for repo '{repo_path}'; acquire a lease with RepoLeaseManager::acquire() first")]
    NoActiveLease {
        /// The DID of the agent missing a lease.
        agent_did: String,
        /// The repo path that required a lease.
        repo_path: PathBuf,
    },

    /// The lease has expired.
    #[error("lease expired: agent '{agent_did}' lease for worktree '{worktree_path}' expired at {expired_at}; renew or release the lease")]
    LeaseExpired {
        /// The DID of the agent whose lease expired.
        agent_did: String,
        /// The worktree path with the expired lease.
        worktree_path: PathBuf,
        /// When the lease expired (ISO 8601 string).
        expired_at: String,
    },

    /// An approval was required but not granted.
    #[error("approval required: operation '{operation}' on '{path}' by agent '{agent_did}' requires approval (risk_level={risk_level})")]
    ApprovalRequired {
        /// The operation that required approval.
        operation: String,
        /// The path the operation targets.
        path: PathBuf,
        /// The DID of the agent requesting the operation.
        agent_did: String,
        /// The risk level of the operation.
        risk_level: String,
    },

    /// An approval was explicitly denied.
    #[error("approval denied: operation '{operation}' on '{path}' by agent '{agent_did}' was denied by reviewer '{reviewer}': {reason}")]
    ApprovalDenied {
        /// The operation that was denied.
        operation: String,
        /// The path the operation targets.
        path: PathBuf,
        /// The DID of the agent whose request was denied.
        agent_did: String,
        /// The reviewer who denied the request.
        reviewer: String,
        /// Why the approval was denied.
        reason: String,
    },

    /// A file operation was attempted on the main/default branch directly.
    #[error("direct main branch modification denied: agent '{agent_did}' attempted to modify '{path}' on branch '{branch}'; all modifications must be made in worktrees")]
    MainBranchModification {
        /// The DID of the agent that attempted the modification.
        agent_did: String,
        /// The path that was targeted.
        path: PathBuf,
        /// The protected branch name.
        branch: String,
    },

    /// The audit log write failed.
    #[error("audit log write failed for operation '{operation}' by agent '{agent_did}': {reason}")]
    AuditLogFailed {
        /// The operation that was being audited.
        operation: String,
        /// The DID of the agent.
        agent_did: String,
        /// Why the audit log write failed.
        reason: String,
    },

    /// I/O error during file operations.
    #[error("file I/O error at '{path}': {reason}")]
    IoError {
        /// The path where the I/O error occurred.
        path: PathBuf,
        /// What went wrong.
        reason: String,
    },

    /// Git operation failed.
    #[error("git operation failed in '{repo_path}': {reason}")]
    GitError {
        /// The repository where the git operation failed.
        repo_path: PathBuf,
        /// What went wrong.
        reason: String,
    },
}

pub type CodeSafetyResult<T> = Result<T, CodeSafetyError>;

lease.rs

Read declaration text · 14 declaration entries

#[derive(Debug, Clone)]
pub struct LeaseRequest {
/// The DID of the agent requesting the lease.

pub agent_did: String,
/// The worktree path to lease.

pub worktree_path: PathBuf,
/// The write scope the agent is granted.

pub write_scope: WriteScope,
/// How long the lease should be valid for.

pub duration: Duration
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepoLease {
/// Unique identifier for this lease.

pub id: String,
/// The DID of the agent holding this lease.

pub agent_did: String,
/// The worktree path this lease covers.

pub worktree_path: PathBuf,
/// The write scope granted by this lease.

pub write_scope: WriteScope,
/// When the lease was acquired.

pub acquired_at: DateTime<Utc>,
/// When the lease expires.

pub expires_at: DateTime<Utc>
}

pub fn is_expired(&self) -> bool;

pub fn remaining(&self) -> Duration;

pub struct RepoLeaseManager {

}

pub fn new() -> Self;

pub async fn acquire(&self, request: LeaseRequest) -> CodeSafetyResult<RepoLease>;

pub async fn release(&self, lease_id: &str) -> CodeSafetyResult<()>;

pub async fn renew(
        &self,
        lease_id: &str,
        additional_duration: Duration,
    ) -> CodeSafetyResult<RepoLease>;

pub async fn is_active(&self, lease_id: &str) -> bool;

pub async fn get_by_agent(&self, agent_did: &str) -> Option<RepoLease>;

pub async fn get_by_path(&self, worktree_path: &PathBuf) -> Option<RepoLease>;

pub async fn list_active(&self) -> Vec<RepoLease>;

pub async fn cleanup_expired(&self) -> usize;

lib.rs

Read declaration text · 15 declaration entries

#[cfg(not(target_arch = "wasm32"))]
pub mod approval;

#[cfg(not(target_arch = "wasm32"))]
pub mod audit;

#[cfg(not(target_arch = "wasm32"))]
pub mod delete_policy;

pub mod error;

#[cfg(not(target_arch = "wasm32"))]
pub mod lease;

#[cfg(not(target_arch = "wasm32"))]
pub mod worktree;

#[cfg(not(target_arch = "wasm32"))]
pub mod write_scope;

pub mod prelude;

#[cfg(not(target_arch = "wasm32"))]
pub use crate::approval::{ApprovalGate, ApprovalRequest, ApprovalResponse, AutoDenyGate};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::audit::{AuditEntry, FileAuditLog, FileOperation, OperationResult};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::delete_policy::{DeleteDecision, DeletePolicy, DeletePolicyMode, RiskLevel};

pub use crate::error::{CodeSafetyError, CodeSafetyResult};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::lease::{LeaseRequest, RepoLease, RepoLeaseManager};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::worktree::{WorktreeGuard, WorktreeInfo, WorktreeManager};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::write_scope::WriteScope;

worktree.rs

Read declaration text · 22 declaration entries

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorktreeInfo {

}

pub fn id(&self) -> &str;

pub fn path(&self) -> &Path;

pub fn branch(&self) -> &str;

pub fn agent_did(&self) -> &str;

pub fn repo_root(&self) -> &Path;

pub fn created_at(&self) -> DateTime<Utc>;

pub struct WorktreeManager {

}

pub fn new(repo_root: &Path) -> Self;

pub fn with_base(repo_root: &Path, worktree_base: &Path) -> Self;

pub async fn create(
        &self,
        agent_did: &str,
        branch_name: &str,
    ) -> CodeSafetyResult<WorktreeInfo>;

pub async fn remove(&self, worktree: &WorktreeInfo) -> CodeSafetyResult<()>;

pub async fn list(&self) -> Vec<WorktreeInfo>;

pub async fn find_by_agent(&self, agent_did: &str) -> Option<WorktreeInfo>;

pub async fn worktree_for_path(&self, path: &Path) -> Option<WorktreeInfo>;

pub fn repo_root(&self) -> &Path;

#[derive(Debug, Clone)]
pub struct WorktreeGuard {

}

pub fn new(info: WorktreeInfo) -> Self;

pub fn info(&self) -> &WorktreeInfo;

pub fn validate_path(&self, path: &Path) -> CodeSafetyResult<()>;

pub fn validate_branch(&self, branch: &str) -> CodeSafetyResult<()>;

pub fn is_protected_branch(branch: &str) -> bool;

write_scope.rs

Read declaration text · 14 declaration entries

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WriteScope {

}

pub fn builder(agent_did: impl Into<String>) -> WriteScopeBuilder;

pub fn agent_did(&self) -> &str;

pub fn is_allowed(&self, path: &Path) -> CodeSafetyResult<()>;

pub fn allowed_directories(&self) -> &[PathBuf];

pub fn denied_paths(&self) -> &[PathBuf];

pub fn has_any_allowed(&self) -> bool;

pub struct WriteScopeBuilder {

}

pub fn allow_directory(mut self, path: impl Into<PathBuf>) -> Self;

pub fn allow_file(mut self, path: impl Into<PathBuf>) -> Self;

pub fn allow_extension(mut self, pattern: impl Into<String>) -> Self;

pub fn deny_path(mut self, path: impl Into<PathBuf>) -> Self;

pub fn deny_directory(mut self, path: impl Into<PathBuf>) -> Self;

pub fn build(self) -> WriteScope;

Continue

On this page