Skip to content

feat(tenancy): add Workspace multi-tenant foundation - #2353

Merged
dadachann merged 58 commits into
masterfrom
feat/multi-tenants
Jul 30, 2026
Merged

feat(tenancy): add Workspace multi-tenant foundation#2353
dadachann merged 58 commits into
masterfrom
feat/multi-tenants

Conversation

@RockChinQ

@RockChinQ RockChinQ commented Jul 24, 2026

Copy link
Copy Markdown
Member

Summary

  • keep Community single-Workspace while supporting multiple users and RBAC memberships
  • add signed Space directory snapshot/delta ingestion with monotonic Account and Membership projection into shared PostgreSQL
  • separate tenant-local, projected-directory, and Cloud control-plane writes while retaining fail-closed RLS
  • connect shared Plugin and Box control planes to Workspace/generation bindings and enforce independent stdio MCP gating
  • pin the verified multi-tenant Plugin SDK commit and document the Cloud v2 architecture, decisions, checklist, and final control-plane/browser evidence

Validation

  • open-source full suite without the closed adapter: 2590 passed, 32 skipped
  • closed Space adapter: 37 passed; Ruff passed
  • real PostgreSQL migration, pgvector, and release-migrator suites: 21 passed
  • Plugin SDK: 1226 passed
  • signed two-Workspace directory projection E2E completed successfully
  • Space browser E2E covered legacy-card retention, CNY Pro checkout, signed callback replay, and Pro entitlement activation

Activation notes

Cloud v2 remains disabled by default. Transactional New API provisioning/quota outboxes and strict payment callback binding are now implemented in Space. Activation still requires hard Box byte/inode quotas, plugin writable-data quota, tenant-safe egress, systemic restart protection, scheduled payment reconciliation/alerting, immutable recognized-revenue periods, and production migration/backup/restore/lifecycle procedures.

Comment thread tests/unit_tests/box/test_box_service.py Fixed
@dadachann
dadachann force-pushed the feat/multi-tenants branch from c772d92 to 84440df Compare July 24, 2026 18:05
Comment thread tests/integration/persistence/test_migrations_postgres.py Fixed
first_chunk_consumed = asyncio.Event()

async def consume():
async for _chunk in stream:
RockChinQ and others added 9 commits July 29, 2026 18:27
- Resolved conflict in provider.py: merged rerank model support with tenant context
- Resolved conflict in telegram.py: kept async.to_thread optimization and added url parameter
- Resolved conflict in test_model_manager.py: kept both cloud runtime and rerank tests
- Changed /api/v1/files/image from AuthType.NONE to USER_TOKEN_OR_API_KEY
- Added Permission.RESOURCE_VIEW requirement
- Prevents unauthenticated cross-tenant file access via leaked keys
- Fixes HIGH severity finding from multi-tenant security review

docs: add comprehensive database migration guide
- Complete migration steps for OSS → multi-tenant
- Backup, execution, verification procedures
- Rollback scenarios and recovery plans
- Performance tuning recommendations
Added 7 critical test scenarios for multi-tenant boundaries:
- Cross-tenant bot access prevention
- Viewer role read-only enforcement
- Removed member immediate access revocation
- Model provider credential isolation
- WebSocket message isolation
- Invitation token workspace scoping
- Multi-workspace context validation

These tests address P0-2 coverage gaps for:
- workspaces.py (membership & invitation flows)
- user.py (authentication & authorization)
- websocket_chat.py (real-time isolation)
- plugins.py (resource access control)

docs: finalize database migration guide
M-1: WebSocket authorization TOCTOU race (FIXED)
- Changed _revalidate_websocket_authorization to return RequestContext
- Ensures validated context is used immediately without race window
- Prevents removed members from sending messages during revalidation gap

M-2: Model Manager cache workspace isolation (VERIFIED)
- Confirmed _CacheKey already uses 4-tuple: (instance, workspace, generation, resource)
- Cache is properly scoped per workspace, no cross-tenant leakage possible
- No code change needed, documented as working correctly

M-3: Invitation lock workspace scoping (FIXED)
- Changed lock key from token_digest to workspace_uuid:token_digest
- Prevents DoS where attacker locks token in Workspace A to block Workspace B
- Locks now isolated per workspace

All MEDIUM severity findings from security review now resolved.
@dadachann
dadachann marked this pull request as ready for review July 30, 2026 13:43
@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jul 30, 2026
@dadachann
dadachann merged commit e1ac5e0 into master Jul 30, 2026
34 checks passed
@dosubot dosubot Bot added eh: Feature enhance: 新功能添加 / add new features m: Lifecycle 启动/关闭流程 / Bootstrap & application life cycle m: Platform 机器人管理相关 / Bots management m: Plugins 插件加载及管理模块 / Plugins loading and management labels Jul 30, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

eh: Feature enhance: 新功能添加 / add new features m: Lifecycle 启动/关闭流程 / Bootstrap & application life cycle m: Platform 机器人管理相关 / Bots management m: Plugins 插件加载及管理模块 / Plugins loading and management size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants