Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
# OpenSpec Change: form-detection
- **Change ID**: form-detection
- **Package**: `@suaveplan/form-detection`
- **Status**: PROPOSED
- **Date**: 2026-04-29
## Summary
Create `@suaveplan/form-detection`, a tree-shakeable DOM heuristics engine that detects login, registration, and password-change forms in web pages with confidence scoring. The package targets browser extension content scripts and is designed to run at ~10KB bundled with zero external dependencies.
## Why
Password-manager browser extensions require reliable autofill injection, but no good standalone open-source library exists for form detection. Competitors (1Password, Bitwarden) keep this logic proprietary. Building a first-party heuristic engine lets Vaulted tune scoring for its own field types and avoids shipping a heavy external dependency inside content scripts.
## What changes
- ADDED: `detectForms(document)` — returns an array of `FormCandidate` objects with `type`, `confidence`, and `fields` properties.
- ADDED: `classifyField(element)` — classifies a single `<input>` or `<textarea>` into `username`, `password`, `new-password`, `email`, `otp`, `credit-card`, or `unknown`.
- ADDED: `extractLabel(field)` — extracts the human-readable label from associated `<label>`, `aria-label`, `placeholder`, `name`, or surrounding text heuristics.
- ADDED: `scoreConfidence(candidate)` — computes a 0.0–1.0 confidence score based on field composition, label keywords, and structural signals.
- ADDED: `FormObserver` — `MutationObserver`-based wrapper that re-evaluates forms as the DOM changes, with debouncing and configurable `root` / `threshold`.
- ADDED: `FormCandidate`, `FieldClassification`, `LabelSource` — named types for cross-package reuse in `@suaveplan/types` if referenced by ≥2 packages.
- ADDED: `FormDetectionError` — typed error hierarchy (`Timeout`, `NoDocument`, `InvalidField`) with error codes.
## Out of scope
- iframe traversal across origins — content-script CSP and cross-origin policy prevent this; only same-origin iframes are considered.
- CAPTCHA solving or bot-detection bypass — strictly form detection, not interaction automation.
- Shadow-DOM piercing beyond open shadow roots — closed shadow roots are intentionally opaque.
- Visual rendering or CSS-based detection — purely semantic/DOM heuristics, no canvas or computed-style analysis.
- Internationalized keyword expansion beyond the bundled set — future change can add lazy-loaded locale packs.
## Gap analysis: sub-standard → enterprise
Most autofill heuristics rely on brittle regex matching against raw HTML, break under shadow DOM, and ignore dynamically injected content. They lack confidence scoring, forcing integrators to accept or reject candidates blindly. Enterprise deployments need a robust engine that scores every candidate, observes DOM mutations without freezing the main thread, ships tree-shakeable by feature, and stays within a < 16 ms budget to avoid jank. This proposal replaces regex soup with a structured heuristic pipeline, `MutationObserver`-based re-evaluation, and explicit performance budgets.
## Security model
- **Threat model**: Hostile pages may craft deceptive DOM structures to misclassify fields, trick autofill injection, or probe the extension via timing side channels.
- **Encryption boundaries**: N/A — this is a pure DOM-heuristics package with no network transport.
- **Input validation**: Zod schemas validate all exported function inputs (`document`, `Element`, options). Invalid inputs throw `FormDetectionError` with a stable error code.
- **Side-channel resistance**: Detection batches scoring to avoid per-element timing observable from the host page; no early-exit shortcuts that leak form structure.
- **Key zeroization**: N/A — no cryptographic material is handled.
- **Privacy guarantees**: Field values are never logged, never captured in telemetry, and never leave the content-script context. Only structural metadata (tag name, confidence score, field count) may be emitted for diagnostics.
- **Browser extension threats**:
- **Hostile page XSS probes**: The package never executes page scripts; all DOM reads are passive queries.
- **CSP `unsafe-inline` restrictions**: The package runs as a content script injected by the extension manifest, not as inline JavaScript, and is therefore not blocked by CSP `unsafe-inline` policies.
- **Same-origin iframe inclusion with cross-origin exclusion**: The traversal descends into same-origin `<iframe>` documents and includes their forms; cross-origin iframes are excluded by the same-origin policy.
- **Open shadow-root descent with closed shadow-root rejection**: The package descends into open shadow roots to discover fields; closed shadow roots are treated as opaque boundaries and are not pierced.
## Performance SLOs
- **Detection latency**: < 16 ms p99 for pages with < 500 input elements.
- **Observer callback latency**: < 4 ms p99 per mutation batch.
- **Memory**: < 1 MB heap for observer and candidate state on typical pages.
- **Bundle size**: core detection < 5 KB gzipped; full observer + detection < 10 KB gzipped; 100 % tree-shakeable by submodule.
- **Frame rates / layout thrashing**: No forced synchronous layout. DOM reads are batched inside `requestAnimationFrame`; writes are avoided entirely.
- **Throughput**: Mutation-driven re-evaluation debounced at 100 ms; capped at 10 batches/sec.
## Observability plan
- **OTel spans**: `form_detection.detect`, `form_detection.classify`, `form_detection.observer.batch`.
- **Metrics**: detection count by form type, average confidence score, observer mutation batch size histogram, sampled false-negative rate (opt-in feedback channel only).
- **Structured logging**: JSON inside content-script context; never includes field values, URLs, or DOM snapshots.
- **Error telemetry**: `NoDocument` and `InvalidField` rates captured with scrubbed stack traces.
- **Health checks**: `FormObserver` exposes `isConnected()` and `flush()` for runtime diagnostics and graceful teardown.
## Dependency audit
- **Zero runtime dependencies** (enforced by `tests/dep-graph.test.ts`).
- Build-time only: TypeScript, biome, test runner.
- **Supply-chain risk**: Minimal — no third-party runtime packages to compromise.
- **Tree-shakeability**: Every exported submodule is independently tree-shakeable.
- **License**: MIT (project standard).
## Operational readiness
- **Graceful degradation**: If DOM access is restricted (e.g., sandboxed iframe), `detectForms` returns an empty array with `confidence: 0` rather than throwing.
- **Resource limits**: Max 1 000 elements scanned per detection pass; `FormObserver` caps the mutation record buffer at 500 records before forced flush.
- **Error recovery**: Observer automatically re-attaches on SPA navigation via `pageshow` / `visibilitychange` listeners.
- **Backpressure**: Mutation batches are debounced at 100 ms; intermediate states are dropped and only the latest DOM snapshot is evaluated.
- **Version compatibility**: Semantic API versioning; `detectForms` and `classifyField` signatures remain stable across minor versions.
## Verification approach
- `src/detect/detect.test.ts` — covers login, registration, password-change, and checkout form discovery in synthetic DOM trees.
- `src/classify/classify.test.ts` — covers field classification for all supported types and ambiguous edge cases.
- `src/label/label.test.ts` — covers label extraction from `<label for>`, `aria-label`, `aria-labelledby`, `placeholder`, and fallback text heuristics.
- `src/score/score.test.ts` — covers confidence scoring monotonicity, boundary values, and signal aggregation.
- `src/observer/observer.test.ts` — covers mutation debouncing, childList vs attribute mutations, and disconnect lifecycle.
- `src/error/error.test.ts` — covers error code uniqueness, `instanceof` branches, and serialization round-trip.
- `src/spec-conformance.test.ts` — pins tree-shakeability invariant, no-external-deps invariant, and sibling-doc presence.
- `tests/dep-graph.test.ts` — pins dependency invariants (zero runtime dependencies).
- **100 % coverage target** for all non-test source files.
- **Property-based tests** (`fast-check`): random DOM trees preserve classification invariants; confidence monotonicity under field addition; label extraction idempotence.
- **Load / stress criteria**: 10 000-element DOM detected in < 16 ms; observer stress with 1 000 mutations/sec for 60 s without memory growth.
- **Security audit checklist**: verify no field values in logs or telemetry; verify no external network requests; DOM-injection fuzzing confirms classification stability under adversarial input.
## Migration impact
None — additive only.
## Impact
### Affected dependents
No dependents (verified by `bunx turbo ls --filter=...@suaveplan/form-detection`).