# Shell Safety Module

**Package:** `cleveragents.tui.shell_safety`

The shell safety module protects users from accidentally executing dangerous
commands in the TUI shell mode (`!` prefix).  It provides a configurable
pattern registry, a danger-level classification system, and an application
service that integrates with the TUI warning overlay.

---

## Purpose

When a user types `!<command>` in the TUI, the `ShellSafetyService` checks
the command against a registry of known-dangerous patterns before the
subprocess is spawned.  Commands that match a pattern at or above the
configured `block_level` are blocked; commands below that level surface a
warning overlay that the user must acknowledge before proceeding.

---

## Key Classes

### `ShellDangerLevel`

Four-level `IntEnum` severity scale:

```
LOW (1) < MEDIUM (2) < HIGH (3) < CRITICAL (4)
```

Numeric comparisons work naturally: `level >= ShellDangerLevel.HIGH`.

### `DangerousPattern`

Immutable frozen dataclass describing a single dangerous pattern:

```python
DangerousPattern(
    name="fork_bomb",
    pattern=r":\(\)\s*\{",
    level=ShellDangerLevel.CRITICAL,
    description="Fork bomb — exhausts process table and crashes the system.",
)
```

### `DangerousPatternDetector`

Maintains the registry of `DangerousPattern` objects and provides
`check_first(command) → DangerousCommandWarning | None` to return the
highest-severity matching pattern.

### `ShellSafetyService`

High-level application service used by the TUI:

```python
from cleveragents.tui.shell_safety import ShellSafetyService, ShellDangerLevel

# Default: block MEDIUM and above automatically
service = ShellSafetyService()

# Custom: only block CRITICAL; show overlay for HIGH and below
service = ShellSafetyService(block_level=ShellDangerLevel.CRITICAL)

# Custom: delegate all decisions to a callback
def my_callback(warning):
    # Return True to allow, False to block
    return warning.danger_level < ShellDangerLevel.HIGH

service = ShellSafetyService(warn_callback=my_callback)

result = service.check_command("rm -rf /")
if not result.allowed:
    print(f"Blocked: {result.warning.description}")
```

### `DangerousCommandWarning`

Value object returned when a dangerous pattern is matched:

| Attribute | Type | Description |
|-----------|------|-------------|
| `command` | `str` | The original command text |
| `pattern` | `DangerousPattern` | The matched pattern |
| `danger_level` | `ShellDangerLevel` | Convenience alias for `pattern.level` |
| `message` | `str` | Human-readable warning message |

---

## Built-in Pattern Categories

| Category | Example patterns | Default level |
|----------|-----------------|---------------|
| Recursive deletion | `rm -rf /`, `rm -rf ~` | CRITICAL |
| Disk-level writes | `dd if=`, `mkfs`, `shred` | CRITICAL |
| Fork bombs | `:(){ :|:& };:` | CRITICAL |
| Privilege escalation | `sudo su`, `chmod 777 /` | HIGH |
| Network exfiltration | `curl \| sh`, `wget \| bash` | HIGH |
| Reverse shells | `nc -e /bin/sh`, `bash -i >& /dev/tcp` | HIGH |
| Dangerous redirects | `> /dev/sda`, `> /etc/passwd` | HIGH |
| Credential exposure | `env \| curl`, `cat ~/.ssh/id_rsa \| nc` | MEDIUM |

---

## Adding Custom Patterns

```python
from cleveragents.tui.shell_safety import (
    DangerousPattern,
    ShellDangerLevel,
    ShellSafetyService,
)

custom = DangerousPattern(
    name="drop_database",
    pattern=r"DROP\s+DATABASE",
    level=ShellDangerLevel.HIGH,
    description="Drops an entire database — irreversible.",
    case_sensitive=False,
)

service = ShellSafetyService(extra_patterns=[custom])
```

---

## Integration with the TUI

The TUI wires `ShellSafetyService` into the shell input handler.  When
`check_command()` returns `allowed=False`, the TUI displays a
`DangerousCommandWarningOverlay` widget with the warning message and danger
level.  The user must explicitly confirm before the command is executed.

For commands that are blocked outright (above `block_level` with no
callback), the overlay displays a non-dismissable error and the command is
never executed.

---

## Testing

The shell safety module is fully covered by BDD scenarios in
`features/shell_safety.feature`.  All pattern matching is deterministic and
does not require a running TUI, making it straightforward to test in
isolation:

```python
from cleveragents.tui.shell_safety import ShellSafetyService

service = ShellSafetyService()
assert not service.is_safe("rm -rf /")
assert service.is_safe("ls -la")
```
