Make OpenAI-family strict mode routable and stop redacting payee words

Strict structured-output mode rejects uniqueItems, so every request to a
gpt-5.6-family zero-data-retention endpoint failed with HTTP 400 behind
a generic error; duplicates were already rejected server-side, so the
keyword leaves the wire schemas, pinned by a strict-keyword allowlist
test built from the ledger that hit this.

The bare-BIC redaction pattern deleted every 8- and 11-letter word —
Openbank, BAUMARKT, RACETRACKER — blinding the model to the payee it
was asked to classify and tripping the unsafe-merchant check on honest
answers. BICs now die only labeled or attached to their IBAN, account
labels join the redaction secrets, an identifier-shaped merchant name
degrades to a merchant-less proposal instead of failing the row, and a
provider error inside an HTTP 200 envelope is reported as such (numeric
code only) instead of as envelope corruption.
This commit is contained in:
Lars Nolden
2026-09-12 23:17:24 +02:00
parent ec99434002
commit c5999adb1b
8 changed files with 223 additions and 25 deletions
+14 -9
View File
@@ -148,15 +148,20 @@ this is not local AI and cannot promise that a remote provider honors policy.
Each classification sends the transaction date, signed amount, currency,
merchant and counterparty text, account institution/currency, the complete
leaf-category registry for the transaction kind, all tags and all merchants
with their real local IDs. Identifier-only redaction removes IBANs, BICs,
UUIDs, URLs/emails, labeled payment or customer references, card fragments,
long digit-bearing tokens, the row's own IDs and configured private names.
Counterparty text is intentionally retained unless it is in Private names;
this is the accepted recognition trade-off, not an anonymity guarantee.
There is no Include Amount opt-in anymore. A response records high, medium or
low confidence. Low-confidence results keep merchant and tags but use the
kind-specific unclassified category; Transactions exposes a Needs review
filter for low-confidence or fallback rows.
with their real local IDs. Identifier-only redaction removes IBANs (with a
directly attached BIC), labeled BIC/SWIFT references, UUIDs, URLs/emails,
labeled payment or customer references, card fragments, long digit-bearing
tokens, the row's own IDs, account labels and configured private names. A
bare eight- or eleven-letter word is never treated as a BIC: that shape
matches ordinary payee names, and a bank code alone reveals no more than the
institution field already sent. Counterparty text is intentionally retained
unless it is in Private names; this is the accepted recognition trade-off,
not an anonymity guarantee. There is no Include Amount opt-in anymore. A
response records high, medium or low confidence. Imports never auto-apply a
low-confidence category: the row keeps the kind-specific unclassified
category with merchant and confidence recorded. Analyse previews show the
low-confidence suggestion unselected for review. Transactions exposes a
Needs review filter for low-confidence or fallback rows.
Categories and tags have editable hints. Categories -> Propose taxonomy sends
up to 300 grouped, redacted transaction samples, then shows proposed