# P7-07 — Documents interface **Status: implemented-scope CONDITIONAL GO; affected frontend and native 13/13 pass, all 18 final images are reviewed, hygiene passes and Documents publication is verified.** Separate P7-08 presentation work remains uncommitted; no clean-checkout or full-phase acceptance is implied. This is the second boundary in the [approved handoff](../../phase-6/p6-05/PHASE7_HANDOFF.md#migration-order-and-commit-boundaries), following the [metadata contract](CONTRACT.md). It reuses existing resource owners and the Phase 4–6 design system. ## Entry and bounded scope The metadata contract was committed and normally pushed as `8e4db121ae0ec3f1637c83ddeaa3f31abd0a61be`. Direct remote verification at **2026-10-14T16:02:14.215615 UTC** recorded clean HEAD = origin = live development. Local/origin/live main remained `27657f31131cd95d42f0e1290853ec9c9b3959a4`. Its exact receipt is retained at `.artifacts/phase7/p7-07/contract-push-receipt.json`; the portable contract results record that successor observation. On **2026-10-16**, a fresh fetch confirmed development HEAD/origin still `8e4db12`, with only the untracked null-return `DocumentsPage.tsx` scaffold. No execution or product changes are inferred during the pause. Existing focused frontend regression runs precede implementation. The authoritative last full frontend run remains 573/89; the derived inventory before this interface is frontend739/94, browser304, backend1053. These are inventories, not new full-suite passing counts. Fetches at **15:52 and 15:55 UTC** fail because the configured remote host on port 443 is unreachable. The third fetch, **16:12:35.608743–16:12:56.824123**, exits **128** for the same connection failure; `remote-retry-20261016-1613/fetch-command.json` and `fetch.log` retain it. Remote verification is pending at those observations. The later verified recovery below supplies a separate dated receipt; cached refs are not substituted for it. The authenticated `/documents` page sits under Career, with a new entry in the existing command palette and paired English/Bokmål labels. The approved index adds one route, bringing the inventory to **33 while preserving the original 32**. It uses the existing shell heading, semantic sections, table/mobile-card patterns, shared theme tokens and feedback infrastructure. No new renderer, editor, generic Document store, account upload bucket, mail persistence or dependency is introduced. Changed product files are `views/DocumentsPage.tsx`, `App.tsx`, `components/QuickCommandDialog.tsx` and `i18n/translations.ts`. Coverage adds `documents-page.test.tsx` and `e2e/phase7-documents.spec.ts`, plus one ordinary case in `quick-command-preservation.test.tsx`. The existing command-list length assertion increases from six to seven for the actual additional command. Backend contract/source behavior remains unchanged. The page reads bounded metadata through `/api/documents`, 25 rows per server page. Search, supported filters, sorting and pagination preserve route context, browser history, unknown query parameters, hash and router state. Search edits replace their history entry; filter/page actions retain deliberate history. Superseded requests and incompatible query results cannot display stale rows. Refresh and load Retry perform guarded reads only. Language changes reformat existing metadata without refetching it. Linked-job selection reuses the existing bounded owner-scoped choices endpoint with search, limit 20 and separate loading/error feedback. The page labels current/draft/frozen resources, independent CV public/private state, source versions and honest recorded-date meanings. Uploaded local dates retain their recorded wall clock; the timezone is unknown. English uses `en-GB`, Bokmål `nb-NO`; unknown dates remain unknown. Saved letter versions are distinguished from current text, including history after current text is cleared. Captured CV version/name stays frozen provenance. A captured package does not prove receipt; a draft does not prove delivery; a public CV does not imply submission. Uploaded certificates remain uploaded evidence, and the existing AI-use flag is read-only here. Open actions navigate to existing resource owners and their dirty-state guards, carrying the Documents return URL/state. Correspondence links provide context, not exact-ID Resume; Submission links do not promise a selected snapshot. Current CV export stays in its existing owner. Exact type/resource/source relationships guard actions; malformed external or mismatched paths are not offered. Percent-encoded historical Nordic public slugs remain usable without fetching their bodies. Attachment download is an explicit, single-flight authenticated API-relative blob GET, avoiding a doubled `/api` prefix. It retains response MIME and the displayed filename, disposes the object URL, reports failure and suppresses late downloads after unmount or query change. File Retry repeats that file GET; actual404 offers list Refresh. Completion restores its initiating button only while the user remains on the temporary results focus target, preserving deliberate Search focus. Listing does not generate PDFs, invoke AI, capture packages or fetch private content bodies. ## Demonstrated findings and repairs | Demonstrated issue | Bounded correction | |---|---| | A valid server result with no rows on an out-of-range page was presented as an empty collection | Distinguish out-of-range page, genuinely empty index, filtered no-match and request failure. Show explicit first-page recovery while preserving filters/context; no silent page change | | Literal search `all` was discarded by generic default-value cleanup | Remove `all` only for the three enumerated filter defaults; preserve free-text search and unrelated URL/hash/state | | Selecting sort and immediately typing Search could rebuild the URL from stale committed parameters, losing `name-asc` | Keep pending edits in a small `{ location, params }` ref until Router commits. Compose consecutive edits; after a committed Back/Forward navigation use its authoritative parameters. Preserve unknown query/hash/router state without changing state frameworks or backend contracts | | Download completion could reclaim focus after the user moved to Search | Restore the originating action only from its temporary results focus target and matching query; preserve deliberate user focus | | Generic action-path validation could hide historical percent-encoded public CV slugs | Validate the expected owned resource/source and constrained public path while retaining valid encoded slugs | | Actual review of the 1440px attachment404 image finds the Alert action squeezing message text to roughly 70px | Give that existing Alert `auto minmax(0, 1fr)` grid columns, allow the message column to shrink and place its action on a separate second row. Styles only; existing refresh/retry behavior and tests stay unchanged | Neutral count labels handle one/many values without ungrammatical suffixes. Fields and state changes remain catalogue-backed. The page keeps white print documents in their existing owners; no pagination or rendering geometry is changed for this interface. ## Executed finite evidence [Entry evidence](evidence/ui-entry.json) records commands and source receipts; [current UI results](evidence/ui-results.json) consolidate the final finite evidence with hygiene/publication status. All times below are UTC on **2026-10-16**. Raw reports and retained failures live under `.artifacts/phase7/current/unit/` and `.artifacts/phase7/p7-07/`; frozen pre/post inputs qualify the earlier observations separately from the final candidate. | Observation | Actual result and qualification | |---|---| | Existing consumers | **64/6 PASS**, 08:59:12.556650–08:59:53.028496; navigation/command/notifications/CV-library/attachment/application-assets suites, with captured inputs unchanged | | Initial scaffold RED | **0 pass/10 fail**, 09:00:57.645492–09:01:47.462948; ordinary missing rendered content/actions, zero pending/todo. Scaffold and Documents tests stay unchanged across RED; the separate command addition is not executed here | | First candidate | **82/8 PASS**, 09:12:21.430119–09:12:51.706771. Separate app TypeScript exits **2**, 09:12:21.432827–09:12:37.343677, for two new test-utility typing errors. Fixes remove unsupported role-option typing and narrow an unknown value without weakening assertions | | Pagination RED | **11 pass/1 fail**, 09:14:36.074153–09:14:46.099718; ordinary out-of-range recovery regression in `ui-page-red` | | Literal-search RED | **12 pass/1 fail**, 09:17:36.435668–09:17:44.801611; exact `all` search regression in `ui-literal-red` | | Combined focus RED | **12 pass/2 fail**, 09:19:13.988227–09:19:23.098100; literal-search/focus observations retained in `ui-focus-red` | | Second candidate | **85/8 PASS**, 09:20:11.574953–09:20:53.563271; 14 Documents cases, one new command case and existing consumers/i18n. App/browser TypeScript pass, but lint exits **1**, 09:20:45.648691–09:21:24.574780, on React Compiler `preserve-manual-memoization` at `selectedJobCompany`. Build does not execute after the failed gate. `ui-green-candidate-2` retains matching pre/post inputs and the complete failure | | Third candidate | **85/8 PASS**, 09:25:00.363258–09:25:29.018303; lint still exits **1**, 09:25:00.365982–09:25:23.137169. The second memo correction is not accepted or bypassed; `ui-green-candidate-3` retains its evidence | | First verified product gates | **85/8 PASS**, 09:29:20.378671–09:29:55.030600; zero failed/pending/todo cases. Fresh lint, app/browser TypeScript and production build pass; the later native sort regression is not yet known | | Batched-query RED | **14 pass/1 fail**, 16:00:27.318436–16:00:50.731485; new fifteenth Documents case reproduces the native sort loss. Its Back-then-edit coverage is strengthened after RED without removing existing assertions | | Query-repair affected GREEN | **86/8 PASS**, 16:02:37.386765–16:03:56.205205; 15 Documents cases, one new command case and existing consumers/i18n, with zero failed/pending/todo cases. Fresh lint, app/browser TypeScript and build all pass | | Post-layout affected GREEN | **86/8 PASS**, 16:13:44.632211–16:14:21.313668; same ordinary cases after the Alert-only layout correction, without a new behavioral assertion or waived check | Three retained single-file **stdin probes** at **09:28:11–09:28:17** isolate the compiler-lint boundary: original control exits 1, explicit primitive-number boundary exits 0 and inline-number validation exits 0. They leave product source unchanged and do not constitute runtime/product gates. The final fix makes the validated job ID's primitive dependency explicit and records why in a comment; no lint rule or runtime assertion is waived. The first passing product gates exit **0**: lint **09:29:20.370635–09:29:48.708668**, app TypeScript **09:29:48.711497–09:30:01.092933**, browser TypeScript **09:30:01.095630–09:30:06.979125**, build **09:30:06.981156–09:30:23.690851**. Export **`PP_o3OeJyY8xztbIpdIkR`** and held source are frozen in `ui-gates-verified/results.json`, SHA256 `e15d8adb8692b5e40840028b8662fcbe592985b4c83aa55c7fb3885d9d4d8d05`. This is the pre-query-repair export used by native attempts one and two. The prior Oct14 frontend build is not evidence for this interface. After the demonstrated query defect is repaired, gates exit **0**: lint **16:02:37.459197–16:03:42.357976**, app TypeScript **16:03:42.361579–16:04:16.198952**, browser TypeScript **16:04:16.204494–16:04:26.882705**, build **16:04:26.885246–16:04:38.121135**. Export **`bDQZjWQBSWlVswr35XRb8`** is retained with GREEN/source evidence in `ui-query-gates-verified/results.json`, SHA256 `bfacd743798172dc8d21358ce5c9ea1a1ded731557812fb059b73c78e27f3bf4`. This boundary precedes the later Alert layout correction. After image review and the Alert-only correction, fresh gates exit **0**: lint **16:11:40.238196–16:12:06.891058**, app TypeScript **16:12:06.894066–16:12:20.300785**, browser TypeScript **16:12:20.303828–16:12:26.675069**, build **16:12:26.677131–16:12:34.714164**. The latest export is **`H6tIi63meKxiKJUAiZrOm`**. Final gates, frontend 86/8, Documents and 17 PNGs are frozen in `ui-layout-documents-verified/results.json`, SHA256 `0d784e2d3881fa17d127c6e7052351698e95a7c2855557a520b6c97c1dc30571`. Matching `ui-alert-native-pre/post` retain all 29 source records plus unchanged API/test DLL and BUILD_ID hashes across final execution, including the affected unit run. ## Native, visual and accessibility evidence The eight-case native specification covers actual local-cookie journeys for seven owned resource kinds/frozen provenance, server pagination/filter/history/job selection, initial503 Retry and incompatible held queries, stale-source Back/Refresh, exact attachment bytes/503/actual404, sign-out/A-B isolation, existing letter dirty Cancel/save, and finite bilingual/theme/reflow. First native attempt: **5 pass/3 fail**, **09:32:07.128874–09:32:49.679844**, with zero skipped/flaky cases and retries 0. `ui-native-attempt-1/results.json`, SHA256 `b5b9eab2a5a7f59b33d343e86825827973f01f3aaf835ca4a2a1ea8d031d1296`, retains the complete failures and source qualifications. Browser TypeScript passed immediately beforehand. This partial run is not final eight-case acceptance. | First-attempt fixture failure | Bounded specification correction | |---|---| | The Autocomplete fixture demands DOM focus on its option | Use the actual input-focused keyboard pattern: ArrowDown, prove `aria-activedescendant` identifies the visible option, then Enter. Keep exact selected-job and persisted URL/filter assertions | | A generic alert locator matches both the real CV Not Found alert and Next's route announcer | Locate the actual error alert; retain real source404, absent index, Back and explicit Refresh assertions | | Full-page capture changes scroll after the first 320px sample; focused-action y is **−1735.5** | Assert strict `0..viewport height` bounds before capture, explicitly restore scroll afterward and reassert the same bounds/focus; retain viewport screenshots. No relaxed reflow threshold or product change | The attempt reaches **six all-enabled axe scans / zero violations / 43 incomplete nodes**: six short notification badges and 37 overlapped contrast backgrounds. It retains **nine PNGs**. The responsive case stops after its first 320px sample, so the remaining seven widths are not evidenced by this attempt. Root has actually inspected only that sample's full-page and failed viewport images; no final visual acceptance is claimed. Full incomplete contexts remain pending contextual triage and manual qualifications. The first three corrections change only the eight-case specification. The **09:34→15:51 UTC usage pause** contains no inferred executions. Resumption compares all **29 captured sources** and recorded binaries unchanged against the first attempt's post-capture. Second native attempt: **7 pass/1 fail**, **15:55:09.478477–15:57:06.140335**, zero skipped/flaky cases and retries 0, retained in `ui-native-attempt-2`. All eight finite samples in C8 now pass strict focus, viewport overflow and enabled axe checks on the pre-query-repair export. C2 reaches its unchanged final server-query assertion and finds **`date-desc` where `name-asc` was selected**. This is a genuine product URL-update defect, preserved in the native evidence and reproduced by the new ordinary unit RED; its assertion is not weakened. That second attempt retains **14 axe scans / zero violations / 94 incomplete nodes**: 14 short badges, 79 overlapping backgrounds and one partially obscured contrast background, plus **17 PNGs**. These are finite observations of the previous export, not final visual/conformance acceptance. The prior **`bDQZjWQBSWlVswr35XRb8`** boundary passes **Documents 8/8**, **16:05:15.800503–16:06:35.882678**; **CV frame 4/4**, **16:06:35.893993–16:08:10.815285**; **ordinary P2-D01 1/1**, **16:08:10.827380–16:08:24.948002**. Its `ui-documents-verified/results.json` SHA256 is `032f284b7b2351cf39dbb2941d147dc42aa68295b579c25a690878a6a8cd4d73`. Latest **H6** checks independently pass **Documents 8/8**, **16:13:21.057245–16:14:18.605400**; **CV frame 4/4**, **16:14:18.614475–16:15:50.859320**; **ordinary P2-D01 1/1**, **16:15:50.869888–16:16:04.776459**. No skip, expected failure or retry conceals the repaired assertion. Latest consumer results and its extra PNG are frozen in `ui-layout-consumers-verified/results.json`, SHA256 `e8f2f5495f5f466183798d82c67de9839b151f1e4423a0088fa5e1886df47553`; previous-build passes are not substituted for these fresh 13 cases. All 17 **bDQ** PNGs are actually inspected by root/peer, producing the Alert layout finding above. Existing English CV `Not Found` copy in image 013 remains a P7-11 localisation finding. Final **H6** completes all eight samples and retains **15 default-enabled plus target-size axe scans / zero violations / 101 incompletes**. Root reads every context: 15 short badges, 85 form-background overlaps and one clipped Dashboard sidebar label in English/dark at 1024px. These remain open contrast/manual obligations, not passing judgments. Final images total **18: 17 Documents + 1 P2-D01**. Root actually views Documents 0–8 and the P2 image, confirms readable Alert text/action below; peer actually reviews Documents 9–16. Thus all 18 are reviewed, with `ui-layout-visual-peer-review.json` retaining the peer's receipt. The P2 full-page image has transitional overlay/sticky positioning; archive bytes/DOM assertions supply its contract evidence, and that image does not prove print fidelity or precise contrast. Finite image review supports the local UX decision without human accessibility acceptance. Setup deliberately captures a submitted package once through the established renderer to create real frozen evidence. That explicit fixture operation must remain separate from the assertion that Documents listing triggers no source-body/render/preview/PDF/export/AI/provider/send request or mutation. Subsequent editor actions retain their existing owner reads and saves. Required finite samples remain 320, 360, 390, 768, 1024, 1280, 1440 and 1920px, including 1280×320 landscape, English/Bokmål and both themes. Retain every enabled axe/target-size violation and incomplete vector, record contextual triage and inspect actual PNGs before drawing visual conclusions. Human screen-reader, physical touch/software keyboard, real zoom and production fonts/photo qualification remain open; automation cannot close them. ## Preservation and remaining work The additions derive frontend inventory **755/95** from **739/94**: 15 new Documents cases and one command case, one new suite. The earlier **754/95** inventory preceded the new query regression case. Eight new native cases pass the finite current-build run and derive browser inventory **312** from **304**; these Documents additions are now published. Backend inventory stays **1,053** at this checkpoint, inherited from the pushed contract. These are inventory calculations, not fresh full-suite pass counts; P7-12 retains the integrated acceptance run. All **57 PRES groups remain 56 PARTIAL / C11 DEFERRED**. Preserve the original 32 routes alongside the approved new route, owner/tenant authorization, canonical Career Profile data, CV overrides/revisions, one-job CV associations and immutable package content/files. Fresh P2-D01 passes as an ordinary case on latest H6; neither the earlier contract nor prior bDQ run is substituted for it. Final [static checks](evidence/ui-static-checks.json) pass at **2026-10-16 16:21 UTC**: secret scan, working/staged/phase whitespace, 19 documents / 518 local links, all 57 groups and 33 routes. Subsequent commit/publication outcomes are recorded below. Retain every triaged contrast/manual qualification and the P7-11 missing-source copy finding. No actual MariaDB runtime, external provider delivery or fresh PDF corpus qualification is supplied by these UI tests. P5-13 remains withheld with **zero model qualification calls**; followMode stays deferred. Phase 8 is not implemented. **UI implemented-scope acceptance: CONDITIONAL GO; hygiene PASS and publication verified. Production: NO-GO; main unchanged.** ## Actual local commit and failed publication — 2026-10-16 Documents interface commit **`5a67ec3d3d5dc27298814b0a3f46540cb54ea3a3`** is recorded locally before its [first normal publication attempt](evidence/ui-publication.json), **16:22:30.090899–16:22:51.339211 UTC**, fails with exit 128 because `git.cesnimda.uk:443` is unreachable. The second attempt at **16:31:50.187856–16:32:11.434629** also fails with exit 128. Publication is blocked at those observations; historical `8e4db12` is not treated as current live identity. Both exact failed attempts remain in the chronology. The later normal push **21:00:51.343381–21:00:53.589287** succeeds. At **21:01:11.788733 UTC**, direct development verification records local HEAD = origin development = live development = **`9dfea1226f57ba12b944e05e0e83fb2fea846131`**, containing implementation `5a67ec3`, publication documentation `84350b7` and the separate UTC repair. Local/origin/live main remain `27657f31131cd95d42f0e1290853ec9c9b3959a4`. The portable publication receipt retains the exact raw recovery path/hash. Known P7-08 notification presentation/native files remain unstaged work; synchronized refs do not mean a clean working tree or publication of that WIP. **P7-07 publication is verified; conditional manual/production qualifications remain.**