Skip to content

ed-da-goat/tax

Repository files navigation

Georgia CPA Firm -- Accounting System

A full-featured accounting system built to replace QuickBooks Online for a small Georgia CPA firm (2-5 staff, 26-50 clients). Runs entirely local -- no cloud subscriptions, no third-party dependencies at runtime.

Status: Complete and Deployed

All 38 backend modules across 8 phases are built, tested, and deployed. The frontend has 27 pages covering every workflow. Security hardened and running in production.

  • 900 tests passing (pytest)
  • 59 database tables with audit triggers
  • 34 routers / 257+ API endpoints
  • 27 frontend pages
  • 50+ ORM models
  • Deployed via nginx HTTPS + launchd services

Build Phases

Phase Modules Description
0 - Migration M1-M7 QBO CSV parser, client splitter, CoA mapper, transaction/invoice/payroll importers, audit report
1 - Foundation F1-F5 Database schema, chart of accounts, general ledger, client management, JWT auth
2 - Transactions T1-T4 Accounts payable, accounts receivable, bank reconciliation, approval workflow
3 - Documents D1-D3 Upload, viewer, search
4 - Payroll P1-P6 Employee records, GA withholding (G-4), GA SUTA, federal tax/FICA/FUTA, pay stubs, approval gate
5 - Tax Exports X1-X11 GA G-7, Form 500/600, ST-3, Schedule C, 1120-S/1120/1065, checklist, W-2, 1099-NEC
6 - Reporting R1-R7 P&L, balance sheet, cash flow, PDF export, firm dashboard, AR/AP aging
7 - Operations O1-O4 Audit trail, automated backup, restore, health check
8 - Feature Gaps FG1-FG4 W-2 generation, 1099-NEC generation, AR/AP aging reports, check printing

Tech Stack

Layer Technology Purpose
Backend Python 3.14 + FastAPI Async API server with rate limiting
Frontend React 18.3 + Vite 6 27-page internal dashboard (React Query, React Router 6)
Database PostgreSQL 59 tables, ACID-compliant, audit triggers on all tables
Auth JWT + RBAC + TOTP 2FA CPA_OWNER and ASSOCIATE roles, defense-in-depth
PDF WeasyPrint Pay stubs, tax forms, financial reports, checks
Encryption Fernet (AES-128-CBC) PII at rest (SSN, tax ID)
Migration Custom CSV parser Imports QuickBooks Online exports
Deploy nginx + launchd HTTPS reverse proxy, auto-start services, nightly backup
Backup GPG (AES-256) Encrypted nightly database backups, 30-day retention

Project Structure

tax/
├── backend/
│   ├── app/
│   │   ├── auth/               # JWT auth, RBAC, 2FA (TOTP)
│   │   ├── models/             # SQLAlchemy ORM (50+ models)
│   │   ├── schemas/            # Pydantic request/response schemas
│   │   ├── routers/            # 34 FastAPI route handlers
│   │   ├── services/           # Business logic layer
│   │   │   ├── migration/      # QBO import pipeline (M1-M7)
│   │   │   ├── payroll/        # Tax calculators, pay stubs, W-2, NACHA
│   │   │   └── tax_filing/     # GA FSET XML, TaxBandits
│   │   ├── middleware/         # Security headers, request size limits, audit
│   │   ├── crypto.py           # Fernet PII encryption
│   │   ├── config.py           # Environment settings (no default secrets)
│   │   ├── database.py         # Async SQLAlchemy engine
│   │   └── main.py             # FastAPI app entry point
│   ├── db/migrations/          # SQL migrations (004-006)
│   ├── scripts/                # seed_test_data.py, migrate_encrypt_pii.py
│   └── tests/                  # 900 tests (pytest + pytest-asyncio)
├── frontend/
│   ├── src/
│   │   ├── pages/              # 27 page components
│   │   ├── components/         # 11 shared components
│   │   ├── hooks/              # useApi, useAuth, useToast, useUnsavedChanges
│   │   ├── utils/              # format.js (currency, dates, entity types)
│   │   └── styles/             # Single CSS file (index.css)
│   └── package.json
├── deploy/
│   ├── setup.sh                # Full install (nginx, launchd, certs)
│   ├── teardown.sh             # Uninstall everything
│   ├── backup.sh               # GPG-encrypted pg_dump
│   ├── restore.sh              # Restore from encrypted backup
│   ├── logrotate.sh            # Daily log rotation
│   ├── dbmaint.sh              # Weekly VACUUM/REINDEX
│   ├── nginx.conf              # HTTPS reverse proxy config
│   ├── com.gacpa.*.plist       # 4 launchd service definitions
│   └── windows-trust.md        # LAN client cert trust instructions
├── ARCHITECTURE.md             # Module dependency map
├── OPEN_ISSUES.md              # 11 open compliance flags (rate verification)
└── AGENT_LOG.md                # Build session history

Quick Start

Prerequisites

  • Python 3.14+
  • PostgreSQL (local instance)
  • Node.js 18+
  • pango (for PDF generation): brew install pango
  • nginx (for deployment): brew install nginx

Backend Setup

cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Create backend/.env with required secrets (the app will crash on startup if any are missing):

DATABASE_URL=postgresql+asyncpg://postgres:YOUR_PASSWORD@localhost:5432/ga_cpa
JWT_SECRET=your-secret-key-here
ENCRYPTION_KEY=your-fernet-key-here
DEBUG=false

Generate a Fernet key: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

Database Setup

# Create the database
psql -U postgres -c "CREATE DATABASE ga_cpa;"

# Run migrations (004-006 are incremental)
psql -U postgres -d ga_cpa -f backend/db/migrations/004_audit_pii_redaction.sql
psql -U postgres -d ga_cpa -f backend/db/migrations/005_recurring_templates.sql
psql -U postgres -d ga_cpa -f backend/db/migrations/006_password_reset_tokens.sql

# Seed test data (optional -- creates 4 clients with all entity types)
cd backend && .venv/bin/python scripts/seed_test_data.py
# Use --reset flag to wipe and reseed

Note: The initial schema (tables, triggers, seed data) is created automatically by SQLAlchemy on first startup via create_all().

Frontend Setup

cd frontend
npm install
npm run build      # Production build

Run in Development

# Terminal 1: Backend
cd backend
source .venv/bin/activate
uvicorn app.main:app --reload

# Terminal 2: Frontend
cd frontend
npm run dev

Deploy to Production

bash deploy/setup.sh

This installs nginx with HTTPS (self-signed cert), creates launchd services for the backend, nightly backup, log rotation, and DB maintenance.

Accessing the App

Method URL
Local https://localhost
LAN https://192.168.1.104 (or your machine's IP)
Dev frontend http://localhost:5173
Dev backend http://localhost:8000

Default credentials: edward@755mortgage.com / admin123 (CPA_OWNER role)

LAN clients (Windows/Mac) need to trust the self-signed certificate. See deploy/windows-trust.md.

Run Tests

cd backend
.venv/bin/python -m pytest --tb=short -q
# 900 passed

API Overview

All endpoints are prefixed with /api/v1. Authentication via httpOnly JWT cookie (set on login).

Group Prefix Key Endpoints
Auth /auth Login, 2FA setup/verify/disable, password reset
Clients /clients CRUD, archive, restore, entity type
Chart of Accounts /clients/{id}/accounts CRUD, Georgia standard categories
Journal Entries /clients/{id}/journal-entries Double-entry GL, approval workflow
Vendors /clients/{id}/vendors CRUD
Bills (AP) /clients/{id}/bills Create, pay, void, check printing
Invoices (AR) /clients/{id}/invoices Create, approve, record payment, void, PDF
Bank Reconciliation /clients/{id}/bank-accounts Import, match, reconcile
Documents /clients/{id}/documents Upload, view, search
Employees /clients/{id}/employees CRUD, terminate
Payroll /clients/{id}/payroll Create run, submit, finalize, pay stub PDF
Approvals /approvals Queue, batch approve/reject
Reports /reports P&L, balance sheet, cash flow, AR/AP aging, PDF/CSV/Excel export
Tax Exports /tax GA G-7, 500, 600, ST-3, federal forms, W-2, 1099-NEC
Statements /clients/{id}/statements Client account statements, email
Recurring /clients/{id}/recurring-templates Recurring transaction templates
Bulk Import /clients/{id}/bulk-import CSV upload for bills/invoices (5,000 row cap)
Search /search Global search across clients, transactions, documents
Year-End /clients/{id}/year-end Year-end close process
Time Tracking /clients/{id}/time-entries Billable hours tracking
Service Billing /clients/{id}/service-invoices Firm billing to clients
Engagements /clients/{id}/engagements Engagement management
Contacts /clients/{id}/contacts Client contact records
Workflows /workflows Task/workflow management
Portal /portal Client portal messages
Fixed Assets /clients/{id}/fixed-assets Asset tracking, depreciation
Budgets /clients/{id}/budgets Budget creation and tracking
Check Sequence /clients/{id}/check-sequence Auto-increment check numbers
Firm Analytics /firm-analytics Cross-client metrics and trends
Operations /operations Backup, restore, health check
Audit Log /audit-log Immutable change history

Security

The system has been through a full security audit (11 findings, all fixed):

  • Password hashing: bcrypt with timing-attack mitigation
  • Authentication: httpOnly + Secure + SameSite=Strict cookies, JWT (30-min expiry)
  • 2FA: TOTP via pyotp, rate-limited (5/min), valid_window=0
  • Encryption at rest: Fernet for PII (SSN, tax ID)
  • Security headers: HSTS, X-Frame-Options, Content-Security-Policy, X-Content-Type-Options
  • SQL injection: SQLAlchemy parameterized queries throughout
  • XSS: React auto-escapes, no dangerouslySetInnerHTML
  • Rate limiting: Login (per-IP and per-email), 2FA endpoints
  • Request size limits: Middleware-enforced body size cap
  • Bulk import cap: 5,000 rows per CSV upload
  • Audit trail: Immutable PostgreSQL trigger-based logging of all changes
  • Encrypted backups: GPG AES-256, passphrase via fd (not visible in ps)
  • No default secrets: App crashes on startup if DATABASE_URL, JWT_SECRET, or ENCRYPTION_KEY missing
  • Production mode: DEBUG=false disables /docs, /redoc, /openapi.json

Compliance

This system handles real financial data under Georgia tax law. Key enforcement:

  • Double-entry: Every transaction balances debits and credits (DB-level CHECK constraint)
  • Audit trail: No hard deletes anywhere. All changes logged with old/new values, user, timestamp
  • Client isolation: Every table with client data has client_id as non-nullable FK; every query filters by it
  • Approval workflow: Associates enter drafts (PENDING_APPROVAL); only CPA_OWNER can approve/post to GL
  • Payroll gate: Finalization verified at both route level (require_role) and function level (verify_role)
  • Tax rate sourcing: Every rate constant cites its Georgia DOR / IRS source document and review date

See OPEN_ISSUES.md for 11 open rate-verification flags for TY2026.

Deployment

The system runs on macOS with these launchd services:

Service Plist Schedule
Backend (uvicorn) com.gacpa.backend Always running, auto-restart
Nightly backup com.gacpa.backup 2:00 AM daily, 30-day retention
Log rotation com.gacpa.logrotate Daily
DB maintenance com.gacpa.dbmaint Weekly VACUUM/REINDEX

nginx serves as an HTTPS reverse proxy with a self-signed certificate (10-year validity).

# Install everything
bash deploy/setup.sh

# Uninstall everything
bash deploy/teardown.sh

# Manual backup
bash deploy/backup.sh

# Restore from backup
bash deploy/restore.sh /path/to/backup.sql.gpg

Remaining Work

  1. CPA_OWNER compliance review -- Verify 11 open tax rate flags in OPEN_ISSUES.md
  2. End-to-end integration testing with real QuickBooks Online export data
  3. Team onboarding -- Create ASSOCIATE accounts, migrate first real client
  4. Trust self-signed cert on team machines (see deploy/windows-trust.md)
  5. Deferred features -- Plaid bank feeds (paid API), document OCR (Tesseract)
  6. Frontend pages -- Recurring templates manager, year-end close UI

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages