feat: local data model and storage (spec 1.3) #6

Merged
addison merged 17 commits from implement-spec-1-3-storage into main 2026-07-03 09:50:19 -04:00
Collaborator

Implements spec 001-mvp/003 Local Data Model and Storage.

Delivered

  • Storage foundation: data dir (Documents/shed-ledger via adrg/xdg), modernc.org/sqlite, user_version migration runner, MVP schema migration + seeded statuses, ErrNewerSchema forward-compat guard
  • Repository operations: customer/feature/model CRUD, status list, building CRUD with serial lookup + feature join handling, photo metadata ops
  • Photo file management under photos// kept in step with the photo table (transactional add with cleanup, delete removes row+file, building delete removes dir)
  • App wiring in main.go: open store on startup, graceful launch on newer-schema or open failure so Updates page stays reachable
  • Review pass applied (RFC3339 consistency, redundant index removed, dead code removed, extra FK test coverage)
  • Spec marked completed

Verification

  • go build ./..., go vet ./..., gofmt clean
  • GOOS=windows go build ./... (pure-Go driver cross-compiles)
  • go test ./internal/storage/ — 15 tests covering schema, seeding, migrations, forward-compat guard, all repos, FK behaviors, photo files
Implements [spec 001-mvp/003 Local Data Model and Storage](specs/001-mvp/003-local-data-model-and-storage/SPEC.md). ## Delivered - [x] Storage foundation: data dir (Documents/shed-ledger via adrg/xdg), modernc.org/sqlite, user_version migration runner, MVP schema migration + seeded statuses, ErrNewerSchema forward-compat guard - [x] Repository operations: customer/feature/model CRUD, status list, building CRUD with serial lookup + feature join handling, photo metadata ops - [x] Photo file management under photos/<building-id>/ kept in step with the photo table (transactional add with cleanup, delete removes row+file, building delete removes dir) - [x] App wiring in main.go: open store on startup, graceful launch on newer-schema or open failure so Updates page stays reachable - [x] Review pass applied (RFC3339 consistency, redundant index removed, dead code removed, extra FK test coverage) - [x] Spec marked completed ## Verification - `go build ./...`, `go vet ./...`, `gofmt` clean - `GOOS=windows go build ./...` (pure-Go driver cross-compiles) - `go test ./internal/storage/` — 15 tests covering schema, seeding, migrations, forward-compat guard, all repos, FK behaviors, photo files
Co-authored-by: Shelley <[email protected]>
- app-managed data dir in Documents/shed-ledger via adrg/xdg
- pure-Go modernc.org/sqlite driver with foreign_keys + WAL pragmas
- user_version migration runner with ErrNewerSchema forward-compat guard
- MVP migration: full schema, serial unique index, seeded statuses

Co-authored-by: Shelley <[email protected]>
dev-bot changed title from feat: local data model and storage (spec 1.3) to WIP: feat: local data model and storage (spec 1.3) 2026-07-03 06:55:27 -04:00
- CRUD for customer, feature, model; list for seeded statuses
- building CRUD with serial lookup, trim/empty/duplicate serial errors,
  and feature attachment via building_feature join
- photo metadata operations ordered by sort_order, created_at
- shared ErrNotFound/ErrSerialRequired/ErrSerialTaken sentinels

Co-authored-by: Shelley <[email protected]>
- AddPhoto writes photos/<building-id>/<id>.<ext> and inserts the row
  transactionally, cleaning up the file on failure
- DeletePhoto removes row then file; missing file tolerated
- deleting a building removes its photo directory tree
- PhotoPath exposes on-disk location for later serving

Co-authored-by: Shelley <[email protected]>
Launches gracefully without building data when the database schema is
newer than the app (forward-compatibility guard) or the store fails to
open, so the Updates page stays reachable.

Co-authored-by: Shelley <[email protected]>
- use RFC3339 second-precision now() everywhere, incl. seeded statuses
- drop redundant inline UNIQUE; keep named serial-number unique index
- remove unused CreatePhoto and duplicate GetBySerialNumber
- guard test also asserts -wal/-shm untouched on newer-schema open
- add FK coverage: feature delete cascade, model/status SET NULL

Co-authored-by: Shelley <[email protected]>
dev-bot changed title from WIP: feat: local data model and storage (spec 1.3) to feat: local data model and storage (spec 1.3) 2026-07-03 07:46:47 -04:00
- backend serves GET /api/health with available/updateRequired/message
- app layout fetches health on load and shows a danger banner when
  storage is unavailable, with a Go to Updates link when the database
  schema is newer than the app
- buildings routes are gated (content and New Building action) while
  storage is unavailable; Updates page stays fully usable

Co-authored-by: Shelley <[email protected]>
- move /api/health fetch from layout load to onMount so routes
  (especially Updates) render immediately
- rename storage-status naming to health/backendStatus: the endpoint
  reports overall backend availability, not just storage

Co-authored-by: Shelley <[email protected]>
Drop the app-wide banner; it duplicated the buildings-page card and
appeared on the Updates page, which must stay clean for updating.

Co-authored-by: Shelley <[email protected]>
Merge branch 'main' into implement-spec-1-3-storage
All checks were successful
PR Validation / validate (pull_request) Successful in 3m33s
64417300df
fix: photo removal
Some checks failed
PR Validation / validate (pull_request) Failing after 2m3s
cd970fa6f5
fix: skip permission-based cleanup tests when running as root
All checks were successful
PR Validation / validate (pull_request) Successful in 3m34s
56194fdc13
Root ignores directory write permissions, so the chmod-0555 setup
cannot force a removal failure in CI containers.

Co-authored-by: Shelley <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kwila/shed-ledger!6
No description provided.