Files
wotra/README.md

150 lines
6.7 KiB
Markdown

# Wotra — Working Time Tracker
A self-hosted working time tracker with a Go backend and a Svelte PWA frontend. Offline-capable, single-binary deploy.
## Features
- **Start / Stop** time tracking with an optional note.
- **Close days**: merges all entries (worked_ms = sum of durations, breaks excluded).
- **Mark days** as holiday, vacation, or sick (auto-credits expected daily hours).
- **Close weeks**: computes overtime/undertime against a frozen snapshot of your expected hours.
- **Settings history**: change hours/week with an `effective_from` date — past closed weeks are unaffected.
- **PWA + offline**: works without a network connection; syncs via IndexedDB outbox when back online.
- **CSV export**: entries, days, weeks.
- **Midnight guard**: running entries are automatically stopped at 23:59:59 if they cross midnight.
## Quick Start
Tool versions are declared in `mise.toml`. Install [mise](https://mise.jdx.dev) and run `mise install` once to get the correct Go and Node versions.
### Development
```bash
# Install frontend dependencies (first time only)
mise run install
# Start both servers (Go API + Vite dev server)
mise run dev
# Go API: http://localhost:8080
# Vite UI: http://localhost:5173 (with /api proxy)
```
`AUTH_TOKEN` defaults to `devtoken` in `mise.toml`. Override it by setting the variable in your environment before running.
Open `http://localhost:5173`, go to **Settings**, enter your token.
### Production (single binary)
```bash
mise run build # builds web/ then embeds it in the Go binary
AUTH_TOKEN=mysecrettoken ./wotra
# open http://localhost:8080
```
### All tasks
| Task | Description |
|---------------|--------------------------------------------------|
| `mise run build` | Build production binary (web + Go) |
| `mise run build:web` | Build Svelte frontend only |
| `mise run build:go` | Build Go binary only |
| `mise run dev` | Start API + UI dev servers concurrently |
| `mise run dev:api` | Start Go API server only |
| `mise run dev:ui` | Start Vite dev server only |
| `mise run test` | Run all Go tests |
| `mise run install` | Install frontend npm dependencies |
| `mise run clean` | Remove build artifacts |
## Configuration (environment variables)
| Variable | Default | Description |
|-------------|-------------|----------------------------------------------|
| `AUTH_TOKEN` | **required** | Bearer token for API access |
| `PORT` | `8080` | HTTP port |
| `DB_PATH` | `wotra.db` | SQLite database file path |
| `TZ` | `UTC` | Timezone for day/week key calculation |
## API Reference
All API endpoints require `Authorization: Bearer <token>` except `/healthz`.
### Entries
| Method | Path | Description |
|--------|-----------------------------|--------------------------|
| POST | `/api/entries/start` | Start tracking |
| POST | `/api/entries/{id}/stop` | Stop a specific entry |
| GET | `/api/entries?from=&to=` | List entries by date |
| PUT | `/api/entries/{id}` | Edit start/end/note |
| DELETE | `/api/entries/{id}` | Soft-delete an entry |
### Days
| Method | Path | Description |
|--------|-------------------------------|--------------------------------------|
| GET | `/api/days?from=&to=` | List closed days |
| POST | `/api/days/{day}/close` | Close a day (merge entries) |
| POST | `/api/days/{day}/mark` | Mark as holiday/vacation/sick |
| DELETE | `/api/days/{day}/close` | Reopen a closed day |
### Weeks
| Method | Path | Description |
|--------|-------------------------------|--------------------------------------|
| GET | `/api/weeks?from=&to=` | List closed weeks |
| POST | `/api/weeks/{week}/close` | Close a week (compute overtime) |
| DELETE | `/api/weeks/{week}/close` | Reopen a closed week |
Week key format: `YYYY-Www` (e.g. `2024-W03`).
### Settings
| Method | Path | Description |
|--------|-------------------------|------------------------------------|
| GET | `/api/settings` | Current effective settings |
| PUT | `/api/settings` | Add a new settings version |
| GET | `/api/settings/history` | All settings history |
### Export
| Method | Path | Description |
|--------|------------------------------|--------------------------|
| GET | `/api/export/entries.csv` | Export entries as CSV |
| GET | `/api/export/days.csv` | Export days as CSV |
| GET | `/api/export/weeks.csv` | Export weeks as CSV |
### Sync
| Method | Path | Description |
|--------|-------------------|-------------------------------------|
| POST | `/api/sync/pull` | Pull changes since a version |
| POST | `/api/sync/push` | Push local changes (advisory) |
### Health
| Method | Path | Description |
|--------|-------------|--------------------------|
| GET | `/healthz` | Unauthenticated health |
## Architecture
```
┌─────────────────────────┐ ┌──────────────────────────┐
│ Svelte PWA (client) │ ◄─────► │ Go service (API) │
│ - IndexedDB (Dexie) │ HTTPS │ - REST/JSON endpoints │
│ - Service Worker │ JSON │ - Business logic │
│ - Sync outbox │ │ - SQLite (modernc) │
└─────────────────────────┘ └──────────────────────────┘
```
See [PLAN.md](PLAN.md) for the full design document.
## Development Notes
- **Go module**: `github.com/wotra/wotra`
- **SQLite driver**: `modernc.org/sqlite` (pure Go, no CGO)
- **Day boundary**: entries must not cross midnight; the server auto-stops any running entry at 23:59:59 local time.
- **Settings history**: `effective_from` lets you change hours/week without rewriting past closed weeks.
- **Overtime**: stored as a signed `delta_ms` on each `closed_weeks` row. Frozen at close time.