v1 readiness: CHANGELOG + threat model + first-run onboarding polish
CI / Test (store) (pull_request) Successful in 5s
CI / Test (rest) (pull_request) Successful in 9s
CI / Build (windows/amd64) (pull_request) Successful in 7s
CI / Build (linux/amd64) (pull_request) Successful in 7s
CI / Lint (pull_request) Successful in 19s
CI / Build (linux/arm64) (pull_request) Successful in 8s
e2e / Playwright vs docker-compose (pull_request) Failing after 1m35s
CI / Test (server-http) (pull_request) Successful in 2m37s

- CHANGELOG.md: Keep-a-Changelog format, v1.0.0 entry summarising
  what each phase delivered.
- docs/threat-model.md: structured walkthrough of assets, actors,
  attack surfaces and residual risks; reviewed against v1.0.0.
- cmd/server/main.go: at first-run startup, print a clickable
  $RM_BASE_URL/bootstrap URL alongside the existing one-shot
  bootstrap token (or a fallback hint when RM_BASE_URL is unset).
- web/templates/pages/bootstrap.html: visible "Minimum 12 characters"
  hint under the password field so the rule is communicated
  before the operator submits.
- tasks.md: close X-01, X-04, X-05 with notes.
This commit is contained in:
2026-05-09 12:29:00 +01:00
parent 69942463ba
commit 22a5bb7db5
5 changed files with 231 additions and 5 deletions
+12 -2
View File
@@ -9,6 +9,7 @@ import (
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
@@ -145,9 +146,18 @@ func run() error {
// text exactly once; we hash it into BootstrapToken on the
// server-side handler.
fmt.Fprintln(os.Stderr, "================================================================")
fmt.Fprintln(os.Stderr, " FIRST RUN — bootstrap token (use within 1 hour, then it's gone):")
fmt.Fprintln(os.Stderr, " FIRST RUN — no admin user exists yet.")
if cfg.BaseURL != "" {
fmt.Fprintln(os.Stderr, " Open this URL in a browser to create the first administrator:")
fmt.Fprintln(os.Stderr, " "+strings.TrimRight(cfg.BaseURL, "/")+"/bootstrap")
} else {
fmt.Fprintln(os.Stderr, " Open the server URL in a browser; you'll be sent to /bootstrap.")
fmt.Fprintln(os.Stderr, " (Set RM_BASE_URL to have a clickable link printed here.)")
}
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, " Headless? POST {token, username, password} to /api/bootstrap")
fmt.Fprintln(os.Stderr, " with this one-shot token (valid until first user is created):")
fmt.Fprintln(os.Stderr, " "+token)
fmt.Fprintln(os.Stderr, " POST it to /api/bootstrap with {token, username, password}.")
fmt.Fprintln(os.Stderr, "================================================================")
}