Files
Andy Dixon a002a2c100 feat: add authentication, audit log, HTTP API and base web UI
Phase 1 foundation. Local auth per ADR-0006: Argon2id passwords, opaque
hashed session tokens with idle/absolute expiry, CSRF token plus Origin
check on cookie sessions, per-IP token bucket and per-account exponential
lockout, three roles enforced by middleware, personal API tokens for
noemactl. Audit log writer used by every admin mutation.

API: request ids, panic recovery, strict CSP and security headers, body
limits, single JSON error envelope, health/ready/status, users, sessions,
tokens, audit, token-protected /metrics.

UI: embedded html/template pages (login, first-run setup, dashboard,
system, users, account, audit, interpretation boundary), light/dark
theme, dependency-free app.js with CSRF-aware fetch and SSE helper.

Binaries: noemad with graceful shutdown, migrations at start, bootstrap
admin from environment, supervised background tasks; noemactl with
status, migrate, user create and meaningful exit codes.
2026-06-15 20:22:19 +01:00

16 lines
945 B
HTML

{{define "content"}}
<div class="card auth-card">
<div class="brand big"><span class="brand-mark" aria-hidden="true"></span>Noema</div>
<h1>First-run setup</h1>
<p class="muted">No accounts exist yet. Create the first administrator. This page disappears once an account exists.</p>
<form method="post" action="/setup" class="stack">
<input type="hidden" name="_csrf" value="{{.CSRF}}">
<label>Username <input name="username" autocomplete="username" required minlength="2" maxlength="64" autofocus></label>
<label>Password <input type="password" name="password" autocomplete="new-password" required minlength="12"></label>
<label>Confirm password <input type="password" name="confirm" autocomplete="new-password" required minlength="12"></label>
{{with .Data.Error}}<p class="error" role="alert">{{.}}</p>{{end}}
<button class="btn btn-primary" type="submit">Create administrator</button>
</form>
</div>
{{end}}