feat(permissions): LP4-1/LP4-2 — enforcer Landlock OS + consommation PTY du plan

LP4-1 : adaptateurs SandboxEnforcer concrets (LandlockSandbox Linux via le LSM
Landlock, NoopSandbox ailleurs) + default_enforcer() cfg-sélectionné, prêts à
être injectés au composition root (LP4-3). Aucun changement de comportement
runtime tant que rien n'est câblé : SpawnSpec.sandbox reste None.

LP4-2 : PortablePtyAdapter consomme SpawnSpec.sandbox via spawn_command_sandboxed
(thread jetable restreint par enforce() puis fork → le domaine Landlock est hérité
par l'enfant à travers execve ; les autres threads d'IdeA ne sont jamais sandboxés).
Builder additif with_sandbox_enforcer ; fail-closed si enforce() échoue.

Tests : domain + infrastructure verts (dont les tests Landlock réels de fencing
read-only/write-only et la confine-au-thread).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 08:00:47 +02:00
parent b05d04ab7a
commit 17ca65ed0f
7 changed files with 653 additions and 8 deletions

View File

@ -0,0 +1,33 @@
//! [`NoopSandbox`] — the no-op [`SandboxEnforcer`] for platforms without an OS
//! sandbox (Windows, macOS) and the universal fallback (lot LP4-1).
//!
//! It compiles **everywhere** and never restricts anything: `enforce` always
//! returns [`SandboxStatus::Unsupported`] and never errors. The caller keeps the
//! advisory LP3 projection as its only guard.
use domain::sandbox::{SandboxEnforcer, SandboxError, SandboxKind, SandboxPlan, SandboxStatus};
/// A [`SandboxEnforcer`] that enforces nothing (non-Linux / fallback).
#[derive(Debug, Default, Clone, Copy)]
pub struct NoopSandbox;
impl NoopSandbox {
/// Builds the no-op enforcer.
#[must_use]
pub fn new() -> Self {
Self
}
}
impl SandboxEnforcer for NoopSandbox {
fn kind(&self) -> SandboxKind {
SandboxKind::Unsupported
}
fn enforce(&self, _plan: &SandboxPlan) -> Result<SandboxStatus, SandboxError> {
// No OS sandbox here: nothing enforced, never an error (the fail-closed
// posture handling is a Landlock-only concern; on an unsupported platform
// there is nothing to fail closed *against*).
Ok(SandboxStatus::Unsupported)
}
}