# 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.