Profielservice ontwikkeld door MijnOverheid Zakelijk. Een service voor het opslaan en delen van contactgegevens en kanaalvoorkeuren.
  • Java 98.4%
  • Shell 1.4%
  • Dockerfile 0.2%
Find a file
Jordy Onrust 391f2adb2f
build: zet openapi-generator op 7.25.0 en herstel het absolute inputSpec-pad (#182)
* build: zet openapi-generator op 7.25.0 en herstel het absolute inputSpec-pad

Het relatieve inputSpec-pad was een workaround voor plugin 7.10.0. Met
${project.basedir} maakt Maven op Windows er C:\... van, en de swagger-parser
in 7.10.0 struikelt daarover. Nagespeeld op Linux — het gaat om pure
string-naar-URI-verwerking, dus het reproduceert platformonafhankelijk — met
een spec onder een map die letterlijk "C:" heet:

    gen 7.10.0, inputSpec C:\proj\...\openapi.yaml
      java.net.URISyntaxException: Illegal character in opaque part at index 2
      0 gegenereerde bestanden
    gen 7.25.0, zelfde pad
      22 gegenereerde bestanden

De URI-parser leest "C" als scheme en de rest als opaque part, waarin de
backslashes niet zijn toegestaan. Swagger-parser 2.1.46 (via generator 7.25.0)
normaliseert de backslashes in resolve() voordat de URI gebouwd wordt;
2.1.22 (via 7.10.0) deed dat alleen in readContentFromLocation.

Het relatieve pad heeft een eigen probleem: het wordt opgelost tegen de cwd van
Maven, niet tegen de moduleroot. Gemeten op deze branch, `mvn -f <pom>` vanuit
een andere map:

    voor  0 bestanden, "Could not find src/main/resources/META-INF/openapi.yaml
          on the classpath"
    na    22 bestanden

LET OP: de bump verandert de foutrespons bij een ontbrekend verplicht veld.
7.25.0 genereert een @JsonCreator-constructor met @JsonProperty(required =
true) voor alle 22 DTO's, waardoor Jackson de fout opwerpt vóór de
bean-validatie. POST /contactgegeven zonder "type" en "waarde", gemeten:

    7.10.0  {"status":400,...,"violations":[{"field":"type","in":"body",
            "message":"must not be null"},{"field":"waarde",...}]}
    7.25.0  {"status":400,...,"detail":"Malformed request body","field":"type"}

De status blijft 400 en HttpValidationProblem staat op additionalProperties:
true, dus de contractvalidatie accepteert beide vormen. Voor een consument
verandert er wel iets: geen violations-array meer, en alleen het eerste
ontbrekende veld. Geen enkele test dekt dit geval; vandaar de meting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnyKkqYJbqJ4q1vVo8x9WQ

* test: leg de foutvorm bij een ontbrekend verplicht veld vast

Sinds generator 7.25.0 zet elke DTO een @JsonCreator met
@JsonProperty(required = true) op de verplichte velden. Jackson wijst een
onvolledige body daardoor af vóór de bean-validatie, met een andere vorm: een
detail "Malformed request body" en het eerste ontbrekende veld in field, in
plaats van een violations-lijst met alle overtredingen.

Beide vormen zijn 400 en passen op HttpValidationProblem, dat
additionalProperties: true heeft en geen required kent, dus de
contractvalidatie ziet het verschil niet. Voor die blinde vlek is deze test.

Nagemeten dat hij het verschil ook echt pakt: met de pom van main (generator
7.10.0) vallen beide tests om op "JSON path detail doesn't match. Expected:
Malformed request body, Actual: null".

De tegenhanger — een verplicht veld dat er wél staat maar blanco is, en dus op
de bean-validatie valt — staat al in BlancoWaardenIntegrationTest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnyKkqYJbqJ4q1vVo8x9WQ

* docs: werk de inputSpec-regel in CLAUDE.md bij

CLAUDE.md zei dat inputSpec relatief blijft omdat een absoluut pad de build op
Windows breekt. Dat gold voor generator 7.10.0; met de bump naar 7.25.0 in
dezelfde branch klopt het niet meer, en het relatieve pad heeft een eigen
probleem — het wordt opgelost tegen de cwd van Maven.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnyKkqYJbqJ4q1vVo8x9WQ

---------

Co-authored-by: Jordy Onrust <285647185+jonrust-minbzk@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 10:39:37 +02:00
.clusterfuzzlite Postgres opstarten voor de test (#128) 2026-09-02 10:36:18 +02:00
.github build(deps): Bump the codeql-action group across 1 directory with 3 updates (#176) 2026-09-14 11:42:57 +02:00
.mvn/wrapper Postgres opstarten voor de test (#128) 2026-09-02 10:36:18 +02:00
docs 594 ldv logboek emailverificatie (#146) 2026-09-03 15:52:12 +02:00
src build: zet openapi-generator op 7.25.0 en herstel het absolute inputSpec-pad (#182) 2026-09-16 10:39:37 +02:00
.dockerignore Setting up fuzzing to run in pipelines 2026-02-18 13:13:16 +01:00
.gitattributes AccCriteria (#82) 2026-06-18 12:19:21 +02:00
.gitignore Java 21 → 25 (Quarkus 3.37) (#115) 2026-08-05 11:45:20 +02:00
CLAUDE.md build: zet openapi-generator op 7.25.0 en herstel het absolute inputSpec-pad (#182) 2026-09-16 10:39:37 +02:00
CODE_OF_CONDUCT.md Voeg ontbrekende community-documenten toe (#768) 2026-08-03 15:02:06 +02:00
CONTRIBUTING.md Postgres opstarten voor de test (#128) 2026-09-02 10:36:18 +02:00
docker-compose.yml Add ClickHouse service to docker-compose (#25) 2026-01-28 14:21:32 +01:00
FUZZING.md 709 - Logboek-subject-id: keyed HMAC met pepper (#147) 2026-08-26 09:18:25 +02:00
GOVERNANCE.md ADR-0012 Open Source documentatie toevoegen (#37) 2026-03-17 13:22:39 +01:00
LICENSE Add LICENSE file 2026-01-15 13:02:31 +01:00
mvnw c# naar quarkus en nieuwe datamodel 2025-11-13 11:52:24 +01:00
mvnw.cmd Herstel LF-normalisatie van mvnw.cmd (#150) 2026-08-19 09:49:21 +02:00
pom.xml build: zet openapi-generator op 7.25.0 en herstel het absolute inputSpec-pad (#182) 2026-09-16 10:39:37 +02:00
publiccode.yml ADR-0012 Open Source documentatie toevoegen (#37) 2026-03-17 13:22:39 +01:00
quarkus.md Quarkus informatie uit README.md en inleiding toegevoegd (#23) 2026-01-21 16:26:51 +01:00
README.md Postgres opstarten voor de test (#128) 2026-09-02 10:36:18 +02:00
SECURITY.md Voeg concrete reactietermijnen toe aan SECURITY.md 2026-08-03 15:26:59 +02:00
SUPPORT.md ADR-0012 Open Source documentatie toevoegen (#37) 2026-03-17 13:22:39 +01:00

Profiel Service

Project Development Status OpenSSF Scorecard

De Profiel Service stelt burgers en ondernemers in staat om op één vertrouwde plek hun contactgegevens en communicatievoorkeuren te beheren, en biedt overheidsinstanties via federatieve koppelingen veilige, actuele en herbruikbare profielinformatie voor persoonlijke en efficiënte dienstverlening.

Documentatie over de Profiel Service is te vinden op de documentatie website van MijnOverheidZakelijk.

Status

Levenscyclus: development (zie publiccode.yml). De service draait in een POC-omgeving en wordt voorbereid op landing op de Logius Private Cloud (LPC).

API

  • Base path: /api/profielservice/v1
  • OpenAPI spec: /openapi.json
  • Swagger UI: /docs
  • Health en metrics: op aparte management-port 9090 onder /q/health en /q/metrics (niet via de publieke port).

De API volgt de NL GOV API Design Rules 2.1.0. Foutmeldingen volgen RFC 9457 (application/problem+json).

Contract-first

Het contract in src/main/resources/META-INF/openapi.yaml is de bron. Annotatie-scanning staat uit (mp.openapi.scan.disable=true), dus datzelfde bestand wordt statisch op /openapi.json geserveerd én voedt de codegen: openapi-generator-maven-plugin maakt er tijdens generate-sources de request- en response-DTO's uit, in nl.rijksoverheid.moz.api.generated.model.

Praktisch betekent dat: schrijf geen DTO met de hand en bewerk niets onder target/generated-sources — pas het contract aan en draai de build opnieuw. De controllers zijn wél handgeschreven (generateApis=false, zie de toelichting in pom.xml); RouteDekkingTest bewaakt dat ze paden en methodes van het contract blijven volgen.

Lokaal draaien

Vereisten:

  • Java 25
  • Maven (of de meegeleverde wrapper ./mvnw)
  • PostgreSQL voor quarkus:dev (zie docker-compose.yml); de tests starten hun eigen embedded PostgreSQL
# Database opstarten (zie docker-compose.yml)
docker compose up -d

# Dev-modus (live reload, http://localhost:8080)
./mvnw quarkus:dev

# Tests (starten zelf een embedded PostgreSQL, geen Docker nodig)
./mvnw verify

Configuratie

Lokale ontwikkel-secrets horen in een gitignored src/main/resources/application-dev.properties:

  • notifynl.emailverificatie.api-key, template-id, reference — van https://admin.notifynl.nl/, vraag het team voor toegang.
  • quarkus.datasource.* — alleen nodig als je geen docker compose gebruikt.

Productie-configuratie staat in de deployment-repo.

hash.pepper

HashHelper pseudonimiseert identificatienummers (BSN/KVK/RSIN) tot het subject-id in het Logboek Dataverwerkingen met een keyed HMAC-SHA-256. De sleutel komt uit hash.pepper; zonder die sleutel is een hash over een BSN triviaal terug te rekenen.

application.properties bevat een dev/test-placeholder. Prod en acc krijgen een eigen geheime waarde uit het secret; de lege %prod/%acc-override staat in de deployment-repo, dus daar start de applicatie niet op zonder waarde. Deze repo zet die override niet, dus een ZAD-preview zonder HASH_PEPPER valt terug op de placeholder hierboven in plaats van te falen. Zie docs/zad-deploy.md.

Het pseudoniem is stabiel zolang de pepper gelijk blijft. Bij het roteren van de pepper krijgen alle subjecten een nieuw pseudoniem en correleren oude logboekregels niet meer met nieuwe.

Quarkus

Dit project draait op Quarkus. Meer informatie hierover staat in quarkus.md.

Circuit breaker voor de Verificatie-service API

Bij herhaalde fouten in de communicatie met de externe verificatie-service (bijvoorbeeld door netwerkproblemen of uitval) wordt de circuit breaker actief. Na een configureerbaar aantal mislukte aanroepen gaat het circuit open: nieuwe verzoeken worden direct afgewezen zonder dat er opnieuw een verbinding wordt geprobeerd. Dit voorkomt dat de applicatie vastloopt op trage of niet-reagerende externe diensten. Na een wachttijd gaat het circuit in half-open toestand en worden nieuwe aanroepen opnieuw toegestaan om te testen of de externe dienst hersteld is.

De circuit breaker is gedeeld tussen de twee aanroepen naar de verificatie-service (requestEmailVerificationCode en verifieerEmail). Dit betekent dat herhaalde fouten op het ene endpoint ook het andere endpoint beschermen: als de verificatie-service voor de ene aanroep niet bereikbaar is, is dat hoogstwaarschijnlijk voor de andere ook het geval. De gedeelde circuit breaker wordt beheerd via VerificatieServiceGuard.

Circuit breaker instellingen

De circuit breaker wordt geconfigureerd via de volgende properties in application.properties. De waarden in de code gelden als standaardwaarden en kunnen per omgeving worden overschreven.

  • verificatie-service.circuit-breaker.request-volume-threshold: Minimum aantal aanroepen binnen het meetvenster voordat het circuit kan openen (standaard 5).
  • verificatie-service.circuit-breaker.failure-ratio: Drempelwaarde voor het percentage mislukte aanroepen waarboven het circuit opent (standaard 1.0 — circuit opent alleen bij volledige uitval).
  • verificatie-service.circuit-breaker.delay: Wachttijd in seconden in de open toestand voordat het circuit half-open gaat (standaard 30).
  • verificatie-service.circuit-breaker.success-threshold: Aantal opeenvolgende successen in half-open toestand dat nodig is om het circuit te sluiten (standaard 2).

Contracttesting

De Profiel Service maakt gebruik van contracttesting om te waarborgen dat wijzigingen aan de API consumenten niet ongemerkt breken.

Hoe het werkt

  • OpenAPI-schemavalidatie: elke integratietest valideert automatisch dat verzoeken en antwoorden overeenkomen met de OpenAPI-specificatie die de draaiende service publiceert (/openapi.json).
  • Pact-providerverificatie: pact-bestanden (JSON) in src/test/resources/pacts/ beschrijven de verwachte contracten. De provider test verifieert dat de service hieraan voldoet. Het huidige bestand moza-profiel-service.json is een zelftestcontract van de provider zelf.

Contracten bijdragen als consument

Ben je consument van de Profiel Service API en wil je een contract bijdragen? Neem dan contact op met het team om dit samen te bespreken. We stellen dan samen een pact-bestand op dat de verwachtingen van jouw toepassing beschrijft.

Een Pact Broker is een mogelijke toekomstige stap, afhankelijk van de behoefte van het team.