Märkesspecifika kopplingar — kunden lägger in sina egna credentials
Verkstaden har redan sina avtal: Volvo-verkstaden har VIDA, VAG-verkstaden har erWin, den fria verkstaden har en fordonsdataleverantör. Kopplingarna konfigureras därför av kunden själv under Inställningar, med sina egna uppgifter — vi tillhandahåller ramen, inte kontot. Uppgifterna når aldrig webbläsaren. De krypteras med AES-256-GCM (INTEGRATION_NYCKEL) innan de skrivs till tabellen integrationer, och API:t returnerar hemliga fält maskerade. Alla uppslag görs av servern. Saknas krypteringsnyckeln sparas ingenting alls — 503 och en förklaring i gränssnittet i stället för klartext i databasen. Endast systemadministratören hanterar uppgifterna; kopplingarna är organisationsknutna som all annan ärendedata. Leverantörer är data, inte kod: URL-mall, autentiseringstyp (bearer/header/basic/query) och svarsmappning beskrivs i services/plattform/integrationer.json, utbytbar via ConfigMap (INTEGRATIONER_FIL). Nya märken läggs till utan att appen byggs om. Varje uppslag skriver senast_testad och senaste_status på kopplingen, så ett utgånget abonnemang syns i inställningarna i stället för att ge tysta tomma svar. Två latenta krascher hittade av klicktestet och åtgärdade: TextFalt och UNDANTAGSORSAKER användes utan import. vite build typkontrollerar inte, så de passerade bygget — därav nya npm-skriptet typkontroll, nu del av verifieringen. Verifierat: 80 vitest-tester, typkontroll, eslint, OpenAPI-validering, integrationstest mot riktig Postgres (rollstyrning, kryptering i vila, maskering, organisationsisolering, fail closed, borttagning) och klickgenomgång mot en körande plattform. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
This commit is contained in:
@@ -26,6 +26,7 @@ tags:
|
||||
- name: Översikt
|
||||
- name: Delning
|
||||
- name: AI
|
||||
- name: Integrationer
|
||||
- name: Drift
|
||||
|
||||
paths:
|
||||
@@ -229,6 +230,185 @@ paths:
|
||||
"401": { $ref: "#/components/responses/Fel" }
|
||||
"403": { $ref: "#/components/responses/Fel" }
|
||||
|
||||
/api/integrationer/leverantorer:
|
||||
get:
|
||||
tags: [Integrationer]
|
||||
summary: Registret över märkesspecifika kopplingar
|
||||
description: >
|
||||
Leverantörer är data, inte kod: registret läses ur
|
||||
`integrationer.json` (eller filen i `INTEGRATIONER_FIL`) och kan
|
||||
bytas via ConfigMap utan att applikationen byggs om. Innehåller
|
||||
endast fältdefinitioner — aldrig någon organisations uppgifter.
|
||||
responses:
|
||||
"200":
|
||||
description: Leverantörsdefinitioner.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
version: { type: string }
|
||||
leverantorer:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
namn: { type: string }
|
||||
beskrivning: { type: string }
|
||||
nyckeltyp:
|
||||
type: string
|
||||
enum: [vin, regnr]
|
||||
description: Vad uppslaget sker på. Utelämnat betyder VIN.
|
||||
falt:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
nyckel: { type: string }
|
||||
etikett: { type: string }
|
||||
hemlig:
|
||||
type: boolean
|
||||
description: >
|
||||
Hemliga fält maskeras alltid i svar och
|
||||
visas aldrig igen efter sparande.
|
||||
"401": { $ref: "#/components/responses/Fel" }
|
||||
|
||||
/api/integrationer:
|
||||
get:
|
||||
tags: [Integrationer]
|
||||
summary: Organisationens konfigurerade kopplingar
|
||||
description: >
|
||||
Kräver rollen `admin`. Uppgifterna lagras krypterade
|
||||
(AES-256-GCM) och returneras alltid maskerade — hemliga värden
|
||||
lämnar aldrig servern i klartext.
|
||||
responses:
|
||||
"200":
|
||||
description: Konfigurerade kopplingar med maskerade uppgifter.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
krypteringKonfigurerad:
|
||||
type: boolean
|
||||
description: Falskt om `INTEGRATION_NYCKEL` saknas — då kan inget sparas.
|
||||
integrationer:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
leverantor: { type: string }
|
||||
namn: { type: string }
|
||||
aktiv: { type: boolean }
|
||||
uppdaterad: { type: string, format: date-time }
|
||||
senast_testad: { type: string, format: date-time, nullable: true }
|
||||
senaste_status: { type: string, nullable: true }
|
||||
uppgifter:
|
||||
type: object
|
||||
additionalProperties: { type: string }
|
||||
"401": { $ref: "#/components/responses/Fel" }
|
||||
"403": { $ref: "#/components/responses/Fel" }
|
||||
post:
|
||||
tags: [Integrationer]
|
||||
summary: Spara eller uppdatera en kopplings uppgifter
|
||||
description: >
|
||||
Kräver rollen `admin`. Endast leverantörens definierade fält
|
||||
sparas och samtliga måste fyllas i. Uppgifterna krypteras innan
|
||||
de skrivs. Ett sparande nollställer tidigare testresultat.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [leverantor, uppgifter]
|
||||
properties:
|
||||
leverantor: { type: string }
|
||||
aktiv: { type: boolean, default: true }
|
||||
uppgifter:
|
||||
type: object
|
||||
additionalProperties: { type: string }
|
||||
responses:
|
||||
"200": { description: Sparad. }
|
||||
"400": { $ref: "#/components/responses/Fel" }
|
||||
"401": { $ref: "#/components/responses/Fel" }
|
||||
"403": { $ref: "#/components/responses/Fel" }
|
||||
"503":
|
||||
description: Kryptering är inte konfigurerad (`INTEGRATION_NYCKEL` saknas).
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Fel" }
|
||||
|
||||
/api/integrationer/{leverantor}:
|
||||
delete:
|
||||
tags: [Integrationer]
|
||||
summary: Ta bort en kopplings uppgifter
|
||||
description: Kräver rollen `admin`.
|
||||
parameters:
|
||||
- name: leverantor
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
"200": { description: Borttagen. }
|
||||
"401": { $ref: "#/components/responses/Fel" }
|
||||
"403": { $ref: "#/components/responses/Fel" }
|
||||
|
||||
/api/integrationer/{leverantor}/uppslag:
|
||||
post:
|
||||
tags: [Integrationer]
|
||||
summary: Slå upp ett fordon hos leverantören
|
||||
description: >
|
||||
Anropet görs alltid av servern — kundens leverantörsnycklar når
|
||||
aldrig webbläsaren. Svaret mappas till våra fält enligt
|
||||
registrets `svarsfalt`. Resultatet skrivs som kopplingens
|
||||
senaste teststatus.
|
||||
parameters:
|
||||
- name: leverantor
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [identifierare]
|
||||
properties:
|
||||
identifierare:
|
||||
type: string
|
||||
description: VIN eller registreringsnummer beroende på leverantörens `nyckeltyp`.
|
||||
responses:
|
||||
"200":
|
||||
description: Fordonsuppgifter från leverantören.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
fordon:
|
||||
type: object
|
||||
additionalProperties: { type: string }
|
||||
"400": { $ref: "#/components/responses/Fel" }
|
||||
"401": { $ref: "#/components/responses/Fel" }
|
||||
"404":
|
||||
description: Kopplingen är inte konfigurerad för organisationen.
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Fel" }
|
||||
"502":
|
||||
description: Leverantören svarade med fel eller inga kända fält.
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Fel" }
|
||||
"503":
|
||||
description: Kryptering är inte konfigurerad.
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Fel" }
|
||||
|
||||
/api/delad/{delningskod}/beslut:
|
||||
post:
|
||||
tags: [Delning]
|
||||
@@ -617,6 +797,10 @@ components:
|
||||
properties:
|
||||
error: { type: string }
|
||||
schemas:
|
||||
Fel:
|
||||
type: object
|
||||
properties:
|
||||
error: { type: string }
|
||||
Roll:
|
||||
type: string
|
||||
enum: [tekniker, arbetsledare, admin]
|
||||
|
||||
Reference in New Issue
Block a user