{"openapi": "3.1.0", "info": {"title": "hafn kontrollplan", "version": "1.0.0", "description": "hafns ytterdörr: skapar hushållskonton mot en engångs inbjudningskod och delar ut en scopad API-nyckel. Samma endpoint tjänar agenter (JSON) och människor (formulär). Hemligheterna i svaret visas en gång och lagras inte."}, "servers": [{"url": "https://127.0.0.1:8766", "description": "Loopback på mail.hafn.eu (nås via SSH-tunnel; publik exponering är ett senare beslut)"}], "paths": {"/v1/konto": {"post": {"operationId": "skapaKonto", "summary": "Skapa hushållskonto och scopad API-nyckel", "description": "Kräver en giltig, oanvänd inbjudningskod. En agent POST:ar application/json och får JSON; ett formulär POST:ar application/x-www-form-urlencoded och får en kvittosida i HTML. Fälten är desamma. Lösenordet och API-nyckeln i svaret visas EN gång. Nyckeln används som 'Authorization: Bearer <apinyckel>' mot https://mail.hafn.eu/jmap/ och kan läsa post, läsa och skriva kalender samt hantera pushprenumerationer — sändning är spärrad (forbidden).", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/KontoBegaran"}}, "application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/KontoBegaran"}}}}, "responses": {"201": {"description": "Kontot skapat. Hemligheterna visas en gång.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/KontoSvar"}}}}, "400": {"description": "Ogiltiga fält", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fel"}}}}, "403": {"description": "Inbjudningskoden är ogiltig eller använd", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fel"}}}}, "409": {"description": "Kontonamnet är upptaget (koden ej förbrukad)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fel"}}}}, "429": {"description": "För många försök från samma adress", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fel"}}}}, "502": {"description": "Bakomliggande fel; inget skapat, koden ej förbrukad", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fel"}}}}}}}, "/v1/begar-mer": {"post": {"operationId": "begarHogreTak", "summary": "Begär högre utgående posttak än 100 mejl/dygn", "description": "Loggar en förfrågan om högre utgående tak. Ingen automatik: en människa hos hafn läser loggen och hör av sig till kontots adminkontakt.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TakBegaran"}}, "application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/TakBegaran"}}}}, "responses": {"202": {"description": "Förfrågan mottagen och loggad", "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string"}}}}}}, "400": {"description": "Ogiltiga fält", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fel"}}}}}}}, "/halsa": {"get": {"operationId": "halsa", "summary": "Livstecken", "responses": {"200": {"description": "Tjänsten svarar", "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string"}}}}}}}}}}, "components": {"schemas": {"KontoBegaran": {"type": "object", "required": ["inbjudningskod", "kontonamn", "adminkontakt"], "properties": {"inbjudningskod": {"type": "string", "pattern": "^hafn(-[a-z2-9]{4}){3}$", "description": "Engångskod från hafn", "examples": ["hafn-abcd-efgh-jkmn"]}, "kontonamn": {"type": "string", "pattern": "^[a-z][a-z0-9-]{2,29}$", "description": "Blir adressen kontonamn@hafn.eu", "examples": ["frisktest"]}, "adminkontakt": {"type": "string", "format": "email", "description": "E-postadress till hushållets kontaktperson"}}}, "KontoSvar": {"type": "object", "properties": {"konto": {"type": "string"}, "adress": {"type": "string"}, "engangslosenord": {"type": "string", "description": "Kontots lösenord. Visas en gång."}, "apinyckel": {"type": "string", "description": "Scopad nyckel (API_...). Visas en gång. Används som Bearer mot JMAP."}, "apinyckelns_scope": {"type": "array", "items": {"type": "string"}}, "jmap": {"type": "string", "format": "uri"}, "imap": {"type": "object"}, "smtp": {"type": "object"}, "viktigt": {"type": "string"}}}, "TakBegaran": {"type": "object", "required": ["konto", "motivering"], "properties": {"konto": {"type": "string", "pattern": "^[a-z][a-z0-9-]{2,29}$"}, "motivering": {"type": "string", "maxLength": 1000}}}, "Fel": {"type": "object", "properties": {"fel": {"type": "string"}, "beskrivning": {"type": "string"}}}}}}