Skip to content

Mike/verification one shot#16

Draft
smartymanwill wants to merge 8 commits into
masterfrom
mike/verification-one-shot
Draft

Mike/verification one shot#16
smartymanwill wants to merge 8 commits into
masterfrom
mike/verification-one-shot

Conversation

@smartymanwill

Copy link
Copy Markdown
Collaborator

No description provided.

Mike added 8 commits June 11, 2026 11:41
Adds the additive verification subsystem alongside autocomplete (PRD §8, ERD
§1–§5, §7, §8):

- Types: VerificationConfig/Result/Error/Decision, CurrentAddress, AddressDiff,
  DeliverabilityCode, enums (interfaces.ts)
- VerificationService: US Street fetch, classify (Types 1–5,7,8), behavior
  dispatch, in-memory dedupe (kills selection→blur double-call), invalidate-on-
  edit staleness
- VerificationUiService: badge + aria-only surfaces, themed via CSS variables
- VerificationOrchestrator: wires selection/blur/staleness triggers
- streetTransport: shared auth/fetch/error helper (no shared base)
- CurrentAddress abstraction + adapters; FormService correction round-trip
- De-skew (Q5): nested autocomplete block + root-key aliases, additive
- validateConfig: neither-mode warning + per-release capability guards
- defaultVerificationConfig: one-line-changeable provisional defaults (§6)
- Public smartyAddress.verify(); mode resolution in index.ts

Internal tests: classify table, dedupe, staleness, dispatch, UI surfaces,
config de-skew + validation (45 tests). All 276 tests green.
- VerificationUiService: full inline panel surface + lightweight ambiguous
  chooser (verification-only fallback, Q4 / ERD §8.1)
- dispatch routes ambiguous+prompt to the chooser; first-candidate auto-picks;
  a customer onCorrectionOffered decision overrides the built-in UI (ERD §7)
- validateConfig: panel + onResult.ambiguous guards lifted
- panel/chooser theme CSS (all values via verify* CSS variables)

Tests: panel render, chooser selection/dismiss, first-candidate override,
hook-overrides-chooser. All 282 green.
- Await-able verifyBeforeSubmit() on SmartyAddress + VerificationService — the
  supported cross-framework blocking path (ERD §6)
- block override on Type 7 (undeliverable→block) + fail-closed routing through
  the submit decision
- onBeforeSubmit hook gets the final say (false blocks)
- Best-effort native <form> interception in the orchestrator when the submit
  trigger is configured; SPA/non-form hosts use the await-able method
- validateConfig: block guard lifted

Tests: verified→allow, undeliverable-block→block, default warn→allow,
fail-closed error→block, hook-forced block. All 286 green.
- classifyInternational (ERD §5.4): verification_status + address_precision +
  per-component changes → the same VerificationResultKey outputs as US
- Q10 per-country max precision: compares address_precision to the per-response
  max_address_precision; falls back to a Premise minimum when absent
- Type 5 (flagged) never fires internationally (USPS-specific)
- fetchInternational against the International Street API; detail-first ordering
  satisfied by the autocomplete flow populating full components before verify
- internationalEnabled() gate flipped on

Existing autocomplete intl-flow integration tests scoped to verification:{enabled:false}
(they assert autocomplete fetch counts; the provisional verification default
would otherwise add the documented Street API call on selection).

Tests: full intl classify table, Q10 boundary (3 cases), 'flagged can't fire
intl', intl verify end-to-end. All 299 green.
- Playwright harness (acceptance/) driving the built IIFE bundle in real
  Chromium with an in-page fetch mock; 8 representative matrix cells across
  Epics 1–4 (verified/corrected/undeliverable/block/ambiguous/staleness/error/
  international) — all green
- acceptance/README.md: the representative matrix + intentionally-untested
  combinations (Q11–Q13, no silent gaps); hosted-vs-local decision (Q12)
- playwright.config.ts + npm run test:acceptance; CI runs it after build
- jest ignores acceptance/; Playwright artifacts gitignored
- epic-0-discovery-status.md: Q1–Q13 dispositions, API-lock + exit-criteria
  status, enabled-default/billing deferred to Epic 5

The ERD (already in-repo) is the locked spike output / API contract.
Review of the verification branch (epics 0-4) against the PRD/ERD/release
structure surfaced six confirmed bugs and several spec deviations. Fixes:

Bugs:
- Submit racing an in-flight verify no longer falls through to a stale/null
  result: runFlow shares the in-flight fetch+classify promise with concurrent
  same-address triggers, so verifyBeforeSubmit awaits the real result and
  `block` actually blocks. Dedupe hits return the prior result (ERD 5.1).
- `prompt` no longer applies the correction before the decision: onCorrectionOffered
  runs first, so `reject` leaves the entered address untouched; type 4 keeps the
  user's entered unit instead of overwriting it (PRD 7 row 4).
- staleness:"revalidate" implemented (debounced re-verify on edit; ERD 5.6 Q9).
- Merged street+unit fields now dedupe correctly (boundary-collapsing fingerprint),
  and chooser/first-candidate/hook applies are fingerprint-recorded so the
  follow-up blur doesn't re-bill. Single-field forms' blur trigger works.
- `block` attaches native interception even without the explicit submit trigger
  (ERD 6); resubmitting-flag leak fixed.
- Native re-submit-on-pass deferred a macrotask: a fast verify resolved mid-
  submit-dispatch and the nested requestSubmit was silently dropped by the
  browser (invisible to mocked unit tests; caught by the new acceptance cell).

Spec deviations:
- intl `ambiguous` keys only on verification_status; intl `corrected` only on
  qualifying changes (no `|| diff` bypassing the Q10 precision gate, which now
  logs the missing-max_address_precision fallback).
- nonBlocking reflects the actual gate decision for type-7-with-block.
- `ignore` renders nothing; `first-candidate` shows the auto-pick as a correction
  (never a silent "choose one"); chooser respects aria-only/none.
- ERD 3.1 allowed-overrides enforced (validateConfig warns; dispatcher drops
  e.g. verified:"block"). verifiedAt set/cleared.
- Theming: verify CSS variables moved to base.ts with dark/light overrides in
  colors.ts; surfaces carry the configured theme classes; raw values in theme.ts
  replaced with variables; unused panel-button classes removed.

Tests/docs:
- New VerificationOrchestrator.test.ts covers selection wiring, native
  interception (incl. stuck-flag + submit-race), both staleness modes, single-
  field blur. New acceptance cells: native interception + country-switch mid-flow;
  fetch mock now fails on unmocked endpoints (no silent endpoint-routing pass).
- acceptance/README.md names previously-silent matrix gaps; epic-0-discovery-status.md
  no longer overclaims (Q1-Q3, Q11 marked deferred/not-expanded).
- design/ added to .prettierignore (reference prototypes, not shippable);
  tracked spec docs prettier-normalized so CI's prettier --check passes.
- Drop section-banner and "what" comments; keep spec-anchored "why" notes
- Name US Street candidate cap (US_STREET_CANDIDATE_LIMIT)
- Register VerificationOrchestrator in the services map so it is override-able
  like the other services
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant