Backend:
- Added color (hex) and icon (lucide name) columns to folders and tags
- Default folders seeded with colors: Home=green, Work=indigo, Travel=blue, etc.
- API returns color/icon in sidebar and CRUD responses
- Create/update endpoints accept color and icon
Frontend:
- Mobile: horizontal scrollable pill tabs with colored dots
- Desktop sidebar: colored dots next to folder names
- Active pill gets tinted border matching folder color
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- New Folder/Tag/ItemTag models with proper relational tables
- Taxonomy CRUD endpoints: list, create, rename, delete, merge tags
- Sidebar endpoint with folder/tag counts
- AI classification reads live folders/tags from DB, not hardcoded
- Default folders/tags seeded on first request per user
- folder_id FK on items for relational integrity
Frontend:
- Left sidebar with Folders/Tags tabs (like Karakeep)
- Click folder/tag to filter items
- "Manage" mode: add new folders/tags, delete existing
- Counts next to each folder/tag
- "All items" option to clear filter
- Replaces the old signal-strip cards
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Settings were failing with 405 (PUT not supported in Meilisearch v1.12).
Changed to PATCH. Filterable/searchable attributes now applied.
Keyword search working: wedding, yusuf, insurance, airport all return results.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Polls only pending/processing items by ID every 4s instead of
reloading the entire list every 3s. Prevents screen flashing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PDF: extracts selectable text via pymupdf, falls back to Tesseract OCR for scanned docs
- PDF: renders first page as screenshot thumbnail
- Images: Tesseract OCR for text extraction, OpenAI vision API fallback for photos
- Plain text files: direct decode
- All extracted text stored in extracted_text field for search/embedding
- Tested: PDF upload → text extracted → AI classified → searchable
New deps: pymupdf, pytesseract, Pillow
System dep: tesseract-ocr added to both Dockerfiles
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Link detail: shows screenshot image (clickable to open URL), URL, summary, tags
- Note detail: click note text to edit, save/cancel buttons
- Notes: AI now fixes spelling/grammar instead of rewriting
- AI returns corrected_text field for notes, worker replaces raw_content
- Removed verbose meta grid (folder/confidence/status/saved)
- Folder shown as a pill badge in meta line
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 3-column CSS masonry grid (2 on tablet, 1 on mobile)
- Link cards show screenshot thumbnails
- Note cards show content body inline
- Tags as pills, folder/date in meta footer
- Screenshot serving endpoint added to brain API
- Auto-polling for pending items (3s interval)
- Detail sheet shows raw_content for notes
- Warm frosted glass card styling matching Atelier design
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Gateway proxies /api/brain/* to brain-api:8200/api/* via pangolin network
- User identity injected via X-Gateway-User-Id header
- Brain app registered in gateway database (sort_order 9)
- Added to GATEWAY_KEY_SERVICES for dashboard integration
- Tested: health, config, list, create all working through gateway
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full backend service with:
- FastAPI REST API with CRUD, search, reprocess endpoints
- PostgreSQL + pgvector for items and semantic search
- Redis + RQ for background job processing
- Meilisearch for fast keyword/filter search
- Browserless/Chrome for JS rendering and screenshots
- OpenAI structured output for AI classification
- Local file storage with S3-ready abstraction
- Gateway auth via X-Gateway-User-Id header
- Own docker-compose stack (6 containers)
Classification: fixed folders (Home/Family/Work/Travel/Knowledge/Faith/Projects)
and fixed tags (28 predefined). AI assigns exactly 1 folder, 2-3 tags, title,
summary, and confidence score per item.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Trips TLS: Removed all ssl CERT_NONE / check_hostname=False from
5 external HTTPS call sites (OpenAI, Gemini, Google Places, Geocode).
All external calls now use default TLS verification.
2. Internal CORS: Removed permissive cors() from inventory and budget.
Both are internal services accessed only via gateway.
3. App visibility: Documented as cosmetic-only in layout.server.ts.
Nav hiding is intentional UX, not access control.
4. Disconnect safety: Added confirm() dialog before service disconnect
in Settings. Prevents accidental disconnects.
5. Inventory cleanup: Removed stale /test startup log message.
Replaced with API key status indicator.
6. Frontend deps: 4 low-severity cookie vulnerabilities in @sveltejs/kit.
Fix requires breaking downgrade to kit@0.0.30 — not safe. Documented.
#7 Transport Security:
- Removed legacy _ssl_ctx alias from config.py
- proxy.py now uses _internal_ssl_ctx directly (explicitly scoped)
- No global TLS bypass remains
#10 Deployment Hardening:
- Inventory Dockerfile: non-root (node user), health check, production deps
- Budget Dockerfile: non-root (node user), health check, npm ci, multi-stage ready
- Frontend-v2 Dockerfile: multi-stage build, non-root (node user), health check
- Added /health endpoints to inventory and budget (before auth middleware)
- All 6 containers now run as non-root with health checks
All services verified: gateway, trips, fitness, inventory, budget, frontend
- Gateway, Trips, Fitness Dockerfiles: run as non-root (appuser)
- Added HEALTHCHECK to gateway, trips, fitness
- Used --chown=appuser on COPY for correct file permissions
- Created data dirs with proper ownership before USER switch
- Trips Dockerfile no longer copies whole context (only server.py)
Partial fix for #10 — Node services (inventory, budget, frontend) not yet hardened.
- Ran npm audit fix on services/budget — updated path-to-regexp
- npm audit now reports 0 vulnerabilities
- CI enforcement deferred (no Gitea CI runner configured)
Partial fix for #8 — vulnerability resolved, CI setup remaining.
- Gateway: admin user seeded from ADMIN_USERNAME/ADMIN_PASSWORD env vars
(no more hardcoded admin/admin). Warns if not set.
- Trips: USERNAME/PASSWORD env vars no longer default to admin/admin.
Warns if not set.
- Fitness: user seed requires USER{n}_USERNAME/PASSWORD env vars.
No more "changeme" fallback. Skips seed if not set.
- /api/auth/register remains disabled (403)
Closes#2
- Added X-API-Key middleware to inventory-service and budget-service
- Services reject all requests without valid API key (401)
- Gateway proxy injects service API keys for inventory and budget
- Dashboard widget fetchers inject API keys
- Generated unique API keys per service, stored in .env
- Added SERVICE_API_KEY env var to docker-compose for both services
Partial fix for #5 — internal services now require auth.
Remaining: document trust model, validate service token semantics.
- All user_id query params now enforced to authenticated user's own ID
- /api/users restricted to return only current user (no user enumeration)
- Wildcard CORS headers removed (service is internal-only via gateway)
- Covers: entries, totals, goals, templates, favorites, goal setting
Closes#4
- handle_share_api now checks X-Share-Password header against bcrypt hash
before returning trip data. Returns 401 with {protected: true} if password
required but not provided/incorrect
- share_password now stored as bcrypt hash, not plaintext
- All plaintext password logging removed from handle_share_verify
- handle_share_verify uses bcrypt.checkpw instead of string equality
- Migration invalidates existing plaintext share passwords (< 50 chars)
- Removed dead hash_password function (used hashlib.sha256)
- Added bcrypt to trips Dockerfile
Closes#3
- Disable open /api/auth/register endpoint (gateway)
- Require gateway session auth on Immich and Karakeep hooks proxies
- Replace SHA-256 with bcrypt in fitness service (auth + seed)
- Remove hardcoded Telegram user IDs from fitness seed
- Add Secure flag to session cookie
- Add domain allowlist and content-type validation to image proxy
- Strengthen .gitignore (env variants, runtime data, test artifacts)