ADR-0013: GraphQL request mapping in the PDP ahead of policy evaluation¶
- Status: accepted
- Date: 2026-08-24 (updated 2026-11-02: the mapper only maps)
- Satisfies: P-02, S05
- Supersedes: ADR-0012
- Deliberation: REQ-17, REQ-42, demo #364, #330, PR #370, PR #371, PR #482, FTV GraphQL profile
- Implemented in: mapper/ftvgraphql.go (OpenFTV adapter), services/ftv-graphql-mapper (profile mapper), schemas/pdp-mirror (schema per FSC service), graphql_schemas.rego (schema pins), scripts/check-schema-drift.sh
Context and problem statement¶
Rules need clean, typed facts about the request instead of a raw query string. These facts are the fields, with their parent types and with their arguments as the source executes them.
The PEP passes the raw body unchanged (ADR-0002). So a component on the PDP side must turn the body into a field list. That list must be complete. If it is not complete, the PDP denies the request (REQ-17).
Decision¶
A request mapper inside the OpenFTV PDP implements the mapping function of
the FTV GraphQL profile (ftv-graphql/0.1) and nothing else. The mapper
does these things:
- It parses the GraphQL body and builds the field list. The parent type of each field comes from the bundled schema of the FSC service of the request. The arguments are as the source executes them.
- It accepts only a query operation. A mutation or subscription gives
OPERATION_NOT_SUPPORTED. - It enforces these limits:
- body: 1 MiB
- nesting depth: 64
- fragment definitions: 100
- selection depth: 64
- field records: 1000
- aliased selections: 100
- validation time: 1 second
- If a step fails, it marks the request
COVERAGE_UNVERIFIABLEwith a subcode (for examplePARSE_ERROR,LIMIT_EXCEEDED). The engine denies the request.
The mapper does not verify the consent proof. It does not call BSNk, does not pseudonymize, and reads no flow. The policy verifies the consent itself (ADR-0032). The regime follows from the evidence (ADR-0031).
The profile mapper is a separate Go module. A thin adapter connects it to OpenFTV.
Consequences¶
- Rules stay declarative. Parsing happens once, in one place, in tested Go code. The conformance vectors of the profile run as tests.
- The PDP loads one schema for each FSC service. The policy bundle pins
the digest of each schema and denies a schema that is not pinned
(
CONFIG_ERROR SCHEMA_MISMATCH). A CI job checks for drift between the pinned schema and the schema that the source executes. - The source gateway accepts only the request shape that the PDP evaluated (ADR-0033).
- The mapper is a patch on OpenFTV v0.1.0. The patch stays until the upstream project includes the profile mapper (#331). For more information, see Risks and technical debt.
- The mapper does not pseudonymize any more. So the EUDI and ASI routes put the plain BSN into the PDP input (ADR-0043, proposed).