- Move embed_prod.go/embed_dev.go out of cmd/wotra/ into root-level
assets_prod.go / assets_dev.go (package assets). go:embed paths
must be relative to the source file; cmd/wotra/ cannot reach
../../web/build.
- Update cmd/wotra/main.go to import the root assets package.
- Change mise.toml build task from parallel depends to sequential
shell commands (build:web then build:go) so the frontend is always
compiled before the Go embed runs.
- Add LogClosedDayDelete and LogClosedWeekDelete to SyncStore
- Inject syncStore into EntryService; log Start, Stop, StopByID,
Update, CreateInterval, Delete, AutoStopStalledEntries
- Inject syncStore into DayService; log CloseDay, MarkDay, ReopenDay,
and the recomputeWeek closed-week upsert
- Inject syncStore into SettingsService; log Upsert, UpdateSettings,
DeleteSettings
- Add LogClosedWeek/LogClosedWeekDelete calls in WeekService.CloseWeek
and ReopenWeek
- Update main.go and all service test helpers for new constructor signatures
- All Go tests and 19 Vitest tests pass
- Migration 003: adds logged_at to sync_log for TTL pruning; migrates
settings_history to UUID TEXT PK with updated_at column
- SyncStore: Prune() deletes rows older than 30d and writes a '_pruned'
marker at the boundary version; Pull() calls Prune lazily and returns
ErrSyncStale (410) when the client's since_version is behind the marker
- sync_handler.go: GET /api/sync/pull?since=N; POST /api/sync/push with
last-updated_at-wins conflict resolution for entries, balance_adjustments,
settings_history; closed_days/closed_weeks skipped (server-only mutations)
- router.go: passes entryStore, adjustmentStore, settingsStore to SyncHandler
- settings_store.go: UUID PK, updated_at column, Upsert() for push path
- settings_service.go: generates UUID on create, sets updated_at on update
- settings_handler.go: ID params changed from int64 to string
- domain.go: Settings.ID string, Settings.UpdatedAt added
- client.ts: all mutation methods catch TypeError (offline) and fall back
to Dexie write + outbox enqueue; crypto.randomUUID() for offline creates;
Settings.id type changed to string
- db.ts: Dexie v3 — settings_history key path changed to string UUID;
upgrade handler clears table for repopulation via pull
- sync.ts: real pushOutbox to POST /api/sync/push; pullChanges uses GET
with ?since=N; 410 triggers coldStart() + retry; coldStart() wipes all
tables and resets last_version
- 4 new Go store tests covering normal pull, stale client, empty prune,
client-ahead-of-marker; all tests pass (store + service, 19 Vitest)
When a day is closed, re-closed, or reopened, DayService now
recomputes worked_ms and delta_ms on the closed week containing
that day (if the week is already closed). This prevents stale
delta values after editing entries and re-closing a day.
- DayService.recomputeWeek: sums worked_ms from all closed_days
in the week, updates closed_weeks row preserving expected_ms
- NewDayService now takes ClosedWeekStore
- WeekKeyForDayKey exported helper (used by DayService)
- TestWeekSnapshotUpdatesWhenDayReopened regression test
Previously any past workday without a closed_days record blocked week
close. Now only days that actually have entries require an explicit
close. Empty workdays count as 0h worked, which is reflected in the
weekly delta automatically.
- WeekService.CloseWeek: after finding no closed_days record, check
whether the day has any entries; only error if it does
- NewWeekService: takes EntryStore to support the above check
- Updated TestCloseWeekMissingDayFails to reflect the new semantic
(test now creates entries on Friday but leaves it unclosed)