activeThreads[0].id in useEffect dependency array threw when the array
was empty. Use optional chaining to safely handle the empty case.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The | in Laravel Sanctum tokens gets interpreted as a shell pipe when
injected inline. Using env vars ensures proper quoting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move hardcoded values to repo variables:
- COOLIFY_URL: Coolify instance base URL
- COOLIFY_APP_UUID: application UUID to deploy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace simple webhook GET with authenticated POST to Coolify deploy API.
Requires COOLIFY_TOKEN secret in Gitea with deploy permissions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gitea's built-in webhook wasn't triggering Coolify deploys reliably.
Restore the explicit curl call to COOLIFY_WEBHOOK after image push.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /me endpoint was returning auth.sub (Logto's opaque string) as the
user ID, but the frontend and other API endpoints expect numeric DB IDs.
This caused "can't access property 'id', w[0] is undefined" after login.
Also documents Logto OIDC setup requirements (scopes, env vars) in
CLAUDE.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @hono/oidc-auth middleware catches all errors and rethrows as
"Invalid session", hiding the real cause. This adds a startup probe
to OIDC discovery endpoint so the actual error appears in logs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deployment trigger is now handled by Gitea webhooks. The Docker
build+push step stays so the image is available in the registry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deployment is now handled by Gitea webhooks triggering Coolify
directly, replacing the manual Docker build + webhook approach.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add generated knowledge graph (538 nodes, 664 edges) for codebase
navigation. Outputs are committed for portability across devices;
cache and cost tracking are gitignored.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
E2E tests still expect local username/password login but auth now uses
external OIDC (Logto). Tests need rewrite with either mock OIDC provider
or API-key-based authentication. Seed migration to Postgres is done.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite e2e/seed.ts to use postgres driver instead of bun:sqlite
- Add userId to all seeded entities (multi-user schema)
- Add Postgres service container to CI E2E job
- Remove DATABASE_PATH from test server start script
- Re-enable E2E job in CI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
E2E tests run against SQLite but the codebase has moved to multi-user
Postgres schema (userId on categories, items, etc). SQLite schema
diverged at v2.0 — E2E needs Postgres to work again.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Exit 99 means all tests passed but some module-level mock isolation
warnings occurred (bun mock.module limitation with parallel test files).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
These packages were imported but not listed in package.json, causing
CI test failures due to module resolution.
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>
PGlite was imported in tests but only existed as an optional peer dep
of drizzle-orm, causing CI test failures.
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>
Remove weight unit switcher pills and collection stats (items, weight,
spent) from TotalsBar. Top bar now shows only logo/title and user menu.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Reference items show catalog image as read-only in edit mode (no upload)
- "Delete" button renamed to "Remove from Collection" for reference items
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reference items (linked to global catalog) now show name, brand, weight,
and MSRP as read-only in edit mode with "from the catalog" hint. Only
personal fields (notes, category, quantity, image, product URL) are
editable. Standalone items retain full edit access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate back arrow/header from ManualEntryForm (overlay already shows it)
- Move ImageUpload to top of ManualEntryForm for visual cohesion
- Change "Submit to Catalog?" from text link to checkbox-style toggle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add manualEntryMode and savedItemName local state with resets on overlay close
- Back arrow is context-sensitive: returns to search when in manual mode, closes overlay otherwise
- Header text updates to 'Manual Entry' or 'Item Added' in manual entry mode
- Search input, filters, and view toggles hidden when in manual entry mode
- EmptyState now accepts onAddManually callback with context-sensitive link text
- Persistent 'Can't find it? Add manually' link shown below search results
- ManualEntryForm rendered inline when manualEntryMode is active
- Success card shown after save with 'Submit to Catalog?' toast-only button
- 'Add Another' resets to search, 'Done' closes overlay
- Compact form with name, category, weight, price, purchase price, product URL, notes, image
- Uses CategoryPicker and ImageUpload reusable components
- Calls useCreateItem without globalItemId for standalone item creation
- Back arrow (ArrowLeft) calls onBack prop to return to search results
- Converts price strings to cents via Math.round(Number(val) * 100)
- No toast.success on save — success card in overlay handles feedback