- Add userId param to createAuthorizationCode calls
- Remove userId param from exchangeCode and refreshAccessToken calls
(now derived from stored records)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OAuth: add userId to oauth_codes schema and migration, derive userId
from stored auth code/token record instead of passing separately
- Auth middleware tests: destructure {db, userId} from createTestDb,
pass userId to createApiKey, fix error message assertion
- MCP tests: add missing await on getCollectionSummary and
createSecondTestUser calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Share PGlite instance per test file (TRUNCATE RESTART IDENTITY instead
of creating new instance per test) — tests run in ~9s vs minutes
- Add missing 'brand' column to items table migration
- Fix corrupt 0002 snapshot (merge conflict artifacts)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix unused function parameters (prefix with _)
- Fix unused imports in test files
- Fix import ordering in test files
- Auto-fix formatting issues across 22 files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add fabMenuOpen, openFabMenu, closeFabMenu to UIStore
- Add catalogSearchOpen, catalogSearchMode, openCatalogSearch, closeCatalogSearch
- openCatalogSearch also closes FAB menu (natural flow)
- Create useTags hook with 5-min staleTime cache
- Add optional tags parameter to useGlobalItems for tag filtering
- searchGlobalItems now accepts tagNames param with AND intersection logic
- Owner count uses items.globalItemId instead of removed itemGlobalLinks
- Removed linkItemToGlobal and unlinkItemFromGlobal functions
- Route handlers now async with tags query param support
- Rewrote tests to async PGlite pattern, added tag filtering tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- getThreadWithCandidates LEFT JOINs globalItems with COALESCE for name, weight, price, image
- createCandidate accepts and stores globalItemId
- resolveThread branches: reference item (globalItemId set) vs standalone (full data copy)
- Removed link/unlink endpoints from items route (replaced by direct globalItemId FK)
- 6 new tests for catalog-linked candidates and branched resolution
- getAllItems and getItemById LEFT JOIN globalItems with COALESCE for name, weight, price, image
- createItem accepts globalItemId and purchasePriceCents, stores brand+model as fallback name
- duplicateItem preserves globalItemId and purchasePriceCents
- updateItem type includes globalItemId and purchasePriceCents
- 10 new tests for reference item creation and merged data retrieval
- Add auth redirect in root layout for unauthenticated users
- Proxy OIDC routes (/login, /callback, /logout) through Vite dev server
- Strip Secure flag from OIDC cookies in dev mode (HTTP localhost)
- Disable retry on auth query to prevent stale cookie loops
- Fix SQLite .get()/.all()/.run() calls in category and global-item
services for PostgreSQL compatibility
- Add userId scoping to category service functions
- Add OIDC error logging in auth middleware
- Apply linter auto-formatting across affected files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- GET /api/users/:id/profile: public profile with public setups (no auth)
- PUT /api/auth/profile: update own profile (requires auth)
- GET /api/setups/:id/public: public setup view with items (no auth)
- Auth middleware skips public profile and public setup GET endpoints
- Register profileRoutes at /api/users in index.ts
- Add getOrCreateUncategorized to category service (Rule 3 fix)
- 10 route tests covering auth, public access, and 404 cases
- GET /api/global-items with optional q search parameter
- GET /api/global-items/:id with ownerCount
- POST /api/items/:id/link to link user item to global item
- DELETE /api/items/:id/link to unlink
- Route registered in index.ts
- 10 route tests covering all endpoints
- 10 test cases covering search, owner count, link/unlink, seed idempotency
- Added globalItems/itemGlobalLinks tables to SQLite schema
- Added Zod schemas and types for global items
- Created 18-item bikepacking gear seed data JSON
- Profile CRUD tests: updateProfile, getPublicProfile, getPublicSetupWithItems
- Setup service isPublic tests: create with isPublic, toggle, list includes isPublic
- Replace Bun.write/mkdir with uploadImage() from storage.service
- Remove uploadsDir parameter from fetchImageFromUrl
- Update tests to mock storage service instead of checking filesystem
Route and MCP test files were calling createTestDb() without await,
causing db to be a Promise object instead of a Drizzle instance.
Also rewrote auth route tests for OIDC-based auth (merge picked old version).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge conflict resolution picked the old password-based oauth tests.
Restored the OIDC session mock version with proper userId destructuring.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All 8 route test files destructure { db, userId } from createTestDb()
- All route test middleware sets c.set("userId", userId)
- MCP tools.test.ts passes userId to all registerXTools(db, userId) calls
- MCP tools.test.ts passes userId to getCollectionSummary(db, userId)
- Added 4 cross-user isolation tests for MCP tools (items, item by ID, threads, collection summary)
- OAuth test db type annotation updated for new createTestDb return shape
- Images test now uses createTestDb with userId context
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Destructure { db, userId } from createTestDb() in all 8 service test files
- Pass userId to every service function call
- Add cross-user isolation tests for items, categories, threads, setups
- Add composite unique constraint test for categories
- Update verifyApiKey assertions to check { userId } return
- Update verifyAccessToken assertions to check { userId } return
- Pass userId to exchangeCode and refreshAccessToken calls
- createTestDb uses PGlite with drizzle-pg migrations
- Seeds test user with logtoSub and per-user Uncategorized category
- Returns { db, userId } instead of just db
- Add createSecondTestUser helper for cross-user isolation tests
- Add await to all oauth service calls in routes (registerClient, getClient, etc.)
- Rewrite oauth tests to use mocked OIDC session instead of createUser/password
- Test consent-based authorize flow instead of credential-based flow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The executor agents wrote sync SQLite-style calls (.get(), .all(), .run())
instead of the async Postgres pattern established in Phase 14. Fixed:
- auth.service.ts: use await + destructuring for all DB operations
- auth routes: await listApiKeys
- All auth test files: async createTestDb(), await service calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- E2E seed creates API key instead of user for authentication
- Auth service tests cover only API key CRUD (removed user/session tests)
- Auth middleware tests validate three-way auth: API key, Bearer token, OIDC session
- Auth route tests mock getAuth for OIDC session, test /me and /keys endpoints
- Remove all references to createUser, verifyPassword, createSession in auth tests
- All beforeEach now use async/await createTestDb()
- All service calls in tests now awaited
- All direct DB calls (.run()/.all()) replaced with await
- All test callbacks made async
- Fixed PostgreSQL GROUP BY strictness in totals.service.ts (categories.name and categories.icon added to groupBy)
- db type changed to 'any' to accommodate PGlite type differences
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite tests/helpers/db.ts to use drizzle-orm/pglite with async createTestDb()
- Generate initial migration with 13 CREATE TABLE statements in drizzle-pg/
- Add drizzle-pg to biome ignore list (generated files)
- PGlite smoke test confirms migrations apply and seed works
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>
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>
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>
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>
Use Bun.serve to create a local test server instead of hitting
external URLs. Fixes flaky test in CI environments without
network access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Exclude drizzle/ and .planning/ from Biome (generated files with
incompatible formatting). Auto-fix import ordering and formatting
in existing source files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>