A Norwegian public body just asked for a new system. One line in the request caught my eye. They want to add new support schemes "without extensive changes to the program code."
The buyer is Garantikassen for fiskere, the Guarantee Fund for fishermen, in Trondheim. The tender is open until 30 November 2026. You can read the full tender notice here. I did not see a contract value in it.
The plan, in short
They want to replace their current system. It will be built in two phases. First the crew-based schemes, then the vessel-based ones. They also ask for configurable rules and rates, a full history of every change, and good screens for both their own case officers and outside users.
It sounded abstract to me, so I looked at what the Fund really does.
One scheme, in real life
The Fund's own website has the rules for a 2026 fuel grant for the coastal shrimp fleet. Here is what the regulation says:
- The grant is 3.50 NOK per litre of fuel.
- A vessel can apply up to 12 times.
- The fuel must be bought in 2026.
- Money is paid while there is money left. Earlier applications go first.
- If wrong information was given, the money can be taken back.
The same website says another scheme, a 2025 bait grant for line vessels, was closed and not continued in 2026. So a scheme can live for one year, then disappear. Next year a new one comes with a different rate and different limits.
If every scheme meant a new release, the developers would never stop. That is the problem the tender line is about.
A mini example
This is my own toy code. It is not how the Fund will build it, and the real documents may ask for something different. But it shows the idea.
from datetime import date
# One scheme is just data.
fuel_2026 = {
"id": "coastal-shrimp-fuel-2026",
"valid_from": date(2026, 1, 1),
"valid_to": date(2026, 12, 31),
"rate_per_litre": 3.50, # NOK
"max_applications": 12,
}
def decide(scheme, application, past_applications):
if len(past_applications) >= scheme["max_applications"]:
return {"status": "rejected", "reason": "too many applications"}
if not scheme["valid_from"] <= application["bunkered_on"] <= scheme["valid_to"]:
return {"status": "rejected", "reason": "fuel not bought in scheme period"}
amount = round(application["litres"] * scheme["rate_per_litre"], 2)
# Save the rate we used. Next year's rate must not change this record.
return {
"status": "approved",
"scheme": scheme["id"],
"rate_used": scheme["rate_per_litre"],
"amount": amount,
}
I ran it. For 1,000 litres bought on 10 March 2026, it approves 3,500 NOK. Fuel bought on 30 December 2025 is rejected. A 13th application is rejected too.
Notice the rate_used line. If the decision only said "approved, scheme X", you could not explain it later, after the rate changes. That is why the tender asks for full history and traceability. The number has to be stored with the decision.
What does not fit in one function
My example is easy because it skips the hard parts. The real regulation also has two ways to qualify for the grant. It has a first-come queue. If money is left at the end of the year, it is shared by litres. A case officer can make exceptions in special cases. And there is an appeals process through another agency.
I don't know how I would put all of that in config without it turning into a second programming language. Maybe the answer is a few rule types in code and the numbers in config. Maybe it is something smarter. I am curious how the winning team will do it.
The contract part
The tender also says the work will follow two Norwegian state standard agreements, SSA-T for development and SSA-V for maintenance. The government's SSA page describes SSA-T as the template for software that is built or adapted for the customer. SSA-V gives the customer new versions, support and bug fixes. Digdir, the Norwegian digitalisation agency, says you usually sign the maintenance agreement at the same time as the development one.
One more thing I noticed. The tender wants iterative development. Digdir describes SSA-T as having a detailed specification phase first, though it also says delivery can be split into parts. So I am not sure how the two fit together in practice. I would like to see that in the full documents.
Why I wrote this
Most "flexible system" talk is vague. A real regulation with a rate, a cap and a date range makes it concrete. If you build back-office software, try this: take one real rulebook and see what you can turn into data. You will find out fast where the hard parts are.
If you have built something like this, I would like to hear what you put in config and what you kept in code.
Top comments (0)