From 1d5950d32c264bb6dadbd106fc7449beeac189df1e3775cedc334397bcc91690 Mon Sep 17 00:00:00 2001 From: CTO Agent Date: Sun, 25 Oct 2026 11:02:04 +0000 Subject: [PATCH] =?UTF-8?q?docs(architecture):=20add=20V1.1=20=E2=80=94=20?= =?UTF-8?q?Pocket-ID=20only,=20PII=20separation,=20Trillian,=20Content=20B?= =?UTF-8?q?inding,=20Replay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/architecture/v1.1.md | 512 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 512 insertions(+) create mode 100644 docs/architecture/v1.1.md diff --git a/docs/architecture/v1.1.md b/docs/architecture/v1.1.md new file mode 100644 index 0000000..6921735 --- /dev/null +++ b/docs/architecture/v1.1.md @@ -0,0 +1,512 @@ +# Technische Zielarchitektur: Vertrauenswürdige Kommunikation zwischen Menschen, KI-Agenten und SAP + +**Status:** Architekturvorschlag V1.1 (aktive Diskussionsgrundlage) +**Vorgänger:** [`v1.0.md`](v1.0.md) — ursprünglicher Entwurf (unverändert archiviert) +**Änderungen gegenüber V1.0:** siehe Abschnitt 0 „Änderungen seit V1.0" + +Diese Lösung wird als **Identity-Aware Agent Messaging Platform** konzipiert: eine Plattform, die Benutzerfreigaben, delegierte Berechtigungen und sämtliche Verarbeitungsschritte kryptografisch nachvollziehbar macht. + +Die zentrale Designentscheidung lautet: + +> **Der Benutzer autorisiert den ursprünglichen Geschäftsinhalt. Jeder Agent attestiert anschließend seine eigene Verarbeitung. Der empfangende Agent überprüft die vollständige Kette, bevor er eine Aktion ausführt.** + +Dabei werden Identität, Berechtigung, Verarbeitung und Nachrichtentransport strikt getrennt. + +## 0. Änderungen seit V1.0 + +Diese Revision setzt die Richtungsentscheidungen aus der ersten Review-Runde um: + +- **Scope Evidence Store (A.1/A.2):** kein rechtssicherer, kein WORM-/GoBD-Anspruch. Ziel ist der kryptografische Nachweis einer unverfälschten Kommunikation während eines **begrenzten Zeitraums** (Default: 1 Jahr). Danach dürfen Nachweise verworfen werden. +- **PII-Trennung (A.1):** verbindlich eingezogen. Attestierungen enthalten nur Hashes und Referenzen; personenbezogene Inhalte liegen in einem separaten, redaktionierbaren PII-Store. +- **IdP (A.3, A.5):** **Pocket ID** wird einziger IdP — für Menschen *und* Agenten. Begründung und Mechanik in Abschnitt 3a. Keycloak wird nicht eingeführt. +- **Content Binding (A.4):** eigener Abschnitt 4.0 als verbindliches UX-/Signatur-Protokoll. +- **Workload-Identität (A.5):** Agenten authentifizieren sich doppelt — Pocket-ID-`client_credentials`-Token *plus* projiziertes Kubernetes-ServiceAccount-Token. Signing Service verifiziert beide. +- **Schlüsselbund-Scope (A.6):** Historische Schlüssel werden nur für die aktive Nachweis-Retention vorgehalten (Default 1 Jahr). Rotation Default 90 Tage → max. ~5 Schlüssel pro Agent gleichzeitig gültig für die Verifikation. +- **Transparency Log (A.7, B.2):** PostgreSQL + Trillian-Merkle-Log statt Cassandra. Begründung in Abschnitt 8. +- **Replay-Schutz (A.8) und Fachliche Integritätsprüfung (A.9):** jetzt verbindliche Abschnitte 5.1 und 6.1. +- **ABAP-Token (A.10):** manuell im SAP-System hinterlegt (bestätigt). Rotationsprozess siehe Abschnitt 7. +- **Matrix (B.1):** verschoben in optionale Phase 5, nur für Mensch↔Agent-Chat. Agent↔Agent-Transport ist HTTPS/mTLS + NATS JetStream. +- **Signing Service (B.3):** eigenes Deployment von Tag 1. +- **Phase 1 (B.4):** End-to-End-Pfad mit einem Agenten als Abschluss. +- **predicateType-Namespace (B.5):** `https://basicstack.de/attestations//`. + +## 1. Zielarchitektur + +Logische Komponentenübersicht, keine direkte Netzwerktopologie. Freigabe- und Attestierungsnachweise werden über eigene APIs erstellt und geprüft; der Transport (HTTPS/mTLS + NATS, optional Matrix) überträgt nur Referenzen und Nachrichten — nie die Vertrauensentscheidung. + +## 2. Die fünf Architekturprinzipien + +1. **Unveränderliche Benutzerfreigabe** — ein vertrauenswürdiger Dienst bestätigt den konkret autorisierten Geschäftsinhalt. +2. **Eigene Identität jedes Agenten** — jeder Agent besitzt eine separate kryptografische Identität und signiert seine eigenen Verarbeitungsschritte. +3. **Verkettete Attestierungen** — jeder Verarbeitungsschritt referenziert exakte Eingabe- und Ausgabe-Hashes. +4. **Unabhängige Autorisierung** — eine Signatur allein erteilt keine Berechtigung; eine Policy Engine kontrolliert erlaubte Transformationen und ERP-Aktionen. +5. **Transportneutralität** — Nachweise funktionieren über HTTP, NATS, Queue oder Matrix, ohne dass die kryptografische Vertrauenskette verloren geht. + +## 3. Konkrete technische Komponenten + +| Dienst | Technologie | Verantwortung | +| --------------------- | ---------------------------------- | --------------------------------------------------- | +| Identity Provider | **Pocket ID** | Benutzeranmeldung (Passkey) und Agent-Clients (OIDC) | +| Approval Service | Go, REST API | Inhaltsgebundene Benutzerfreigabe | +| Agent Registry | PostgreSQL | Agentenidentitäten, Schlüsselhistorie, Berechtigungen | +| Signing Service | Go + OpenBao (Transit) | DSSE-Signaturen, verifiziert Agenten-Identität doppelt | +| Attestation Service | Go + in-toto | Verarbeitungsschritte dokumentieren | +| Policy Decision Point | Open Policy Agent (OPA) | Berechtigungen und Transformationsregeln | +| Verification Service | Go | Gesamte Vertrauenskette überprüfen | +| Transparency Log | **Trillian + PostgreSQL** | Append-only Merkle-Log mit Inclusion Proofs | +| Message Transport | HTTPS/mTLS + **NATS JetStream** | Agent↔Agent-Kommunikation | +| Chat Transport (opt.) | Matrix/Synapse | Mensch↔Agent-Chat (nur Phase 5) | +| SAP Connector | ABAP REST API / OData | Validierte Buchungsaufträge | +| Evidence Store | PostgreSQL (Metadaten) + S3 | DSSE-Envelopes und Attestate (Retention: 1 Jahr) | +| PII-Store | Verschlüsselt in S3 | Belege und Geschäftsdaten, redaktionierbar | + +Approval, Attestation, Registry und Verification bleiben in **einem modularen Go-Dienst** zusammengefasst. Separate APIs und Module bleiben erhalten, aber der Betrieb vieler kleiner Microservices wird vermieden. **Signing Service läuft als eigenes Deployment** mit separater Trust-Boundary. + +### 3a. Identity Provider: warum Pocket ID reicht + +Pocket ID unterstützt neben dem Authorization-Code-Flow auch den OIDC **`client_credentials`-Grant** (Endpunkt `POST /api/oidc/token`) und bietet eine Standard-OIDC-Discovery inkl. JWKS unter `https://auth.basicstack.de/.well-known/openid-configuration`. Damit decken wir beide Welten: + +- **Menschen** melden sich per Passkey (WebAuthn) über den normalen Authorization-Code-Flow an. +- **Agenten** werden in Pocket ID als eigene OIDC-Clients registriert (ein Client pro Agent, z.B. `agent-travel`, `agent-sap-mapping`, `agent-sap-posting`). Jeder Client erhält eine `client_id` + ein `client_secret`, das im zugehörigen Kubernetes-Namespace als Secret hinterlegt wird. Der Agent holt sich daraus ein kurzlebiges Access-Token per `client_credentials`. +- **SAP** (bzw. die ABAP-Validierungs-Webservice-Logik aus Abschnitt 7) kann denselben Pocket-ID-JWKS-Endpunkt nutzen, um ein von Agent C präsentiertes Token zu verifizieren — ohne Federation, ohne weiteren IdP. + +Keycloak wird **nicht** eingeführt. Das spart einen betriebskritischen Dienst. + +## 4. Datenmodell der Vertrauenskette + +Jeder Vorgang (z.B. Reisekostenabrechnung) erhält eine unveränderliche `workflow_id`. Jede Fassung der Daten wird als eigenes Artefakt mit SHA-256-Hash gespeichert. Der *Hash* liegt im Evidence Store; der *Inhalt* (PII) liegt im separaten PII-Store. + +### Vertrauens- und Verarbeitungskette + +1. **Benutzerfreigabe** — Approval Service bindet die Signatur an den Hash des Inhalts, den der Benutzer tatsächlich im Browser gesehen und per Content Binding bestätigt hat (siehe 4.0), und an die OIDC-Identität des Mitarbeiters. +2. **Agent A: Vorbereitung** — Agent A signiert eine Attestierung über Eingabe-Hash, Ausgabe-Hash, Transformationsart und die ursprüngliche Freigabe. +3. **Agent B: SAP-Mapping** — Agent B signiert seine eigene Attestierung und referenziert die Ausgabe von Agent A. +4. **Agent C: SAP-Buchung** — Agent C überprüft die komplette Kette und erzeugt nach erfolgreicher Buchung einen signierten Buchungsnachweis. + +Attestierungen sind keine Chatnachrichten, sondern eigenständige, überprüfbare Datensätze. + +### 4.0 Content Binding bei der Benutzerfreigabe + +Das Risiko: der Browser könnte dem Benutzer etwas anderes zeigen als dem Approval Service. + +Verbindlicher Ablauf: + +1. Approval Service rendert den Freigabe-Inhalt serverseitig, berechnet dessen SHA-256-Hash `H_content` und speichert `(session_id, H_content, salt)` zusammen mit einem einmaligen `challenge_nonce`. +2. Browser zeigt den Inhalt **und** eine aus `H_content + challenge_nonce` abgeleitete, menschenlesbare **Prüfziffer** (z.B. 6 Zeichen Base32) als visuelles Fingerprinting an. +3. Benutzer bestätigt per Passkey (WebAuthn-Signatur über `challenge_nonce || H_content`). Die WebAuthn-Challenge enthält `H_content` als Teil der Assertion-Daten — der Hardware-Authenticator signiert damit explizit das, was der Server und (per Prüfziffer) der Benutzer gesehen haben. +4. Approval Service verifiziert die WebAuthn-Assertion gegen den registrierten Passkey, prüft, dass die Session-Daten unverändert sind, und erzeugt erst dann die DSSE-signierte Approval-Attestierung. + +Damit scheitert ein kompromittierter Browser, der dem Benutzer eine andere Zahl zeigt, am visuellen Prüfziffer-Vergleich *oder* am WebAuthn-Signaturinhalt. + +### 4.1 Benutzerfreigabe (DSSE-Statement) + +```json +{ + "_type": "https://in-toto.io/Statement/v1", + "subject": [ + { + "name": "expense/EXP-2026-0042/v1", + "digest": { "sha256": "<64 hex characters>" } + } + ], + "predicateType": "https://basicstack.de/attestations/approval/v1", + "predicate": { + "workflow_id": "WF-0042", + "approval_id": "APR-0042", + "schema": { + "name": "expense.canonical", + "version": "1.0.0" + }, + "issuer": "approval-service", + "user": { + "iss": "https://auth.basicstack.de", + "sub": "user-12345" + }, + "content_binding": { + "method": "webauthn-content-hash-v1", + "assertion_hash": "sha256:", + "verification_code": "F3K-9MQ" + }, + "action": "expense.submit", + "audience": "sap-expense-workflow", + "allowed_transformations": ["expense.normalize", "expense.map_to_sap"], + "nonce": "", + "issued_at": "2026-10-25T10:30:00Z", + "expires_at": "2026-11-01T00:00:00Z" + } +} +``` + +Der Approval Service darf dieses Dokument nur erzeugen, wenn die WebAuthn-Signatur über dem Content-Hash gültig ist. Ein Agent darf diesen Endpunkt nicht mit einer frei angegebenen Benutzer-ID aufrufen. + +### 4.2 Signatur mit DSSE + +```json +{ + "payloadType": "application/vnd.in-toto+json", + "payload": "", + "signatures": [ + { "keyid": "approval-service-key-2026-q4", "sig": "" } + ] +} +``` + +DSSE's Pre-Authentication Encoding (PAE) signiert Nutzlast und Inhaltstyp gemeinsam. `keyid` ist nur Hinweis — die Identität ergibt sich aus der verifizierten Signatur gegen das in der Agent Registry zum `issued_at` gültige öffentliche Schlüsselmaterial. + +### 4.3 Transformations-Attestierung (Beispiel Agent B) + +```json +{ + "_type": "https://in-toto.io/Statement/v1", + "subject": [ + { + "name": "expense/EXP-2026-0042/sap-payload", + "digest": { "sha256": "" } + } + ], + "predicateType": "https://basicstack.de/attestations/transform/v1", + "predicate": { + "workflow_id": "WF-0042", + "actor": "agent-sap-mapping", + "operation": "expense.map_to_sap", + "materials": [ + { "name": "expense/EXP-2026-0042/normalized", "sha256": "" } + ], + "parent_attestation": "sha256:", + "approval_ref": "APR-0042", + "schema": { + "input": { "name": "expense.canonical", "version": "1.0.0" }, + "output": { "name": "sap.expense.payload", "version": "1.2.0" } + }, + "transform_version": "1.3.0", + "issued_at": "2026-10-25T10:31:15Z" + } +} +``` + +Agent B signiert diese Attestierung mit seinem eigenen Schlüssel. + +### 4.4 Agentenregistrierung und Schlüsselhistorie + +Jeder Agent ist in zwei Systemen eingetragen: + +- **Pocket ID:** als OIDC-Client (`client_id`, `client_secret` im K8s-Secret). +- **Agent Registry (unsere Postgres-Tabelle):** die Identität plus Signatur-Schlüsselhistorie. + +Schema (vereinfacht): + +```sql +CREATE TABLE agents ( + agent_id TEXT PRIMARY KEY, + pocket_id_client TEXT UNIQUE NOT NULL, + k8s_namespace TEXT NOT NULL, + k8s_service_account TEXT NOT NULL, + display_name TEXT NOT NULL, + allowed_actions TEXT[] NOT NULL, + created_at TIMESTAMPTZ NOT NULL +); + +CREATE TABLE agent_keys ( + key_id TEXT PRIMARY KEY, -- z.B. "agent-travel-2026-q4" + agent_id TEXT NOT NULL REFERENCES agents(agent_id), + public_key_pem TEXT NOT NULL, -- Ed25519 + valid_from TIMESTAMPTZ NOT NULL, + valid_to TIMESTAMPTZ NOT NULL, + revoked_at TIMESTAMPTZ, + revocation_reason TEXT, + archived_at TIMESTAMPTZ -- gesetzt wenn außerhalb Retention +); + +CREATE INDEX idx_agent_keys_lookup + ON agent_keys (agent_id, archived_at) + WHERE archived_at IS NULL; +``` + +**Validierung alter Attestierungen** nutzt den Schlüssel, der zum `issued_at` der Attestierung galt (`valid_from ≤ issued_at < valid_to`, nicht `revoked_at` vor `issued_at`). Das ist das TUF-Pattern. + +**Retention und Performance.** Default-Rotation **90 Tage**, Nachweis-Retention **1 Jahr** → pro Agent max. ~5 nicht-archivierte Schlüssel. Beim Überschreiten der Retention wird der Schlüssel auf `archived_at` gesetzt; alte Attestierungen, die noch im Evidence Store liegen, aber über diese Grenze hinaus zu validieren wären, werden explizit abgelehnt (`decision: expired_retention`). Damit bleibt der aktive Keyring klein und die Validierung konstant schnell — auch bei 100+ Agenten. + +## 5. Verifikation beim empfangenden Agenten + +Der SAP-Agent darf sich nicht auf die mitgesendeten IDs verlassen. Er muss die gesamte Nachweiskette prüfen. + +``` +POST /api/v1/attestations/verify +Authorization: Bearer +Content-Type: application/json +``` + +```json +{ + "workflow_id": "WF-0042", + "artifact_digest": "sha256:", + "requested_action": "expense.post_to_sap", + "target": "sap-s4hana-prod" +} +``` + +| Prüfung | Fehlerfall | +| -------------------------------------------------------------------- | --------------------- | +| Signatur der Benutzerfreigabe gültig (Schlüssel zum `issued_at` gültig)? | Ablehnen | +| Content-Binding-Assertion in der Approval-Attestierung vorhanden? | Ablehnen | +| Benutzeridentität im Pocket-ID-JWKS auflösbar? | Ablehnen | +| Freigabe gültig, nicht widerrufen, nicht abgelaufen? | Ablehnen | +| Alle Agentensignaturen gültig gegen `agent_keys` zur `issued_at`? | Ablehnen | +| Agenten zum Signaturzeitpunkt registriert und berechtigt? | Ablehnen | +| Input-/Output-Hashes der Materialien-Kette konsistent? | Ablehnen | +| Transformationen laut Freigabe zulässig? | Ablehnen | +| Schema-Version der kanonischen Daten mit Approval kompatibel? | Ablehnen | +| SAP-Nutzlast entspricht freigegebener Geschäftssemantik (OPA)? | Ablehnen | +| `payload_hash` bereits für `target` gebucht? | Keine erneute Buchung | + +Erfolgsantwort: + +```json +{ + "valid": true, + "workflow_id": "WF-0042", + "original_user": { "issuer": "https://auth.basicstack.de", "subject": "user-12345" }, + "actors": ["agent-travel", "agent-sap-mapping"], + "authorized_action": "expense.post_to_sap", + "artifact_digest": "sha256:", + "decision_id": "DEC-2026-0042", + "decision_nonce": "", + "bound_to_agent": "agent-sap-posting", + "bound_to_target": "sap-s4hana-prod", + "expires_at": "2026-10-25T10:36:00Z" +} +``` + +Diese Decision ist eine kurzlebige, an Agent C + Payload-Hash + Target gebundene Ausführungsberechtigung. + +### 5.1 Replay-Schutz (verbindlich) + +- `decision_id` enthält einen eigenen `decision_nonce`, Lebensdauer **5 Minuten**. +- Decision ist gebunden an `(agent_id, payload_hash, target)` — Zieländerung oder Agent-Wechsel invalidiert sie. +- Verification Service hält eine Postgres-Tabelle `decisions` mit `UNIQUE (payload_hash, target)` für den Doppelbuchungs-Check. +- SAP-Connector führt eine **eigene** Replay-Tabelle (`sap_decision_log`) mit `UNIQUE (decision_id)`. Beide Prüfungen sind unabhängig voneinander — Defence in Depth. +- Doppelbuchung wird gegen `payload_hash` (nicht nur `workflow_id`) geprüft, damit minimal veränderte Nutzlasten nicht durchrutschen. + +## 6. Berechtigungssteuerung mit Open Policy Agent + +Beispiel-Regeln: + +- Agent A darf Belege extrahieren und Reisekosten strukturieren. +- Agent B darf Kontierungsinformationen ergänzen und SAP-Felder zuordnen. +- Agent B darf keine Beträge oder Währungen ohne zusätzliche Freigabe ändern. +- Agent C darf ausschließlich vollständig validierte Reisekostenabrechnungen buchen. + +Rego-Policies werden zentral verwaltet und versioniert; die zum Entscheidungszeitpunkt verwendete Policy-Version wird im Evidence Store mit abgelegt. + +### 6.1 Fachliche Integritätsprüfung — Schema-Versionierung (verbindlich) + +Ein Hashvergleich allein reicht nicht, weil sich beim Mapping das technische Format verändert. Deshalb binden wir die Freigabe an ein **versioniertes kanonisches Schema**: + +```json +{ + "schema": { "name": "expense.canonical", "version": "1.0.0" }, + "employee_id": "EMP-12345", + "currency": "EUR", + "total_amount": "428.50", + "expense_items": [ + { "type": "HOTEL", "amount": "328.50" }, + { "type": "MEALS", "amount": "100.00" } + ] +} +``` + +Verbindlich: + +- Schemas werden als JSON Schema in `schemas/` im Repo versioniert. +- Jede Approval-Attestierung signiert `schema.name` und `schema.version` mit. +- Jede Transform-Attestierung signiert Input- *und* Output-Schema. +- OPA-Policies arbeiten gegen das kanonische Schema; sie prüfen z.B. „Agent B darf `total_amount` nicht verändern" oder „Agent B darf `expense_items[].amount` höchstens kaufmännisch runden". +- Schema-Änderungen sind Breaking Changes und erfordern eine neue Hauptversion. + +## 7. SAP S/4HANA Integration + +Für die S/4HANA-2023-Umgebung ist eine ABAP-Integrationsschicht vorgesehen, statt Agent C direkten Zugriff auf Buchungsfunktionen zu geben. + +Fluss: `Agent C` → `ABAP REST Endpoint` (Authentifizierung · Freigabenachweis · Idempotenz) → `SAP-Anwendungslogik` (Mitarbeiterzuordnung · fachliche Prüfungen · Buchung). + +``` +POST /sap/bc/zexpense/v1/submit +Authorization: Bearer +Idempotency-Key: WF-0042 +Content-Type: application/json +``` + +```json +{ + "workflow_id": "WF-0042", + "approval_id": "APR-0042", + "verification_ref": "DEC-2026-0042", + "expense_ref": "EXP-2026-0042", + "payload_hash": "sha256:" +} +``` + +Zusätzlich stellt ProofedMesh einen **Validierungs-Webservice** bereit, den das ABAP vor der Buchung aufruft: + +``` +POST /api/v1/decisions/{decision_id}/replay-check +``` + +Rückgabe: ob die Decision noch gültig, nicht verbraucht, an Agent C gebunden und für dieses `target` autorisiert ist. Damit braucht SAP keine eigene Krypto-Logik. + +**Zwei unabhängige Prüfungen** in SAP: + +- **Technische Identität:** Der Aufruf kommt vom autorisierten SAP-Agenten (Bearer-Token-Prüfung). +- **Fachliche Identität:** Der freigebende Benutzer wird über eine serverseitig gepflegte Zuordnung der korrekten SAP-Personalnummer zugeordnet. Eine vom Agenten gelieferte Personalnummer darf diese Zuordnung nicht überschreiben. + +**sap-agent-token** wird manuell im SAP-System hinterlegt. Rotationsprozess: + +1. Signing Service oder Operator generiert neues Token (JWT, 90-Tage-Gültigkeit) und signiert es mit dem Service-Schlüssel von Agent C. +2. Operator trägt neues Token in SAP ein (Transaktion `SM59` oder äquivalent, abhängig von der konkreten SAP-Konfiguration). +3. Agent C erhält das neue Token über ein K8s-Secret; alte Secrets werden nach einer Übergangszeit entfernt. +4. SAP-Validierung akzeptiert alte und neue Token, solange sie signiert sind — die Agent-Identität wird aus dem Token-`sub` gelesen, nicht aus dem Token-Material selbst. + +**Welche SAP-Buchungsschnittstelle** verwendet wird (SAP Travel Management, Concur, kundeneigener FI-Prozess), bleibt in einem späteren ADR offen — architektonisch ist das austauschbar. + +### SAP-Auditdaten + +Zusätzlich zum ERP-Beleg: Tabelle `ZAGENT_AUDIT`. + +| Feld | Inhalt | +| --------------------- | ---------------------------------- | +| WORKFLOW_ID | Eindeutige Prozess-ID | +| APPROVAL_ID | Benutzerfreigabe | +| USER_SUB | Externe Benutzeridentität | +| PERNR | Zugeordnete Personalnummer | +| AGENT_ID | Buchender Agent | +| PAYLOAD_HASH | SHA-256 der Buchungsdaten | +| VERIFICATION_ID | Verifikationsentscheidung | +| DECISION_ID | Replay-Check-Referenz | +| BUKRS / BELNR / GJAHR | FI-Belegreferenz | +| CREATED_AT | Buchungszeitpunkt | + +Idempotenz: `UNIQUE (WORKFLOW_ID)` *und* `UNIQUE (DECISION_ID)`. Bei N fehlgeschlagenen Buchungsversuchen landet der Vorgang in einer SAP-Operator-Queue zur manuellen Prüfung — kein stiller Datenverlust. + +## 8. Nachweisablage und Transparency Log + +### 8.1 Scope und Retention + +**Ziel:** kryptografisch belegen, dass die Agent-Kommunikation unverfälscht gelaufen ist, und diese Prüfung auch nachträglich zulassen. **Kein** rechtssicheres GoBD-Archiv. + +**Retention Default: 1 Jahr.** Nach Ablauf werden Attestierungen, Decisions und zugehörige Schlüsselhistorie automatisiert gelöscht (`archived_at` + Cron-Job). Konfigurierbar pro Prozess-Typ. + +### 8.2 Datenklassen + +| Daten | Speicherung | +| --------------------------------------- | ---------------------------------------- | +| Prozessstatus, Identitäten, Referenzen | PostgreSQL (`trust-postgres`) | +| Signierte Attestierungen (DSSE) | S3 Object Storage | +| **Transparency-Log-Einträge + Proofs** | **Trillian + PostgreSQL** | +| Reisekostenbelege und Geschäftsdaten | Verschlüsselt in S3 (**separater Bucket, PII-Store**) | +| Signatur- und Schlüsselhistorie | Agent Registry (Postgres), max 1 Jahr | +| Policy-Versionen | Git-versioniert, Hash im Evidence Store | + +**Strikte Trennung PII vs. Nachweis:** Der PII-Store (Belege, Namen, Kostenstellen) ist unabhängig vom Evidence Store löschbar. Löscht ein Benutzer per DSGVO-Antrag seine Daten, verschwinden die Belege; die Hashes und Signaturen in Evidence Store und Transparency Log bleiben erhalten, verifizieren aber dann nur noch „diese Kette existierte", nicht mehr „ihr Inhalt war X". + +### 8.3 Warum Trillian + PostgreSQL (nicht Cassandra) + +Ein Transparency Log ist ein **append-only Merkle-Tree** mit Inclusion Proofs und periodisch signiertem Tree-Root (Signed Tree Head). Entscheidend sind: + +- **Strikte Reihenfolge** aller Einträge (eine lineare Sequenznummer). +- **Starke Konsistenz** zwischen Logeintrag und Merkle-Root — der Root muss nach jedem Append reproduzierbar berechnet werden können. +- **Inclusion Proofs** auf Anfrage, idealerweise in ms. + +Cassandra ist für diese Zugriffsmuster architektonisch ungeeignet: eventual consistency, ordering nur per Partition, keine serialisierbare globale Sequenz. Es wäre technisch möglich, aber mit erheblichem Over-Engineering (externer Sequencer, Lock-Dienst) — und würde sigstore's Entscheidung widersprechen. + +**Empfehlung:** [Google Trillian](https://github.com/google/trillian) als Transparency-Log-Engine (ist die Grundlage von sigstore rekor), gestützt auf PostgreSQL — das ist unsere ohnehin vorhandene Infrastruktur. Für unser erwartetes Volumen (< 1 Mio. Einträge/Jahr, Single-Tenant) läuft das auf einer kleinen Instanz. Der Log-Root wird täglich signiert und ins Backup-System gespiegelt — damit ist eine nachträgliche Manipulation durch den DB-Admin erkennbar. + +Falls Trillian als Dependency zu schwer wirkt, Alternative: eine eigene minimale Append-Only-Postgres-Tabelle mit stündlich berechnetem Merkle-Root und Export des Roots als signiertes JSON — deutlich weniger Funktionalität (keine Inclusion Proofs auf Anfrage), aber ausreichend für unseren Scope. + +## 9. Deployment in Kubernetes + +Namespaces und Dienste: + +``` +identity/ + pocket-id (bestehend) + +agent-trust/ + trust-api (Approval + Attestation + Registry + Verification) + signing-service (eigenes Deployment, enge Trust-Boundary) + policy-engine (OPA) + trust-postgres + trillian-log (Transparency Log) + +transport/ + nats (JetStream für Agent↔Agent) + +paperclip/ + paperclip + agent-travel + agent-sap-mapping + agent-sap-posting + +openbao/ + openbao (Transit Engine für Signaturschlüssel) + +matrix/ (optional, Phase 5) + synapse + element-web + agent-matrix-gateway +``` + +**Signing Service**: eigenes Deployment, dediziertes Pocket-ID-Client-Secret, eigener ServiceAccount, NetworkPolicy erlaubt eingehend nur die Agent-Namespaces. Agenten rufen den Signing-Endpunkt auf; private Schlüssel verlassen OpenBao nie. + +### 9.1 Workload-Identitäts-Prüfung (doppelt) + +Der Signing Service verifiziert für jeden eingehenden Request **beide** Credentials: + +1. **Pocket-ID-Access-Token** (Header `Authorization: Bearer `) — gegen Pocket-ID-JWKS validiert; `sub` = `agent-` muss zu einem registrierten Agent in der Agent Registry gehören. +2. **Projected ServiceAccount-Token** (Header `X-Workload-Token: `, Audience `signing-service.agent-trust`) — gegen Kubernetes-TokenReview-API validiert; Namespace + ServiceAccount müssen zum Agent in der Agent Registry passen. + +Nur wenn beide Prüfungen zum selben `agent_id` auflösen, wird signiert. Damit ist weder ein geleaktes Pocket-ID-Secret allein noch ein kompromittierter Pod außerhalb des erwarteten Namespaces ausreichend. + +OpenBao's Transit Engine signiert mit Ed25519. **Caveat:** Transit kennt kein DSSE — der Signing Service berechnet die DSSE-Pre-Authentication-Encoding (PAE) selbst und übergibt nur den Hash an Transit. Backup via Transit-Export-Policy und Snapshot der OpenBao-Instanz. + +## 10. Implementierungsreihenfolge + +**Phase 1 — End-to-End-Skelett (3 bis 5 Wochen)** +Pocket ID als IdP (Mensch und Agent-Client), Approval Service mit Content Binding, **ein** Testagent mit Ed25519-Schlüssel in der Agent Registry, Signing Service mit doppelter Identitätsprüfung, Verification Service für die zweistufige Kette (Approval → Agent → Simulierte Senke). Deliverable: ein signierter Durchlauf vom Login bis zur simulierten SAP-Senke. + +**Phase 2 — Agent Attestations in Breite** +Weitere Agenten, Schlüsselrotation, in-toto-Transformationsnachweise, Materialien-Hash-Kette, OPA-Policies in Rego, Policy-Versionierung. + +**Phase 3 — Replay-Schutz, Transparency Log, Retention** +Trillian-Deployment, Decision-Nonce-Mechanik, Decision-Replay-Tabelle, Retention-Cron-Job, PII-Store-Trennung. + +**Phase 4 — SAP-Integration** +ABAP-Endpunkt, serverseitige Mitarbeiterzuordnung, SAP-seitige Replay-Prüfung über Validierungs-Webservice, Operator-Queue. + +**Phase 5 — Matrix für Mensch-Chat (optional)** +Nur Mensch↔Agent-Chat, E2EE. Agent↔Agent läuft weiterhin über NATS/HTTPS. + +## 11. Was bewusst anders ist als in V1.0 + +- Matrix ist **nicht** Standard-Transport — nur optionale Mensch-Chat-Schicht in Phase 5. Intern NATS JetStream + HTTPS/mTLS. +- Transparency Log ist eine eigene Komponente, nicht nur „Postgres-Tabelle". +- Signing Service ist eigenes Deployment ab Tag 1. +- PII-Store ist strikt getrennt vom Evidence Store. +- Keine Unveränderbarkeits-/GoBD-Garantien — Retention 1 Jahr, dann Löschung. +- Pocket ID ist alleiniger IdP — Keycloak entfällt. + +## 12. Empfohlener Kernstack (Zielbild) + +| Identität | **Pocket ID** (Menschen + Agent-Clients) | +| ------------- | ------------------------------------------------------------------- | +| Workload-ID | K8s projected ServiceAccount Token + TokenReview | +| Signaturen | Ed25519 / DSSE, OpenBao Transit | +| Provenienz | in-toto v1, predicate-Namespace `basicstack.de/attestations/*/*` | +| Autorisierung | OPA (Rego) + Approval Service | +| Transparency | Trillian + PostgreSQL | +| Transport | HTTPS/mTLS + NATS JetStream (Agent↔Agent); Matrix optional (Mensch) | +| Agenten | Paperclip | +| ERP | SAP S/4HANA / ABAP REST + Validierungs-Webservice | +| Evidence | PostgreSQL + S3 (Retention 1 Jahr) | +| PII | Separater verschlüsselter S3-Bucket, redaktionierbar | + +**Wichtigste Empfehlung bleibt:** Zuerst in Phase 1 ein vollständiger signierter Testprozess von der Benutzerfreigabe bis zur simulierten SAP-Senke, mit genau einem Agenten. Matrix und ADRs für Schema/OPA-Deep-Dive folgen danach.