Go browser and UI boundary review

Browser Boundary

Browser-adjacent Go should keep host APIs behind narrow adapters. Direct browser globals, JavaScript callbacks, DOM mutation, raw HTML, and runtime diagnostics should be owned by a small testable boundary. Rendering code must validate before serializing, escape text and attribute values, keep deterministic attribute ordering, and avoid serializing callback functions, secrets, or diagnostic metadata into DOM attributes.

URL-bearing fields should accept only same-origin paths, host-resolved resources, or explicitly allowlisted HTTPS origins. Reject javascript:, data:, path traversal, credential-bearing URLs, and sensitive-looking public runtime config keys before rendering or request execution.

Bad:

fmt.Fprintf(w, `<a href="%s">%s</a>`, link.URL, link.Label)

Better:

type LinkView struct {
	URL   SafeURL
	Label string
}

func NewLinkView(link Link) (LinkView, error) {
	url, err := ValidatePublicURL(link.URL)
	if err != nil {
		return LinkView{}, err
	}
	return LinkView{URL: url, Label: link.Label}, nil
}

Prefer html/template or the project’s renderer helpers for output. The review point is that URLs and text are validated before they reach markup.

Projected View Models

UI-producing Go should project before it renders. Provider DTOs, raw provider errors, authorization checks, and permission policy belong in provider or product projection code, not in generic renderers.

View models should contain the visible labels, controls, events, errors, loading and empty states, links, and permissions needed by the renderer. Review generated or server-rendered UI for accessible names, form labels, text status changes, table headers, safe external-link attributes, and an audited sanitizer before any rich text or raw HTML reaches the tree.