The previous reason named only multi edit, which made the relaxation look
specific to one tool and newly needed. Neither is true.
LAM emits inline <script> elements through htmlJavaScript from 18 shipped
files, covering two-factor setup, deletion, tree view, mass upload, PDF
editing, several account modules and the config pages. Every one was blocked
before; nothing had driven those paths until a test used multi edit.
Hashing was evaluated and does not work here. A directive carrying any hash
makes browsers ignore unsafe-inline entirely, so all 18 sites would have to be
enumerated, and several build their snippet per request.
script-src-elem.unsafe-inline was off, so the progress driver LAM renders
inline was blocked by the CSP. LDAP import/export and Multi edit posted their
job, rendered "Status: in progress" and never polled it, leaving both tools
hanging for every user. Found while driving Multi edit from a Playwright spec;
the directory was verifiably unmodified afterwards, so it was not a display
artefact.
unsafe-inline re-admits the inline execution an XSS needs and unsafe-eval re-admits string-to-code, so a CSP relaxation must be verified against the running app rather than copied from another role. The new lint requires a nocheck marker plus a Reason on the flag's own line, so a marker cannot drift to the neighbouring directive.
The 197 pre-existing grants across 70 roles are checked out with a TODO: they were never verified and still have to be.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Extract the csp, domains, and networks blocks out of roles/*/meta/server.yml
into dedicated meta files, each mapping to its own top-level applications key
via the recursive meta-walk:
csp: -> meta/csp.yml -> applications.<app>.csp
domains: -> meta/domains.yml -> applications.<app>.domains
networks: -> meta/networks.yml -> applications.<app>.networks
Residual nginx/proxy keys (status_codes, client_max_body_size, locations,
ip6_enabled, config_upstream_url) stay in server.yml; an emptied server.yml is
deleted. 98 server.yml -> 249 new files, 74 deleted.
- Consumers repointed applications.<app>.server.{csp,domains,networks} ->
applications.<app>.{csp,domains,networks} across templates, vars, tasks,
lookups and filters.
- Infra readers migrated: canonical_domains_map, application_domain_index,
build_ldap_role_entries, service-registry overlay discovery,
roles_with_service, and the file-based readers utils/domains/list.py +
utils/meta/scan.py (read the now-deleted server.yml directly).
- Detection + mapping: _META_TOPICS gains csp/domains/networks;
ROLE_FILE_META_{CSP,DOMAINS,NETWORKS} constants + ROLE_FILES entries.
- New self-expiring lint guard (test_server_meta_no_split_fields) fails if a
server.yml still carries a split field; auto-fails from 2026-12-28 as a
delete reminder.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>