ten99timecard/README.md
2026-03-04 21:21:59 -05:00

107 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ten99timecard
Income logging, projections, and quarterly estimated tax calculations for US
1099 contractors. Entirely client-side by default — your data is encrypted with
your password and stored in a browser cookie. Optionally sync to a self-hosted
MongoDB backend (still encrypted end-to-end; the server never sees plaintext).
**Not tax advice.** Calculations are federal-only approximations. Talk to a CPA.
---
## What's inside
| Page | What it does |
| --- | --- |
| **Dashboard** | Configurable stat widgets + charts. YTD income, projected annual tax, next quarterly due date. |
| **Ledger** | Three tabs: **Work Log** (non-taxable billable record — flat amount *or* hours×rate), **Payments** (taxable 1099 income), **Expenses** (with deductible flag). Each is a year→month→day→item collapsible spreadsheet with global expand-to-level controls. Period summaries show totals, per-child averages, and linear projections. |
| **Tax** | Full estimated-tax breakdown: SE tax (with SS wage-base cap + additional Medicare), QBI deduction, progressive federal brackets, safe harbor (100%/110% rule), quarterly schedule with past-due flags. Fields you haven't filled in (prior-year AGI, W-2 withholding, etc.) appear as **highlighted prompts** explaining why they'd sharpen the estimate. |
| **Timer** | Billable-work stopwatch. Start / Pause / Split / Reset. Each split captures the rate *at split time* (changing the rate never rewrites history). Editable split table with two-step confirm. One-click push to Work Log. Logged rows get a badge. **Crash-proof:** state is heartbeated to a cookie every second; if the page reloads while running, a red banner shows exactly when you crashed, when you came back, and the gap — with a button to subtract the gap or keep it (because you were working during the outage). |
| **Settings** | Theme picker (10 themes × dark/light), default hourly rate, storage mode (cookie / file / cloud), encrypted file import/export. |
### Themes
Standard · Sakura · Pumpkin · Fall · Aqua · Lavender · Comic · Manga · High Contrast · Cyberpunk — each in dark & light.
---
## Quick start
```bash
npm install
npm run dev # client on http://localhost:5173
```
The app works out of the box with **cookie storage**. No server, no database,
no account. Open the page, create a local vault (username + password), start
logging. Your password derives an AES-256-GCM key via PBKDF2 (100k rounds);
the cookie holds only ciphertext.
### Run the cloud sync server (optional)
```bash
cp server/.env.example server/.env # edit MONGO_URI + JWT_SECRET
npm run dev:server # Express on http://localhost:4000
```
Then switch storage mode to **Cloud** in Settings. The server stores one opaque
blob per user. Plaintext never leaves the browser.
### Google OAuth (optional)
Fill `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` in `server/.env`. Without these
the server still serves email+password auth.
---
## Tests
```bash
npm test # 155 tests: 135 client (Vitest+RTL) + 20 server (supertest+mongodb-memory-server)
npm run build # tsc --noEmit && vite build, both workspaces
```
Coverage spans the tax engine, crypto round-trip, cookie chunking, statistics
rollup/projection, timer crash recovery, store CRUD, and component interaction.
---
## Stack
**Client:** Vite · React 18 · TypeScript 5 · Zustand · React Router · Recharts · date-fns · Web Crypto API
**Server:** Express · MongoDB · bcrypt · jsonwebtoken · Passport (Google OAuth) · zod
**Testing:** Vitest · React Testing Library · jsdom · supertest · mongodb-memory-server
Everything is MIT/Apache/BSD licensed.
---
## Tax math (summary)
- **SE tax** = 15.3% of `netProfit × 0.9235`
(12.4% Social Security up to wage base, 2.9% Medicare uncapped, +0.9% additional Medicare above threshold)
- **Half of SE tax** is an above-the-line deduction
- **QBI §199A** = 20% of qualified business income, limited to 20% of taxable income, phased out above threshold
- **Taxable income** = gross deductible expenses ½SE QBI standard deduction other adjustments
- **Safe harbor** = pay the lesser of 90% of current-year tax or 100% (110% if prior AGI > $150k) of prior-year tax, split across four quarters
- Tax year data shipped for **2024** and **2025**; unknown years fall back to closest
State tax is intentionally out of scope.
---
## Storage model
| Mode | Where | Encrypted? |
| --- | --- | --- |
| Cookie (default) | `document.cookie`, chunked at ~3.8KB, mirrored to localStorage | ✅ AES-256-GCM |
| File | Download/upload `.t99` blob | ✅ Same key derivation |
| Cloud | `PUT /api/data` on your server | ✅ Encrypted *before* upload |
Ciphertext format: `base64( salt[16] || iv[12] || aes-gcm-ciphertext )`.
Lose your password → lose your data. That's the point.
---
## License
MIT