Skip to content

fix(a11y): add focus trap to mobile navigation drawer#1

Closed
NaitikVerma6776 wants to merge 180 commits into
mainfrom
cursor/focus-trap-mobile-sidebar-9bb6
Closed

fix(a11y): add focus trap to mobile navigation drawer#1
NaitikVerma6776 wants to merge 180 commits into
mainfrom
cursor/focus-trap-mobile-sidebar-9bb6

Conversation

@NaitikVerma6776

Copy link
Copy Markdown
Owner

Description

Adds a keyboard focus trap to the mobile navigation drawer in AppShell.tsx. When the drawer is open, focus stays inside it, Escape closes it, and focus returns to the hamburger button on close.

Related Issues

Closes utksh1#821

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Changes

  • Trap Tab/Shift+Tab focus within the mobile navigation drawer
  • Move focus into the drawer on open and return it to the hamburger on close
  • Add drawer ARIA attributes (role="dialog", aria-modal, aria-expanded, aria-controls)
  • Preserve the existing sidebar-state-changed event-based sidebar sync

How Has This Been Tested?

  • npm run test -- testing/unit/components/AppShell.test.tsx (13 tests passing)
  • npm run typecheck
  • npm run quality
  • npm run build

Checklist

  • My code follows the code style of this project.
  • I have performed a self-review of my own code.
  • My changes generate no new warnings.
Open in Web Open in Cursor 

ded-furby and others added 30 commits June 2, 2026 23:54
Fixes malformed Markdown code fences in the Tasks API pagination examples.
Adds unit coverage proving malformed persisted Findings review state does not break rendering.
Updates the frontend Vitest dev dependency and lockfile to resolve the dev dependency vulnerability tracked in issue utksh1#458.
Adds scanner network egress policy enforcement, protected admin network-policy endpoints, Docker network setup for sandboxed execution, audit logging, deployment documentation, and focused backend coverage.
Ensures frontend API request timeout handles are cleared when fetch rejects or aborts, with focused tests for cleanup paths.
Encode task pagination query parameters with backend coverage.
Add report comparison UI and finding diff utility with frontend unit coverage.
…tksh1#483)

Add backend notification delivery service with webhook/email placeholder support, dedupe, redacted payloads, and unit coverage.
…1#484)

Add owner scoping for tasks/findings/reports, cache namespacing, and cross-user authorization coverage to address BOLA access.
Validate task status filters, return clear 400 responses for invalid values, and align pagination coverage with the stricter validation.
POST /api/v1/workflows/scheduler/tick was the only execution endpoint
without a rate limiter. Any API key holder could call it in a tight loop,
triggering every enabled workflow on each tick with no throttling, which
bypasses the scheduling interval and can exhaust scan quotas or flood the
task queue.

Added a scheduler_tick_limiter following the existing EndpointRateLimiter
pattern used by every other execution endpoint. The bucket is configured
through new settings (rate_limit_scheduler_tick_limit and
rate_limit_scheduler_tick_window), defaulting to one tick per 10 seconds,
which permits legitimate external triggers while blocking runaway loops.
The limiter is registered in reset_all_endpoint_limiters so test isolation
and admin resets clear its history alongside the other buckets.

Added a route-level integration test that mocks scheduler.tick and asserts
the second call within the window is rejected with 429.

Closes utksh1#474
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
…utksh1#593)

* fix: wrap bulk delete in transaction for atomicity (issue utksh1#402)

- Add begin(), commit(), rollback(), execute_no_commit() to Database class
- Wrap delete_task_records DELETE statements in a transaction so a
  mid-way failure rolls back instead of leaving orphaned records
- Re-check running status INSIDE the transaction to prevent the
  race where a task starts running between the check and the delete
- Add atomicity regression tests verifying no partial deletion occurs
  when running tasks are present, and that all associated records
  (findings, reports, audit_log) cascade correctly

* fix test mocks for transaction-based delete_task_records

Update unit test mocks in test_bulk_delete_sqlite_limit.py to account
for the new transaction support in delete_task_records():
- Add mock_db.fetchone (running-task re-check inside transaction)
- Add mock_db.execute_no_commit (deletes now use this instead of execute)
- Add mock_db.begin/commit/rollback (transaction lifecycle)
- Update empty-list test to verify no transaction methods are called

---------

Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
…ksh1#254) (utksh1#592)

Co-authored-by: Pragati <Pragati5-DEBUG@users.noreply.github.com>
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* ci: extend artifact guard to cover output/ scan exports

Closes utksh1#586

- Added output/, data/raw/, data/reports/, backend/data/raw/,
  backend/data/reports/, and logs/ to BLOCKED_PATTERNS in
  check-artifacts.sh
- Updated check-artifacts.yml trigger paths to include output/**,
  data/**, backend/data/**, and logs/**
- Both tracked-file and PR-diff checks now cover scan exports

* fix(ci): allow .gitkeep files and remove committed PDF exports

- Remove tracked scan PDF exports from output/pdf/ that should never
  have been committed
- Allow .gitkeep placeholder files through the artifact guard in both
  the tracked-file check and PR-diff check

* fix(ci): only flag added files in PR diff, not deletions

--diff-filter=A ensures the artifact guard does not incorrectly block
PRs that are removing committed artifacts from the repo

---------

Co-authored-by: siddiqui7864 <siddiqui7864@github.com>
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* Propagate cancellation to full process trees

Adds _terminate_process_group() which sends SIGTERM to the entire OS
process group of a spawned scanner, waits a configurable grace period
(default 5 s, _CANCEL_GRACE_SECONDS), then escalates to SIGKILL if the
group has not exited. This kills every child and grandchild spawned by
the scanner, leaving no orphan processes after cancellation or timeout.

All create_subprocess_exec calls in _execute_command now pass
start_new_session=True so each scanner gets its own session and process
group, making killpg safe to call against just the scanner's group.

_process_pids: Dict[str, int] tracks the PID of each running task so
cancel_task() can terminate the full group before cancelling the
asyncio.Task. The dict entry is cleared in the execute_task finally
block alongside running_tasks.

Timeout and CancelledError paths in _execute_command call
_terminate_process_group instead of process.kill(), then await
process.wait() with a 3 s cap to confirm the root process exits.

Fixes utksh1#216

* Clear _process_pids in _execute_command on every exit path to prevent stale PID reuse

---------

Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* feat(notifications): add Settings UI for alert rules (PR 5 of utksh1#254)

* fix(ci): remove trailing blank line in SettingsNotifications test

* fix(frontend): stabilize Settings theme test after notification UI

---------

Co-authored-by: Pragati <Pragati5-DEBUG@users.noreply.github.com>
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* feat: virtualise Findings, Scans, Reports with @tanstack/react-virtual (utksh1#234)

* fix: rewrite Scans.test.tsx for paginated Scans.tsx with ConfirmModal

* fix: add missing getCurrentTimeZone to date mock in Findings.test.tsx

* fix: fix TypeScript type errors in Findings.test.tsx date mock and ResizeObserver polyfill

* chore: remove Scans.test.tsx — will be submitted in separate PR

* fix: use sortedFindings for selection and keyboard nav; add sorted-order ArrowDown test

---------

Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* Add database-backed workflow run history and rollback

Persists every workflow run as a workflow_runs row and every workflow
update as a workflow_versions snapshot, enabling operators to audit past
executions and roll back a workflow to any prior definition.

Schema additions (migration 006 + _create_schema):
  workflow_versions (id, workflow_id, version_number PER workflow,
    definition_json, created_at, created_by)
  workflow_runs (id, workflow_id, version_id FK, version_number,
    triggered_by, status, task_ids_json, started_at, completed_at,
    error_message)

New Database methods:
  snapshot_workflow_version(wf_id, name, schedule_seconds, enabled,
    steps, created_by) — inserts a full definition snapshot with a
    monotonic per-workflow version_number.
  get_workflow_versions(wf_id) — all versions newest-first.
  get_workflow_version(wf_id, version_number) — single version or None.
  record_workflow_run(wf_id, version_id, version_number, task_ids,
    triggered_by) — inserts a run row and returns its ID.
  get_workflow_runs(wf_id, limit, offset) — paginated run history with
    task_ids deserialised from JSON.

Route changes:
  PATCH /workflows/:id — snapshots a new version on every successful update.
  POST /workflows/:id/run — records a run row attributed to the active version.
  GET  /workflows/:id/runs — paginated run history for a workflow.
  GET  /workflows/:id/versions — all version snapshots newest-first.
  POST /workflows/:id/rollback/:version_number — restores the live workflow
    to the target version and records a new snapshot tagged
    rollback_to_vN so the action is auditable and itself reversible.

Fixes utksh1#225

* Add workflow run lifecycle: queued→completed/failed/cancelled

Adds a background finalizer (_finalize_workflow_run) that polls task
statuses after run_workflow_once() and updates the run row to
completed, failed, or cancelled once all tasks reach a terminal state.
Falls back to failed after 1 h if tasks remain in-progress.

Adds three Database methods:
  finalize_workflow_run(run_id, status, error_message) — sets status +
    completed_at on a run row.
  check_workflow_run_tasks(run_id) — inspects all task statuses for the
    run and returns the appropriate terminal status, or None if tasks
    are still in progress.

Changes default status from 'pending' to 'queued' (accurately reflects
that tasks are enqueued — not that execution is in progress) in both
_create_schema and migration 006.

Adds 7 new tests covering: finalize to completed/failed/cancelled,
error_message persistence, check_workflow_run_tasks with empty/running/
completed/failed task sets.

---------

Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* feat(security): add pip/npm dependency audit CI policy with tests

* Final changes.

* docs: fix audit config guide link

---------

Co-authored-by: Utkarsh <Utkarsh@192.168.1.2>
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* fix(task-details): add memory leak and race condition protections

* Refactor isMounted handling in TaskDetails and FindingDrawer

fix(task-details): move isMounted cleanup to TaskDetails component

---------

Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* Updated PLUGINs.md file. Issue-utksh1#550

* docs: use repository-relative link for plugin-validation in PLUGINS.md

---------

Co-authored-by: Utkarsh Singh <jee60101@gmail.com>
* fix(ci): resolve backend lint F821 and stale frontend test mocks

Two separate CI regressions were introduced by commits 0e03877 and a2a7e02:

Backend lint (F821 - Undefined name 'db')
  workflows.py._run_workflow() calls get_target_policy(db, ...) but 'db'
  was never acquired in that method. tick() obtains 'db' but does not
  pass it into _run_workflow(). Fixed by adding db = await get_db() at
  the top of _run_workflow().

Frontend unit test failures (3 tests)
  ToolConfig.tsx now calls listTargetPolicies(), listCredentialProfiles(),
  and listSessionProfiles() inside its useEffect via Promise.all. Tests
  that only mocked the original 3-4 API functions caused Promise.all to
  reject (unmocked vi.fn() returns undefined, not a Promise), making
  setServerLimits never execute and breaking max/min attribute assertions.

  Workflows.tsx changed emptySteps to include an execution_context object
  in each step. The createWorkflow assertion expected the old shape.

Fixes applied:
  - ToolConfigDynamic.test.tsx: add listTargetPolicies, listCredentialProfiles,
    listSessionProfiles, getSettings to vi.mock factory and beforeEach mocks;
    update startTask assertion to accept the new 5th executionContext argument
  - ToolConfigTimeout.test.tsx: add the three new API functions to vi.mock
    factory and beforeEach mocks so Promise.all resolves correctly
  - Workflows.test.tsx: update createWorkflow expectation to include
    execution_context in the steps array

* fix(ts): add total field to NamedResourceList mocks for TypeScript compliance

{ items: [] } was inferred as { items: never[] }, which does not satisfy
NamedResourceList<T> (requires items: T[] and total: number). Added total: 0
to all three mock returns so TypeScript accepts the fixture without casting.
anshul23102 and others added 27 commits June 16, 2026 20:50
…h1#687)

* test(crawler): add contract and parser coverage for crawler plugin

Add backend test suite for the crawler plugin that loads the real
plugins/crawler/metadata.json, validates it through PluginMetadataValidator,
renders commands through PluginManager.build_command(), and calls the real
plugins.crawler.parser.parse() directly.

Assertions are tied to the actual plugin contract:
- engine.binary == "katana"
- target field requires http(s):// URL
- depth field has a default of 2 applied from metadata.json
- explicit depth override works correctly
- full command token sequence from real command_template
- severity classification: high for critical/injection, low for found/exposed
- required keys in each finding dict
- items list matches the parsed output lines

Tests will fail if metadata.json, command_template, or parser.py drift.

Closes utksh1#494

* test(crawler): assert token-drop behavior for missing target

build_command drops the unresolved {target} token instead of returning None.
Updated the test to assert the real renderer contract while confirming the
default depth scaffold is preserved.

* test: add parser and contract coverage for plugin domain-finder

- Add metadata validation tests for domain-finder plugin
- Add command rendering tests via PluginManager
- Add parser contract tests with realistic fixtures
- Verify plugin loads correctly through plugin system
- Ensure parser handles severity classification
- Validate empty output and raw line preservation

Closes utksh1#496

* fix: use importlib for domain-finder parser import (hyphenated directory name)

Domain-finder directory has a hyphen in its name, which Python's standard
import system cannot handle. Use importlib.util to load the parser module
directly from the file path instead.

* fix(tests): enhance localStorage mock to support Object.keys() iteration for nuclear purge test

The custom jsdom localStorage mock did not properly implement iteration,
causing Object.keys(localStorage) to fail in SettingsSaveReset.test.tsx.
Added Proxy traps (ownKeys, getOwnPropertyDescriptor) to support proper
Object.keys() enumeration, allowing the nuclear purge test to pass.
…utksh1#857) (utksh1#1008)

Add a minimal, representative multi-result fixture spanning
  several S3 buckets, an Azure Blob container, and a GCS bucket with mixed severities, plus focused tests asserting one finding per line, in-order raw preservation,
  multi-provider coverage, distinct identifier survival, and per-line severity classification with no cross-line bleed.

Parser logic is unchanged; this is
  fixture/coverage only.
…ator (utksh1#1005)

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
* test(ci): validate parser capability groups(utksh1#876)

* test: align parser capability groups

* fix(ci): add parser capability matrix
…h1#1024)

- update dir_discovery metadata wordlist field guidance

- expand wordlist README with usage guidance

- add dir_discovery plugin tests + extend plugin unit tests
…tksh1#1026)

* feat(reporting): Implement core backend report generation

Introduce core exporters (HTML, PDF, CSV, SARIF) and dedicated unit tests verifying core report generation. Add severity border color styling to findings cards.

* feat(reporting): Add severity distribution chart generation

Introduce PIL-based severity bar chart generator and embed it in the HTML report Executive Overview. Add unit tests for the chart generator.
…ck and optimistic lock (utksh1#992)

* fix: prevent task deletion race condition (TOCTOU) with in-memory check and optimistic lock

- Add running_tasks in-memory check to single-task delete endpoint,
  matching the existing protection in bulk_delete_tasks
- Add optimistic DB lock in execute_task that verifies the task is
  still QUEUED before transitioning to RUNNING, aborting silently if
  the task was already deleted

* fix: return cursor from Database.execute and execute_no_commit for rowcount access

* test: add regression tests for task deletion race fix

- Make Database.execute() return the cursor so callers can inspect rowcount
- Add test_execute_task_aborts_when_task_no_longer_queued — verifies the
  optimistic UPDATE ... WHERE status='queued' returns rowcount 0 when the
  task is already running, preventing double-execution
- Add test_execute_task_aborts_when_task_deleted_before_running — verifies
  abort when the task row is deleted before the optimistic lock fires
- Add test_delete_task_rejected_when_in_executor_running_tasks — verifies
  the in-memory running_tasks check in delete_task rejects deletion during
  the race window where executor holds the task but DB still says 'queued'

---------

Co-authored-by: ionfwsrijan <ionfwsrijan@users.noreply.github.com>
… notification rule CRUD (utksh1#993)

* fix: prevent Broken Object Level Authorization (BOLA) in workflow and notification rule CRUD

- Add owner_id column to workflows and notification_rules tables with
  migration support for existing databases
- Change workflows.name UNIQUE constraint to composite UNIQUE(owner_id, name)
  to allow same-named workflows across different owners
- Add owner parameter to all workflow CRUD endpoints (list, create, update,
  delete, runs, versions, rollback) and verify ownership before operations
- Add owner scoping to all notification rule endpoints (list, create, get,
  update, delete)
- Fix workflow scheduler to use the workflow's owner_id instead of
  DEFAULT_OWNER_ID for rate limiting and task creation

* test: add owner_id to mock workflow data in tick rate limiting tests

* fix: replace UNIQUE(name) with UNIQUE(owner_id, name) on legacy SQLite DBs

- Add safe migration path: detect old inline UNIQUE(name) constraint on
  the workflows table and recreate the table with the composite unique
  constraint UNIQUE(owner_id, name) — SQLite cannot ALTER constraints.
- Add comprehensive integration tests for cross-owner isolation:
  * Same-name workflows allowed across different owners
  * Workflow list/get/update/delete/run/runs/versions/rollback all
    return 403 for non-owners, 200 for owners
  * Notification rule list/get/update/delete return 403 for non-owners,
    200 for owners
  * Missing resources return 404, not 403
  * Owner retains full access to own resources

---------

Co-authored-by: ionfwsrijan <ionfwsrijan@users.noreply.github.com>
)

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
…ksh1#1038)

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
…#1034)

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
)

* test: add edge case tests for redact_inputs type dispatch

* test: address review feedback on redact_inputs edge cases

---------

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
)

* test : add unit tests for crawler surface-parsing helpers

* test: trim crawler surface-parsing tests to only missing cases

After PR utksh1#979 merged comprehensive crawler helper coverage, this file held
largely-duplicate tests. Replace the bulk of the file with only the cases
not already covered by test_crawler_helpers.py:
  - _extract_title with unclosed <title>
  - _extract_tech_hints dedup across multiple header channels
  - _extract_cms_hints dedup across channels
  - _classify_path_hint for /user/login (login category token)
  - _normalize_form for DELETE method (state_changing)
  - _normalize_form tolerates a non-dict entry in the inputs list

---------

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
…h1#1007)

* test : add unit tests for routes JSON deserialization helpers

* ci : trigger re-run

* refactor: extract routes JSON deserialization helpers into import-safe module

Move parse_json_fields, FINDING_JSON_FIELDS, deserialize_finding_rows and
deserialize_asset_service_rows out of routes.py into a new small module
routes_json_helpers.py so unit tests can import and exercise the real
production functions without pulling in the heavy routes.py import chain
(FastAPI, reporting, xhtml2pdf).

routes.py re-exports the helpers so all existing call sites and downstream
imports keep working unchanged.

The dedicated unit test file now imports from routes_json_helpers directly,
so a regression in the actual implementation is caught by these tests instead
of testing frozen copies that could silently drift.

---------

Co-authored-by: tmdeveloper007 <tmdeveloper007@users.noreply.github.com>
…ontent (utksh1#900)

* fix: prevent mobile navigation menu from overlapping page content

Use opaque design-system backgrounds, raise overlay z-index, lock body scroll when the drawer is open, and add tests for backdrop close and scroll lock.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: update pr description format

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…dependencies (utksh1#1059)

* feat(security): Exception definitions for esbuild and vite to pass audit gate

* fix(security): resolve Vite and esbuild vulnerabilities by upgrading dependencies
Keep the existing sidebar-state-changed event listener and scope the
change to AppShell focus management, drawer ARIA attributes, and tests.

Co-authored-by: Naitik Verma <naitikverma5207@gmail.com>
@NaitikVerma6776 NaitikVerma6776 self-assigned this Jun 19, 2026
@NaitikVerma6776 NaitikVerma6776 deleted the cursor/focus-trap-mobile-sidebar-9bb6 branch June 19, 2026 16:47
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.

[FEAT] Add focus trap for mobile sidebar navigation