Skip to content

panic

panic

Emergency panic — immediately cut all resource access across all projects.

Two-phase sequence: Phase 1 raises shields, locks the vault session tier + stops its daemon, and stops the gate server — all in parallel, all reversible. Phase 2 optionally SIGKILLs the containers themselves (podman stop --time 0) — they are not removed.

The vault step deletes the session-unlock tmpfs file in addition to stopping the daemon so the next socket activation can't auto-resume from the session tier — a stopped-but-unlocked daemon defeats the point of pressing PANIC. Persistent tiers (keyring, systemd-creds, credentials.passphrase) are intentionally untouched; clearing them is destructive and the operator can opt-in via terok-sandbox vault lock --forget.

Token revocation is deliberately excluded — it is irreversible and shields + stopped services already cut access.

logger = logging.getLogger(__name__) module-attribute

PanicResult(shields_raised=list(), shield_errors=list(), vault_stopped=False, vault_error=None, gate_stopped=False, gate_error=None, containers_stopped=list(), container_stop_errors=list(), shield_bypassed=False, total_running=0) dataclass

Outcome of an execute_panic invocation.

shields_raised = field(default_factory=list) class-attribute instance-attribute

shield_errors = field(default_factory=list) class-attribute instance-attribute

vault_stopped = False class-attribute instance-attribute

vault_error = None class-attribute instance-attribute

gate_stopped = False class-attribute instance-attribute

gate_error = None class-attribute instance-attribute

containers_stopped = field(default_factory=list) class-attribute instance-attribute

container_stop_errors = field(default_factory=list) class-attribute instance-attribute

shield_bypassed = False class-attribute instance-attribute

total_running = 0 class-attribute instance-attribute

has_errors property

Return whether any operation failed.

execute_panic(*, stop_containers=False)

Execute the full panic sequence.

Discovers every running container, then raises shields, stops vault and gate — all in parallel. If stop_containers, also kills the containers afterwards (SIGKILL; they are not removed).

Source code in src/terok/lib/domain/panic.py
def execute_panic(
    *,
    stop_containers: bool = False,
) -> PanicResult:
    """Execute the full panic sequence.

    Discovers every running container, then raises shields, stops vault
    and gate — all in parallel.  If *stop_containers*, also kills the
    containers afterwards (SIGKILL; they are not removed).
    """
    result = PanicResult()
    targets = _discover_targets()
    result.total_running = len(targets)
    result.shield_bypassed = get_shield_bypass_firewall_no_protection()

    _phase1_lockdown(result, targets)
    _write_panic_lock()

    # Phase 2: optional container kill
    if stop_containers and targets:
        result.containers_stopped, result.container_stop_errors = _stop_containers(targets)

    return result

panic_stop_containers()

Discover and SIGKILL all running containers (Phase 2 standalone).

Source code in src/terok/lib/domain/panic.py
def panic_stop_containers() -> tuple[list[str], list[tuple[str, str]]]:
    """Discover and SIGKILL all running containers (Phase 2 standalone)."""
    return _stop_containers(_discover_targets())

is_panicked()

Return whether the panic lock file exists.

Source code in src/terok/lib/domain/panic.py
def is_panicked() -> bool:
    """Return whether the panic lock file exists."""
    return (core_state_dir() / _LOCK_FILENAME).is_file()

clear_panic_lock()

Remove the panic lock file if it exists.

Source code in src/terok/lib/domain/panic.py
def clear_panic_lock() -> None:
    """Remove the panic lock file if it exists."""
    (core_state_dir() / _LOCK_FILENAME).unlink(missing_ok=True)

format_panic_report(result)

Format a human-readable summary of the panic result.

Source code in src/terok/lib/domain/panic.py
def format_panic_report(result: PanicResult) -> str:
    """Format a human-readable summary of the panic result."""
    lines = [
        f"Containers found: {result.total_running}",
        _format_shield_status(result),
        f"Vault: {'locked + stopped' if result.vault_stopped else 'FAILED'}",
        f"Gate:  {'stopped' if result.gate_stopped else 'FAILED'}",
    ]

    if result.containers_stopped:
        lines.append(f"Containers killed: {len(result.containers_stopped)}")

    if result.has_errors:
        lines += ["", "Errors:", *_format_errors(result)]

    return "\n".join(lines)