strict has no way to exempt one site, so an app with a justified exception can never reach failOnViolation: true
StrictModeConfig offers enabled, failOnViolation and allowPatterns. allowPatterns is the only escape hatch and it is rule-global:
// dist/script-validation.js, 0.2.396
const allowPatterns = strictConfig.allowPatterns ?? []
for (const { pattern, message, suggestion } of PROHIBITED_DOM_PATTERNS) {
if (allowPatterns.some(allowed => /\w/.test(allowed) && message.includes(allowed)))
continue
// …
}It is a substring match against the rule's message, decided once per rule for the whole app, with no reference to the file or the call site. There is nothing else: no stx-strict-ignore comment, no ignoreFiles, no excludeFiles, no per-block attribute. Grepped the whole of dist/ on 0.2.396 to be sure.
So the only ways to handle a violation that is correct are to turn the rule off everywhere, or to leave failOnViolation: false on forever.
The case this blocks
Six HQ apps use this guard. Measured with stx's own validator today: bughq 15 violating blocks, statushq 19, reportshq 10, analyticshq 7, loghq 0, commshq 0. Most are genuine debt and we are working through them.
Some are not debt. An auth form that must intercept its own submit before the runtime loads:
<form id="signin" method="post" action="/api/auth/login">The endpoint parses JSON.parse(await request.text()), so that native POST is not a working fallback — it exists so password managers recognise the form. Under <script client> interception waits for hydration, and a submit in that window posts urlencoded data and signs in with empty fields. A plain <script> with document.getElementById is the correct implementation, and it trips getElementById forever.
Exempting it with allowPatterns: ['getElementById'] would disable that rule across every other page in the app, which is the rule we most want enforced. So the choice is: lose the rule everywhere, or never ratchet.
What would fix it
Any one of these, in preference order:
A comment pragma, checked per block or per line, the way every other linter does it:
// stx-strict-ignore-next-line getElementById -- pre-hydration submit guard var form = document.getElementById('signin')This is the one that documents why at the site, which is the thing a reviewer needs.
File scoping in config, e.g.
allowPatterns: [{ pattern: 'getElementById', files: ['resources/views/login.stx'] }], keeping today's plain-string form working.An
ignoreFiles: string[], which is coarse but still better than global, and cheap to implement.
Why it matters beyond ergonomics
failOnViolation: true is the only state where this guard prevents a regression rather than reporting one. Four of our six apps sit at false with a comment saying "ratchet once the queue is empty". If a queue can contain entries that are correct and unfixable, it never empties, and the guard stays advisory indefinitely — which is close to the original problem, where an absent strict key dropped every finding silently.
A pragma also makes the deliberate cases self-documenting. Right now a reader cannot tell "not migrated yet" from "correct, and here is why", because both look identical in the output.
Found on 0.2.396.