# Architektur ## Überblick Die Erweiterung ist ein **Manifest-V3-Client** ohne eigenen Server. Sie besteht aus vier Kontexten, die über `chrome.runtime`-Nachrichten kommunizieren: ``` ┌───────────────┐ Messages ┌──────────────────────┐ HTTPS/Bearer ┌──────────────────┐ │ popup.html │ ───────────▶ │ background.js │ ───────────────▶ │ OpenNIT-Server │ │ popup.js │ ◀─────────── │ (Service Worker) │ ◀─────────────── │ /api/vault/... │ └───────────────┘ │ - Cache (5 Min) │ └──────────────────┘ ┌───────────────┐ Messages │ - Lock-Gate │ │ content.js │ ───────────▶ │ - Favicon-Cache │ │ (jede Seite) │ ◀─────────── │ - Clipboard-Timer │ └───────────────┘ └──────────┬───────────┘ │ CLIP_WRITE ┌────────▼─────────┐ │ offscreen.html │ (Zwischenablage leeren) └──────────────────┘ ``` ## Komponenten | Datei | Rolle | |-------|-------| | `background.js` | Zentrale Logik: API-Aufrufe, 5-Minuten-Cache, **Lock-Gate**, Favicon-Cache (Data-URLs), Zwischenablage-Timer. Alle Secrets fließen hier durch. | | `content.js` | Wird auf jeder Seite ausgeführt. Erkennt Benutzer-/Passwort-/OTP-Felder (inkl. Shadow-DOM, mehrstufige Logins, segmentierte OTP-Felder), zeigt das Vorschlags-Dropdown und füllt Felder framework-kompatibel (React/Vue/Angular). | | `popup.html` / `popup.js` | Toolbar-Popup: Liste, Suche, Detailansicht, Anlegen + Generator, PIN-Schirm. | | `options.html` / `options.js` | Einstellungen: Server-URL, Token, PIN-Sperrdauer, Zwischenablage. | | `offscreen.html` / `offscreen.js` | Minimaldokument, das ausschließlich die Zwischenablage leert (MV3-konform). | ## Nachrichten (Auszug) | Typ | Von → Nach | Zweck | |-----|-----------|-------| | `CHECK_STATUS` | popup/content → bg | Token prüfen, App-Name/User, `pin_enabled` | | `GET_LOCK` / `DO_UNLOCK` / `LOCK_NOW` | popup → bg | PIN-Sperre abfragen/entsperren/sperren | | `GET_ENTRIES` / `GET_MATCHING_ENTRIES` | popup/content → bg | Einträge (alle / passend zur URL) | | `GET_PASSWORD` / `GET_TOTP` | popup/content → bg | Secret **on demand** | | `GET_FAVICON` | popup/content → bg | Favicon als Data-URL (serverseitig gecacht) | | `VAULT_FILL` | popup → content | Aktives Tab-Formular ausfüllen | | `SCHEDULE_CLIP_CLEAR` | popup/content → bg | Zwischenablage-Leerung planen | ## Server-API (in OpenNIT) Alle Endpunkte unter `/api/vault/extension/` mit `Authorization: Bearer `: - `GET /entries` – Liste (Titel, Benutzer, URL, Notizen, `has_totp`, `favicon_domain`, `has_favicon`) - `GET /entries/{id}/password` – Passwort (protokolliert im Audit-Log) - `GET /entries/{id}/totp` – aktueller TOTP-Code + Restsekunden - `GET /entries/{id}/favicon?fetch=1` – gecachtes Favicon (bei Bedarf serverseitig geholt) - `POST /entries` – neuen Eintrag anlegen - `GET /status` – Token gültig? + `pin_enabled` / `pin_lock_secs` - `POST /unlock` – Tresor-PIN verifizieren + serverseitiges Entsperr-Fenster für den Token setzen - `POST /lock` – Token sofort wieder sperren (Entsperr-Fenster zurücksetzen) - `GET /oauth/authorize` · `POST /oauth/authorize` – SSO-Anmeldung/Zustimmung (Session, PKCE) - `POST /oauth/token` – Authorization-Code- bzw. Refresh-Grant (öffentlich, PKCE) → Access/Refresh - `POST /oauth/revoke` – Refresh-Kette widerrufen (Logout) Details zum SSO-Flow: [`SSO-PLAN.md`](SSO-PLAN.md). Die Erweiterung nutzt SSO über `chrome.identity`; Access-Tokens werden im Hintergrund still per Refresh (mit Rotation) erneuert. ## Lock-Gate (serverseitig erzwungen) Ist für den Nutzer ein **Tresor-PIN** aktiv, liefern die Server-Endpunkte für Einträge/Passwort/TOTP erst nach frischer PIN-Entsperrung Daten (`unlocked_until` pro Token) und antworten sonst mit **HTTP 423**. Der Client spiegelt den Zustand nur (PIN-Schirm) – die eigentliche Durchsetzung liegt im Server, damit ein **gestohlener Token allein wertlos** ist. Der Client hält seinen Entsperr-Status zusätzlich in `chrome.storage.session` (verfällt beim Schließen des Browsers). Die Einstellung „PIN-Sperre" legt nur die Fensterdauer fest; „Bis der Browser geschlossen wird" nutzt ein langes Serverfenster + Client-Sitzungsende. ## Sicherheitsprinzipien - **Kein Remote-Code** – alle Skripte im Paket (MV3-CSP-konform, keine Inline-Skripte). - **Secrets on demand** – Passwörter/TOTP erst bei Nutzung, nie in der Liste. - **Kein persistentes Secret** – nur URL, Token, Einstellungen in `chrome.storage`. - **Server-seitige Krypto** – Ver-/Entschlüsselung im OpenNIT-Server, nicht im Browser.