271 Commits

Author SHA1 Message Date
9c7bc2881c fix: add CORS headers for OAuth and MCP endpoints
All checks were successful
CI / ci (push) Successful in 31s
CI / e2e (push) Successful in 1m2s
Required for claude.ai browser-based OAuth flows that make
cross-origin requests to discovery, token, and MCP endpoints.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v1.4.1
2026-04-04 10:48:22 +02:00
412ca60e42 style: apply biome formatting to OAuth service and tests
All checks were successful
CI / ci (push) Successful in 37s
CI / e2e (push) Successful in 1m55s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v1.4.0
2026-04-04 09:27:57 +02:00
5fdf4c3019 docs: add MCP OAuth documentation and fix lint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 09:27:34 +02:00
6dcb421fb0 test: add end-to-end OAuth to MCP flow integration test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:26:25 +02:00
f01add3943 feat: add Bearer token auth to MCP alongside API key auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:24:10 +02:00
1fad25726d feat: add OAuth 2.1 endpoints (register, authorize, token)
Add well-known metadata, dynamic client registration, authorization
flow with PKCE, and token exchange/refresh endpoints with route-level
integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 09:22:58 +02:00
7309c080df feat: add OAuth service with PKCE, token management, and tests
Implements client registration, authorization code flow with PKCE (S256),
access/refresh token generation/verification, and cleanup utilities.
Follows TDD — all 12 service-level tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:20:09 +02:00
f47e1d74ae feat: add OAuth tables (clients, codes, tokens) to schema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:17:53 +02:00
c04b9b0e09 docs: add MCP OAuth 2.1 implementation plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 09:09:30 +02:00
6a77995530 docs: add MCP OAuth 2.1 server design spec
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 09:03:11 +02:00
1344f2f87f docs: create milestone v2.0 roadmap (5 phases) 2026-04-03 22:24:24 +02:00
64403f6977 docs: define milestone v2.0 requirements 2026-04-03 22:19:52 +02:00
443802fc68 docs: complete project research 2026-04-03 22:14:27 +02:00
642ae0d43f docs: start milestone v2.0 Platform Foundation 2026-04-03 21:53:31 +02:00
f9c6693b63 docs: add releasing section to CLAUDE.md
All checks were successful
CI / ci (push) Successful in 27s
CI / e2e (push) Successful in 1m5s
Document the Gitea Actions release pipeline and how to trigger it
via API with patch/minor/major bump types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 21:11:53 +02:00
bb60168ffb Merge pull request 'feat: user menu dropdown + fix MCP tool schemas' (#10) from feature/user-menu-dropdown into Develop
All checks were successful
CI / ci (push) Successful in 25s
CI / e2e (push) Successful in 1m2s
v1.3.2
2026-04-03 18:59:59 +00:00
68f6647f76 fix: convert MCP tool schemas from JSON Schema to Zod for SDK v1.29.0
All checks were successful
CI / ci (push) Successful in 28s
CI / ci (pull_request) Successful in 25s
CI / e2e (push) Successful in 1m2s
CI / e2e (pull_request) Successful in 1m3s
The MCP SDK v1.29.0 changed server.tool() to require Zod schemas
(raw shapes) instead of plain JSON Schema objects. The old format
triggered "expected a Zod schema or ToolAnnotations" errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 20:54:20 +02:00
0a40d7627f feat: add user menu dropdown with settings link and sign out
Replace the plain "Sign out" button in the header with a user icon
that opens a dropdown menu containing Settings and Sign out options.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 20:19:53 +02:00
3eccbb12fd Merge pull request 'v1.4 Collection Tools' (#9) from feature/v1.4-collection-tools into Develop
All checks were successful
CI / ci (push) Successful in 24s
CI / e2e (push) Successful in 1m0s
2026-04-03 18:05:23 +00:00
fb925a9dce fix: include quantity in getAllItems select, createItem values, and updateItem type
All checks were successful
CI / ci (push) Successful in 24s
CI / ci (pull_request) Successful in 25s
CI / e2e (push) Successful in 1m3s
CI / e2e (pull_request) Successful in 1m1s
Quantity was missing from three places in item.service.ts:
- getAllItems didn't select it (API returned undefined)
- createItem didn't pass it to insert (always used DB default of 1)
- updateItem type didn't include it (silently stripped from updates)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 19:57:25 +02:00
70e7cd2f0f fix: show Add Candidate button in comparison view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:51:49 +02:00
33f735af67 fix: remove scale/shadow whileDrag effect that stuck after release
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:50:49 +02:00
f8a1a00e0a fix: prevent snap-back after drag and click-opens-edit during drag
Two fixes:
- Remove onSettled clearing tempItems before refetch completes,
  let useEffect clear it when fresh server data arrives
- Track isDragging ref to suppress edit panel click after drag
- Remove layout="position" which interfered with reorder detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:49:39 +02:00
27c36b6b9a fix: make entire candidate row draggable instead of handle-only
Remove dragControls/dragListener pattern which prevented onReorder
from firing. The whole row is now the drag target with visual feedback
(scale + shadow). Grip icon remains as a visual indicator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:46:52 +02:00
684cfd3789 fix: stabilize drag-to-reorder with layout animation fixes
- Remove transition-all from list items (fights framer-motion layout)
- Add layout="position" to Reorder.Item for proper sibling tracking
- Replace CSS gap with marginBottom (gap confuses layout engine)
- Add explicit short transition duration for snappy reorder

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:44:39 +02:00
52751ae9d4 fix: use onDragEnd on Reorder.Item instead of onPointerUp on Group
The previous approach used onPointerUp on the Reorder.Group which
fired unreliably — triggering on non-drag clicks and sometimes not
at all after a drag. Moving to onDragEnd on each Reorder.Item gives
clean, predictable drag-to-reorder behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:42:16 +02:00
3fc737c872 fix: add tab navigation to collection page and skip 404 retries
Adds Gear/Planning/Setups pill tabs to the collection page so users
can switch tabs without going back to the dashboard. Also skips
React Query retries on 404 responses for immediate error display.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:31:57 +02:00
b993a0a831 fix: skip retries on 404 for single-resource queries
Prevents 10-second loading skeleton when navigating to non-existent
threads, setups, or items. Shows error/not-found state immediately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:28:04 +02:00
a8696c2a85 fix: commit missing migration metadata and run CI on all branches
All checks were successful
CI / ci (push) Successful in 25s
CI / ci (pull_request) Successful in 26s
CI / e2e (push) Successful in 1m24s
CI / e2e (pull_request) Successful in 1m23s
The Drizzle migration journal and snapshot for 0008 (quantity column)
were not committed, causing test failures in CI. Also updates CI to
trigger on all branches, not just Develop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:18:12 +02:00
15f146ee89 feat: add CSV import/export for gear collection
Some checks failed
CI / ci (pull_request) Failing after 22s
CI / e2e (pull_request) Has been skipped
Adds export (GET /api/items/export) and import (POST /api/items/import) routes
backed by a pure csv.service with no external deps, plus useExportItems/useImportItems
hooks and an Import/Export section in the Settings page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:12:07 +02:00
8c1fe47a99 feat: add setup impact preview UI with delta badges across all views
Adds SetupImpactSelector dropdown and ImpactDeltaBadge inline badge, wired into the thread detail page. Delta badges appear on CandidateListItem, CandidateCard, and ComparisonTable (Weight Impact / Price Impact rows) whenever a setup is selected for comparison.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:11:57 +02:00
b9a06dd244 feat: add item duplication with copy-and-edit workflow
Adds POST /api/items/:id/duplicate endpoint, useDuplicateItem hook, and a
Duplicate button on ItemCard (collection view only) that opens the new item
for editing immediately after creation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:07:20 +02:00
818db73432 feat: add impact delta computation with TDD tests
Implements computeImpactDeltas pure function with 8 TDD tests covering replace/add/none modes and null weight/price handling. Adds useImpactDeltas hook, categoryId to ThreadWithCandidates, and selectedSetupId state to uiStore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:06:46 +02:00
1a5e6a303e feat: add quantity support to totals, UI, and thread resolution
- totals.service: multiply weight/cost sums by quantity in category and global totals
- setup.service: multiply by quantity in getAllSetups SQL subqueries; expose quantity in getSetupWithItems item list
- thread.service: explicitly pass quantity: 1 when inserting resolved item
- ItemForm: add Quantity number input (min=1, default=1) after price field
- ItemCard: show ×N badge next to item name when quantity > 1
- CollectionView: pass quantity prop to ItemCard in both filtered and grouped views
- $setupId.tsx: pass quantity to ItemCard; multiply by quantity in client-side per-setup totals
- WeightSummaryCard: multiply by quantity in all chart and legend weight calculations
- useItems / useSetups: add quantity to ItemWithCategory / SetupItemWithCategory interfaces

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:04:27 +02:00
923a0f66b0 feat: add quantity field to items schema
Add integer quantity column (default 1) to the items table, generate
the corresponding Drizzle migration, and extend createItemSchema /
updateItemSchema with an optional positive-integer quantity field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:04:15 +02:00
1b492f2ac2 docs: add v1.4 Collection Tools design spec
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:00:02 +02:00
70466a9a1c fix(ci): install unzip before Bun in E2E job
All checks were successful
CI / ci (push) Successful in 25s
CI / e2e (push) Successful in 1m21s
The Playwright Docker image lacks unzip, which Bun's install script requires.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 17:47:50 +02:00
5e0771d929 ci: add Playwright E2E tests to CI pipeline
Some checks failed
CI / ci (push) Successful in 25s
CI / e2e (push) Failing after 55s
Runs as a separate job after unit tests pass, using the official
Playwright Docker image with Chromium pre-installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 17:45:52 +02:00
70211bdc57 fix: add bunfig.toml to scope bun test to tests/ directory
All checks were successful
CI / ci (push) Successful in 26s
Prevents bare `bun test` from picking up Playwright .spec.ts files
in the e2e/ directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 17:43:53 +02:00
35989f8120 docs: update CLAUDE.md with branching workflow, E2E testing commands
Some checks failed
CI / ci (push) Failing after 22s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 17:42:01 +02:00
b974675b11 fix: scope bun test to tests/ directory to exclude Playwright files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 16:25:56 +02:00
c4ce96ce4f test: add E2E tests for threads, auth, and error handling
Also fix CandidateListItem to not use Reorder.Item when isActive=false,
which caused a framer-motion crash on resolved thread detail pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 16:23:26 +02:00
60db8bd9de test: add E2E tests for dashboard and collection views
Covers dashboard card rendering (item count, nav links, active thread/setup counts)
and collection page (gear display, search, category filter, tab switching).
Updates playwright config to serve production build with pre-seeded test DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 16:14:07 +02:00
ecbfbc00e9 test: add E2E database seed and Playwright global setup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 16:10:12 +02:00
f7ce380104 chore: install Playwright and add E2E test configuration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 16:07:50 +02:00
0d7c4f476a test: add unit tests for rate limiter middleware 2026-04-03 16:05:54 +02:00
86a4a747b5 test: add unit tests for parseId helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 16:05:35 +02:00
e9d33e59e9 refactor: add useFormatters hook to reduce boilerplate across 14 components
Created useFormatters() combining useWeightUnit + useCurrency + formatWeight/formatPrice
into a single hook returning weight(grams) and price(cents) bound functions plus
raw unit and currency values. Updated all 14 consumer files to use the new hook,
removing the repeated 4-import + 2-hook-call pattern from each.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:49:16 +02:00
5308991123 refactor: replace hand-written test SQL with Drizzle migration runner
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:44:42 +02:00
a6e7035aab chore: mark planning category filter todo as done
The icon-aware CategoryFilterDropdown was already wired into PlanningView
during Phase 8 (v1.2), replacing the native <select>.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 15:43:45 +02:00