feat: multi-tenant workspace isolation, RBAC, sidebar nav, billing, and Android enhancements

- Backend: workspace_id isolation for 14 model tables + safe migration/backfill
- Backend: RBAC system with 4 roles and 23 permissions, seeded on startup
- Backend: workspace admin endpoints (list/manage all workspaces)
- Backend: admin user management API (CRUD, reset password)
- Backend: billing API with subscription plans, usage tracking, rate limiting
- Backend: fix system_logs.py UNION query and wrong column references
- Backend: WebSocket JWT auth and workspace enforcement
- Frontend: sidebar navigation replacing top dropdown menu
- Frontend: user management page (Users.vue) for admins
- Frontend: enhanced Workspaces.vue with admin table view
- Frontend: workspace RBAC computed properties in user store
- Android: agent marketplace, billing/subscription UI, onboarding wizard
- Android: phone login, analytics tracker, crash handler, network diagnostics
- Android: splash screen, encrypted token storage, app update enhancements
- Docs: multi-tenant RBAC guide with 8 sections and role-permission matrix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 01:00:22 +08:00
parent 51eafb23f3
commit 876789fac1
93 changed files with 8803 additions and 669 deletions

View File

@@ -2,7 +2,7 @@
Agent 执行日志模型 — 结构化记录每次 Agent 执行的完整信息
用于知识自进化系统的数据基础
"""
from sqlalchemy import Column, String, Text, Integer, DateTime, JSON, Float, Boolean
from sqlalchemy import Column, String, Text, Integer, DateTime, JSON, Float, Boolean, ForeignKey
from sqlalchemy.dialects.mysql import CHAR
from app.core.database import Base
import uuid
@@ -20,6 +20,7 @@ class AgentExecutionLog(Base):
task_id = Column(String(36), nullable=True, index=True, comment="关联 Task ID")
user_id = Column(String(36), nullable=True, index=True, comment="用户 ID")
session_id = Column(String(100), nullable=True, comment="会话标识")
workspace_id = Column(CHAR(36), ForeignKey("workspaces.id"), nullable=True, index=True, comment="工作区ID")
# 输入/输出
input_text = Column(Text, nullable=True, comment="用户输入文本")