Skip to content

Commit 485e5ca

Browse files
atulmguptaCopilot
andauthored
Phase 46 prompt 99 execution gate (#62)
* phase-46/01-error-reporting: capture window/promise/react/query errors and ship to /api/v1/web-errors Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/02-abort: thread AbortSignal through request() and every useQuery, audit script enforces Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/03-tableid-sweep: assign tableId to every DataTable caller, audit gate enforces Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/04-maintenance: add SystemMode + maintenance banner across stack with admin override Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/05-session-timeout: idle countdown + hard-401 modal preserve return URL and surface unsaved drafts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/06-active-filter-chips: visible chip summary above every FilterBar Adds shared ActiveFilterChips + useActiveFilterChips so users see what they have filtered without re-opening every control. Sweeps all FilterBar callers (admin/audit, alerts, alert log, drives, charging sessions, tesla charging history, locations, geofences, notifications) and mounts the chip strip immediately after the bar, wired to URL-state setters. A new audit:filterbar-chips script is chained into npm run lint to keep the pairing enforced. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/07-top-progress: top route-change progress bar with Suspense bridge and motion-token transitions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/08-feedback: in-app feedback modal with admin queue and optional GitHub Issues bridge Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/09-search-history: SearchInput remembers recent searches per scope with dropdown UX - NEW lib/searchHistory.ts: localStorage v1 store, scoped, capped 12, dedup case-insensitive, min 2 chars, trim — matches commandFrecency resilience contract (handles malformed JSON, non-object payloads, malformed entries). - EXTEND components/forms/SearchInput.tsx with optional historyScope, showHistoryOnFocus, maxHistory props. Dropdown shows when input is focused with empty value and the scope has entries; supports click-to-fill, per-entry remove (X), 'Clear history', and full keyboard nav (ArrowDown, ArrowUp, Enter, Escape) with combobox/listbox ARIA semantics. - ADOPT historyScope on 9 list-page SearchInput callers: drives, charging, charging:sessions, notifications, locations, geofences, alerts:logs, alerts, admin:audit. KeyboardShortcutsModal and AlertStudioPage modal inputs intentionally skipped (transient panel filters, not list searches). - ADD i18n keys search.history.title, .clear, .removeAria. - Drive-by: drop two stale eslint-disable-next-line directives in components/feedback/__tests__/FeedbackModal.test.tsx so the lint gate passes (no-console rule is not enabled, leaving the suppressions as dead --report-unused-disable-directives violations). Tests: 26 lib/searchHistory + 16 SearchInput.history; full suite 1727/1727. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/10-mobile-gestures: PullToRefresh + SwipeRow with touch-only opt-in and 5-page adoption Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/11-forced-colors: forced-colors variant + critical-component overrides keep UI visible in Windows high contrast Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/12-visually-hidden: shared VisuallyHidden + useAnnouncer hook + audit gate retire ad-hoc sr-only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/13-chart-a11y: ChartContainer fallback table for SR + forced-colors users with audit-enforced ariaLabel/data props Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/14-combobox: shared WAI-ARIA combobox + multi-select with async option support, replaces hand-rolled selectors Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/15-avatar: shared Avatar + UserCell with deterministic CB-safe colors, refactor chatbot to share Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/16-chart-export: surface PNG/SVG/copy-image actions in every ChartContainer via ChartExportMenu Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/17-marker-cluster: adopt MarkerCluster on locations + navigation + drive maps with audit gate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(web): break FeedbackModal infinite render loop on closed state The cleanup useEffect listed submit (a TanStack Query mutation object) in its dep array. TanStack Query returns a fresh mutation object on every internal state change — including the very submit.reset() call inside the effect — so while the modal was closed the effect re-fired on every render, flooding the console with Maximum update depth exceeded warnings and pinning a CPU. Drop submit from the deps; the reset only needs to fire on the open->closed transition, which [open] alone captures correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/18-deferred-filter: useDeferredFilter on heavy list pages keeps input responsive during list re-render Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/19-quiet-hours: per-user DND windows with bypass severities, dispatcher defers and worker replays Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/20-alert-ack: ack-with-note dialog + alert event timeline + reopen flow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/21-route-announcer: announce SPA navigation to screen readers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/22-route-prefetch: prefetch lazy chunks on link hover/focus Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/23-slider-component: shared Slider + RangeSlider primitives Shared Slider (single-thumb) and RangeSlider (dual-thumb) components built on native <input type=range> so all WAI-ARIA APG slider keyboard semantics (Arrow / PageUp / PageDown / Home / End) work natively, with formatted display values surfaced via aria-valuetext for screen readers. RangeSlider stacks two range inputs with pointer-events:none on the track and [&::-webkit-slider-thumb]:pointer-events-auto on the thumbs, swaps z-index based on thumb position so collisions stay grabbable, and sorts the [low, high] tuple in onChange so callers never see an inverted range. Tests are colocated under web/src/components/ui/ to match the gate's allowed-files regex (matches the existing Logo.test.tsx pattern). Adoption sweep skipped per the prompt's Blocked Path: none of the five listed adopter pages have a numeric input that fits a bounded slider model (AlertStudio thresholds are signal-heterogeneous, DriveScore has only date filtering, BatteryHealth has no window picker, GeofenceDrawer uses leaflet-draw, ChargingHeatmap is read-only). Primitives ship now; adopters can land separately when bounded use sites appear. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/24-tag-input: shared TagInput primitive + adoption sweep Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/25-required-fields: visible + aria required indicator on form primitives Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/26-unit-input: shared UnitInput with canonical-metric storage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/27-notification-grouping: group_key column + grouped list view Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/28-notification-bell-popover: in-place triage panel from header bell Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/29-sound-notifications: per-category sound prefs + shared player Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/30-context-menu: shared ContextMenu primitive + 3 adopters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/31-reauth-step-up: sudo-style reauth on sensitive actions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/32-masked-value: privacy primitive + sweep across admin/diagnostic UIs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/33-self-test: aggregated diagnostic endpoint + admin page Adds POST /api/v1/system/diagnostic returning a structured DiagnosticReport that fans out 10 concurrent checks (DB connectivity + migration version, signal_log freshness, Tesla token + circuit breaker, MQTT, Redis, resilience HealthMonitor, runtime goroutines, uptime). Each check has a per-check timeout, panic recovery, and ordered output so the SPA can render a stable list. Endpoint is rate- limited at 20/min/IP. Frontend ships /diagnostic page with Run/Re-run button, per-check cards (status badge, detail, remediation), Copy report (JSON), and Download .txt for support escalation. Empty state CTA also fires the mutation. Page-level App.tsx mounting + Layout.tsx sidebar splice are deferred (out of allowed-files scope) — Sidebar.tsx exports the typed nav entry data for a follow-up splice. Backend tests cover aggregation severity ladder, ordering, per-check timeout, panic recovery, duration measurement, POST-only HTTP, nil- dep tolerance, and breaker-state mapping. Frontend tests cover empty state, run flow, remediation surfacing, copy/download actions, endpoint failure path, and Run→Re-run label flip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/34-live-log-tail: SSE log stream + admin live tail page Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/35-2fa-totp-ui: TOTP enrollment + verification + ReauthDialog tab Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/36-settings-export-import: JSON export + dry-run import + sudo-gated apply Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/37-webhook-channel-ui: webhook channel CRUD + body template + HMAC signing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/38-inline-edit: EditableText primitive + adopt on geofence/rule names EditableText replaces the open-a-Modal-to-rename pattern with inline double-click / Enter / F2 → input → Enter-to-save / Escape-to-cancel. Default display is a button-styled-as-text (native keyboard semantics); custom 'display' render prop lets consumers wrap the value in a Link plus pencil button (used by the alert rule name cell). Single guarded commit path covers Enter+blur dedupe, no-op edits, validation, and async save with Spinner + inline ErrorText on rejection. Successful saves announce '<label> saved' via the shared useAnnouncer(). Adoption deviates from the prompt's listed paths per the Blocked Path: - features/locations/components/GeofenceList.tsx does not exist; adopted in features/maps/pages/GeofencesPage.tsx instead. The per-card name span becomes inline-editable, and a dedicated rename mutation sends a full merged payload (safer than relying on the backend's partial PUT semantics). The Pencil button that opens the full lat/lng/radius modal is left in place as the multi-field path. - features/notifications/components/AlertRuleList.tsx does not exist; adopted in features/notifications/pages/AlertRulesPage.tsx instead. The custom display render prop preserves the existing Link-to-studio navigation and adds a sibling pencil button that calls onStartEdit. Wired to the existing useSaveAlertRule() PATCH path. - Vehicle nickname adoption is dropped: the current VehicleDetailPage has no Modal-based rename and the backend exposes no PATCH /vehicles/{id} endpoint. Both are out of scope for this prompt's allowed-files regex. Tests use fireEvent (no @testing-library/user-event in the repo) per the established TagInput / ContextMenu / SearchInput pattern. Test file is colocated at components/ui/EditableText.test.tsx (not __tests__/) to match the gate's substring allowlist regex. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/39-lightbox: shared Lightbox primitive + vehicle photo gallery adoption Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/40-rate-limit-status-panel: scope budget endpoint + admin status panel Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/41-job-queue-status: queue depth endpoint + admin status panel + drawer Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/42-session-device-management: provider-agnostic local sessions list + revoke Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/43-per-vehicle-settings: hierarchical resolver + per-vehicle override UI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/44-rbac-matrix: permissions catalog + role_permissions table + matrix admin page Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/45-column-reorder: DataTable drag-to-reorder + visibility menu + persistence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/46-impersonate-user: admin impersonation with banner + audit + sudo gate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/47-crash-recovery: draft index + restore prompt across reloads/crashes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/48-rtl-support: i18nDir helper + dir attr + RTL audit + chart label flip Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/49-currency-input: CurrencyInput primitive + locale-aware parse + GeneralSettings adoption Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/50-reset-to-defaults: per-section + global settings reset with sudo gate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/51-recently-viewed-pages: client-side recent pages store + palette + widget Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/52-virtualization-adoption: enable DataTable virtualization on long pages + audit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/53-pause-polling: refetchIntervalInBackground default false + audit + opt-in annotation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/54-photo-upload: vehicle photo upload + EXIF strip + 3-size storage + hero render Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/55-export-adoption: enable DataTable exportable on long-tail list pages + audit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/56-fullscreen-button: shared FullscreenButton + ChartContainer/Map adoption Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/57-auth-mode-contract: provider-agnostic auth mode endpoint + RequiresAuth wrapper Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/58-remove-sidebar-version-badge: drop duplicate DEV chip from sidebar header; canonical version stays in footer VersionSegment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/59-redis-viewer-error-states: surface 503 / network failures in Redis Signal Viewer instead of pretending the cache is empty Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/60-skip-to-content: WCAG 2.4.1 skip link mounted as first focusable element Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/61-tour-replay: Settings -> Product tours panel + per-tour reset/relaunch wiring Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/62-export-columns: optional column allowlist for CSV/JSON exports + picker UI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/63-browser-compat: detect missing modern web features and warn the user once Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: open-mode auth tolerance + /auth/refresh no-op + 000170 collision Resolves four bugs surfaced when running the latest backend in open-mode (AUTH_ENABLED=false) with no Tesla account linked. 1. internal/handler/v1/dashboard_handler.go: GetStats no longer returns 401 when no UserClaims is in the request context. Open-mode is the project's documented default — there is no JWT middleware to populate the context — so the handler now falls back to the empty-string subject (the same scope key used by notification_quiet_hours.user_id, auth_session_handler, and other phase-46 endpoints). 2. internal/api/auth_handler.go::Refresh: when no Tesla account is linked the handler returned 502 Bad Gateway (teslaClient.RefreshTokens fails with 'no refresh token available'). It now reads tokenRepo first and returns 200 {status:noop, reason:no tesla account linked} when there is nothing to refresh, eliminating the console spam from auto-refresh loops in open-mode installs. 3. web/src/lib/resilience.ts + api/auth.ts + api/index.ts: removed the auto-refresh-on-plain-401 logic. It tried to refresh the *Tesla OAuth token* on every non-Tesla 401 (ForwardAuth session expiry, missing user context, etc.), which never helped and produced 502 spam. Plain 401s now go straight to the SessionExpiredModal via maybeDispatchSessionExpired, matching the documented session model (cookie is renewed by the upstream sliding-session proxy on /auth/session polls). Tesla-specific 401s with code TESLA_TOKEN_EXPIRED still flow through the dedicated TeslaReauthBanner path, and the user-initiated 'Refresh Tesla token' button in TeslaAccountSection (useRefreshAuth) still works. 4. migrations/000170_quiet_hours.up.sql: prepended DROP TABLE IF EXISTS notification_quiet_hours CASCADE. Baseline migration 000142 created an earlier per-channel notification_quiet_hours table that was incompatible with the per-user schema in this migration; the IF NOT EXISTS guard silently skipped the CREATE and the subsequent index on user_id then fataled, leaving the DB at dirty=170 on every fresh install. The legacy table was empty in production so the DROP loses no data. Verification: - web: npx tsc --noEmit clean; npm run lint clean (all 22 audits); npx vitest run = 2640/2640 passed (incl. resilience.test.ts). - go: build of internal/handler/v1/... clean; vet of internal/api clean for auth_handler.go. Full repo build is currently broken by an unrelated, in-flight phase-46 prompt (vehicle_handler.go + battery_handler.go + new internal/signal/asof.go); those changes are NOT included in this commit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/64-time-machine: read-only ?as_of= point-in-time view via signal_log + global banner Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/65-scheduled-exports: cron-driven recurring exports with download/email/webhook delivery Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/66-edit-lease: BroadcastChannel-based two-tab edit conflict detection on Settings/Automation/AlertRules Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/67-chart-legend-toggle: click-to-hide series via ChartContainer chartKey + URL-persisted state Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/68-inline-help: HelpIcon primitive + audit script + adoption sweep across 4 settings/admin pages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/69-touch-target: WCAG 2.5.5 forward-looking touch-target audit + .touch-target utility + baseline fixes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/70-cookie-consent: optional cookie/GDPR consent banner gated by TESLASYNC_REQUIRE_COOKIE_CONSENT (default off) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * phase-46/99-execution-gate: phase complete, all 70 prompts merged with green logs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Geofence circle WKT, presets, and UI fixes Add support for circle-shaped geofences and synthesize polygon WKT (circleToPolygonWKT, geofenceCreateRequest, decodeGeofenceWriteBody). Use the decoder in Geofence Create/Update handlers and add unit tests for decoding/round-tripping. Emit latitude/longitude/radius in Geofence.MarshalJSON for the web client. Seed automation presets via registerBuiltins and add registry helpers and tests to validate preset shapes. Fix notification_repo to COALESCE nullable `error` column to avoid NULL scan failures. Frontend tweaks: defensive cache updaters in useNotifications hooks (only mutate array-shaped caches), clamp popover positioning in NotificationBellPopover, adjust AddWidgetButton icon/padding, and refine RecentlyViewedWidget spacing and responsive layout. * Hide auth-gated nav items; UI tweaks Hide auth-gated navigation items when no ForwardAuth identity provider is configured by adding a requiresAuth flag and wiring useIsForwardAuth into Layout and CommandPalette. Update isVisibleNavItem signature/logic and related memo deps to respect the auth mode. Reserve footer space in the sidebar for the fixed StatusBar, adjust PageContainer header/action layout for better responsive alignment, and tweak slider background styles to use --glass-border. Make DataTable stickyHeader default to true (with docs and tests) and add tests to cover the new default and opt-out behavior. * Remove db-refactor prompt log files Delete generated CI/prompt log artifacts under .github/prompts/db-refactor/logs (phases 45 and 46). These are stale/noisy build and test logs and are being removed to reduce repository clutter. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a201040 commit 485e5ca

673 files changed

Lines changed: 98939 additions & 23678 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

β€Ž.github/prompts/db-refactor/logs/phase-45-01-i18n-template-literal-eradication.logβ€Ž

Lines changed: 0 additions & 628 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-02-error-boundary-route-reset.logβ€Ž

Lines changed: 0 additions & 667 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-03-nan-safe-formatters.logβ€Ž

Lines changed: 0 additions & 667 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-04-modal-overlay-consolidation.logβ€Ž

Lines changed: 0 additions & 681 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-05-lazy-route-bundle-smoke-test.logβ€Ž

Lines changed: 0 additions & 710 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-06-settings-broadcast-propagation.logβ€Ž

Lines changed: 0 additions & 694 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-07-sidebar-section-header-typography.logβ€Ž

Lines changed: 0 additions & 695 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-08-light-mode-css-var-parity-revisit.logβ€Ž

Lines changed: 0 additions & 700 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-09-help-tooltip-technical-screens.logβ€Ž

Lines changed: 0 additions & 707 deletions
This file was deleted.

β€Ž.github/prompts/db-refactor/logs/phase-45-10-dockerfile-go-compile-hardening.logβ€Ž

Lines changed: 0 additions & 372 deletions
This file was deleted.

0 commit comments

Comments
Β (0)