Dialog builder
The dialog builder lets developers, testers, designers and service owners create a dialog and see how it looks in Arbeidsflate, without creating anything in Dialogporten. It must never be available in production, or used with real data and comes with some deliberate limitations, cf Security.
Using it
Section titled “Using it”Open /dialog-builder. There is no menu entry.
- Select the recipient in the party selector in the header.
- Fill in the form, or paste a dialog as JSON.
- Fix anything listed under Resultat. Clicking an error opens the right section and puts the cursor in the field.
- Click Forhåndsvis, or copy the link to share it.
What you can paste
Section titled “What you can paste”- The body of
POST /api/v1/serviceowner/dialogs. - The response from
GET /api/v1/serviceowner/dialogs/{dialogId}orGET /api/v1/enduser/dialogs/{dialogId}. - The response from the
getDialogByIdGraphQL query in Arbeidsflate. It has noserviceResource, so the builder fills inurn:altinn:resource:fyll-inn.
Kopier JSON gives you a body you can send to the API. If the recipient is a person, replace party with the real URN first: the frontend only has the encrypted URN.
Differences from a real dialog
Section titled “Differences from a real dialog”- Actions: GET actions work as links. All other actions turn into links that do nothing, so nothing is ever sent.
- Front channel embeds: never fetched. The URLs are kept in the JSON, but the preview shows no embedded content.
- Access info and context menu: not available, since the dialog does not exist.
- Party: a dialog is always shown for the selected party.
partyis not part of the link. - Person names: shown exactly as written. Real names from Dialogporten are stored last name first, and the frontend reverses them, but the names here are typed in or already formatted.
Security
Section titled “Security”The preview renders content that comes from a URL, so a crafted link is the threat to design against. Anyone can send one.
- Never in production.
AVAILABLE_HOSTNAMESinavailability.tsis an exact list of hostnames, checked when routes are registered and again when they render. Anything not on the list gets no routes, and the code is never loaded. The JavaScript files are still part of the deployed image, because at23, tt02 and production share a build, but nothing in production can reach them. Do not add a production hostname, or replace the list with a looser check. - Nothing is trusted from the link. The dialog is validated again when it is loaded, and an invalid dialog is not rendered at all. Do not skip this, even if the builder has already validated it.
- Only
https:URLs.format: uriin the API specification acceptsjavascript:, soisHttpsUrldoes the check, and it also rejects URLs with embedded credentials. - Text is sanitized. Plain text is rendered by React, and Markdown goes through the same allowlist as real dialogs, which has no
script,imgoriframe. - No requests based on the link. Embeds are dropped in
toDialogFragment, because fetching them would let a link trigger requests from the user’s browser, with cookies if the URL is on our own host. Actions that send data do nothing, and no real dialog token exists. - No data sent anywhere. Nothing from the preview is sent to the BFF or to Dialogporten.
- Always marked as a preview. The banner, the page title and the breadcrumb all say Forhåndsvisning, so a shared link does not pass for a real dialog from a service owner.
Do not paste real dialogs from production into the builder: the link contains the dialog in compressed form, not encrypted.
Limits
Section titled “Limits”- Link length: full page loads fail above about 8 KB, which is the default limit in nginx. That covers reloads, shared links and the redirect after login. Forhåndsvis navigates inside the app and works at any size. The builder warns above 7 KB.
- Link contents: the dialog is compressed, not encrypted. It appears in gateway logs and in Application Insights page views in test environments.
partyis removed and person identifiers are masked before encoding. - Validation: the builder says «Ingen feil funnet», not that the dialog is valid, because
dialogSchema.tsis written by hand from the OpenAPI specification and the main Dialogporten validator. It does not follow API changes automatically, and it does not check maximum lengths. Unknown fields are shown as warnings, so a new API field does not block a preview.
The schema can be compared with swagger.verified.json in @digdir/dialogporten-schema. Look for V1ServiceOwnerDialogsCommandsCreate_Dialog.