Encrypt file paths in API URLs using Fernet tokens

Raw filesystem paths were exposed in browser URLs, dev tools, and proxy logs.
Now all file-serving endpoints accept an opaque encrypted token (t= param)
derived from the session secret via HKDF, with a 4-hour TTL.

Backend:
- Add core/path_tokens.py with Fernet encrypt/decrypt (HKDF from .session_secret)
- Add file_token to all list/gallery/feed/search responses across 7 routers
- Accept optional t= param on all file-serving endpoints (backward compatible)

Frontend:
- Update 4 URL helpers in api.ts to prefer token when available
- Add 4 new helpers for paid-content/embedded-metadata URLs
- Update all 14 page/component files to pass file_token to URL builders
- Add file_token to all relevant TypeScript interfaces

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Todd
2026-03-30 08:25:22 -04:00
parent 523f91788e
commit 49e72207bf
24 changed files with 295 additions and 65 deletions

View File

@@ -19,6 +19,7 @@ from slowapi.util import get_remote_address
from ..core.dependencies import get_current_user, require_admin, get_app_state
from ..core.exceptions import handle_exceptions, ValidationError
from ..core.path_tokens import encode_path
from modules.semantic_search import get_semantic_search
from modules.universal_logger import get_logger
@@ -93,6 +94,9 @@ async def semantic_search(
source=source,
threshold=threshold
)
for r in results:
fp = r.get('file_path')
r['file_token'] = encode_path(fp) if fp else None
return {"results": results, "count": len(results), "query": query}
@@ -118,6 +122,9 @@ async def find_similar_files(
source=source,
threshold=threshold
)
for r in results:
fp = r.get('file_path')
r['file_token'] = encode_path(fp) if fp else None
return {"results": results, "count": len(results), "source_file_id": file_id}