Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KontAKT

Aarhus Kommune aktindsigt case management — Flask + HTMX, SQLAlchemy on MSSQL, behind IIS.

Architecture in one paragraph

The Flask web tier is thin. All heavy or long-running work — OS2Forms intake polling, IMAP polling of the shared mailbox, GO/Nova fetches, screening, retention deletion, warning emails — runs on OpenOrchestrator robots on separate machines. KontAKT enqueues OO work by POSTing to PyOrchestrator API (/api/queue, /api/trigger). OO writes results back to KontAKT by writing directly to its MSSQL tables (or, in the rare case it makes sense, calling a small KontAKT endpoint).

First-time setup

1. Database

On the MSSQL server (the existing one OO uses), as sysadmin:

CREATE DATABASE KontAKT COLLATE Danish_Norwegian_CI_AS;
ALTER DATABASE KontAKT SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE KontAKT SET ALLOW_SNAPSHOT_ISOLATION ON;

Then in the new KontAKT database, run db/schema.sql.

2. App login

Edit db/create_login.sql and replace the placeholder password with a real strong one. Run it as sysadmin. This creates the kontakt_app login and grants db_datareader + db_datawriter (no DDL — schema changes go through schema.sql).

3. Configuration

Two layers:

  • config.toml at the project root — committed, non-secret. Server names, SMTP host, SMTP from-address, allowed email domain, TTLs, etc. Edit directly. Create config.local.toml for per-developer overrides (gitignored, merges on top).

  • Environment variables — secrets only:

    Variable What
    KONTAKT_SECRET_KEY Flask session signing key. 32+ random chars.
    KONTAKT_DB_USERNAME MSSQL login (= kontakt_app).
    KONTAKT_DB_PASSWORD The password you set in create_login.sql.
    KONTAKT_PYORCH_API_KEY X-API-Key for the PyOrchestrator API.
    KONTAKT_GO_USERNAME NTLM user for GO API (case-search autocomplete on step 3).
    KONTAKT_GO_PASSWORD Password for KONTAKT_GO_USERNAME.
    KONTAKT_NOVA_CLIENT_SECRET OAuth client secret for KMD Nova (case-search autocomplete).
    KONTAKT_OO_API_KEY X-API-Key that OO uses when calling INTO KontAKT (attachment upload callbacks).

On your dev machine (PowerShell)

setx KONTAKT_SECRET_KEY      "<paste 32+ random chars>"
setx KONTAKT_DB_USERNAME     "kontakt_app"
setx KONTAKT_DB_PASSWORD     "<the password from step 2>"
setx KONTAKT_PYORCH_API_KEY  "<pyorch api key>"
setx KONTAKT_OO_API_KEY      "<random 32+ chars — shared with OO scripts>"

setx persists into your user environment — open a new terminal to pick up the values. To generate a secret key:

python -c "import secrets; print(secrets.token_urlsafe(48))"

On the IIS server

Use iis/web.config as a template. The <environmentVariables> block under <httpPlatform> is where the four secrets go. Everything else stays in config.toml.

4. Python env

Python 3.11+ required (for stdlib tomllib).

python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -e .[dev]

5. HTMX

Self-contained for behind-firewall deployment — vendor the file:

New-Item -ItemType Directory -Force app\static\vendor | Out-Null
Invoke-WebRequest -Uri "https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js" -OutFile "app\static\vendor\htmx.min.js"

6. Run

$env:FLASK_APP = "wsgi.py"
python -m flask run --debug

Visit http://localhost:5000/auth/login. With auth_dev_mode = true in config.toml, the magic link prints to the console — no SMTP needed for local dev.

Production (IIS)

wsgi.py is the entry point. The recommended pattern is HttpPlatformHandler (modern replacement for FastCGI for Python on IIS):

  1. Install HttpPlatformHandler on the IIS server.
  2. Drop iis/web.config into the site root next to the project; replace the REPLACE-ME values.
  3. The app pool identity needs read+execute on the project folder and read+write on iis/logs/ (created at runtime).

HttpPlatformHandler launches waitress as a child process with the env vars from <environmentVariables> set, and proxies HTTP to it on a private port.

Auth & user management

  • Magic link to *@aarhus.dk, raw token in email, only SHA-256 hash in DB, 15-min TTL, one-time use.
  • Users are not auto-created. An admin must add the user row first; otherwise the magic link, while still sent, will fail to verify.
  • Self-service "request access" page is planned — sends the email to admin queue for approval.
  • Every authentication-related action (magic_link_requested, user_login, user_login_failed, user_logout) is recorded in audit_log with IP and email context.

Auth is isolated in app/auth/service.py so it can be swapped for OIDC/Entra ID later without touching routes.

Project layout

KontAKT/
├── config.toml                  # non-secret config, committed
├── db/
│   ├── schema.sql               # canonical schema — run once on fresh DB
│   └── create_login.sql         # creates the kontakt_app MSSQL login
├── iis/
│   └── web.config               # IIS HttpPlatformHandler template
├── app/
│   ├── __init__.py              # app factory
│   ├── config.py                # TOML + env loader
│   ├── extensions.py            # db = SQLAlchemy()
│   ├── models.py
│   ├── audit.py                 # audit.log() helper
│   ├── auth/                    # magic-link login
│   ├── main/                    # dashboard + case views (stub)
│   ├── templates/
│   └── static/
├── wsgi.py
└── pyproject.toml

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages