feat: brain taxonomy — DB-backed folders/tags, sidebar, CRUD API

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>
This commit is contained in:
Yusuf Suleman
2026-04-01 20:23:45 -05:00
parent 4805729f87
commit 68a8d4c228
7 changed files with 693 additions and 100 deletions

View File

@@ -28,8 +28,9 @@ class Item(Base):
url = Column(Text, nullable=True)
raw_content = Column(Text, nullable=True) # original user input (note body, etc.)
extracted_text = Column(Text, nullable=True) # full extracted text from page/doc
folder = Column(String(64), nullable=True)
tags = Column(ARRAY(String), nullable=True, default=list)
folder_id = Column(UUID(as_uuid=False), ForeignKey("folders.id", ondelete="SET NULL"), nullable=True)
folder = Column(String(64), nullable=True) # denormalized folder name for fast reads
tags = Column(ARRAY(String), nullable=True, default=list) # denormalized tag names for fast reads
summary = Column(Text, nullable=True)
confidence = Column(Float, nullable=True)
metadata_json = Column(JSONB, nullable=True, default=dict)