Skip to content

POWDER-RANGER/CIVWATCH

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

261 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ•—    β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—  β–ˆβ–ˆβ•—
β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘
β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘  β•šβ–ˆβ–ˆβ•”β•  β•šβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘
 β•šβ•β•β•β•β•β•β•šβ•β•   β•šβ•β•    β•šβ•β•β•β•šβ•β•β• β•šβ•β•  β•šβ•β•   β•šβ•β•    β•šβ•β•β•β•β•β•β•šβ•β•  β•šβ•β•

Next-Generation Civic Transparency Platform

Turn fragmented public records into legible, queryable intelligence.

Typing SVG

TypeScript Python FastAPI React Node.js PostgreSQL Redis Docker

Version License: MIT Status ML Pipeline Maintenance Sprint

πŸ“Š Live Status Β· πŸ›£οΈ Roadmap Β· πŸ“‹ Architecture Β· πŸ”’ Security Β· πŸ› Issues


🧭 What Is CIVWATCH?

CIVWATCH is a full-stack civic intelligence platform that transforms fragmented public records β€” agendas, minutes, budgets, contracts, votes β€” into normalized, anomaly-aware timelines. Designed for residents, journalists, and civic analysts who need more than PDFs.

Current state (April 11, 2026): Phase 1 Foundation is complete. Phase 2 Feature Completeness is active (window: Apr 4–20). The ML service runs live DBSCAN anomaly detection on :5000. The backend serves /api/status and /api/health on :3000. PostgreSQL is wired and storing data. JWT auth middleware is live. The React frontend nav route for the AnomalyDashboard is wired. Three critical Phase 2 gaps remain:

  1. Feature extraction type errors in dataAnalyzer.ts blocking verified vector output (#3)
  2. DBSCAN execution path β€” no scheduler/trigger wired from anomaly_scores (manual-call only)
  3. ML /predict endpoint β€” missing schema + return ⚑ System Status

Last verified: April 11, 2026 β€” 3:56 AM CDT

Component Status
🟒 Backend β€” /api/status LIVE β€” GET :3000/api/status β†’ {"status":"ok"}
🟒 Backend β€” /api/health LIVE β€” GET :3000/api/health β†’ uptime + version
🟒 Backend β€” /api/alerts LIVE β€” POST/GET with PostgreSQL queries
🟒 Backend β€” /api/analytics LIVE β€” routes wired, DB queries active
🟒 Backend β€” Auth middleware DONE β€” requireAuth JWT validation live
🟒 Backend β€” Error handling DONE β€” AppError middleware + structured responses
🟒 ML Service (FastAPI) LIVE β€” Server on :5000, CORS enabled
🟒 ML β€” Health / Readiness LIVE β€” /health + /ready probes confirmed
🟒 ML β€” DBSCAN /detect LIVE β€” Fully functional, StandardScaler applied
🟒 ML β€” Sentiment (single) LIVE β€” /analyze/sentiment with TextBlob MVP
🟒 ML β€” Batch scoring LIVE β€” /analyze/batch 1:1 input/output
🟒 ML β€” Anomaly scoring v2 LIVE β€” /score/anomaly with z-score + flags
🟒 PostgreSQL WIRED β€” Pool initialized, tables created, routes querying
🟒 Docker Compose DONE β€” All services start; healthchecks fixed (bd55128)
🟒 CI/CD Pipeline LIVE β€” Real tests running (Jest/pytest), 6 security workflows
🟑 Anomaly route PARTIAL β€” GET /api/anomalies registered, returns empty array
🟑 Ingest route PARTIAL β€” POST /api/ingest accepts, no storage/forwarding
🟑 Feature extraction BOTTLENECK β€” dataAnalyzer.ts type errors block real vectors (#3)
🟑 Frontend nav PARTIAL β€” AnomalyDashboard route wired; data source empty
🟑 Dashboard layout PARTIAL β€” Components exist; no charts/graphs; no live data (#10)
🟑 Redis cache PLANNED β€” Client declared; not wired into routes (#5)
🟑 GraphQL resolvers STUB β€” Schema defined; no resolvers (#6)
🟑 Unit tests PARTIAL β€” Jest/pytest configured; coverage ~15% (#15)
🟑 NLP preprocessing MVP β€” TextBlob only; transformers swap planned (#8)
πŸ”΄ DBSCAN execution path GAP β€” No scheduler/trigger wired from anomaly_scores
πŸ”΄ ML /predict endpoint NOT STARTED β€” No schema; returns static JSON; no return binding (#9)
πŸ”΄ Integration tests NOT STARTED β€” No cross-service tests (#15)
πŸ”΄ WebSocket / Real-Time NOT STARTED β€” Streaming layer not built (#12)
πŸ”΄ Rate limiting NOT STARTED β€” No middleware (#7)
πŸ”΄ E2E tests NOT STARTED β€” No user flow tests (#15)
πŸ”΄ Dark mode NOT STARTED β€” No theme support (#13)

Legend: 🟒 Done & verified | 🟑 Partial / needs work | πŸ”΄ Not started / blocked

πŸš€ Quick Startbinding to GET /api/anomalies

Prerequisites: Docker & Docker Compose Β· Node.js 20+ Β· Python 3.10+

Clone

git clone https://github.com/POWDER-RANGER/CIVWATCH.git cd CIVWATCH

Configure environment

cp .env.example .env

Edit .env β€” set DB credentials, Redis URL, API keys

Bring the full stack up

docker-compose up

Or use the npm shortcut

npm run docker:up

Verify It's Running

Backend health

curl http://localhost:3000/api/status

β†’ {"status":"ok"}

ML service health

curl http://localhost:5000/health

β†’ {"status":"ok"}

Frontend

open http://localhost:4000

Local Dev (No Docker)

Install everything at once

npm run setup

Run all services concurrently

npm run dev

Or run individually:

npm run dev:backend # Node.js API β†’ :3000 npm run dev:frontend # React UI β†’ :4000 npm run dev:ml # FastAPI ML β†’ :5000

🧠 ML Pipeline

The anomaly detection engine is live and fully independent. It runs on :5000 and is the most production-ready component in the stack.

POST civic data points for anomaly scoring

curl -X POST http://localhost:5000/detect
-H "Content-Type: application/json"
-d '{ "data": [ [1.2, 0.5, 200000], [1.0, 0.4, 195000], [8.9, 7.1, 4500000] ] }'

Response: DBSCAN cluster labels β€” outliers flagged as -1. StandardScaler normalization is applied before every clustering pass.

Step Status
Data ingestion (POST /detect) βœ… Live
Normalization (StandardScaler) βœ… Live
Clustering (DBSCAN / scikit-learn) βœ… Live
Outlier flagging (Label -1) βœ… Live
Sentiment analysis (/analyze/sentiment) βœ… Live
Batch scoring (/analyze/batch) βœ… Live
Anomaly scoring v2 (/score/anomaly) βœ… Live
Model persistence πŸ”΄ Planned
Transformers swap (M2 NLP) πŸ”΄ Planned
GPU optimization πŸ”΄ Planned

πŸ—‚οΈ Repo Layout

CIVWATCH/
β”œβ”€β”€ πŸ“ backend/           Node.js/Express API
β”‚   β”œβ”€β”€ /api/status       βœ… LIVE
β”‚   β”œβ”€β”€ /api/health       βœ… LIVE
β”‚   β”œβ”€β”€ /api/alerts       βœ… LIVE
β”‚   β”œβ”€β”€ /api/analytics    βœ… LIVE
β”‚   β”œβ”€β”€ /api/anomalies    ⚠️ PARTIAL (empty array)
β”‚   └── /api/ingest       ⚠️ PARTIAL (accepts, no processing)
β”‚
β”œβ”€β”€ πŸ“ frontend/          React scaffold (nav route wired)
β”‚   └── AnomalyDashboard  ⚠️ PARTIAL (no data binding)
β”‚
β”œβ”€β”€ πŸ“ ml/                Python FastAPI β€” ML engine
β”‚   β”œβ”€β”€ POST /detect      βœ… DBSCAN live
β”‚   β”œβ”€β”€ GET /health       βœ… LIVE
β”‚   β”œβ”€β”€ GET /ready        βœ… LIVE
β”‚   β”œβ”€β”€ POST /analyze/sentiment  βœ… LIVE
β”‚   β”œβ”€β”€ POST /analyze/batch      βœ… LIVE
β”‚   └── POST /score/anomaly      βœ… LIVE (z-score + flags)
β”‚
β”œβ”€β”€ πŸ“ src/analytics/     dataAnalyzer.ts (mean/median/stddev) ⚠️ Type errors (#3)
β”œβ”€β”€ πŸ“ tests/             Jest + pytest configured, coverage ~15%
β”œβ”€β”€ πŸ“ docs/              Architecture, API spec, testing strategy
β”œβ”€β”€ πŸ“ demo/              Demo scenarios and scripts
β”œβ”€β”€ πŸ“ civwatch-desktop/  Electron wrapper (Phase 1 complete)
β”œβ”€β”€ πŸ“ .github/           GitHub Actions: 6 security workflows
β”œβ”€β”€ 🐳 docker-compose.yml Multi-service orchestration (fixed)
β”œβ”€β”€ βš™οΈ .env.example       Environment config template
β”œβ”€β”€ πŸ“‹ package.json       Monorepo root (workspaces)
└── πŸ“‹ requirements.txt   Python dependencies

πŸ›£οΈ Roadmap

Phase 1 β€” Foundation βœ… COMPLETE

βœ… Backend /api/health + /api/status live
βœ… PostgreSQL pool initialized + wired in routes
βœ… ML FastAPI server live on :5000
βœ… DBSCAN /detect endpoint fully functional
βœ… StandardScaler normalization applied
βœ… JWT auth middleware (requireAuth) live
βœ… Docker Compose healthchecks fixed (bd55128)
βœ… CI/CD pipeline β€” real tests running
βœ… 6 security scanning workflows (bandit, CodeQL, Semgrep, etc.)
βœ… Electron shell + IPC bridge (PR #102)
βœ… AnomalyDashboard nav route wired (commit 15b1c41)

Phase 2 β€” Feature Completeness 🚧 IN PROGRESS (Apr 4–20, 2026)

πŸ”΄ [CRITICAL] Feature extraction β€” Fix dataAnalyzer.ts type errors; verify real vectors (#3)
πŸ”΄ [CRITICAL] DBSCAN trigger β€” Wire scheduler/trigger from anomaly_scores table
πŸ”΄ [CRITICAL] ML /predict β€” Add feature vector schema + return binding to /anomalies (#9)
🟑 Complete ingest pipeline β€” POST /api/ingest must store/queue/forward
🟑 Build React UI components (charts, tables, anomaly visualizations) (#10, #11)
🟑 Implement WebSocket real-time layer (#12)
🟑 Wire Redis caching into alert routes (#5)
🟑 Add GraphQL resolvers (#6)
🟑 Write integration tests (backend-to-ML, frontend-to-backend) (#15)
🟑 Swap TextBlob for transformers (M2 NLP upgrade) (#8)
🟑 Model serialization + persistence (#9)
🟑 Performance profiling

Phase 3 β€” Production Hardening 🟑 PLANNED (Apr 21–May 2, 2026)

🟑 Security audit + penetration testing (OWASP A01–A05) (#17)
🟑 Rate limiting + request throttling (#7)
🟑 Performance optimization β€” query tuning, load testing
🟑 80%+ code coverage gate in CI (#16)
🟑 Packaged releases (.exe, .dmg, .AppImage)
🟑 Documentation review + ops runbook (#18)

πŸ§ͺ Testing

Current coverage: ~15% across Jest (Node/TS) + pytest (Python). Target for Phase 2: 50%+. MVP target: 80%+.

Node/TypeScript test suite

npm test

Python ML service tests

pytest tests/ -v

Run both

npm run test --workspaces && pytest tests/ -v

See docs/testing.md for the full testing strategy.

🀝 Contributing

Good first issues β€” each is fully tracked:

Task Issue
Fix TypeScript type errors in dataAnalyzer.ts #3
Wire Redis client into alert routes #5
Add GraphQL resolvers (Query/Mutation/Subscription) #6
Build React anomaly visualization components (charts) #10
Implement WebSocket real-time layer #12
Write integration tests (backend-to-ML) #15
Rate limiting middleware #7
Dark mode theme support #13

See CONTRIBUTING.md for full guidelines. Keep PRs small and focused. Every PR needs a short why in the description.

πŸ“š Documentation Index

File Purpose
STATUS.md Live per-component implementation matrix (updated Apr 11)
IMPLEMENTATION_ROADMAP.md Phased PR plan (PR0 β†’ PR19)
NEXT_PHASE.md This-week tasks + debugging guide
docs/architecture.md System design, port map, data flow
CHANGELOG.md Version history (Keep a Changelog)
SETUP.md Detailed local environment setup
SECURITY.md Security practices + threat model
RESPONSIBLE_DISCLOSURE.md Vulnerability reporting procedures
CREDIBILITY_CHECKLIST.md Repo health + credibility audit
GIT-CRYPT-SETUP.md Encrypted secrets via git-crypt

πŸ”’ Security

Do not open public GitHub issues for security vulnerabilities. Report via GitHub Security Advisories only.

Full policy β†’ SECURITY.md Β· RESPONSIBLE_DISCLOSURE.md

πŸ“„ License

MIT β€” see LICENSE.

Built by Curtis Farrar Independent Systems Engineer Β· AI Security Architect Β· Civic Monitoring Keokuk, Iowa, USA

"Make civic data as actionable as a security feed."

GitHub Β· Portfolio

This README reflects actual current state β€” not aspirations. Full truth table β†’ STATUS.md

About

Civic transparency platform

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors