Commit Graph

90 Commits

Author SHA1 Message Date
e8207a33f9 feat(28-01): add account management routes for password, email, and deletion
Creates /api/account routes with password change (verifies current first),
email update, has-password check, and account deletion with public setup
anonymization. Adds Zod validation schemas and registers routes in index.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:47:17 +02:00
fcd8279d79 feat(28-01): create Logto Management API client service with M2M auth
Implements LogtoManagementClient with token caching, password verification,
password update, email update, user deletion, and has-password check.
All methods proxy to Logto Management API via M2M credentials.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:45:48 +02:00
6e3ce4a31f fix: resolve biome lint errors in discovery files
All checks were successful
CI / ci (push) Successful in 1m8s
CI / e2e (push) Has been skipped
CI / deploy (push) Successful in 14s
Remove unused functions and imports from route tests, fix array index key
warnings in skeleton components, apply biome formatting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:15:58 +02:00
0323e0cd33 feat(26-02): discovery HTTP routes, server registration, and route tests
- Create src/server/routes/discovery.ts with GET /setups, /items, /categories handlers
- Register discoveryRoutes in src/server/index.ts with browseTier rate limiting
- Add auth skip for /api/discovery/* GET requests in auth middleware
- Create tests/routes/discovery.test.ts with 10 tests covering all endpoints and pagination
2026-04-10 14:57:35 +02:00
06b6e935f2 test(26-01): add failing tests for discovery service
- getPopularSetups: ordering, privacy filter, cursor pagination, creatorName
- getRecentGlobalItems: ordering, cursor pagination, second page deduplication
- getTrendingCategories: ordering by count desc, null category exclusion, empty state
2026-04-10 14:53:09 +02:00
fc9a9134e8 chore(25-02): apply biome formatter to task 1 and 2 files 2026-04-10 11:06:11 +02:00
df6c75f164 feat(25-02): add MCP catalog tools upsert_catalog_item and bulk_upsert_catalog
- New catalog.ts with catalogToolDefinitions and registerCatalogTools
- upsert_catalog_item: single item upsert with full attribution fields (SEED-03)
- bulk_upsert_catalog: batch upsert up to 100 items with created/updated counts
- Registered in createMcpServer after image tools
- 6 new MCP catalog tool tests passing
2026-04-10 11:03:50 +02:00
25f590247c test(25-02): add failing tests for POST single and bulk upsert routes 2026-04-10 11:02:28 +02:00
c8ebbf8139 feat(25-01): Zod schemas, upsert service functions, passing tests
- Add upsertGlobalItemSchema and bulkUpsertGlobalItemsSchema to schemas.ts
- Add UpsertGlobalItemInput and BulkUpsertGlobalItemsInput types to types.ts
- Implement upsertGlobalItem with onConflictDoUpdate and tag sync
- Implement bulkUpsertGlobalItems processing array in single transaction
- Fix migration 0003 to only add new columns + unique constraint
- All 21 tests pass including 8 new upsert operation tests
2026-04-10 10:58:36 +02:00
9093a2c8f6 test(25-01): add failing tests for upsertGlobalItem and bulkUpsertGlobalItems
- Import upsertGlobalItem and bulkUpsertGlobalItems (not yet exported)
- Tests cover: create, conflict update, attribution fields, tag sync
- Tests cover: empty tags clear, tags omitted leaves untouched
- Tests cover: bulk upsert counts (created vs updated)
2026-04-10 10:56:54 +02:00
afab8175f9 feat(24-01): refactor rateLimit to factory pattern with createRateLimit
- Add createRateLimit(maxAttempts, windowMs) factory function
- Rewrite rateLimit export to delegate to factory (backward compatible)
- Keep shared store, getClientIp, cleanup, and _resetForTesting unchanged
- Add createRateLimit factory test suite with 5 test cases
- All existing rateLimit middleware tests still pass
2026-04-10 10:06:19 +02:00
b9c3bf5b5f fix: update auth test to expect numeric user ID from /me endpoint
All checks were successful
CI / ci (push) Successful in 1m4s
CI / e2e (push) Has been skipped
CI / deploy (push) Successful in 13s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:34:07 +02:00
be1197f3da fix: lint formatting in storage test
Some checks failed
CI / ci (push) Successful in 1m7s
CI / e2e (push) Has been skipped
CI / deploy (push) Failing after 11s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:31:39 +02:00
d519a83cc4 infra: migrate deployment to Coolify with Garage S3
Some checks failed
CI / ci (push) Failing after 19s
CI / deploy (push) Has been skipped
CI / e2e (push) Has been skipped
- Remove docker-compose files (Coolify manages services individually)
- Replace MinIO with Garage (S3-compatible, actively maintained)
- Add CI deploy job: build+push :develop image on every green Develop push
- Add Coolify webhook trigger for automatic redeployment
- Update README, .env.example, and storage references
- Rename migrate script to provider-agnostic name

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:28:43 +02:00
27c139de9a fix: update OAuth service tests for userId-from-record refactor
Some checks failed
CI / ci (push) Failing after 58s
CI / e2e (push) Has been skipped
- 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>
2026-04-06 20:30:30 +02:00
7dbbfcb915 fix: resolve all 13 remaining test failures
Some checks failed
CI / ci (push) Failing after 56s
CI / e2e (push) Has been skipped
- 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>
2026-04-06 20:25:41 +02:00
6482bc3b8a fix: format tests/helpers/db.ts
Some checks failed
CI / ci (push) Failing after 44s
CI / e2e (push) Has been skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 20:10:20 +02:00
c09183d94a fix: optimize test infrastructure and fix missing brand migration
Some checks failed
CI / ci (push) Failing after 13s
CI / e2e (push) Has been skipped
- 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>
2026-04-06 20:08:11 +02:00
3638e7b240 fix: resolve all lint errors across source and test files
Some checks failed
CI / ci (push) Failing after 11s
CI / e2e (push) Has been skipped
- 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>
2026-04-06 19:39:47 +02:00
62249b5b48 Merge branch 'worktree-agent-adbc35a5' into Develop
# Conflicts:
#	.planning/STATE.md
#	drizzle-pg/meta/0002_snapshot.json
#	drizzle-pg/meta/_journal.json
#	src/db/schema.ts
2026-04-06 08:00:04 +02:00
67facea338 feat(20-01): extend UIStore with FAB/catalog state, add useTags hook, update useGlobalItems
- 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
2026-04-06 07:57:47 +02:00
6f07e874f9 test(20-01): add failing tests for tag service and route
- Tag service tests: empty array, alphabetical ordering, id+name projection
- Tag route tests: GET /api/tags returns 200, correct tag objects
2026-04-06 07:56:32 +02:00
ecc6ac689a feat(19-03): add tag filtering to global item search and migrate owner count
- 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>
2026-04-05 20:55:36 +02:00
8a5ee731d0 feat(19-02): add catalog-linked candidates, branched resolution, remove link/unlink routes
- 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
2026-04-05 20:49:56 +02:00
d1ffd79bbb feat(19-02): add COALESCE merge for reference items in item service
- 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
2026-04-05 20:34:54 +02:00
574a12e6fa fix: OIDC auth flow, Vite proxy, and PostgreSQL query compat
- 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>
2026-04-05 18:25:31 +02:00
2843351d90 Merge branch 'worktree-agent-a86c0a6d' into Develop
# Conflicts:
#	.planning/REQUIREMENTS.md
#	.planning/STATE.md
#	src/db/schema.ts
#	src/db/seed.ts
#	src/server/index.ts
#	src/server/routes/setups.ts
#	src/server/services/category.service.ts
#	src/server/services/setup.service.ts
#	src/shared/schemas.ts
#	src/shared/types.ts
2026-04-05 13:13:34 +02:00
465297c398 Merge branch 'worktree-agent-a7e6e4b2' into Develop
# Conflicts:
#	.planning/REQUIREMENTS.md
#	.planning/ROADMAP.md
#	.planning/STATE.md
#	drizzle/meta/_journal.json
#	src/db/schema.ts
#	src/db/seed.ts
#	src/shared/schemas.ts
#	src/shared/types.ts
2026-04-05 13:13:26 +02:00
eb8f4b7cb2 feat(18-03): add profile routes, public setup endpoint, and auth middleware updates
- 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
2026-04-05 13:10:13 +02:00
d97d5d92ba feat(18-02): add global item routes, item link/unlink endpoints, and route tests
- 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
2026-04-05 13:07:26 +02:00
3a6876f7e8 test(18-02): add failing tests for global item service and seed
- 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
2026-04-05 13:05:28 +02:00
2d5d4f9c1a test(18-03): add failing tests for profile service and setup isPublic
- Profile CRUD tests: updateProfile, getPublicProfile, getPublicSetupWithItems
- Setup service isPublic tests: create with isPublic, toggle, list includes isPublic
2026-04-05 13:05:02 +02:00
89b0496845 chore(18-03): apply 18-01 schema foundation as dependency baseline 2026-04-05 13:04:09 +02:00
5ce3f92a78 feat(17-02): refactor image service and routes to use S3 storage service
- Replace Bun.write/mkdir with uploadImage() from storage.service
- Remove uploadsDir parameter from fetchImageFromUrl
- Update tests to mock storage service instead of checking filesystem
2026-04-05 12:20:31 +02:00
544dd5bcd9 Merge branch 'worktree-agent-a402d11d' into Develop
# Conflicts:
#	.env.example
#	.planning/STATE.md
#	bun.lock
#	docker-compose.dev.yml
#	docker-compose.yml
#	package.json
2026-04-05 12:17:35 +02:00
f845f878fe feat(17-01): add S3 storage service with upload, delete, and presigned URL support
- Create storage.service.ts wrapping @aws-sdk/client-s3 with forcePathStyle for MinIO
- Export uploadImage, deleteImage, getImageUrl, withImageUrl, withImageUrls
- Add unit tests with mocked S3Client (8 tests passing)
- Install @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner
2026-04-05 12:15:09 +02:00
5ae3836d64 fix(16): add async/await to createTestDb in route and MCP tests
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>
2026-04-05 11:52:38 +02:00
c4a7a6c76f fix(16): restore OIDC-based oauth tests with userId support
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>
2026-04-05 11:34:10 +02:00
98aed09d11 Merge branch 'worktree-agent-ad8081f0' into Develop
# Conflicts:
#	.planning/REQUIREMENTS.md
#	.planning/STATE.md
#	tests/mcp/tools.test.ts
#	tests/routes/auth.test.ts
#	tests/routes/categories.test.ts
#	tests/routes/items.test.ts
#	tests/routes/oauth.test.ts
#	tests/routes/params.test.ts
#	tests/routes/setups.test.ts
#	tests/routes/threads.test.ts
2026-04-05 11:33:13 +02:00
5085d8e3f7 feat(16-04): update route tests and MCP tests for multi-user userId
- 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>
2026-04-05 11:31:05 +02:00
5b702a0e98 feat(16-04): update all service tests to pass userId and add isolation tests
- 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
2026-04-05 11:01:51 +02:00
ad309510af Merge branch 'worktree-agent-a9a8b0dc' into Develop
# Conflicts:
#	.planning/REQUIREMENTS.md
#	.planning/ROADMAP.md
#	.planning/STATE.md
#	drizzle-pg/meta/0000_snapshot.json
#	drizzle-pg/meta/_journal.json
#	src/db/schema.ts
#	src/db/seed.ts
#	src/server/middleware/auth.ts
#	src/server/services/auth.service.ts
#	src/server/services/category.service.ts
#	src/server/services/oauth.service.ts
#	tests/helpers/db.ts
2026-04-05 10:38:29 +02:00
050478c543 feat(16-01): update test helper to seed user and return { db, userId }
- 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
2026-04-05 10:34:38 +02:00
6be9a2b168 fix(15): update oauth routes/tests for async + OIDC session auth
- 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>
2026-04-04 21:43:06 +02:00
59e7f4be8a fix(15): convert auth service/tests to async PGlite pattern
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>
2026-04-04 21:40:12 +02:00
72eefd1a06 Merge branch 'worktree-agent-a7f7c229' into Develop
# Conflicts:
#	.planning/REQUIREMENTS.md
#	.planning/ROADMAP.md
#	.planning/STATE.md
#	tests/routes/auth.test.ts
#	tests/services/auth.service.test.ts
2026-04-04 20:56:29 +02:00
689a56b2b7 feat(15-03): update E2E seed and auth tests for OIDC architecture
- 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
2026-04-04 20:54:18 +02:00
f30d375544 feat(14-06): convert route tests + MCP tests to async PGlite
- All 8 route test files: async createTestApp(), async beforeEach
- MCP tools test: await createTestDb(), await getCollectionSummary()
- Fixed MCP tool files: added await to all service calls in items, categories, threads, setups tools
- Fixed MCP collection resource: made getCollectionSummary async
- Fixed MCP index.ts: await getCollectionSummary call
- Increased test timeout to 30s in bunfig.toml for PGlite WASM overhead
- Zero SQLite references remain in tests/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:40:14 +02:00
458b33f1c7 feat(14-06): convert all 9 service test files to async PGlite
- 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>
2026-04-04 13:11:52 +02:00
3bf1fd7cb8 feat(14-01): add PGlite test helper and generate initial PostgreSQL migration
- 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
2026-04-04 12:18:50 +02:00