Commit graph

11 commits

Author SHA1 Message Date
ce2efd9be7 feat: persistent session + logout button + auto-redirect for authenticated users
- Logout button added to dashboard and event page headers
- Landing page checks for valid session cookie → auto-redirects to dashboard
- Session cookie persists 24h — closing and reopening browser keeps login
2026-06-05 11:24:05 +00:00
91534ed8bd fix: renderOTPForm in auth.go now uses cached single-field template
- Was using its own inline template with 6 digit_0..digit_5 fields
- Now calls getTemplate('otp_form') which has the single 6-digit input
- templates.go already had the correct single-field version
2026-06-03 07:57:56 +00:00
bb34528bf5 feat: single OTP field, event metadata on page, delete event
- OTP: 6 separate inputs → single 6-digit field with copy/paste support
- Event page: shows name, currency, exchange rate at top
- Edit toggle: unlock to edit fields, lock to save (via PUT)
- Delete button with confirmation popup
- DeleteEvent handler + DB function + route
- Backward compatible: collectOTP strips non-digits
2026-06-03 07:46:12 +00:00
92f070440f refactor: implement best-practice recommendations from code review
MUST FIX:
- M1: Fixed ignored errors in AI providers (json.Marshal, http.NewRequest, json.Unmarshal)
- M2: Template cache — pre-parse all templates once at startup, reuse via getTemplate()
- M3: Fixed silent ParseFloat error fallbacks — now returns HTTP 400 on invalid amounts
- M4: Wrapped readFile errors with context (fmt.Errorf with %w)
- M5: Deleted stale llm.go placeholder file
- M6: Renamed utils.New() to utils.NewUUID() for clarity
- M7: Validate current_event_id cookie UUID format, prevent tampering

SHOULD FIX:
- S4: Added utils.Timestamp() helper to replace repeated time.Now().Format() calls
- S6: Added request ID middleware for concurrent request log tracing
- S7: Increased DB pool from 1 to 4 connections (HTMX concurrency)
- S8: Graceful shutdown via http.Server.Shutdown() on SIGINT/SIGTERM
- S9: Storage served behind auth middleware with path traversal check

COULD FIX:
- C2: renderOTPForm uses cached template (not per-request Must)
- C3: CSP pinned to unpkg.com/htmx.org@1.9.10
- C4: Added ReadHeaderTimeout, ReadTimeout, WriteTimeout, IdleTimeout
- C7: PDF generation auto-adds page breaks when content overflows

ADDITIONAL:
- Pass config to AI provider constructors (newGeminiProvider, newOpenAIProvider)
- Value receivers on geminiProvider/openaiProvider (empty structs)
- Added envOrDefault() helper in ai/receipt.go
- Session cleanup goroutine started in main.go
- Removed duplicate imports and unused html/template from handlers
2026-05-31 02:13:07 +00:00
a7381bde0c fix: final vulnerability sweep — storage auth, security headers, body limits, cookie flags
- Storage route moved behind auth middleware (was publicly accessible)
- Security headers: X-Content-Type-Options, X-Frame-Options, CSP, Referrer-Policy
- Request body size limit: 10 MB on all endpoints via MaxBytesReader
- Session cookie now sets Secure flag when BASE_URL uses HTTPS
- readFile() returns proper errors for dirs & oversized files (was nil,nil)
- Removed dead DEEPSEEK_API_KEY code from main.go
- Added fmt import to ai/receipt.go for error formatting
2026-05-31 02:01:12 +00:00
e831fcf617 fix: resolve 7 critical security findings from code review
CR-1: Path traversal in createReceiptZip — validate image_path is within storage/
CR-2: Missing authz on EditExpense/UpdateExpense — verify event ownership
CR-3: OTP timing side-channel — use crypto/subtle.ConstantTimeCompare
CR-4: Logout doesn't invalidate session — moved to AuthHandler with Sessions.Delete()
CR-5: OTP reuse race condition — mutex lock around validate+delete
CR-6: Live credentials on disk — removed .env from disk entirely
CR-7: No TLS — documented as expected behind-proxy deployment

Additional:
- Removed stale github.com/expenseflow import path from auth.go
- Made EnvironmentFile optional (prefix with -) so .env is not required
- App runs and starts clean without any .env file
2026-05-31 01:50:08 +00:00
f50048e833 chore: rename to ReceiptNext + deployment scripts
- Full rename: module path, imports, directory structure
- install.sh: one-command bare-metal deployment
- contrib/receiptnext.service: systemd service file
- Makefile: build, install, manage service
- .gitenv updated to ReceiptNext
- New Releases page on git.lohmar.co.uk/cclohmar/ReceiptNext
2026-05-30 14:20:49 +00:00
dcb43b08a0 feat: send receipt images as ZIP attachment with report
- Email now includes both report (CSV/PDF) + ZIP of all receipt images
- ZIP images named {event-name}-{index}.{ext} matching list order
- Uses Go's archive/zip (stdlib, no external deps)
- Sender.SendReport now accepts []*Attachment for multiple files
- Gracefully skips missing image files with warnings
2026-05-30 13:38:23 +00:00
64f5b9a65b fix: mobile receipt capture not working - missing name attribute on file input + htmx targetError on OTP verification 2026-05-30 11:34:36 +00:00
6b6196a59a fix: nil pointer panic when EmailSender is not configured 2026-05-29 20:05:01 +00:00
ca970104ee chore: initial commit — ExpenseFlow AI-Powered Expense Tracker
- Passwordless email OTP authentication
- Event-based expense tracking with HTMX UI
- AI receipt extraction via DeepSeek Vision API
- CSV/PDF report generation with email filing
- PWA with service worker and manifest
- Mobile-first responsive design
- SQLite database with auto-migration
2026-05-29 19:43:30 +00:00