Pre-v1 hardening: admin bootstrap, CSP + security headers, log stream, onboarding tour - #57
Merged
Merged
Conversation
…ng tour Closes #27, #32, #34; adds a first-login onboarding tour. - #27 Admin bootstrap via ADMIN_EMAIL: the user with this email is (and stays) the global admin — deterministic, replacing the first-user-becomes-admin race. Self-healing (promotes on login) and last-admin demotion is already guarded. - #32 Security hardening: strict Content-Security-Policy + X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy on every response. Removed the one inline <script> (SSE redirect now via self-hosted app.js), so script-src can be 'self'. Rate limiting was already added. - #34 Structured logging + Log Stream: slog with LOG_FORMAT=text|json tee'd to stderr and an in-memory hub; admin Logs page streams the log live over SSE (token-guarded) and documents the json-to-shipper path. - Onboarding: a skippable, full-screen first-login tour (tracked via users.onboarded_at; CSP-safe — nav in app.js, dismiss via htmx). Security pass: fixed a Content-Disposition header-injection vector (the PDF filename is now slugified to [a-z0-9-]) and added a same-origin guard to all redirects. govulncheck and gosec both run clean (reviewed false positives are annotated with #nosec + justification).
This was referenced Jul 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last round of work before tagging v1.0.0. Closes #27, #32, #34 and adds a first-login onboarding tour.
#27 — Deterministic admin bootstrap (
ADMIN_EMAIL)Replaces "first user to sign in becomes admin" (a race on an empty DB) with a deterministic rule: the user whose email matches
ADMIN_EMAILis — and stays — the global admin (self-healing on login). Combined with the existing last-admin-demotion guard, admin state is now race-free and deterministic.#32 — Security headers + CSP
Content-Security-Policy(script-src 'self'— all JS is self-hosted, no inline scripts), plusX-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy,Permissions-Policyon every response.<script>(the SSE consolidation redirect now runs from a self-hostedapp.js).#34 — Structured logging + admin Log Stream
slogwithLOG_FORMAT=text|json, tee'd to stderr and an in-memory ring-buffer hub.LOG_FORMAT=jsonis the path for external shippers.Onboarding tour
A skippable, full-screen first-login tour (5 slides → positive welcome). Tracked via a new
users.onboarded_atcolumn (migration0002); CSP-safe (slide nav inapp.js, dismiss via htmx).Security pass
[a-z0-9-](closes aContent-Dispositionheader-injection vector), and added a same-origin guard to all redirects.govulncheck→ 0 vulnerabilities;gosec→ 0 issues (reviewed false positives annotated with#nosec+ justification).Verification
go build,go vet,gofmt,go test ./...(incl. Postgres gateway tests) all green. Docker release image builds, runs migrations (incl.0002), and serves with the CSP header + JSON logs. New behaviors covered by tests (ADMIN_EMAIL bootstrap + self-heal, onboarding show/complete, log hub, SSE token gate).Also: closed #36 (distribution project, no automated deploy) and #38 (multi-tenancy: future, not current roadmap).