From 2740ab276cc82e0e905f115602a232ccfc136a04 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Sun, 18 Oct 2026 13:24:18 +0200 Subject: [PATCH] docs(19.1-02): add forum bluemonday policy note - Pin the named forum policy on bluemonday v1.0.27 already in go.mod - Separate it from seaglass UGC: PHP allow-list, http/https/mailto, nofollow and target blank - D-17 owns Render/Purify; forum must not vendor goldmark or bluemonday Co-authored-by: Cursor --- .../2026-10-18-bluemonday-forum-policy.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .planning/notes/2026-10-18-bluemonday-forum-policy.md diff --git a/.planning/notes/2026-10-18-bluemonday-forum-policy.md b/.planning/notes/2026-10-18-bluemonday-forum-policy.md new file mode 100644 index 00000000..c630b994 --- /dev/null +++ b/.planning/notes/2026-10-18-bluemonday-forum-policy.md @@ -0,0 +1,32 @@ +# Decision: named bluemonday forum policy (not richeditor UGC) + +**Date:** 2026-10-18 +**Status:** Accepted +**Context:** Phase 19.1 plan 02 (D-16, D-17, D-18), 19.1-RESEARCH.md Pitfall 5 and Pitfall 6 + +## Decision + +Forum sanitizing uses `github.com/microcosm-cc/bluemonday` **v1.0.27**, already required by the framework `go.mod` (seaglass / richeditor, `.planning/notes/2026-10-11-framework-html-sanitizer-bluemonday.md`). This note does **not** add the library again. `sm-forum-plugin` must not `require` bluemonday or goldmark. + +The policy is a **named forum policy**, not seaglass's richeditor UGC policy. It matches the PHP HTMLPurifier config 1:1 (`golem15/forum` `MarkdownRenderer`): + +- `AllowElements` of the PHP list: `p`, `br`, `strong`, `em`, `b`, `i`, `h1`–`h6`, `ul`, `ol`, `li`, `blockquote`, `pre`, `code`, `a` with `href`/`rel`/`target`, `table`, `thead`, `tbody`, `tr`, `th`, `td`, `hr`, `del`, `ins`, `sub`, `sup`. No `img`, no `figure`, no extra UGC tags. +- `AllowURLSchemes("http", "https", "mailto")` only. Not `tel:`, and not the extra relative/tel allowances seaglass adds on top of `UGCPolicy`. +- `RequireNoFollowOnLinks(true)` — PHP `HTML.Nofollow` true. seaglass sets this **false**. +- `AddTargetBlankToFullyQualifiedLinks(true)` — PHP `HTML.TargetBlank` true. + +Markdown conversion uses `github.com/yuin/goldmark` **v1.8.6**, already a framework dependency, with GFM (`extension.GFM`: tables, strikethrough, autolinks). Analog of PHP `GithubFlavoredMarkdownConverter` with `html_input=strip` and `allow_unsafe_links=false`. Raw HTML in markdown input is stripped; unsafe schemes never become links. + +**D-17 owns `Render(markdown)` and `Purify(html)`.** A small `summercms.go` module (or an extension of cabana's markdown support; the `/msd-quick` task decides the package) exports those two funcs with this named policy. Forum, and later Wavepath `purify()` callers (trainings), import that module. Forum does not grow a local renderer, does not call `cabana.RenderMarkdown` (regex gate, no GFM tables, wrong policy), and does not import `seaglass` for post HTML. + +## Related dependencies + +- **seaglass / 2026-10-11 note:** bluemonday UGC for stored richeditor HTML (`RequireNoFollowOnLinks(false)`, `tel:`, images and extra attributes). Forum posts must not use that policy. +- **`cabana.RenderMarkdown`:** goldmark without GFM plus three regexes. Pitfall 6: it is the wrong gate for forum; D-17 is the gate. +- **goldmark GFM** is already used in-tree (`internal/docsite/render.go`). No new markdown library. + +## Consequences + +- Framework `go.mod` keeps the existing pins: `github.com/microcosm-cc/bluemonday v1.0.27` and `github.com/yuin/goldmark v1.8.6`. Forum's `go.mod` never requires either. +- D-17 `Render` runs goldmark GFM then the named forum policy; `Purify` runs the policy on already-HTML. New and edited posts store `content_html` on write (D-18); adopted rows are served stored. +- If D-17 has not landed (`func Render(` / `func Purify(` absent under `modules/`, excluding `cabana.RenderMarkdown`), forum execution **blocks**. It does not vendor the libraries and does not substitute seaglass or a local `forum/classes/markdown.go`.