diff --git a/server/cmd/echolot-server/main.go b/server/cmd/echolot-server/main.go index 908f460..ababd1a 100644 --- a/server/cmd/echolot-server/main.go +++ b/server/cmd/echolot-server/main.go @@ -234,7 +234,17 @@ func serve(cfg *config.Config) error { http.Error(w, err.Error(), 500) return } - fmt.Fprintf(w, `{"token":%q,"expires_in_s":86400}`+"\n", tok) + // The whole bootstrap, not just the token: this is what gets pasted or turned into a + // QR code, and assembling it here is what keeps an operator from transcribing a pin by + // hand — a pin wrong by one character fails as an inscrutable TLS error days later. + w.Header().Set("Content-Type", "application/json") + enc := json.NewEncoder(w) + enc.SetEscapeHTML(false) // the link is full of / and =; escaping them helps nobody + _ = enc.Encode(map[string]any{ + "token": tok, + "expires_in_s": 86400, + "enroll_uri": ctl.EnrollmentLink(tok), + }) }) adminSrv := &http.Server{Addr: cfg.AdminListen, Handler: admin, ReadHeaderTimeout: 10 * time.Second} go func() { errCh <- fmt.Errorf("admin: %w", adminSrv.ListenAndServe()) }()