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>
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>
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>