package setup import ( "html" "net/http" "git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/web" ) // renderHTML writes the wizard page inside the core shell (SPEC-009 §4). The // door renders no dynamic HTML itself (SPEC-003 §4); the wizard is the hand-off // target for the `setup` workflow. // // F-2: the bootstrap renders secrets and ceremony state — never cache it. func renderHTML(w http.ResponseWriter, status int, page web.Page) error { w.Header().Set("Cache-Control", "no-store") return web.Render(w, status, page) } // writeError writes a terse plain-text error. func writeError(w http.ResponseWriter, status int, msg string) { w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(status) _, _ = w.Write([]byte(msg + "\n")) } // redirect sends the operator back to the wizard (post/redirect/get). func redirect(w http.ResponseWriter, r *http.Request, path string) { http.Redirect(w, r, path, http.StatusSeeOther) } // wizardPage renders the current step inside the shell. The wizard runs before // any identity exists, so the page is a GUEST screen: no nav (SPEC-009 §4). // Every form carries the signed pre-session CSRF token (A15). func wizardPage(st step, token, domain string) web.Page { c := html.EscapeString(token) return web.Page{ Title: "MyDay setup", Guest: true, CSRF: token, Content: web.Markup(`
Bring this instance to life: the domain, the top admin, then mail and locale.
` + stepBody(st, c, domain)), } } // stepBody renders the section for one step. func stepBody(st step, c, domain string) string { switch st { case stepDomain: return `Add an authenticator app. A passkey can be added later, at first sign-in.
` + `