Changelog
Latest updates and improvements.
v1.31.0
2026-10-0123:30
Show Details Hide Details
- FeatureThe federation activity report now lists the transactions instead of only counting them. It was a tally per service, which answered none of the questions anyone actually brings to it: which counterparty, under which agreement, in which direction, did it succeed, and what identifier do I give the other organisation so they can find the same call in their own log. All of that was already in each record and was discarded by the summary. There is now a table of the calls themselves, a breakdown per counterparty, delegation stated in words rather than left to be inferred from a single number, failures emphasised, and a note of how many calls were left out when a day is too long to list.
- FixThree faults in that report, all of which only appeared against real traffic. Every status column read as missing although every call had one recorded, because the number arrives from storage in more than one shape and only one was handled. The counterparty breakdown listed an internal self-test address and the placeholder word used when no identity is configured as though they were organisations we had been talking to. And a direction the standard does not define, which our own self-test writes, was blanked out instead of shown, making four rows look like missing data.
- FixThe report's tables keep a stable order. They were built from an unordered map, so the rows shuffled between runs and a reader comparing two days could not tell a real change from a reshuffle. They are now ordered busiest first, with ties broken by name.
- FeatureWhen a research report has a claim the gathered evidence cannot support, the pipeline now looks for a source for that specific claim before asking the writer to deal with it. Previously the only options were to cite something already gathered or to strike the claim, so a fact that was true and simply absent from the handful of searches the research pass happened to run was deleted. Nineteen staged reports sit one to three such claims short of the top grade, and the claims remaining are specific and checkable: a version number, a date, an amount, the name of a body. The search is deliberately narrow: one query per claim, three claims per round, filtered to the topic. Anything found is given to both the writer and the checker so a newly sourced claim is not penalised for a source it was just handed.
v1.30.0
2026-10-0122:30
Show Details Hide Details
- FeatureThe federation layer now keeps the transaction log the standard requires, which the Dutch government profile makes mandatory rather than optional. Each call is recorded before it is forwarded, with the authorisation it rested on, the parties on both sides and the party each of them acted for. One identifier travels with the call from the caller through us to the service, so a single transaction reads as one story on every system that touched it.
- SecurityA call that cannot be recorded is now refused. The standard is explicit that an unlogged request must be denied, and our logging previously swallowed every failure and let the call through, so a transaction whose record was lost still happened and the log quietly had a hole in it. The readiness panel also treats the log as essential for this reason: a gateway that cannot write one serves no traffic at all, and one that is listening while refusing everything looks healthier than one that is down.
- FeatureA counterparty can read back the transaction records it is a party to, and only those. Identity comes from the connection certificate rather than from a parameter, because a parameter would let one organisation enumerate another's traffic, and a caller entitled to nothing receives an empty list rather than a refusal that would reveal whether a transaction exists.
- FixTransaction records from before this change are now translated into the published format where that is unambiguous, and withheld from a counterparty where it is not. The records we had been writing for months used a bare word where the standard defines a fixed set of values, and carried no reference to the authorisation a call rested on, which the format requires. A counterparty reading them would have rejected them. They remain in our own log and our own views; inventing the missing reference would have been a lie about which agreement permitted a call.
- FeatureTransaction records are also written into the tamper-evident audit chain the rest of the platform uses, which the standard does not ask for and a supervisor reasonably will. This extends the existing chain rather than adding a fourth place that records what we did.
v1.29.1
2026-10-0121:30
Show Details Hide Details
- FixThe federation gateway now comes up by itself after a restart when it is configured. Starting it was a manual action, so every deploy quietly returned the installation to a state no counterparty could reach, and the readiness panel would have reported a gap nobody meant to reintroduce. An installation that has not configured it stays silent, as it should.
- FixThe readiness panel no longer prints the consequence of a missing piece next to a piece that is present. Writing the explanation beside each item reads naturally and was therefore what the code did, so the first thing the panel ever showed on the live server was a warning that no certificate was configured, directly beside the configured certificate.
- FixThe guard that stops the nightly documentation writer inventing controls now reads the page rather than the application. It followed every shared component import, so one page's source came to thirty-six thousand characters in which almost any three common words appear, and an invented control passed the check comfortably. It wrote one into the sales forecast page overnight, which the build then rejected. The guard and the check that gates the build now agree on what a page is, and a test reads one list out of the other so they cannot drift apart again.
v1.29.0
2026-10-0123:30
Show Details Hide Details
- FeatureThe federation layer has now been tested by somebody else's tests, which is the only way conformance is actually established. Four of the five automated checks in the official compliance tester pass; the fifth fails on a defect in the tester itself, which we proved using the tester's own libraries and have written up for the standards body. Two further checks need a person present and are the next run. A written report records the score, how to reproduce it, and what remains.
- SecurityA counterparty can no longer file an agreement between two other organisations with us. Nothing checked that the party submitting an agreement was named on it, so anyone in the federation could lodge one between two others; once those two signed it at their own systems, legitimately, our copy would come into force and start authorising traffic here. The submitting party must now be on the agreement.
- SecurityThe validity window of an agreement is now covered by its signature. We kept the window, the identifier and the federation name beside the agreement rather than inside it, which put them outside what both parties sign: a counterparty could have changed when an agreement we held expired without changing anything either of us had signed. They now live inside the signed content, as the standard requires.
- FixAccepting, rejecting and revoking an agreement work at all. All three addresses were unreachable and answered an authentication error instead, because the path matcher expected a prefix the dispatcher had already removed. Their own test passed throughout, because it asked the matcher the question in the matcher's own words. Two managers talking over a real connection found it in one run.
- FixWe answer at the addresses the published interface actually names. Every endpoint sits under a version prefix that the specification states once, in a place the endpoint list does not repeat, so a conformant counterparty following the documentation reached nothing. Agreement submission also answers the status the interface specifies, and accepts the request shape counterparties really send, including the nested permission format we did not read before.
- FixA permission to list a service in a directory is now held rather than refused. We declined those agreements because we run no directory, but holding an agreement and acting on it are different things, and refusing one fails a counterparty for a capability the request does not need us to have. It is held, and it never authorises a call.
- FeatureA readiness panel for the federation layer says whether this installation can actually talk to another organisation, naming each missing piece and what it breaks, rather than reporting counts over an environment that was never configured. It deliberately does not score its own conformance.
v1.28.0
2026-10-0122:00
Show Details Hide Details
- SecurityAn agreement can no longer be replaced behind our back. Each agreement carries a unique identifier, and a counterparty could submit a second, different agreement reusing an identifier we already held. That would have left an authorisation reference pointing at two different documents, with whichever happened to be read first deciding what was permitted. A second agreement under a held identifier is now refused, while a counterparty re-sending the same one still succeeds, because that is a retry. If we cannot read our own records to check, we refuse rather than assume.
- FeatureIncoming agreements are checked against every rule the standard sets before they are stored, not just the one we had. An agreement addressed to another federation, dated in the future, already expired on arrival, naming a signing algorithm we cannot verify, or granting nothing at all was previously accepted and filed. Each of those is now declined with a reason the other side can act on, and nothing is written.
- FixA token now tells a counterparty where to send its request. The address field held our organisation identifier instead of the gateway URL that the specification requires and the caller actually reads, so a conformant counterparty had nowhere to go. Tokens also record which authorisation they rest on and which party they were issued to, the two questions an audit asks on either side of a connection.
- FixEvery exchange between federation managers now carries the sender's own public address, as the published interface requires on all five of its endpoints. We required it on one. A counterparty that had moved was a counterparty we could not answer.
- FixRefusals use the standard's vocabulary and nothing else. The code and the HTTP status now travel as one value that cannot be separated, which turned up two faults the old free-form writer was hiding: a token from another federation was refused with the wrong status, and the challenge a caller needs in order to retry was set on two of the three cases that require it. Where the standard genuinely has no code for something, such as our storage failing or a duplicate agreement identifier, the refusal carries a readable reason and no code rather than one we invented.
v1.27.0
2026-10-0120:00
Show Details Hide Details
- FeatureThe federation layer now speaks the standard rather than a close relative of it. Tokens are obtained the way the specification requires, naming the exact authorisation on the exact agreement instead of a service by name. A counterparty can fetch our signing keys and verify an agreement we signed, which it previously could not do at all. Agreements can be accepted, rejected and revoked, and a peer can announce itself. The addresses are the ones the published interface names, so a counterparty following the documentation reaches us instead of being turned away.
- SecurityA token minted inside somebody else's federation is no longer honoured. Nothing compared the group a token was issued for against our own, so a token signed by an organisation we have no relationship with, for a party we never agreed anything with, was accepted on the strength of its signature. An expired token now says it expired rather than only that it is invalid, and a refusal tells the caller what to present.
- FixError replies match the published schema. They carried a field the schema does not define and omitted the one it requires, and every refusal claimed to come from the gateway even when it came from the agreement layer. The vocabulary is now the standard's own, checked against the published interface by a test so the two cannot drift apart.
v1.26.2
2026-09-3019:00
Show Details Hide Details
- FixA large upload is given time to arrive. The server allows thirty seconds to receive a request, which is generous for an instruction and far too little for a file: a few hundred megabytes over an ordinary connection is minutes of honest transfer, and the connection was being cut partway with a timeout. It never appeared in testing because an upload from the same machine finishes before the clock matters, so only a real file over a real network showed it. The routes that carry a file now get half an hour to receive one, every other route keeps its thirty seconds, and a test spends real time proving both halves.
v1.26.1
2026-09-3018:00
Show Details Hide Details
- FixUploading a real file works again. Every request body on the platform was capped at thirty-two megabytes to stop an oversized payload exhausting memory, and that cap was applied to file uploads too, whatever limit the page itself allowed. So an import that permits a gigabyte was cut off mid-stream, the parser reported only that the body was too large, and the screen said no file had been received. Anything small enough stayed under the ceiling and worked, which is why nothing looked wrong until a production export arrived. The routes that carry files now have room for one, everything else keeps the protection, and a refused upload says what was actually wrong instead of claiming nothing arrived.
v1.26.0
2026-09-3016:30
Show Details Hide Details
- FeatureThe timeline can be opened from a cascade run or a work entry, not only from a trace. It offered to take either and then answered that no record carried the id, because the run was never given the trace it had already started and the work entry was never given one at all. Both now carry it, so pasting a run id from the board shows what that run actually did. Where an id genuinely still cannot be resolved, an audit row, the tool now says so plainly instead of promising and failing.
- FixA service action no longer files a machine-readable blob where its outcome belongs. The audit call had two arguments in the wrong holes, so a serialised result map was written as the status and hashed into the evidence chain as the outcome of every start and stop. It now records the command and a plain success or failure.
- FeatureThe Dutch standards library is filled in and every link goes somewhere. It held two entries and its only address had gone dead when the custodian restructured their site. There are now fifty-eight, each fetched and confirmed before it was recorded, covering the transport and exchange standards, the sector models, zaakgericht werken, the base registers, identification, invoicing, care, work and income, justice, archiving and the European pieces.
v1.25.0
2026-09-3014:00
Show Details Hide Details
- FeatureThe personal-data scanner can be asked in words. It already ran on every page fetched from the web and was available to external tools, but there was no way to simply ask the chat whether a piece of text contains personal data. There is now, and it answers with a count, a risk level and a breakdown by kind, optionally returning the text with each finding replaced. The scan stays local: everything with a format and a checksum is found by rule on the server, and only names and addresses, which have no format, ever reach a model.
- FixDutch telephone numbers are recognised. The scanner only matched numbers written with an international prefix, so it found +31 6 12345678 and never 06-12345678, which is how a number appears on virtually every Dutch page the platform reads. On a platform built for Dutch public bodies that was the common case going undetected. Mobile and landline, with or without spaces, dots or dashes, are all found now, and a test holds the line against reading other identifiers as telephone numbers.
- FixA day on which nothing was filed no longer reports a broken evidence chain. The document store's integrity check answered not ok from the day it was built until the day somebody uploaded a file, because it read a missing day as a failure rather than as a quiet one. An empty day now says so plainly, a day whose file exists and will not verify still fails loudly, and the difference is asserted by a test.
Page 1 of 6