mono/packages/ui/docs/security.md
2026-02-08 15:09:32 +01:00

2.4 KiB

Security Improvement Plan

1. Secrets Management (Critical)

Issue: Profile.tsx currently fetches and exposes API keys (OpenAI, Google, etc.) to the client browser. Goal: Never send raw API keys to the client unless explicitly requested for a "Settings" view context, and even then, mask them.

A. Client Side (Profile.tsx)

  • Remove all code that fetches _api_key columns from profiles in Profile.tsx.
  • Remove Input fields for API keys in the main Profile view in Profile.tsx.
  • Create a new "Provider Settings" page (or modal) protected by re-auth or strict checks (Target: src/pages/ProviderSettings.tsx).
  • Use /api/me/secrets (Server Proxy) to manage keys, never direct DB Updates for secrets.

B. Server Side

  • Ensure user_secrets table has RLS auth.uid() = user_id.
  • Ensure no public endpoints (like /api/profile/:id) return columns from user_secrets in ServingProduct.

2. Authorization & ACL

Goal: Secure multi-user collaboration and Organization access.

A. Shared Pages

  • Implement page_collaborators RLS.
  • Verify: A user cannot edit a page they are only a 'viewer' on.
  • Verify: Listing pages returns both owned and shared pages in PageManager.tsx.

B. Organization Impersonation

  • Middleware: Implement OrganizationMiddleware in server/src.
  • Logic: If X-Org-Slug header is present:
    1. Check if auth.uid() is an Admin/Member of that Org.
    2. If yes, scope all queries to that Organization's collection_id or Context.
    3. (Advanced) Allow "Impersonation" where an Admin acts as a specific user. This requires a signed Token exchange or a Server-Side "Sudo" mode. Decision: For now, stick to Role-Based Access (Admin reads all Org data) rather than direct User Impersonation to avoid audit confusion.

3. General Hardening

  • 404 Handling: In Post.tsx, ensure 404s do not redirect blindly.
    • If permission denied (Private post), show "Unauthorized" (403).
    • If missing, show "Not Found" (404).
  • Rate Limiting: Ensure /api/feed and /api/search have basic rate limiting (using hono-rate-limiter or Redis) to prevent scraping.