Goal
Generate goAML-conform XML for an MROS report so a compliance officer can download it from DFX and upload it to the goAML web portal.
Phase 1 (data capture) is split across PRs #3621 / #3623 / #3624 / services #1074. This issue is for Phase 2 — the actual XML output.
Scope
Backend (this repo)
-
GoAmlXmlBuilder service in src/subdomains/supporting/mros/
- Assembles the report from:
Mros entity (status, reportCode, submissionDate, authorityReference, caseManager, reason, action, indicators, personOverrides, transactions)
UserData (firstname, surname, birthday, nationality, address, phone, mail, identDocument*) — with Mros.personOverrides taking precedence
- Linked
Transaction[] for the activity / transaction sections
Config.mros for fixed DFX data (rentity_id, entity_reference template, location address, currency CHF, DFX as reporting entity)
- Maps to goAML schema 5.0.2 elements (
<report> envelope → <reason> / <action> / <activity> / <transaction> / <indicators>)
- Output: well-formed XML string, namespace
http://www.unodc.org/goaml
-
XSD validation via libxmljs2 (or equivalent)
- Loads the goAML XSD (vendor folder or download cache)
- Validates the generated XML before returning
- Returns structured error list when invalid (so the frontend can show what's missing)
-
Endpoint GET /mros/:id/xml
- Auth:
RoleGuard(UserRole.COMPLIANCE)
- Default: validate + return XML with
Content-Type: application/xml and Content-Disposition: attachment; filename="goaml-SAR-{mros.id}-{entityReference}.xml"
- Alt query
?validate=only returns the validation error list (200 with empty array if clean) so the UI can run a pre-flight check
-
Config (src/config/config.ts):
mros.rentityId (DFX's goAML entity ID, env-var-backed)
mros.location (Bahnhofstrasse 7, 6300 Zug, CH, type "Geschäft")
Frontend (DFXswiss/services)
- Download button on the MROS edit page (now at
compliance/mros/:id)
- Pre-flight "Validate" button that calls
?validate=only and shows missing-field hints
- Open as a separate services PR; this issue tracks the backend deliverable
Dependencies
Both must be merged + deployed before Phase 2 work starts in earnest, since the XML builder reads from those fields.
References
Out of scope (later phases)
- Attachments (Formular A, Identifikationsdokumente, Transaktionsbelege as embedded files in the XML)
- Report types other than SAR
- Direct submission to goAML (no public API; manual XML upload remains)
- Reject/Revert flow (
prev_rejected_ref_number)
Goal
Generate goAML-conform XML for an MROS report so a compliance officer can download it from DFX and upload it to the goAML web portal.
Phase 1 (data capture) is split across PRs #3621 / #3623 / #3624 / services #1074. This issue is for Phase 2 — the actual XML output.
Scope
Backend (this repo)
GoAmlXmlBuilderservice insrc/subdomains/supporting/mros/Mrosentity (status, reportCode, submissionDate, authorityReference, caseManager, reason, action, indicators, personOverrides, transactions)UserData(firstname, surname, birthday, nationality, address, phone, mail, identDocument*) — withMros.personOverridestaking precedenceTransaction[]for the activity / transaction sectionsConfig.mrosfor fixed DFX data (rentity_id, entity_reference template, location address, currency CHF, DFX as reporting entity)<report>envelope →<reason>/<action>/<activity>/<transaction>/<indicators>)http://www.unodc.org/goamlXSD validation via
libxmljs2(or equivalent)Endpoint
GET /mros/:id/xmlRoleGuard(UserRole.COMPLIANCE)Content-Type: application/xmlandContent-Disposition: attachment; filename="goaml-SAR-{mros.id}-{entityReference}.xml"?validate=onlyreturns the validation error list (200 with empty array if clean) so the UI can run a pre-flight checkConfig (
src/config/config.ts):mros.rentityId(DFX's goAML entity ID, env-var-backed)mros.location(Bahnhofstrasse 7, 6300 Zug, CH, type "Geschäft")Frontend (DFXswiss/services)
compliance/mros/:id)?validate=onlyand shows missing-field hintsDependencies
Both must be merged + deployed before Phase 2 work starts in earnest, since the XML builder reads from those fields.
References
Out of scope (later phases)
prev_rejected_ref_number)