Pantry now runs on the v1 API like Inventory/Animals: service layer in
src/lib/services/pantry.ts, pure logic + tests in src/lib/pantry/core.ts,
thin routes at /api/v1/pantry/* riding the items:* scopes. Pulls write
ItemLog type USED with a structured amount (queryable consumption).
Bulk-use runs its reads inside the transaction, accumulates repeated
pulls, and reports skipped items instead of silently dropping them —
the Pull dialog now surfaces those by name. Old /api/pantry routes
deleted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
#4 cleanup + Tony's house structure.
- Task.locationId (migration): reminders can attach to a place, not just a
plant/item/animal. Add one from a location's menu (e.g. clean gutters on House >
Exterior); the Reminders page + tasks service surface the linked location/item/
animal.
- Locations "Quick setup": paste/confirm an indented outline → creates the nested
tree (find-or-create by name+parent, idempotent), pre-filled with the Moon
homestead house layout. Optional "sweep existing garden areas under Yard" moves
every top-level place that holds plants under a new Yard parent — the
'move all the yard stuff to a new top level' ask.
- Pure outline parser (src/lib/locations/outline.ts, +4 tests); bulk setup service
+ /api/locations/bulk. Verified end-to-end: nested tree + paths, garden sweep,
place reminder.
Yard sub-bucketing deferred per Tony.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
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>