Metadata-Version: 2.4
Name: terok-clearance
Version: 0.7.1
Summary: Shield clearance and desktop notifications for terok
License-Expression: Apache-2.0
License-File: LICENSE
License-File: LICENSES/Apache-2.0.txt
Keywords: dbus,notifications,desktop,freedesktop
Author: Jiri Vyskocil
Author-email: jiri@vyskocil.com
Maintainer: Jiri Vyskocil
Maintainer-email: jiri@vyskocil.com
Requires-Python: >=3.12,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Desktop Environment
Classifier: Typing :: Typed
Requires-Dist: asyncvarlink (>=0.3.1,<0.4.0)
Requires-Dist: dbus-fast (>=4.3.0,<5.0)
Requires-Dist: pyyaml (>=6.0)
Requires-Dist: terok-util (>=0.2.0,<0.3.0)
Project-URL: Changelog, https://github.com/terok-ai/terok-clearance/blob/master/CHANGELOG.md
Project-URL: Documentation, https://terok-ai.github.io/terok-clearance/
Project-URL: Homepage, https://terok-ai.github.io/terok-clearance/
Project-URL: Issues, https://github.com/terok-ai/terok-clearance/issues
Project-URL: Repository, https://github.com/terok-ai/terok-clearance
Project-URL: Security, https://github.com/terok-ai/terok-clearance/security/policy
Description-Content-Type: text/markdown

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://terok-ai.github.io/terok/terok-logo-w.svg">
    <img src="https://terok-ai.github.io/terok/terok-logo-b.svg" alt="terok-clearance" width="120">
  </picture>
</p>

# terok-clearance

[![PyPI](https://img.shields.io/pypi/v/terok-clearance)](https://pypi.org/project/terok-clearance/)
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![REUSE status](https://api.reuse.software/badge/github.com/terok-ai/terok-clearance)](https://api.reuse.software/info/github.com/terok-ai/terok-clearance)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=terok-ai_terok-clearance&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=terok-ai_terok-clearance)

Live allow/deny prompts for the [terok-shield](https://github.com/terok-ai/terok-shield) firewall — desktop
notifications, varlink hub, verdict daemon.

When a hardened terok container hits a blocked outbound destination,
the operator sees a desktop notification with **Allow** and **Deny**
buttons; the chosen verdict is written into the running container's nftables ruleset.

<p align="center">
  <img src="https://terok-ai.github.io/terok/img/architecture.svg" alt="terok ecosystem — terok-clearance turns blocked-traffic events into operator decisions">
</p>

## What is the clearance system

The clearance system is the operator-in-the-loop decision path for
terok's egress firewall.  It is built from a hub and verdict pair
that talk over a varlink Unix socket and surface decisions through
the freedesktop Notifications D-Bus interface:

```mermaid
sequenceDiagram
    participant C as Container
    participant S as terok-shield<br/>(nftables)
    participant H as clearance-hub
    participant U as Operator (desktop)
    participant V as clearance-verdict

    C->>S: outbound packet to api.example.com
    S-->>C: REJECT (default-deny)
    S->>H: blocked-connection event<br/>(NFLOG → varlink)
    H->>U: desktop notification<br/>"Allow api.example.com?"
    U->>H: clicks "Allow"
    H->>V: ApplyVerdict(allow, dest)
    V->>S: terok-shield allow api.example.com
    S-->>S: nft add element …
    S-->>C: subsequent packets pass
```

The hub and the verdict server are composed in-process by the
per-container supervisor that ``terok-sandbox``'s OCI hook spawns —
one supervisor (and therefore one hub socket) per container.  The
hub fans events out to whichever operator UIs are subscribed (the
plain-terminal `terok-clearance` tool, the embedded `terok-tui`
screen, a `DbusNotifier` listening on the session bus).  The
verdict server is the only piece that calls into the container's
network namespace, so it sits behind the hub's authz boundary and
keeps the privileged surface small.

## What it provides

- **Async-first Python API** — `create_notifier()`, `Notifier`
  protocol, `DbusNotifier`, `CallbackNotifier`, `NullNotifier`
- **Varlink hub** — `ClearanceHub`, `ClearanceClient`,
  `EventSubscriber` for in-process subscribers (used by the
  TUI to render live verdicts)
- **Multi-socket subscriber** — `MultiSocketSubscriber` multiplexes
  every per-container hub socket under `$XDG_RUNTIME_DIR/terok/clearance/`
  so a single UI sees the union of every supervisor's event stream
- **Embeddable verdict server** — `VerdictServer` for the
  per-container supervisor to compose alongside the hub
- **Graceful degradation** — `NullNotifier` is returned when no
  D-Bus session bus is available, so headless hosts can still run
  the rest of the stack

## Where it sits in the stack

terok-clearance is the user-in-the-loop side-rail of the terok
ecosystem.  Above it,
[terok](https://github.com/terok-ai/terok)'s TUI subscribes to every
per-container hub socket to display verdicts in-band; on a desktop
session the same events fire freedesktop popups.  Below it, the
verdict server reaches into
[terok-shield](https://github.com/terok-ai/terok-shield) to mutate
the running ruleset.  Lifecycle is owned by
[terok-sandbox](https://github.com/terok-ai/terok-sandbox)'s
per-container supervisor, which composes the hub and verdict server
in-process for every container it watches.

The package is genuinely usable on its own — the notification API
and the protocol abstractions are stable enough to sit at the heart
of any desktop-driven IPC use case.

## Requirements

- Linux with a D-Bus session bus (any desktop environment with a
  notification daemon) — the package degrades cleanly to a no-op
  notifier when no bus is reachable
- Python 3.12+

## Installation

```bash
pip install terok-clearance
```

For most users this dependency is pulled in transitively by
`terok-sandbox`'s setup phase.  Install it directly only when
embedding the API in your own tooling.

## Quick start

### Send a notification

```python
import asyncio
from terok_clearance import create_notifier

async def main():
    notifier = await create_notifier(app_name="terok")
    action_received = asyncio.Event()

    def on_action(nid, key):
        print(f"{nid}: {key}")
        action_received.set()

    notifier.on_action(on_action)

    nid = await notifier.notify(
        "Clearance request",
        "Task alpha wants access to api.github.com:443",
        actions={"allow": "Allow", "deny": "Deny"},
    )

    await action_received.wait()
    await notifier.close()

asyncio.run(main())
```

### CLI tool (development / testing)

```bash
terok-clearance-notify "Title" "Body" --actions allow:Allow deny:Deny --wait
```

## License

Apache-2.0 — see [LICENSES/Apache-2.0.txt](LICENSES/Apache-2.0.txt).

