Index › The product › eRegulations-Next: concept note

UNCTAD · eRegulations-Next · Step 1 of 7 · concept note

eRegulations-Next: concept note

Draft 01-10-2026 · waiting for melux's agreement in principleUpdated 01-10-2026

This page is step 1: what eRegulations-Next is and how it is built; the modules of step 2 will detail it. Read next: Decisions · Progress.

eRegulations and TradePortal rewritten as one application, on the stack of the other *-Next products, with every function they have today and none of their three front-end stacks. Every existing country moves to it by an import of its data, not by re-entry.

In one minute

  • What: the same product countries use today: procedures described step by step, published in several languages, searched by filters, read through an API. Every function is kept; only the implementations are simplified D1.
  • How: one Next.js application with Postgres, in place of three .NET and Angular applications, a shared library and four SQL Server databases D7.
  • Where: one installation per country, each with its own database D2.
  • Moving countries: an importer reads an instance's SQL Server backups, 7.x or legacy, and loads them whole; it can be run again until the day of the switch D8.
  • Who depends on it outside: Simplifications-Next, the EAC comparator, ITC. A new API, and the old routes they call, kept to the letter D4.

This note restarts the work at step 1, under the way of working the tariff calculator follows D9. It is drawn from the inventory of the current system and the lot 1 design of 24-09-2026, both kept as they were written, in French. Words used in a sense of their own will go in the dictionary.

1 · What exists today

One product in its 7.x line, deployed per country, built from three applications that must be released together.

Part Built with What it does
Administration API (eRegulations-4.0-Admin) ASP.NET Core 8, EF Core, SQL Server The back-office's API, with its own JWT sign-in
Shared library (same repository) .NET 8 Model, data access, publishing; used by both Admin and Public, so their releases are tied
Back-office (eRegulations-5.0-Admin-SPA) Angular 19, PrimeNG Editing procedures, catalogues, site content, translations, users
Public site (eRegulations-4.0-Public) Razor with jQuery, Backbone and Bootstrap 3, plus Angular 9 for procedure pages The site, the public read API, the legacy API
Statistics .NET console Periodic counts per instance, read by the system dashboard

Each country is one Coolify application and a SQL Server 2022 Express database, plus three databases shared between countries (consistency review, statistics, a legacy global one) and four mounted folders of files: media, the home page's configuration, public content, interface labels.

The fleet: 7 instances on 7.x (Burundi, Comoros, Iasi, PAST, pilot-tradeportal, South Sudan, lab-next) and about 90 legacy instances in 4.x and 5.x, about 200 groups, on four Windows servers.

TradePortal is not a mode. It is the same code with modules switched on by configuration: the duty and tax calculator, HS code search, products, the administrative burden cost (ABC).

Debt and security faults found, not to be carried over
  • The translation controller writes and publishes without authentication; step certification checks no permission.
  • JWT and single sign-on secrets in appsettings.json; a password accepted in a URL; consistency tickets readable anonymously; CORS open to every site; /media served with no allow-list.
  • Credentials in clear in eRegulations-deploy/HANDOVER-2026-06-08.md and server addresses in the CSS inventory: to rotate and purge from git, whatever this project decides.
  • Three front-end stacks side by side on the public site; a 6 GB shared consistency database against SQL Express's 10 GB limit.

2 · What eRegulations-Next is

The same product, with the same functions and the same addresses for those who read it from outside. Nothing a country uses today is lost D1.

For the public: the home page and its menus, search by filters and by words, procedure summaries and step sheets with their requirements, costs, timeframes, results, laws and contacts, the directories, printing, embedding in another site, feedback, in each language the country publishes, right to left included.

For a country's team: the procedure tree of objectives, blocks and steps, the catalogues (institutions, units, people, documents, laws, cost variables, filters), site content and layout, publishing with its versions and audit, translations, users and roles, consistency review and step statuses.

For TradePortal countries: the modules a setting switches on, as today.

The rule this rewrite keeps. What a country has published reads the same after the move: the importer rebuilds each published procedure from what the public site shows today, not from the draft, and checks its totals against the live site (lot 1 design §7.5).

Left out: functions already dead in 7.x, left out D15
  • The CR-Alerts e-mail digest, inactive.
  • "Send to translation", commented out.
  • The Partners table in administration; the public /Partners directory stays.
  • The Razor procedure page that duplicates the Angular one.
  • /TradeStatistics, empty unless an instance supplies its own part.
  • Dead tables: XMLSerializedItem*, Workspace, Process*, ProcedureContext, ObjectSecurity, and some 200 legacy stored procedures.

3 · How it is built

One application and one database per country. The public site and the API read only published documents; everything else a country changes is a setting, not an environment variable.

One Next.js application holds the public site, the back-office, the API and the pages meant for embedding, on Postgres, aligned on Academy-Next D7. One image serves every country; each country is a deployment with its own database D2.

A published procedure is one document. The draft is kept in normalised tables. Publishing writes a version of the whole procedure, in every language, that the public site and the API read without another query. Today's equivalent is twenty denormalised Snapshot_* tables per language.

Text is translatable everywhere in one way: each field holds its languages together, falling back to the country's default language. Today each table has a sister _i18n table, named inconsistently.

Settings live in the database and are changed from the back-office: languages, default currency, modules, analytics, mail, layout, the country's CSS. The environment holds only the database address, the sign-in secret and the media folder. Today about 25 environment switches and Razor parts supplied per instance do this.

Sign-in is local to the instance: a name and a password, no Keycloak D3. Passwords imported from today's bcrypt, SHA-256 or clear text are kept or re-hashed at first sign-in; none is ever sent in a URL.

Rights, as designed on 24-09-2026
  • Permissions named resource.action, as in today's Permission table, so they import directly.
  • A role is a set of permissions; it is given to a user over the whole instance, or over one objective and everything under it.
  • Today's per-user grants and denials, and per-object permissions, become custom roles at import. There is no explicit denial any more.
  • UNCTAD's master users are copied into every instance, as today.

4 · Moving the countries: the importer

A country moves by loading its backups into the new model. The import can be repeated as often as needed; the switch is one more import, then a change of address.

The source is SQL Server backups only; no instance exports anything else. The importer restores them in a throwaway SQL Server, brings a legacy database up to the 7.x shape with the scripts the provisioner already uses, reads it table by table, transforms each domain with a pure function, and loads everything in one Postgres transaction. Original identifiers are kept for everything an address or the API points at D8.

It stops without writing when a backup cannot be read, a schema is not recognised, two user names differ only by case with no rule to merge them, or the target is not empty.

Its report counts each kind of item in source and target, lists rejected rows and anomalies, and compares the cost and timeframe totals of twenty published procedures with the live site's.

The day of the switch: editing frozen in the old back-office, a final import, the report read, the address switched.

What the importer must get right, from the inventory
  • Several databases merged: the country's, consistency filtered by system, global for legacy users, statistics if wanted.
  • Version drift: 7.x identified by __EFMigrationsHistory; legacy 4.x and 5.x with known differences, already documented by the provisioner's eight-phase migration.
  • Cost formulas linked to cost variables by name, not by key; media owners told apart by a type column; unit identifiers overlapping institution identifiers.
  • Files: media/, public content, file names in CP850 in legacy zips; the home page as JSON per language; the country's CSS and its history.
  • Interface labels are not imported: the old keys do not match the new interface. The report lists each country's own labels for manual reprise.
  • The unit of timeframes, and the 8-hour working day the current API converts to, to confirm before step 4.

5 · Those who read it from outside

Other systems read eRegulations every day. They keep working the day a country moves, without changing anything.

Who What they call today What they get
Simplifications-Next The 7.x read API, /api/procedure/…, /api/objective, /api/filter… The new API, /api/v1, documented in OpenAPI; it moves to it D4
EAC trade helpdesk comparator, ITC, other comparators The legacy subset: /Filters, /Objectives, /Procedures, in their historic shape The same routes, same shapes D4
Sites that embed a page or the search bar ?embed=true, /EmbedSearch Pages meant for embedding, from a list of allowed sites

6 · TradePortal modules, and the tariff calculator

The modules come back as settings of the installation. One of them already has its own project.

Module Today Proposed
Duty and tax calculator A proxy to the country's ASYCUDA, with a 7-day cache in the database The tariff calculator, unctad-ai/tariff-calculator-platform, embedded D13; its own D1 and D9 already plan for eRegulations to embed it. Today's proxy and its cache are not ported
HS code search Autocompletion on hscode.tradeportal.org Kept
Products Filter options carrying HS codes, a /Products directory Kept
Administrative burden cost Staff levels, zones, time per document; computed on the public site Kept

7 · How the work runs

Seven steps, each through four marks, as for the tariff calculator. Nothing is drawn or built before a step is signed off D9.

The marks are: written, agreed in principle by melux, checked by reviewers (Claude and Codex, each on their own), signed off with its date after colleagues' comments.

Step Ends with
1 · Concept note This page, agreed
2 · Short specifications One page per module, at most 450 words
3 · Mockups Public site, an embedded page, the back-office; clickable
4 · Detailed specifications The data model, the importer's mappings, the API contract old and new, the rights catalogue. The lot 1 design of 24-09-2026 feeds this step
5 · Detailed mockups Every state of every screen
6 · Build phases One branch and one pull request per phase
7 · The product 7.1 foundation, model and importer · 7.2 public site and API · 7.3 back-office · 7.4 translations, review, statuses, rights · 7.5 TradePortal modules · 7.6 operations, and the first country switched

The six lots of 24-09-2026 D5 become the phases of step 7, in the same order D6.

Step 2's fourteen modules, proposed: 0 public site · 1 search and filters · 2 procedure and step pages · 3 directories · 4 public API and embedding · 5 procedure editing · 6 catalogues and media · 7 publishing and history · 8 translations · 9 users, roles and sign-in · 10 review and statuses · 11 TradePortal modules · 12 import and switch · 13 running it.

8 · The first country

pilot-tradeportal proves the import; a live country proves the switch.

Before its switch, each country's installation runs at <country>-next.eregistrations.dev, and takes the country's current address on the day of the switch D14.

Rehearsal: pilot-tradeportal. Imported at the end of 7.1, its report read with no unexplained difference, its pages compared with today's site once the public site exists (7.2).

First switch: a live 7.x country, not chosen yet (?2), once the back-office lets its team edit (7.3), and the TradePortal modules if it uses them. The legacy instances follow, in an order step 6 sets.

9 · Risks

Risk What covers it
A published procedure reads differently after the move Built from what is published, not from the draft; totals compared with the live site; pages compared in 7.2
An outside reader breaks the day a country moves The legacy routes kept to the letter, tested against today's answers D4
Legacy databases drift in ways not yet seen The provisioner's scripts and its list of known drift; the import stops rather than guess
SQL Server runs slowly on Apple Silicon, in emulation Acceptable for the import; checked in the first task of 7.1
A function is missed because it is used by one country only The inventory, read again against each country's settings and Razor parts before step 2 is signed off
Secrets found in the current repositories stay valid Rotated and purged now, outside this project

10 · Decisions and questions

Eight decisions of 24-09-2026 are recorded as D1 to D8; four of 01-10-2026 set the way of working, and three more answer this note's questions. One is deferred: which live country switches first.

Question Answer
Which functions are kept? All of today's; only implementations simplified D1
How many installations? One per country, each with its own database D2
How do people sign in? Locally, no Keycloak D3
What API? A new one, plus the legacy routes outsiders call D4
In what order is it built? Six lots, foundation and importer first, then the public site D5, D6
On what stack? The other *-Next products', aligned on Academy-Next D7
How do countries move? An importer of their backups, 7.x and legacy D8
?1 The duty and tax calculator? The tariff calculator, embedded D13
?2 Which live country switches first? Deferred: not decided yet; needed before 7.6
?3 Where does a country's installation run before its switch? <country>-next.eregistrations.dev, then the country's current address at the switch D14
?4 Are the functions dead in 7.x left out? Yes, the list in §2; the CR-Alerts digest is not brought back D15
Sources
  • Inventory of the current system, 24-09-2026: eRegulations-4.0-Admin, eRegulations-5.0-Admin-SPA, eRegulations-4.0-Public (origin/main), eRegulations-4.0-API, eRegulations-API-Docs, eRegulations-CR-Alerts, eRegulations-Statistics, eRegulations-Monitor, eRegulations-deploy, read only.
  • Lot 1 design, 24-09-2026: its decisions (§2) are D1 to D8.
  • The tariff calculator's working documents, unctad-ai/tariff-calculator-platform, read 01-10-2026: its way of working, its D1 and D9 on eRegulations.
  • Not seen: each country's own Razor parts and settings, read country by country before step 2 is signed off.
Drafted with Claude for melux · UNCTAD · working material, hidden from search enginesUpdated · 01-10-2026