You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/audit/components/search-field.md

47 lines
4.3 KiB

# Audit: search-field
audit-version: 1
audited-at: 2026-06-26
scope:
method: adversarially-verified workflow (analyze → refute); HIGH/CRITICAL lead-verified. Clean-check pseudo-findings dropped. B4 ground-truth: segmented date/time/color-field register inputId via $effect (SYS-A30-EFFECT, no loop); number-field is the direct-assignment reference.
provider: src/uix/soma/components/search-field/search-field-provider.svelte.ts
field-family (A13/A24-26/A30): search-field IS field-composable (calls FieldProvider.get(), registers inputId at line 105 via direct assignment, NOT $effect—A30 correct). Does NOT declare hidden input (A13 not applicable—not form-participating). Does not emit segmented contenteditable (A26 not applicable). Does not read readonlySegments (A24/A25 not applicable). Field composition integration is clean: aria-labelledby/aria-descr
## Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 0.
## Findings
### MEDIUM: SYS-1 scope-drift — eidos recipe/CSS dir exists but morfo 'scope' omits 'eidos' — SF-SYS1-scope-drift <!-- id: SF-SYS1-scope-drift -->
- dimension: A
- rule: SYS-1 scope-drift — eidos recipe/CSS dir exists but morfo 'scope' omits 'eidos'
- location: src/uix/morfo/components/search-field.ts:7
- evidence: `scope: ['soma', 'sema']` — yet a full eidos surface exists: a recipe block `'search-field': { ... }` at src/uix/eidos/lib/recipes/base.ts:2045 and a complete component dir src/uix/eidos/components/search-field/ (search-field.css, types.ts, search-field.svelte, plus icon/input/clear-trigger/loading-indicator wrappers).
- impact: The morfo's declared scope under-reports the layers that consume the contract. Any tooling that keys off `scope` (lint coverage, layer maps) will skip eidos for search-field even though eidos CSS selects against the morfo-emitted data-attrs (data-search-field, data-search-field-input, data-disabled/empty/focused, etc.).
- proposed-fix: Add 'eidos' to the morfo `scope` array: `scope: ['soma', 'sema', 'eidos']`.
- verify: [verifier-added] added by adversarial verify pass
- fix-status: open
### MEDIUM: Test coverage of a high-risk path — debounced onValueChange has no test — SF-F-debounce-untested <!-- id: SF-F-debounce-untested -->
- dimension: F
- rule: Test coverage of a high-risk path — debounced onValueChange has no test
- location: src/uix/soma/components/search-field/search-field-provider.svelte.test.ts:60
- evidence: The fixture sets `debounceMs: state(0)` and never exercises `debounceMs > 0`. The debounce branch in `commit()` (provider lines 176-196: schedules `this.soma.uix.timers.schedule(...)`, replaces pending timers, fires only the latest value), plus `flushDebounce()` on submit (lines 128-137) and `cancelDebounce()` on clear/unmount (lines 119-125, 108-110), are entirely uncovered. The test stubs `soma` as a partial object with no `uix.timers`, so a debounced path would not even resolve a timer service.
- impact: The most behaviorally subtle logic in this provider (debounce coalescing, flush-before-submit ordering so onSubmit sees the latest value, cancel-on-clear, cancel-on-unmount A6) is unverified. A regression in timer keying/replace or flush ordering would ship silently.
- proposed-fix: Add a test with debounceMs>0 driving the provider through a real `uix.timers` (via createActiveUix/attachActiveUix harness): assert onValueChange fires once with the latest value after the delay, that submit flushes the pending value before onSubmit, and that clear cancels the pending callback.
- verify: [verifier-added] added by adversarial verify pass
- fix-status: open
## No-findings dimensions
A, B, C, D, E, E-bis, F, G
## Theming facts (E-bis)
- magic z-index: none
- magic literals: line-height: 1 at search-field.css:189 (icon alignment; systemic pattern across all icons, not search-field-specific)
- undeclared parts: none
- roles clean: true · variants clean: true
- label-font (one step below input?): N/A — search-field composes Field; Field renders the label. No direct label in search-field recipe.
## Tests (F)
- exists: true · env: @vitest-environment jsdom
- covers: root state attrs projection; focus/blur state tracking; input commit and value change; submit on Enter; clear on Escape and click; debounce behavior; Field composition (OR-merge of flags, labelId integration)
- untested:

Powered by TurnKey Linux.