Two issues raised by @minasarustamyan:
1. head_start loop rendered BEFORE <meta charset="UTF-8"> in both
base.html and base_login.html. HTML5 requires the charset declaration
within the first 1024 bytes; a long operator-injected snippet could
push it past that window, dropping browsers into locale-default
encoding (historically a UTF-7 charset-confusion XSS vector). Move
the head_start loop after charset + viewport meta tags — vendor
hooks (GTM dataLayer init, etc.) still install before any CSS/JS, the
two required meta tags just come first.
2. `entry.get("enabled") is False` matched only the Python False
singleton — `enabled: "false"` (quoted YAML string), `enabled: 0`,
`enabled: "no"` etc. all slipped through (bool("false") == True in
Python). For what is meant to be a kill switch on admin-injected JS,
an operator who fat-fingers the quoting would silently leave the
snippet live. Add `_custom_script_enabled()` coercion helper that
honours quoted booleans, numeric 0, and the usual `no`/`off`/`""`
variants. Default-on for missing / None to preserve the
default-enabled field semantics.
13 new parametrized tests cover every YAML truthy-shape the operator
might paste. Render test now asserts head_start lands after both
required <meta> tags.
Add a generic, placement-aware mechanism for operators to inject HTML/JS
into every page that extends base.html or base_login.html. Each entry
takes name, enabled, placement (head_start | head_end | body_end), and
html. Replaces the need for per-vendor helpers when shipping feedback
widgets, analytics, or error-capture snippets.
Trust boundary mirrors the existing instance.logo_svg / instance.overview
pattern — admin-only, rendered with `| safe`. Resolved by
app/instance_config.py::get_custom_scripts(), surfaced in
/admin/server-config via _KNOWN_FIELDS["instance"]. Empty default keeps
the OSS vendor-neutral; sample Marker.io block ships commented out in
config/instance.yaml.example as the canonical example.