Commit Graph

33 Commits

Author SHA1 Message Date
5f4c482636 v0.16.0 — HomeBox CSV import + sold lifecycle + custom fields
Bring an existing HomeBox inventory straight in, and capture the fields HomeBox
has that we were missing (skipping asset IDs per Tony).

- Item: soldTo/soldPrice/soldDate/soldNotes + flexible customFields (JSON, e.g.
  VIN / oil weight for vehicles); both editable in the item dialog and shown on
  the detail page
- Pure HomeBox CSV parser (src/lib/inventory/homebox-import.ts, +5 tests) —
  RFC4180 quoting (commas/newlines/escaped quotes in fields), HomeBox's 0001-*
  null dates and 0 = empty price, semicolon labels, HB.field.* custom columns,
  nested 'A / B' location paths
- Import service + /api/v1/items/import: find-or-creates the nested locations
  and labels, creates items, recomputes location paths, returns a summary
- Inventory 'Import' button: paste/upload CSV, review every row with checkboxes
  (uncheck to skip), then import. Preview parses client-side (parser is pure)
- Verified end-to-end: nested locations, split labels, sold + custom fields,
  skip, quoted names, null-date handling. tsc + 38 tests + build green

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 01:01:17 -05:00
63569aabd3 v0.15.0 — Inventory depth (HomeBox parity) + Locations page
Rounds out Inventory toward HomeBox, and gives Locations a real home.

Inventory:
- Attach manuals, receipts, and warranty docs (any file), not just photos —
  attachment uploader now has a kind picker; WARRANTY kind added
- Richer purchase/warranty: purchasedFrom, warrantyDetails, lifetimeWarranty,
  insured (item dialog + detail facts + header badge)
- Schedule recurring maintenance from an item (creates a Task linked via
  itemId); item detail shows its maintenance with overdue flagged. Task create
  now accepts itemId/animalId

Locations:
- New Locations page + nav: browse/add/rename/move/delete the whole place tree
  (LocationManager over the existing /api/locations routes); shows plant/item
  counts per place. The spot to merge near-dupes before dropping legacy zone

Verified end-to-end against a running server (new fields round-trip, maintenance
task links to item, MANUAL attachment stored). tsc + 33 tests + build green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 00:34:07 -05:00
cffa739056 docs: add Animals module to README + CLAUDE.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 00:28:51 -05:00
39be24c2fc v0.14.0 — Animals & Pets
Livestock and household pets as leaves on the Location tree, mirroring Garden.

- Animal model (species/breed/sex/birthdate/location, soft-delete) + AnimalLog
  (feeding, vet, weight, medication, breeding, acquired, died); Task.animalId for
  recurring care reminders
- API-first /api/v1/animals (CRUD) + logs, animals:read/write scopes; animals
  service shared with the coming MCP
- Animals pages: list grouped by species with auto-computed age, detail with
  facts + latest weight + care log; add/edit/remove + log entry. Nav entry.
  Backup/restore cover the new tables
- Pure age.ts (newborn/days/months/years) with tests; verified end-to-end against
  a running server (create, vet + weigh-in logs, read-back)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 00:23:53 -05:00
777569a21a docs: add README, refresh CLAUDE.md for current modules + git-checkout deploy
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 00:18:06 -05:00
b0118d3fec v0.13.0 — Inventory (HomeBox): durable items that nest
The first inventory vertical on the shared spine. Things you own — tools, gear,
equipment — each living in a Location or inside another Item.

- Item model (kind DURABLE|CONSUMABLE; consumable fields present but unused so
  Pantry needs no migration), self-nesting via parentItemId (toolbox holds drill,
  with a cycle guard), value/warranty/serial/brand/qty, qrSlug, photo
- Label (m2m) + ItemAttachment (photos/manuals/receipts) + ItemLog
  (maintenance/repair/move/dispose) history; Task.itemId
- API-first: /api/v1/items (CRUD), labels, logs, multipart attachments — the UI
  consumes the same scoped endpoints. items service shared with the coming MCP
- Inventory pages: tree grouped by Location with items nested inside items;
  item detail with warranty status, photos, contents, history; add/edit/delete,
  log, photo upload. Nav entry. Backup/restore cover the new tables
- Pure value.ts (warrantyStatus, totalValue) with tests; verified end-to-end
  against a running server (nest, cycle-guard 400, log 201)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 00:12:03 -05:00
0904790dca Security: force first-login password change, gate admin tools, validate restore
Fixes from the code review:
- #1 Wire mustChangePassword: dashboard layout redirects to a new /change-password
  page + /api/account/change-password (verifies current pw, re-hashes, clears the
  flag, refreshes the session). Provisioned admins can no longer keep the default.
- #2 Assert NEXTAUTH_SECRET in production (not during build); set it on authOptions.
- #3 Backup page now server-gated to admins (split into server page + client panel),
  matching the Updates page.
- #4 Restore validates input: strict zod schema for the users table (known fields,
  role enum) + array checks for the rest; returns generic errors instead of String(err).

No version bump/changelog — left for you to fold into the next release (you're
editing those live). Not pushed, not deployed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:59:39 -05:00
c5bf108cb9 v0.12.0 — REST API + personal access tokens
A bidirectional API so other apps (Home Assistant, phone shortcuts, scripts,
and the coming MCP server) can read and update the homestead.

- ApiToken model (sha256-hashed, scoped, with prefix/lastUsed/expiry/revoke)
- authenticateRequest() accepts EITHER a NextAuth cookie session OR a Bearer
  PAT; cookie sessions get full access, tokens are limited to their scopes
  (write implies read; resource and global wildcards). ApiError + handleApiError
- Shared service layer (plants/tasks/locations/plant-types) reused by every
  endpoint and, later, the MCP server — logic lives once
- /api/v1: plants (read + add log), plant-types, locations, tasks (read/create/
  complete), and a whoami/discovery root
- Settings → API tokens: create with per-resource read/write checkboxes, raw
  token shown once, revoke; tokens added to backup/restore
- Pure tests for scope matching + token hashing; verified end-to-end (401/403/
  201, lastUsedAt) against a running server

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:55:58 -05:00
cdb21ed58a v0.11.0 — Plant types: the reusable "kind" record
A rich-but-all-optional reference record per kind of plant (care, sun, water,
bloom & harvest windows, toxic-to-pets, edible parts, spacing), distinct from a
specific planting or a group.

- PlantType model + optional Plant.plantTypeId; migration + idempotent backfill
  that seeds 247 kinds from the built-in plant library and links plantings by
  species/common name (wired into the deploy entrypoint)
- /api/plant-types CRUD; new "Plant types" section (browse by category, edit a
  kind, see every spot you've planted it)
- New plants auto-link to their type on create; plant detail shows "More about…"
- PlantType added to backup/restore; bump APP_VERSION 0.11.0 + changelog

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:46:07 -05:00
9c0312676a v0.10.0 — Location spine: garden moved onto a shared place tree
Completes the Location feature (schema + migration landed earlier under 98cabc5).

- Hierarchical Location model is the shared spine; unlimited nesting
- Garden add/edit now picks a reusable Location (inline create) instead of
  freeform text; garden groups By Location off the real tree
- Dual-write keeps legacy Plant.zone in sync with location.name (Release A)
- /api/locations CRUD + /api/locations/[id]/log (logs a location + its sub-locations)
- Location tree pure-core (buildTree/computePath/descendantIds) with tests
- Location added to backup/restore export
- Bump APP_VERSION 0.10.0 + plain-English changelog entry

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:36:54 -05:00
6f8fe9a798 ignore self-update runtime log
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:48:47 -05:00
98cabc514d v0.9.1 — Self-update: 403 on trigger mismatch + reliability
webhook returns 200 even when a trigger rule isn't satisfied, which would let
the app's res.ok check falsely report success if the secret drifted. Set
trigger-rule-mismatch-http-response-code: 403 so unauthorized triggers are
clearly rejected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:44:36 -05:00
4e02339f59 updater: fix webhook secret template (backtick literal, not escaped quotes)
The -template parser is Go text/template; JSON-escaped \" broke the action.
Backtick raw-string literal is valid inside the JSON string and parses cleanly.
Config-only (mounted + hotreload) — no app rebuild.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:41:28 -05:00
a4a6fe4c9b updater: mark /appdata as safe.directory before git ops
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:22:32 -05:00
1c66dbd481 v0.9.0 — One-click self-update (homegrown, no OTM)
Add an admin 'Pull & rebuild' button (Settings → Updates). It POSTs an
admin-gated route that signals a privileged 'updater' sidecar (adnanh/webhook +
docker socket) over the internal network with a shared secret; the sidecar runs
'git fetch && reset --hard origin/master && docker compose up -d --build app'
detached. The UI polls /api/version until the rebuilt app returns on the new
version, then reloads.

Secret matching uses webhook -template + getenv so UPDATER_SECRET stays out of
the repo (host .env only). No request data reaches the shell — the command is
fixed in updater/update.sh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:20:48 -05:00
42cd7a7b4d v0.8.0 — Update-available detection (version chip + changelog)
Footer becomes a changelog chip and shows an 'Update available' badge when a
newer APP_VERSION exists upstream. Detection reads src/lib/version.ts from the
Gitea default branch (dms model) and compares — self-contained, no OTM control
plane. Adds src/lib/update-check.ts and GET /api/version (also a running-version
probe for the upcoming one-click rebuild).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:12:18 -05:00
2e0931343f v0.7.0 — Suggestions module via @otm/account-panel
Wire the shared Gitea-backed suggestions panel: page, list/create + comments +
upload API routes, sidebar link. Suggestions file as issues on bonna61/Moonbase;
screenshot uploads persist via a mounted volume. Mirrors the FMB wiring.

Secrets (NEXTAUTH_SECRET, GITEA_TOKEN) moved out of docker-compose.yml to an
interpolated gitignored .env on the host, per CLAUDE.md (never commit the token).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:03:47 -05:00
1f5aa001a8 v0.6.0 — Backup & Restore page; install netcat for Postgres-wait
Version the backup/restore feature that merged in unversioned, and add
netcat-openbsd to the bookworm-slim runtime so the new entrypoint Postgres
readiness check (nc -z postgres 5432) works instead of looping forever.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:52:15 -05:00
Bonna Moon
c12e607be7 Add Backup & Restore page (zip download + drag-drop upload) 2026-06-15 21:47:49 -05:00
Bonna Moon
9ec4457552 Add db:backup and db:restore npm scripts 2026-06-15 21:45:09 -05:00
Bonna Moon
4bc5ddc77b Wait for Postgres ready before running migrations 2026-06-15 21:39:21 -05:00
6603717cbb v0.5.2 — Fix Docker deploy on NAS (glibc base, openssl, root, full deps)
The NAS container was crash-looping: npx pulled Prisma 7.8.0 (which rejects
url in the datasource), and the alpine + non-root + standalone setup couldn't
detect openssl or write the migration engine. Switch to the FMB-proven runtime
(node:20-bookworm-slim + openssl, run as root, full node_modules, next start)
so the local pinned Prisma 5.22 CLI runs and migrations apply cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:36:30 -05:00
Bonna Moon
1ebfb06e68 Fix Docker entrypoint using pinned local Prisma CLI
npx prisma was downloading Prisma CLI v7.8.0 which dropped the
url = env("DATABASE_URL") schema syntax. Use the project's own
installed Prisma CLI from node_modules instead, copied from the
builder stage.
2026-06-15 21:09:08 -05:00
Bonna Moon
175ebecdc8 Add public dir so Docker COPY doesn't fail
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 21:00:24 -05:00
Bonna Moon
4245232834 Fix TS errors blocking Docker build; docker-compose builds locally
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:56:37 -05:00
Bonna Moon
04dec2a198 v0.5.1 — Reminders, plant groups, location views, Wikipedia photos, Docker deploy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:53:03 -05:00
Bonna Moon
e3f6a8ec92 v0.2.3 — Fix new plant categories rejected by API validation 2026-06-15 17:45:34 -05:00
Bonna Moon
f27838745c v0.2.2 — Fix add plant form (simplify, remove react-hook-form) 2026-06-15 17:41:06 -05:00
Bonna Moon
ed4a50dae9 v0.2.1 — Fix add plant button not submitting 2026-06-15 17:36:46 -05:00
Bonna Moon
5938c6346e v0.2.0 — Plant autocomplete + annual/perennial flower categories 2026-06-15 17:07:26 -05:00
Bonna Moon
78728963f4 v0.1.1 — Garden: edit and delete plants 2026-06-15 16:58:03 -05:00
Bonna Moon
eb43ec37a0 Add CLAUDE.md project notes 2026-06-15 16:15:20 -05:00
Bonna Moon
99918fffbc v0.1.0 — Moon Base initial scaffold: auth, garden plant registry + log 2026-06-15 16:14:48 -05:00