169 Commits

Author SHA1 Message Date
Trey T
4ec4bbbfe8 Auto-seed lookups + admin + templates on first API boot
Some checks failed
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
Add a data_migration that runs seeds/001_lookups.sql,
seeds/003_admin_user.sql, and seeds/003_task_templates.sql exactly
once on startup and invalidates the Redis seeded_data cache afterwards
so /api/static_data/ returns fresh results. Removes the need to
remember `./dev.sh seed-all`; the data_migrations tracking row prevents
re-runs, and each INSERT uses ON CONFLICT DO UPDATE so re-execution is
safe.
2026-04-15 08:37:55 -05:00
Trey T
58e6997eee Fix migration numbering collision and bump Dockerfile to Go 1.25
Some checks failed
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
The `000016_task_template_id` and `000017_drop_task_template_regions_join`
migrations introduced on gitea collided with the existing unpadded 016/017
migrations (authtoken_created_at, fk_indexes). Renamed them to 021/022 so
they extend the shipped sequence instead of replacing real migrations.
Also removed the padded 000012-000015 files which were duplicate content
of the shipped 012-015 unpadded migrations.

Dockerfile builder image bumped from golang:1.24-alpine to 1.25-alpine to
match go.mod's `go 1.25` directive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:17:23 -05:00
Trey t
237c6b84ee Onboarding: template backlink, bulk-create endpoint, climate-region scoring
Some checks failed
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
Clients that send users through a multi-task onboarding step no longer
loop N POST /api/tasks/ calls and no longer create "orphan" tasks with
no reference to the TaskTemplate they came from.

Task model
- New task_template_id column + GORM FK (migration 000016)
- CreateTaskRequest.template_id, TaskResponse.template_id
- task_service.CreateTask persists the backlink

Bulk endpoint
- POST /api/tasks/bulk/ — 1-50 tasks in a single transaction,
  returns every created row + TotalSummary. Single residence access
  check, per-entry residence_id is overridden with batch value
- task_handler.BulkCreateTasks + task_service.BulkCreateTasks using
  db.Transaction; task_repo.CreateTx + FindByIDTx helpers

Climate-region scoring
- templateConditions gains ClimateRegionID; suggestion_service scores
  residence.PostalCode -> ZipToState -> GetClimateRegionIDByState against
  the template's conditions JSON (no penalty on mismatch / unknown ZIP)
- regionMatchBonus 0.35, totalProfileFields 14 -> 15
- Standalone GET /api/tasks/templates/by-region/ removed; legacy
  task_tasktemplate_regions many-to-many dropped (migration 000017).
  Region affinity now lives entirely in the template's conditions JSON

Tests
- +11 cases across task_service_test, task_handler_test, suggestion_
  service_test: template_id persistence, bulk rollback + cap + auth,
  region match / mismatch / no-ZIP / unknown-ZIP / stacks-with-others

Docs
- docs/openapi.yaml: /tasks/bulk/ + BulkCreateTasks schemas, template_id
  on TaskResponse + CreateTaskRequest, /templates/by-region/ removed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:23:57 -05:00
Trey t
33eee812b6 Harden prod deploy: versioned secrets, healthchecks, migration lock, dry-run
Swarm stack
- Resource limits on all services, stop_grace_period 60s on api/worker/admin
- Dozzle bound to manager loopback only (ssh -L required for access)
- Worker health server on :6060, admin /api/health endpoint
- Redis 200M LRU cap, B2/S3 env vars wired through to api service

Deploy script
- DRY_RUN=1 prints plan + exits
- Auto-rollback on failed healthcheck, docker logout at end
- Versioned-secret pruning keeps last SECRET_KEEP_VERSIONS (default 3)
- PUSH_LATEST_TAG default flipped to false
- B2 all-or-none validation before deploy

Code
- cmd/api takes pg_advisory_lock on a dedicated connection before
  AutoMigrate, serialising boot-time migrations across replicas
- cmd/worker exposes an HTTP /health endpoint with graceful shutdown

Docs
- deploy/DEPLOYING.md: step-by-step walkthrough for a real deploy
- deploy/shit_deploy_cant_do.md: manual prerequisites + recurring ops
- deploy/README.md updated with storage toggle, worker-replica caveat,
  multi-arch recipe, connection-pool tuning, renumbered sections

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:22:43 -05:00
Trey t
ca818e8478 Merge branch 'master' of github.com:akatreyt/MyCribAPI_GO
Some checks failed
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
2026-04-01 20:45:43 -05:00
Trey T
bec880886b Coverage priorities 1-5: test pure functions, extract interfaces, mock-based handler tests
- Priority 1: Test NewSendEmailTask + NewSendPushTask (5 tests)
- Priority 2: Test customHTTPErrorHandler — all 15+ branches (21 tests)
- Priority 3: Extract Enqueuer interface + payload builders in worker pkg (5 tests)
- Priority 4: Extract ClassifyFile/ComputeRelPath in migrate-encrypt (6 tests)
- Priority 5: Define Handler interfaces, refactor to accept them, mock-based tests (14 tests)
- Fix .gitignore: /worker instead of worker to stop ignoring internal/worker/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 20:30:09 -05:00
Trey t
2e10822e5a Add S3-compatible storage backend (B2, MinIO, AWS S3)
Introduces a StorageBackend interface with local filesystem and S3
implementations. The StorageService delegates raw I/O to the backend
while keeping validation, encryption, and URL generation unchanged.

Backend selection is config-driven: set B2_ENDPOINT + B2_KEY_ID +
B2_APP_KEY + B2_BUCKET_NAME for S3 mode, or STORAGE_UPLOAD_DIR for
local mode. STORAGE_USE_SSL=false for in-cluster MinIO (HTTP).

All existing tests pass unchanged — the local backend preserves
identical behavior to the previous direct-filesystem implementation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:31:24 -05:00
Trey t
34553f3bec Add K3s dev deployment setup for single-node VPS
Mirrors the prod deploy-k3s/ setup but runs all services in-cluster
on a single node: PostgreSQL (replaces Neon), MinIO S3-compatible
storage (replaces B2), Redis, API, worker, and admin.

Includes fully automated setup scripts (00-init through 04-verify),
server hardening (SSH, fail2ban, ufw), Let's Encrypt TLS via Traefik,
network policies, RBAC, and security contexts matching prod.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:30:39 -05:00
Trey T
00fd674b56 Remove dead climate region code from suggestion engine
Suggestion engine now purely uses home profile features (heating,
cooling, pool, etc.) for template matching. Climate region field
and matching block removed — ZIP code is no longer collected.
2026-03-30 11:19:04 -05:00
Trey T
cb7080c460 Smart onboarding: residence home profile + suggestion engine
14 new optional residence fields (heating, cooling, water heater, roof,
pool, sprinkler, septic, fireplace, garage, basement, attic, exterior,
flooring, landscaping) with JSONB conditions on templates.

Suggestion engine scores templates against home profile: string match
+0.25, bool +0.3, property type +0.15, universal base 0.3. Graceful
degradation from minimal to full profile info.

GET /api/tasks/suggestions/?residence_id=X returns ranked templates.
54 template conditions across 44 templates in seed data.
8 suggestion service tests.
2026-03-30 09:02:03 -05:00
Trey T
4c9a818bd9 Comprehensive TDD test suite for task logic — ~80 new tests
Predicates (20 cases): IsRecurring, IsOneTime, IsDueSoon,
HasCompletions, GetCompletionCount, IsUpcoming edge cases

Task creation (10): NextDueDate initialization, all frequency types,
past dates, all optional fields, access validation

One-time completion (8): NextDueDate→nil, InProgress reset,
notes/cost/rating, double completion, backdated completed_at

Recurring completion (16): Daily/Weekly/BiWeekly/Monthly/Quarterly/
Yearly/Custom frequencies, late/early completion timing, multiple
sequential completions, no-original-DueDate, CompletedFromColumn capture

QuickComplete (5): one-time, recurring, widget notes, 404, 403

State transitions (10): Cancel→Complete, Archive→Complete, InProgress
cycles, recurring full lifecycle, Archive→Unarchive column restore

Kanban column priority (7): verify chain priority order for all columns

Optimistic locking (7): correct/stale version, conflict on complete/
cancel/archive/mark-in-progress, rollback verification

Deletion (5): single/multi/middle completion deletion, NextDueDate
recalculation, InProgress restore behavior documented

Edge cases (9): boundary dates, late/early recurring, nil/zero frequency
days, custom intervals, version conflicts

Handler validation (4): rating bounds, title/description length,
custom interval validation

All 679 tests pass.
2026-03-26 17:36:50 -05:00
Trey T
7f0300cc95 Add custom_interval_days to TaskResponse DTO
Field existed in Task model but was missing from API response.
Aligns Go API contract with KMM mobile model.
2026-03-26 17:06:34 -05:00
Trey T
6df27f203b Add rate limit response headers (X-RateLimit-*, Retry-After)
Custom rate limiter replacing Echo built-in, with per-IP token bucket.
Every response includes X-RateLimit-Limit, Remaining, Reset headers.
429 responses additionally include Retry-After (seconds).
CORS updated to expose rate limit headers to mobile clients.
4 unit tests for header behavior and per-IP isolation.
2026-03-26 14:36:48 -05:00
Trey T
b679f28e55 Production hardening: security, resilience, observability, and compliance
Password complexity: custom validator requiring uppercase, lowercase, digit (min 8 chars)
Token expiry: 90-day token lifetime with refresh endpoint (60-90 day renewal window)
Health check: /api/health/ now pings Postgres + Redis, returns 503 on failure
Audit logging: async audit_log table for auth events (login, register, delete, etc.)
Circuit breaker: APNs/FCM push sends wrapped with 5-failure threshold, 30s recovery
FK indexes: 27 missing foreign key indexes across all tables (migration 017)
CSP header: default-src 'none'; frame-ancestors 'none'
Gzip compression: level 5 with media endpoint skipper
Prometheus metrics: /metrics endpoint using existing monitoring service
External timeouts: 15s push, 30s SMTP, context timeouts on all external calls

Migrations: 016 (token created_at), 017 (FK indexes), 018 (audit_log)
Tests: circuit breaker (15), audit service (8), token refresh (7), health (4),
       middleware expiry (5), validator (new)
2026-03-26 14:05:28 -05:00
Trey T
4abc57535e Add delete account endpoint and file encryption at rest
Delete Account (Plan #2):
- DELETE /api/auth/account/ with password or "DELETE" confirmation
- Cascade delete across 15+ tables in correct FK order
- Auth provider detection (email/apple/google) for /auth/me/
- File cleanup after account deletion
- Handler + repository tests (12 tests)

Encryption at Rest (Plan #3):
- AES-256-GCM envelope encryption (per-file DEK wrapped by KEK)
- Encrypt on upload, auto-decrypt on serve via StorageService.ReadFile()
- MediaHandler serves decrypted files via c.Blob()
- TaskService email image loading uses ReadFile()
- cmd/migrate-encrypt CLI tool with --dry-run for existing files
- Encryption service + storage service tests (18 tests)
2026-03-26 10:41:01 -05:00
Trey T
72866e935e Disable auth rate limiters in debug mode for UI test suites
Rate limiters on login/register/password-reset endpoints cause 429 errors
when running parallel UI tests that create many accounts. In debug mode,
skip rate limiters entirely so test suites can run without throttling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:06:18 -05:00
Trey t
42a5533a56 Fix 113 hardening issues across entire Go backend
Security:
- Replace all binding: tags with validate: + c.Validate() in admin handlers
- Add rate limiting to auth endpoints (login, register, password reset)
- Add security headers (HSTS, XSS protection, nosniff, frame options)
- Wire Google Pub/Sub token verification into webhook handler
- Replace ParseUnverified with proper OIDC/JWKS key verification
- Verify inner Apple JWS signatures in webhook handler
- Add io.LimitReader (1MB) to all webhook body reads
- Add ownership verification to file deletion
- Move hardcoded admin credentials to env vars
- Add uniqueIndex to User.Email
- Hide ConfirmationCode from JSON serialization
- Mask confirmation codes in admin responses
- Use http.DetectContentType for upload validation
- Fix path traversal in storage service
- Replace os.Getenv with Viper in stripe service
- Sanitize Redis URLs before logging
- Separate DEBUG_FIXED_CODES from DEBUG flag
- Reject weak SECRET_KEY in production
- Add host check on /_next/* proxy routes
- Use explicit localhost CORS origins in debug mode
- Replace err.Error() with generic messages in all admin error responses

Critical fixes:
- Rewrite FCM to HTTP v1 API with OAuth 2.0 service account auth
- Fix user_customuser -> auth_user table names in raw SQL
- Fix dashboard verified query to use UserProfile model
- Add escapeLikeWildcards() to prevent SQL wildcard injection

Bug fixes:
- Add bounds checks for days/expiring_soon query params (1-3650)
- Add receipt_data/transaction_id empty-check to RestoreSubscription
- Change Active bool -> *bool in device handler
- Check all unchecked GORM/FindByIDWithProfile errors
- Add validation for notification hour fields (0-23)
- Add max=10000 validation on task description updates

Transactions & data integrity:
- Wrap registration flow in transaction
- Wrap QuickComplete in transaction
- Move image creation inside completion transaction
- Wrap SetSpecialties in transaction
- Wrap GetOrCreateToken in transaction
- Wrap completion+image deletion in transaction

Performance:
- Batch completion summaries (2 queries vs 2N)
- Reuse single http.Client in IAP validation
- Cache dashboard counts (30s TTL)
- Batch COUNT queries in admin user list
- Add Limit(500) to document queries
- Add reminder_stage+due_date filters to reminder queries
- Parse AllowedTypes once at init
- In-memory user cache in auth middleware (30s TTL)
- Timezone change detection cache
- Optimize P95 with per-endpoint sorted buffers
- Replace crypto/md5 with hash/fnv for ETags

Code quality:
- Add sync.Once to all monitoring Stop()/Close() methods
- Replace 8 fmt.Printf with zerolog in auth service
- Log previously discarded errors
- Standardize delete response shapes
- Route hardcoded English through i18n
- Remove FileURL from DocumentResponse (keep MediaURL only)
- Thread user timezone through kanban board responses
- Initialize empty slices to prevent null JSON
- Extract shared field map for task Update/UpdateTx
- Delete unused SoftDeleteModel, min(), formatCron, legacy handlers

Worker & jobs:
- Wire Asynq email infrastructure into worker
- Register HandleReminderLogCleanup with daily 3AM cron
- Use per-user timezone in HandleSmartReminder
- Replace direct DB queries with repository calls
- Delete legacy reminder handlers (~200 lines)
- Delete unused task type constants

Dependencies:
- Replace archived jung-kurt/gofpdf with go-pdf/fpdf
- Replace unmaintained gomail.v2 with wneessen/go-mail
- Add TODO for Echo jwt v3 transitive dep removal

Test infrastructure:
- Fix MakeRequest/SeedLookupData error handling
- Replace os.Exit(0) with t.Skip() in scope/consistency tests
- Add 11 new FCM v1 tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:14:13 -05:00
Trey t
3b86d0aae1 Include completion_summary in my-residences list endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:14:24 -05:00
Trey t
6803f6ec18 Add honeycomb completion heatmap and data migration framework
- Add completion_summary endpoint data to residence detail response
- Track completed_from_column on task completions (overdue/due_soon/upcoming)
- Add GetCompletionSummary repo method with monthly aggregation
- Add one-time data migration framework (data_migrations table + registry)
- Add backfill migration to classify historical completions
- Add standalone backfill script for manual/dry-run usage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:05:10 -05:00
Trey t
739b245ee6 Fix PDF report UTF-8 encoding for residence names and task fields
Add UnicodeTranslatorFromDescriptor to convert UTF-8 strings to
Windows-1252 for gofpdf built-in fonts. Prevents garbled characters
in residence names, task titles, categories, priorities, and statuses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:23:44 -05:00
Trey t
7bd2cbabe9 Fix broken email icon by updating old domain references to myhoneydue.com
The email icon URL was pointing to honeyDue.treytartt.com which now returns 404.
Updated to api.myhoneydue.com along with BASE_URL, FROM_EMAIL, and CORS defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:38:55 -06:00
Trey t
bf309f5ff9 Move admin dashboard to admin.myhoneydue.com subdomain
- Remove Next.js basePath "/admin" — admin now serves at root
- Update all internal links from /admin/xxx to /xxx
- Change Go proxy to host-based routing: admin subdomain requests
  proxy to Next.js, /admin/* redirects to main web app
- Update timeout middleware skipper for admin subdomain

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:35:31 -06:00
Trey t
1fdc29af1c Add admin subdomain redirect for admin.myhoneydue.com
When ADMIN_HOST is set, redirects root "/" to "/admin/" so
admin.myhoneydue.com works without needing the /admin path suffix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:25:26 -06:00
Trey t
821a3e452f Remove docs and marketing files relocated to old_files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 07:09:06 -06:00
Trey t
4976eafc6c Rebrand from Casera/MyCrib to honeyDue
Total rebrand across all Go API source files:
- Go module path: casera-api -> honeydue-api
- All imports updated (130+ files)
- Docker: containers, images, networks renamed
- Email templates: support email, noreply, icon URL
- Domains: casera.app/mycrib.treytartt.com -> honeyDue.treytartt.com
- Bundle IDs: com.tt.casera -> com.tt.honeyDue
- IAP product IDs updated
- Landing page, admin panel, config defaults
- Seeds, CI workflows, Makefile, docs
- Database table names preserved (no migration needed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 06:33:38 -06:00
Trey t
793e50ce52 Add regional task templates API with climate zone lookup
Adds a new endpoint GET /api/tasks/templates/by-region/?zip= that resolves
ZIP codes to IECC climate regions and returns relevant home maintenance
task templates. Includes climate region model, region lookup service with
tests, seed data for all 8 climate zones with 50+ templates, and OpenAPI spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:15:30 -06:00
Trey t
72db9050f8 Add Stripe billing, free trials, and cross-platform subscription guards
- Stripe integration: add StripeService with checkout sessions, customer
  portal, and webhook handling for subscription lifecycle events.
- Free trials: auto-start configurable trial on first subscription check,
  with admin-controllable duration and enable/disable toggle.
- Cross-platform guard: prevent duplicate subscriptions across iOS, Android,
  and Stripe by checking existing platform before allowing purchase.
- Subscription model: add Stripe fields (customer_id, subscription_id,
  price_id), trial fields (trial_start, trial_end, trial_used), and
  SubscriptionSource/IsTrialActive helpers.
- API: add trial and source fields to status response, update OpenAPI spec.
- Clean up stale migration and audit docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:36:14 -06:00
Trey t
d5bb123cd0 Redesign email templates to match web landing page Warm Sage design system
Rewrote all 11 email templates to use the Casera web brand: Outfit font via
Google Fonts, sage green (#6B8F71) brand stripe, cream (#FAFAF7) background,
pill-shaped clay (#C4856A) CTA buttons, icon-badge feature cards, numbered
tip cards, linen callout boxes, and refined light footer. Extracted reusable
helpers (emailButton, emailCodeBox, emailCalloutBox, emailAlertBox,
emailFeatureItem, emailTipCard) for consistent component composition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:02:41 -06:00
Trey t
6dcf797613 Fix worker healthcheck: use pgrep -f for Alpine busybox compatibility
Alpine's busybox pgrep -x doesn't match process names correctly.
Use pgrep -f /app/worker to match the full command path instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:02:42 -06:00
Trey t
7438dfd9b1 Fix timeout middleware panic on proxy/WebSocket routes and worker healthcheck
The TimeoutMiddleware wraps the response writer in *http.timeoutWriter which
doesn't implement http.Flusher. When the admin reverse proxy or WebSocket
upgrader tries to flush, it panics and crashes the container (502 Bad Gateway).
Skip timeout for /admin, /_next, and /ws routes.

Also fix the Dockerfile HEALTHCHECK to detect the worker process — the worker
has no HTTP server so the curl-based check always failed, marking it unhealthy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:56:12 -06:00
Trey t
7690f07a2b Harden API security: input validation, safe auth extraction, new tests, and deploy config
Comprehensive security hardening from audit findings:
- Add validation tags to all DTO request structs (max lengths, ranges, enums)
- Replace unsafe type assertions with MustGetAuthUser helper across all handlers
- Remove query-param token auth from admin middleware (prevents URL token leakage)
- Add request validation calls in handlers that were missing c.Validate()
- Remove goroutines in handlers (timezone update now synchronous)
- Add sanitize middleware and path traversal protection (path_utils)
- Stop resetting admin passwords on migration restart
- Warn on well-known default SECRET_KEY
- Add ~30 new test files covering security regressions, auth safety, repos, and services
- Add deploy/ config, audit digests, and AUDIT_FINDINGS documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:48:01 -06:00
treyt
56d6fa4514 Add Dozzle log viewer to dev and prod compose files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:39:43 -06:00
treyt
e26116e2cf Add webhook logging, pagination, middleware, migrations, and prod hardening
- Webhook event logging repo and subscription webhook idempotency
- Pagination helper (echohelpers) with cursor/offset support
- Request ID and structured logging middleware
- Push client improvements (FCM HTTP v1, better error handling)
- Task model version column, business constraint migrations, targeted indexes
- Expanded categorization chain tests
- Email service and config hardening
- CI workflow updates, .gitignore additions, .env.example updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:32:09 -06:00
treyt
806bd07f80 Update README for split dev/prod Docker config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:29:52 -06:00
treyt
f1e39f90c7 Split Docker config for dev/prod and fix arch-agnostic builds
- Dockerfile: use --platform=$BUILDPLATFORM + ARG TARGETARCH instead of
  hardcoded GOARCH=arm64, enabling cross-compilation and native builds
  on both arm64 (M1) and amd64 (prod server)
- docker-compose.yml: rewrite for Docker Swarm — image refs, deploy
  sections, overlay network, no container_name/depends_on conditions,
  DB/Redis ports not exposed externally
- docker-compose.dev.yml: rewrite as self-contained dev compose with
  build targets, container_name, depends_on, dev-safe defaults
- Makefile: switch to docker compose v2, point dev targets at
  docker-compose.dev.yml, add docker-build-prod target
- Delete stale docker/Dockerfile (Go 1.21) and docker/docker-compose.yml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:27:35 -06:00
treyt
9f8828a503 Fix admin healthcheck: use 127.0.0.1 instead of localhost
Alpine Linux resolves localhost to IPv6 ::1, but Next.js binds to
IPv4 0.0.0.0 — causing the healthcheck to fail with connection refused.
Also update worker env vars from legacy Celery names to current ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:08:40 -06:00
Trey t
ebbbe52560 Fix GOARCH: build arm64 binaries to match Docker platform
The Go build was targeting amd64 while docker-compose sets
platform: linux/arm64, causing SIGSEGV on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:57:41 -06:00
treyt
9916003bcd Fix Docker segfault on Apple Silicon — add linux/arm64 platform
Go runtime netpoll_epoll segfaults under amd64 emulation on ARM Macs.
Explicitly target arm64 for all build services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:48:40 -06:00
Trey t
21aaba90d4 Rewrite README with comprehensive new-machine setup instructions
Add step-by-step guides for Docker, hybrid, and fully native setups.
Include environment variable reference, seed data docs, and project structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:36:02 -06:00
Trey t
09a35c0b99 Align document handlers/repo with contract updates 2026-02-18 21:37:38 -06:00
Trey t
e7c23bdeb1 Fix backend API parity: document filters, task days param, i18n locales, contract tests
- Add document list filter support (residence, type, category, contractor, is_active, expiring_soon, search) to handler/service/repo
- Add `days` query param parsing to ListTasks handler (matches ListTasksByResidence)
- Add `error.invalid_token` i18n key to all 9 non-English locale files
- Update contract test to include VerificationResponse mapping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:49:48 -06:00
Trey t
bb7493f033 Close all 25 codex audit findings and add KMP contract tests
Remediate all P0-S priority findings from cross-platform architecture audit:
- Add input validation and authorization checks across handlers
- Harden social auth (Apple/Google) token validation
- Add document ownership verification and file type validation
- Add rate limiting config and CORS origin restrictions
- Add subscription tier enforcement in handlers
- Add OpenAPI 3.0.3 spec (81 schemas, 104 operations)
- Add URL-level contract test (KMP API routes match spec paths)
- Add model-level contract test (65 schemas, 464 fields validated)
- Add CI workflow for backend tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:15:07 -06:00
Trey t
215e7c895d wip 2026-02-18 10:54:18 -06:00
Trey t
a5245955af Document temporarily disabled kanban cancel column in CLAUDE.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 10:45:26 -06:00
Trey t
c0b402d7d3 Temporarily hide cancelled column from kanban board
Comment out the cancelled column from API responses to reduce clutter.
Code preserved for easy re-enablement by searching for "TEMPORARILY DISABLED".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 19:45:07 -06:00
Trey t
c2e8800312 Fix task due date update not persisting for tasks with completions
When a user explicitly edited a task's due date, the backend was only
updating NextDueDate if the task had no completions. For recurring tasks
with completions, this caused the UI to show stale NextDueDate values
since effectiveDueDate prioritizes NextDueDate over DueDate.

Now always updates NextDueDate when user explicitly edits due date.
Completion logic will still recalculate NextDueDate when task is completed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:50:36 -06:00
Trey t
0e2e1532d2 Add timezone display to admin Next.js frontend
Display user timezone in:
- Notification Preferences table (new Timezone column)
- User detail page (Basic Information card)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 23:07:48 -06:00
Trey t
c464ee093e Add timezone to admin interface user and notification prefs views
Shows the user's auto-captured timezone (IANA format) in:
- Notification preferences list/detail/update responses
- User detail response

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 22:55:38 -06:00
Trey t
70a56e8e96 Add timezone-aware daily digest notifications
The daily digest notification count was inconsistent with the kanban UI
because the server used UTC time while the client used local time.
A task due Dec 24 would appear overdue on the server (UTC Dec 25) but
still show as "due today" for the user (local Dec 24).

Changes:
- Add timezone column to notification_preference table
- Auto-capture user's timezone from X-Timezone header when fetching tasks
- Use stored timezone in HandleDailyDigest for accurate overdue calculation

The mobile app already sends X-Timezone on every request, so no client
changes are needed. The timezone is captured on each app launch when
the tasks API is called.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 22:48:34 -06:00
Trey t
12ae11ca59 Refactor daily digest to use canonical repository functions
Replace raw SQL in HandleDailyDigest with repository functions that use
the canonical task scopes. This ensures the daily digest push notification
uses the exact same overdue/due-soon logic as the kanban display.

Changes:
- Add residenceRepo to Handler struct for user residence lookups
- Use taskRepo.GetOverdueTasks() instead of raw SQL (uses ScopeOverdue)
- Use taskRepo.GetDueSoonTasks() instead of raw SQL (uses ScopeDueSoon)
- Set IncludeInProgress: false to match kanban behavior

Fixes bug where notification reported 3 overdue tasks when kanban showed 2
(in-progress tasks were incorrectly counted as overdue in the digest).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 22:03:40 -06:00