# Sandbox-Modell

Jedes Ch∆In-Modul läuft in einer WebAssembly-Sandbox ohne
ambienten Hostzugriff. Das Modul kann genau das, was es in
seiner `module.yaml` deklariert — und sonst nichts.

## Was ein Modul deklariert

```yaml
permissions:
  - net: api.openai.com         # nur ausgehendes HTTPS
  - net: 127.0.0.1:11434         # lokales Ollama
  - fs.read: /var/lib/fai/in     # nur-lese-Verzeichnis
  - fs.write: /var/lib/fai/out   # schreibbares Verzeichnis
  - env: OPENAI_API_KEY          # eine bestimmte Umgebungsvariable
  - hub: invoke                  # andere Module aufrufen
```

Was nicht auf der Liste steht, ist zur Laufzeit unmöglich. Ein
Modul, das `net:` vergisst, kann das Netzwerk gar nicht
erreichen. Der `WasiCtxBuilder` des Hubs verdrahtet nur die
deklarierten Preopens und Env-Vars — keine Hintertür.

## Was der Operator kontrolliert

Operatoren setzen ihre eigene Obergrenze in
`~/.fai/config.yaml`:

```yaml
security:
  module_allowlist:               # nur diese Module laden
    - "text.*"
  module_denylist:                # diese nie laden
    - "experimental.*"
  max_permissions:                # Cap je Scope
    net: ["api.openai.com"]
    fs.read: ["/var/lib/fai"]
  require_signatures: true        # unsignierte Bundles ablehnen
  require_sbom: true              # Bundles ohne CycloneDX ablehnen
```

Module, deren Berechtigungen die Operator-Obergrenze
überschreiten, scheitern beim Laden mit explizitem Fehler. Die
Operator-Obergrenze ist die zweite Schleuse; die Modul-eigene
Deklaration ist die erste.

## Was du in dieser App siehst

- Das **Store**-Detail-Sheet eines installierten Moduls zeigt
  die Berechtigungsliste mit Icons (`net:` Globus, `fs.read:`
  Ordner, `fs.write:` Stift, `env:` Terminal).
- Die **Diagnose**-Seite zeigt Modul-Anzahl und Capability-
  Anzahl im Summary.
- Ein **Flow-Lauf**, der eine Berechtigung verletzt, schlägt
  mit benanntem Fehler fehl (`PermissionDenied:
  net:example.com`) — sichtbar im Protokoll.

## Was es nicht gibt

- Keine Prozess-Isolation zwischen Modulen. Alle laufen im
  einen Hub-Prozess. Ein WASM-Trap eskaliert zum
  Flow-Schritt-Fehler, nicht zum Hub-Crash, aber
  Speicher-Überlastung in einem Modul kann die anderen
  beeinträchtigen. Pooled-Instance-Modus ist auf der Roadmap.
- Keine Live-Policy-Backend (OPA-artige Laufzeit-
  Entscheidungen). Berechtigungslisten sind statisch zur
  Modul-Ladezeit. Kunden-getrieben; aufgeschoben bis ein
  echter Einsatz es braucht.
