Skip to content

Complete canonical frontend deep-link and operator parity #156

Description

@alexeygrigorev

Complete canonical deep-link and operator parity

Status: pending — groomed and ready for implementation
Tags: bug, portal, frontend, testing, design, P0
Parent: #148
Depends on: None
Blocks: final deployed acceptance in #155 and closure of #148
Next owner: Software Engineer

Scope

Correct the post-cutover canonical UI in top-level frontend/ at current main 36d446c. Complete the existing hash-route adapter, entity loading/history behavior, mobile Inbox triage, and the small missing operator controls below. Use the existing authenticated work APIs and shared browser-cookie login/logout flow; this is not a new router, shell, data model, or information-architecture project.

Deployment blockers #136/#143 do not block local implementation, review, merge, or source CI. After this source fix is integrated, #155 owns normal deployed verification at the corrected SHA.

Supported route matrix

These are the only supported workspace hash paths. Entity parameters are optional; without one, the route opens its list/surface.

Route Required behavior
#/ Home
#/inbox?intakeId=<id> Inbox; exact intake detail
#/tasks?taskId=<id>&date=<YYYY-MM-DD>&bundleId=<id>&contextBundleId=<id> Task queue; date sets the date, bundleId filters the queue, taskId opens the exact task, and contextBundleId shows the independent return/workflow context; preserve valid combinations
#/bundles?bundleId=<id>&taskId=<id> Exact workflow; optional exact task within that workflow
#/assistants?assistantJobId=<id> Assistant list; exact job detail
#/templates?templateId=<id> Runtime-template list; exact template detail/editor
#/recurring Templates surface focused on recurring operations
#/artifacts Artifacts surface
#/notifications Home with Notifications panel open
#/bookkeeping Bookkeeping
#/sponsors?bookingId=<id> Sponsors; exact booking detail
#/newsletter Newsletter
#/calendar Calendar
#/mailing-exports Mailing exports
#/processes Process Docs
#/admin Admin
#/users Users

Use URLSearchParams/encoded values and safe text rendering. A single trailing slash may normalize to the table form. Unsupported query keys are discarded. Empty hash, unknown paths, malformed path/query encoding, invalid dates, and structurally invalid parameter combinations normalize with replaceState to /#/ without adding a history entry, losing the authenticated session, or rendering route input as HTML.

Acceptance Criteria

Routes, entities, and browser history

  • Fresh navigation, refresh, hashchange, Back, and Forward resolve every row and valid parameter combination in the matrix inside the one canonical shell; UI state and URL never diverge or create navigation loops.
  • Operator-initiated list selection, close/back, notification launch, search result, and task/workflow/intake/assistant/template/sponsor relationship navigation write the canonical URL with pushState; normalization alone uses replaceState.
  • Entity context is applied only after its required data resolves. A requested intake outside the active filter still opens that exact item.
  • A stale or 404 intakeId, taskId, bundleId, assistantJobId, templateId, or bookingId shows an entity-specific, focusable not-found state with the requested ID as text plus Retry and Return-to-list actions. It never selects the first row, opens another record, leaves a generic loading panel, or reports a non-404 API failure as “not found.”
  • Combined task/workflow links preserve date, queue bundleId, and independent contextBundleId; #/bundles?...&taskId=... reports a task/workflow mismatch instead of silently substituting context.
  • Signed-out page navigation and visible Sign out use the shared browser-cookie /login and /logout flow. /api/* and /work/api/* continue to return JSON 401, never SPA HTML or a browser bearer-token path.

Mobile Inbox and readable history

  • Inbox has one visible page heading. At 390x844 it shows item status/context and one state-appropriate primary action before secondary controls; choosing an action reveals only its required fields, while secondary and destructive actions live in labelled keyboard-operable disclosures.
  • State behavior is explicit: new/triaged items prioritize Convert or Attach; blocked items prioritize due Follow-up sent or Response received; attached/converted/assistant-ready items prioritize their linked task/workflow/assistant continuation; duplicate/ignored/archived items are a read-only resolution summary. Invalid backend transitions are not presented as available actions.
  • Mutation controls prevent double submission, keep inline validation/API/conflict errors with the selected item, move focus to the error/status, and retain entered values for retry.
  • History uses operator language instead of raw action codes, renders parseable absolute Europe/Berlin date/time in a <time datetime> (relative copy may supplement it), and includes useful actor/reason/waiting/follow-up/relationship context without dumping raw metadata. Order is labelled and deterministic.
  • At 1440x900 and 390x844, Inbox queue/detail, disclosures, history, route not-found states, panels/dialogs, and close/back controls have no horizontal overflow, overlap, clipping, or unreachable keyboard action.

Small operator parity controls

  • Sign out is visible and keyboard accessible in desktop and mobile Settings, identifies the current action clearly, and invokes /logout without exposing session material.
  • Each notification has a labelled Dismiss action using the existing authenticated API. Success removes only that item and updates both bell counts; failure remains visible/retryable; activating Dismiss never also opens the linked task.
  • Recurring rows clearly distinguish Pause/Resume from Delete. Delete requires a labelled confirmation explaining that it removes only the schedule, not generated tasks; a successful unreferenced delete refreshes the list, while the existing 409 generated-history response tells the operator to Pause instead and preserves the row.
  • Changed states have correct heading order, names/roles, aria-current/expanded/live semantics, modal focus trap/restore, visible focus, and keyboard operation, with zero critical/serious WCAG A/AA violations in the automated affected-state scan.

Test Scenarios

Scenario: Complete route and history matrix

Given: deterministic real-API fixtures for every entity parameter
When: each route/combination is opened fresh and the operator follows relationships, closes detail, and uses Back/Forward/hash changes
Then: the exact entity, visible context, URL, focus, and history entry are synchronized

Scenario: Invalid route and stale entities

Given: unknown/malformed routes plus stale, filtered-out, mismatched, and non-404-failing entity requests
When: routing/data loading finishes
Then: malformed routes replace-normalize to Home, the filtered-out item opens exactly, and stale/mismatch/failure states stay honest and recoverable without fallback selection

Scenario: State-based mobile Inbox

Given: new, triaged, blocked-due, blocked-future, attached, converted, assistant-ready, and resolved fixtures at 390x844
When: the operator performs each available next action by keyboard and touch-sized controls
Then: only valid state-based actions/fields are exposed, mutations use the real API once, and humanized history/state remain readable without overflow

Scenario: Operator controls

Given: an authenticated session, task-linked notifications, and referenced/unreferenced recurring configs
When: the operator signs out, dismisses a notification, and attempts both recurring deletions
Then: shared logout is used, dismissal/counts are correct, unreferenced deletion succeeds, and referenced deletion explains Pause without data loss

Required Verification

Use the normal test server/in-memory DynamoDB path; request interception, mocked route payloads, source-string markers, and screenshots without behavior assertions do not count.

  • Focused route-normalization/entity/history tests plus Playwright assertions for every matrix row and valid combination.
  • Real API/browser coverage for stale 404 versus other failures, filtered Inbox selection, notification dismissal, recurring DELETE 204/409, and shared logout/auth JSON semantics.
  • Automated accessibility scan plus keyboard/focus assertions for route not-found, Inbox disclosures/actions/history, Settings, Notifications, and recurring confirmation/error.
  • npm --prefix backend test
  • npm --prefix backend run typecheck
  • npm --prefix backend run build
  • npm --prefix backend run test:e2e
  • uv run --project lambda-functions --extra search --with pytest python -m pytest tests/docs_app

Tester captures and reads these exact sanitized viewport screenshots under .tmp/screenshots/issue-156/:

  • desktop-task-combined-context-1440x900.png
  • desktop-entity-not-found-1440x900.png
  • desktop-inbox-blocked-actions-history-1440x900.png
  • desktop-settings-sign-out-1440x900.png
  • desktop-notification-dismiss-1440x900.png
  • desktop-recurring-delete-guidance-1440x900.png
  • mobile-task-combined-context-390x844.png
  • mobile-entity-not-found-390x844.png
  • mobile-inbox-new-primary-390x844.png
  • mobile-inbox-blocked-follow-up-history-390x844.png
  • mobile-settings-sign-out-390x844.png
  • mobile-notification-dismiss-390x844.png
  • mobile-recurring-delete-guidance-390x844.png

Architect reviews route/auth/history boundaries; Designer reviews both viewport sets and progressive disclosure; then Tester and PM gates run.

Lifecycle Gates

  • Software Engineer implementation, uncommitted
  • Architecture PASS
  • Designer PASS with screenshot findings
  • Tester PASS with commands, exit codes, counts, accessibility results, and screenshots
  • PM ACCEPTED
  • Software Engineer commit with Closes #156
  • Orchestrator local merge and push
  • On-Call source CI/CD PASS
  • Verify the canonical frontend through normal DataOps deployment #155 normal deployed acceptance rerun at the integrated SHA

Out of Scope

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Must havebugSomething is brokendesignDesign and UXfrontendFrontend UIportalShared portal shell and UXtestingTests and QA

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions