docs(architecture): add parallel read path (Data Sources, Query Attestations, Session Scope Tokens); make own DB-App the first rollout
This commit is contained in:
parent
7205fa2e98
commit
fddce4d0fb
1 changed files with 418 additions and 296 deletions
|
|
@ -2,107 +2,210 @@
|
|||
|
||||
**Status:** Architekturvorschlag V1.1 (aktive Diskussionsgrundlage)
|
||||
**Vorgänger:** [`v1.0.md`](v1.0.md) — ursprünglicher Entwurf (unverändert archiviert)
|
||||
**Letzte Änderung:** Senken-Konzept generalisiert — SAP ist nur eine mögliche Senke neben eigenen DB-Applikationen, HTTP-Webhooks, Message-Queues u.a.
|
||||
**Letzte Änderung:** Paralleler Lesepfad eingezogen — Agenten holen Vorab-Informationen aus registrierten **Datenquellen** über das gleiche Trust-Modell wie bei Senken (Query Attestations, Session Scope Tokens). Erster produktiver Rollout: eigene DB-App als Quelle UND Senke.
|
||||
|
||||
Diese Lösung wird als **Identity-Aware Agent Messaging Platform** konzipiert: eine Plattform, die Benutzerfreigaben, delegierte Berechtigungen und sämtliche Verarbeitungsschritte kryptografisch nachvollziehbar macht.
|
||||
Diese Lösung wird als **Identity-Aware Agent Messaging Platform** konzipiert: eine Plattform, die Benutzerfreigaben, delegierte Berechtigungen und sämtliche Verarbeitungsschritte kryptografisch nachvollziehbar macht — inkl. der *Lesezugriffe*, die ein Agent vor der eigentlichen Freigabe durchführt, um dem Benutzer sinnvolle Vorschläge zu machen.
|
||||
|
||||
Die zentrale Designentscheidung lautet:
|
||||
|
||||
> **Der Benutzer autorisiert den ursprünglichen Geschäftsinhalt. Jeder Agent attestiert anschließend seine eigene Verarbeitung. Die empfangende Senke überprüft die vollständige Kette, bevor sie eine Aktion ausführt.**
|
||||
> **Der Benutzer autorisiert den ursprünglichen Geschäftsinhalt. Jeder Agent attestiert anschließend seine eigene Verarbeitung — inkl. jedes Datenzugriffs, der die Vorschlagsgrundlage geformt hat. Die empfangende Senke überprüft die vollständige Kette, bevor sie eine Aktion ausführt.**
|
||||
|
||||
Dabei werden Identität, Berechtigung, Verarbeitung und Nachrichtentransport strikt getrennt.
|
||||
|
||||
## 0. Änderungen seit V1.0
|
||||
|
||||
Diese Revision setzt die Richtungsentscheidungen der ersten beiden Review-Runden um:
|
||||
Diese Revision setzt die Richtungsentscheidungen der bisherigen Review-Runden um:
|
||||
|
||||
- **Scope Evidence Store:** kein rechtssicherer, kein WORM-/GoBD-Anspruch. Ziel ist der kryptografische Nachweis einer unverfälschten Kommunikation während eines **begrenzten Zeitraums** (Default: 1 Jahr).
|
||||
- **Scope Evidence Store:** kein rechtssicherer, kein WORM-/GoBD-Anspruch. Ziel ist der kryptografische Nachweis einer unverfälschten Kommunikation während eines begrenzten Zeitraums (Default: 1 Jahr).
|
||||
- **PII-Trennung:** verbindlich. Attestierungen enthalten nur Hashes und Referenzen; personenbezogene Inhalte liegen in einem separaten, redaktionierbaren PII-Store.
|
||||
- **IdP:** **Pocket ID** wird einziger IdP — für Menschen *und* Agenten (per `client_credentials`-Grant). Kein Keycloak.
|
||||
- **Content Binding:** eigener Abschnitt 4.0 als verbindliches UX-/Signatur-Protokoll (WebAuthn über Content-Hash + visuelle Prüfziffer).
|
||||
- **Workload-Identität:** doppelte Prüfung — Pocket-ID-Token *plus* K8s-ServiceAccount-Token.
|
||||
- **IdP:** Pocket ID wird einziger IdP — für Menschen und Agenten (`client_credentials`-Grant). Kein Keycloak.
|
||||
- **Content Binding:** verbindliches UX-/Signatur-Protokoll (WebAuthn über Content-Hash + visuelle Prüfziffer).
|
||||
- **Workload-Identität:** doppelte Prüfung — Pocket-ID-Token plus K8s-ServiceAccount-Token.
|
||||
- **Schlüsselbund-Scope:** Rotation Default 90 Tage × Retention 1 Jahr → max. ~5 aktive Schlüssel pro Agent.
|
||||
- **Transparency Log:** Trillian + PostgreSQL (nicht Cassandra — Begründung in 8.3).
|
||||
- **Replay-Schutz und fachliche Integritätsprüfung:** verbindliche Abschnitte (5.1 und 6.1).
|
||||
- **Transport:** Matrix nur optional in Phase 5 für Mensch-Chat; Agent↔Agent läuft über HTTPS/mTLS + NATS JetStream.
|
||||
- **Transparency Log:** Trillian + PostgreSQL.
|
||||
- **Replay-Schutz und fachliche Integritätsprüfung:** verbindliche Abschnitte.
|
||||
- **Transport:** Matrix nur optional (Phase 6) für Mensch-Chat; Agent↔Agent über HTTPS/mTLS + NATS JetStream.
|
||||
- **Signing Service:** eigenes Deployment ab Tag 1.
|
||||
- **predicateType-Namespace:** `https://basicstack.de/attestations/<domain>/<version>`.
|
||||
- **🆕 Senken-Generalisierung:** SAP ist eine von vielen möglichen Prozess-Senken. Der Trust-Core ist senken-agnostisch. Senken-Adapter sind eine austauschbare Schicht mit festem Vertrag (Abschnitt 7).
|
||||
- **Senken-Generalisierung:** SAP ist eine von vielen möglichen Senken. Trust-Core senken-agnostisch. Senken-Adapter sind Plug-ins mit festem Vertrag.
|
||||
- **🆕 Datenquellen und paralleler Lesepfad:** Agenten holen während der Vorbereitung Informationen aus registrierten **Datenquellen** (Section 3b, 4.5a) über das gleiche Vertrauens- und Autorisierungsmodell wie bei Senken. Jede Abfrage erzeugt eine **Query Attestation**; die Benutzerfreigabe bindet an diese Query-Materialien.
|
||||
- **🆕 Session Scope Tokens:** Session-gebundene, kurzlebige Delegations-Tokens, mit denen Agenten „im Auftrag von Benutzer X in Session S" lesen dürfen. Siehe Abschnitt 3c.
|
||||
- **🆕 Erster produktiver Rollout:** **eigene kleine Go-DB-App** (`sink:expense-db-app` + `ds:expense-db-app`) als kombinierte Quelle und Senke. SAP folgt später.
|
||||
|
||||
## 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.
|
||||
Logische Komponentenübersicht, keine direkte Netzwerktopologie. Der Prozess hat **zwei Pfade**, die beide über denselben Trust-Core abgesichert sind:
|
||||
|
||||
Der Prozess endet an einer **Senke** (Sink). Senken sind nach außen offene Zielsysteme — ERP (SAP S/4HANA, SAP Concur), eigene Datenbankanwendungen, HTTP-Webhooks externer Dienste, Message-Queues (Kafka/NATS), Dateiablage (SFTP, S3), Legacy-Systeme (Mail/EDI) oder beliebige kundeneigene APIs. Der Trust-Core ist senken-agnostisch; pro Senken-Typ gibt es einen **Senken-Adapter**, der denselben Vertrag erfüllt (Abschnitt 7).
|
||||
- **Schreibpfad (Senke):** Approval → Agent-Attestierungen → Verification → Senken-Adapter → signierter Übergabenachweis.
|
||||
- **Lesepfad (Datenquelle):** Agent → Session Scope Token → Datenquellen-Adapter → signierte Query Attestation. Query-Materialien gehen als Eingaben in die nachfolgenden Attestierungen und in die Benutzerfreigabe ein.
|
||||
|
||||
## 2. Die fünf Architekturprinzipien
|
||||
Der Transport (HTTPS/mTLS + NATS, optional Matrix) überträgt nur Referenzen und Nachrichten — nie die Vertrauensentscheidung.
|
||||
|
||||
Senken sind nach außen offene Zielsysteme — ERP, eigene Datenbankanwendungen, HTTP-Webhooks, Message-Queues, Dateiablage u.a. Datenquellen sind nach außen offene Lesesysteme — eigene DBs, HR-Systeme, Projektmanagement-APIs, SAP-OData-Reads u.a. Beide Typen folgen demselben Adapter-Vertrag.
|
||||
|
||||
## 2. Die sechs 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 Senken-Aktionen.
|
||||
5. **Transportneutralität** — Nachweise funktionieren über HTTP, NATS, Queue oder Matrix, ohne dass die kryptografische Vertrauenskette verloren geht.
|
||||
|
||||
Zusatzprinzip: **Senken-Neutralität.** Weder der Trust-Core noch der Verifikationspfad kennen die Semantik einer konkreten Senke. Senken-Adapter übersetzen zwischen dem senken-agnostischen „Decision"-Objekt und dem jeweiligen Zielsystem.
|
||||
3. **Verkettete Attestierungen** — jeder Verarbeitungsschritt referenziert exakte Eingabe- und Ausgabe-Hashes; Lesezugriffe werden ebenfalls attestiert und als Materialien verkettet.
|
||||
4. **Unabhängige Autorisierung** — eine Signatur allein erteilt keine Berechtigung; eine Policy Engine kontrolliert erlaubte Transformationen, Lesezugriffe und Senken-Aktionen.
|
||||
5. **Transportneutralität** — Nachweise funktionieren über HTTP, NATS, Queue oder Matrix.
|
||||
6. **Quellen- und Senken-Neutralität** — Trust-Core und Verifikationspfad kennen keine konkrete Quellen- oder Senken-Semantik; beide sind Plug-ins mit festem Vertrag.
|
||||
|
||||
## 3. Konkrete technische Komponenten
|
||||
|
||||
| Dienst | Technologie | Verantwortung |
|
||||
| --------------------- | ---------------------------------- | --------------------------------------------------- |
|
||||
| --------------------------- | ---------------------------------- | ------------------------------------------------------------- |
|
||||
| Identity Provider | **Pocket ID** | Benutzeranmeldung (Passkey) und Agent-Clients (OIDC) |
|
||||
| Approval Service | Go, REST API | Inhaltsgebundene Benutzerfreigabe |
|
||||
| **Session Scope Token Svc** | Go (Teil des trust-api) | **Short-lived Delegations-Tokens „Agent X im Auftrag von User Y in Session S für Scope Z"** |
|
||||
| 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 |
|
||||
| Attestation Service | Go + in-toto | Verarbeitungsschritte und Lesezugriffe dokumentieren |
|
||||
| Policy Decision Point | Open Policy Agent (OPA) | Berechtigungen für Transformationen, Lesezugriffe, Senken |
|
||||
| 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) |
|
||||
| **Sink Registry** | PostgreSQL | **Registrierte Senken, Adapter-Metadaten, Audience-Keys** |
|
||||
| **Senken-Adapter** | **pro Senke; siehe Abschnitt 7** | **Übersetzt verifizierte Decision in Senken-Aktion** |
|
||||
| Chat Transport (opt.) | Matrix/Synapse | Mensch↔Agent-Chat (nur Phase 6) |
|
||||
| **Sink Registry** | PostgreSQL | Registrierte Senken, Adapter-Metadaten, Audience-Keys |
|
||||
| **Data Source Registry** | PostgreSQL | **Registrierte Datenquellen, erlaubte Query-Patterns, PII-Klassifikation** |
|
||||
| Senken-Adapter | pro Senke; siehe Abschnitt 7 | Übersetzt verifizierte Decision in Senken-Aktion |
|
||||
| **Datenquellen-Adapter** | **pro Quelle; siehe Abschnitt 7a** | **Prüft Scope-Token + Policy, führt Query aus, erzeugt Query Attestation** |
|
||||
| Evidence Store | PostgreSQL (Metadaten) + S3 | DSSE-Envelopes und Attestate (Retention: 1 Jahr) |
|
||||
| PII-Store | Verschlüsselt in S3 | Belege und Geschäftsdaten, redaktionierbar |
|
||||
| PII-Store | Verschlüsselt in S3 | Belege, Geschäftsdaten UND Query-Ergebnisse mit PII — redaktionierbar |
|
||||
|
||||
Approval, Attestation, Registry (Agent + Sink) und Verification bleiben in **einem modularen Go-Dienst** zusammengefasst. **Signing Service läuft als eigenes Deployment**. **Senken-Adapter** laufen pro Senken-Typ als eigenes Deployment oder — bei trivialen Senken — als Thin-Client im Buchungs-Agenten.
|
||||
Approval, Session Scope Token Service, Attestation, Registry (Agent + Sink + Data Source) und Verification laufen in **einem modularen Go-Dienst** (`trust-api`). Signing Service läuft als eigenes Deployment. Senken- und Datenquellen-Adapter laufen pro Typ (oft als derselbe Prozess, wenn eine Komponente beides anbietet — siehe 7.2).
|
||||
|
||||
### 3a. Identity Provider: Pocket ID allein genügt
|
||||
|
||||
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:
|
||||
Pocket ID unterstützt neben dem Authorization-Code-Flow auch den OIDC `client_credentials`-Grant (`POST /api/oidc/token`) und bietet Standard-OIDC-Discovery inkl. JWKS unter `https://auth.basicstack.de/.well-known/openid-configuration`.
|
||||
|
||||
- **Menschen** melden sich per Passkey (WebAuthn) über den Authorization-Code-Flow an.
|
||||
- **Agenten** werden in Pocket ID als eigene OIDC-Clients registriert (ein Client pro Agent). Jeder Client erhält `client_id` + `client_secret`, hinterlegt als K8s-Secret im Agent-Namespace. Agenten holen sich daraus kurzlebige Access-Tokens.
|
||||
- **Senken** (insb. externe wie SAP) verifizieren per Pocket-ID-JWKS. Keine Federation nötig.
|
||||
- **Menschen** melden sich per Passkey an.
|
||||
- **Agenten** sind in Pocket ID als OIDC-Clients registriert; holen sich kurzlebige Access-Tokens per `client_credentials`.
|
||||
- **Senken und Datenquellen** verifizieren per Pocket-ID-JWKS.
|
||||
|
||||
Keine Federation nötig.
|
||||
|
||||
### 3b. Data Source Registry
|
||||
|
||||
Datenquellen sind registrierte Entitäten mit stabiler ID, erlaubten Query-Patterns und PII-Klassifikation.
|
||||
|
||||
```sql
|
||||
CREATE TABLE data_sources (
|
||||
data_source_id TEXT PRIMARY KEY, -- z.B. "ds:expense-db-app"
|
||||
display_name TEXT NOT NULL,
|
||||
adapter_kind TEXT NOT NULL, -- "db_app" | "http_api" | "sap_odata" | "custom"
|
||||
endpoint_url TEXT,
|
||||
owner_team TEXT NOT NULL,
|
||||
pii_class TEXT NOT NULL, -- "none" | "indirect" | "direct"
|
||||
created_at TIMESTAMPTZ NOT NULL,
|
||||
retired_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TABLE data_source_resources (
|
||||
data_source_id TEXT NOT NULL REFERENCES data_sources(data_source_id),
|
||||
resource TEXT NOT NULL, -- z.B. "project_assignments", "cost_centers"
|
||||
allowed_filters TEXT[] NOT NULL, -- z.B. ["employee_id", "project_code"]
|
||||
returns_pii BOOLEAN NOT NULL,
|
||||
schema_name TEXT NOT NULL,
|
||||
schema_version TEXT NOT NULL,
|
||||
PRIMARY KEY (data_source_id, resource)
|
||||
);
|
||||
```
|
||||
|
||||
Pro Agent-Datenquellen-Kombination gibt es OPA-Regeln (siehe Abschnitt 6).
|
||||
|
||||
### 3c. Session Scope Tokens — Delegation „Agent im Auftrag von Benutzer"
|
||||
|
||||
Problem: Der Lese-Agent muss der Datenquelle beweisen, dass er für Benutzer Y in Session S liest — nicht nur, dass er irgendein Agent ist.
|
||||
|
||||
Lösung: Der **Session Scope Token Service** (Teil von `trust-api`) stellt kurzlebige, signierte Delegations-Tokens aus. Technisch ein JWT mit `act`-Claim nach RFC 8693 (OAuth 2.0 Token Exchange — die Semantik, nicht der volle Flow).
|
||||
|
||||
Ablauf:
|
||||
|
||||
1. Benutzer meldet sich per Pocket ID an und startet eine Session im Approval Service (`POST /api/v1/sessions`). Approval Service hält `session_id`, `user_sub`, `active_until`.
|
||||
2. Agent A will für diese Session eine Datenquelle lesen. Er ruft:
|
||||
|
||||
```
|
||||
POST /api/v1/session-scope-tokens
|
||||
Authorization: Bearer <agent-pocket-id-token>
|
||||
X-Workload-Token: <k8s-sa-token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "SES-2026-10-25-abc",
|
||||
"requested_scope": {
|
||||
"data_source": "ds:expense-db-app",
|
||||
"resource": "project_assignments",
|
||||
"filters": { "employee_id": "<EMP from session>" },
|
||||
"operation": "read"
|
||||
},
|
||||
"ttl_seconds": 300
|
||||
}
|
||||
```
|
||||
|
||||
3. Der Service prüft:
|
||||
- beide Agent-Credentials (Pocket-ID + K8s SA) → `agent_id`;
|
||||
- OPA: darf `agent_id` die angeforderte Operation auf dieser Datenquelle im Namen *dieses konkreten Benutzers* ausführen? (z.B. „nur eigene Projekte, nicht fremde");
|
||||
- Session aktiv und valide?
|
||||
4. Rückgabe: Scope-Token (JWT), signiert vom trust-api-Schlüssel:
|
||||
|
||||
```json
|
||||
{
|
||||
"iss": "https://trust.basicstack.de",
|
||||
"sub": "agent-travel",
|
||||
"act": {
|
||||
"iss": "https://auth.basicstack.de",
|
||||
"sub": "user-12345",
|
||||
"session_id": "SES-2026-10-25-abc"
|
||||
},
|
||||
"scope": {
|
||||
"data_source": "ds:expense-db-app",
|
||||
"resource": "project_assignments",
|
||||
"filters": { "employee_id": "EMP-12345" },
|
||||
"operation": "read"
|
||||
},
|
||||
"jti": "<unique>",
|
||||
"iat": 1735120000,
|
||||
"exp": 1735120300
|
||||
}
|
||||
```
|
||||
|
||||
5. Agent A ruft die Datenquelle: `GET https://expense-db-adapter/api/v1/project_assignments?employee_id=EMP-12345` mit Header `Authorization: Bearer <scope-token>`.
|
||||
6. Datenquellen-Adapter prüft Scope-Token (Signatur gegen trust-api-JWKS, `exp`, `scope` deckt den Request), führt die Abfrage aus und schreibt eine **Query Attestation** (siehe 4.5a).
|
||||
|
||||
Vorteile:
|
||||
- Datenquellen müssen weder Session-State noch Benutzer-Authentifizierung selbst halten — nur Token verifizieren.
|
||||
- OPA entscheidet zentral, welche Agent-Benutzer-Kombinationen welche Lesescopes bekommen.
|
||||
- Kompromittierte Agent-Credentials erlauben nur die Scopes, die vom Session Scope Token Service herausgegeben wurden — nicht die Weltlese-Erlaubnis.
|
||||
|
||||
## 4. Datenmodell der Vertrauenskette
|
||||
|
||||
Jeder Vorgang 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) im separaten PII-Store.
|
||||
Jeder Vorgang erhält eine unveränderliche `workflow_id`. Jede Fassung der Daten wird als eigenes Artefakt mit SHA-256-Hash gespeichert. PII bleibt im separaten PII-Store; Attestierungen enthalten nur Hashes und Referenzen.
|
||||
|
||||
### Vertrauens- und Verarbeitungskette (allgemein, am Beispiel Reisekosten → beliebige Senke)
|
||||
### Vertrauens- und Verarbeitungskette (am Beispiel Reisekosten → eigene DB-App als erster Rollout)
|
||||
|
||||
1. **Benutzerfreigabe** — Approval Service bindet die Signatur an den Hash des Inhalts, den der Benutzer 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 ursprüngliche Freigabe.
|
||||
3. **Agent B: Mapping auf Senken-Datenmodell** — Agent B signiert seine eigene Attestierung mit Referenz auf die Ausgabe von Agent A.
|
||||
4. **Agent C: Senken-Übergabe** — Agent C überprüft die komplette Kette, führt die Aktion über den passenden **Senken-Adapter** aus und erzeugt nach erfolgreicher Übergabe einen signierten Übergabenachweis mit Senken-Belegreferenz.
|
||||
|
||||
Attestierungen sind keine Chatnachrichten, sondern eigenständige, überprüfbare Datensätze.
|
||||
0. **Session-Start.** Benutzer meldet sich per Passkey an, Agent-Travel beginnt den Chat.
|
||||
1. **Vorab-Lesezugriffe (parallel-Pfad).** Agent-Travel holt sich pro Lesezugriff ein Session Scope Token und ruft die Datenquelle (z.B. `ds:expense-db-app`, Resource `project_assignments`). Jeder Zugriff erzeugt eine **Query Attestation** (siehe 4.5a). Der User sieht die zurückgelieferten Vorschläge und wählt (z.B. ein Projekt).
|
||||
2. **Benutzerfreigabe.** Approval Service bindet die Signatur an den Hash des Inhalts, den der Benutzer per Content Binding bestätigt hat, UND an die Materialien-Hashes der oben erzeugten Query Attestations (siehe 4.1).
|
||||
3. **Agent A: Vorbereitung.** Agent-Travel signiert eine Transform-Attestierung über Eingabe-Hash, Ausgabe-Hash, Transformationsart, Freigabe-Referenz und die genutzten Query-Materialien.
|
||||
4. **Agent B: Mapping.** Agent-Sink-Mapping führt eigene Lesezugriffe durch (z.B. Kontierungsvorschläge → neue Query Attestations), transformiert, signiert.
|
||||
5. **Agent C: Übergabe.** Agent-Sink-Posting verifiziert die komplette Kette, übergibt an den Senken-Adapter, erzeugt den signierten Übergabenachweis.
|
||||
|
||||
### 4.0 Content Binding bei der Benutzerfreigabe
|
||||
|
||||
Risiko: der Browser könnte dem Benutzer etwas anderes zeigen als dem Approval Service.
|
||||
Risiko: der Browser könnte dem Benutzer etwas anderes zeigen als dem Approval Service. Verbindlicher Ablauf:
|
||||
|
||||
Verbindlicher Ablauf:
|
||||
|
||||
1. Approval Service rendert den Freigabe-Inhalt serverseitig, berechnet SHA-256 `H_content` und speichert `(session_id, H_content, salt)` mit einmaligem `challenge_nonce`.
|
||||
2. Browser zeigt den Inhalt *und* eine aus `H_content + challenge_nonce` abgeleitete, menschenlesbare **Prüfziffer** (z.B. 6 Zeichen Base32).
|
||||
1. Approval Service rendert den Freigabe-Inhalt serverseitig, berechnet SHA-256 `H_content` und speichert `(session_id, H_content, salt, challenge_nonce)`.
|
||||
2. Browser zeigt den Inhalt *und* eine aus `H_content + challenge_nonce` abgeleitete menschenlesbare Prüfziffer.
|
||||
3. Benutzer bestätigt per Passkey (WebAuthn-Assertion über `challenge_nonce || H_content`).
|
||||
4. Approval Service verifiziert die WebAuthn-Assertion, prüft Session-Integrität, erzeugt erst dann die DSSE-signierte Approval-Attestierung.
|
||||
4. Approval Service verifiziert die WebAuthn-Assertion und erzeugt die DSSE-signierte Approval-Attestierung.
|
||||
|
||||
Damit scheitert ein kompromittierter Browser, der etwas anderes anzeigt, am visuellen Prüfziffer-Vergleich *oder* am WebAuthn-Signaturinhalt.
|
||||
### 4.1 Benutzerfreigabe (DSSE-Statement, inkl. Query-Materialien)
|
||||
|
||||
### 4.1 Benutzerfreigabe (DSSE-Statement)
|
||||
|
||||
Beachte: `audience` zeigt auf eine **registrierte Senke** aus der Sink Registry (3b), nicht hart auf „SAP".
|
||||
Neu: `materials` referenziert die Query Attestations, deren Ergebnisse die Vorschlagsgrundlage für den Benutzer waren.
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -110,7 +213,7 @@ Beachte: `audience` zeigt auf eine **registrierte Senke** aus der Sink Registry
|
|||
"subject": [
|
||||
{
|
||||
"name": "expense/EXP-2026-0042/v1",
|
||||
"digest": { "sha256": "<64 hex characters>" }
|
||||
"digest": { "sha256": "<content hash>" }
|
||||
}
|
||||
],
|
||||
"predicateType": "https://basicstack.de/attestations/approval/v1",
|
||||
|
|
@ -128,18 +231,30 @@ Beachte: `audience` zeigt auf eine **registrierte Senke** aus der Sink Registry
|
|||
"assertion_hash": "sha256:<webauthn assertion hash>",
|
||||
"verification_code": "F3K-9MQ"
|
||||
},
|
||||
"materials": [
|
||||
{
|
||||
"name": "query/project_assignments/employee=EMP-12345",
|
||||
"sha256": "<result_hash>",
|
||||
"attestation_ref": "sha256:<query attestation hash>"
|
||||
},
|
||||
{
|
||||
"name": "query/cost_centers/active-for-EMP-12345",
|
||||
"sha256": "<result_hash>",
|
||||
"attestation_ref": "sha256:<query attestation hash>"
|
||||
}
|
||||
],
|
||||
"action": "expense.submit",
|
||||
"audience": "sink:sap-s4hana-prod",
|
||||
"audience": "sink:expense-db-app",
|
||||
"allowed_transformations": ["expense.normalize", "expense.map_to_sink"],
|
||||
"allowed_sinks": ["sink:sap-s4hana-prod", "sink:expense-db-app"],
|
||||
"nonce": "<base64 nonce for replay protection>",
|
||||
"allowed_sinks": ["sink:expense-db-app"],
|
||||
"nonce": "<base64 nonce>",
|
||||
"issued_at": "2026-10-25T10:30:00Z",
|
||||
"expires_at": "2026-11-01T00:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Neu: `allowed_sinks` erlaubt in der Freigabe explizit mehrere Zielsenken (z.B. Dual-Write SAP + eigene DB).
|
||||
Verifikation (Abschnitt 5) prüft, dass genau die hier referenzierten Query Attestations existieren, gültig signiert sind und ihre Ergebnisse den im Freigabeinhalt verwendeten Werten entsprechen (z.B. „das ausgewählte Projekt ist tatsächlich in der Ergebnisliste").
|
||||
|
||||
### 4.2 Signatur mit DSSE
|
||||
|
||||
|
|
@ -153,33 +268,35 @@ Neu: `allowed_sinks` erlaubt in der Freigabe explizit mehrere Zielsenken (z.B. D
|
|||
}
|
||||
```
|
||||
|
||||
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 den zur `issued_at` gültigen Schlüssel in der Agent Registry.
|
||||
### 4.3 Transformations-Attestierung (Agent B, Mapping)
|
||||
|
||||
### 4.3 Transformations-Attestierung (Beispiel Agent B — Mapping auf eine konkrete Senke)
|
||||
Neue Felder: `read_materials` referenziert Query Attestations, die diese Transformation genutzt hat.
|
||||
|
||||
```json
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v1",
|
||||
"subject": [
|
||||
{
|
||||
"name": "expense/EXP-2026-0042/sink-payload",
|
||||
"digest": { "sha256": "<output hash>" }
|
||||
}
|
||||
{ "name": "expense/EXP-2026-0042/sink-payload", "digest": { "sha256": "<output hash>" } }
|
||||
],
|
||||
"predicateType": "https://basicstack.de/attestations/transform/v1",
|
||||
"predicate": {
|
||||
"workflow_id": "WF-0042",
|
||||
"actor": "agent-sink-mapping",
|
||||
"operation": "expense.map_to_sink",
|
||||
"sink_target": "sink:sap-s4hana-prod",
|
||||
"sink_target": "sink:expense-db-app",
|
||||
"materials": [
|
||||
{ "name": "expense/EXP-2026-0042/normalized", "sha256": "<input hash>" }
|
||||
],
|
||||
"read_materials": [
|
||||
{ "name": "query/account_assignments/project=P-42",
|
||||
"sha256": "<result_hash>",
|
||||
"attestation_ref": "sha256:<query attestation hash>" }
|
||||
],
|
||||
"parent_attestation": "sha256:<previous proof hash>",
|
||||
"approval_ref": "APR-0042",
|
||||
"schema": {
|
||||
"input": { "name": "expense.canonical", "version": "1.0.0" },
|
||||
"output": { "name": "sink.sap.expense", "version": "1.2.0" }
|
||||
"output": { "name": "sink.db.expense", "version": "1.0.0" }
|
||||
},
|
||||
"transform_version": "1.3.0",
|
||||
"issued_at": "2026-10-25T10:31:15Z"
|
||||
|
|
@ -187,14 +304,12 @@ DSSE's Pre-Authentication Encoding (PAE) signiert Nutzlast und Inhaltstyp gemein
|
|||
}
|
||||
```
|
||||
|
||||
Agent B signiert diese Attestierung mit seinem eigenen Schlüssel. Wird dieselbe Freigabe auf eine zweite Senke abgebildet (z.B. „sink:expense-db-app"), erzeugt Agent B eine **zweite** Attestierung mit anderem `sink_target` und `output`-Schema.
|
||||
|
||||
### 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 (Postgres):** Identität plus Signatur-Schlüsselhistorie.
|
||||
- Pocket ID: als OIDC-Client (`client_id`, `client_secret` im K8s-Secret).
|
||||
- Agent Registry (Postgres): Identität plus Signatur-Schlüsselhistorie.
|
||||
|
||||
```sql
|
||||
CREATE TABLE agents (
|
||||
|
|
@ -223,22 +338,18 @@ CREATE INDEX idx_agent_keys_lookup
|
|||
WHERE archived_at IS NULL;
|
||||
```
|
||||
|
||||
**Validierung alter Attestierungen** nutzt den Schlüssel, der zur `issued_at` galt (TUF-Pattern).
|
||||
|
||||
**Retention und Performance.** Rotation Default 90 Tage, Nachweis-Retention 1 Jahr → max. ~5 nicht-archivierte Schlüssel/Agent. Nach Retention: `archived_at` wird gesetzt; Attestierungen jenseits der Retention werden explizit mit `expired_retention` abgelehnt.
|
||||
Validierung alter Attestierungen nutzt den Schlüssel, der zur `issued_at` galt (TUF-Pattern). Rotation Default 90 Tage × Retention 1 Jahr → max. ~5 nicht-archivierte Schlüssel/Agent.
|
||||
|
||||
### 4.5 Sink Registry
|
||||
|
||||
Senken sind **registrierte Entitäten** mit eigener Identität, Audit-Vertrag und — falls sinnvoll — eigenem Krypto-Schlüsselmaterial für Übergabenachweise:
|
||||
|
||||
```sql
|
||||
CREATE TABLE sinks (
|
||||
sink_id TEXT PRIMARY KEY, -- z.B. "sink:sap-s4hana-prod"
|
||||
sink_id TEXT PRIMARY KEY, -- z.B. "sink:expense-db-app"
|
||||
display_name TEXT NOT NULL,
|
||||
adapter_kind TEXT NOT NULL, -- "sap_abap" | "db_app" | "http_webhook" | "message_queue" | "file_drop" | "custom"
|
||||
endpoint_url TEXT, -- primary endpoint (sofern HTTP)
|
||||
idempotency_scope TEXT NOT NULL, -- "payload_hash" | "workflow_id" | "sink_defined"
|
||||
callback_pubkey_pem TEXT, -- optional: Senke signiert eigene Buchungsnachweise
|
||||
endpoint_url TEXT,
|
||||
idempotency_scope TEXT NOT NULL,
|
||||
callback_pubkey_pem TEXT,
|
||||
allowed_actions TEXT[] NOT NULL,
|
||||
owner_team TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL,
|
||||
|
|
@ -246,254 +357,271 @@ CREATE TABLE sinks (
|
|||
);
|
||||
```
|
||||
|
||||
Der Verification Service verifiziert bei jedem Aufruf: `requested_action ∈ sink.allowed_actions` und `sink.retired_at IS NULL`.
|
||||
### 4.5a Query Attestation (Lesezugriffs-Nachweis)
|
||||
|
||||
## 5. Verifikation beim empfangenden Senken-Adapter
|
||||
Jeder Lesezugriff eines Agenten auf eine Datenquelle erzeugt eine signierte Query Attestation. Die Attestierung enthält Query-Parameter und einen deterministischen Hash der Rückgabe — nicht die Rückgabe selbst (PII bleibt im PII-Store).
|
||||
|
||||
Der Senken-Adapter (oder — bei Thin-Client-Senken — Agent C) darf sich nicht auf die mitgesendeten IDs verlassen. Er muss die gesamte Nachweiskette prüfen.
|
||||
```json
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v1",
|
||||
"subject": [
|
||||
{
|
||||
"name": "query/project_assignments/employee=EMP-12345",
|
||||
"digest": { "sha256": "<hash of (query_params || result_hash)>" }
|
||||
}
|
||||
],
|
||||
"predicateType": "https://basicstack.de/attestations/query/v1",
|
||||
"predicate": {
|
||||
"workflow_id": "WF-0042",
|
||||
"session_id": "SES-2026-10-25-abc",
|
||||
"actor": "agent-travel",
|
||||
"data_source": "ds:expense-db-app",
|
||||
"operation": "data_source.read",
|
||||
"query": {
|
||||
"resource": "project_assignments",
|
||||
"filters": { "employee_id": "EMP-12345" },
|
||||
"query_hash": "sha256:<canonicalized query>"
|
||||
},
|
||||
"result": {
|
||||
"row_count": 3,
|
||||
"result_hash": "sha256:<canonicalized result rows>",
|
||||
"pii_class": "indirect",
|
||||
"pii_store_ref": "s3://pii-store/queries/WF-0042/SES-abc/<uuid>.json"
|
||||
},
|
||||
"on_behalf_of": {
|
||||
"iss": "https://auth.basicstack.de",
|
||||
"sub": "user-12345"
|
||||
},
|
||||
"session_scope_token_jti": "<jti of the scope token used>",
|
||||
"schema": { "name": "ds.expense.project_assignment", "version": "1.0.0" },
|
||||
"issued_at": "2026-10-25T10:28:12Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wesentlich: Die Query Attestation wird **vom Datenquellen-Adapter** erzeugt und signiert (nicht vom Agenten), damit der Agent nicht die Rückgabe fälschen kann. Der Adapter benutzt seinen eigenen Schlüssel (`ds-adapter-<name>-key-<rev>`), der in der Agent Registry mit `agent_id = "ds-adapter:<name>"` registriert ist.
|
||||
|
||||
Der PII-Anteil der Rückgabe landet im PII-Store unter `pii_store_ref`; dort gelten die normalen Retention- und Löschregeln. Verifikation nach Löschung: die Signaturkette bleibt gültig, aber `result_hash` kann dann nicht mehr gegen den Inhalt geprüft werden — das ist der bewusste Trade-off aus der DSGVO-Löschbarkeit.
|
||||
|
||||
### 4.6 Agentenregistrierung — zusätzliche Datenquellen-Berechtigungen
|
||||
|
||||
```sql
|
||||
CREATE TABLE agent_data_source_scopes (
|
||||
agent_id TEXT NOT NULL REFERENCES agents(agent_id),
|
||||
data_source_id TEXT NOT NULL REFERENCES data_sources(data_source_id),
|
||||
resource TEXT NOT NULL,
|
||||
allowed_filters TEXT[] NOT NULL,
|
||||
operation TEXT NOT NULL CHECK (operation IN ('read')),
|
||||
requires_user_context BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
PRIMARY KEY (agent_id, data_source_id, resource, operation)
|
||||
);
|
||||
```
|
||||
|
||||
Der Session Scope Token Service konsultiert diese Tabelle UND OPA (für feinere Regeln). `requires_user_context = TRUE` erzwingt, dass der Scope-Token nur mit aktiver Benutzer-Session ausgestellt wird (verhindert hintergründige Lesezugriffe ohne Benutzer).
|
||||
|
||||
## 5. Verifikation
|
||||
|
||||
```
|
||||
POST /api/v1/attestations/verify
|
||||
Authorization: Bearer <service-token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"workflow_id": "WF-0042",
|
||||
"artifact_digest": "sha256:<final hash>",
|
||||
"requested_action": "expense.post",
|
||||
"target": "sink:sap-s4hana-prod"
|
||||
"target": "sink:expense-db-app"
|
||||
}
|
||||
```
|
||||
|
||||
Prüfungen:
|
||||
Prüfungen (vollständig):
|
||||
|
||||
| Prüfung | Fehlerfall |
|
||||
| -------------------------------------------------------------------- | --------------------- |
|
||||
| Signatur der Benutzerfreigabe gültig (Schlüssel zur `issued_at` gültig)? | Ablehnen |
|
||||
| Signatur der Benutzerfreigabe gültig (Schlüssel zur `issued_at`)? | 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 |
|
||||
| `target` in Sink Registry registriert und `allowed_actions` erlaubt die Aktion? | Ablehnen |
|
||||
| Alle in Approval referenzierten Query Attestations existieren und sind gültig signiert? | Ablehnen |
|
||||
| Datenquellen zur Query-Zeit registriert und Agent berechtigt? | Ablehnen |
|
||||
| Query-Materialien konsistent mit den im Freigabeinhalt verwendeten Werten? | Ablehnen |
|
||||
| `target` in Sink Registry und `allowed_actions` erlaubt die Aktion? | Ablehnen |
|
||||
| `target` in `approval.allowed_sinks` enthalten? | 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 |
|
||||
| Alle in Transform-Attestierungen referenzierten `read_materials` existieren? | Ablehnen |
|
||||
| Transformationen laut Freigabe zulässig? | Ablehnen |
|
||||
| Schema-Version der kanonischen Daten mit Approval kompatibel? | Ablehnen |
|
||||
| Schema-Versionen kompatibel? | Ablehnen |
|
||||
| Nutzlast entspricht freigegebener Geschäftssemantik (OPA)? | Ablehnen |
|
||||
| `payload_hash` bereits für `target` übergeben? | Keine erneute Übergabe |
|
||||
|
||||
Erfolgsantwort:
|
||||
### 5.1 Replay-Schutz (verbindlich, unverändert)
|
||||
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"workflow_id": "WF-0042",
|
||||
"original_user": { "issuer": "https://auth.basicstack.de", "subject": "user-12345" },
|
||||
"actors": ["agent-travel", "agent-sink-mapping"],
|
||||
"authorized_action": "expense.post",
|
||||
"artifact_digest": "sha256:<final hash>",
|
||||
"decision_id": "DEC-2026-0042",
|
||||
"decision_nonce": "<base64>",
|
||||
"bound_to_agent": "agent-sink-posting",
|
||||
"bound_to_target": "sink:sap-s4hana-prod",
|
||||
"expires_at": "2026-10-25T10:36:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 5.1 Replay-Schutz (verbindlich)
|
||||
|
||||
- `decision_id` enthält einen `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 Doppelübergabe-Check.
|
||||
- Jeder Senken-Adapter führt eine **eigene** Replay-Tabelle (`sink_decision_log`) mit `UNIQUE (decision_id)` und `UNIQUE (payload_hash)`. Defence in Depth, denn der Trust-Core kennt die Idempotenz-Eigenschaften der Senke nicht.
|
||||
- Doppelübergabe wird gegen `payload_hash` (nicht nur `workflow_id`) geprüft.
|
||||
- `decision_id` enthält `decision_nonce`, Lebensdauer 5 Minuten.
|
||||
- Bindung an `(agent_id, payload_hash, target)`.
|
||||
- Verification Service: `UNIQUE (payload_hash, target)` in `decisions`.
|
||||
- Jeder Senken-Adapter führt eigene Replay-Tabelle `sink_decision_log`.
|
||||
- Scope-Tokens (für Reads) haben eigene `jti` und `exp`; Replay-Schutz pro Datenquelle: UNIQUE `(data_source_id, jti)` in einer kleinen `scope_token_log`-Tabelle beim Adapter (optional — die kurze TTL deckt den Normalfall).
|
||||
|
||||
## 6. Berechtigungssteuerung mit Open Policy Agent
|
||||
|
||||
Beispiel-Regeln (bewusst nicht ERP-spezifisch):
|
||||
OPA deckt **drei Policy-Klassen** ab:
|
||||
|
||||
- Agent A darf Belege extrahieren und Geschäftsdaten strukturieren.
|
||||
- Agent B darf Kontierungs- oder Zieldaten ergänzen und Felder auf das Senken-Schema zuordnen.
|
||||
- Agent B darf keine Beträge oder Währungen ohne zusätzliche Freigabe ändern.
|
||||
- Agent C darf ausschließlich vollständig validierte Vorgänge an Senken übergeben, und zwar nur an Senken aus `allowed_sinks` der Freigabe.
|
||||
- Pro Senken-Typ können zusätzliche Policies greifen (z.B. „Senke `db-app` erlaubt Updates, Senke `sap-s4hana-prod` nur Inserts").
|
||||
1. **Transformation-Policies** — welche Agenten dürfen welche Transformationen auf welchen Schemas durchführen? (unverändert aus V1.0)
|
||||
2. **Senken-Policies** — welche Agenten dürfen welche Senken für welche Aktionen nutzen? (aus V1.1 Erstfassung)
|
||||
3. **🆕 Datenquellen-/Scope-Policies** — welche Agenten dürfen welche Lesezugriffe im Namen welcher Benutzer durchführen?
|
||||
|
||||
Rego-Policies werden zentral verwaltet und versioniert; die zum Entscheidungszeitpunkt verwendete Policy-Version wird im Evidence Store mit abgelegt.
|
||||
Beispiel-Regeln für Datenquellen:
|
||||
|
||||
- Agent-Travel darf `ds:expense-db-app` → `project_assignments` lesen, aber nur gefiltert nach `employee_id` des aktuellen Benutzers (keine fremden Zuweisungen).
|
||||
- Agent-Sink-Mapping darf `ds:expense-db-app` → `account_assignments` lesen, aber nur für Projekte, die aus einer vorherigen Query Attestation desselben Workflows stammen.
|
||||
- Agent-Travel darf `ds:hr-system` → `employee_profile` NUR mit `requires_user_context=TRUE` und nur die Felder `name`, `cost_center`, nicht `salary`.
|
||||
- Agenten dürfen keine Datenquellen abfragen, deren `retired_at IS NOT NULL`.
|
||||
|
||||
Rego-Policies werden zentral versioniert; die zum Entscheidungszeitpunkt verwendete Policy-Version wird in der Query Attestation bzw. Decision mit abgelegt.
|
||||
|
||||
### 6.1 Fachliche Integritätsprüfung — Schema-Versionierung (verbindlich)
|
||||
|
||||
Ein Hashvergleich allein reicht nicht, weil sich beim Mapping das technische Format ändert. Deshalb binden wir die Freigabe an ein **versioniertes kanonisches Schema**:
|
||||
Kanonische und Senken-/Quellen-spezifische Zielschemas liegen versioniert in `schemas/` im Repo. Approval signiert `schema.name` und `schema.version` mit. Transform- und Query-Attestierungen tragen ebenfalls `schema`-Felder. Schema-Änderungen sind Breaking Changes und erfordern eine neue Hauptversion.
|
||||
|
||||
```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" }
|
||||
]
|
||||
}
|
||||
```
|
||||
## 7. Senken-Integration
|
||||
|
||||
Verbindlich:
|
||||
|
||||
- Kanonische Schemas und Senken-spezifische Zielschemas liegen versioniert in `schemas/` im Repo.
|
||||
- Jede Approval-Attestierung signiert `schema.name` und `schema.version` mit.
|
||||
- Jede Transform-Attestierung signiert Input- *und* Output-Schema plus `sink_target`.
|
||||
- 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. Senken-Integration (generalisiert)
|
||||
|
||||
Der Trust-Core ist senken-agnostisch. Jede Senke wird über einen **Senken-Adapter** angebunden, der denselben Vertrag erfüllt. SAP S/4HANA ist eine Senken-Implementierung; weitere Beispiele siehe 7.1–7.5.
|
||||
(unverändert gegenüber V1.1 Erstfassung — Vertrag in 7.0, Beispiele 7.1–7.5)
|
||||
|
||||
### 7.0 Vertrag jedes Senken-Adapters
|
||||
|
||||
Jeder Adapter MUSS:
|
||||
Jeder Adapter MUSS: verifizieren (`/api/v1/attestations/verify`), idempotent sein (`sink_decision_log` mit `UNIQUE (decision_id)` und `UNIQUE (payload_hash)`), Audit-Mindestdaten speichern, Übergabenachweis zurückgeben, Fehlerpfad definieren, serverseitige Business-ID-Mapping-Hoheit wahren.
|
||||
|
||||
1. **Verifizieren** — ruft `POST /api/v1/attestations/verify` auf (oder bettet die Verifikationslogik mit eingezogenen Schlüsseln ein) und bricht bei `valid=false` oder abgelaufener Decision ab.
|
||||
2. **Idempotent sein** — führt eine eigene Tabelle `sink_decision_log` mit `UNIQUE (decision_id)` und `UNIQUE (payload_hash)`.
|
||||
3. **Audit-Mindestdaten speichern** — pro erfolgreicher Übergabe: `workflow_id`, `approval_id`, `decision_id`, `payload_hash`, `agent_id`, `original_user_sub`, `sink_record_ref` (z.B. Belegnummer / DB-ID / Message-ID / Dateipfad), `created_at`.
|
||||
4. **Übergabenachweis zurückgeben** — signierte Antwort (ideal: Senke besitzt eigenen Schlüssel in `sinks.callback_pubkey_pem`; Fallback: Agent C signiert die unsignierte Senken-Antwort inkl. `sink_record_ref` selbst).
|
||||
5. **Fehlerpfad definieren** — nach N fehlgeschlagenen Versuchen fließt der Vorgang in eine senken-eigene Operator-Queue oder meldet strukturierten Fehler an den Trust-Core (`sink_delivery_failed`-Attestierung).
|
||||
6. **Mapping zu Business-IDs** darf nur serverseitig passieren — eine vom Agenten gelieferte Personalnummer / Benutzer-ID / Kostenstelle darf eine im Senken-System hinterlegte Zuordnung nicht überschreiben.
|
||||
### 7.1 SAP S/4HANA (später)
|
||||
|
||||
Die Verification Service-Antwort ist senken-agnostisch (`decision_id`, `bound_to_target`, `bound_to_agent`, `authorized_action`). Was die Senke damit tut, ist adapter-spezifisch.
|
||||
Siehe V1.1 Erstfassung. Phase-6-Senke, nicht Phase 4.
|
||||
|
||||
### 7.1 Beispiel: SAP S/4HANA (Senke `sink:sap-s4hana-prod`)
|
||||
### 7.2 Eigene DB-App (Phase 4 — ERSTER produktiver Rollout, kombinierter Lese- und Schreibpfad)
|
||||
|
||||
ABAP-Integrationsschicht statt direktem Agentenzugriff auf Buchungsfunktionen.
|
||||
Die eigene DB-App ist **gleichzeitig Datenquelle (`ds:expense-db-app`) und Senke (`sink:expense-db-app`)**. Ein gemeinsamer Go-Service deployed als `expense-db-adapter` mit Backing-Store `expense-db-postgres`.
|
||||
|
||||
Fluss: `Agent C` → `ABAP REST Endpoint` → `SAP-Anwendungslogik`.
|
||||
Endpunkte (Beispiel):
|
||||
|
||||
```
|
||||
POST /sap/bc/zexpense/v1/submit
|
||||
Authorization: Bearer <sap-agent-token>
|
||||
Idempotency-Key: WF-0042
|
||||
Content-Type: application/json
|
||||
# Datenquellen-Seite (Reads)
|
||||
GET /api/v1/project_assignments?employee_id=<EMP>
|
||||
GET /api/v1/account_assignments?project_code=<P>
|
||||
GET /api/v1/cost_centers?active=true
|
||||
|
||||
# Senken-Seite (Writes)
|
||||
POST /api/v1/expense/submit # Erst-Buchung
|
||||
POST /api/v1/expense/update # Nachbuchung (optional, pro OPA-Policy)
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"workflow_id": "WF-0042",
|
||||
"approval_id": "APR-0042",
|
||||
"verification_ref": "DEC-2026-0042",
|
||||
"expense_ref": "EXP-2026-0042",
|
||||
"payload_hash": "sha256:<final hash>"
|
||||
}
|
||||
Alle Reads erwarten `Authorization: Bearer <session-scope-token>`. Alle Writes erwarten `Authorization: Bearer <agent-pocket-id-token>` und rufen Verification Service.
|
||||
|
||||
Datenmodell (vereinfacht):
|
||||
|
||||
```sql
|
||||
CREATE TABLE project_assignments (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
employee_id TEXT NOT NULL,
|
||||
project_code TEXT NOT NULL,
|
||||
valid_from DATE NOT NULL,
|
||||
valid_to DATE,
|
||||
UNIQUE (employee_id, project_code, valid_from)
|
||||
);
|
||||
|
||||
CREATE TABLE account_assignments (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
project_code TEXT NOT NULL,
|
||||
cost_center TEXT NOT NULL,
|
||||
gl_account TEXT NOT NULL,
|
||||
valid_from DATE NOT NULL,
|
||||
valid_to DATE
|
||||
);
|
||||
|
||||
CREATE TABLE cost_centers (
|
||||
cost_center TEXT PRIMARY KEY,
|
||||
display_name TEXT NOT NULL,
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE expenses (
|
||||
workflow_id TEXT PRIMARY KEY,
|
||||
employee_id TEXT NOT NULL,
|
||||
project_code TEXT NOT NULL,
|
||||
cost_center TEXT NOT NULL,
|
||||
currency TEXT NOT NULL,
|
||||
total_amount NUMERIC(12,2) NOT NULL,
|
||||
payload_hash TEXT NOT NULL,
|
||||
decision_id TEXT UNIQUE NOT NULL,
|
||||
approval_id TEXT NOT NULL,
|
||||
original_user_sub TEXT NOT NULL,
|
||||
posted_by_agent TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE sink_decision_log (
|
||||
decision_id TEXT PRIMARY KEY,
|
||||
payload_hash TEXT UNIQUE NOT NULL,
|
||||
sink_record_ref TEXT NOT NULL,
|
||||
posted_by_agent TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
Vor der Buchung ruft ABAP den Validierungs-Webservice:
|
||||
Der Adapter prüft bei jeder Lese-Anfrage: Scope-Token signiert durch trust-api, Resource und Filter aus Scope-Token decken Request-Resource und -Filter, `exp` nicht abgelaufen. Danach führt er die Abfrage aus und erzeugt die Query Attestation.
|
||||
|
||||
```
|
||||
POST /api/v1/decisions/{decision_id}/replay-check
|
||||
```
|
||||
### 7.3–7.5 Weitere Senken-Typen (HTTP-Webhook, Message-Queue, Dateiablage) — unverändert aus V1.1 Erstfassung.
|
||||
|
||||
Rückgabe: ob Decision noch gültig, nicht verbraucht, an Agent C und Target gebunden.
|
||||
### 7.6 Welchen Adapter wo deployen? — unverändert.
|
||||
|
||||
**sap-agent-token** wird manuell im SAP-System hinterlegt. Rotation: neuer JWT (90 Tage) wird vom Signing Service erzeugt, Operator trägt in SM59 ein, alte und neue Token sind während Rollover parallel gültig.
|
||||
## 7a. Datenquellen-Integration
|
||||
|
||||
**SAP-Audit** liegt in Tabelle `ZAGENT_AUDIT` (`WORKFLOW_ID`, `APPROVAL_ID`, `USER_SUB`, `PERNR`, `AGENT_ID`, `PAYLOAD_HASH`, `VERIFICATION_ID`, `DECISION_ID`, `BUKRS/BELNR/GJAHR`, `CREATED_AT`), mit `UNIQUE (WORKFLOW_ID)` und `UNIQUE (DECISION_ID)`.
|
||||
### 7a.0 Vertrag jedes Datenquellen-Adapters
|
||||
|
||||
### 7.2 Beispiel: Eigene Datenbankapplikation (Senke `sink:expense-db-app`)
|
||||
Jeder Datenquellen-Adapter MUSS:
|
||||
|
||||
Minimale Senken-Variante: eine selbst gebaute Postgres-App (eigener Microservice).
|
||||
1. **Scope-Token verifizieren** — Signatur gegen trust-api-JWKS, `exp` nicht abgelaufen, Scope deckt den Request (`data_source`, `resource`, `filters`, `operation`), `jti` noch nicht verbraucht (sofern Replay-Schutz aktiv).
|
||||
2. **Query ausführen** mit genau den im Scope-Token enthaltenen Filtern — keine Erweiterung erlaubt.
|
||||
3. **Query Attestation signieren** mit eigenem Adapter-Schlüssel.
|
||||
4. **PII-Anteil der Rückgabe in den PII-Store schreiben**, Ergebnis-Hash in die Attestation stellen.
|
||||
5. **An Agent zurückliefern** — Rückgabe-Payload (für die unmittelbare Nutzung) PLUS die Query Attestation (für die spätere Verwendung in Approvals/Transforms).
|
||||
6. **Audit-Zeile schreiben** — `(workflow_id, session_id, agent_id, user_sub, data_source_id, resource, filters, result_hash, created_at)`.
|
||||
|
||||
Fluss: `Agent C` → HTTPS/mTLS → `expense-db-adapter` (Go-Service) → `expense-postgres`.
|
||||
### 7a.1 Beispiel: Eigene DB-App als Datenquelle
|
||||
|
||||
```
|
||||
POST /api/v1/expense/submit
|
||||
Authorization: Bearer <agent-c-oidc-token> # Pocket-ID-Access-Token
|
||||
Content-Type: application/json
|
||||
```
|
||||
Siehe 7.2 (kombiniert mit Senken-Seite).
|
||||
|
||||
Der Adapter:
|
||||
- verifiziert das Pocket-ID-Token gegen JWKS,
|
||||
- ruft Verification Service (`POST /api/v1/attestations/verify`),
|
||||
- schreibt in `sink_decision_log` (Idempotenz),
|
||||
- führt die Business-Insert/Update-Transaktion aus,
|
||||
- gibt `sink_record_ref` (z.B. `db:expense_app/expenses/<uuid>`) an Agent C zurück.
|
||||
### 7a.2 Beispiel: HR-System via HTTP-API
|
||||
|
||||
Idempotenz: `UNIQUE (decision_id)` und `UNIQUE (payload_hash)` in `sink_decision_log`. Business-Tabelle hat `UNIQUE (workflow_id)`.
|
||||
Externer HR-Dienst (OData/REST). Datenquellen-Adapter läuft in unserem Cluster, kapselt das Backend-Secret, mappt zwischen externem Schema und `data_source_resources`-Schema. OPA-Policy kann einzelne Felder (z.B. `salary`) ausschließen.
|
||||
|
||||
Vorteil gegenüber SAP: keine externe Krypto-Vertrauensbasis nötig; Adapter kann unmittelbar auf Agent Registry und JWKS zugreifen.
|
||||
### 7a.3 Beispiel: SAP OData-Read
|
||||
|
||||
### 7.3 Beispiel: Generischer HTTP-Webhook (Senke `sink:custom-webhook-*`)
|
||||
|
||||
Für externe Dienste, die nur „einen HTTP-POST entgegennehmen" können.
|
||||
|
||||
```
|
||||
POST <sink.endpoint_url>
|
||||
Authorization: Bearer <sink-webhook-secret> # pro Senke in Sink Registry
|
||||
X-Decision-Id: DEC-2026-0042
|
||||
X-Payload-Hash: sha256:<final hash>
|
||||
Idempotency-Key: <decision_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
Der Senken-Adapter läuft **auf unserer Seite** (nicht im externen System), weil wir die Verifikation vor dem Push durchführen müssen. Er verwaltet pro Senke:
|
||||
- Secret für `Authorization`-Header (im K8s-Secret),
|
||||
- Retry-Backoff (3 Versuche, exponentiell),
|
||||
- Rückmeldung an Agent C mit `sink_record_ref: "http:<url>:<externe-id-aus-response>"`.
|
||||
|
||||
Falls die Senke keine Response-ID liefert, generiert der Adapter eine aus `H(decision_id || endpoint_url)`.
|
||||
|
||||
### 7.4 Beispiel: Message-Queue (Senke `sink:nats-kafka-*`)
|
||||
|
||||
Für asynchrone Übergaben an interne Downstream-Systeme (Analytics, Replikation).
|
||||
|
||||
Der Senken-Adapter publiziert nach erfolgreicher Verifikation einen Event auf einem Topic. Payload enthält `workflow_id`, `decision_id`, `payload_hash` und (sofern erlaubt) den fachlichen Nutzinhalt. Idempotenz: Queue-Message-Deduplication-Key = `decision_id`. Senken-Belegnummer = Queue-Message-ID.
|
||||
|
||||
### 7.5 Beispiel: Dateiablage (Senke `sink:sftp-*`, `sink:s3-*`)
|
||||
|
||||
Für Export in Partnerumgebungen (SFTP) oder Cold-Storage.
|
||||
|
||||
Der Adapter legt eine Datei mit kanonischem Namen (`<workflow_id>_<decision_id>.json`) ab, signiert sie als DSSE und schreibt eine Index-Zeile in `sink_decision_log`. Dateipfad = `sink_record_ref`.
|
||||
|
||||
### 7.6 Welchen Adapter wo deployen?
|
||||
|
||||
| Senke | Adapter läuft bei uns | Adapter läuft im Zielsystem |
|
||||
| -------------------- | --------------------- | --------------------------- |
|
||||
| SAP S/4HANA | nein (dünner Agent C) | ja (ABAP-Endpoint + Validierungs-Webservice-Call) |
|
||||
| Eigene DB-App | ja (`expense-db-adapter`) | — |
|
||||
| HTTP-Webhook extern | ja (`webhook-adapter`) | — |
|
||||
| Message-Queue | ja (`queue-adapter`) | — |
|
||||
| Dateiablage | ja (`file-adapter`) | — |
|
||||
| Legacy (Mail/EDI) | ja (adapter spezifisch) | — |
|
||||
|
||||
Daumenregel: Wenn das Zielsystem eigene Autorisierungs-/Audit-Funktionen hat (SAP), bringen wir dort einen dünnen Verifier unter. Wenn nicht, läuft der komplette Adapter in unserem Cluster.
|
||||
Später, parallel zur SAP-Senken-Anbindung. Dann ist SAP sowohl `ds:sap-s4hana-prod` als auch `sink:sap-s4hana-prod`.
|
||||
|
||||
## 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 nachträglich zulassen. **Kein** rechtssicheres GoBD-Archiv.
|
||||
|
||||
**Retention Default: 1 Jahr.** Nach Ablauf werden Attestierungen, Decisions und zugehörige Schlüsselhistorie automatisiert gelöscht. Konfigurierbar pro Prozess-Typ *und pro Senken-Typ* (z.B. Webhook-Senken kürzer).
|
||||
Default-Retention: 1 Jahr. Attestierungen, Decisions, Query Attestations und zugehörige Schlüsselhistorie werden danach automatisiert gelöscht. Konfigurierbar pro Prozess-Typ, Senke und Datenquelle.
|
||||
|
||||
### 8.2 Datenklassen
|
||||
|
||||
| Daten | Speicherung |
|
||||
| --------------------------------------- | ---------------------------------------- |
|
||||
| Prozessstatus, Identitäten, Referenzen | PostgreSQL (`trust-postgres`) |
|
||||
| Senken-Registrierung | PostgreSQL (`trust-postgres`) |
|
||||
| Senken- und Datenquellen-Registry | 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) |
|
||||
| Geschäftsdaten + Query-Ergebnisse mit PII | PII-Store (separater S3-Bucket, redaktionierbar) |
|
||||
| Signatur- und Schlüsselhistorie | Agent Registry (Postgres), max 1 Jahr |
|
||||
| Policy-Versionen | Git-versioniert, Hash im Evidence Store |
|
||||
| Senken-Übergabenachweise | S3 + Index in `sink_decision_log` der jeweiligen Senke |
|
||||
| Policy-Versionen | Git-versioniert, Hash in Attestations |
|
||||
| Senken-Übergabenachweise | S3 + `sink_decision_log` je Senke |
|
||||
|
||||
**Strikte Trennung PII vs. Nachweis.**
|
||||
Query-Ergebnisse mit PII landen immer im PII-Store. Löschung dort invalidiert *nicht* die Signaturkette, nur die Nachkontrolle der Ergebnisse.
|
||||
|
||||
### 8.3 Warum Trillian + PostgreSQL (nicht Cassandra)
|
||||
### 8.3 Trillian + PostgreSQL (unverändert)
|
||||
|
||||
Ein Transparency Log ist ein append-only Merkle-Tree mit Inclusion Proofs und signierten Tree-Heads. Entscheidend: strikte Reihenfolge, starke Konsistenz, Inclusion Proofs in ms. Cassandra ist dafür ungeeignet (eventual consistency, Ordering nur per Partition). Trillian + PostgreSQL ist bewährt (Basis von sigstore rekor), passt in unsere bestehende Postgres-Infrastruktur und reicht für < 1 Mio Einträge/Jahr auf einer kleinen Instanz. Täglicher signierter Log-Root wird ins Backup-System gespiegelt.
|
||||
Append-only Merkle-Log mit Inclusion Proofs. Cassandra ist dafür ungeeignet (siehe V1.1 Erstfassung).
|
||||
|
||||
## 9. Deployment in Kubernetes
|
||||
|
||||
|
|
@ -502,14 +630,14 @@ identity/
|
|||
pocket-id
|
||||
|
||||
agent-trust/
|
||||
trust-api (Approval + Attestation + Agent Registry + Sink Registry + Verification)
|
||||
trust-api (Approval + Session Scope Tokens + Attestation + Agent Registry + Sink Registry + Data Source Registry + Verification)
|
||||
signing-service (eigenes Deployment, enge Trust-Boundary)
|
||||
policy-engine (OPA)
|
||||
trust-postgres
|
||||
trillian-log
|
||||
|
||||
transport/
|
||||
nats (JetStream für Agent↔Agent)
|
||||
nats (JetStream)
|
||||
|
||||
paperclip/
|
||||
paperclip
|
||||
|
|
@ -517,65 +645,57 @@ paperclip/
|
|||
agent-sink-mapping
|
||||
agent-sink-posting
|
||||
|
||||
sinks/
|
||||
expense-db-adapter (für sink:expense-db-app)
|
||||
sinks-and-sources/
|
||||
expense-db-adapter (für ds:expense-db-app UND sink:expense-db-app)
|
||||
expense-db-postgres
|
||||
webhook-adapter (für sink:custom-webhook-*)
|
||||
queue-adapter (für sink:nats-kafka-*)
|
||||
file-adapter (für sink:sftp-*, sink:s3-*)
|
||||
# SAP-Adapter läuft als ABAP im SAP-System (nicht in K8s)
|
||||
# später: webhook-adapter, queue-adapter, file-adapter
|
||||
# später: hr-api-adapter (nur Datenquelle)
|
||||
# SAP-Adapter läuft als ABAP im SAP-System
|
||||
|
||||
openbao/
|
||||
openbao
|
||||
|
||||
matrix/ (optional, Phase 5)
|
||||
synapse
|
||||
element-web
|
||||
agent-matrix-gateway
|
||||
matrix/ (optional, Phase 6)
|
||||
```
|
||||
|
||||
### 9.1 Workload-Identitäts-Prüfung (doppelt)
|
||||
### 9.1 Workload-Identitäts-Prüfung (doppelt, unverändert)
|
||||
|
||||
Der Signing Service verifiziert für jeden Request **beide** Credentials:
|
||||
|
||||
1. **Pocket-ID-Access-Token** (Header `Authorization: Bearer`) — gegen Pocket-ID-JWKS; `sub = agent-<name>` muss zu einem registrierten Agent passen.
|
||||
2. **Projected ServiceAccount-Token** (Header `X-Workload-Token`, Audience `signing-service.agent-trust`) — gegen K8s TokenReview; Namespace + ServiceAccount müssen zum Agent in der Registry passen.
|
||||
|
||||
Nur wenn beide auf denselben `agent_id` auflösen, wird signiert.
|
||||
|
||||
OpenBao Transit signiert Ed25519. Caveat: Transit kennt kein DSSE — der Signing Service berechnet die DSSE-PAE selbst und übergibt nur den Hash an Transit.
|
||||
Signing Service und Session Scope Token Service verifizieren beide: Pocket-ID-Access-Token UND projected K8s ServiceAccount-Token. Nur bei übereinstimmendem `agent_id` wird signiert bzw. ein Scope-Token ausgestellt.
|
||||
|
||||
## 10. Implementierungsreihenfolge
|
||||
|
||||
**Phase 1 — End-to-End-Skelett (3–5 Wochen)**
|
||||
Pocket ID als IdP, 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 zweistufige Kette, **eine triviale Senke** (`sink:dummy-sink` als Mock-Adapter in Go) für den vollständigen Durchlauf.
|
||||
**Phase 1 — End-to-End-Skelett (3–5 Wochen).**
|
||||
Pocket ID als IdP, Approval Service mit Content Binding, ein Testagent, Signing Service mit doppelter Identitätsprüfung, Verification Service für zweistufige Kette, triviale Mock-Senke (`sink:dummy-sink`). Noch ohne Lesepfad.
|
||||
|
||||
**Phase 2 — Agent Attestations in Breite**
|
||||
Weitere Agenten, Schlüsselrotation, in-toto-Transformationsnachweise, OPA-Policies, Policy-Versionierung.
|
||||
**Phase 2 — Agent Attestations + Lesepfad (Minimum).**
|
||||
Weitere Agenten, Schlüsselrotation, in-toto-Transformationsnachweise, **Session Scope Token Service, Data Source Registry, erste triviale Datenquelle (`ds:dummy-ds`), Query Attestations**, OPA-Policies in Rego (Transformation + Datenquelle), Policy-Versionierung.
|
||||
|
||||
**Phase 3 — Replay-Schutz, Transparency Log, Retention**
|
||||
Trillian-Deployment, Decision-Nonce-Mechanik, Decision-Replay-Tabellen, Retention-Cron-Jobs, PII-Store-Trennung.
|
||||
**Phase 3 — Replay-Schutz, Transparency Log, Retention.**
|
||||
Trillian-Deployment, Decision-Nonce-Mechanik, Retention-Cron-Jobs, PII-Store-Trennung inkl. Query-Result-PII.
|
||||
|
||||
**Phase 4 — Erste produktive Senke(n)**
|
||||
Ein echter Senken-Adapter — Reihenfolge nach Business-Priorität:
|
||||
- Variante A: **SAP S/4HANA** (ABAP-Endpunkt, serverseitige Mitarbeiterzuordnung, SM59-Rotationsprozess, Validierungs-Webservice).
|
||||
- Variante B: **Eigene DB-Applikation** (Go-Adapter mit Postgres, einfacher zu bauen, geeignet als Pilot).
|
||||
Beide Varianten nutzen denselben Senken-Vertrag aus 7.0. Welche zuerst gebaut wird, entscheidet die Produkt-Priorität.
|
||||
**Phase 4 — Eigene DB-App als kombinierte Quelle und Senke (erster produktiver Rollout).**
|
||||
`expense-db-adapter` + `expense-db-postgres`, mit `ds:expense-db-app` (Reads auf `project_assignments`, `account_assignments`, `cost_centers`) und `sink:expense-db-app` (Writes auf `expenses`). Vollständiger produktiver Reisekostenprozess: Chat-Agent liest Projektzuweisungen, Benutzer wählt und bestätigt per Passkey, Mapping-Agent liest Kontierungsvorschläge, Posting-Agent schreibt — alles kryptografisch verkettet, prüfbar, mit 1-Jahres-Retention.
|
||||
|
||||
**Phase 5 — Weitere Senken-Typen**
|
||||
HTTP-Webhook-Adapter, Message-Queue-Adapter, File-Adapter — Baumuster steht nach Phase 4, inkrementell.
|
||||
**Phase 5 — Weitere Senken-/Datenquellen-Typen.**
|
||||
HTTP-Webhook-Adapter, Message-Queue-Adapter, File-Adapter, erste externe Datenquelle (z.B. HR-API).
|
||||
|
||||
**Phase 6 — Matrix für Mensch-Chat (optional)**
|
||||
Nur Mensch↔Agent-Chat, E2EE. Agent↔Agent läuft weiter über NATS/HTTPS.
|
||||
**Phase 6 — SAP-Integration.**
|
||||
SAP S/4HANA als Senke (ABAP-Endpoint, Validierungs-Webservice, SM59-Rotation) und ggf. als Datenquelle (OData-Reads via Adapter).
|
||||
|
||||
**Phase 7 — Matrix für Mensch-Chat (optional).**
|
||||
E2EE-Chat.
|
||||
|
||||
## 11. Was bewusst anders ist als in V1.0
|
||||
|
||||
- SAP ist **eine** Senke, nicht das Ziel. Trust-Core ist senken-agnostisch, Senken sind Plug-ins mit festem Vertrag.
|
||||
- Matrix ist **nicht** Standard-Transport — nur optionale Mensch-Chat-Schicht.
|
||||
- Transparency Log ist eigene Komponente (Trillian), nicht nur Postgres-Tabelle.
|
||||
- Zwei Pfade (Schreib- und Lesepfad), beide über denselben Trust-Core.
|
||||
- Datenquellen und Senken sind symmetrische Konzepte mit festem Adapter-Vertrag.
|
||||
- Session Scope Tokens machen Delegation „Agent im Auftrag von Benutzer" explizit und auditierbar.
|
||||
- SAP ist eine mögliche Senke/Quelle, nicht das Ziel. Erster produktiver Rollout ist eigene DB-App.
|
||||
- Matrix ist optional, Phase 7.
|
||||
- Transparency Log ist eigene Komponente (Trillian).
|
||||
- Signing Service ist eigenes Deployment ab Tag 1.
|
||||
- PII-Store ist strikt getrennt vom Evidence Store.
|
||||
- Keine Unveränderbarkeits-/GoBD-Garantien — Retention 1 Jahr.
|
||||
- PII-Store strikt getrennt vom Evidence Store, inkl. Query-Result-PII.
|
||||
- Keine Unveränderbarkeits-/GoBD-Garantien.
|
||||
- Pocket ID ist alleiniger IdP.
|
||||
|
||||
## 12. Empfohlener Kernstack (Zielbild)
|
||||
|
|
@ -583,14 +703,16 @@ Nur Mensch↔Agent-Chat, E2EE. Agent↔Agent läuft weiter über NATS/HTTPS.
|
|||
| Identität | Pocket ID (Menschen + Agent-Clients) |
|
||||
| ------------- | ------------------------------------------------------------------- |
|
||||
| Workload-ID | K8s projected ServiceAccount Token + TokenReview |
|
||||
| Delegation | Session Scope Tokens (JWT mit `act`-Claim, 5-Min-TTL) |
|
||||
| Signaturen | Ed25519 / DSSE, OpenBao Transit |
|
||||
| Provenienz | in-toto v1, predicate-Namespace `basicstack.de/attestations/*/*` |
|
||||
| Autorisierung | OPA (Rego) + Approval Service |
|
||||
| Autorisierung | OPA (Rego) + Approval Service — drei Policy-Klassen (Transform/Senke/Datenquelle) |
|
||||
| Transparency | Trillian + PostgreSQL |
|
||||
| Transport | HTTPS/mTLS + NATS JetStream (Agent↔Agent); Matrix optional (Mensch) |
|
||||
| Agenten | Paperclip |
|
||||
| **Senken** | **Plug-in-Architektur** — SAP S/4HANA (ABAP), eigene DB-Apps (Go-Adapter), HTTP-Webhooks, Message-Queues, Dateiablage |
|
||||
| Senken | Plug-in-Architektur — erster Rollout: eigene DB-App. Später SAP, Webhook, Queue, Dateiablage |
|
||||
| Datenquellen | Plug-in-Architektur — erster Rollout: eigene DB-App (gleicher Adapter wie Senke). Später HR-API, SAP OData u.a. |
|
||||
| Evidence | PostgreSQL + S3 (Retention 1 Jahr) |
|
||||
| PII | Separater verschlüsselter S3-Bucket, redaktionierbar |
|
||||
| PII | Separater verschlüsselter S3-Bucket, redaktionierbar (inkl. Query-Result-PII) |
|
||||
|
||||
**Wichtigste Empfehlung bleibt:** Zuerst in Phase 1 ein vollständiger signierter Testdurchlauf mit einer trivialen Mock-Senke. Erst in Phase 4 wird die erste echte Senke angebunden — ob SAP oder eine eigene DB-App entscheidet die Produkt-Priorität.
|
||||
**Wichtigste Empfehlung:** Phase 1–3 bauen den Trust-Core samt Lesepfad mit Mock-Komponenten. **Phase 4 ist der erste produktive Durchlauf** mit eigener DB-App als kombinierter Quelle und Senke. SAP und externe Datenquellen folgen in Phase 6.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue