Files
LangBot/docs/multi-tenant/verification-report.md
T
2026-07-19 09:59:53 +08:00

6.1 KiB

Multi-tenant verification report

Date: 2026-07-19

This report records the implementation and verification evidence for the Core Workspace isolation kernel. It does not claim that the closed SaaS Control Plane or Cloud v2 deployment is production-ready.

Repository refs and scope

  • LangBot branch: feat/multi-tenants
  • LangBot implementation commit: c6f826fe2d2e12cc73479155e8f25566048c1c56
  • LangBot base: origin/master at 6baeb032a7f76c65337b51c7b58593de4687a61c
  • Plugin SDK branch: feat/multi-tenants
  • Plugin SDK commit and LangBot dependency pin: a1544b6b38a37ba72e3284f2836618144f0742c1
  • Space remained on main at 5058b039c2629e3b01ebd7358369b50e7df62a1c, with no tracked changes made by this implementation.

The SDK protocol is versioned as 0.4.15 but is intentionally consumed from the exact pushed Git commit on this feature branch. Publishing 0.4.15 and replacing the Git pin with a registry pin remain merge-to-master release steps.

Automated verification

LangBot backend

.venv/bin/ruff check .
  passed

changed and untracked Python format check
  220 files already formatted

.venv/bin/pytest tests/unit_tests -q
  2051 passed, 1 skipped, 110 warnings in 26.87s

.venv/bin/pytest tests/integration -q
  163 passed, 19 skipped, 28 warnings in 6.00s

uvx --from uv@latest uv lock --check
  resolved 277 packages; passed

git diff --check
  passed

Database migrations

  • Fresh and upgraded SQLite schemas passed, including verified pre-boundary backups, forced-failure restore, retry, and revision manifest checks.
  • A disposable PostgreSQL 16 instance exercised fresh and upgraded tenancy migrations: 9 passed, 9 warnings in 8.57s.
  • Alembic has one head, 0010_scope_resources, through the chain 0008_mcp_resource_prefs -> 0009_workspace_tenancy -> 0010_scope_resources.
  • ORM-to-migration coverage found no missing tenant table.

Plugin SDK and runtime

SDK full test suite
  1029 passed, 18 warnings in 8.20s

SDK Ruff and action consistency checks
  passed

Docker-backed Box integration tests
  13 passed

The SDK remote branch and LangBot Git dependency were both resolved and verified at the same commit recorded above.

Frontend

pnpm lint
  0 errors, 34 warnings

pnpm build
  passed; 3167 modules

pnpm exec playwright test --project=chromium
  40 passed in 19.9s

Bot form initialization race pressure test
  10 passed in 9.4s

The browser suite covers singleton bootstrap, explicit multi-Workspace selection under the test policy, selector headers, account-state cleanup, Workspace switching, and invitation terminal-state recovery.

Packaging and deployment configuration

  • Docker Compose with Plugin Runtime and Box control tokens passed docker compose ... --profile all config --quiet.
  • Compose, Kubernetes, and the default configuration passed YAML parsing.
  • Kubernetes selector, volume, and control-token reference checks passed.
  • skills/bin/lbs index --check and skills/bin/lbs validate passed.
  • The staged secret scan found no committed credential; test-token literals were confirmed to be non-secret fixtures.

Real browser E2E

The bundled production web application and backend were started against a clean, temporary SQLite data directory. The following flows were performed in the in-app browser against the real API rather than mocks:

  1. The first Account registered and became owner of the automatically created singleton Workspace.
  2. The owner created a one-time invitation link.
  3. A signed-out second Account inspected the fragment-based invitation, registered, accepted it, and entered the Workspace as viewer.
  4. The same member was cycled through viewer, operator, developer, admin, and owner. Visible controls matched the backend permission matrix, including owner transfer only for an owner.
  5. A viewer invitation mutation returned 403 permission_denied; an owner attempt to create a second OSS Workspace returned 403 edition_limit.
  6. Owner/member account switching, refresh, and a newly opened browser tab recovered only the active Account and singleton Workspace state.
  7. Used, revoked, expired, and email-mismatched invitation states rendered distinct errors. Terminal tokens were cleared, while the mismatch flow allowed switching to the intended Account.
  8. With the plugin system disabled, /api/v1/plugins and /api/v1/system/status/plugin-system both returned 200 after a clean server restart. The only remaining browser console error was the expected failure to reach the optional external Space release feed.

The test server was stopped, port 15321 was verified free, and the temporary test directory was moved to the system Trash. Multi-Workspace same-name and same-identifier isolation is exercised by the automated test-only Cloud policy; the OSS browser cannot create a second Workspace by design.

Final audit

The final isolation audit found no remaining P0/P1 tenant isolation issue in the OSS singleton-Workspace, multi-user scope. Focused checks also covered the plugin-disabled Workspace fence, invitation fragment/account-switch behavior, and the Bot form initialization sequence. Unrelated untracked workspace files were excluded from both commits.

Deliberately incomplete SaaS gates

Multi-Workspace activation remains unavailable in the open-source bootstrap. Cloud v2 must remain disabled until the following closed-system gates are implemented and independently verified:

  • signed InstanceManifest verification and closed CloudWorkspacePolicy injection;
  • authoritative Account, Workspace, Membership, Invitation, placement, entitlement, usage, subscription, and billing services;
  • generation-aware database transaction and outbox fences through commit;
  • stable durable object references across placement-generation cutovers;
  • atomic shared OAuth-state and directory-projection stores;
  • tenant-safe egress and SSRF enforcement for all configurable outbound URLs;
  • a greenfield Cloud v2 deployment, without carrying forward the legacy Space deployment model.

These are release gates, not hidden fallbacks. Mutable Core configuration or an edition flag cannot enable SaaS multi-tenancy.