add multi-user memory sharing with r/w permissions

- New migration 004: memory_shares and tag_shares tables with indexes
- Share individual memories or entire tags with other users (read/write)
- Tag shares are live rules: future memories with shared tags auto-visible
- Recall query merges own + shared memories via UNION, returns shared_by field
- Owner-only delete enforcement (403 for non-owners, even with write access)
- PUT /api/memories/{id} update endpoint with permission checks
- 5 new MCP SSE tools: memory_share, memory_unshare, memory_share_tag,
  memory_unshare_tag, memory_update
- Permission helper checks ownership, individual shares, and tag shares
This commit is contained in:
Viktor Barzin 2026-03-22 15:34:01 +02:00
parent 1a275e976c
commit f45e8ce2b3
No known key found for this signature in database
GPG key ID: 0EB088298288D958
4 changed files with 556 additions and 13 deletions

View file

@ -1,4 +1,4 @@
from typing import Any, Optional
from typing import Any, Literal, Optional
from pydantic import BaseModel, Field
@ -38,3 +38,26 @@ class SecretResponse(BaseModel):
class SyncResponse(BaseModel):
memories: list[dict[str, Any]]
server_time: str
class ShareMemory(BaseModel):
shared_with: str = Field(..., min_length=1, max_length=100)
permission: Literal["read", "write"] = "read"
class ShareTag(BaseModel):
tag: str = Field(..., min_length=1, max_length=100)
shared_with: str = Field(..., min_length=1, max_length=100)
permission: Literal["read", "write"] = "read"
class UnshareTag(BaseModel):
tag: str = Field(..., min_length=1, max_length=100)
shared_with: str = Field(..., min_length=1, max_length=100)
class MemoryUpdate(BaseModel):
content: Optional[str] = Field(None, max_length=MAX_MEMORY_CHARS)
tags: Optional[str] = None
importance: Optional[float] = Field(None, ge=0.0, le=1.0)
expanded_keywords: Optional[str] = None