-- Migration 0016: SSH-Passwort-Zugangsdaten als eigenstaendiges Objekt mit -- eigener ID -- Vorarbeit fuer Teil D.6 Schritt 3 (Umsetzungsauftrag_Sonnet5.md -- D.3): Achse B ("Benutzergruppe x Zugangsdatensatz") braucht fuer alle drei -- Credential-Arten (SSH-Key, RDP, SSH-Passwort) dieselbe Form -- eine -- Freigabetabelle referenziert eine ID, keine host_id. SSH-Keys und (seit -- Migration 0012) RDP-Zugangsdaten haben das bereits; SSH-Passwoerter noch -- nicht (0011_ssh_password_credentials.sql: host_id war PRIMARY KEY, ein -- Datensatz ausschliesslich 1:1 an genau einem Host). -- -- Vorgehen exakt analog zu Migration 0012 (siehe dortiger Kommentar fuer die -- ausfuehrliche Begruendung): alte 1:1-Tabelle bleibt als Datenquelle -- erhalten, wird umbenannt; neues eigenstaendiges Objekt plus 1:1- -- Zuordnungstabelle (bewusst weiterhin PRIMARY KEY auf host_id -- diese -- Migration fuehrt NICHT die Mehrfachzuweisung-an-mehrere-Hosts-UI ein, die -- RDP inzwischen hat; das waere ein eigener, spaeterer Schritt. Hier geht es -- ausschliesslich darum, dass das Objekt eine stabile ID hat, auf die eine -- Achse-B-Freigabetabelle verweisen kann). -- -- Korrelation zwischen den beiden folgenden INSERTs laeuft wie bei 0012 -- ueber password_enc statt ueber eine temporaere ID-Spalte: jede -- Verschluesselung verwendet einen frischen Zufalls-Nonce (app/security/ -- crypto.py::encrypt_secret), zwei Zeilen der Alttabelle koennen also nie -- denselben password_enc-Wert haben. ALTER TABLE ssh_password_credentials RENAME TO ssh_password_credentials_legacy; CREATE TABLE IF NOT EXISTS ssh_password_credentials ( id INTEGER PRIMARY KEY, label TEXT NOT NULL, username TEXT NOT NULL, password_enc BLOB NOT NULL, created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), rotated_at TEXT ); CREATE TABLE IF NOT EXISTS host_ssh_password_credential_map ( host_id INTEGER PRIMARY KEY REFERENCES hosts(id) ON DELETE CASCADE, ssh_password_credential_id INTEGER NOT NULL REFERENCES ssh_password_credentials(id) ); INSERT INTO ssh_password_credentials (label, username, password_enc, created_at) SELECT 'Migriert: ' || h.hostname, spcl.username, spcl.password_enc, spcl.updated_at FROM ssh_password_credentials_legacy spcl JOIN hosts h ON h.id = spcl.host_id; INSERT INTO host_ssh_password_credential_map (host_id, ssh_password_credential_id) SELECT spcl.host_id, spc.id FROM ssh_password_credentials_legacy spcl JOIN ssh_password_credentials spc ON spc.password_enc = spcl.password_enc;