docs(tenancy): record verification evidence

This commit is contained in:
Junyan Qin
2026-07-19 09:59:53 +08:00
parent c6f826fe2d
commit b516161a91
2 changed files with 167 additions and 1 deletions
@@ -1,6 +1,8 @@
# Multi-tenant implementation checklist
This checklist turns the Workspace architecture into implementation and verification gates.
This checklist turns the Workspace architecture into implementation and
verification gates. Exact commands and observed results are recorded in the
[verification report](./verification-report.md).
## Scope guard
+164
View File
@@ -0,0 +1,164 @@
# 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
```text
.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
```text
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
```text
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.