Files
cpas/CPAS Violation Tracker.md
T
2026-05-19 00:33:08 -05:00

8.8 KiB
Raw Blame History

type, status, tags, repo, started, updated, owner
type status tags repo started updated owner
project active
project
cpas
hr
internal-tool
docker
react
node
sqlite
https://git.alwisp.com/jason/cpas 2026-03-06 2026-05-14 Jason Stedwell

CPAS Violation Tracker

Single-container Dockerized web app for CPAS (workforce standing / violation documentation) used internally at Message Point Media. Replaces ad-hoc paper / spreadsheet violation tracking with a structured, auditable system that produces signed PDF records and surfaces tier-escalation risk live.

Repo: git.alwisp.com/jason/cpas · First commit: 2026-03-06 · Deployed on Unraid (10.2.0.14:3001)

Stack

  • Frontend: React + Vite (single-page app, dark theme, mobile-responsive at 375px+)
  • Backend: Node.js + Express
  • DB: SQLite via better-sqlite3, WAL mode, auto-migrations on boot
  • PDF: Puppeteer + bundled Chromium (system install inside container)
  • Packaging: One multi-stage Dockerfile — build React, install backend, bundle Chromium, ship as a single image
  • Runtime requirement on dev box: Docker Desktop only. No host Node/npm needed.

What it does

It manages employee violations against the CPAS rubric on a rolling 90-day window:

  • Company Dashboard — every employee sorted by active CPAS points (highest risk first), with summary stat cards, tier badges, an "at-risk" flag (within 2 pts of next tier), and search + department filter.
  • Violation Form — pick an employee, pick a violation type, see prior 90-day count inline; recidivist auto-escalation; pre-submit tier-crossing warning; context-aware fields; one-click PDF download on submit; optional employee acknowledgment block.
  • Employee Profile Modal — full violation history, amendment count, edit employee, merge duplicate, negate/restore, hard delete, per-violation PDF, free-text notes/flags ("on PIP", "union member"), and a per-violation 90-day point expiration timeline with projected tier drops.
  • Violation Amendment — point value / type / incident date are immutable; non-scoring fields (location, witness, narrative, acknowledgment) are amendable with a field-level diff trail.
  • Audit Log — append-only record of every write action (employee CRUD, violation logged/amended/negated/restored/deleted); filterable, paginated panel from the dashboard.
  • Toast notification system — global success/error/warning/info, auto-dismiss with progress bar.
  • PDF generation — Puppeteer, snapshot of prior active points at incident time, optional employee acknowledgment block on the signature page.
  • Stakeholder demo/demo static route with synthetic data, served before the SPA catch-all; no auth required.

CPAS Tier System

Points Tier Label
04 01 Elite Standing
59 1 Realignment
1014 2 Administrative Lockdown
1519 3 Verification
2024 4 Risk Mitigation
2529 5 Final Decision
30+ 6 Separation

Scores are summed over a rolling 90-day window; negated violations excluded.

Database

Six tables + one view:

  • employees — id, name, department, supervisor, notes
  • violations — full incident record, including prior_active_points snapshot
  • violation_resolutions — soft-delete reason / details
  • violation_amendments — field-level diff log (one row per changed field)
  • audit_log — append-only system action log
  • active_cpas_scores (view) — 90-day point sum per employee

Auto-migrations in db/database.js add new columns to existing DBs on startup — meaningful here because Jason runs this in production on Unraid, so the schema evolves without losing data.

Deployment notes worth remembering

  • Unraid: static IP on br0 bridge (10.2.0.14), DB persisted at /mnt/user/appdata/cpas/db/cpas.db, WebUI on port 3001.
  • --pids-limit 2048 is critical — Puppeteer/Chromium spawns many processes for each PDF; Unraid's default cap silently kills PDF generation.
  • Volume: /mnt/user/appdata/cpas/db/data. Database survives rebuilds, image reloads, and container removal.
  • Updates are a 3-step loop: docker build locally → docker save | gzip → SMB drop into appdata → docker load + restart container in Unraid GUI.

Mobile

Responsive design targets 375px+ (iPhone SE and up). At ≤768px the dashboard table swaps to a card-based layout (DashboardMobile.jsx); the nav stacks; tap targets are ≥44px; form inputs use 16px font to prevent iOS focus zoom. No external CSS library — single mobile.css utility sheet + a useMediaQuery hook. Implementation details and testing checklist live in MOBILE_RESPONSIVE.md.

Project structure

cpas/
├── Dockerfile                  # Multi-stage: React build + Express + Chromium
├── server.js                   # API + static SPA + /demo route
├── db/
│   ├── schema.sql              # Tables + 90-day active score view
│   └── database.js             # SQLite + auto-migrations
├── pdf/
│   ├── generator.js            # Puppeteer
│   └── template.js             # HTML PDF template
├── demo/                       # /demo synthetic-data SPA
└── client/                     # React + Vite frontend
    └── src/
        ├── App.jsx             # Root + footer (copyright, dev ticker, Gitea link)
        ├── data/
        │   ├── violations.js   # All CPAS violation definitions
        │   └── departments.js
        ├── hooks/useEmployeeIntelligence.js
        └── components/         # Dashboard, ViolationForm, EmployeeModal,
                                # AmendViolationModal, AuditLog, ToastProvider, etc.

API surface (selected)

  • GET /api/health — health + build version
  • GET /api/dashboard — all employees with active points + violation counts
  • GET /api/employees/:id/expiration — roll-off timeline with days remaining
  • POST /api/violations — log violation (accepts acknowledged_by, acknowledged_date)
  • PATCH /api/violations/:id/amend — non-scoring field amendment + diff log
  • PATCH /api/violations/:id/negated / /restore — soft delete + restore
  • GET /api/violations/:id/pdf — PDF download
  • GET /api/audit — paginated audit log

Status

Phase 8 of the public roadmap is complete (stakeholder demo + app footer with live dev ticker). Core HR documentation workflow is shipped: dashboard, violation entry, employee profile, amendments, audit log, expiration timeline, acknowledgment field, toast system, mobile layout.

Notable open ideas (from roadmap)

Quick wins (low effort): column sort on dashboard, department multi-select filter, N keyboard shortcut for new violation, configurable at-risk threshold via env var, version.json injected at build time.

Reporting: violation trend chart (daily/weekly/monthly), department heat map, per-employee sparklines in profile modal.

Workflow: draft/pending violations before finalize, violation templates.

Notifications: tier-escalation alerts (email or in-app) on crossing into Tier 2+.

Infra (higher effort): multi-user auth with roles (currently runs on trusted internal LAN with none), scheduled DB backup, dark/light theme toggle.

Review take

The app is well-scoped and visibly production-shaped, not a hobby project. Strong signals: append-only audit log, field-level amendment diffs, immutable scoring fields, prior_active_points snapshot baked into each violation row so historical PDFs stay accurate, and auto-migrations so the schema can evolve in place on a live Unraid deployment. The Unraid-specific install guide explicitly calls out --pids-limit 2048 for Chromium, which is the kind of footgun that only gets documented after it's been hit in production — that detail alone tells you this is being actually used.

The single biggest gap relative to its current capability is auth. Everything else on the roadmap is incremental polish; multi-user auth with roles is the one change that meaningfully expands who can use the system safely. Worth pairing it with the proposed scheduled DB backup, since the moment more than one supervisor is writing, accidental damage gets more likely.

A secondary observation: the audit log + amendment diff infrastructure is already strong enough to support a "who changed what, when" view per employee — that's basically free reporting if surfaced in the profile modal as a timeline.

  • Repo — git.alwisp.com/jason/cpas
  • Local install guide — README.md (in repo)
  • Unraid install guide — README_UNRAID_INSTALL.md
  • Mobile implementation notes — MOBILE_RESPONSIVE.md