7.1 KiB
Audit: announce
audit-version: 1 audited-at: 2026-06-26 scope: method: adversarially-verified workflow; HIGH lead-verified. B7 ground-truth: Toolbar A35 + Form A36 incidents STAYED FIXED (untrack present); toast/clipboard/drag-drop use uix.timers (no A6 leak); button is clean (its archetype finding was inert — Spinner not runtime-registered); data-size/data-shape are eidos visual attrs (not contract violations). provider: src/uix/soma/components/announce/announce-provider.svelte.ts cleanup-audit (A6/A35/A36): Line 75-77: Single $effect with cleanup return (clearTimers()). Disposes: politeTimer and assertiveTimer via cancel() if present (lines 149-161). Timers are scheduled via soma.uix.timers.schedule() (A6 compliant). Global createAnnouncer (global.svelte.ts): timers stored in RegionPair.timer and cance
Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 0.
Findings
MEDIUM: eidos CSS selectors must match morfo-declared or runtime-auto-generated attributes. A decl — announce-001
- dimension: E-bis: Theming / Selector drift
- rule: eidos CSS selectors must match morfo-declared or runtime-auto-generated attributes. A declared prop like
visuallyHiddenmust have a corresponding data attribute or inline style to drive styling. - location: src/uix/eidos/components/announce/announce.css:23
- evidence: Line 23 uses selector
[data-announce-region]:not([data-visually-hidden])to style visible regions. However,data-visually-hiddenattribute is never written by soma. The provider (announce-provider.svelte.ts:246) writes inlinestylewhen hidden, but never writes adata-*attribute to signal visibility state to eidos. - impact: The CSS selector
:not([data-visually-hidden])always matches because the attribute is never present. This means card styling (display, padding, border, etc.) is incorrectly applied to ALL regions, including those wherevisuallyHidden=true(which should be sr-only with no card chrome). - repro: Mount an Announce.Region with
visuallyHidden={false}. The region will receive card styling (padding, border, etc.). Mount another withvisuallyHidden={true}(default). It will ALSO receive card styling, breaking the sr-only case. - proposed-fix: Option A: Modify AnnounceRegionProvider.props (line 242-248) to write
data-visually-hidden: hidden ? '' : undefinedso the CSS:not([data-visually-hidden])selector works correctly. Option B: Change the CSS selector to check for inline style presence (not reliable) or add a separatedata-visibleattribute when visuallyHidden is false. Recommend Option A with a morfo data declaration for the attribute. - verify: [downgraded] MECHANISM CONFIRMED, IMPACT REFUTED. Confirmed:
data-visually-hiddenis NEVER written anywhere. Morfo (announce.ts:88-99) declares onlydata-role+data-liveon theregionpart; the provider (announce-provider.svelte.ts:243-247) drivesvisuallyHiddenONLY via inlinestyle: hidden ? VISUALLY_HIDDEN_STYLE : undefined; grep across soma+eidos finds no writer of the attr (announce.css:23 is the sole reference). So[data-announce-region]:not([data-visually-hidden])(announce.css:23) ALWAYS matches — the negation is dead/non-functional CSS; the 'visible regions only' guard the author intended never excludes the sr-only case. THAT part is a real selector-drift defect (E-bis), MEDIUM stands. BUT the candidate's IMPACT ('incorrectly applied to ALL regions ... breaking the sr-only case') is REFUTED: when visuallyHidden=true, soma sets the inline sr-only style (position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)) which has higher specificity than the stylesheet rule and overridespadding:0/border:0inline (lines 12-22). The leftoverdisplay:block/background/border-radius/font-size/line-heightfrom the CSS block are visually inert on a 1x1px clipped box — the region stays hidden. So the sr-only case is NOT broken; the defect is dead CSS / a non-functional visible-vs-hidden distinction, not an a11y/visual regression. Keeping MEDIUM but correcting the rationale/impact. - fix-status: open
MEDIUM: eidos CSS selectors must key off attributes the morfo declares or soma actually writes; a — announce-101
- dimension: E-bis: Theming / selector drift, SYS-1-adjacent
- rule: eidos CSS selectors must key off attributes the morfo declares or soma actually writes; a
:not([attr])guard against an attribute that is never emitted is dead CSS that silently never differentiates state. - location: src/uix/eidos/components/announce/announce.css:23
- evidence:
[data-announce-region]:not([data-visually-hidden]) { display:block; padding:...; border:...; background:...; }— butdata-visually-hiddenis never written: announce.ts:88-99 declares onlydata-roleanddata-liveon the region part, and announce-provider.svelte.ts:243-247 drivesvisuallyHiddenexclusively via inlinestyle(hidden ? VISUALLY_HIDDEN_STYLE : undefined), never a data attribute. Grep across soma+eidos confirms no writer. - impact: The intended 'visible regions only' branch is non-functional: the
:not()negation always passes, so the visible-card rule applies to every region. It is masked in the default (visuallyHidden=true) case because the higher-specificity inline sr-only style clips the box, so there is no user-visible regression today — but the CSS no longer expresses the visible-vs-hidden intent and will silently mis-style if the inline style ever changes. Dead-code distinction. - repro: Mount
<Announce.Region visuallyHidden={false}>and<Announce.Region visuallyHidden={true}>; inspect computed styles — the visible-card rule (display:block/background/font-size) resolves on BOTH because:not([data-visually-hidden])matches both; only the inline sr-only clip differentiates them, not the CSS branch as intended. - proposed-fix: Either (a) project the state as a real attribute the CSS can key on — e.g. declare
data-visually-hiddenin the region part's morfodataand have soma write it fromopts.visuallyHidden, then keep:not([data-visually-hidden]); or (b) gate the visible-card chrome on an opt-in attribute the consumer sets (e.g.data-variant='visible') rather than a negation of a never-present attr. Option (a) keeps the existing selector working. - verify: [verifier-added] added by adversarial verify pass
- fix-status: open
No-findings dimensions
A: Contract (morfo), B: Behavior (A35/A36/A6/A15/live-regions/A30/A33/A31), C: DOM-selector, D: Frontier, E: TSC, F: Tests, G: Redundancy
Theming facts (E-bis)
- magic z-index: none
- magic literals: none
- undeclared parts: none
- roles clean: true · variants clean: true
Tests (F)
- exists: true · env: jsdom via vitest
- covers: timer scheduling and cancellation via soma.uix.timers; A/B toggle for repeated announcements; role/aria-live derivation; declarative region attrs sync; standalone region without provider; provider context context injection
- untested: visible region CSS application (visuallyHidden=false styling); async timer edge cases under network throttle; cross-document announcer (createAnnouncer in iframe/shadow DOM)