/gs/db: pfad-erhaltende host-stabile Dokument-URLs (Entkopplung der Clients vom Storage-Backend)#3958
Merged
Merged
Conversation
Die /gs/db-Dokumentausgabe (GsService.setUserDataDocs) liefert in documents[].url bisher die rohe Storage-URL, gebaut aus dem konkreten Storage-Endpoint. Das koppelt API-/Sheet-Clients an das Storage-Backend; jede Storage-Migration aendert/zerbricht die ausgelieferten URLs. Aenderungen: - KycDocumentService.getUserFileProxyUrlMap(userDataId): bildet den Storage-Pfad einer KYC-Datei auf ihre host-stabile, proxied URL ab (<services>/file/<uid>?show, ausgeliefert von GET /kyc/file/:id). - setUserDataDocs: ersetzt vor der Ausgabe die rohe .url durch die proxied URL, sofern eine zugehoerige KycFile-Entity (uid) existiert. - Die interne Filterung partitioniert jetzt ueber den Storage-Pfad (doc.path) statt ueber die nun proxied .url - host-unabhaengig und verhaltensgleich zur bisherigen URL-Substring-Filterung. Dateien ohne KycFile-Entity (z. B. Legacy-/Spider-Dateien) haben keine uid und behalten die rohe URL als sicheren Fallback.
…ny aus Tests entfernen - neuer Test ohne Mock von getUserFileProxyUrlMap: gelistetes Blob matcht über den Storage-Pfad (b.name == user/<id>/<type>/<name>) die aus einer KycFile gebaute Proxy-Map und wird proxied; spider-/Legacy-Dokument fällt auf die rohe Storage-URL zurueck - any[] durch Partial<UserData>[] ersetzt, as-never-Casts in den neuen Tests durch typisierte Mock-Helfer (asKycFileBlobs/storageBlob) abgeloest - GsService-Konstruktion in wiederverwendbaren buildGsService-Helfer extrahiert
… sortieren - gs.service.spec: beforeEach nutzt buildGsService-Helper wieder, statt die ~22 Mocks erneut auszuschreiben (Helper nimmt appInsightsQueryService optional entgegen, damit die Tests dieselben Mock-Instanzen sehen) - getUserFileProxyUrlMap: KycFile-Zeilen vor dem Map-Aufbau deterministisch nach id aufsteigend sortieren, damit bei Re-Uploads (gleicher type+name) der neueste Eintrag konsistent gewinnt
…iant)
Die uid-basierte Proxy-URL-Form bricht aktive Konsumenten: Die Auswertungen
extrahieren den Dateinamen ueber url.split('<scope>/<id>/<type>')[1] und
brauchen daher den Storage-Pfad als Substring der URL. Die uid-Form enthaelt
diesen nicht mehr.
Statt der uid-Form wird jetzt nur der Host auf Config.frontend.services
gepinnt, der vollstaendige Storage-Pfad bleibt erhalten:
<services>/kyc/<scope>/<id>/<type>/<name>. Damit ist die URL host-stabil
(kein Storage-Backend-Host) und gleichzeitig pfad-erhaltend, der Konsumenten-
Invariant bleibt gewahrt.
- KycDocumentService.getUserFileProxyUrlMap durch toHostStableUrl(path) ersetzt
- GsService.setUserDataDocs schreibt doc.url = toHostStableUrl(doc.path)
- Tests asserten Host-Stabilitaet, Pfad-Erhalt und das Split-Parsing der
Konsumenten; Round-Trip ueber die reale KycDocumentService
…st-Imports absolut Die per-Segment-Encoding-Zeile (encodeURIComponent je Segment, Slashes erhalten) lag dupliziert in azure-storage.service.ts blobUrl und in kyc-document.service.ts toHostStableUrl. Sie wird in die geteilte statische Methode AzureStorageService.encodePath ausgelagert; beide Aufrufer nutzen sie, womit der "byte-identisch ausser Host"-Invariant strukturell erzwungen ist (Verhalten unverändert). Die neu hinzugefügten Test-Imports in gs.service.spec.ts werden gemäss CONTRIBUTING auf absolute src/-Pfade umgestellt.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Der
/gs/db-Pfad liefert indocuments[].urldie rohe Storage-URL (<storage-backend-host>/kyc/<storage-path>), gebaut aus dem konkreten Storage-Endpoint. Das koppelt die konsumierenden Clients an das jeweilige Storage-Backend: Jede Migration des Storage-Backends ändert oder zerbricht die ausgelieferten URLs.Wichtige Korrektur ggü. dem ersten Ansatz dieses PRs
Ein erster Ansatz hat
documents[].urlauf eine uid-basierte Proxy-URL (<services>/file/<uid>?show) umgestellt. Eine Konsumenten-Untersuchung hat ergeben, dass das aktive Konsumenten bricht:Die konsumierenden Auswertungen extrahieren den Dateinamen aus der URL über
Die uid-Form enthält den Storage-Pfad
<scope>/<id>/<type>/<name>nicht mehr → der Split liefertundefined→ die Dokument-Anzeige der betroffenen Auswertungen wird leer. Betroffen sind 12 aktive KYC-/Compliance-Operator-Auswertungen, davon 4 sofort brechend.Daraus folgt ein harter, nicht verhandelbarer Invariant:
documents[].urlmuss den Storage-Pfad<scope>/<id>/<type>/<name>als unveränderten Substring enthalten.Lösung: host-stabil UND pfad-erhaltend
documents[].urlwird so umgeschrieben, dass nur der Host auf die stabile Services-Domain (Config.frontend.services) gepinnt wird, der vollständige Storage-Pfad aber unverändert erhalten bleibt:Damit gilt beides:
url.split('<scope>/<id>/<type>')[1]-Parsing der Konsumenten funktioniert unverändert weiter.Die URL-Struktur ist strukturgleich zur bisherigen rohen URL (gleicher Container-Prefix
kyc, gleicher Pfad) — nur der Host ist getauscht. Das maximiert die Kompatibilität mit bestehenden Konsumenten.Änderungen
KycDocumentService.toHostStableUrl(path)(neu): Baut aus einem Storage-Pfad die host-stabile URL${Config.frontend.services}/kyc/${path}. Die Host-/URL-Form liegt bewusst hier, neben der übrigen Storage-/URL-Logik des Services; der Container-Prefix wird als benannte Konstante geführt.GsService.setUserDataDocs(...): Ersetzt vor der Ausgabe die rohe.urljedes Dokuments durchtoHostStableUrl(doc.path).doc.path) statt über die.url. Verhalten ist gleichwertig zur bisherigen URL-Substring-Filterung (der Storage-Pfad war auch in der rohen URL Substring), aber entkoppelt von der URL-Form.Offener Punkt für den API-Owner: Dereferenzierbarkeit der URL
Die gewählte Form erfüllt den Parsing-Invariant der Konsumenten (Namens-Extraktion) und ist host-stabil. Offen ist, ob die URL zusätzlich ein abrufbarer Link sein muss:
GET /kyc/file/:id). Einen pfad-basierten Serve-Endpunkt unter<services>/kyc/<storage-path>, der diese URL tatsächlich dereferenziert, gibt es nicht.Dieser Punkt ist hier explizit als bewusst offene Entscheidung dokumentiert und nicht stillschweigend vorweggenommen; Entscheidung beim API-Owner.
Bewusste Abgrenzung
getSupportData(/gs/support) liefert seinedocuments[].urlweiterhin als rohe Storage-URL. Dieser Pfad bedient ein internes Support-/Admin-Tool und ist hier bewusst nicht mitgeändert, um die Änderung auf die client-/auswertungs-sichtbare/gs/db-Ausgabe zu fokussieren. Eine Vereinheitlichung (gleicher Helper) ist als Folge-Schritt denkbar.Verwandt
AzureStorageService; dieser PR setzt die genannte Abstraktion nicht voraus. Beide zusammen würden einen Backend-Wechsel transparent machen.Verifikation
tsc --noEmit: fehlerfrei (exit 0)prettier: konform (geänderte Dateien)eslint(geänderte Dateien): keine Fehler, keinanyin den Testsjestgs.service.spec.ts: 34/34 grün, inkl. der neuen Tests:url.split('<scope>/<id>/<type>')[1]liefert weiterhin den DateinamenKycDocumentService: gelistetes Blob (b.name→doc.path) wird host-stabil + pfad-erhaltend umgeschrieben (user- und spider-Pfad)Release Checklist
Pre-Release
/gs/dbliefertdocuments[].urljetzt host-stabil (<services>/kyc/<storage-path>) statt der rohen Storage-URL; der Storage-Pfad bleibt unverändert enthalten, das bestehende Auswertungs-Parsing funktioniert weiter; keine neuen/entfernten SpaltenPost-Release
Consumer-Sync (CONTRIBUTING #4) — verifiziert
Vollständige Untersuchung der betroffenen
/gs/db-documents-Konsumenten:documents[].urlausschliesslich zum Parsen des relativen Dateinamens (url.split(<storagePath>)[1]).documents[].url.→ Die host-stabile, pfad-erhaltende Form hält das Namen-Parsing intakt → für diese Konsumenten bruchfrei. Ein pfad-dereferenzierender Server-Endpunkt ist für diese Änderung nicht erforderlich.
Offene Punkte (bewusst, Owner-Entscheid)
/gs/db-documents-Konsumenten wurde geprüft, dass keinerdocuments[].urldirekt klickt/abruft — sie parsen nur den Dateinamen und bauen den klickbaren Link unabhängig (separate Basis + Zugriffstoken) bzw. zeigen die Spalte nur an. Die host-stabile URL muss daher NICHT dereferenzierbar sein; ein pfad-basierter Serve-Endpunkt ist für die heutigen Konsumenten nicht erforderlich (falls künftig nötig, separat ergänzbar).toHostStableUrlenkodiert Pfadsegmente identisch zur früheren rohen Blob-URL (per-SegmentencodeURIComponent, Slashes erhalten) → byte-identisch ausser Host (echter Drop-in), der extrahierte Dateiname-Suffix bleibt unverändert.