Skip to content

Propose ADR-0003 for imports, with the unit import contract - #32

Merged
RonnyB71 merged 1 commit into
mainfrom
docs/adr-imports
Nov 1, 2026
Merged

RonnyB71 merged 1 commit into
mainfrom
docs/adr-imports

Conversation

@RonnyB71

@RonnyB71 RonnyB71 commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Proposes how data from Digdir's authoritative source gets into Saman (NF-07), starting with units (LO-01, LO-02, FO-02). This PR is documentation only. Per CLAUDE.md, the implementation waits until ADR-0003 is Accepted.

Please discuss it here, as review comments.

ADR-0003: Imports from the authoritative source (Proposed)

The sender runs PowerShell, POSTs a CSV file, and shouldn't have to wait for database updates. The proposal:

  1. POST /api/enheter/import takes the CSV file as the body.
  2. Only an integration user may call it. It authenticates with a Payload API key, and has a new role, integration, limited to the import endpoints.
  3. Every row is validated before the file is accepted. A file with errors is refused whole with 400, listing every error with its line number.
  4. An accepted file is stored as an import run (importkjoringer), which administrators can see in the admin panel. The response is 202 Accepted, with a status URL.
  5. A job (importUnits) in Payload's jobs queue applies the file in one transaction:
    • it creates or updates units and sets their parents and leaders
    • it marks units missing from the file as inactive (full snapshot)
    • it links people's units again
  6. Concurrency control (exclusive + supersedes) means one import at a time, and a newer file replaces an older one that hasn't started.
  7. Retries: up to 3 times with backoff.
  8. Started by autoRun every 10 seconds in the CMS.

The ADR also lists the options that weren't chosen, and why: importing during the request, a separate pipeline, sending only changes, multipart, an Entra ID app with client credentials, and a separate worker.

Still to agree (checklist in the ADR):

  • Final column names: Saman's own names for now, until the source decides.
  • Protection against a truncated file: proposed to refuse a file with fewer than half as many units as are active today, until an administrator confirms it. Every row is checked anyway, but a file that's cut off is still valid row by row, and as a full snapshot it would close the units it lacks.
  • How long files are kept: proposed 90 days.
  • The network path from Leikanger to the CMS.

docs/integrations/unit-import.md

The contract to send to whoever writes the PowerShell script:

  • the request, the file format and the columns, with an example
  • what makes a file be refused
  • the responses, with examples
  • the status endpoint
  • an example script for Windows PowerShell 5.1 and PowerShell 7

The script covers the pitfalls with Export-Csv (ASCII by default in 5.1, and the #TYPE line) and with Invoke-RestMethod (-InFile, not a string in -Body).

Other

  • ADR index: ADR-0003 is added to the index in docs/adr/README.md.
  • architecture.md: its open question about the batch endpoint's contract now points to ADR-0003.
  • CLAUDE.md: describes the new folder docs/integrations/.

🤖 Generated with Claude Code

How units, and later people and locations, come in from the authoritative
source (NF-07): the sender POSTs a full snapshot as CSV, Saman validates
every row, stores the file as an import run and answers 202, and a job in
Payload's jobs queue applies it in one transaction. docs/integrations/
holds the contract for whoever writes the PowerShell script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RonnyB71
RonnyB71 merged commit 1cd5c53 into main Nov 1, 2026
6 checks passed
@RonnyB71
RonnyB71 deleted the docs/adr-imports branch November 1, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant