đŸŒČ🩀 TLS-Gate & Die Wald-CA: Warum jedes Bit zĂ€hlt (ASCII-Prozesskette)

FĂŒr alle KrĂŒmel & die Crew (#oldschool #mcp #nullfeld #zeitlos)
Stand: 18.10.2026 · Gemini-Crew & Branko
Zweck: Sichtbar machen, warum der Nachbau „ohne Docker" im echten System so verdammt prĂ€zise sein muss — wann welcher SchlĂŒssel wo greift, warum RZ, Strato, Crumbforest-Container und OZM-Museum getrennte Welten mit Lese-BrĂŒcken sind und warum eine unabhĂ€ngige Container-CA das Geheimnis fĂŒr echtes Offline-Überleben ist.


0. Warum man beim Nachbau ohne Docker um jedes Bit kÀmpft

Docker versteckt oft schlampige Grenzen: Man wirft alles in einen Container, teilt sich blind ein Dateisystem oder eine .env und merkt erst beim Ausfall, dass alles an einem einzigen Faden hing.

Wenn man es nackt auf dem System (Native PHP-FPM + MariaDB + Linux-User + Systemd) baut, wird jede Grenze physisch echt:
- Welcher Linux-User (root, www-data, tlsgate) darf welche Datei lesen?
- Welcher Datenbank-User (tlsgate_ddl vs. tlsgate_app) spricht ĂŒber welchen Unix-Socket?
- Welcher SchlĂŒssel liegt im RAM, welcher auf Platte (/etc/tlsgate/master.key), welcher versiegelt in der DB (tg1:...)?
- Wann wird ein Key abgeleitet (KDF), wann gebunden (Associated Data), wann aus dem RAM genullt (sodium_memzero)?

Ein einziges falsches Bit bei group_id, user_id, key_id oder Dateirechten (0640 vs. 0600) — und das System sagt NEIN (Fail-Closed). Genau diese HĂ€rte beim Einrichten ist spĂ€ter der Schutzschild im Betrieb.


1. Die Gesamt-Topologie: Drei Welten, getrennte VPNs, gemeinsames Lesen

Im Rechenzentrum (RZ) lĂ€uft der TLS-Gate-Core im Verbund mit dem Strato-Setup (crumbforest.org / .io / nullfeld / backbone). Gleichzeitig existieren eigene IdentitĂ€ten und eigene CAs fĂŒr den Crumbforest-Container (Waldmitte) und das OZM Museum.

+=========================================================================================+
|                          AUSSENWELT / OEFFENTLICHE REGISTRARE                           |
|       InterNetX / AutoDNS SOAP-API (Public TLS: *.crumbforest.org / *.crumbforest.io)   |
+=========================================================================================+
                                             ^
                                             | HTTPS + WSDL-Allowlist (TLSGATE_SOAP_HOSTS)
                                             | Stream-Timeout 20s / Connect-Timeout 15s
                                             v
+=========================================================================================+
|                     RECHENZENTRUM (RZ) & STRATO-VERBUND (NULLFELD / BACKBONE)           |
|                                                                                         |
|  +-----------------------------------------------------------------------------------+  |
|  |                         TLS-GATE CORE (NativePHP RC1.0)                           |  |
|  |                                                                                   |  |
|  |   Mandant / Gruppe A: [crumbforest]          Mandant / Gruppe B: [ozm]            |  |
|  |   - Public Certs (.org / .io)                - Eigene OZM-Identitaet              |  |
|  |   - Registrar-Spiegel (Inventory)            - Eigener WireGuard-Kreis            |  |
|  |   - NetBox-Spiegel (seeds.crumbforest.io)    - Eigene SOAP/NetBox/CA-Blobs        |  |
|  +-----------------------------------------------------------------------------------+  |
|                  |                                                 |                    |
|                  | WG-Tunnel A (10.42.0.x / nullfeld)              | WG-Tunnel B (OZM)  |
+==================|=================================================|====================+
                   |                                                 |
                   | (Getrennte Schreib-/Tunnelhoheit)               |
                   v                                                 v
+-----------------------------------------+       +---------------------------------------+
|   WELT 1: CRUMBFOREST CONTAINER         |       |   WELT 2: OZM MUSEUM                  |
|   (Waldmitte / Pelicases / Baumhaus)    |       |   (Hammerbrooklyn / Ausstellung)      |
|                                         |       |                                       |
|   * Eigene lokale Container-CA          |       |   * Eigene lokale Museums-CA          |
|   * Lokale Sensorik (Pose, Hailo,       |       |   * Lokale Sensorik (Raum, Licht,     |
|     snakeview, rattlecam, LiPo-Sim)     |       |     Klangkoerper, Installationen)     |
|   * Lokales RAG (Ollama + Qdrant/       |       |   * Eigener lokaler Kontext           |
|     KernelCrumb / missions-core)        |       |                                       |
|                                         |       |                                       |
|   [SCHREIBT NUR LOKAL]                  |       |   [SCHREIBT NUR LOKAL]                |
+-----------------------------------------+       +---------------------------------------+
                     \                                           /
                      \     <--- Duerfen untereinander --->     /
                       +=======>   NUR LESEN (Read-Only)  <====+
                            (Kein Central Command, kein Durchgriff)

Warum diese Trennung? (Structural Antifascism by Design)

  1. Getrennte WireGuard-VPNs & getrennte CAs: Wenn im Museum ein Sensor-Node wackelt oder umgebaut wird, berĂŒhrt das niemals den SchlĂŒsselraum des Crumbforest-Containers (und umgekehrt).
  2. Untereinander lesen, aber nicht fremdsteuern: Kein Node hat „Central Command" ĂŒber den anderen. Jeder Raum ist sein eigenes Universum, darf aber den Zustand/Spiegel des Nachbarn lesend verstehen.
  3. Mandanten-Bindung bis ins Kryptogramm: Selbst im selben TLS-Gate-Core im RZ kann Gruppe crumbforest mathematisch niemals ein Secret von Gruppe ozm entschlĂŒsseln, weil group_id fest in den AEAD-Tag (tg1|soap|<group_id>|default) eingebacken ist.

2. Wann, Wo, Welcher Key? (Die SchlĂŒssel-Uhrwerk-Matrix)

Hier scheitert man beim Nachbau am schnellsten, wenn man nicht genau sieht, wann welcher SchlĂŒssel wo lebt:

===========================================================================================
SCHICHT 0: DIE PLATTE (Root-Ebene, ausserhalb von Git & ausserhalb von Web-Root)
===========================================================================================
Datei: /etc/tlsgate/master.key (oder TLSGATE_MASTER_KEY_FILE)
Inhalt: 1:<64-Hex-Zeichen (32 Byte Roh-Entropie)>[,2:<64-Hex-Zeichen>...]
Rechte: chown root:www-data, chmod 0640 (Web-Worker darf nur lesen, nie schreiben)

        |
        | (Wird NUR im Moment von Secrets::seal() oder Secrets::open() eingelesen)
        v

===========================================================================================
SCHICHT 1: DIE SCHLUESSEL-ABLEITUNG (KDF im RAM — Secrets.php)
===========================================================================================
Funktion: sodium_crypto_kdf_derive_from_key(32, subkey_id, "TLSGATE1", $rootKey)
Formel  : subkey_id = (key_id * 100) + PURPOSE_SLOT

  Root-Key (32 Byte)
     |
     +---> Slot 1 ('totp')   --> Subkey fuer 2FA-Geheimnisse der Benutzer
     +---> Slot 2 ('soap')   --> Subkey fuer Registrar-Logins (InterNetX/AutoDNS)
     +---> Slot 3 ('outbox') --> Subkey fuer ausgehende Nachrichten / Queue
     +---> Slot 4 ('ca')     --> Subkey fuer lokale VPN- & Container-CA Private Keys!
     +---> Slot 5 ('netbox') --> Subkey fuer NetBox-API-Tokens (seeds.crumbforest.io)

        |
        | + 24 Byte Zufalls-Nonce (random_bytes)
        | + Associated Data (AD) = "tg1|<purpose>|<bind>"
        v

===========================================================================================
SCHICHT 2: DIE VERSIEGELUNG (AEAD XChaCha20-Poly1305 in der MariaDB)
===========================================================================================
Was in der Datenbank steht, ist IMMER nur der fertige "tg1:"-Blob:

  Format: "tg1:" + Base64( [0x01] [key_id: u32_le] [nonce: 24B] [ciphertext + 16B MAC] )

  WICHTIG — DIE BINDUNG (Associated Data):
  -----------------------------------------------------------------------------------------
  Zweck     | Tabelle            | Spalte           | Bind-String ($bind)
  ----------+--------------------+------------------+--------------------------------------
  totp      | users              | totp_secret_enc  | "user:<users.id>"
  soap      | soap_credentials   | secret_enc       | "<group_id>|<label>"
  netbox    | netbox_credentials | token_enc        | "<group_id>|<label>"
  ca        | (ca_keys / lokal)  | privkey_enc      | "<group_id>|<ca_slug>"
  -----------------------------------------------------------------------------------------
  -> Kopiert jemand in der DB den Blob von Gruppe 1 nach Gruppe 2, stimmt $bind beim
     Oeffnen nicht mehr -> AEAD-MAC schlaegt fehl -> RuntimeException!
  -> Sofort nach seal()/open(): sodium_memzero($sub) loescht den Subkey aus dem RAM.

3. Die 4 Prozessketten im Detail (Schritt fĂŒr Schritt)

Prozesskette A: Kaltstart & Bootstrap (Ohne Docker auf der Node)

[1. Linux / MariaDB]
    |
    +-- System-User `tlsgate` (CLI/Cron) & `www-data` (PHP-FPM Pool)
    +-- DB-User `tlsgate_ddl` (DARF: CREATE, ALTER, TRIGGER — NUR fuer Migration!)
    +-- DB-User `tlsgate_app` (DARF NUR: SELECT, INSERT, UPDATE, DELETE auf App-Tabellen)
    |
    v
[2. Master-Key erzeugen]
    $ php bin/user_cli.php key gen > /etc/tlsgate/master.key
    $ chmod 0640 /etc/tlsgate/master.key
    |
    v
[3. Datenbank-Schema & Append-Only-Trigger einspielen]
    $ DB_USER=tlsgate_ddl DB_PASS=... bin/tg migrate
    |  -> Legt Tabellen an (groups, users, audit_log, registrar_inventory, netbox_devices...)
    |  -> Installiert BEFORE UPDATE / BEFORE DELETE Trigger (SIGNAL SQLSTATE '45000')
    |     auf: audit_log, booking_events, catalog_events, registrar_inventory_events
    |
    v
[4. Gruppen (Mandanten) & Zugangsdaten versiegeln]
    $ bin/tg user add-group crumbforest "Crumbforest"
    $ bin/tg user add-group ozm         "OZM Museum & Hub"
    $ bin/tg user cred add crumbforest default https://.../wsdl <user>
    |  -> Prueft WSDL gegen TLSGATE_SOAP_HOSTS
    |  -> Versiegelt Login+Passwort mit Slot 2 ('soap') + Bind "1|default"
    |
    v
[5. Code-Integritaet einfrieren]
    $ bin/TLS-app-scan.bash write
    |  -> Schreibt SHA-256 ueber alle .php/.sh/.sql nach /var/lib/tlsgate/app.manifest
    |  -> TLS-node-doktor.bash prueft ab jetzt bei jedem Lauf auf Drift!

Prozesskette B: Login & Sitzungs-Uhrwerk (Warum kein Code doppelt zÀhlt)

Browser (KrĂŒmel / Crew)                  PHP-FPM (Auth.php / Totp.php)                MariaDB (tlsgate_app)
-----------------------                  -----------------------------                ---------------------
1. POST /login.php (E-Mail + PW) ------> ipBlocked()? (max 10 Fails / 15m) ---------> SELECT count(*) FROM login_attempts
                                         SELECT user WHERE email = ? ---------------> (Falls unbekannt: Argon2id gegen
                                         password_verify() (Constant-Time)             dummyHash() rechnen -> kein Timing!)
                                         |
                                         +-- session_regenerate_id(true)
                                         +-- $_SESSION['tg_pending'] = {uid, ts}
                                         |
2. POST /login.php (6-stelliger TOTP) -> Öffnet totp_secret_enc mit:
                                         Slot 1 ('totp') + Bind "user:<uid>"
                                         PrĂŒft 30s-Zeitschritt ($step > totp_last_step)
                                         |
                                         +-- ATOMARES UPDATE (Patch AUD-02): -------> UPDATE users
                                         |   Verhindert Race-Condition bei            SET totp_last_step = $step ...
                                         |   doppeltem Request in derselben ms!       WHERE id = ?
                                         |                                              AND (totp_last_step IS NULL
                                         |                                                   OR totp_last_step < $step)
                                         +-- rowCount() === 1 ?
                                         |   JA   -> session_regenerate_id(true)
                                         |           Cookie: __Host-tlsgate (Strict)
                                         |           Audit::log('auth.login', 'ok') -> INSERT INTO audit_log (Append-Only!)
                                         |   NEIN -> Audit::log('replay_race')

Prozesskette C: Der Spiegel-Abgleich (NetBox & Registrar — Fail-Closed)

Sowohl im RZ als auch vor einem Offline-Einsatz zieht TLS-Gate den echten Zustand in lokale Spiegel-Tabellen. FĂ€llt draußen das Netz aus, wird niemals mit Fake-Daten ĂŒberschrieben:

[Upstream: NetBox API / SOAP API]
        |
        | 1. Holt Live-Daten (Strikte Timeouts: 15s Connect / 20s HTTP, kein Redirect-Follow)
        v
[Normalisierer: NetBoxClient::normalize() / Inventory::normalize()]
        |
        | 2. Reine Funktion (Pure Function): PrĂŒft Schema-Vertrag
        |    Fehlt ein Pflichtfeld oder ist source === 'unavailable'?
        |    ---> SOFORTIGER ABBRUCH (Kein DB-Write, alter Spiegel bleibt intakt!)
        v
[Sicherheits-Sicherung (Circuit Breaker)]
        |
        | 3. Hat die Liste >= 2000 Zeilen (Paging-Grenze)?      ---> ABBRUCH!
        | 4. Sind > 50% der bekannten GerÀte plötzlich weg      ---> ABBRUCH!
        |    (bei Bestand >= 10, ohne --force)?                      (Schutz vor halber API-Antwort)
        v
[MariaDB Transaktion: BEGIN ... COMMIT]
        |
        +-- Neue EintrÀge      -> INSERT + Event 'new'
        +-- GeÀnderte EintrÀge -> UPDATE + Event 'changed' (mit altem -> neuem Wert als JSON)
        +-- Verschwundene      -> SET gone_at = NOW() + Event 'gone' (Nichts wird stumm gelöscht!)
        +-- ZurĂŒckgekehrte     -> SET gone_at = NULL  + Event 'back'

Prozesskette D: Die unabhĂ€ngige Container-CA im Wald (Offline-First Überlebensmodus)

Das ist der grĂ¶ĂŸte architektonische Vorteil eures Entwurfs:
Ein Crumbforest-Container (unter der BrĂŒcke, im Wald oder als Pelicase im Feld) hat seine eigene lokale CA fĂŒr seine lokale Sensorik (snakeview, rattlecam, crumbzero00/01, ESP32, lokales Ollama/Qdrant).

Er muss nicht im Internet sein, damit Sensoren, lokale Web-Tools und das lokale RAG sicher (mTLS / HTTPS / signierte Receipts) miteinander sprechen und Kinderfragen mit vollem lokalem Kontext beantworten können!

+=========================================================================================+
|                PHASE 1: DER CONTAINER IST OFFLINE IM WALD (AUTARKER BETRIEB)            |
+=========================================================================================+

   [KrĂŒmel / Terminal / Browser im Raum]
            |
            |  Frage: "Wie funktioniert der Regenbogen-Sensor?" / Lokale Pose-Daten
            |  (Verbindung lokal ĂŒber Container-CA gesichert — KEIN Internet nötig!)
            v
   +---------------------------------------------------------------------------------+
   | LOKALER CONTAINER-KNOTEN (z. B. crumbdesktop / Baumhaus / Pelicase)             |
   |                                                                                 |
   |  1. LOKALE CONTAINER-CA (Slot 4: 'ca')                                          |
   |     - Signiert lokale TLS-/Sensor-Zertifikate (snakeview, rattlecam, zero00)    |
   |     - PrĂŒft GerĂ€te gegen den letzten lokalen `netbox_devices`-Spiegel           |
   |                                                                                 |
   |  2. LOKALES GEDÄCHTNIS & INFERENZ (questions-core / KernelCrumb / Ollama)       |
   |     - Beantwortet Fragen SOFORT aus lokalem Qdrant-Vektorraum & Rinden          |
   |     - Kein Cloud-Call, keine API-Kosten ("Die 1 verliert, die 0 gewinnt")       |
   |                                                                                 |
   |  3. LOKALE APPEND-ONLY SPUR (outbox / inbox.rs / receipt.rs / audit_log)        |
   |     - Jede lokale Zertifikats-/Missions-Quittung wird lokal mit Zeitstempel     |
   |       und Hash in die Append-Only-Outbox geschrieben (versiegelt mit Slot 3).   |
   +---------------------------------------------------------------------------------+
            |
            |  (Stunden, Tage oder Wochen vergehen offline im Wald...)
            v
+=========================================================================================+
|                PHASE 2: WIEDERVERBINDUNG (WIRE-GUARD TUNNEL ZUM NULLFELD STEHT)         |
+=========================================================================================+
            |
            |  WireGuard-Handshake (10.42.0.x <-> 10.42.0.1 nullfeld / RZ)
            |  (Wichtig: Client-initiiert! Der Container meldet sich, das Nullfeld ruft nie)
            v
   +---------------------------------------------------------------------------------+
   | SYNCHRONISATION & BRÜCKENSCHLAG (Delta-Abgleich)                                |
   |                                                                                 |
   |  A. Container ---> Nullfeld / RZ:                                               |
   |     - Schiebt signierte Quittungen (Receipts / Outbox-Events / Tagesrinden)     |
   |     - Keine Roh-Videos/Bewegungsdaten (Passkante hÀlt Privates lokal im Raum!)  |
   |                                                                                 |
   |  B. Nullfeld / RZ ---> Container:                                               |
   |     - Liefert frischen NetBox-Device-Spiegel (`netbox_devices`)                 |
   |     - Liefert aktualisierte Public-Cert-BĂŒndel (`CertBundle`) falls nötig       |
   |     - Liefert neue Qdrant-Snapshots / Katalog-StÀnde                            |
   +---------------------------------------------------------------------------------+
            |
            v
   [Tunnel kann jederzeit wieder gekappt werden -> Container lÀuft nahtlos weiter!]

4. Von PepperPHP zu CrabbyRust: Warum der Übergang jetzt glasklar ist

Weil ihr in TLS-NativePHP_v1 bereits auf jede Framework-Magie verzichtet habt, entspricht jedes Bauteil im PHP-Core heute schon 1:1 seinem kĂŒnftigen GegenstĂŒck im Rust-Kern (OZM_Nullfeld_v1):

+--------------------------------------+       +-----------------------------------------------+
| HEUTE: TLS-NativePHP_v1 (PepperPHP)  |  ===> | MORGEN: Nullfeld / Rust-Core (CrabbyRust)     |
+--------------------------------------+       +-----------------------------------------------+
| Secrets.php (tg1: + Libsodium KDF)   |  1:1  | Gleiche Bytes! libsodium-sys / chacha20poly   |
| Guard::decide() (Pure Function)      |  1:1  | Passkante / runner.rs Gate                    |
| database/order_states.json           |  1:1  | #[derive(Deserialize)] enum OrderState        |
| audit_log + Event-Trigger (MariaDB)  |  1:1  | inbox.rs (Single-Writer) + receipt.rs         |
| bin/tg + bin/*_cli.php               |  1:1  | Ein einziges statisches Rust-Binary (clap)    |
| public/*.php + SslController         |  1:1  | axum-Router + askama-Templates (gleiche CSP)  |
| deploy/node/bend.sh (Restore-Beweis) |  1:1  | Bleibt das ehrliche Ops-Fundament auf der Node|
+--------------------------------------+       +-----------------------------------------------+

Merksatz fĂŒr alle KrĂŒmel & kĂŒnftigen Sessions:

Warum scheint es auf den ersten Blick kompliziert?
Weil hier nichts unter den Teppich gekehrt wird. Kein Docker-Container, der heimlich Root-Rechte mischt; keine Cloud, die heimlich SchlĂŒssel verwaltet; kein Sync, der bei halber Leitung heimlich Daten löscht.
Jeder SchlĂŒssel kennt seinen Zweck (Slot 1..5), jede Zeile kennt ihre Gruppe (Associated Data), und jeder Container im Wald bleibt auch ohne Internet ein vollstĂ€ndiger, geschĂŒtzter Denkraum. đŸŒČ🩉🐌🩀


5. Der mögliche Rust-Build (tlsgate-core): Wurzelschutz an Tor, TĂŒr, BrĂŒcke, Baum — und Bugsy 🐞

„Ein KrĂŒmel wandert offline durch den Wald. Bugsy, der ErzĂ€hler, FunkFox, DeepBit und die KrĂŒmeleule. Verbinde dich mit deinem Fußabdruck — kein Passwort brĂŒllen, dein Fußabdruck ist nur deiner.“
— aus dem Hörraum (branko.de/hoerraum)

Wenn wir den kommenden Rust-Build (tlsgate-core) im Stil von OZM_Nullfeld_v1 (questions-core + missions-core) planen, geht es nicht einfach darum, PHP-Dateien in .rs-Dateien zu ĂŒbersetzen. Es geht um Wurzelschutz:
* Wo steht das Tor (Firewall / WireGuard)?
* Was ist die TĂŒr (Passkante / Auth / TOTP / Fußabdruck)?
* Wie trĂ€gt die BrĂŒcke (zwischen nullfeld, backbone, Container-CA und OZM-Museum)?
* Wie bleiben der Baum & seine Wurzeln (lokales Qdrant, lokales pgvector, lokales Ollama, gebunden an echte MAC- & IP-IdentitĂ€ten) geschĂŒtzt?
* Und welche Rolle spielt Bugsy (🐞), der einfache KĂ€fer auf der alten BrĂŒcke?


5.1 Die Wald-Anatomie im Rust-Build: Tor · TĂŒr · BrĂŒcke · Baum · Bugsy

+=========================================================================================+
|                  DIE 5 ELEMENTE DES WURZELSCHUTZES IM RUST-BUILD                        |
+=========================================================================================+

  [1. DAS TOR]  --> firewall_hardening.rs + WireGuard (wg0)
                    "Die Firewall steht VOR allen Diensten."
                    Kein offenes Qdrant (6333), kein offenes Postgres (5432), kein offenes
                    Ollama (11434) ins Internet. Die TĂŒr ist der Tunnel, nicht die Hoffnung.

  [2. DIE TÜR]  --> auth.rs + passkante.rs + totp.rs ("Dein Fußabdruck ist nur deiner")
                    Wer klopft an? Mensch (Argon2id + atomarer TOTP-Step) oder
                    Maschine/Zero/Sensor (MAC + WireGuard-IP + Container-CA-Zertifikat).

  [3. DIE BRÜCKE]-> ozm_bridge_protocol.rs + receipt.rs ("Bugsy auf der alten BrĂŒcke")
                    Verbindet Container-CA (Waldmitte) <-> Nullfeld <-> OZM-Museum.
                    Gesetz 3: Keine Profile, kein Rohdaten-Abfluss. Nur signierte
                    Quittungen (Receipts), Rinden und Resonanz-Signale ĂŒberqueren den Fluss.

  [4. DER BAUM] --> Die zwei Vektor-GedÀchtnisse + Lokale Stimme/Inferenz (Wurzelwerk)
                    - Wurzel A (nullfeld): Qdrant (`docs_crumbforest`) + MariaDB
                    - Wurzel B (backbone): PostgreSQL + `pgvector` (`forest_memory`)
                    - Wurzel C (Lokal/M4/Container): Ollama (`nomic-embed-text` / `gemma`)
                      + Hörraum-Stimmen (offline geklont auf dem M4, 0 Cloud-Bytes).

  [5. BUGSY 🐞] --> bugsy_probe.rs ("Zeig mal, wir schauen gemeinsam")
                    Ein einfacher, kleiner KĂ€fer (Read-Only Diagnose-Daemon / CLI-Inspector).
                    Er hat KEINE Schreibmacht, keine Root-Keys, kein `DROP TABLE`.
                    Er krabbelt ĂŒber Tor, TĂŒr, BrĂŒcke und Wurzel und meldet leise:
                    "Etwas reibt leicht — MAC in NetBox fehlt / Cert lĂ€uft in 9 Tagen ab /
                     Qdrant-Collector hinkt 1 Push hinterher."

5.2 MAC / IP / Vektor-Topologie im VPN (Wer lebt wo im Rust-Plan?)

Damit im VPN und in den lokalen RÀumen niemand raten muss, bindet der Rust-Build jede Vektor-Wurzel und jeden KI-Dienst hart an seine Loopback- oder WireGuard-/LAN-IdentitÀt (IP + NetBox-MAC) (dcim/mac-addresses/ -> netbox_devices-Spiegel):

+=========================================================================================+
|             VPN- & LOKAL-NETZPLAN: VEKTOREN, OLLAMA & CA-BINDUNG (MAC / IP)             |
+=========================================================================================+

  +-------------------------------------------------------------------------------------+
  | KNOTEN 1: NULLFELD (WireGuard-Hub `10.42.0.1` / `194.164.194.191`)                  |
  | Rolle: Der gesprĂ€chige KrĂŒmel-Chat & Gitea-Ursprung                                 |
  |-------------------------------------------------------------------------------------|
  | * WireGuard `wg0`   : 10.42.0.1/24 (Port 51820/udp — DAS TOR)                       |
  | * Qdrant (Vektor 1) : 127.0.0.1:6333 (NUR lokal / Tunnel! Collection:               |
  |                       `docs_crumbforest`, gespeist aus lokalem Gitea-Bare)          |
  | * MariaDB (TLS-Gate): 127.0.0.1:3306 / Unix-Socket (`tlsgate_app`)                  |
  | * questions-core    : 127.0.0.1:8443 -> spricht plain-HTTP im geschĂŒtzten           |
  |   (Rust/Axum)         Tunnel/Loopback mit Qdrant & Ollama (kein TLS-Ballast im WG)  |
  +-------------------------------------------------------------------------------------+
                                           ^
                                           | WireGuard-BrĂŒcke (10.42.0.x)
                                           v
  +-------------------------------------------------------------------------------------+
  | KNOTEN 2: BACKBONE (`87.106.12.97` / Alias: strato-eins)                            |
  | Rolle: Das ACID-GedÀchtnis der Personas & Checkmk-WÀchter                           |
  |-------------------------------------------------------------------------------------|
  | * PostgreSQL+pgvector: 127.0.0.1:5432 -> DB `crumbforest_db`, Tabelle               |
  |   (Vektor 2)           `forest_memory` (Personas: DeepBit, FunkFox, CapaciTobi...)  |
  | * Grundsatz          : Strikt getrennt von nullfeld-Qdrant! (`zwei-vektor-          |
  |                        gedaechtnisse.md` — niemals auf nullfeld psql suchen!)       |
  +-------------------------------------------------------------------------------------+
                                           ^
                                           | Client-initiierter Sync (Zero/Container ruft)
                                           v
  +-------------------------------------------------------------------------------------+
  | KNOTEN 3: WALD-CONTAINER / BAUMHAUS / CREW-KISTEN (Lokal & Offline-First)           |
  | (`crumbdesktop` 10.42.0.52 | `m4-laptop` 10.42.0.10 | `cruncher` 192.168.1.10       |
  |  `snakeview` 192.168.1.180 | `deepsea` 192.168.1.202 | `crumbzero00/01`)            |
  |-------------------------------------------------------------------------------------|
  | * IdentitÀts-Anker  : (device_id, primary_ip, primary_mac_address) aus              |
  |                       lokalem `netbox_devices`-Spiegel + Container-CA-Cert!         |
  | * Lokales Ollama    : 127.0.0.1:11434 (`nomic-embed-text` 768d, `gemma:2b`)         |
  | * Lokales Qdrant    : 127.0.0.1:6333 (`KernelCrumb_v0` / `ozmai_chunks`)            |
  | * Hörraum / Audio   : Lokal auf M4 gerendert (Bugsy, Eule, FunkFox, DeepBit)        |
  | * Lokale Sensorik   : Pose-Pipeline / Hailo / MQTT (`cruncher` 192.168.1.10:1883)   |
  |                       -> GeschĂŒtzt durch die LOKALE CONTAINER-CA (Slot 4: `'ca'`)   |
  +-------------------------------------------------------------------------------------+

Warum MAC + IP + CA-Zertifikat zusammengehören („Verbinde dich mit deinem Fußabdruck“)

In einer normalen Cloud zĂ€hlt nur ein Bearer-Token — wer es kopiert, ist drin.
Im Wald (Container & OZM-Museum) prĂŒfen wir dreistufig (Wurzelschutz):
1. Die Spur im Boden (MAC & LAN/WG-IP): Steht das GerÀt (snakeview, cruncher, blackbox, crumbzero00) mit seiner echten Hardware-MAC (dcim/mac-addresses/ in NetBox) und IP im lokalen netbox_devices-Spiegel auf status = active?
2. Der SchlĂŒssel unter der BrĂŒcke (Container-CA / Slot 4): Hat das GerĂ€t ein von der lokalen Container-CA signiertes Client-/Node-Zertifikat, dessen CommonName / SAN exakt zu diesem NetBox-Eintrag passt?
3. Die Passkante (passkante.rs): Selbst mit gĂŒltigem Zertifikat darf ein Kamera-Node (snakeview) niemals Roh-Videos aus dem Container ins RZ schieben — nur Bewegungs-Vektoren im Raum, und ĂŒber die BrĂŒcke nur signierte Quittungen.


5.3 Der konkrete Rust-Workspace: Wie tlsgate-core gebaut wird

Genauso wie OZM_Nullfeld_v1 heute schon questions-core und missions-core unter #![forbid(unsafe_code)], lto = true, strip = true baut, gliedert sich der Rust-Build fĂŒr TLS-Gate + Wald-CA + Bugsy:

tlsgate-rs/ (Cargo Workspace — Edition 2024, unsafe_code = "forbid", 2-4 MB static binary)
|
├── crates/
|   ├── tg-crypto/          # 1:1 BinĂ€r-Zwilling von Secrets.php
|   |   ├── kdf.rs          # Blake2b KDF (context = "TLSGATE1", subkey_id = key_id*100 + slot)
|   |   ├── aead.rs         # XChaCha20-Poly1305 ("tg1:" Format + AD "tg1|<purpose>|<bind>")
|   |   └── secret_box.rs   # ZeroizeOnDrop Wrapper (ersetzt SoapCredential/NetBoxCredential)
|   |
|   ├── tg-ca/              # NEU: Die lokale Container- & Museums-CA (Slot 4: 'ca')
|   |   ├── root_ca.rs      # Erzeugt/öffnet lokalen CA-Key (versiegelt mit tg-crypto Slot 4)
|   |   ├── leaf_cert.rs    # Signiert Kurzzeit-Certs fĂŒr Nodes/Sensoren (rcgen / x509-cert)
|   |   └── footprint.rs    # Bindet Cert an NetBox-(Name, IP, MAC) -> "Fußabdruck-Beweis"
|   |
|   ├── tg-mirror/          # Fail-Closed Spiegel (NetBox, Registrar, Vektor-Status)
|   |   ├── netbox.rs       # Zieht Devices + dcim/mac-addresses (mit >50% Mass-Gone Breaker)
|   |   ├── inventory.rs    # SOAP/Registrar-Bestand (mit 2000er Limit-Guard & Paging)
|   |   └── vector_sync.rs  # PrĂŒft lokalen Stand von Ollama (11434), Qdrant (6333), pgvector (5432)
|   |
|   ├── tg-gate/            # Tor, TĂŒr & Passkante (Reine Funktionen ohne I/O!)
|   |   ├── guard.rs        # Port von Guard::decide() + Rollen-Matrix (readonly..admin)
|   |   ├── totp.rs         # RFC 6238 TOTP + Atomarer Replay-Schutz (WHERE totp_last_step < $1)
|   |   └── passkante.rs    # Was darf im Container bleiben, was darf ĂŒber die BrĂŒcke?
|   |
|   └── tg-bugsy/           # 🐞 Bugsy: Der einfache KĂ€fer auf der alten BrĂŒcke
|       ├── crawl.rs        # Read-Only PrĂŒfgang ĂŒber Tor (UFW/WG), TĂŒr (Certs), Baum (Vektoren)
|       └── whisper.rs      # Kein LĂ€rm, kein Pager-Panikmodus: "Etwas reibt leicht – schau mal hier"
|
└── bins/
    ├── tg                  # CLI-Binary (ersetzt bin/tg, bin/*_cli.php, TLS-node-doktor.bash)
    └── tlsgate- daemon     # Axum-HTTP/mTLS-Server (ersetzt PHP-FPM Pool hinter Nginx/Apache)

5.4 Bugsy (🐞) im Einsatz: Warum ein „einfacher KĂ€fer" besser schĂŒtzt als ein Wachhund

In klassischen IT-Systemen baut man laute Überwachungs-Agenten mit Root-Rechten, die ĂŒberall hineinfassen und bei jedem Wackler rote Alarme feuern (und wenn crumbmaster / der Pi400 oder deepsea wegen geteiltem Strom bewusst ausgeschaltet sind, dreht das Monitoring durch).

Im Crumbforest ist Bugsy (crew.rs: „Zeig mal, wir schauen gemeinsam“ / Nullfeld-Reaktion: „Etwas reibt leicht – ich kann es zeigen, wenn du willst.“) der Gegenentwurf:

+-----------------------------------------------------------------------------------------+
|                   🐞 BUGSY AUF DER ALTEN BRÜCKE (`tg bugsy` / `tg-bugsy`)               |
+-----------------------------------------------------------------------------------------+
|                                                                                         |
|  EIGENSCHAFTEN VON BUGSY:                                                               |
|  1. Winzig & friedlich : Nur Lese-Rechte (`readonly`), öffnet NIEMALS Slot 2/4/5 Keys.  |
|  2. Kennt die Stille   : Weiß aus dem Spiegel, dass `crumbmaster` (Pi400) oder          |
|                          `deepsea`/`snakeview` (Strom-Wechsel) schlafen dĂŒrfen.         |
|                          Offline != kaputt!                                             |
|  3. Krabbelt 4 Orte ab :                                                                |
|                                                                                         |
|     [Am TOR]    -> Steht `ufw` / `nftables` VOR den Diensten?                           |
|                    Lauschen Qdrant (`:6333`), Postgres (`:5432`) und Ollama (`:11434`)  |
|                    wirklich NUR auf `127.0.0.1` / `wg0` (`10.42.0.x`)?                  |
|                                                                                         |
|     [An der TÜR]-> Stimmt `/var/lib/tlsgate/app.manifest` (SHA-256)?                    |
|                    Passen die MAC-Adressen im ARP-Tisch der Container-BrĂŒcke zu den     |
|                    eingetragenen `dcim/mac-addresses` im lokalen NetBox-Spiegel?        |
|                                                                                         |
|     [Auf der    -> Wann war der letzte Delta-Abgleich zum `nullfeld`?                   |
|      BRÜCKE]       Liegen unversendete Quittungen (`outbox` / `receipt.rs`) bereit?     |
|                    LĂ€uft ein Registrar- oder Container-CA-Zertifikat bald ab?           |
|                                                                                         |
|     [An der     -> Antwortet lokales Ollama (`127.0.0.1:11434`) mit `nomic-embed-text`? |
|      WURZEL]       Sind die zwei Vektor-GedÀchtnisse sauber getrennt                    |
|                    (`nullfeld` = Qdrant `docs_crumbforest` vs.                          |
|                     `backbone` = pgvector `forest_memory`)?                             |
|                                                                                         |
|  AUSGABE VON BUGSY (Terminal / Hörraum-Stil):                                           |
|  -------------------------------------------------------------------------------------  |
|  $ tg bugsy                                                                             |
|  🐞 [TOR]     wg0 (10.42.0.52) steht. Qdrant & Ollama lauschen nur lokal (127.0.0.1).   |
|  🐞 [TÜR]     Alle 5 SchlĂŒssel-Slots (key_id=1) konsistent. 0 Replay-Races.             |
|  🐞 [BRÜCKE]  Container lĂ€uft seit 14h autark (offline). 3 Receipts warten geduldig.    |
|  🐞 [BAUM]    Lokales Qdrant (KernelCrumb) wach.                                        |
|  🐞 [REIBUNG] Etwas reibt leicht: `blackbox` (192.168.1.168) hat im NetBox-Spiegel      |
|               noch keine primary_mac_address (NetBox 4.x dcim/mac-addresses Gotcha).    |
|               Zeig mal, wir schauen gemeinsam, wenn du Zeit hast.                       |
+-----------------------------------------------------------------------------------------+

5.5 Der komplette Lebenszyklus einer Kinderfrage (Vom Hörraum bis zur Wurzel & zurĂŒck)

Zum Abschluss: Warum wir diesen ganzen Aufwand mit PHP-Vorarbeit $\rightarrow$ Rust-Core $\rightarrow$ Container-CA $\rightarrow$ MAC/IP-Spiegel ĂŒberhaupt treiben. Damit genau dieser Weg einer Frage zu 100 % geschĂŒtzt, lokal und frei bleibt:

   [Ein Kind im Container / Baumhaus / Hörraum stellt eine Frage]
   "Wie merkt sich der Wald eigentlich unsere Geschichten, ohne uns auszuspionieren?"
                                  |
                                  v
  +-----------------------------------------------------------------------+
  | 1. DIE TÜR (Container-CA & Fußabdruck)                                |
  |    Das Terminal im Raum spricht ĂŒber das lokale Container-Zertifikat  |
  |    (Slot 4 `'ca'`, gebunden an die MAC/IP des Raum-Nodes).            |
  |    Kein fremder Server im Internet sieht, dass gefragt wurde.         |
  +-----------------------------------------------------------------------+
                                  |
                                  v
  +-----------------------------------------------------------------------+
  | 2. DIE PASSKANTE (`passkante.rs` / `Guard::decide()`)                 |
  |    PrĂŒft: EnthĂ€lt die Anfrage persönliche Daten / Kamera-Rohbilder?   |
  |    Rohdaten bleiben hart im Raum. Nur die reine Frage geht an den     |
  |    lokalen Baum.                                                      |
  +-----------------------------------------------------------------------+
                                  |
                                  v
  +-----------------------------------------------------------------------+
  | 3. DER LOKALE BAUM (Ollama `127.0.0.1:11434` + Qdrant `127.0.0.1:6333`)|
  |    - `nomic-embed-text` berechnet lokal den 768d-Vektor der Frage.    |
  |    - Lokales Qdrant / `pgvector` findet die passende Rinde aus dem    |
  |      `CrumbCodex` und dem `OZM-Keks-Handbuch`.                        |
  |    - Bugsy, Eule oder FunkFox antworten (im Hörraum mit den lokal     |
  |      auf dem M4 geklonten Stimmen).                                   |
  |    - Kosten: 0,00 € · Cloud-AbhĂ€ngigkeit: 0 % · Die 0 gewinnt!        |
  +-----------------------------------------------------------------------+
                                  |
                                  v
  +-----------------------------------------------------------------------+
  | 4. DIE ALTE BRÜCKE (Wenn spĂ€ter wieder WireGuard zum Nullfeld steht)  |
  |    Nur eine anonyme, kryptographisch signierte Quittung (`receipt.rs`)|
  |    oder eine kuratierte Tagesrinde wandert ĂŒber `wg0` (`10.42.0.1`)   |
  |    ins `nullfeld`, damit der gemeinsame Wald weiterwÀchst.            |
  +-----------------------------------------------------------------------+

6. Die NIS2-/BSI-Erkenntnis: Warum PHP im RZ der König bleibt — und Rust eine reine VPN-/Raum-TUI (#cli) ist

Erkenntnis nach den ersten erfolgreichen Live-Tests gegen die echte DB & dem backbone_doktor.sh-Check (19.10.2026):
Im Rechenzentrum (RZ) unter BSI-Grundschutz und NIS2 (gerade bei DNS-, Zertifikats- und VPN-nahen Diensten) wirft ein ungewohnter Rust + Tokio + Nginx-Proxy-Stack sofort hunderte Compliance- und Zertifizierungsfragen auf.
Ein gehaertetes Native-PHP + Apache + MySQL/MariaDB-Setup dagegen ist auf jedem klassischen UNIX/Linux-Unterbau (Debian, Gentoo, Arch, FreeBSD) seit Jahrzehnten zertifizierbar, vom BSI verstanden und durch die TLS-Gate-HĂ€rtung (Secrets.php, auth_socket, Append-Only-Trigger, SHA-256-Manifest) auf modernstem Niveau („Newschool PHP").

Damit klĂ€rt sich auch endgĂŒltig die Frage aus OZM_Nullfeld_v1 (Was ist Server, was ist Host, was ist Client?):

6.1 Die 6 goldenen Gesetze fĂŒr die Rust-App (tg-tui / Raum-CA)

Eine Rust-App wird nicht als öffentlicher Webserver ins RZ gestellt, sondern:
1. Macht nur im Terminal Sinn (#cli / TUI): Ein interaktives, schnelles Terminal-Cockpit (im Stil von lazydocker / ratatui — Weiterentwicklung von bin/tg-dash + Bugsy 🐞).
2. Darf NUR im VPN / lokalen Raum funktionieren: Bindet ausschließlich auf Loopback (127.0.0.1) oder das WireGuard-/Raum-Interface (10.42.0.x), niemals auf 0.0.0.0 im öffentlichen Netz.
3. Erlaubt NUR bekannte oder gelesene MAC-Adressen: Jedes GerÀt im lokalen Raum muss mit seiner echten Hardware-MAC (dcim/mac-addresses aus dem gelesenen NetBox-Spiegel) bekannt sein. Unbekannte MAC = kein Zertifikat, kein Durchgang.
4. Ist eine eigene CA im lokalen Raum-Netzwerk: Verwaltet die lokale Container-/Museums-CA (Slot 4: 'ca') fĂŒr die lokale Sensorik (snakeview, rattlecam, cruncher, crumbzero00/01, lokales Ollama/Qdrant).
5. Wird ĂŒber die Domain-/VPN-CA bestĂ€tigt: Die Raum-CA ist kein wilder Freiflug, sondern kryptographisch ĂŒber die Domain-/VPN-CA (crumbforest.io / onezeromore.com) rĂŒckbestĂ€tigt.
6. Von außen (Internet) komplett unerreichbar: Kein offener Port ins Internet. Der Raum holt sich seinen Spiegel rein lesend (Pull via HTTPS + TLS-Client-Login) aus dem RZ. Null Risiko fĂŒr die VM oder das Bare-Metal im RZ!


6.2 Server · Host · Client: Die endgĂŒltige Rollenteilung (RZ vs. Backbone vs. Wald-Raum)

+=========================================================================================+
| 1. DER SERVER (IM RECHENZENTRUM — BSI / NIS2-KONFORM, PORTABEL: DEBIAN/GENTOO/FREEBSD)  |
|    Domains: `onezeromore.com` (bereits im RZ) & `crumbforest.io` (externer RZ-Test)     |
+=========================================================================================+
|                                                                                         |
|   [Apache 2.4 + NativePHP RC1.0 (`TLS-Gate`) + MySQL/MariaDB (`tlsgate_app`)]           |
|   * Spricht als EINZIGER aktiv SOAP mit dem Registrar (InterNetX/AutoDNS).              |
|   * HĂ€lt die kanonische DB, das Append-Only `audit_log` und die Domain-Zertifikate.     |
|   * Bietet nach außen NUR eine gehĂ€rtete HTTPS-Kante (mit TLS-Login / mTLS) an,         |
|     ĂŒber die berechtigte RĂ€ume ihre JSONs / Spiegel-Daten LESEND abholen können.        |
|   * KEIN Risiko fĂŒr VM oder Bare-Metal im RZ: Vom Container/VPN kommt kein Schreib-     |
|     durchgriff und kein offener Proxy-Dienst ins RZ hinein!                             |
|                                                                                         |
|   +---> [BORGMATIC ARCHIV ("Alter Wald")]                                               |
|         Ein alter Wald wird nie ĂŒberschrieben — er wird von Borgmatic verschlĂŒsselt     |
|         gepflegt und bleibt NUR LESBAR, solange man den SchlĂŒssel trĂ€gt.                |
|         Jeder aktive Aufbau ist immer ein frischer, neuer Wald.                         |
+=========================================================================================+
                                             ^
                                             | NUR LESENDE VERBINDUNG (HTTPS + TLS-Login)
                                             | LĂ€dt JSON-Spiegel (Inventar, NetBox, Certs)
                                             | (Kein Schreibzugriff ins RZ!)
                                             |
+============================================|============================================+
| 2. DER HOST / BRÜCKENPFEILER (`backbone` 87.106.12.97 & `nullfeld` 194.164.194.191)     |
|    GeprĂŒft mit `backbone_doktor.sh` (Debian 12, UFW: 22/80/443, Fail2ban, 9x LE-Certs)  |
+=========================================================================================+
|                                                                                         |
|   * `backbone` (87.106.12.97):                                                          |
|     - TrÀgt `crumbforest.io`, `seeds.crumbforest.io` (NetBox), `chat`, `monitor`, `rkl` |
|     - HÀlt das ACID-GedÀchtnis (`PostgreSQL + pgvector`).                               |
|     - Hinweis aus Doktor-Lauf: `www.crumbforest.io` (CNAME) & `lynis` File-Integrity    |
|       (= genau das, was `TLS-app-scan.bash` fĂŒr TLS-Gate bereits löst!).                |
|                                                                                         |
|   * `nullfeld` (194.164.194.191 / `wg0` 10.42.0.1):                                     |
|     - WireGuard-Hub & Gitea-Ursprung + Qdrant (`docs_crumbforest`).                     |
+============================================|============================================+
                                             ^
                                             | WireGuard-VPN (10.42.0.x) + Domain-VPN-CA
                                             | Von außen (Internet) NICHT erreichbar!
                                             |
+============================================|============================================+
| 3. DER CLIENT & LOKALE RAUM-WÄCHTER (DIE RUST-APP IM CONTAINER / OZM-MUSEUM)            |
|    Genau hier (und NUR hier!) lebt das Rust-Binary (`ratatui` / `#cli` lazydocker-UI)   |
+=========================================================================================+
|                                                                                         |
|  +-----------------------------------------------------------------------------------+  |
|  | 🩀 RUST TUI (`tg-tui` — im Stil von `lazydocker` fĂŒr die Crew im Raum)            |  |
|  |-----------------------------------------------------------------------------------|  |
|  | [1: Raum-CA & Certs]   [2: Bekannte MACs (ARP <-> NetBox)]   [3: RZ-JSON-Spiegel] |  |
|  | [4: Lokale Vektoren (Ollama/Qdrant)]        [5: 🐞 Bugsy Diagnose & Borg-Stand]   |  |
|  +-----------------------------------------------------------------------------------+  |
|         |                                        |                            |         |
|         v                                        v                            v         |
|  [MAC-Gatekeeper]                     [Lokale Raum-CA (Slot 4)]     [Lesender Abruf]    |
|  PrĂŒft jede lokale Verbindung         BestĂ€tigt durch die           Zieht per HTTPS +   |
|  gegen die aus NetBox gelesenen       Domain-VPN-CA; stellt         TLS-Login die       |
|  MAC-Adressen (`dcim/mac-addresses`). Kurzzeit-Zertifikate nur      aktuellen JSONs     |
|  Unbekannte MAC -> Blockiert!         fĂŒr bekannte Raum-Sensoren    aus dem PHP-Core    |
|                                       aus (`snakeview`, `zero00`).  im RZ.              |
+=========================================================================================+

6.3 Wie das lazydocker-artige Rust-Terminal (tg-tui) im Raum aussieht

Statt einer weiteren Web-OberflĂ€che, die man wieder absichern und zertifizieren mĂŒsste, startet die Crew im VPN oder direkt im Container das statische Rust-Binary im Terminal:

+-----------------------------------------------------------------------------------------+
| đŸŒČ🩀 Crumbforest // OZM Raum-Konsole (tg-tui v0.1)     [VPN: wg0 10.42.0.52] [OFFLINE-OK]|
+-----------------------------------+-----------------------------------------------------+
| [1] đŸ›ïž RZ-Spiegel (Read-Only)     | 📡 AKTIVER BEREICH: [2] LOKALE RAUM-CA & MAC-GATE   |
|     onezeromore.com : OK (TLS)    |                                                     |
|     crumbforest.io  : OK (TLS)    | Aussteller : Container-CA Waldmitte (Slot 4 sealed) |
|     Letzter JSON-Pull: vor 12m    | BestĂ€tigt  : Domain-VPN-CA (crumbforest.io) ✓       |
|     Borgmatic-Wald  : 61 StĂ€nde   | Außenport  : KEINER (0.0.0.0 geschlossen) ✓         |
+-----------------------------------+-----------------------------------------------------+
| [2] 🔐 Raum-CA & MAC-WĂ€chter  <-- | GERÄT         IP             MAC (NetBox)     CA-ST |
|     Bekannte MACs   : 18 gelesen  | --------------------------------------------------- |
|     Aktive Raum-Certs: 7 gĂŒltig   | cruncher      192.168.1.10   aa:bb:cc:..:01   ✅ OK |
|     Abgewiesene MACs: 0           | snakeview     192.168.1.180  aa:bb:cc:..:02   ✅ OK |
+-----------------------------------+ deepsea       192.168.1.202  aa:bb:cc:..:03   đŸ’€ AUS|
| [3] 🧠 Lokaler Baum (Wurzel)      | crumbmaster   192.168.1.166  aa:bb:cc:..:04   đŸ’€ AUS|
|     Ollama (127.0.0.1:11434): ON  | crumbzero00   192.168.1.201  aa:bb:cc:..:05   ✅ OK |
|     Qdrant (127.0.0.1:6333) : ON  | blackbox      10.42.0.51     (fehlt in NB!)   ⚠ REIB|
+-----------------------------------+-----------------------------------------------------+
| [4] 🐞 Bugsy (Alte BrĂŒcke)        | 🐞 BUGSY SAGT:                                      |
|     backbone (87.106.12.97):      | "Im RZ lÀuft PHP stabil unter Apache/MySQL (NIS2-   |
|     - 9/9 LE-Certs gĂŒltig (35-79d)|  sauber). Unser Raum hat vor 12 Min. die neuesten   |
|     - UFW + fail2ban aktiv        |  JSONs lesend geholt. `www.crumbforest.io` auf      |
|     - www.crumbforest.io CNAME    |  backbone zeigt noch auf den Domainnamen statt IP." |
+-----------------------------------+-----------------------------------------------------+
| [r] Read-Only Pull vom RZ   [c] Raum-Cert fĂŒr bekannte MAC erneuern   [b] Bugsy   [q] Ende |
+-----------------------------------------------------------------------------------------+

Fazit dieser Architektur-Entscheidung:

  1. Im RZ (und auf Strato): Das Native-PHP RC1.0 (TLS-Gate) auf Apache + MySQL bleibt das produktive, BSI-/NIS2-taugliche Fundament — portabel von Debian ĂŒber Gentoo und Arch bis FreeBSD. Es verwaltet die echten Registrar-SOAP-Calls, den Katalog und die DB.
  2. Zwischen Raum und RZ: Nur eine einzige, lesende HTTPS-Verbindung mit TLS-Login holt die JSON-Spiegel in den Container oder das OZM-VPN. Das RZ-System ist dadurch zu 100 % vor RĂŒckwirkungen aus den Experimentier- und Museums-RĂ€umen geschĂŒtzt.
  3. Im Wald / Container / VPN: Rust (OZM_Nullfeld_v1 / tg-tui) spielt seine StĂ€rke genau dort aus, wo es unschlagbar ist: als einzelnes, statisches Terminal-Werkzeug (#cli ala lazydocker) und lokaler Raum-WĂ€chter, der nur bekannte MAC-Adressen reinlĂ€sst, die lokale Raum-CA (bestĂ€tigt durch die Domain-VPN-CA) fĂŒhrt und von außen unsichtbar bleibt.
  4. Borgmatic & der ewige Wald: Ein alter Wald wird niemals kaputtgepatcht — solange Borgmatic ihn pflegt und der SchlĂŒssel existiert, bleibt er als Geschichte lesbar, wĂ€hrend daneben immer ein sauberer neuer Wald wachsen darf. đŸŒČ🩀🐞

7. Nach 24 Monden Vision auf dem Parkplatz: ninja.sh, container01.crumbforest.org & die PoliversitÀt

„Auf dem Parkplatz des OZM HAMMERBROOKLYN Exponats stehen zwei 40-Fuß-Container. Doch sie sind keine leeren HĂŒllen. Sie sind bereits jetzt aktiv, mit derselben schweren TĂŒr wie das OZM HAMMERBROOKLYN Exponat selbst 
 Hier beginnt die Zukunft – nicht im Kopf, sondern auf dem Parkplatz.“
— Crumbforest – Die PoliversitĂ€t der Zukunft steht schon da

Mit deinem Mondzeit-Script ninja.sh (ninja-dashboard.html), dem Live-Snapshot von backbone und der Rolle von container01.crumbforest.org laufen jetzt alle FĂ€den aus 24 Monden in ein einziges, widerspruchsfreies Bild zusammen.

7.1 Was der ninja.sh-Lauf auf backbone (2026-10-19 17:12:21) beweist

Dein ninja.sh verkörpert exakt dieselbe Philosophie wie TLS-Gate und Bugsy 🐞:
1. Capability Probing statt Distro-Raten (probe()): PrĂŒft Werkzeuge und Pfade (systemctl vs. rc-service, apt vs. pacman/emerge), nicht Marketing-Namen.
2. Terminal-Selbstschutz (clean()): Filtert Steuerzeichen aus User-Agent und Request-Pfad, damit kein Angreifer ĂŒber Log-Injection das Admin-Terminal kapert.
3. Read-Only + Guardrail (is_self()): Erkennt automatisch deine eigene SSH-IP (77.3.8.154) und alle lokalen Server-IPs (127.0.0.1, 87.106.12.97, 2a02:...), damit man sich im Gefecht niemals selbst aussperrt, und gibt Kommandos nur als Copy-Paste-Vorschlag fĂŒr die 2. Shell aus.
4. Live-Befund auf backbone:
* Load bei 0.11, 27,8 GiB RAM frei, Platte zu 89 % frei, 0 hÀngende SQL-Queries.
* Im Web-Log (0.0 req/s Grundrauschen) sieht man sofort die ĂŒblichen .env/wp-admin-Scanner (34.34.160.116) und die akademischen Security-Scanner der Ruhr-Uni Bochum (winston/finn/goose.softsec.ruhr-uni-bochum.de), die sauber an 401 (397x) und 444 abprallen.


7.2 Physische PrĂ€senz als SchlĂŒssel: Warum container01.crumbforest.org nur von innen aufgeht

Das ist der entscheidende Punkt, der die PoliversitĂ€t auf dem Parkplatz (die zwei 40-Fuß-Container mit derselben schweren TĂŒr wie das OZM-Exponat) mit der Kryptographie verbindet:

Wer mit dem Raum sprechen will, muss physisch vor Ort sein — durch einen Besuch im Container, im OZM-Museum oder ĂŒber einen dort verbauten Raspi Zero (crumbzero00, crumbzero01). Von außen (aus dem offenen Internet) existiert kein Weg hinein.

+=========================================================================================+
|          PHYSISCHE PRAESENZ ALS SCHLUESSEL: DER 40-FUSS-CONTAINER AUF DEM PARKPLATZ     |
|                     (`container01.crumbforest.org` — #lokal)                            |
+=========================================================================================+

   [OFFENES INTERNET]
           |
           x  <--- KEIN OFFENER PORT! (Weder HTTP noch SSH noch API von aussen erreichbar)
           |
+==========|==============================================================================+
|  DIE SCHWERE TUER (Physischer Raum: Container 1 & 2 / OZM Museum / Raspi Zero vor Ort)  |
+=========================================================================================+
           |
           |  Besucher / Kind / Crew steht ECHT im Raum (oder Raspi Zero im OZM-Raum)
           v
  +-------------------------------------------------------------------------------------+
  | 1. SCHICHT: HARDWARE-FUSSABDRUCK (ARP / MAC-WĂ€chter <-> Ansible + NetBox)           |
  |    - Ansible funkt mit NetBox (`seeds.crumbforest.io`) und hÀlt die Liste           |
  |      der erlaubten MAC-Adressen (`dcim/mac-addresses`) synchron.                    |
  |    - Taucht am Switch / WLAN im Container eine NEUE, UNBEKANNTE MAC-Adresse auf:    |
  |      +---> SOFORT BLOCKIERT (Kein Cert, kein Route-Zugriff)                         |
  |      +---> MONITORING -> ALARM (Checkmk / Ninja-Shield / Bugsy 🐞 meldet Fremd-MAC) |
  +-------------------------------------------------------------------------------------+
           |
           |  (MAC ist bekannt & in NetBox als Teil des Raums verifiziert)
           v
  +-------------------------------------------------------------------------------------+
  | 2. SCHICHT: `container01.crumbforest.org` (Lokales Tor / TĂŒr / SchlĂŒssel)           |
  |    - Nginx + Rust/Tokio-Proxy + Lokale Raum-CA (`#lokal`)                           |
  |    - Stellt die Verbindung zu den lokalen Raumfahrt-/Roboter-Systemen,              |
  |      zum lokalen `ttyd` / `ninja-dashboard` und zum lokalen RAG her.                |
  |    - BestÀtigt durch die Domain-VPN-CA, aber 100% autark lauffÀhig (Offline-First). |
  +-------------------------------------------------------------------------------------+
           |
           |  Kind baut Roboter / bewegt Sensor / stellt Frage -> Datenspur entsteht lokal
           |  Roboter zieht spÀter als Kunst ins OZM-Exponat ein!
           v
  +-------------------------------------------------------------------------------------+
  | 3. SCHICHT: BEIM NÄCHSTEN ONLINE-FENSTER (Client-initiierter Sync zum RZ / Nullfeld)|
  |    - `container01.crumbforest.org` meldet sich von innen heraus mit seinem Update:  |
  |      +---> Holt lesend neue JSONs / Certs vom PHP-Core im RZ (`onezeromore.com` /   |
  |            `crumbforest.io`) ĂŒber HTTPS + TLS-Client-Login.                         |
  |      +---> Schiebt signierte Lern-/Resonanz-Spuren (ohne Personen-Profile!)         |
  |            und falls eine fremde MAC geklopft hat: den Sicherheits-Event.           |
  +-------------------------------------------------------------------------------------+

7.3 Wie alle Schnipsel aus 24 Monden jetzt ineinandergreifen (#nullfeld)

Wenn man heute auf den Tisch schaut, ist kein einziges Werkzeug mehr ein isoliertes EinzelstĂŒck — jedes hat seinen festen Platz in der Kette:

Baustein / Schnipsel Wo er lebt Welche Aufgabe er in der Gesamt-Architektur erfĂŒllt
TLS-NativePHP_v1 (Apache + MySQL) Im RZ (onezeromore.com, crumbforest.io) Das BSI-/NIS2-taugliche HerzstĂŒck fĂŒr Domains, Registrar-SOAP, Katalog, Buchungen und versiegelte tg1:-Secrets.
Borgmatic Im RZ / Backup Pflegt den „alten Wald" verschlĂŒsselt und rein lesbar, wĂ€hrend vorne der neue Wald wĂ€chst.
Ansible + NetBox (seeds.crumbforest.io) Auf backbone $\rightarrow$ alle RĂ€ume Single Source of Truth fĂŒr alle Nodes, IPs und Hardware-MAC-Adressen (dcim/mac-addresses).
backbone_doktor.sh & ninja.sh Auf backbone / jedem Linux-Host Read-Only Triage & Gesundheits-Spiegel in Echtzeit (mit clean(), is_self() und Copy-Paste-Empfehlungen statt Blindflug).
container01.crumbforest.org (Rust / Tokio / Nginx + Raum-CA) Lokal im 40-Fuß-Container / OZM-Museum Die schwere TĂŒr vor Ort: LĂ€sst nur physisch Anwesende / bekannte Raspi-Zero-MACs rein, schlĂ€gt bei fremder MAC sofort Alarm im Monitoring und synchronisiert sich beim nĂ€chsten Online-Fenster selbststĂ€ndig.
OZM_Nullfeld_v1 & Hörraum Auf nullfeld & lokal im Container (M4 / Zeros) Das lebendige GedÀchtnis (Qdrant / pgvector / Ollama) und die Stimmen der Crew (Bugsy, Eule, FunkFox, DeepBit), die Kinderfragen ohne Cloud-Kosten beantworten.
Ansible-Crumbforest-Rust (#local) Auf der lokalen Crumbforest Ansible-Node / im Raum Der neugeschriebene lokale Prozess: Verbindet die belegbar funktionierenden ansible.builtin-Playbooks (cruncher-tlsgate-env, qdrant, ozm-inbox, wurzelsicherung, vpn-hub) mit einem deterministischen lokalen Rust-Controller (crumb-local) ohne Python-.venv/pynetbox-FragilitÀt.

8. Von Ansible-Crumbforest zu Ansible-Crumbforest-Rust #local (Der neue lokale Prozess)

Nach der Analyse von Ansible-Crumbforest ist klar, was dort auf der Crumbforest Ansible Node belegbar funktioniert – und warum es fĂŒr Ansible-Crumbforest-Rust #local in den neuen lokalen Prozess ĂŒberfĂŒhrt werden muss:

8.1 Warum der alte Prozess (Ansible-Crumbforest) an seine Grenze stieß vs. Der neue lokale Prozess (#local)

+=========================================================================================+
| ALT: `Ansible-Crumbforest` (Zentraler Push + Python/.venv + NetBox-API-Spagat)          |
+=========================================================================================+
|  1. Control-Node brauchte `.venv/bin/python` + `pynetbox` + `netbox.netbox` (3.23).     |
|  2. NetBox 4.2+ / 4.6 Bruch: `mac_address` ist kein Interface-Feld mehr, sondern ein    |
|     eigenes Objekt (`/api/dcim/mac-addresses/`). Deshalb mussten Playbooks wie          |
|     `netbox_sync.yml`, `netbox-raspis.yml`, `netbox-vpn.yml` halb `netbox.*`-Module     |
|     und halb rohe `ansible.builtin.uri`-POSTs mit `jq`/Jinja mischen.                   |
|  3. `credentials/netbox_api_token` lag als Schreib-Token fĂŒr `seeds.crumbforest.io`     |
|     im Playbook-Pfad; `tlsgate-test.yml` zeigte noch auf `TLS-Gate-Mock-Pipeline`.      |
+=========================================================================================+
                                             |
                                             | Transformation in den neuen lokalen Prozess
                                             v
+=========================================================================================+
| NEU: `Ansible-Crumbforest-Rust` (`#local` — Auf der lokalen Crumbforest Ansible-Node)   |
+=========================================================================================+
|  1. DREIKLANG DER WERKZEUGE (Kein `.venv`/`pynetbox`-Krampf mehr!):                     |
|     * 🐚 BASH (`scripts/crumbconnect.sh`, `inventar.sh`, `ninja.sh`, `bend.sh`):        |
|          Die lesbare Wurzel vor Ort („Computer ohne Maus/Klick", Capability-Probing).   |
|     * 📜 ANSIBLE (`playbooks/*.yml` — NUR `ansible.builtin.*`!):                        |
|          Die auf der Ansible-Node belegbar funktionierenden Host-VertrÀge mit           |
|          Vorher/Nachher-Gegenprobe (`--check --diff`), die kein fremdes Python-Modul    |
|          auf den Zielknoten (`cruncher`, `deepsea`, `snakeview`, `zeros`) verlangen.    |
|     * 🩀 RUST (`crumb-local` Binary in `Ansible-Crumbforest-Rust`):                     |
|          Der deterministische lokale WĂ€chter & Orchestrator im Raum:                    |
|          - PrĂŒft `Wenn eine MAC piepst` (`OBSERVED_PHYSICAL_DEVICE` vs. `NETBOX_RECORD`)|
|          - Liest den `TLS-Gate` `DeviceMirror` (Read-Only Pull via `tg1:` / mTLS)       |
|          - Spricht NetBox 4.6 nativ (2-Stufen-MAC-Modell + `/32` WireGuard-Interfaces)  |
|          - Erzwingt den Tokio-Serialisierungs-Kanon (`1 Writer`, `sync_all()`).         |
+=========================================================================================+

8.2 Die 6 belegbar funktionierenden SĂ€ulen aus Ansible-Crumbforest, die in Ansible-Crumbforest-Rust #local ĂŒbernommen werden

Aus dem bestehenden Repo sind diese 6 Playbook-/Script-Ketten der harte, funktionierende Kern, der im neuen lokalen Prozess erhalten und durch das lokale Rust-Binary (crumb-local) zusammengehalten wird:

  1. 00_doktor.yml + inventar.yml (Schnecki-Prinzip: Erst lesen, nie blind schreiben):
  2. PrĂŒft Uptime, Disk, RAM, wg show wg0, UFW, Fail2ban, Gitea, Qdrant, Ollama und sammelt auf allen Linux-KrĂŒmeln (crumbforest + ozm_linux) reale Hardware-, Disk-, RAM-, WG-Pubkey- und MAC-Fakten.
  3. 01_vpn_hub.yml + scripts/crumbconnect.sh (Crumbpage 40 — „Die stille TĂŒr"):
  4. Der Node erzeugt sein SchlĂŒsselpaar lokal (Private Key bleibt im Baum).
  5. Jede VPN-IP im CrumbVPN ist zwingend eine /32 (10.42.0.11/32 deepsea, 10.42.0.12/32 snakeview, 10.42.0.19/32 cruncher, 10.42.0.20/32 crumbzero01). Kein Crossconnect vorab!
  6. 02_cruncher_tlsgate_env.yml (Die lokale / VPN-Umgebung fĂŒr TLS-NativePHP_v1):
  7. Baut auf cruncher (10.42.0.19) die exakte RZ-analoge Umgebung ohne Docker und ohne Reboot:
    • Apache 2.4 (mpm_event + proxy_fcgi), gebunden nur an 127.0.0.1 und wg0 (10.42.0.19) (mit After=wg-quick@wg0.service).
    • PHP 8.4 FPM (packages.sury.org gepinnt auf Priority 100/600 + GPG-Fingerprint-PrĂŒfung).
    • MySQL 8.4 LTS nativ (mysql-tlsgate.service auf 127.0.0.1:3306 + auth_socket, GPG-verifiziert).
    • Tag kette: Übernimmt die Vorlagen aus deploy/node/bend.sh aus unserem TLS-NativePHP_v1-Repo und prĂŒft vorher/nachher per Assert, dass das lebende OZM-Exponat (hexapi, mosquitto, influxdb) keine Sekunde unterbrochen wurde!
  8. 03_cruncher_qdrant_musl.yml + qdrant-abschottung.yml (16K-Page-Heilung & Loopback-Schutz):
  9. Heilt den jemalloc-SIGABRT auf dem 16K-Page-Kernel (getconf PAGESIZE = 16384) durch das native aarch64-unknown-linux-musl-Binary unter eigenem System-User qdrant, strikt gebunden an 127.0.0.1:6333 (IPAddressAllow=127.0.0.0/8, IPAddressDeny=any).
  10. 04_ozm_inbox_host.yml (Der Host-Vertrag fĂŒr die Rust-Raum-BrĂŒcke):
  11. Legt User crumb-inbox, /srv/ozm-inbox/{bin,room}, den on-node erzeugten integrity_key_v1 (0600) und /etc/ozm-inbox/export.env an — strikt gebunden an wg0 (10.42.0.19:8790, IPAddressAllow=10.42.0.0/24, ReadOnlyPaths=/srv/ozm-inbox/room).
  12. 05_wurzelsicherung.yml (Die Quellen sichern, nicht das Abgeleitete):
  13. Sichert die echten Quellen (pg_dump -Fc auf backbone, gitea-repositories + mysqldump auf nullfeld sowie die maschinen-eigenen Pfade) mit SHA256SUMS ĂŒber den lokalen Knoten auf mindestens zwei Ziele inklusive Off-Site (deepsea im OZM) und meldet am Ende ungeschönt die Off-Site-Wahrheit.

8.3 Die komplette lokale Prozesskette in Ansible-Crumbforest-Rust #local (ASCII-Ablauf)

So greifen MAC-Piepsen, Rust-Gatekeeper (crumb-local), Ansible-Host-Vertrag und TLS-NativePHP_v1 auf der lokalen Crumbforest Ansible-Node ineinander:

+=========================================================================================+
|        DER NEUE LOKALE PROZESS: `Ansible-Crumbforest-Rust` (#local)                     |
|        Reihenfolge (Crumbpage 40): 1. BASE -> 2. VPN (/32) -> 3. ERINNERN -> 4. BROT    |
+=========================================================================================+

  [SCHRITT 0: WENN EINE MAC PIEPST (Neues oder bekanntes GerÀt im Raum / Hotspot)]
   Axiom 1: IN_HOTSPOT(device)          =/=> ACCESS_GRANT(device)
   Axiom 2: RESOLVES(name)              =/=> REACHABLE(host)
   Axiom 3: NETBOX_RECORD(dev)          =/=> OBSERVED_PHYSICAL_DEVICE(dev)
                                   |
                                   v
  +-------------------------------------------------------------------------------------+
  | 🩀 1. `crumb-local mac-gate` (Rust-Binary auf der lokalen Ansible-Node)             |
  |    - Liest lokale Nachbarschaft (`ip neigh` / Bridge / `wg show wg0 dump`)          |
  |    - Vergleicht gegen den lokalen `TLS-Gate` / NetBox-Spiegel (`netbox_devices`):   |
  |      * FALL A: MAC UNBEKANNT -> Kein WG-Peer, kein Cert, sofortiger                 |
  |                Monitoring-Alarm (`ninja.sh` / Checkmk / Bugsy 🐞)!                  |
  |      * FALL B: MAC BEKANNT & `status=active` -> Freigabe fĂŒr Schritt 2.             |
  +-------------------------------------------------------------------------------------+
                                   |
                                   v
  +-------------------------------------------------------------------------------------+
  | 🐚 2. `crumbconnect.sh` + `01_vpn_hub.yml` (Die stille TĂŒr — Jede IP ist `/32`)     |
  |    - GerÀt erzeugt lokal `/etc/wireguard/wg0.private` (verlÀsst NIE das GerÀt!).    |
  |    - Übergibt nur `PublicKey` + `10.42.0.x/32`.                                     |
  |    - Lokale Ansible-Node fĂŒhrt `ansible-playbook playbooks/01_vpn_hub.yml --check`  |
  |      und danach scharf aus -> Handshake steht (`latest handshake: now`).            |
  +-------------------------------------------------------------------------------------+
                                   |
                                   v
  +-------------------------------------------------------------------------------------+
  | 📜 3. HOST-VERTRÄGE AUSROLLEN (`ansible.builtin.*` mit Exponat-Gegenprobe!)         |
  |    - `00_doktor.yml`               -> Read-Only Puls vor jeder Änderung.            |
  |    - `02_cruncher_tlsgate_env.yml` -> Apache (nur 127.0.0.1 + wg0) + PHP 8.4 +      |
  |                                       MySQL 8.4 + `TLS-NativePHP_v1` (`bend.sh`).   |
  |    - `03_cruncher_qdrant_musl.yml` -> Natives musl-Qdrant (16K-Page safe, Loopback).|
  |    - `04_ozm_inbox_host.yml`       -> `/srv/ozm-inbox` + `integrity_key_v1` (wg0).  |
  |    - Gegenprobe: `hexapi` / `mosquitto` / `influxdb` liefen ohne Unterbrechung!     |
  +-------------------------------------------------------------------------------------+
                                   |
                                   v
  +-------------------------------------------------------------------------------------+
  | 🩀 4. TOKIO-KANON & ERINNERN (`crumb-local netbox-sync` & `inbox-verify`)           |
  |    - Statt fragilem Python-`pynetbox` synchronisiert `crumb-local` direkt gegen     |
  |      NetBox 4.6 (2-Stufen-MAC `/api/dcim/mac-addresses/` + `/32` WG-IP)             |
  |      ODER zieht im Air-Gap-Raum den signierten Read-Only JSON-Spiegel aus dem RZ.   |
  |    - FĂŒr jeden Zero-Node gilt der Tokio-Kanon:                                      |
  |      * Disjunktes `CRUMB_DATA_DIR` pro Instanz (`zero00` != `zero01`)               |
  |      * Genau 1 Tokio-Task besitzt die State-Domain (`inbox + outbox + receipts`)    |
  |      * `DURABLE_LOCAL`: `File::sync_all()` vor jeder HTTP/WG-Quittung!              |
  +-------------------------------------------------------------------------------------+
                                   |
                                   v
  +-------------------------------------------------------------------------------------+
  | 🌰 5. `05_wurzelsicherung.yml` (Quellen sichern -> 2 Orte + Off-Site `deepsea`)     |
  |    - `pg_dump -Fc` + `gitea-repositories` + `mysqldump` + `SHA256SUMS`              |
  |    - Ehrlicher Schlussbericht: Liegt die Kopie wirklich außerhalb des RZ im OZM?    |
  +-------------------------------------------------------------------------------------+