Files
jobtrackingapp/docs/redesign/phase-5/p5-15/ROUTE_ACCEPTANCE.md
T

128 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P5-15 route and visible-action acceptance plan
## Final native census successor — P5-15-06
[Fresh complete regression](p5-15-06/README.md) retains all32 concrete route patterns (31originals+Analytics), each anonymous/normal/admin entry and refresh:192observations,98selected expected API reads, no500. These journeys assert actual headings/data/destinations/authentication/role denials and retain the repaired AUTH-01 query behavior; HTTP200 alone is not acceptance. [Portable observations](p5-15-06/evidence/validation.json) retain all three census records. All32 matrix rows remain PARTIAL because provider/manual/long-tail acceptance is incomplete; no route or alias is removed. Production main remains unchanged/NO-GO. The planning text below is historical rather than a claim that these fresh checks did not occur.
Planning checkpoint: **`46a0c0c6d23464869f50c0d88552963c29cfdacf`**, branch `codex/ui-redesign-phase4`, 2026-10-09. This is source characterization and a future audit plan. **No fresh route/browser/provider/manual checks have run; no acceptance or route-removal decision is made.** The [57-group matrix](PRESERVATION_ACCEPTANCE.md) retains every original sub-workflow.
## Original versus current census
The [original audited route inventory](../../audit/ROUTE_MAP.md) at Phase 1 contains **31 concrete patterns: 29 pages and two redirect aliases**. The [Phase 3 route/query plan](../../phase-3/ROUTE_PLAN.md), [Phase 5 navigation migration](../NAVIGATION_MIGRATION.md) and [release-candidate census](../release-readiness/PRESERVATION_REVIEW.md#route-census-and-compatibility) establish the compatibility chain.
Current [App routing](../../../../job-tracker-ui/src/App.tsx) declares **35 routes** across its outer data-router objects and inner `Route path` elements. Exclude outer `/*`, inner `*` and the duplicate inner `/` redirect infrastructure: **32 unique concrete patterns = all 31 originals + `/analytics`**. Current disposition is **29 pages and three redirects**: `/analytics` adds a page while original `/kanban` becomes a redirect to the integrated Board. The public outer LandingPage owns `/`; its private inner Dashboard redirect is not a second page. RouteErrorPage is an error boundary, not another pattern.
[P5-01](../p5-01/README.md) moved navigation entries while retaining original routes; [P5-04b](../p5-04b/README.md) introduced the integrated `/jobs?view=board` and legacy Board redirect; [P5-07](../p5-07/README.md) added meaningful personal `/analytics`. P5-08a/b and P5-09–14 enhance existing workspace/editor paths without adding concrete route patterns. Static presence proves declarations only; direct URL, refresh, Back/Forward, real permissions, dirty Cancel/Discard, safe errors and deployed health remain to be audited.
## Exactly 32 current concrete patterns
Every row is **PARTIAL** for route acceptance: current source plus linked historical regression exists, but fresh-current, provider or required manual checks remain NOT VERIFIED. No missing test is labelled a functional FAIL. Route columns characterize the actual current behavior rather than narrowing the original capability.
| Concrete pattern | Original/current disposition | Current actual owner | Query / action / compatibility semantics and limit | PRES scope | Historical regression anchors / remaining acceptance limit | Planning status |
|---|---|---|---|---|---|---|
| `/` | Preserved public page | [LandingPage](../../../../job-tracker-ui/src/views/LandingPage.tsx) | Public product/plans. Authenticated mount replaces to /dashboard; protected-route state is forwarded by login action. Query/capture/landing continuity is a future audit. | E01/E02/E07/E08 | [landing/auth redirect](../../../../job-tracker-ui/src/LandingPage.authRedirect.test.tsx), [landing](../../../../job-tracker-ui/src/landing-page.test.tsx); provider/mobile limits in E01 | **PARTIAL** |
| `/login` | Preserved public page | [LoginPage](../../../../job-tracker-ui/src/views/LoginPage.tsx) | Local/provider/challenge/configured registration controls; validates local state.from then replaces after sign-in. SessionChanged notice and reset-email prefill remain. | E02–E05/E09 | [login](../../../../job-tracker-ui/src/login-page.test.tsx), [smoke](../../../../job-tracker-ui/e2e/smoke.spec.ts); live auth/provider limits E02–E04 | **PARTIAL** |
| `/register` | Preserved public page | [LoginPage](../../../../job-tracker-ui/src/views/LoginPage.tsx) | initialMode=register, subject to configuration; uses the same safe post-auth target and provider/challenge boundaries. | E02/E03 | [login](../../../../job-tracker-ui/src/login-page.test.tsx), [local auth](../../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs); configured/provider limits E02 | **PARTIAL** |
| `/forgot-password` | Preserved public page | [ForgotPasswordPage](../../../../job-tracker-ui/src/views/ForgotPasswordPage.tsx) | email prefill; explicit reset request. Runtime mail/configuration/browser completion remains unverified. | E02 | [local auth](../../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs); complete browser/mail journey remains E02 gap | **PARTIAL** |
| `/reset-password` | Preserved public page | [ResetPasswordPage](../../../../job-tracker-ui/src/views/ResetPasswordPage.tsx) | email/token query; explicit password submit. Invalid/expired/already-used token and sensitive URL handling need acceptance. | E02 | [local auth](../../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs); complete token submit/mail journey remains E02 gap | **PARTIAL** |
| `/verify-email` | Preserved public page | [VerifyEmailPage](../../../../job-tracker-ui/src/views/VerifyEmailPage.tsx) | userId/email/token query; verification outcomes remain under identity owner, not shell page placement. | E02 | [verification](../../../../job-tracker-ui/src/verify-email-page.test.tsx), [local auth](../../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs); actual mail E02 | **PARTIAL** |
| `/confirm-email-change` | Preserved public page | [VerifyEmailPage emailChange](../../../../job-tracker-ui/src/views/VerifyEmailPage.tsx) | Same page in email-change mode; existing userId/email/token confirmation, independent from Career data. | E06 | [verification](../../../../job-tracker-ui/src/verify-email-page.test.tsx), [local auth](../../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs); account mutation gaps E06 | **PARTIAL** |
| `/microsoft-legacy-relink` | Preserved public page | [MicrosoftLegacyRelinkPage](../../../../job-tracker-ui/src/views/MicrosoftLegacyRelinkPage.tsx) | userId/tenantId/objectId/token recovery metadata; actual provider popups/consent/revoke and origin/state unverified. | E03 | [relink](../../../../job-tracker-ui/src/microsoft-legacy-relink-page.test.tsx), [token validator](../../../../JobTrackerApi.Tests/MicrosoftTokenValidatorTests.cs); real consent E03 | **PARTIAL** |
| `/cv/:slug` | Preserved public page | [PublicCvPage](../../../../job-tracker-ui/src/views/PublicCvPage.tsx) | Published slug owner and anonymous HTML/PDF. No numeric private-editor redirect; publication/revocation and PDF capacity remain protected. | C05/C12 | [public CV](../../../../job-tracker-ui/src/public-cv-page.test.tsx), [PublicCvController](../../../../JobTrackerApi.Tests/PublicCvControllerTests.cs), [smoke](../../../../job-tracker-ui/e2e/smoke.spec.ts); deployed fonts/publication lifecycle C05/C12 | **PARTIAL** |
| `/dashboard` | Enhanced original page — P5-06 | [DashboardView](../../../../job-tracker-ui/src/components/DashboardView.tsx) | Home reports/onboarding/five owner-local flags and contextual links. Snapshot/trend retries remain separate; period is component state here. | S01/S02/E07–E09 | [P5-06 evidence](../p5-06/README.md), [daily loop](../../../../job-tracker-ui/src/daily-control-loop.test.tsx); metric/preference limits S01/S02 | **PARTIAL** |
| `/analytics` | Added enhanced page — P5-07 | [AnalyticsPage → DashboardView(mode=analytics)](../../../../job-tracker-ui/src/views/AnalyticsPage.tsx) | Authenticated personal reports use the same existing facts/cohorts. months=6/12/24 is URL state; defaults 12; independent of Dashboard visibility flags. | S01/S02/E07–E09/J05/J09 | [P5-07 evidence](../p5-07/README.md); no new server facts/populations or deployed acceptance S01 | **PARTIAL** |
| `/discover` | Preserved page; Jobs secondary entry | [JobDiscoveryPage](../../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx) | NAV discovery, saved searches/alerts and detail controls unchanged; no new source/provider scope from relocation. | J01/J02 | [discovery](../../../../job-tracker-ui/src/job-discovery.test.tsx), [smoke](../../../../job-tracker-ui/e2e/smoke.spec.ts); live NAV J01/J02 | **PARTIAL** |
| `/jobs` | Enhanced original page — P5-03/P5-04b | [JobTable(mode=jobs)](../../../../job-tracker-ui/src/components/JobTable.tsx) | Table default; view=board mounts KanbanBoard within same owner. Shared complete logical query; page/columns/density/selection lifetime remains explicit. | J03–J07/W01/S03 | [P5-03](../p5-03/README.md), [P5-04b](../p5-04b/README.md), [native Board/query integration](../../../../job-tracker-ui/e2e/board-presentation.spec.ts), [integration component](../../../../job-tracker-ui/src/jobs-view-integration.test.tsx); finite-query/scaling limits J03–J07 | **PARTIAL** |
| `/jobs/:id` | Enhanced original page — P5-08a/b | [ApplicationWorkspacePage](../../../../job-tracker-ui/src/views/ApplicationWorkspacePage.tsx) | Seven URL sections, Application/Timeline sub-navigation, existing domain owners/dirty guards. Legacy section strings and numeric navigation-helper tab arguments retained; numeric values are not URL `section` aliases. followMode is metadata only. | W01–W12/M01/M02/E07–E09 | [P5-08b](../p5-08b/README.md), [route contracts](../../../../job-tracker-ui/src/application-route-contracts.test.ts), [preservation browser](../../../../job-tracker-ui/e2e/redesign-preservation.spec.ts); deferred followMode/manual/provider limits W01–W12 | **PARTIAL** |
| `/reminders` | Preserved page; Jobs secondary entry | [RemindersView](../../../../job-tracker-ui/src/components/RemindersView.tsx) | Follow-ups retains grouped reasons and workflow actions; existing calendar/rule/date contracts, no newly scheduled interview semantics. | W10/W11 | [daily loop](../../../../job-tracker-ui/src/daily-control-loop.test.tsx), [calendar](../../../../job-tracker-ui/src/application-calendar.test.tsx); F21/provider W11 | **PARTIAL** |
| `/operations` | Preserved page; utility entry | [OperationsPage](../../../../job-tracker-ui/src/views/OperationsPage.tsx) | Activity/processing list/progress/result/retry/cancel. Bell View all points here; no /notifications page exists. | W12/S02 | [operations](../../../../job-tracker-ui/src/operations-page.test.tsx), [OperationsController](../../../../JobTrackerApi.Tests/OperationsControllerTests.cs); worker/disconnect W12 | **PARTIAL** |
| `/kanban` | Legacy original pattern; redirect after P5-04b | [LegacyBoardRedirect](../../../../job-tracker-ui/src/App.tsx) | Navigate replace to /jobs with view=board. Clones search and overwrites only view; explicitly preserves hash and location.state. No removal date approved. | J07/W01/E07 | [P5-04b](../p5-04b/README.md), [native Board/query integration](../../../../job-tracker-ui/e2e/board-presentation.spec.ts), [App redirect](../../../../job-tracker-ui/src/App.tsx); physical touch/scaling J07 | **PARTIAL** |
| `/companies` | Preserved page; Jobs secondary entry | [CompaniesTable](../../../../job-tracker-ui/src/components/CompaniesTable.tsx) | edit=id opens company editor, including command result destination; contacts/pipeline/history remain with existing form owner. | J08 | [companies](../../../../job-tracker-ui/src/companies-relationship.test.tsx), [command](../../../../job-tracker-ui/src/quick-command-preservation.test.tsx); modal-save accessibility J08 | **PARTIAL** |
| `/offers` | Preserved page; Jobs secondary entry | [OfferComparisonPage](../../../../job-tracker-ui/src/views/OfferComparisonPage.tsx) | Recorded compensation/notes/deadline/source comparison; Dashboard/Analytics offer links continue; no inferred salary calculator. | J09/S01 | [offers](../../../../job-tracker-ui/src/offer-comparison.test.tsx), [P5-07 links](../p5-07/README.md); full mobile/currency review J09 | **PARTIAL** |
| `/correspondence` | Preserved primary page | [CorrespondenceInboxPage](../../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx) | view=review selects GmailReviewPage; other URL view values select inbox. Compose/drafts remain existing in-page state/actions, not new routes. | M01–M06 | [inbox](../../../../job-tracker-ui/src/correspondence-inbox-page.test.tsx), [draft persistence](../../../../JobTrackerApi.Tests/EmailDraftPersistenceTests.cs); live mail/reconnect M01–M06 | **PARTIAL** |
| `/correspondence/review` | Preserved legacy redirect | [Navigate review alias](../../../../job-tracker-ui/src/App.tsx) | Hard-coded replace to /correspondence?view=review. Does not pass incoming other query, hash or state. Record this existing limit; audit required metadata before parity claims. | M05 | [inbox](../../../../job-tracker-ui/src/correspondence-inbox-page.test.tsx), [review](../../../../job-tracker-ui/src/gmail-review-page.test.tsx); actual provider/create chain M05 | **PARTIAL** |
| `/profile` | Preserved page; Settings/account entry | [ProfilePage](../../../../job-tracker-ui/src/views/ProfilePage.tsx) | Account identity/avatar/password/email and local security/session cards retained; same page, distinct from canonical Career Profile. | E04–E06 | [profile](../../../../job-tracker-ui/src/profile-page.test.tsx), [2FA](../../../../job-tracker-ui/src/two-factor-settings.test.tsx); complete account/device journeys E04–E06 | **PARTIAL** |
| `/applications/:id` | Preserved legacy redirect | [LegacyApplicationRedirect](../../../../job-tracker-ui/src/App.tsx) | Replace to /jobs/:id + location.search and state=location.state. Hash is not passed by the current adapter; no alias removal approved. | W01/E07 | [P5-08b](../p5-08b/README.md), [workspace](../../../../job-tracker-ui/src/application-workspace-overlay.test.tsx), [App redirect](../../../../job-tracker-ui/src/App.tsx); legacy sections/followMode W01 | **PARTIAL** |
| `/career` | Preserved page; Career Profile entry | [CareerWorkspacePage → CareerProfilePage](../../../../job-tracker-ui/src/views/CareerWorkspacePage.tsx) | section=profile/evidence/import; default overview. Structured source/import/evidence/history owners remain; /career/profile is not an App route. | C01–C04 | [Career workspace](../../../../job-tracker-ui/src/career-workspace-page.test.tsx), [profile](../../../../job-tracker-ui/src/profile-page.test.tsx); long-tail/import/provider C01–C04 | **PARTIAL** |
| `/career/builder` | Preserved page; CVs entry | [CvBuilderPage](../../../../job-tracker-ui/src/views/CvBuilderPage.tsx) | CV library create/copy/delete/templates/manage/publish/share/export. Creates/open navigate to numeric owned editor, public slug remains distinct. | C05 | [builder library](../../../../job-tracker-ui/src/cv-builder-page.test.tsx), [P5-12](../p5-12/README.md); full library/publication chain C05 | **PARTIAL** |
| `/career/builder/:id` | Enhanced original editor — P5-09–12/P5-14 | [CvBuilderEditor](../../../../job-tracker-ui/src/views/CvBuilderEditor.tsx) | One save/revision/history/preview owner, Content-first local studio tabs and responsive panes. Production CV generation/Apply unavailable guard; P5-13 review deferred. | C06–C12/W05/E07–E09 | [editor](../../../../job-tracker-ui/src/cv-builder-deep-link.test.tsx), [P5-12](../p5-12/README.md), [AI readiness](../p5-13-readiness/README.md); P5-13/P5-14/manual/rendering limits C06–C12 | **PARTIAL** |
| `/admin/audit` | Preserved authorized admin page | [AdminAuditPage](../../../../job-tracker-ui/src/views/AdminAuditPage.tsx) | Separate audit/history/supported undo/restore; API role checks remain authoritative. Shell visibility is not authorization proof. | A02 | [audit](../../../../job-tracker-ui/src/admin-audit-page.test.tsx), [authorization](../../../../JobTrackerApi.Tests/ApiAuthorizationPostureTests.cs); native undo A02 | **PARTIAL** |
| `/admin/users` | Preserved authorized admin page | [AdminUsersPage](../../../../job-tracker-ui/src/views/AdminUsersPage.tsx) | Separate users/role/reset/delete/last-admin/self guards; no aggregate Admin page invented. | A01 | [users](../../../../job-tracker-ui/src/admin-users-page.test.tsx), [UsersController](../../../../JobTrackerApi.Tests/UsersControllerTests.cs); revoke/reset A01 | **PARTIAL** |
| `/admin/system` | Preserved authorized admin page | [AdminSystemPage](../../../../job-tracker-ui/src/views/AdminSystemPage.tsx) | Separate diagnostics/configuration/mail/AI/probe/benchmark/maintenance; visible admin metadata retained, production actions unverified. | A03 | [system](../../../../job-tracker-ui/src/admin-system-page.test.tsx), [maintenance](../../../../JobTrackerApi.Tests/MaintenanceJobDispatcherTests.cs); deployed probes A03 | **PARTIAL** |
| `/trash` | Enhanced original page — P5-03 | [JobTable(mode=trash)](../../../../job-tracker-ui/src/components/JobTable.tsx) | Deleted-only list and restore/edit; Table-specific utility, no Board view or permanent-delete substitution. | J06/S03 | [P5-03](../p5-03/README.md), [table density](../../../../job-tracker-ui/e2e/table-density.spec.ts); finite restore/bulk/manual J06 | **PARTIAL** |
| `/settings` | Preserved page; Account entry | [SettingsView](../../../../job-tracker-ui/src/components/SettingsView.tsx) | Existing tabs/mobile selector/data/rules/notifications/AI/privacy/backup/account lifecycle, Profile and Connections links; saves retain existing owners. | S03–S05/J10/E08 | [Settings](../../../../job-tracker-ui/src/settings-view.test.tsx), [native layout](../../../../job-tracker-ui/e2e/settings-page-layout.spec.ts); concurrent saves/billing/restore S03–S05 | **PARTIAL** |
| `/settings/connected-accounts` | Preserved page; Settings secondary entry | [ConnectedAccountsPage](../../../../job-tracker-ui/src/views/ConnectedAccountsPage.tsx) | Gmail/Graph/IMAP connection status/connect/disconnect distinct from sign-in identity; mail/calendar grants do not authorize new routing/send behavior. | M06/E03 | [connections](../../../../job-tracker-ui/src/email-provider-connections.test.tsx), [native Settings](../../../../job-tracker-ui/e2e/settings-page-layout.spec.ts); actual OAuth/mail/expiry M06 | **PARTIAL** |
## Query state and alias behavior to audit
| Contract / actual owner | Current source behavior | Required execution acceptance / owner / priority |
|---|---|---|
| Jobs filters and shared Board query — [jobsQuery](../../../../job-tracker-ui/src/jobsQuery.ts), [JobTable](../../../../job-tracker-ui/src/components/JobTable.tsx) | `q/status/companyId/location/needsFollowUp/readiness/includeDeleted/sortBy/sortDir` are shared logical inputs. `view=board` is Board only in Jobs mode; other values use Table. Table page uses positive URL page and zero-based local index; Board does not reinterpret it as a population limit. | Audit identical complete IDs, custom statuses, owner/deleted/derived filters, saved-view CRUD, unknown/invalid values and scale. Preserve nonavailable/error semantics and selected scope. Jobs/API owner; H. |
| Table↔Board view and list mutation — [JobTable](../../../../job-tracker-ui/src/components/JobTable.tsx) | View link clones query, sets `view`, keeps hash and router state while clearing `focusJobId`; switching clears Table page selection. Filter/sort/page update clones other query and replaces history with state, but does not explicitly pass hash. Density is local presentation state, not account/saved-view/API data. | Direct entry, refresh, Back/Forward, page two, zero matches, unknown safe query/hash and select→switch→return; characterize list update hash before promising fidelity. Jobs owner; H. |
| Legacy Board — [App LegacyBoardRedirect](../../../../job-tracker-ui/src/App.tsx) | `/kanban` clones incoming search, sets `view=board`, replaces history, explicitly retains hash/state. Query-supplied `view=table` is deliberately overwritten. | Native direct/refresh/back and unknown query/hash/state with filtered all-result membership, no loops or mutation. Jobs/shell owner; H. |
| Legacy application — [App LegacyApplicationRedirect](../../../../job-tracker-ui/src/App.tsx) | `/applications/:id` replaces to `/jobs/:id` with the exact search string and router state. It does not pass hash. | Every legacy section/sub/followMode, invalid/missing/foreign id, state return and hash limit; no implicit AI/send/capture/write. Workspace owner; H. |
| Review alias — [App Navigate](../../../../job-tracker-ui/src/App.tsx), [inbox adapter](../../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx) | `/correspondence/review` hard-codes replace to `/correspondence?view=review`; other incoming query/hash/state are not passed. Inbox reads `view=review`; drafts/compose use existing in-page state. | Direct/refresh/back and required old metadata, reviewed job create/no-write navigation, dirty draft and send-uncertainty boundaries. Existing fidelity limit is not silently declared repaired. Mail owner; H. |
| Seven job sections — [applicationWorkspace adapter](../../../../job-tracker-ui/src/applicationWorkspace.ts), [workspace navigation](../../../../job-tracker-ui/src/views/ApplicationWorkspacePage.tsx) | Canonical: `overview/match/application/documents/timeline/tasks/interview`. Legacy: analysis→match; cv/cover-letter→application; job-details→overview; checklist/notes→tasks; communication→timeline; portfolio→documents. Unknown section→overview. `sub` selects Application cv/letter/answers/submission or Timeline activity/correspondence. Old cv/letter/communication sections take priority over unrelated sub metadata. | All canonical/legacy entries, disclosure reveal/focus, tab keyboard, unknown key no-write, Back/Forward/refresh, job missing/denied/retry and unsaved letter/answers Cancel/Discard. Workspace/accessibility owner; H. |
| Numeric navigation-helper tab arguments and follow-up metadata — [jobWorkspaceRoute](../../../../job-tracker-ui/src/jobWorkspaceRoute.ts) | Helper tab arguments map 0→overview, 1→communication, 2→documents, 3→cv, 4→communication, 5→match, 6→analysis, 7→interview, 8→checklist, 9→timeline. These generate section strings, not numeric URL `section` aliases; the helper preserves optional `followMode`. Workspace section/sub change clones current query and retains location.state. **No mode-specific UI consumer exists.** | Retain helper tab-to-section outputs and metadata through section/history/reload; honor [recorded mail-phase deferral](../p5-08b-readiness/README.md). Do not count metadata preservation as compose/follow-up UI acceptance. Workspace/mail owner; H. |
| Jobs return/focus — [JobTable](../../../../job-tracker-ui/src/components/JobTable.tsx), [workspace close](../../../../job-tracker-ui/src/views/ApplicationWorkspacePage.tsx) | Row entry records numeric `jobListFocusId` on originating history and sends state `from` + `focusJobId`. `from` is pathname/search only. Workspace close replaces to local `from` or `/jobs` and sends numeric focus; no mounted background Jobs assumption. | Real loaded row/card/Board workflow entry, explicit Back/browser Back, safe from/unknown state and missing row, filter/page/focus recovery, dirty cancellation across all shell routes. Workspace/Jobs owner; H. |
| Capture — [App Shell effect](../../../../job-tracker-ui/src/App.tsx), [captureUrl](../../../../job-tracker-ui/src/captureUrl.ts) | Private Shell resolves `add/addtext`, opens prefilled review, consumes only those keys with history replacement while keeping other search. That navigate call does not explicitly pass hash/state. Opening is not creation. Root public LandingPage authenticated redirect goes to `/dashboard` without explicitly forwarding search. | Characterize root/private/unauthenticated extension/bookmarklet/PWA share, invalid URL, Cancel/reload/no replay/no duplicate write, safe metadata and optional post-create failure. Capture/identity owner; H. |
| Protected route/login continuity — [App auth guard](../../../../job-tracker-ui/src/App.tsx), [LandingPage](../../../../job-tracker-ui/src/views/LandingPage.tsx), [LoginPage](../../../../job-tracker-ui/src/views/LoginPage.tsx) | Shell denied entry replaces to public `/` with state.from **pathname only**, not search/hash. Landing forwards state to login. Login accepts a local slash path excluding `//` and backslashes, else Dashboard. Authenticated public Landing replaces straight to Dashboard. | Deep links with Jobs filters/sections/capture after session expiry/login, safe malformed external targets, remember/challenge/provider paths and stale-account cancellation. Characterize loss limits; no complete deep-link continuity claim from path presence. Identity owner; H. |
| Career section — [CareerProfilePage](../../../../job-tracker-ui/src/views/CareerProfilePage.tsx) | `section=profile/evidence/import`, default overview. Canonical source remains separate from account Profile and CV variant settings/history. | Section direct/refresh/back and dirty import/edit/navigation, long-tail saves, raw/history restore and source/variant separation. Career owner; H. |
| Analytics period — [DashboardView](../../../../job-tracker-ui/src/components/DashboardView.tsx), [AnalyticsPage](../../../../job-tracker-ui/src/views/AnalyticsPage.tsx) | `months=6/12/24`, invalid/default 12; setQuery clones unrelated query. Dashboard uses local period state and five owner-local flags; Analytics shows reports independently. | Exact values/cohorts, Back/refresh/query preservation, independent snapshot/trend failures, no invented metrics and Dashboard flag isolation. Reports owner; M. |
| Company command/deep edit — [CompaniesTable](../../../../job-tracker-ui/src/components/CompaniesTable.tsx), [QuickCommandDialog](../../../../job-tracker-ui/src/components/QuickCommandDialog.tsx) | Company search result enters `/companies?edit=id`; positive edit key requests existing company form. Form is not relocated or auto-saved by route presence. | Command/direct/refresh, missing/foreign id, retained draft and durable modal error; P4-02-D02 remains open. Companies/accessibility owner; H. |
| Token and provider URLs — [reset](../../../../job-tracker-ui/src/views/ResetPasswordPage.tsx), [verification](../../../../job-tracker-ui/src/views/VerifyEmailPage.tsx), [relink](../../../../job-tracker-ui/src/views/MicrosoftLegacyRelinkPage.tsx) | Reset email/token; verify userId/email/token; Microsoft relink userId/tenantId/objectId/token. Backend OAuth callbacks/postMessage are separate from React page patterns. | Expired/invalid/missing/used token and safe logs/titles/history, real sandbox popup origin/state/revoke, no identity leakage. Explicit provider approval at execution time. Identity/provider owner; H. |
| Numeric private CV and public slug — [editor](../../../../job-tracker-ui/src/views/CvBuilderEditor.tsx), [public page](../../../../job-tracker-ui/src/views/PublicCvPage.tsx) | Private variant id controls saved lens/history; public slug publication is independent. Current Production CV suggestion-service generation/Apply returns 503; old assistant affordances may still be visible. P5-13 review UI is absent. | Missing/foreign/unpublished/revoked entry, dirty editor/library/Back, no source/sibling mutation, public/private PDF admission and honest unavailable AI. Preserve [P5-13 exception](../OPEN_BLOCKERS.md#p5-13-deferred-debt-and-return-conditions--2026-10-08); CV/AI owner; H. |
## Navigation entries and forbidden removal without replacement
Current [App navigation arrays](../../../../job-tracker-ui/src/App.tsx), [AppShell menus/drawer](../../../../job-tracker-ui/src/layout/AppShell.tsx) and [Jobs view owner](../../../../job-tracker-ui/src/components/JobTable.tsx) supply the actual reachable entries. A future audit must demonstrate expanded desktop, collapsed rail menu and scrollable labelled mobile drawer plus successful heading focus and dirty Cancel preservation. A declaration or hidden menu is insufficient.
| Original / required entry | Current reachable replacement or retained entry | Removal constraint / required acceptance |
|---|---|---|
| Dashboard | Home primary `/dashboard` | Retain reports/flags/onboarding/attention and exact-value links; no replacement by Analytics-only page. |
| Job applications | Jobs primary `/jobs`; Table default | Preserve filters/saved views/pagination/columns/density/mobile row actions and reviewed Add. |
| Kanban board separate primary | Jobs Table/Board switch `/jobs?view=board`; legacy `/kanban` redirect retained | Only old primary entry is consolidated; full query/status/mutation/keyboard parity remains protected. No alias removal date. |
| Discover jobs | Jobs secondary `/discover` | Remain reachable, labelled in narrow/collapsed shell; preserve saved-search/alerts. |
| Reminders | Jobs secondary `/reminders` with count | Preserve every reminder reason, count and workflow/calendar action; do not replace with only overdue cards. |
| Companies / Offers / Trash | Jobs secondary `/companies`, `/offers`, `/trash` | Every low-frequency entry stays reachable; Trash is deleted-only restore, never hard delete. Company edit query remains. |
| Correspondence | Independent primary `/correspondence`; inbox/drafts/review | Never hide global mail in Documents or confuse log with send. Retain review alias and uncertain-send safeguards. |
| Career workspace | Career Profile `/career` | Canonical facts/import/evidence remain distinct from account Profile and CV editing. No invented `/career/profile` route. |
| CV Builder | CVs `/career/builder` and numeric editor | Retain create/copy/delete/publication/export, all controls and one persistence owner; new review remains deferred. |
| Profile former duplicate primary | Settings secondary `/profile` **and** account-menu profile | Both accessible replacement entries exist; security/session/avatar/email/password forms remain under same owner. |
| Settings / Connections | Settings primary, secondary Connections `/settings/connected-accounts`; existing Settings link | Preserve all tabs/mobile selector/data/privacy/backup/account lifecycle and distinct provider grants. |
| Audit / Users / System | Separate admin-only bottom navigation entries | Server role checks remain mandatory; do not invent an aggregate `/admin` landing or drop an operational tool. |
| Language/theme/account Sign out | Header/account controls reuse existing owners | Remain reachable at narrow/collapsed widths and keyboard; UI locale is separate from CV document locale. |
| Quick search/Add | Header search + Ctrl/Cmd+K; six static commands, job/company results; AddJobModal | Retain exact destinations, failure Retry/stale-result disposal and no-create-on-open boundary. |
| Bell/activity | Bell NotificationsPopover; View all→`/operations`; operation/result deep links | Preserve read/dismiss/status/retry/cancel. No `/notifications` route or new notification producer inferred. |
| Admin version/commit | Admin-only shell/account disclosure | Same authorized information remains reachable without narrow-header overlap; public metadata scope not expanded. |
| Proposed Documents / Notifications / global AI / aggregate Admin | No current standalone routes or dead placeholders | Explicitly deferred/absent. Existing job Documents and contextual AI entries remain; absent new pages cannot justify removing their old owners. |
| Analytics | Added meaningful `/analytics` primary in Insights | Existing personal facts/cohorts only; no fabricated metric or new aggregate/admin analytics. |
## Visible control action audit required for P5-15
This is a **source-level action map plus a future manual/native audit checklist**, not a click-through result or complete control census. The larger feature inventory owns sub-actions. Audit role/data/state combinations on every relevant route and all currently visible controls; record named control, expected destination/request, actual result, error/empty/locked/loading/dirty state and focus. H identifies controls requiring behavioral proof beyond a screenshot.
| Surface / actual owner | Visible controls and source-defined actions | Required audit / owner / priority |
|---|---|---|
| [Shell](../../../../job-tracker-ui/src/layout/AppShell.tsx), [App callbacks](../../../../job-tracker-ui/src/App.tsx) | Navigation parent/child/rail menu/mobile drawer, collapse, skip/main, search, Add on Jobs, bell, Settings/profile, theme/language, Sign out, admin badge disclosure | Every entry in prior table; Escape/close/resize focus, active child/parent, dirty navigation Cancel/Discard and account disposal. Shell/accessibility/identity; H. |
| [Command palette](../../../../job-tracker-ui/src/components/QuickCommandDialog.tsx) | Six commands: Dashboard, Jobs, Reminders, Companies, Settings, Add review; job→numeric workspace, company→edit query; keyboard selection, Retry, Escape | No mutation on palette/search/route mount, late-result rejection, IME/Enter/arrow behavior, focus after opening/cancel and manual spoken result/error states. P5-02-D01/P5-04b-R01 remain open. Shell; H. |
| [Bell](../../../../job-tracker-ui/src/components/NotificationsPopover.tsx), [Operations](../../../../job-tracker-ui/src/views/OperationsPage.tsx) | Notification open/read/dismiss/Retry, View all→Operations; operation result link/retry/cancel | Correct owner/deep-link result, no duplicated start, missing/error/long reconnect, announcements/focus; operation utility is not a new notifications page. Operations/shell; H. |
| [Dashboard/report owner](../../../../job-tracker-ui/src/components/DashboardView.tsx) | Five checkbox flags, month buttons, snapshot/trends Retry, exact-value details, Jobs/Offers and workflow attention links, onboarding actions | Audit owner-local flags vs language-save endpoint, exact existing denominators, loading/error independent states, link destinations and all-hidden fallback. **P5-06-O01 observed language-preference 500 during reads remains unresolved.** Reports/identity; H. |
| [Jobs/Trash](../../../../job-tracker-ui/src/components/JobTable.tsx), [saved views](../../../../job-tracker-ui/src/components/SavedViewsMenu.tsx) | Filters/sort/page/size/columns/density/view switch, row/card actions, selected bulk status/soft-delete/restore, edit, Settings data link | Correct selected scope/partial failure, no row open from nested action, dirty/Back/focus, all-result parity, native persisted restore and readable long EN/NB. Jobs/API; H. |
| [Board](../../../../job-tracker-ui/src/components/KanbanBoard.tsx) | Card/workflow entry, pointer/keyboard move, exact-status menu, collapse/group states | Keyboard pickup/drop/cancel, failed move retained, custom-stage group, physical touch/native drag and scale; preserve API raw status identity. Jobs; H. |
| [Workspace](../../../../job-tracker-ui/src/views/ApplicationWorkspacePage.tsx) | Back/edit, seven sections, Application CV/letter/answers/submission, Timeline activity/correspondence, Documents shortcuts, Notes edit/checklist/calendar | All source-defined destinations and disclosures, legacy key priority, source/archived distinction and independent draft guards. **followMode mode-specific compose UI remains deferred; metadata is not action fulfillment.** Workspace/mail; H. |
| [Workspace assets](../../../../job-tracker-ui/src/components/ApplicationAssets.tsx), [attachments](../../../../job-tracker-ui/src/components/Attachments.tsx) | Attach/create/copy/detach/tailor CV, manual/AI letter review/save/history, draft save, package capture/detail/archive download, attachment consent/upload/rename/delete | CV source/variant/sibling ownership, reject no-write, dirty Cancel, frozen bytes after mutation/delete, actual upload/download/error; capture is not send. Workspace/storage/AI; H. |
| [Career](../../../../job-tracker-ui/src/views/CareerProfilePage.tsx) | Overview/structured profile/evidence/import, fields/raw copy/history restore, upload/extract/diff/select/accept/discard/retry/cancel | Canonical scope, low-confidence review, source navigation, long-tail/mobile save, no silent overwrite and interrupted operation behavior. Career/extraction; H. |
| [CV library](../../../../job-tracker-ui/src/views/CvBuilderPage.tsx), [editor](../../../../job-tracker-ui/src/views/CvBuilderEditor.tsx), [settings](../../../../job-tracker-ui/src/components/cv/CvCustomizeTab.tsx) | Create/copy/delete/templates/publish/share/PDF; Content/Template/Customize/AI Tools/History; source/override/reset/reorder/visibility; undo/redo/save retry/conflict recovery; editor/preview return | Retain P5-14 measured/keyboard/pointer cases; every capability control and locked/unsupported/error state, publication old-link revoke, revision/draft/source/sibling/frozen invariants and private/public export. Physical/zoom/manual AT remains open. CV/renderer; H. |
| [CV AI affordances](../../../../job-tracker-ui/src/components/cv/AiSectionAssistant.tsx), [DocumentAiTab](../../../../job-tracker-ui/src/views/CvBuilderEditor.tsx) | Existing section/whole-document assistant controls request generation/accept; Production optional service gives 503 unavailable. P5-13 review frame is unimplemented. | Honest error/entitlement/privacy/metering, no provider/write in Production withheld scope, unchanged unrelated AI. No model/UI/responsive review acceptance until exact return conditions. AI/CV; H. |
| [Inbox](../../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx), [job correspondence](../../../../job-tracker-ui/src/components/Correspondence.tsx), [review](../../../../job-tracker-ui/src/views/GmailReviewPage.tsx) | Inbox filters/page/detail/source/link, compose/reply/drafts/confirm send, uncertain new attempt, job manual log/import, Gmail thread/link/move/unlink/sync, reviewed proposed jobs | Native drafts/revisions/context, no automatic resend/create, no log/send conflation, approved sandbox provider/reconnect/attachment proof and human AT; mail-phase followMode remains outstanding. Mail/API; H. |
| [Settings](../../../../job-tracker-ui/src/components/SettingsView.tsx), [backup](../../../../job-tracker-ui/src/components/BackupCard.tsx), [Connections](../../../../job-tracker-ui/src/components/EmailProviderConnections.tsx) | Tabs/mobile selector; rules/scenario/notification retry, table/theme/language, import/export, privacy/usage/plans, ZIP/backup/deletion confirmation, connection grants/revoke | Correct save owner and dirty tab lifetime; retained notification concurrency 500/rules observation/language 500 investigation, configured billing/deletion/restore guards; provider/production work separately authorized. Settings/API/identity; H. |
| [Companies](../../../../job-tracker-ui/src/components/CompaniesTable.tsx), [Offers](../../../../job-tracker-ui/src/views/OfferComparisonPage.tsx), [Discovery](../../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx) | Contact/company edit/delete/history/source links, recorded offers/notes/deadline, discovery search/source/sort/detail/save searches/run/pause/delete/dismiss | Durable company modal error P4-02-D02, safe source URLs, native contact/date/saved-search persistence and narrow many-offer/long result traversal. Domain/accessibility; H. |
| [Admin Users](../../../../job-tracker-ui/src/views/AdminUsersPage.tsx), [Audit](../../../../job-tracker-ui/src/views/AdminAuditPage.tsx), [System](../../../../job-tracker-ui/src/views/AdminSystemPage.tsx) | Role/create/reset/delete, permitted undo/restore, SMTP/probes/benchmarks/maintenance/diagnostics | API role/last-admin/self/recent-auth gates, mounted revoke, persisted successful actions and safe sensitive output. Actual provider/production actions are outside this plan. Admin/operations; H. |
## Evidence required before a later acceptance decision
Run the agreed applicable regressions at a named source only after execution is authorized; associate each route/visible-action outcome with the original PRES sub-workflow, role/owned fixture, URL/query/state, request/no-write assertions, viewport/theme/locale and focus result. Capture direct entry, refresh, Back/Forward, legacy alias, loading/empty/error/locked state, missing/foreign record, dirty Cancel/Discard and account switch where relevant. Audit human screen-reader names/live announcements, physical touch/software keyboard, 200%/400% zoom, forced colours and text spacing rather than substituting axe incompletes or emulated taps.
The source limitations above are future audit inputs, not fresh regression failures or approval to change semantics. Preserve [recorded deferred scope and open issues](../OPEN_BLOCKERS.md). Current deployment/ingress/backup/schema/configuration/rollback/protected CI and actual deployed route acceptance remain NOT VERIFIED under the separate [production NO-GO](../production-release-decision/README.md). This plan does not close P5-15 or authorize implementation, suite execution, provider calls or release.