Files
SimpleFinanceDash/.planning/codebase/INTEGRATIONS.md

120 lines
4.0 KiB
Markdown

# External Integrations
## Database: PostgreSQL 16
**Location**: `backend/internal/db/db.go`, `backend/internal/db/queries.go`
### Connection
- **Driver**: `github.com/jackc/pgx/v5` (pgx connection pool)
- **Default URL**: `postgres://simplefin:simplefin@localhost:5432/simplefindb?sslmode=disable`
- **Environment Variable**: `DATABASE_URL`
- **Connection Pool**: `pgxpool.Pool` with automatic management
### Schema
**Tables** (from `backend/migrations/001_initial.sql`):
1. **users** — id (UUID), email, password_hash, oidc_subject, display_name, preferred_locale, timestamps
2. **categories** — id (UUID), user_id (FK), name, type (enum), icon, sort_order, timestamps
3. **budgets** — id (UUID), user_id (FK), name, start_date, end_date, currency, carryover_amount, timestamps
4. **budget_items** — id (UUID), budget_id (FK), category_id (FK), budgeted_amount, actual_amount, notes, timestamps
5. **schema_migrations** — version tracking
**Enum**: `category_type` — bill, variable_expense, debt, saving, investment, income
**Numeric precision**: `NUMERIC(12, 2)` in PostgreSQL, `shopspring/decimal` in Go
### Migration Runner
- Custom implementation in `backend/internal/db/db.go`
- Reads `.sql` files from embedded filesystem (`embed.FS`)
- Tracks applied versions in `schema_migrations` table
- Sequential numbering: `001_initial.sql`, `002_...`, etc.
## Authentication
### Local Auth (Active)
**Location**: `backend/internal/auth/auth.go`
- **Password hashing**: bcrypt with `DefaultCost`
- **Session**: JWT (HS256) in HTTP-only cookie
- **Secret**: `SESSION_SECRET` environment variable
- **Token TTL**: 7 days
- **Cookie**: HttpOnly, SameSite=Lax, MaxAge=7 days
**Routes**:
- `POST /api/auth/register` — Create account
- `POST /api/auth/login` — Login
- `POST /api/auth/logout` — Clear cookie
- `GET /api/auth/me` — Current user
### OIDC (Planned, Not Implemented)
**Location**: `backend/internal/api/handlers.go` (stubs returning 501)
- Routes: `GET /api/auth/oidc`, `GET /api/auth/oidc/callback`
- Environment variables defined in `compose.yml`: `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`
- DB support ready: `oidc_subject` column, `GetUserByOIDCSubject()`, `UpsertOIDCUser()` queries
## CORS
**Location**: `backend/internal/api/router.go`
```go
AllowedOrigins: ["http://localhost:5173", "http://localhost:8080"]
AllowedMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
AllowedHeaders: ["Content-Type"]
AllowCredentials: true
```
## Frontend API Client
**Location**: `frontend/src/lib/api.ts`
- Base URL: `/api` (proxied to `http://localhost:8080` via Vite in dev)
- Uses native Fetch API with `credentials: 'include'`
- Custom `ApiError` class for error handling
- Typed endpoints: `auth.*`, `categories.*`, `budgets.*`, `budgetItems.*`, `settings.*`
## Internationalization (i18n)
**Location**: `frontend/src/i18n/`
- **Library**: i18next + react-i18next
- **Languages**: English (en, default), German (de)
- **Keys**: ~87 per language (auth, navigation, dashboard, budget, categories, settings)
- **User preference**: Stored in DB (`preferred_locale` column)
## Deployment
### Docker (Multi-stage Build)
**Location**: `Dockerfile`
1. **Stage 1** (bun): Build frontend → `frontend/dist`
2. **Stage 2** (golang:1.24-alpine): Build Go binary with embedded frontend + migrations
3. **Stage 3** (alpine): Runtime with `ca-certificates`, port 8080
### Docker Compose
**Location**: `compose.yml`
- **app**: Go server (:8080), depends on db
- **db**: PostgreSQL 16 (:5432), health check, `pgdata` volume
### Environment Variables
| Variable | Purpose | Required |
|----------|---------|----------|
| `DATABASE_URL` | PostgreSQL connection string | Yes |
| `SESSION_SECRET` | JWT signing secret | Yes (production) |
| `OIDC_ISSUER` | OIDC provider URL | No (future) |
| `OIDC_CLIENT_ID` | OIDC client ID | No (future) |
| `OIDC_CLIENT_SECRET` | OIDC client secret | No (future) |
## External Services
**None currently integrated.** No third-party APIs, webhooks, payment processors, email providers, or message queues.