Open
Conversation
Claude/merge to main a3mj a
…, CI/CD, and functional search - Add React ErrorBoundary component wrapping the app in layout.tsx - Add /api/health endpoint returning status, timestamp, version, uptime - Set up Vitest with 10 passing tests (data integrity, error boundary, health API) - Add GitHub Actions CI workflow (test + build on push/PR to main) - Make Header search bar functional with station/research/page filtering - Remove fake notification badge; add tooltips to placeholder buttons - Add CLAUDE.md with full audit summary and phased improvement roadmap
…eployment docs - Add client-side logger utility (src/lib/logger.ts) with buffered log entries - Add input validation/sanitization library (src/lib/validation.ts) with XSS protection - Apply sanitization to Header search input - Add CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy headers in next.config.ts - Add deployment documentation to README (Docker, Vercel, health check, testing) - Add 7 validation tests (17 total tests passing) - Update CLAUDE.md marking Phase 1 and Phase 2 complete
…a export - Add SQLite database (better-sqlite3) with stations, readings, ingestion_log tables - Add seed script (npm run db:seed) that migrates static data to DB (12 stations, 144 readings) - Add GET /api/stations — list all stations with latest readings - Add GET /api/stations/:id/history — time-series data with date range filtering - Add GET /api/export — CSV and JSON data export with optional station filter - Add POST /api/ingest — USGS NWIS real-time data ingestion with logging - Update CLAUDE.md with Phase 3 architecture and Azure migration plan - Update .gitignore to exclude SQLite database files
Frontend migration (Phase 3): - StationTable fetches from /api/stations with loading state and static fallback - MetricCards fetches from /api/stations, computes averages dynamically - Station detail page fetches from /api/stations/:id/history and /api/export - Export CSV button now wired to real /api/export endpoint Phase 4 deliverables: - Dockerfile (multi-stage: deps → build → runner with standalone output) - docker-compose.yml with persistent volume for SQLite database - .dockerignore for clean Docker builds - CONTRIBUTING.md with setup guide, coding standards, API docs, workflow - Architecture diagram (ASCII) added to README - Updated tech stack table in README with SQLite and Vitest 17 tests passing, production build verified.
- Add 12 integration tests for API routes (29 total tests, 7 suites): - /api/stations: list all, validate fields, verify last readings - /api/stations/:id/history: full data, field types, 404 handling, date range, limit - /api/export: JSON export, station filter, CSV format/headers, empty results - Add .env.example documenting DB_PATH, INGEST_API_KEY, DATABASE_URL
- Add rate limiting middleware (100 req/min per IP) for all API routes - Add CORS configuration with UDC origin allowlist - Add HSTS header for production deployments - Require INGEST_API_KEY in production (503 if missing) - Add data source attribution banner on dashboard - Replace misleading "Real-Time Data" and "Live monitoring" labels with accurate "USGS Data Integration" and source descriptions - Fix metadata description to remove "Real-time" claim
…tent - db.ts: Create data/ directory if missing before opening SQLite database - seed.ts: Create data/ directory if missing, clear existing seed data before re-seeding to prevent duplicate records on repeated runs - ci.yml: Add db:seed step before running tests so API tests have data
… check - Remove output: "standalone" (incompatible with Vercel serverless) - Add vercel.json to bundle data/ dir with serverless functions - Fix db.ts to copy SQLite DB to /tmp on Vercel (read-only filesystem) - Seed DB at build time so it's bundled in the deployment - Enhance /api/health to verify DB connectivity and station count - Add USGS and CartoDB to CSP connect-src for client-side requests
…s-jJXP2 Claude/audit production readiness j jxp2
Migrate database layer to support both SQLite (local) and Neon PostgreSQL (production/Vercel) via a unified async DbClient interface. When DATABASE_URL is set, the app connects to Neon; otherwise falls back to SQLite. - Add @neondatabase/serverless and ws packages - Rewrite src/lib/db.ts with dual-backend DbClient abstraction - Update all API routes (stations, history, export, health, ingest) to use async getDbClient() - Update seed script to support both SQLite and PostgreSQL - Health endpoint now reports database provider (sqlite vs neon-postgresql) - Keep legacy getDb() for local SQLite tests
Establishes rules for Claude Code to never expose credentials in commits, logs, or output, and to always include session attribution in commit messages.
…ations - Replace site 01651750 (discontinued Oct 2017) with 01649500 (NE Branch Anacostia at Riverdale, active WQ monitoring) and 01646500 (Potomac at Little Falls, active with DO/pH/temp/conductivity) - Add logging when a site returns no time series data - Remove ineffective ON CONFLICT DO NOTHING clause (auto-increment PK)
…s-jJXP2 Claude/audit production readiness j jxp2
- Add crons config to vercel.json (schedule: 0 */6 * * *) - Add GET handler to ingest route for Vercel Cron (uses CRON_SECRET) - Refactor POST/GET to share runIngest() logic - POST still works for manual triggers with INGEST_API_KEY
USGS readings may have null for eColiCount, conductivity, turbidity, etc. Add null checks before calling .toLocaleString() and comparisons in StationTable, station detail page, and map popups. Show "—" for missing values instead of crashing.
…s-jJXP2 Claude/audit production readiness j jxp2
- Add vercel.live to script-src, connect-src, and frame-src in CSP headers - Guard eColiCount null check in MetricCards to prevent toLocaleString crash
…s-jJXP2 Fix CSP to allow Vercel Live and fix null eColiCount crash
- Add null guards to all .toLocaleString() calls across DCMap, StationTable, and station detail page to prevent crashes with USGS null data fields - Fix getStationColor() to handle null eColiCount with ?? 0 fallback - Add explicit script-src-elem CSP directive for Vercel Live toolbar - Allow *.vercel.live subdomains and wss://ws-us3.pusher.com in CSP - Add defensive null check in WaterQualityIndicator component Root cause: USGS ingestion returns null for fields like eColiCount, but multiple components assumed non-null values from the static seed data.
…s-jJXP2 Comprehensive null safety + CSP fix for Vercel deployment
Vercel Hobby accounts only allow daily cron jobs. Changed USGS ingestion from every 6 hours (0 */6 * * *) to once daily at 6 AM UTC (0 6 * * *).
…s-jJXP2 Fix Vercel cron: use daily schedule for Hobby plan
…e UI, and accessibility Research credibility & data integrity: - EPA Water Quality Portal (WQX) integration: ingest historical Anacostia watershed data via POST /api/ingest?source=epa (HUC 02070010, 5+ years of data) - Automated data validation: reject physically impossible readings (pH>14, negative DO, etc.) with warnings logged per reading - Data provenance badges: source labels (USGS/EPA/Model/Manual) shown in StationTable and station detail pages so researchers can verify each data point's origin - Citation metadata: CSV exports include citation header block; JSON exports include structured citation object with dataset name, publisher, and access URL - Methodology & data dictionary page (/methodology): sampling protocols, QA/QC procedures, parameter definitions with EPA standards, validation ranges, and ingestion history table - Ingestion log API: GET /api/ingestion-log exposes audit trail to users Educational value: - Python and R analysis templates (public/templates/) with API integration, EPA compliance checks, and publication-ready charts - Templates linked from education page's new "Analysis Templates" section WCAG 2.1 AA accessibility: - Skip-to-content link in layout.tsx - aria-label, aria-expanded, aria-haspopup on all interactive controls - aria-hidden on decorative icons throughout Header, Sidebar, station detail - role="search" on search container, scope="col" on table headers - Keyboard-navigable StationTable rows (Enter/Space to select) - Chart containers labeled with role="img" and descriptive aria-labels - id="main-content" on all page main elements - Sidebar as labeled navigation landmark Also: CSP updated for waterqualitydata.us, tests updated for new export format.
…s-jJXP2 Add EPA WQX integration, data validation, methodology page, provenanc…
- Add reusable Modal component with ESC close, backdrop click, scroll lock - Rewrite MetricCards: 8 clickable cards open rich modals with EPA context, station-level data, compliance indicators, and navigation - Rewrite education page: interactive exercises, audience filtering, module detail modals, API access documentation - Enhance research page: status badges, quick links for researchers, results count, methodology links - Polish dashboard: descriptive section headers for Water Quality, Multi-Parameter, Environmental Justice, and Station Table sections - Add EJ insight summary and open data links in footer - All 29 tests passing, TypeScript clean
- Add SidebarContext for mobile sidebar state management - Sidebar: hidden on mobile/tablet, slides in as overlay drawer with backdrop and close button when hamburger menu is tapped - Header: add hamburger menu button (visible below lg breakpoint), show compact UDC logo badge on mobile, make search bar fluid-width, hide date on small screens, show short date on tablets, hide "Stakeholder" text label and "Live" indicator on small screens - All pages: change ml-[240px] to lg:ml-[240px] so content fills full width on mobile/tablet - Add slide-in-left CSS animation for mobile drawer
…s-jJXP2 Claude/audit production readiness j jxp2
Header:
- Tighter padding/gaps on small screens (px-2, gap-0.5)
- Hide bell and stakeholder buttons below sm breakpoint
- Hide stakeholder label below md (icon-only on tablets)
- Shorter search placeholder ("Search..." vs full text)
- Add overflow-hidden to prevent header from causing scroll
Footer:
- Redesigned as centered, stacked layout that works at any width
- Clear visual hierarchy: logo/name, institute info, data links, attribution
- Links use flex-wrap with dot separators instead of inline slashes
- Better spacing and readable font sizes on small screens
All pages:
- Add min-w-0 overflow-x-hidden to main content area
- Responsive padding: p-3 on mobile, p-4 on sm, p-6 on md+
- Hero section: responsive padding and border-radius
…ss-jJXP2 Claude/audit production readiness j jxp2
Footer: - Create dedicated Footer component with 4-column responsive grid - Add Institute section (WRRI, CURII, EQTL), contact info, address - Add Quick Links (Research, Education, Methodology, Data Export) - Add Data Sources with external links (USGS, EPA, DOEE, DC Open Data) - Add professional attribution for Olink Technologies Inc, DAPS Analytics, and Dr. Tolessa Deksissa - Add copyright and funding lines - Fully responsive: stacks cleanly on mobile, 2-col tablet, 4-col desktop - Replace inline footer in page.tsx with reusable component Search: - Fix search to query researcher name (pi), department, description, and funding fields — previously only searched title and tags - When matching on PI name, show "Project Title (Researcher)" in results - Add Methodology and Dashboard pages to searchable results
…ss-jJXP2 Redesign footer and fix search to include researcher names
Implements an AI chat assistant that helps researchers and students interpret water quality data directly within the dashboard. Architecture: - POST /api/chat — Vercel AI SDK v6 streaming endpoint using Claude Sonnet with a domain-specific system prompt containing EPA water quality standards, seasonal patterns, station metadata, and UDC WRRI research context - 3 tool-augmented functions: getStationData, getStationHistory, listAllStations — AI can query live dashboard APIs to answer data-specific questions with real readings - ResearchAssistant.tsx — Floating chat panel (bottom-right FAB) with streaming responses, suggested questions, conversation history, clear/close controls, and graceful degradation when ANTHROPIC_API_KEY is not configured - Loaded globally via layout.tsx with dynamic import (SSR disabled) Packages: ai@6, @ai-sdk/react@3, @ai-sdk/anthropic, zod
WRRI faculty can now manage station data through /admin: - CSV/JSON file upload with drag-and-drop and auto column mapping - AI-assisted column mapping using Claude Haiku (with heuristic fallback) - Full CRUD for stations (add, edit, delete) and readings (view, delete) - Ingestion log viewer with ability to trigger USGS/EPA data pulls - Protected with ADMIN_API_KEY env var (open access when unset for dev) - Preview step shows AI column mapping before committing upload - Sidebar nav link under ADMIN section
…ss-jJXP2 Claude/audit production readiness j jxp2
- Derive base URL from request headers instead of hardcoded localhost:3000, fixing tool calls (getStationData, getStationHistory, listAllStations) that failed on Vercel because localhost doesn't exist in serverless - Add try/catch around streamText with proper 500 error response - Add request body validation with 400 error for malformed requests - Make chat panel responsive on mobile: use left-3/right-3 positioning instead of fixed 360px width that overflowed on small screens
…ss-jJXP2 Fix AI chat API error on Vercel and improve mobile chat panel
…ndling Root cause: Zod v4 (4.3.6) schemas are not compatible with AI SDK v6's tool() function which expects Zod v3 format internally. Replaced all tool inputSchema definitions with jsonSchema() from the ai package, which bypasses the Zod conversion entirely. Additional fixes: - Use x-forwarded-proto header for correct HTTPS base URL on Vercel - Guard against empty messages array (used by API key preflight check) - Wrap convertToModelMessages in try/catch with proper error response - Show actual error message in chat UI instead of generic text
…ss-jJXP2 Fix AI chat: replace Zod v4 schemas with jsonSchema, improve error ha…
Add ANTHROPIC_API_KEY to the example environment file.
The real API key was accidentally committed to .env.example in 3166b9d. Replace with placeholder and add missing ADMIN_API_KEY template. SECURITY: The exposed key must be revoked immediately at console.anthropic.com.
The claude-sonnet-4-5-20250514 model was causing "Something went wrong" errors on production. Switch to claude-haiku-4-5-20251001 which is broadly available and cost-effective. Also improved error handling to surface actual API error details instead of generic messages.
…panish i18n Chat API improvements: - Rate limiting (10 req/min per IP) with in-memory store - CSRF/origin validation to block cross-origin requests - Configurable model via CHAT_MODEL env var (default: claude-haiku-4-5) - Token usage logging via onFinish callback - Streaming error handling via onError callback - Increased maxOutputTokens from 2048 to 4096 Multilingual (i18n) system: - Translation dictionary (src/lib/i18n.ts) with ~120 keys in English and Spanish - LanguageContext with localStorage persistence and document.lang update - Language switcher in Header (globe icon with EN/ES flags) - Integrated i18n into: layout, page, Header, Sidebar, Footer, StationTable, EnvironmentalJustice, and dashboard sections All 29 tests pass, build succeeds.
Replace crude 7-point diamond with real DC boundary coordinates sourced from US Districts GeoJSON data. Now properly traces the NW/NE diagonal borders (Maryland line), east vertex, and ~100 detailed points along the Potomac River for the western/southern border — making DC actually look like DC on the map.
…ss-jJXP2 Fix DC boundary outline with accurate 119-point polygon
Replace the attribution requirement with an explicit rule to never include claude.ai session URLs in commits, PRs, or code.
On mobile (<640px): legend starts collapsed as a small "Legend" button that toggles open/closed on tap. Smaller padding, font sizes, and max-height with scroll for small screens. Prevents map drag/zoom when interacting with legend. Layer controls panel also slightly narrower on mobile.
…ss-jJXP2 Claude/audit production readiness j jxp2
Leaflet internally uses z-index values in the hundreds/thousands, which caused the map to render above the chat panel when scrolling. Bumped the chat button and panel from z-50 to z-[10000] so they always float above map layers.
…ss-jJXP2 Fix AI chat panel z-index to stay above Leaflet map
- Settings: Replace placeholder sidebar link with a modal offering theme (light/dark/system) and language (EN/ES) selection, reusing the existing Modal component and ThemeContext/LanguageContext. - Admin auth: Persist admin key in sessionStorage so it survives page refresh. Remove silent catch-based auto-auth that could bypass the login gate. Add a "Sign Out" button to the admin header. Show a loading state while the auth check runs on mount. - i18n: Add settings.* translation keys for both EN and ES.
Set turbopack.root to "." so Next.js resolves dependencies from the project directory instead of a parent directory that may contain its own package.json (causing "Can't resolve tailwindcss" errors).
Wraps the /api/stations route in try-catch with descriptive error messages for native module load failures (common on Windows when binaries need rebuilding). Also adds a clear error message in createSqliteClient() when better-sqlite3 fails to load.
…ss-jJXP2 Claude/audit production readiness j jxp2
- Enforce ADMIN_API_KEY in production across all 4 admin API routes (stations, readings, upload, ai-map-columns). Without the key set, admin access is now blocked with 503 instead of silently allowed. - Show login error messages in admin UI instead of generic alert. - Fix station detail page to average multiple readings per month instead of overwriting (USGS ingests many per day). - Add "Baseline data" warning badge when station only has seed data. - Add USGS site mappings for ANA-003 (Buzzard Point 01651827) and ANA-004 (Anacostia at Washington 01651750) to pull real sensor data. - Update EPA station map with matching new site IDs.
Combines loginError state (our branch) with authChecked state and sessionStorage persistence (from main). Both improvements are kept.
Next.js App Router statically caches GET route handlers that don't read request parameters. This caused /api/stations to serve stale seed data (12/15/2025) instead of fresh USGS-ingested readings from the Neon database. Adding export const dynamic = "force-dynamic" ensures every request queries the database live.
- Map Watts Branch (USGS 01651800) and Hickey Run (USGS 01651770) to WB-001 and HR-001 in both USGS and EPA ingestion configs - Show "Baseline (modeled)" instead of misleading seed timestamps (12/15/2025) for stations with only seed data — affects station detail page, map popups, and dashboard table - Stations with live USGS/EPA data continue showing real timestamps
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 28306168 | Triggered | Claude API Key | e0722b9 | .env.example | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.