Scoped Mandate — ein Mandat, viele Einkäufe, eine SCA
Ein KI-Agent kauft im Namen des Nutzers ein. Der Nutzer erteilt der Sparkasse einmal per Face ID ein begrenztes Mandat; danach prüft die Bank jede Zahlung gegen Limits, Händler und Gültigkeit, der Händler prüft die Warengruppen und signiert eine Attestation, der Agent handelt mit eigener Identität und eigenem Schlüssel. Die Wallet entscheidet nie über Zahlungen — sie zeigt den Stand der Bank und kann widerrufen.
Zielbild: ARF, PaSO, SPAA Interface Specification API-Referenz
Auf einen Blick
Drei Bilder, die ganze Idee: ① Der Nutzer erlaubt einmal — das ist die einzige Freigabe. ② Der Agent kauft ein, ohne Rückfrage, innerhalb der Grenzen. ③ Händler und Bank sagen Nein, wenn etwas nicht passt — und der Nutzer hat jederzeit das letzte Wort.
%%{init: {'look':'handDrawn','theme':'base','themeVariables':{
'fontFamily':'"Comic Neue","Patrick Hand",cursive','fontSize':'17px',
'primaryColor':'#ffffff','primaryBorderColor':'#3a3e45','primaryTextColor':'#2b2f36',
'lineColor':'#3a3e45','clusterBkg':'#fbfbfc','clusterBorder':'#b4b9c1','edgeLabelBackground':'#ffffff','titleColor':'#2b2f36'}}}%%
flowchart TB
subgraph P1["① Einmal erlauben"]
direction LR
N1["👤 Nutzer
„Mein Agent darf Lebensmittel kaufen:
bis 60 € je Einkauf, 300 € gesamt.“"]
W1["📱 Wallet
zeigt alles an —
Face ID, ein einziges Mal"]
B1["🏦 Sparkasse
hält das Mandat
und die Grenzen"]
N1 --> W1 --> B1
end
subgraph P2["② Der Agent kauft ein"]
direction LR
A2["🤖 Agent
„2 Milch, Brot, Spülmittel“"]
H2["🧺 Kiezmarkt
prüft die Warengruppen,
stempelt den Korb"]
B2["🏦 Sparkasse
prüft die Grenzen,
zahlt per SCT Inst"]
R2["🧾 Beleg
an den Nutzer"]
A2 --> H2 --> B2 --> R2
end
subgraph P3["③ Grenzen gelten"]
direction LR
X3["🍺 „… und ein Bier?“"] -- „Nein“, sagt der Händler --> H3["🛒"]
Y3["💸 Mehr als 60 €?"] -- „Nein“, sagt die Bank --> B3["🏦"]
Z3["👤 „Widerrufen!“"] -- jederzeit --> B4["🏦 keine Zahlung mehr"]
end
P1 ~~~ P2 ~~~ P3
classDef nutzer fill:#fff0f2,stroke:#e60013,stroke-width:2px
classDef bank fill:#ffe5e8,stroke:#e60013,stroke-width:2px
classDef wallet fill:#eef2ff,stroke:#3a3e45
classDef agent fill:#f3f4f6,stroke:#3a3e45
classDef haendler fill:#e6f6f0,stroke:#0f8b8d,stroke-width:2px
classDef beleg fill:#fffbe6,stroke:#b26a00
class N1,Z3 nutzer
class B1,B2,B3,B4 bank
class W1 wallet
class A2 agent
class H2,H3 haendler
class R2 beleg
class X3,Y3 agentIm Detail: der Ablauf als Sequenzdiagramm
Flows A (Agent-Identität, einmalig), B (Mandat und SCA), C (Einkauf) und D (Ablehnung, Widerruf). Jede Entscheidung liegt bei Bank oder Händler — die Wallet zeigt an und bestätigt, der Agent führt aus. Nummern = Reihenfolge der Nachrichten.
%%{init: {'theme':'base','themeVariables':{
'fontFamily':'Sparkasse, system-ui, sans-serif','fontSize':'14px',
'primaryColor':'#ffe5e8','primaryBorderColor':'#e60013','primaryTextColor':'#2b2f36',
'actorBkg':'#f3f4f6','actorBorder':'#9aa0a8','actorTextColor':'#2b2f36',
'signalColor':'#3a3e45','signalTextColor':'#3a3e45',
'noteBkgColor':'#fff0f2','noteBorderColor':'#e60013','noteTextColor':'#2b2f36',
'labelBoxBkgColor':'#f3f4f6','labelBoxBorderColor':'#9aa0a8','labelTextColor':'#2b2f36',
'loopTextColor':'#515761','activationBkgColor':'#ffe5e8','activationBorderColor':'#e60013',
'sequenceNumberColor':'#fff'}}}%%
sequenceDiagram
autonumber
actor N as Nutzer
participant W as Wallet (EUDIPal)
participant A as Agent
participant B as Bank (Mandate Service)
participant H as Händler (Merchant Service)
rect rgb(243, 244, 246)
Note over N,A: Flow A — Agent registrieren (einmalig)
N->>W: Shopping-Agent aktivieren
W->>A: Identität anlegen
A->>A: P-256-Key im Secure Enclave (eigener Scope, ohne Biometrie)
A->>A: Credential: Agent + Betreiber, agent_id aus dem Key
A-->>W: Name, Betreiber, Credential-Hash
Note over A: Phase 2: Credential kommt EBW-signiert vom Betreiber
end
rect rgb(255, 240, 242)
Note over N,B: Flow B — ein Mandat, eine SCA
N->>A: „Kauf mir Milch, Brot, Spülmittel"
A->>B: POST /mandate-requests (Scopes, agent_credential, JWK)
B->>B: Agent + Anbieter prüfen (Hash, Key)
B-->>A: mandate_request_id, transaction_data
A->>W: Consent anzeigen
W->>N: Mandat anzeigen (Grenzen, Händler, Warengruppen)
N->>W: Face ID — SCA mit Mandatstext
W->>W: Hash über die angezeigten transaction_data
W->>B: POST /mandates/authorize (hash, amr)
B-->>W: Mandat aktiv (Spiegel)
end
rect rgb(243, 244, 246)
Note over A,H: Flow C — Einkauf ohne Rückfrage
A->>H: GET /catalog?q=…
H-->>A: Artikel, Preise, Warengruppen
A->>H: POST /attest (Warenkorb, functional_scope, agent)
H->>H: Fach-Scope prüfen
H-->>A: signierte Attestation
A->>A: Signatur prüfen, Zahlungsauftrag signieren (agent_proof)
A->>B: POST /payments (Hashes, Betrag, agent_proof)
B->>B: Payment-Scope prüfen (Limits, Händler, Gültigkeit, Signatur)
B-->>A: Beleg — SCT Inst, Rest im Mandat
A-->>N: Positionen, Summe, Beleg
end
rect rgb(255, 240, 242)
Note over N,H: Flow D — Ablehnung und Widerruf
alt Händler lehnt ab (z. B. Bier, category_excluded)
H-->>A: 422 rejected_by: merchant
A-->>N: „Händler: Alkohol ist im Mandat ausgeschlossen"
else Bank lehnt ab (z. B. limit_exceeded)
B-->>A: 422 rejected_by: bank
A-->>N: „Bank: Betrag über dem Limit je Einkauf"
end
N->>B: Widerruf (Wallet, S-App, Dashboard)
B-->>N: Mandat widerrufen — keine weitere Zahlung
endDie vier Parteien
Stand und Ausblick
Der komplette Ablauf läuft end-to-end und live: Ein Nutzer erteilt der Sparkasse einmal per Face ID ein begrenztes Mandat, danach kauft ein KI-Agent im Chat eigenständig beim Kiezmarkt ein; die Bank prüft jede Zahlung gegen das Mandat, der Händler prüft die Warengruppen, und jede Ablehnung nennt Partei und Grund. Alle drei Parteien haben einen eigenen Bildschirm, die Schnittstellen sind als Spezifikation und OpenAPI 3.1 dokumentiert. Bank und Händler sind bewusst Mocks mit stabilen Schnittstellen.
Detaillierte Roadmap mit Aufwänden, Entscheidungen und Konformitäts-Checkliste: interner Bereich (Anmeldung).
Dokumente
API-Referenz
Maschinenlesbar für Partner: OpenAPI 3.1, gerendert mit Redoc; die Roh-YAML liegt hier und bei jedem Service unter /openapi.yaml.
https://bank.s-you.me · YAML · liveOpenAPI 3.1Händler — Merchant Service APIDiscovery mit Signing-Key, Katalog, Attestation, Prüf-Log. OpenAPI 3.1.https://shop.s-you.me · YAML · liveLive-Systeme
Öffentlich erreichbar, keine Anmeldung. Alles läuft in Frankfurt (Google Cloud Run, europe-west3).
Quick start
curl -s https://bank.s-you.me/.well-known/mandate-service | jq .
curl -s 'https://shop.s-you.me/catalog?q=milch' | jq .
# kompletter Bank-Flow B/C/D mit echtem P-256-Agenten-Key (29 Checks)
uv run --python 3.12 --with 'cryptography==43.0.3' python tools/mock-bank/smoke_test.py https://bank.s-you.me
In der App (Build ≥ 751): Chat → „Kauf mir 2 Milch, Brot und Spülmittel“ → Freigabe-Sheet → Face ID → Beleg. „Und ein Bier dazu“ → der Händler lehnt ab, der Agent sagt wer und warum. „Was hat der Agent gekauft?“ → Log der Bank. „Widerrufen“ → danach lehnt die Bank jede Zahlung ab.