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.
4.2 KiB
4.2 KiB
Audit: link-preview
audit-version: 1 audited-at: 2026-06-26 scope: ['soma'] (SCOPE-DRIFT → SYS-1) method: adversarially-verified workflow (analyze → refute); HIGH/CRITICAL personally re-verified against cited code by the lead. provider: src/uix/soma/components/link-preview/link-preview-provider.svelte.ts
Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 0. systemic hits: SYS-1 (scope-drift: eidos exists but not declared in morfo scope); SYS-2 (magic literals in CSS: 1px, 0.18em, 4px, 0.985 scale).
Findings
MEDIUM: SYS-1 — link-preview-001
- dimension: A
- rule: SYS-1
- location: src/uix/morfo/components/link-preview.ts:7
- evidence: scope: ['soma'] declared in morfo, but eidos recipe dir exists at src/uix/eidos/components/link-preview/ with 7 files (index.ts, link-preview.svelte, link-preview-content.svelte, link-preview-trigger.svelte, link-preview-arrow.svelte, link-preview.css, types.ts)
- impact: Morfo scope omits 'eidos' while eidos recipe and components exist; creates maintenance confusion and violates the documented scope contract.
- repro: grep -r "src/uix/eidos/components/link-preview" to confirm files exist; check morfo scope at src/uix/morfo/components/link-preview.ts:7
- proposed-fix: Either (a) add 'eidos' to morfo scope:
scope: ['soma', 'eidos'], or (b) if eidos is intentional internal structure, document why scope is intentionally ['soma'] only and mark eidos as internal pattern. - verify: [confirmed] Confirmed SYS-1 scope-drift. morfo line 7:
scope: ['soma'],while a full eidos recipe dir exists: ls src/uix/eidos/components/link-preview/ shows index.ts, link-preview.svelte, link-preview-content.svelte, link-preview-trigger.svelte, link-preview-arrow.svelte, link-preview.css, types.ts. morfo/types.ts:799 documentsscopeas 'Layers that implement this component. Eidos-only primitives may declare ["eidos"].' Peer overlays correctly list eidos: dropdown-menu.ts:11scope: ['soma', 'sema', 'eidos'], tooltip.ts:14scope: ['soma', 'eidos', 'sema']. link-preview omits 'eidos' despite shipping a recipe. MEDIUM is right per batch-1 SYS-1 baseline. - fix-status: open
No-findings dimensions
B, C, D, F, G
Theming facts (E-bis)
- magic z-index: z-index is tokenized via --popover-content-z (canonical preset)
- magic literals: text-decoration-thickness: 1px (should use --border-width or clarify as exempt) | text-underline-offset: 0.18em (should use --tracking-* or clarify as exempt) | opacity: 0 in keyframes (acceptable as terminal state) | scale(0.985) and 4px offsets in keyframes (should be tokenized or documented)
- undeclared parts: none
- roles clean: true · variants clean: true
- conformance: link-preview uses only primary role (canonical); no invented roles or sizes; size variants xs|sm|md|lg|xl conform to E-bis subset.
Tests (F)
- exists: true · env: jsdom
- covers: open/close timers with configurable delays (openDelay/closeDelay); touch pointer ignored (only mouse/pen); disabled flag blocks open; SafePolygon pointer bridge (content hover prevents close); dismissal via Escape key and outside-click; floating content/arrow props exposure; data-state transitions
- untested: keyboard Escape key (mentioned in README but not explicitly tested in jsdom); focus return to trigger on close (A17 not exercised); content visibility presence transitions (Presence API self-cleanup verified at code level); client/Playwright integration tests (jsdom-only; no browser interaction test)
Style observations (non-blocking)
- LinkPreview correctly uses trigger as navigational (not button), which is documented and intentional per APG guidance for hover-card discovery.
- aria-hidden=true on content is explicit design choice to hide preview from AT; justified by README study §2.3 (duplicate content, hover-only activation, focus stays on trigger).
- SafePolygon bridge with touch guard (pointer type check) is well-implemented to preserve preview on pointer transitions.
- Color tokens use primary role only; fallback to --color-content-primary is defensive.
- Animation preset (4 directional in/out keyframes) matches floating-ui positioning strategy; naming data-side correlates CSS state to floating placement.