Skip to content

Commit 80b6118

Browse files
authored
Merge pull request #26 from itk-dev/feature/ai-bibliotek-whitelisted-signup
feat: restrict AI Bibliotek sign-up to whitelisted municipalities
2 parents 9b062e6 + d325574 commit 80b6118

4 files changed

Lines changed: 49 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

77
## [Unreleased]
88

9+
### Changed — Whitelisted municipality sign-up (ai-bibliotek)
10+
- Sign-up's "Myndighed eller organisation" field is now a select limited to whitelisted municipalities, and registration enforces that the email domain matches the selected municipality's domain (shared `MUNICIPALITIES` list in `auth.js`)
11+
- Documented the intended access model in `index.md`: whitelisted email domains, account verification via email link on sign-up, and a per-domain admin who can delete and promote users (these remain design intent — the `localStorage` mock does not implement them)
12+
913
### Changed — Real PDF links in Vosnæs hearing detail mock (deltag-aarhus)
1014
- The four materials in the Vosnæs prototype (`mocks/index.html`) now link to the actual public PDFs (Forslag til Lokalplan nr. 1237, Miljøvurderingsrapport, Ikke-teknisk resumé, Forslag til §25-tilladelse), opening in a new tab. The lokalplan preview modal's "Åbn på ny side" and "Download PDF" buttons point at the live `plandata.dk` document.
1115

docs/projects/ai-bibliotek/index.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ Hero med søgefelt, kort introduktion og statistik (antal assistenter, deltagend
3535

3636
Simpel brugerflade hvor en medarbejder kan oprette en konto (i første omgang opret sig selv) eller logge ind. Brugere gemmes i `localStorage`. Ingen reel auth — kun til demoformål.
3737

38+
I prototypen vælges **myndighed** fra en dropdown (kun whitelistede myndigheder), og registrering kræver, at e-mailen ligger på den valgte myndigheds domæne. Det illustrerer den tiltænkte adgangsmodel:
39+
40+
- **Whitelistet domæne** — kun medarbejdere med en arbejdsmail på et whitelistet domæne (fx `@aarhus.dk`) kan oprette sig. Domænet er adgangsporten; nye myndigheder optages ved at få deres domæne tilføjet til listen.
41+
- **Verifikation ved oprettelse** — den nye bruger bekræfter sin konto via et link sendt til e-mailen, før kontoen aktiveres.
42+
- **Domæne-admin** — for hvert domæne udpeges en bruger som **admin** med rettigheder til at **slette** brugere og **forfremme** andre brugere (herunder til admin) inden for samme domæne.
43+
44+
::: info Prototype
45+
Selve verifikationsflowet, admin-rollen og brugeradministrationen er kun beskrevet som tiltænkt model — prototypen simulerer dem ikke. Mocken håndhæver dog whitelisten og domæne-matchet ved oprettelse.
46+
:::
47+
3848
### Katalog og søgning
3949

4050
Fritekstsøgning kombineret med facetter: **oprindelseskommune, sprogmodel, rammeværk** (i dag OpenWebUI) og **datafølsomhed** (almindelige personoplysninger / fortrolige / personfølsomme). Resultater vises som kort med badges.
@@ -82,6 +92,10 @@ Prototypen er et diskussionsgrundlag, ikke en implementeringsklar løsning. En r
8292

8393
I prototypen er **kataloget offentligt at browse**, mens det at **dele og eksportere** kræver login. Det er en antagelse, ikke en beslutning. Skal selve eksistensen af en assistent (navn, formål, kommune) være åben, mens JSON og modelkort er bag login? Eller skal hele biblioteket være lukket for ikke-myndigheder?
8494

95+
### Hvem styrer whitelisten og admin-rollen?
96+
97+
Adgang gives via whitelistede e-mail-domæner. Hvem godkender, at et nyt domæne (en ny myndighed) optages? Og hvem udpeger den første admin for et domæne, før der overhovedet er en admin til at forfremme andre? Der skal tages stilling til både onboarding af nye myndigheder og den indledende rolletildeling.
98+
8599
### Hvad er der i JSON-filerne?
86100

87101
Kan vi ukritisk dele indholdet af en OWUI-assistents JSON? Systemprompter kan indeholde interne formuleringer, henvisninger til konkrete sager eller forudsætninger, der ikke bør deles bredt. Der skal tages stilling til, hvad der reviewes inden deling.

docs/public/projects/ai-bibliotek/mocks/js/auth.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@ export const DEMO_USERS = [
1818
{ id: "demo-odense", name: "Jonas Holm", organization: "Odense Kommune", email: "jonas@odense.dk", password: "demo1234" }
1919
];
2020

21+
/* Whitelisted myndigheder. Only employees with an email on a municipality's
22+
domain may register — this list drives both the sign-up select and the
23+
domain check in register(). In a real system the whitelist is the gate;
24+
here it just makes the rule tangible in the prototype. */
25+
export const MUNICIPALITIES = [
26+
{ name: "Aarhus Kommune", domain: "aarhus.dk" },
27+
{ name: "Odense Kommune", domain: "odense.dk" },
28+
{ name: "Københavns Kommune", domain: "kk.dk" },
29+
{ name: "Aalborg Kommune", domain: "aalborg.dk" },
30+
{ name: "Vejle Kommune", domain: "vejle.dk" },
31+
{ name: "Randers Kommune", domain: "randers.dk" }
32+
];
33+
2134
export const auth = {
2235
currentUser() {
2336
const session = store.getSession();
@@ -33,6 +46,14 @@ export const auth = {
3346
if (password.length < 4) {
3447
throw new Error("Adgangskoden skal være mindst 4 tegn.");
3548
}
49+
const muni = MUNICIPALITIES.find(m => m.name === organization?.trim());
50+
if (!muni) {
51+
throw new Error("Vælg en myndighed fra listen.");
52+
}
53+
const domain = email.split("@")[1] || "";
54+
if (domain !== muni.domain) {
55+
throw new Error(`E-mailen skal være en @${muni.domain}-adresse for ${muni.name}.`);
56+
}
3657
const users = store.getUsers();
3758
if (users.some(u => u.email === email)) {
3859
throw new Error("En bruger med denne e-mail findes allerede.");

docs/public/projects/ai-bibliotek/mocks/js/views/login.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { el, clear, navigate, toast } from "../util.js";
2-
import { auth, DEMO_USERS } from "../auth.js";
2+
import { auth, DEMO_USERS, MUNICIPALITIES } from "../auth.js";
33

44
export function render(root, query = {}) {
55
clear(root);
@@ -106,11 +106,18 @@ function registerForm() {
106106
]),
107107
el("label", { class: "field" }, [
108108
"Myndighed eller organisation",
109-
el("input", { type: "text", name: "organization", placeholder: "f.eks. Aarhus Kommune", autocomplete: "organization" })
109+
el("select", { name: "organization", required: true }, [
110+
el("option", { value: "", disabled: true, selected: true }, "Vælg myndighed …"),
111+
...MUNICIPALITIES.map(m =>
112+
el("option", { value: m.name }, `${m.name} (${m.domain})`)
113+
)
114+
]),
115+
el("span", { class: "hint" }, "Kun whitelistede myndigheder. Kontakt os for at få din myndighed tilføjet.")
110116
]),
111117
el("label", { class: "field" }, [
112118
"E-mail",
113-
el("input", { type: "email", name: "email", required: true, autocomplete: "email" })
119+
el("input", { type: "email", name: "email", required: true, autocomplete: "email" }),
120+
el("span", { class: "hint" }, "Skal være din arbejdsmail på myndighedens domæne (f.eks. @aarhus.dk).")
114121
]),
115122
el("label", { class: "field" }, [
116123
"Adgangskode",

0 commit comments

Comments
 (0)