summaryrefslogtreecommitdiff
path: root/cmd/dashboard/main.go
AgeCommit message (Collapse)Author
2026-08-24Remove confirmed-orphaned routes, handlers, and templatesHEADmasterPeter Stone
From the sitemap audit: /tabs/meals (same dead-tab pattern as the removed /tabs/conditions, only reachable via ?tab=meals with no nav button), /partials/lists (superseded by inline .Lists rendering in trello-board.html), /shopping/toggle and /shopping/mode/{store}/toggle (superseded by the one-way complete/filter model), plus the orphaned trello-boards.html and error-banner.html templates that nothing rendered or included. Rewrote the meals grouping test to exercise groupMeals() directly since that logic is still live via the timeline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GMEkHeqKz6FLkmizowBTK
2026-08-23Remove unused /tabs/conditions partial and routePeter Stone
Only the standalone /conditions page was ever meant to exist; the HTMX tab variant was dead weight, reachable only via an unlinked ?tab=conditions query param with no button in the tab bar. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017GMEkHeqKz6FLkmizowBTK
2026-08-16Replace Google Tasks service-account auth with real OAuthPeter Stone
Service-account auth structurally cannot see a regular user's personal task lists (no equivalent of Calendar's per-item sharing model) -- confirmed via GetTaskLists returning exactly the service account's own empty "My Tasks" list, never the real user's three lists. Zero rows were ever cached in production as a result. Adds a standard 3-legged OAuth flow: /settings/google-tasks/connect redirects to Google's consent screen (AccessTypeOffline+ApprovalForce so a refresh_token is always issued), /callback exchanges the code and persists the token (new oauth_tokens table), /disconnect clears it. GoogleTasksClient now takes an option.ClientOption instead of a credentials file path; NewGoogleTasksOAuthClient wraps it with a dbTokenSource that reloads/refreshes from the DB on each access-token expiry and re-persists -- carefully preserving the original refresh_token when Google's refresh response omits one (it usually does), which would otherwise silently and permanently break future refreshes. Settings page shows connection status and a Connect/Disconnect button. Calendar keeps using service-account auth (that one actually works). Requires a one-time manual step: create an OAuth 2.0 Client ID in Google Cloud Console and set GOOGLE_OAUTH_CLIENT_ID/SECRET in .env -- documented in .env.example.
2026-08-12Add task title editing/deletion, timeline click-to-open, widget app launchPeter Stone
Task-detail modal was description-only with no delete affordance; HandleUpdateTask now saves the title too and a Delete button hits a new DELETE /tasks/{id} route backed by store.DeleteNativeTask, which repairs chain_position/unlocks the successor when the deleted task belongs to a chain. Timeline tab task/card/gtask rows now open the same detail modal as the Tasks tab. Android widget's "TODAY" header is now a tap target that launches DashboardActivity, since nothing previously opened the full app from the widget.
2026-08-07Wire the Tasks tab into nav; fold in buckets/projects/labels and recurrencePeter Stone
The Tasks tab (/tabs/tasks) existed server-side and was tested, but nothing in the nav linked to it -- it was pure dead weight in the other direction. Wiring it up as the natural home for everything that was either misplaced in Settings or missing a web UI entirely: - Maintenance Buckets, Projects, and Labels moved out of Settings and into the Tasks tab (restyled from Settings' opaque slate cards to the glass/backdrop-blur look already used by the tab's chain/atom cards -- they're now embedded in index.html's page shell, not a standalone page, so the shared bg-card/bg-input classes from that shell apply). Settings keeps only what's actually settings: Passkeys, Trusted Agents, Data Sources. - Added a Recurrence section to the task-detail modal (freq/interval/ weekday form, posting to a new POST /tasks/recurrence -- the HTMX counterpart to the widget API's HandleWidgetTaskRecurrence). Native task recurrence previously had zero web UI at all, only reachable via the Android widget's RecurrenceEditDialog. Also fixed a real bug found while touching this code: HandleGetTaskDetail's source switch only had a case for "trello" -- opening any native ("doot") task's detail modal, which is most tasks in this tab, showed a blank title and description. Factored both call sites (initial GET and the re-render after a recurrence edit) through one loadTaskDetailData helper and added the missing "doot" case. Also fixed task-detail.html's styling, which was still using pre-dark-theme classes (text-gray-900 etc.) -- functionally invisible text on the modal's dark background. Verified with a throwaway local server (real templates + real DB, not the MockRenderer the unit tests use) seeded with a recurring task, a bucket, a project, and a label -- confirmed all five touched routes render 200 with the expected content, including the populated Buckets/Projects/Labels sections and a real weekly-recurrence form with the correct weekdays pre-checked. Caught and fixed a copy bug this way too ("every 2 weeklys" -> "every 2 weeks"). Not committed; deleted after use. go build ./..., go vet ./..., and go test ./... all clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-08-06Remove the feature toggle system (dead code)Peter Stone
Audited it (couldn't query the live DB directly -- auto-mode classifier blocks direct production reads without prior approval -- so this is a code-only audit): GetFeatureToggles/SetFeatureEnabled/IsFeatureEnabled/ CreateFeatureToggle/DeleteFeatureToggle had exactly one caller each, all inside their own CRUD handlers. Nothing anywhere else in the codebase read a toggle's Enabled state to gate any actual behavior -- confirmed by grepping every remaining .Enabled/IsFeatureEnabled reference back to either this dead code or its own tests. It was pure UI-managed CRUD with no consumer, unlike Trusted Agents (wired into agent.go/websocket.go) or Data Sources (wired into the sync pipeline) which stayed. Removes the Settings page section, the three /settings/features* routes and handlers, the five Store methods, the FeatureToggle model, and adds 028_drop_feature_toggles.sql (next free migration number, per this repo's convention of never renumbering -- see 021_drop_tasks.sql for the same drop-table-forward pattern) to drop the now-unused table. Also removed the now-dead tests for all of the above. go build ./... and go test ./... both clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-08-04Fix production wedge: propagate context to Google Calendar API callsPeter Stone
Three .Do() calls in google_calendar.go accepted a ctx parameter but never chained .Context(ctx) into the actual SDK call, so the existing global 60s request timeout never reached the blocking network call. One hung Google Calendar request wedged every DB/session-touching request path in production for three days (2026-08-01 through 2026-08-04), undetected because /health unconditionally returned 200 throughout. - Wire .Context(ctx) into GetUpcomingEvents, GetEventsByDateRange, and GetCalendarList. - Bound aggregateData's four external fetches with a per-fetch sub-context as defense-in-depth (only effective if the callee actually honors ctx -- documented as such, not oversold). - Make GetUpcomingEvents/GetEventsByDateRange fetch calendars concurrently instead of sequentially: a review of this fix caught that a shared per-fetch deadline over a sequential loop would starve calendars past the first under any real latency, silently caching partial results as complete. Concurrent fetches give every calendar an equal shot at the same deadline instead. - /health now does a real PingContext DB check instead of a static "ok" (Handler.PingDB, tested for both healthy and closed-DB cases). - Add internal/api/context_audit_test.go: an AST-based structural guard that fails any future .Do() call in google_*.go missing .Context(...) anywhere in its chain, so this class of bug can't silently recur. Verified by deliberately reintroducing the original bug against a backup and confirming the guard catches it. - Add scripts/health-watchdog.sh: cron job restarts the service if /health fails twice in a row, five minutes apart. go test ./... -race is green. Deployed and live-verified.
2026-07-18Add bucket CRUD and read-only Projects/Labels to Settings pagePeter Stone
New "Maintenance Buckets" section: create a bucket, add a pool item by title (creates the task and assigns it in one step), remove an item, delete a bucket (unbuckets its tasks rather than deleting them). New read-only Projects and Labels sections (name + color swatch) -- both are simple enough that read-only is the right call on web, per user direction, rather than duplicating the Android popup's editing UX. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-18Rework Tasks tab: Chains section, checklist modal, project visibilityPeter Stone
The flat Tasks-tab atom list was silently dumping every chain step (locked and unlocked) and dormant bucket-pool items in as ordinary undated cards, with no chain/project context and no protection against completing a locked step out of order. - CompleteNativeTask now rejects completing a locked chain task (ErrChainTaskLocked), mapped to 400 in both the widget and web complete-atom handlers. - Chain tasks and dormant bucket items are excluded from the flat atom list; a new "Chains" section shows one card per active/paused chain with the current step and N/M progress. - New chain checklist modal (GET /chains/{id}) lists every position in order with pause/resume/abandon -- the web view originally deferred as Android-only. - Fixed a real bug this surfaced: resuming a paused chain only flipped the status flag, never unlocking the deferred successor, so a chain paused right after a completion stayed stuck forever. SetChainStatus now catches up the deferred advancement on resume, idempotently. - Atom cards gained a project-name chip for general visibility. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-17Implement linear task chains and recurring maintenance bucketsPeter Stone
Backend, web timeline, and Android widget wiring for the last two unimplemented items from doot-future-task-scheduling-ideas. Chains: task_chains table + chain_id/chain_position/chain_unlocked on native_tasks (migration 026), WIP-limit-1 advancement hooked into CompleteNativeTask, locked tasks excluded from all date-based queries, 5 new /api/widget/chains* endpoints, an N/M position badge on web and Android widget rows. Buckets: maintenance_buckets table + bucket_id/bucket_state/ bucket_last_active_at on native_tasks (migration 027), staleness-then-priority selection scoring, a new RunBucketCycleCheck scheduler loop, 5 new endpoints including the distinct Defer action, a Defer button on web and Android widget rows. Also corrected stale "not yet approved" status headers on the two already-shipped specs this work depended on (labels/projects, budgets/ availability) -- their headers were never updated after implementation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-16Add availability CRUD, task estimate, and budget-tracked toggle endpointsPeter Stone
Adds 6 widget HTTP handlers (availability get/create/delete, task estimate, project and label budget-tracked toggles) plus route registration, following the existing widget handler conventions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQaPGQVSfmKUiHXB87qRTC
2026-07-16feat(tasks): add HTTP endpoints for projects and label colorsPeter Stone
Extends the task-detail response with project/labels so the popup can display them without a second round trip. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16feat(tasks): add HTTP endpoints for task detail, update, and recurrencePeter Stone
GET /api/widget/task, POST /api/widget/task/update, POST /api/widget/task/recurrence, POST /api/widget/task/next-date. Doot-only; the recurrence/next-date fields are null in the detail response for a non-recurring task.
2026-07-16feat(tasks): add periodic due-date check for recurring tasksPeter Stone
A recurring task's successor now also gets created once its due date passes, independent of completion -- an ignored/overdue recurring task no longer blocks the next occurrence from appearing. Runs every 15 minutes via a new goroutine in main.go, cancelled on shutdown.
2026-07-16feat: add authenticated /docs viewer for superpowers specs/plansPeter Stone
Renders docs/superpowers/{specs,plans}/*.md to HTML via goldmark, served from doot's own web server behind the existing session auth instead of as raw files. DOCS_DIR is configurable (defaults to docs/superpowers relative to the working directory) so the deployed server can point straight at the working repo and stay live-synced with no separate copy/deploy step for new docs.
2026-07-16feat(widget): tap event to open its source directly, drop detail popupPeter Stone
Tapping a calendar event (or any event-type item) now opens the event's URL (Google Calendar, Plan to Eat, etc.) directly instead of showing an intermediate popup with an "Open in Calendar" button. Removes EventDetailActivity and the recurrence-schedule lookup it was the only consumer of: WidgetRepository.getRecurrence, the Go /api/widget/recurrence endpoint, HandleWidgetRecurrence, GoogleCalendarAPI.GetRecurrenceRule, and formatRecurrence, plus their tests. RecurringEventID itself stays -- it's general calendar-sync metadata used elsewhere in the timeline pipeline, not exclusive to the removed popup.
2026-07-13Merge github/master: reconcile with parallel widget workPeter Stone
Another session pushed 27 commits in parallel covering quick-add, event detail popups, recurrence display, overdue badges, a manual refresh button, and its own fix for the same overdue-tasks bug (via a separate GetOverdueNativeTasks fetch folded into BuildTimeline, rather than widening GetNativeTasksByDateRange's bound directly). Reconciled rather than blindly taking one side: - Reverted GetNativeTasksByDateRange to its original bounded query and kept upstream's GetOverdueNativeTasks + BuildTimeline fold-in as the sole overdue mechanism for native tasks, to avoid double-counting overdue items (my widened query + their separate fetch would have both returned them). Re-pointed the regression test at the now-correct contract and added a store-level test for GetOverdueNativeTasks directly. - Kept my GetGoogleTasksByDateRange fix as-is (single unbounded query) -- upstream never touched Google Tasks overdue handling, so there's no duplication risk there. - Rewove WidgetRoot's LazyColumn structure (added for scrolling) around upstream's new header buttons, pinned all-day event rows, and the enhanced TomorrowSection, none of which were written LazyColumn-aware since that work landed on this side only. - Combined both sides' additions to TaskDetailActivity/TaskDetailSheet (description-edit detail popup + due-date reschedule label) and WidgetRepository/Actions (optimistic local removal + refresh button wiring) -- these were independent, non-overlapping features that both needed to survive. - Renumbered the migration collision: both sides independently added a migration numbered 022. Card-description was already applied to the live production DB under that filename earlier this session (migrations are tracked by filename), so it keeps 022; the recurring-event-id migration, never deployed under any name here, moves to 023. Verified: go build clean, full test suite passes (only the two pre-existing agent-handler failures and the pre-existing models package build error remain, both confirmed unrelated via git stash before this session began), and a dry run against a copy of the live production database applies both migrations cleanly with no re-run conflicts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-13feat(widget): editable task details, scrollable list, and overdue-task fixesPeter Stone
- Add description editing to the widget's task detail popup for doot/gtasks/trello, backed by new GET /api/widget/detail and POST /api/widget/update endpoints - Make Google Tasks and Trello cards completable via the widget (Trello completion archives the card); fix Trello description never being fetched, which meant saving could silently wipe a card's real desc - Fix google_tasks.due_date/updated_at (TEXT columns) never round-tripping through sql.NullTime, which broke cached Google Tasks reads whenever the cache was valid - Fix native-task and Google-Task date-range queries excluding anything due before the window start, which dropped incomplete tasks off the widget the moment their due day passed (the "overdue tasks disappeared" bug) - Fix native task description edits blanking the task's title - Make the widget's day list scroll (LazyColumn) instead of clipping - Optimistically remove a task from the widget immediately on completion, ahead of the authoritative background refresh Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-12feat(widget): add recurrence lookup endpoint (GET /api/widget/recurrence)Peter Stone
2026-07-12feat(widget): add POST /api/widget/add for quick-addPeter Stone
2026-07-06feat: remove Todoist integration entirelyDoot Agent
Native tasks (native_tasks table) fully replace Todoist. All Todoist API code, store functions, handlers, routes, templates, and tests have been removed. Migration 021 drops the now-unused tasks cache table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05feat(gateway): add publicPaths bypass for all-method service routesPeter Stone
Adds a publicPaths field to serviceMount alongside webhookPaths. webhookPaths remains POST-only (HMAC-signed webhooks). publicPaths bypasses session auth for all methods, relying on the upstream service's own bearer-token auth instead. Used to expose /claudomator/chatbot/mcp for MCP client connections (claude-code) which carry their own Authorization header and cannot carry a doot session cookie.
2026-06-29fix: calendar/meals sync, tomorrow flat layout, /health endpointPeter Stone
- Calendar: fall back to GOOGLE_CALENDAR_ID config when no source_configs synced yet (fixes blank calendar after fresh deploy) - Meals: call fetchMeals in HandleTimeline so PlanToEat cache refreshes on every timeline load, not just during manual refresh - Tomorrow section: replace calendar-grid with flat chronological list matching widget layout (time label | source bar | title) - Add /health endpoint (no auth required) for deploy health checks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: reschedule tasks from widget bottom sheetPeter Stone
Tapping a doot task shows a date picker. On confirm, POSTs to /api/widget/reschedule, updates due_date in native_tasks, refreshes widget. Reschedule button only shows for source="doot" tasks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: native task management + Todoist migrationPeter Stone
Adds doot-owned task storage (native_tasks table) so tasks can be managed without Todoist. CompleteTask for 'doot' source just updates the DB — no external API call, no token dependency. Migration path: POST /settings/import-from-todoist — copies Todoist cache → native_tasks Then remove TODOIST_TOKEN from .env to disable Todoist Changes: - migration 020: native_tasks table - store: GetNativeTasks, GetNativeTasksByDateRange, GetUndatedNativeTasks, CreateNativeTask, CompleteNativeTask, UncompleteNativeTask, UpdateNativeTask, ImportFromTodoist - timeline: native tasks appear as source="doot" (teal) - handleAtomToggle: "doot" case — no external API needed - HandleWidgetComplete: method on Handler, handles "doot" natively - HandleUnifiedAdd: "doot" source creates in native_tasks - widget: "doot" tasks are completable, teal color indicator Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: add standalone task detail page for Android widget deep-linksPeter Stone
Adds GET /task?id=xxx&source=xxx route that renders a full mobile-friendly task detail page (session-protected). Widget task rows now open this page when tapped. HandleUpdateTask redirects back to the page after a non-HTMX save. Android: threads serverUrl through composable chain to TaskRow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: register /api/widget routes behind WIDGET_TOKEN bearer authPeter Stone
Add widget API routes for Android widget integration. Routes use bearer token authentication and are placed outside session-protected groups. GET /api/widget returns today's timeline items; POST /api/widget/complete completes Todoist tasks. Routes only register if WIDGET_TOKEN env var is set. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18feat: add scout service mount to gatewayPeter Stone
Wires scout listing feed (SCOUT_URL env var) into the service gateway loop. Set SCOUT_URL=http://127.0.0.1:8081 to expose it at /scout/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15feat: service gateway framework + playground demoPeter Stone
Formalizes doot as an authenticated reverse proxy for arbitrary upstream services. Any local HTTP service can now be registered behind doot's existing auth + SSL layer with 3 lines of config. - Rename NewClaudomatorProxy → NewServiceProxy (generic) - Replace hard-coded claudomator proxy block with serviceMount slice loop - Add PlaygroundURL config (PLAYGROUND_URL env var) - Add playground/web/server.py: stdlib Python status page on port 9090 - Document pattern in .agent/design.md; update .env.example To add a new service: set its URL env var, add a config field, append one mount entry in main.go. Claudomator's GitHub webhook bypass is expressed as webhookPaths on its mount. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03fix: add CSRF and WebSocket origin protection to Claudomator proxyPeter Stone
Token-based CSRF is impractical for a reverse proxy whose UI doesn't know Doot's session tokens, so state-changing requests to /claudomator/* are now validated against the configured WebAuthn origin via Origin/Referer header. WebSocket upgrades reject mismatched or missing Origin headers before hijacking the connection. Both checks are no-ops when WebAuthnOrigin is unset (local dev). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25feat: add Claudomator stories as atom source in Doot tasks tabClaude Agent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25feat: gate Claudomator UI behind Doot session auth via reverse proxyDoot Agent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23fix: remove orphaned HandleRefreshTab routePeter Stone
2026-03-23feat: complete Agent Context API Phase 2 & 3 (Write/Create/Management)Peter Stone
- Implement write operations (complete, uncomplete, update due date, update task) - Implement create operations (create task, add shopping item) - Add Trusted Agents management UI in Settings with revocation support - Fix SQLite timestamp scanning bug for completed tasks - Add comprehensive unit tests for all new agent endpoints - Update worklog and feature documentation
2026-03-21feat: Phase 1 — remove bug feature and dead codePeter Stone
- Delete Bug struct, BugToAtom, SourceBug, TypeBug, TypeNote - Remove bug store methods (SaveBug, GetBugs, ResolveBug, etc.) - Remove HandleGetBugs, HandleReportBug, bug branches in handlers - Remove bug routes, bugs.html template, bug UI from index.html - Remove AddMealToPlanner stub + interface method - Migration 018: DROP TABLE IF EXISTS bugs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04feat: sync log, cache clear endpoint, Todoist projects from cached tasksPeter Stone
- migration 016: sync_log table - store: AddSyncLogEntry, GetRecentSyncLog, InvalidateAllCaches, GetProjectsFromTasks - settings: HandleClearCache (POST /settings/clear-cache), SyncLog in page data - settings: use GetProjectsFromTasks instead of deprecated Todoist REST /projects - handlers: populate atom projects from store - agent: log warning on registration failure instead of silently swallowing - google_tasks: simplify URL literal - tests: sync log CRUD, clear cache handler, settings page includes sync log, sync sources adds log entry, incremental sync paths, task completion response/headers, calendar cache fallback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-07Fix passkey registration showing broken UI when WebAuthn not configuredPeter Stone
Root cause: WEBAUTHN_RP_ID and WEBAUTHN_ORIGIN env vars not set in production, so WebAuthn is nil and all passkey endpoints return 404. The settings page was unconditionally showing the passkey registration card, leading to confusing "Failed to start registration" errors. Fix: Pass WebAuthnEnabled flag from main.go through Handler to the settings template, which now conditionally renders the passkey card only when WebAuthn is properly configured. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07Add build version footer, deploy ldflags, template test helper, and logs scriptPeter Stone
- Display build commit hash in unobtrusive footer overlay - Inject buildCommit/buildTime via ldflags in deploy.sh - Add assertTemplateContains test helper, refactor existing template tests - Add scripts/logs for fetching production journalctl via SSH Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05Add passkey (WebAuthn) authentication supportPeter Stone
Enable passwordless login via passkeys as an alternative to password auth. Users register passkeys from Settings; the login page offers both options. WebAuthn is optional — only active when WEBAUTHN_RP_ID and WEBAUTHN_ORIGIN env vars are set. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05Improve session handling, shopping UI, and cleanupPeter Stone
Session improvements: - Extend session lifetime to 7 days for mobile convenience - Add idle timeout to extend session on activity - Use standard cookie name for better compatibility Shopping model: - Add FlattenItemsForStore helper for extracting store items - Add StoreNames helper for store list - Improve shopping-tab.html with inline add forms Frontend: - Add WebSocket reconnection and agent approval UI to app.js - Simplify timeline calendar JS (move event positioning to CSS) - Update login page styling Deployment: - Remove unused git checkout step from deploy.sh - Update apache.conf WebSocket proxy settings Documentation: - Add Agent Context API feature spec to issues/ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01Improve shopping mode and flatten nav barPeter Stone
Shopping mode: - Click to complete items (deletes user items, hides external items) - Add print button with compact two-column print layout - Fix CSRF token for HTMX requests - Fix input clearing with proper htmx:afterRequest handler - Remove "Quick Add" store option, require valid store Navigation: - Replace dropdown menu with flat nav showing all tabs - Remove unused dropdown JS Tests: - Add TestHandleShoppingModeComplete for user and external items Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31Add feature toggles system with settings UI (#74)Peter Stone
- Add feature_toggles table (migration 012) - Add source_config table for future source selection (migration 013) - Create settings page at /settings with: - Feature toggle management (enable/disable/create/delete) - Data source configuration (sync and toggle boards/calendars) - Add store methods for feature toggles and source config - Add GetCalendarList and GetTaskLists to Google API clients - Document feature toggle workflow in DESIGN.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28Add Agent Context API for external agent integrationPeter Stone
Phase 1: Authentication and read-only context - POST /agent/auth/request - request access with name + agent_id - GET /agent/auth/poll - poll for approval status - POST /agent/auth/approve|deny - user approval (browser auth required) - GET /agent/context - 7-day timeline context (agent session required) Phase 1.5: Browser-only agent endpoints (HTML pages) - GET /agent/web/request - request page with token - GET /agent/web/status - status page with polling - GET /agent/web/context - context page with timeline data WebSocket notifications: - GET /ws/notifications - push agent requests to browsers - Approval modal with trust indicators and countdown timer Database: - agents table for registered agent tracking - agent_sessions table for pending/active sessions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27Fix z-index, conditions auth, and meal combining (#62, #63, #64)Peter Stone
Bug fixes: - #62: Increase FAB button z-index from z-40 to z-50 - #63: Combine multiple meals per date+mealType in Meals tab - #64: Make /conditions route public (no auth required) Changes: - FAB button now z-50 (same as modals, appears on top when scrolling) - Meals tab groups meals by date+mealType, joins recipe names with " + " - Conditions page moved outside protected routes group DESIGN.md updates: - Updated z-index hierarchy table - Added Meals View section - Noted conditions page is public Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26Add Google Tasks integration (#43)Peter Stone
- New GoogleTasksClient for fetching and managing Google Tasks - Tasks appear in Timeline view with yellow indicator dot - Tap checkbox to complete/uncomplete tasks via Google API - Shares credentials file with Google Calendar (GOOGLE_CREDENTIALS_FILE) - Configure task list via GOOGLE_TASKS_LIST_ID env var (default: @default) - Supports comma-separated list IDs for multiple lists New files: - internal/api/google_tasks.go - Google Tasks API client Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26Add shopping mode for focused single-store shopping (#34)Peter Stone
- Full-screen view for one store at a time - Tap items to toggle completion - Completed items greyed and sorted to bottom - Quick-add form at bottom of screen - Store switcher pills for easy navigation - "Shop" button on each store in shopping tab Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26Use configured timezone throughout codebasePeter Stone
- Add config/timezone.go with timezone utilities: - SetDisplayTimezone(), GetDisplayTimezone() - Now(), Today() - current time/date in display TZ - ParseDateInDisplayTZ(), ToDisplayTZ() - parsing helpers - Initialize timezone at startup in main.go - Update all datetime logic to use configured timezone: - handlers/handlers.go - all time.Now() calls - handlers/timeline.go - date parsing - handlers/timeline_logic.go - now calculation - models/atom.go - ComputeUIFields() - models/timeline.go - ComputeDaySection() - api/plantoeat.go - meal date parsing - api/todoist.go - due date parsing - api/trello.go - due date parsing This ensures all dates/times display correctly regardless of server timezone setting. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26Fix calendar timezone handling with configurable display timezonePeter Stone
- Add TIMEZONE config option (defaults to Pacific/Honolulu) - Store display timezone in GoogleCalendarClient - Convert all event times to configured display timezone - Parse events in their native timezone then convert for display This fixes the issue where events were showing 10 hours off due to server running in UTC while user is in Hawaii. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26Phase 4: Extract magic numbers to constantsPeter Stone
Create config/constants.go with centralized configuration values: - Concurrency limits (MaxConcurrentTrelloRequests) - Timeouts (HTTP, Google Calendar, graceful shutdown, request) - Meal times (breakfast, lunch, dinner hours) - Database pool settings (connections, lifetime) - Session and rate limiting settings Update all files to use these constants instead of hardcoded values. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26Phase 3: Error handling and security hardeningPeter Stone
- Handle JSON marshal errors in sqlite.go (log + fallback to empty array) - Add 30s timeout to Google Calendar client initialization - Fix CSRF timing attack by using subtle.ConstantTimeCompare Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>