Ga naar inhoud

Demo increments

A demo increment (ID SL-NN) is a bounded piece of demo work. Each increment proved part of the design and produced requirements, findings, and open questions. The IDs are stable anchors: the design to demo matrix, the findings, the open questions, and the requirement pages refer to them. The issues and pull requests of ICTU/GBO-demo track the work itself.

Each increment entry uses the same fields:

  • Status values: done, planned, blocked, dropped, merged, or partly covered.
  • Demo work: links go to ICTU/GBO-demo only. The public repository started with v0.1.0 on July 20, 2026. Increments SL-01a to SL-42 were built before that date, so they have no public pull request. The code that they produced is in the public history from v0.1.0.
  • Produced: the IDs that the increment created or changed. If a later increment replaced the result, the entry names the successor.
  • Explained in: the TO page that explains the result.

Demo work outside increments lists the demo work that was not part of an increment.

Increments

SL-01a: Consent TTL and finer denial reasons

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the consent register (toestemmingsregister) sets an expiry time, and the policy denies an expired consent. If the expiry time is missing or unreadable, the policy also denies. The policy gives a separate reason code for each failed check (not found, withdrawn, expired, scope mismatch, and field not in consent).
  • Produced: REQ-19, REQ-06 (made more precise), and part of F-04.
  • Explained in: Consent

SL-01b: Single use and status machine

  • Status: blocked
  • Demo work: none.
  • What it showed: not built. The increment waited on Q-04 (single use or repeatable). Q-04 is answered: FR-DvTP v0.9 makes a consent repeatable within its validity period, so single use is not necessary. The status "retrieved" from FR-22 is open: Q-42 asks who marks a consent as retrieved, and when.
  • Produced: rest of F-04 (closed), F-19.
  • Explained in: Consent

SL-02: Pseudonymization in the path

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the demo kept the BSN away from private consumers without a decision on the pseudonym form (Q-01). The consent register stored a polymorphic identity (PI) instead of the BSN. The PEP resolved the BSN only after an allow. For a denied request, the PEP did not resolve the BSN at all.
  • Produced: REQ-20 and REQ-21. Later, the conversion moved to the source gateway (SL-22). Since SL-51, the proof carries a value per source, and the source decrypts it after the decision.
  • Explained in: Pseudonymization

SL-03a: AST field parsing in OPA

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the policy parses the real GraphQL query, with schema validation, instead of a regex in the PEP. The fields in the query must be a subset of the allowed fields of the scope. If a query does not parse, it gets a deny.
  • Produced: REQ-17, and model B (field allowlist) for Q-14.
  • Explained in: Authorization

SL-03b: Constraint axis (4b) and two-schema model

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the policy checked that the query carried the consent ID and that it matched the authorization context. A consumer-facing schema without BSN stood next to the internal source schema, and the PEP translated between them.
  • Produced: REQ-25 to REQ-27 (removed later, successors REQ-79 and REQ-17), and REQ-06 (new reason codes). Later, the query translation moved to the source gateway (SL-42).
  • Explained in: Authorization

SL-04: Persist OPA decision logs

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the PDP logs every decision with a decision ID, the reason, and the trace ID of the request. Loki stores the log, and a Grafana panel links each decision to its trace.
  • Produced: REQ-32 (REQ-31 merged into REQ-71), and the audit part of F-07.
  • Explained in: Logging

SL-05: FSC sector-grant check

  • Status: done
  • Demo work: before the public repository.
  • What it showed: organization permission is an authorization concern of its own, next to the legal basis. The demo checked a sector-level grant per service. FSC has no sector concept (F-36). #378 removed the sector-pip. Since SL-45, a register gives the admission.
  • Produced: part of F-08 (REQ-33 and REQ-34, removed later).
  • Explained in: ADR-0022, Contract admission and source activation

SL-06a: User demo flow A: consent issuance

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a citizen goes from a mock service provider (dienstverlener) website to the consent portal (toestemmingsportaal) inside a MijnOverheid shell. He logs in with a DigiD mock, gives consent, and returns. The redirect carries the consumer, the service, the purpose, the data sets, and the return address. The result page fetches real data through the whole chain.
  • Produced: REQ-37, F-15, F-16, F-17, and F-18.
  • Explained in: Citizen grants consent

SL-06b: User demo flow B: access under MijnOverheid

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a citizen sees his consents under MijnOverheid, with status active, expired, or revoked, and opens a detail page. He can revoke a consent after he approves the revoke in a dialog. The next request on that consent gets a deny.
  • Produced:
  • Explained in: Citizen views and revokes consents

SL-07: Restore trace correlation

  • Status: done
  • Demo work: before the public repository.
  • What it showed: trace context propagates end to end. One trace covered all services of a request.
  • Produced: no requirement. The result is the basis for REQ-55.
  • Explained in: Logging

SL-08: Consent PIP through PEP pre-fetch

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the PEP fetched the consent record and gave it to the policy as input, so the policy engine made no network call. Since PR #371, the flow is reversed: the policy verifies the signed consent proof and asks the register for the status itself.
  • Produced: REQ-18 and F-22. Later, REQ-68 replaced this result.
  • Explained in: Authorization

SL-09: Onboarding and gatekeeper flow

  • Status: partly covered
  • Demo work: covered by SL-45.
  • What it showed: SL-45 delivered the admission register and the contract decision by the PDP. Missing: an onboarding interface for consumers, and the test of the connection conditions (Q-74). Q-22 answers who keeps the register and on which grounds.
  • Produced: see SL-45.
  • Explained in: Contract admission and source activation

SL-10: Observability infrastructure (Loki and Grafana)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: structured logs carry the trace ID. Loki and Grafana link a log line to its trace and back.
  • Produced: REQ-28 and REQ-29 (merged into REQ-55 and REQ-60), and the correlation part of F-07.
  • Explained in: Logging

SL-11: Consent portal backend (S02)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the consent portal (PSA S02) became a service of its own, apart from the consent register (S01). The DigiD mock gives a token, and the backend takes the citizen identity only from that token. The backend calls BSNk, so the register gets no BSN.
  • Produced: REQ-23, REQ-24 (REQ-22 and REQ-35 were removed later).
  • Explained in: Building blocks, Citizen grants consent

SL-12: Consent register persistence

  • Status: planned
  • Demo work: none as an increment.
  • What it showed: not built as planned. In demo v0.9.0, the register has a Postgres store. If DATABASE_URL is set, the register uses this store (postgres_store.go). The local compose stack does not set the variable and runs in memory.
  • Produced: none. Q-54 holds the open durability requirements.
  • Explained in: Consent

SL-13: Rego structure clean-up

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a structure in three parts (common helpers, entry point, rules per use case) scales to more access bases without duplicated code. Consent moved to the level of a data set (scope).
  • Produced: REQ-10 (reworked) and F-03 (put into context).
  • Explained in: Authorization

SL-14: Query template as upper bound (POC)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a proof of concept of variant D from Q-14 on one scope. A query template sets the upper bound of what a consumer can ask. The proof of concept gave the discussion a concrete example. It is no production evidence.
  • Produced: no requirement. The result is input for Q-14.
  • Explained in: Authorization

SL-15: Phase out orchestrator

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the demo needs no coordinating service. The three front ends call their own capability service directly. This design supports the separation of generic and specific functions (PSA P-14).
  • Produced: no requirement.
  • Explained in: Building blocks

SL-16: Developer portal

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a separate developer portal (scenarios, request builder, replay, architecture strip, links to traces) keeps the technical controls out of the citizen demo.
  • Produced: no requirement.
  • Explained in: Building blocks

SL-17: AuthZEN envelope adoption

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the PDP answers in the AuthZEN decision envelope, with a reason code for the operator on a deny. At that time, the wire shape between PEP and PDP did not follow the GBO profile (F-27).
  • Produced: F-27, REQ-42.
  • Explained in: Authorization, ADR-0002

SL-18: RFC0052-GBO policy refactor and PDP handler

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a context handler in front of the policy engine parses the GraphQL request. The policy has named rules that bind to types and fields, and it decides per field. Each decision lists the rules that it evaluated. The handler became the request mapper inside the OpenFTV PDP.
  • Produced: F-27.
  • Explained in: Authorization, ADR-0013

SL-19: EUDI stand-alone in the demo compose stack

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the issuance server of nl-wallet runs in the demo compose stack. A pre-production wallet received a real attestation from the demo, without the GBO chain.
  • Produced: Q-17, Q-18.
  • Explained in: EUDI issuance, ADR-0018

SL-20: EUDI adapter with AuthZEN dispatch through the PEP

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a thin adapter between the issuance server and the source sends EUDI requests through the same PDP as DvTP. One generic chain serves two front doors. The flow field in the body that chose the regime was an interim solution (F-32).
  • Produced:
  • Explained in: EUDI issuance

SL-21: Level C multi-policy demo

  • Status: planned
  • Demo work: none.
  • What it showed: not started. The increment has no worked-out scope.
  • Produced: none.
  • Explained in: no page.

SL-22: Source gateway de-pseudonymization (DvTP)

  • Status: done
  • Demo work: before the public repository. It was built together with SL-23 in SL-42.
  • What it showed: the conversion from pseudonym to BSN moved from the PEP to a source gateway at the source, with the keys of the source. Since then, the GBO core (PEP, PDP, and policy engine) handles no BSN in the DvTP path.
  • Produced: F-30, REQ-21 (place of the conversion).
  • Explained in: Pseudonymization, ADR-0033

SL-23: Consent out of the query, pseudonym in the query, and policy binding

  • Status: done
  • Demo work: before the public repository. It was built in SL-42.
  • What it showed: the consent ID left the GraphQL query. The query carried a pseudonym on the subject place, and the policy bound that value to the consent. Consent became a matter for the policy instead of the business flow.
  • Produced: F-29 and F-44. REQ-25 to REQ-27 were revised and removed later. Since SL-51, the query carries a placeholder instead of a pseudonym (REQ-79).
  • Explained in: Pseudonymization, ADR-0032

SL-24: Access-basis dispatch through component metadata or certificate

  • Status: dropped
  • Demo work: none of its own.
  • What it showed: the plan was to derive the regime (consent or PID) from verified component identity instead of a declared flow field. First, signed FSC grant properties replaced the plan. Since PR #363, the regime follows from the evidence that a request carries.
  • Produced: replaced by REQ-74, with F-32, F-43, and Q-15.
  • Explained in: ADR-0031

SL-25: PID signature verification in the EDI adapter

  • Status: dropped
  • Demo work: none.
  • What it showed: not necessary. The issuance server verifies the PID, and the adapter gets plain JSON attributes. One gap stays: the callback from the issuance server to the adapter has no authentication (#133).
  • Produced: input for REQ-45 and F-70.
  • Explained in: EUDI issuance

SL-26: EDI issuer through an FSC Outway (OIN): PuB-EAA route

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the issuer fetches source data through an FSC Outway under its own OIN. EUDI and DvTP arrive at the source in the same way. The access basis stays different per route.
  • Produced: REQ-46 (REQ-47 removed).
  • Explained in: EUDI issuance

SL-27: Legitimation of the authorization context (signed envelope)

  • Status: merged
  • Demo work: none of its own.
  • What it showed: the question was how the claims of a request (subject, consumer, and scopes) stay legitimate and bound to each other. The question merged into the work on the consent binding (F-44). SL-47 answered it with a signed, actor-bound consent proof.
  • Produced: see SL-47.
  • Explained in: ADR-0032

SL-28: Authentic Source Interface (QTSP verification)

  • Status: done
  • Demo work: epic ICTU/GBO-demo#336, closed on October 27, 2026. The numbered list after this entry gives the parts of the epic.
  • What it showed: an ASIP mock to ETSI TS 119 478 clause 6.1, with its own authorization server, a reference QTSP, and a conformance matrix in CI. The QTSP is not an FSC participant. The generic chain (FSC, PDP, source gateway, and source) starts behind the ASIP (F-87). The citizen logs in with a DigiD mock or the NL Wallet.
  • Explained in: QTSP verification (ASI route), ADR-0037, ADR-0038, ADR-0039, Feedback on ETSI TS 119 478

Epic #336 has 14 parts:

  1. Verify and retrieve with a seal (#498, PR #499). The ASIP verifies and retrieves against an in-memory source. It gives the four verification results, the published contract, and a seal on each result. Produced: REQ-83, REQ-84, REQ-85, F-80, and Q-32.
  2. Authorization server (#503, PR #504, PR #522, and refactor PR #505). The authorization server implements clause 6.1.3 with PKCE, private_key_jwt, DPoP, and JWT tokens. It also has dynamic client registration with a sealed software statement, a stub register, and a periodic re-check. Produced: REQ-86 to REQ-89, F-84, F-85, F-86, Q-33, Q-34, and Q-35.
  3. Citizen approves or refuses (#523, PR #524). The transaction is one-time, short-lived, and bound to the browser. The token carries PID attributes. Produced: REQ-90, REQ-91, F-88, and Q-36.
  4. Chain behind the ASIP (#525, PR #526, PR #527, PR #529, PR #530, PR #532). The ASIP is an FSC peer and asks the BRP over FSC under rule ASI0001. Each source has one data service and one token, each request causes one source request, and every rule names its services. Produced: REQ-92 to REQ-95, REQ-97, F-87, F-89, F-90, Q-37, and Q-38. REQ-96 merged into REQ-91, and REQ-98 was removed.
  5. Discovery records: merged into part 6.
  6. Discovery and conformance matrix (#533, PR #534, PR #535, PR #536, PR #537, PR #538, PR #539, PR #540, PR #541, PR #542). The part added a record per data service for the Discover Interface, and a reference QTSP. It also added a conformance matrix per ETSI requirement with a check in CI, and a 404 for a retrieve without a value. Produced: REQ-99 to REQ-101, F-91, F-92, Q-39, and Q-29.
  7. NL Wallet identification (#546, PR #550, PR #551, PR #552). The ASI route uses OpenID4VP with the verifier of nl-wallet. A run with the real NL Wallet is recorded. Produced: REQ-102, F-93, F-94, and Q-40.
  8. Documentation and security notes (PR #574). The documentation tells what is real, stub, interpretation, or shortcut. It gives a choice per point of RFC 9700 and FAPI 2.0. Produced: F-96, Q-41, F-84 (extended), and the ETSI feedback list.
  9. Protect the BSN in the token: not done. #595 tracks the follow-up.
  10. DigiD mock and one request screen (#544, PR #545). The legal name of the QTSP comes from the register. The consent is fixed only after a successful identification. The token carries the means (acr/amr). Produced: REQ-86, REQ-90, REQ-91 (validated), F-88, and Q-36.
  11. House style and consent screen (#547, PR #559, and optional binding in #571, PR #572). The consent screen uses plain language. RFC 9396 authorization_details binds the token to the attributes. Without a configuration that requires it, this binding is optional. Produced: REQ-91, REQ-103, F-95, and Q-33.
  12. Same-device login with the NL Wallet (#548, PR #573). The ASI route accepts the return only in the browser of the transaction. Produced: REQ-102 and F-93. #596 tracks the real run on one phone.
  13. Wallet issuance by the reference QTSP (#549, PR #570, and tools PR #566, PR #567). After a successful result, the reference QTSP issues a marked test attestation. Produced: F-93. REQ-105 was removed.
  14. Citizen logs in at the reference QTSP (#560, PR #562, PR #563, PR #564). Produced: F-93 and Q-40. REQ-104 was removed.

The close of the epic (PR #590, PR #591, PR #593) made the consent page name the QTSP that gets consent (REQ-91). On October 28, 2026, the GBO profile on ETSI TS 119 478 followed (ASI profile). The profile produced REQ-112 to REQ-115 and Q-64 to Q-67.

Epic #336 has four follow-ups:

  • #592: the source describes its attributes in its source metadata. Steps 1 to 5 are in v0.9.0 (PR #623, PR #624, and earlier). In demo v0.9.0, every ASI data service names an authentic source (Q-38, ADR-0039).
  • #594: the ASI route in the simulation environment, and an external QTSP.
  • #595: protect the BSN in the token (F-86).
  • #596: the real run of same-device login.

SL-29: BSN out of the EDI decision logs

  • Status: done
  • Demo work: before the public repository.
  • What it showed: a masking rule kept the BSN out of the decision log. SL-44 showed that the masking rule did not work in the OpenFTV PDP (F-54). Since PR #370, the EUDI BSN is in both decision logs. It stays there until a decision on #368.
  • Produced: input for REQ-60 (not met in demo v0.9.0) and F-54.
  • Explained in: Logging, ADR-0043

SL-30: Dev portal EUDI flow tracing

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the developer portal shows the EUDI issuance chain next to the two DvTP chains, with trace links and history.
  • Produced: input for Q-08 (wallet side).
  • Explained in: Building blocks

SL-31: FSC Inway payload is pure GraphQL and a token, with no envelope

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the Inway passes the body unchanged and writes trusted context only from token claims. A header prefix separates trusted context from untrusted context (F-34).
  • Produced: F-34 and REQ-18 (REQ-50 merged into it, and REQ-49 removed).
  • Explained in: Authorization

SL-32: Adapter parameters from a use-case catalog instead of code

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the EUDI adapter took scope, tax year, and attestation type from a catalog instead of from code. SL-46 replaced the catalog with metadata that the source publishes.
  • Produced: Q-19 (route b) and F-23.
  • Explained in: Source onboarding

SL-33: EUD0001 explicit scope and actor authorization

  • Status: done
  • Demo work: before the public repository.
  • What it showed: every policy path checks actor and scope itself. The DvTP rule checks that the consent covers the scope. The EUDI rule declares which actors and scopes it allows.
  • Produced: REQ-48, and model B for both paths (Q-14).
  • Explained in: Authorization

SL-34: FSC exploration

  • Status: done
  • Demo work: before the public repository.
  • What it showed: an analysis of OpenFSC v2.4.0. The Inway has an AuthZEN plugin, so a separate PEP service duplicates its role. FSC has no sector grant. Data transformation after the decision belongs in the source gateway instead of the PDP.
  • Produced:
  • Explained in: Deployment, ADR-0003

SL-34a: Root CA and self-hosted certificate portal (offline CA)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the demo runs its own root CA with a certificate portal, so FSC peers get certificates without an external CA.
  • Produced: no requirement. The result is input for Q-07.
  • Explained in: Organization identity and trust, Deployment

SL-34b: Tracer bullet: one organization running before broad roll-out

  • Status: merged
  • Demo work: covered by SL-34a and SL-34c.
  • What it showed: the plan was to run one FSC organization before the roll-out. SL-34a and SL-34c covered the purpose. Step 2 of the plan was removed.
  • Produced: none.
  • Explained in: Deployment

SL-34c: Self-hosted directory peer and directory UI (offline registry)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the demo runs its own FSC directory peer with a user interface, so it does not depend on an external directory.
  • Produced: no requirement.
  • Explained in: Deployment

SL-35: Bootstrap of the FSC organization EDI issuer (consumer)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the EUDI issuer runs as an FSC consumer organization of its own, with its own peer and certificate.
  • Produced: no requirement.
  • Explained in: Deployment

SL-36: Bootstrap of the FSC organization Belastingdienst mock (provider)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the Belastingdienst mock runs as an FSC provider organization of its own, with its own Manager and Inway.
  • Produced: no requirement.
  • Explained in: Deployment

SL-37: FSC service bri and contract negotiation between organizations

  • Status: done
  • Demo work: before the public repository. Seed automation came later.
  • What it showed: the source publishes the service bri, and the organizations negotiate a contract for it. A contract has one service connection grant, for one Outway and one service. The contract cannot express a sector (F-36).
  • Produced: F-36 (detail).
  • Explained in: Contract admission and source activation

SL-38: FSC txlog observability and trace ID equal to Fsc-Transaction-Id

  • Status: done
  • Demo work: before the public repository.
  • What it showed: FSC v2.4.0 does not propagate trace context, and its plugins drop the request context. The demo made the trace ID equal to the FSC transaction ID and read the FSC transaction logs. SL-50 reversed the key: W3C Trace Context is the key, and the demo records the transaction ID next to it (F-67).
  • Produced: F-39, F-40, F-41, F-42, and REQ-55 (REQ-54 merged into it).
  • Explained in: Logging, ADR-0035

SL-39: Eudi-adapter to real FSC Outway

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the EUDI adapter calls the source through a real FSC Outway, with mTLS and contract-based authorization up to the Inway. The scope header is an untrusted catalog index, and the policy checks it independently (F-14).
  • Produced: F-23 (widened), F-14 (resolved).
  • Explained in: EUDI issuance

SL-40: Pdp-service as AuthZEN endpoint behind FSC Inway (EUDI)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the AuthZEN plugin of the FSC Inway calls the PDP directly. No separate PEP is necessary in the FSC chain.
  • Produced: F-35 (shown live), REQ-42.
  • Explained in: ADR-0002

SL-41: Documentation and developer portal update: real FSC nodes

  • Status: done
  • Demo work: before the public repository.
  • What it showed: the documentation and the developer portal show the real FSC nodes instead of the fsc-mock.
  • Produced: no requirement. F-31 stays valid.
  • Explained in: Building blocks

SL-42: Follow-up: fully phase out fsc-mock (option B, DvTP)

  • Status: done
  • Demo work: before the public repository.
  • What it showed: DvTP runs over real FSC too, with a second consumer organization. The demo removed the fsc-mock and the PEP service. The PDP is the only policy endpoint for DvTP and EUDI. The source gateway does the conversion after the decision (SL-22, SL-23).
  • Produced:
  • Explained in: Consumer queries under consent, ADR-0033

SL-43: Death certificate: BRP source and second EUDI attestation (subject differs from discloser)

  • Status: done
  • Demo work: PR #125
  • What it showed: a second source (BRP) and a second attestation. A surviving partner discloses his PID and gets the death certificate of the partner. The subject of the attestation is not the person who discloses. Each bronhouder needs its own certificate set for issuance.
  • Produced:
  • Explained in: EUDI issuance

SL-44: OpenFTV Manager: policy management and distribution through bundles (PAP)

  • Status: done
  • Demo work: PR #208
  • What it showed: the PAP runs at the source side. Git stays the source of truth, and policy goes to the PDP as an identified, versioned bundle. The management API has its own policy set. If the store is empty, the management API denies. Push distribution, delete, and masking of decision logs do not work in this configuration.
  • Produced:
  • Explained in: Policy distribution, Policy lifecycle, ADR-0021

SL-45: Admission as a register and contract decision by the PDP

  • Status: done
  • Demo work: PR #228, PR #239, PR #241
  • What it showed: admission is a registration instead of a policy rule. The PDP decides each contract proposal in a policy tree of its own, with machine-readable reason codes. An automatic "no" leaves the proposal pending, so it is recoverable. Admission is per bronhouder. The demo has no admission per service.
  • Produced:
  • Explained in: Contract admission and source activation, ADR-0015

SL-46: Generic source metadata: source publishes, GBO validates and activates

  • Status: done
  • Demo work: PR #219, PR #224, PR #237, PR #247, PR #276
  • What it showed: each source publishes its service description on /.well-known/gbo: query, parameters, mapping, attestation schema, and offers. GBO validates the description against a profile and activates it as an explicit step. A valid contract does not activate the description. If a description is bad or old, it fails closed per source, and it can be rolled back.
  • Produced:
  • Explained in: Source onboarding, ADR-0016

SL-47: Signed, actor-bound consent proof

  • Status: done
  • Demo work: PR #238
  • What it showed: the consent register issues a signed consent proof (ES256, with a JWKS). The policy verifies the signature and binds the consumer in the proof to the verified caller. The status check stays online and fails closed. The validity period is in the signed proof, so the consumer cannot change it.
  • Produced: F-61, REQ-68, and REQ-69. The increment closed F-24 and F-44, and sharpened Q-05. REQ-13, REQ-25, and REQ-27 were revised and removed later.
  • Explained in: Consent, ADR-0032

SL-48: Flow dispatch cleaned up: no default regime, no flow header

  • Status: done
  • Demo work: PR #236
  • What it showed: the demo removed the default regime, and the regime header that a consumer was able to send. If a request had no signed flow property, it matched no rule and got a deny. PR #363 removed the flow property too (REQ-74).
  • Produced: the premise of F-49 lapsed. REQ-56 was tightened, then removed and replaced by REQ-74.
  • Explained in: ADR-0031

SL-49: Identity separation: FSC Peer ID separate from source OIN

  • Status: done
  • Demo work: PR #242, PR #244, PR #247, PR #277
  • What it showed: the FSC Peer ID (transport identity) and the OIN of the source (legal identity) are recorded apart. The OIN and the name of the organization come from the verified issuer certificate. CA private keys stay out of the application runtime.
  • Produced: F-60 and REQ-67. The increment sharpened Q-06 and Q-07.
  • Explained in: Organization identity and trust

SL-50: LDV and ADL exploration: three logging standards, one trace ID

  • Status: done
  • Demo work: build in #302, and review and correction in PR #366.
  • What it showed: three related logging standards apply. The decision log already implements the Authorization Decision Log (ADL). The gap is at the processing: each GBO component that processes personal data writes a Logboek Dataverwerkingen (LDV) log line at its controller (Verantwoordelijke). The trace ID from traceparent links the logs, and each controller logs its own pseudonym.
  • Produced:
  • Explained in: Logging, ADR-0026, ADR-0035, ADR-0036

SL-51: Encrypted identity per source in the consent proof, replaced after the decision

  • Status: done
  • Demo work:
    • ICTU/GBO-demo#468 and PR #469, the first part of #364, on the BSNk mock from PR #466.
    • the follow-up in #473: PR #475 removed subject_id_type, and PR #476 added two placeholders, one per form. PR #477 added a pseudonym for each source, an identity for a source on the BSN authorization list, and more than four parties.
  • What it showed: the design works with the BSNk interface. At the consent, the portal backend activates and transforms. The proof carries an encrypted value per source, and the consumer sends a placeholder. The PDP decides on that placeholder. Only after an allow, the source decrypts its own value, without a call to BSNk.
  • Produced:
  • Not built:
    • a pseudonym for the consumer (#478)
    • the subject variable in one place (#479)
    • an API that answers on a pseudonym (#474)
    • onboarding of keys (#467)
  • Explained in: Pseudonymization, Consumer queries under consent, ADR-0032, ADR-0033

Demo work outside increments

From September 14 to 16, 2026, the demo work ran through demo issues instead of an increment. This work produced the following IDs:

  • PR #284 and PR #363: the regime follows from the evidence of the request instead of a grant property. Produced: F-70 and REQ-74. F-62 is resolved, and SL-24 is dropped. REQ-56 was partly replaced and removed later.
  • PR #370 and PR #371: the request mapper does only GraphQL mapping. The policy verifies the consent proof and asks for the status. Produced: REQ-68, F-61, Q-05, Q-23, and Q-25. The BSN is in both decision logs on purpose, so REQ-60 is not met (F-54).
  • PR #372: make policy-check is a local safety net. Produced: RL-05 and F-52.
  • PR #373: the ADL is the audit source. Produced: F-72 and REQ-71. The rest of F-53 and F-63 is done. A check against a running stack showed the gap of REQ-59: the records carry no policy version.
  • PR #337: OpenFTV v0.1.0 makes the ADL mandatory (REQ-71). A silent bundle 403 led to F-52 and RL-05.
  • PR #318: the demo has a file transport for source metadata. Produced: F-71, an exception in REQ-64, and Q-06.
  • PR #321: the description of the issuer comes from the certificate (REQ-67).

The same round recorded three observations in issues:

  • #369: the ADL record behind the Inway has no trace and no transaction ID. Related: F-41, REQ-55, and REQ-71.
  • #225: the choice between one shared certificate set and a set per source. Related: REQ-58, Q-07, and Q-17.
  • #133: the callback from the issuance server to the adapter has no authentication. Related: F-70 and Q-18.

Later, PR #464 (#379) added more demo work outside increments. An integrator calls under FSC delegation, and the consent binds the represented party. Produced: REQ-106, F-73, Q-46, and ADR-0034.

Traceability

  • Requirements: each increment lists the requirements it produced.
  • Findings: each increment lists its findings. For all findings, see Findings.
  • Open questions: each increment lists its open questions. For all questions, see Open questions.
  • Design coverage: Design to demo matrix.