# N-400 QA coverage (Keystone Citizen private QA)

## Official source / edition
- **USCIS page:** https://www.uscis.gov/n-400
- **Edition date listed by USCIS:** `01/20/25` (mm/dd/yy)
- **Local blank used for QA fill:** `/qa/n400/n-400-blank-ed-01-20-25.pdf` (derived from official form; encryption/XFA stripped for AcroForm fill; **14 pages**; edition string retained on page 1)
- Re-checked uscis.gov/n-400 on 2026-11-05 ~10:20 PM ET: edition date still 01/20/25 (page last updated 06/16/2026). Re-check uscis.gov before any paid launch if USCIS publishes a newer edition.

## Architecture (this iteration)
- Browser-only guided intake → review → `pdf-lib` fill → download.
- Answers held in **JavaScript memory only** (not localStorage, not KV, not URLs, not chat/AI).
- Locale preference for QA UI chrome may use `kc_n400_qa_locale` (locale code only).
- Blank PDF bytes served from Worker/KV asset binding; **no answer payloads stored server-side**.

## Correctness batch (2026-11-05, after independent review)
- Shared engine `lib/n400-core.js` used by both the browser and `tests/core-regression.mjs` (saved-output + reload assertions).
- Checkboxes are chosen by the official on-state; the other boxes in the group are unchecked. Every option of every schema choice was tested.
- **Nothing is cut or dropped silently.** Required blanks, invalid dates, values that don't fit an official box (max length / width), dropdown values not offered by the form, characters the font can't show, and internal mapping errors all **block** the PDF and name the field.
- Phone/A-Number/SSN formatting is normalized only when every digit is kept. ZIP+4 is not cut to 5 digits; it blocks with an explanation.
- Unicode appearances use self-hosted Noto Sans (OFL); no transliteration.
- Part 9 is shown in official item order; the accessibility suffixes "Select Yes/No" have been removed from labels. No answer-dependent legal rules were added.
- Every page carries a DRAFT / INCOMPLETE / SYNTHETIC header + diagonal watermark + edition + unanswered/worksheet counts. The form is not rasterized; 14 pages are kept.
- Self-hosted pdf-lib 1.17.1 + fontkit 1.1.1 (MIT); strict CSP on /qa/n400 (`connect-src 'self'`, no third-party scripts or fonts).

## Batch 2 (2026-11-05): history rows + Part 14 continuation
- Item references now follow the 01/20/25 page text: Part 3 Biographic, Part 4 Residence, Part 5 Marital, Part 6 Children, Part 7 Employment, Part 8 Travel, Part 11 contact. The earlier schema had older-edition Part numbers.
- History rows can be added or removed: addresses up to 20, employment up to 20, trips up to 60 (these caps are shown in the UI). Answers beyond a cap are a named block, never dropped silently.
- The official table rows are filled first (3 addresses, 3 employment rows, 6 trips; layout verified by rendering).
- Extra rows, plus trip "countries" text too long for the 55-character box, go to **Part 14**. The official Part 14 page (Items 2-5: Page/Part/Item + text, name line) is filled first, then appended continuation sheets.
  - Each continuation sheet carries: name + A-Number (only if provided), Page/Part/Item per entry, full wrapped text, "(continued)" when an entry runs onto the next sheet, a blank signature/date line (the instructions say to sign and date each sheet; never filled), "Continuation sheet i of K - PDF page N of M", and the DRAFT banner + watermark.
  - When the countries box overflows, it gets "See Part 14. Additional Information" and the full answer goes to Part 14.
- Names, addresses, ZIP, IDs, email and phone never continue; they still block with a named reason. Invalid dates, reversed date pairs, unsupported glyphs and mapping bugs still block.
- The original 14 pages keep their geometry and barcode fields; continuation pages are appended after them.
- Review runs the same preflight as PDF generation. A stale "ready" state is cleared on any change, retry or error.
- The worksheet lists every value, including added rows.
- Unverified: whether USCIS accepts the appended sheets / this derived PDF; Acrobat rendering; scripted barcodes. The "See Part 14" pointer in the countries box is a convention, not a quoted instruction.

## Batch 3 (local, not deployed): Part 9 explanations, other names, nationalities, children, multi-race
- Part 9 references re-derived from 01/20/25 layout (items 17.a-37 corrected; added 26.c, 26.d, 34; stray Part 10 item removed; old-edition tooltip text removed).
- Each Part 9 Yes/No has an optional explanation box. Text goes to Part 14 as "Page N, Part 9, Item X". A non-blocking review note appears ONLY where the official form says to explain a Yes (Items 1-14, 17.a-19, 20-21, 23-24, 27-29, 30.a). No blanket rule; no answer chosen; never blocks.
- Other names: 2 native rows (Page 1 Part 2 Item 2), up to 10; extras -> Part 14 with that reference.
- Nationality: native box unchanged; up to 10 additional nationalities -> Part 14 (Page 2 Part 2 Item 9), as the form instructs.
- Children (Part 6 Item 2, children under 18): 3 native rows with the official columns (name, DOB, residence, relationship, support Y/N); official option wording only; blanks stay blank/Off; >3 children -> Part 14; address for a child not residing with you -> Part 14 (review note if missing). DOB 18+ years ago -> review note only.
- Race: multi-select of the 5 official boxes (exact indexed widgets; Asian and NHPI share on-value /A). Required; blank, unknown or duplicate values block.
- Header now states what is actually not filled; Part 14 is used; Parts 15-16 reserved for interview.

## Batch 4 (STAGED ONLY, not deployed; live build is etag 790b6959)
- Part 9 Item 15 table (Page 8): 5 printed rows (not 3) with the official columns: crime/offense, date, conviction date, place, result/disposition, sentence. Up to 20 rows; rows 6+ go to Part 14 "Page 8, Part 9, Item 15" with every value. Long crime/place/result/sentence text that cannot fit a native box at a readable size (7pt min) goes to Part 14 in full, with a pointer in the box. Translated add/remove confirmation.
- Item 22.c: Selective Service registration date + number (native boxes). Item 30.b: titles of nobility text (native box; overflow to Part 14 Page 10 Item 30.b).
- Item 7.b: **live-build defect fixed in staging**: its official field name contains escaped dots, so the answer was worksheet-only. It now fills the printed Yes/No (verified box positions).
- Part 5 re-derived from the printed blank: 2 armed forces, 3 times married, 4.a-c, 4.d same address (No -> address to Part 14 Page 4 Item 4.d; review note if blank), 5.a by birth/other, 5.b date, 6 A-Number, 7 spouse times married, 8 employer. **Live-build defects fixed in staging**: "spouse is U.S. citizen" was written into the 4.d boxes, and the employer was written into the Item 7 count box.
- The 01/20/25 form has **no prior-marriage detail table**, so none is collected. Parents: only Part 2 Item 10 (parent U.S. citizen Y/N) is native; it is mapped. Military: only the Part 5 Item 2 and Part 9 Items 25-29 Yes/No. The old worksheet-only parents/military/prior-marriage sections were removed, not moved.
- Part 14 placement: the fit check now uses the real rendered line height. The live build could clip the last line of a 5-line entry inside a 72pt official slot (**live-build defect**). Each entry now takes the first free slot tall enough, otherwise it goes to an appended sheet.
- Header "NOT FILLED" line updated.

## Batch 5 (verified candidate cfba5670; staged/local — live generation still paused)
- Part 4 current physical address maps to the current block (not the previous-address table); To stays printed PRESENT (no end-date box).
- Previous-address rows 2-4 map to the 3 printed table rows; rows 5+ go to Part 14. Continuation titles use **previous address #k** (k = row−1), not “Physical address row N”.
- Part 4 Item 2 (same mailing?) and Item 3 mailing address, foreign province/postal/country boxes, unit type/number, Part 2 Item 3 middle name, and Item 12.c SSA consent are mapped. Answers are never copied or inferred across fields.
- Address-history date chronology: within-row end-before-start still blocks; adjacent-row overlap / gap / reversed-start notes warn only and keep typed values. Gap uses inclusive UTC calendar days (same-day or next-day abut = no gap; a missing calendar day triggers the note). Order notes use From dates only and do not require a complete older To.
- Independent mapping audit (212 option runs) + scoped browser/final-output QA completed against this candidate; see `/workspace/n400-independent-map-audit/b5/`.


## Photo document intake integration (staged candidate only — DEFAULT OFF)
- Optional docs mount from copied `vendor-document-intake-v0.1.2` (source Keystone v0.1.2; original tree unmodified).
- Feature flag: `features.json` `photoDocumentIntake: false` by default; local enable `?photoIntake=1` (or `docsIntake=1`). Flag off: no module fetch/mount; core/UI baseline unchanged.
- Bridge `lib/n400-photo-bridge.mjs`: allowlisted identity/contact text keys only; explicit confirm; stale-conflict detection; fail-closed on fee/interp/prep/elig/signatures/unknown. Runtime extraction **unavailable** (honest notice). Synthetic extract fixtures are test-only.
- Erase session / destroy revokes object URLs; no document bytes/filenames in localStorage/IDB.
- **Not** browser-verified in this candidate; NOT filing-ready; no OCR/backend/network; no accounts/uploads/deploy.

## Batch C1.1 (emit-gating fix; staged only — not deployed)
- Closed/blank gates no longer print retained branch details on the official PDF: fee Items 2–5.b only if `fee_reduce===Y` (and 5.b name only if `fee_hh_head===N`); `interp_*` only if `used_interpreter===Y`; `prep_*` only if `used_preparer===Y`.
- Typed closed-branch answers stay in session/worksheet marked `[entered — not applied to official PDF]` with nonblocking EN/ES review notes (`w_*_contradict` / `w_*_pending` / `w_fee_5b_not_applied`).
- Soft `w_office_elig_review` when an office is chosen and eligibility is not D (319(b)); no auto-change of eligibility.
- C1 baseline + independent audit left immutable; B6.1/B5 untouched.

## Batch C1 (self-prep completeness candidate; staged only — not deployed; live generation paused)
- Part 10 fee-reduction Items 1–5.b map from explicit answers to page-11 widgets (`P10_Line1_Citizen` Yes/No, income, household size, earners count via misnamed `P11_Line1_TotalChildren[1]`, head-of-household Yes/No + name). No eligibility decision; evidence listed as review note only (no upload).
- Conditional Part 12 / Part 13 **contact** fields map when the applicant explicitly reports an interpreter/preparer; signature/date widgets stay blank. Spanish UI / AI chat are not auto-treated as interpreter/preparer.
- Part 1 field-office dropdown (`DropDownList1[0]`) mapped with exact official PDF options (optional; 319(b) instruction cited in help). Not selected for the user.
- DRAFT/INCOMPLETE/SYNTHETIC banners retained. No filing-ready claim.

## Still NOT done / incomplete
- Wet-ink signatures/dates: Part 11 applicant, Part 12 interpreter, Part 13 preparer, Part 14 continuation sheets (Instructions: stamped/typewritten name not acceptable).
- Part 10 reduced-fee **evidence uploads** not collected/attached (Instructions list required documents; accounts/uploads decision pending separately).
- Fee payment / fee-waiver filing choices (G-1055) not collected.
- Parts 15–16 interview-only (Instructions: do not complete until USCIS officer instructs).
- Legal/privacy review, live payments, barcode/Acrobat/USCIS acceptance remain open.
## Mapping status (01/20/25 part numbers) — B5
| Area | Auto PDF | Notes |
|---|---|---|
| Part 1 eligibility | Yes | Field office dropdown mapped (optional official options) |
| Part 2 identity | Yes | Other names 2 native + Part 14; Item 3 middle name; Item 12.c consent mapped (user choice only) |
| Part 3 biographic | Yes | Race multi-select |
| Part 4 residence | Mostly | Current + 3 previous native; extras -> Part 14; Item 2/3 + foreign boxes mapped; chronology notes |
| Part 5 marital | Yes | Items 1-8; form has no prior-marriage table |
| Part 6 children | Yes | Rows 1-3; extras -> Part 14 |
| Part 7 employment / Part 8 travel | Yes | Native rows + Part 14 extras |
| Part 9 (Yes/No + 15 table, 22.c, 30.b) | Yes | Explanations -> Part 14 |
| Part 10 fee reduction | Yes (answers) | Items 1–5.b mapped; evidence uploads not handled; no eligibility decision |
| Part 11 contact | Partial | Phone/mobile/email mapped; signature/date never filled — incomplete, not entirely blank |
| Part 12 / 13 contact | Conditional | Name/org/phone/email/language from explicit report; signatures never filled |
| Part 11/12/13 signatures; Parts 15-16 | Never | Wet-ink / interview only |

## Paid-launch blockers (checklist)
- [ ] Attorney / UPL disclaimer review
- [ ] Live Stripe + entitlement (not this QA)
- [ ] Auth, encryption-at-rest, deletion if any server storage introduced
- [ ] Re-verify PDF edition vs USCIS
- [ ] Expand mapping for worksheet-only sections if claiming “complete prep”
- [ ] Acrobat visual QA on every page / NeedAppearances quirks
- [ ] Remove synthetic-only banners only when productized intentionally
- [ ] Public site still draft/noindex/orders off until separately authorized

## Synthetic fixture
- `fixtures/synthetic-sample-DRAFT.pdf` — smoke fill of a few fields + DRAFT banner (not a full intake).

## Localization (EN/ES), batch 3
- Guided screens, section titles and notes, all field labels and help (816 rendered fields with every row at its maximum), choice options, review statuses, Review/Generate issue and review-note text, Part 14 "moved" lines, row controls and the known-unsupported list come from dictionaries: `locales/en.json`, `locales/es.json` (89 keys, parity), `locales/schema.es.json`.
- Core issues carry `code` and `params`; the UI renders `issue.<code>`. English `msg` stays as the fallback and the canonical text.
- Spanish is a plain, literal display translation for this QA tool. It is not certified and not a legal interpretation. Official numbers are kept (Part/Item, for example "Parte 4, Punto 1"; Part 9 item numbers).
- The official PDF, the Part 14 sheets and the HTML worksheet stay in canonical English. Answers are never translated or normalized.
- Checks: `tests/l10n-coverage.mjs` (static, 2838 assertions) and the headless phone-width UI run at `/workspace/n400-fix/ui/ui-test.mjs` (ES+EN at 360px, no missing strings, no overflow, no external requests).
